API is taking shape

This commit is contained in:
Miek Gieben 2011-03-28 14:45:40 +02:00
parent 62fc0f05f7
commit 2b7d2203fb
4 changed files with 50 additions and 27 deletions

View File

@ -9,28 +9,22 @@ import (
func main() {
var serial *int = flag.Int("serial", 0, "Perform an IXFR with the given serial")
var nameserver *string = flag.String("ns", "127.0.0.1", "Query this nameserver")
var nameserver *string = flag.String("ns", "127.0.0.1:53", "Query this nameserver")
flag.Parse()
zone := flag.Arg(flag.NArg()-1)
res := new(dns.Resolver)
res.FromFile("/etc/resolv.conf")
res.Servers[0] = *nameserver
c := make(chan dns.Xfr)
d := new(dns.Conn)
m := new(dns.Msg)
d.RemoteAddr = *nameserver
if *serial > 0 {
m.SetIxfr(zone, uint32(*serial))
} else {
m.SetAxfr(zone)
}
go res.Xfr(m, c)
go d.XfrRead(m, c)
for x := range c {
// if x.Err != nil {
// fmt.Printf("%v\n",x.Err)
// } else {
fmt.Printf("%v %v\n",x.Add, x.RR)
// }
fmt.Printf("%v %v %v\n",x.Add, x.RR, x.Err)
}
}

46
dns.go
View File

@ -16,17 +16,7 @@
// The package dns supports querying, incoming/outgoing Axfr/Ixfr, TSIG, EDNS0,
// dynamic updates, notifies and DNSSEC validation/signing.
//
// Use patter for simple querying:
//
// res := new(Resolver)
// res.Servers = []string{"127.0.0.1"}
// m := new(Msg)
// m.MsgHdr.Recursion_desired = true
// m.Question = make([]Question, 1)
// m.Question[0] = Question{"miek.nl", TypeSOA, ClassINET}
// in, err := res.Query(m)
//
// Asynchronize querying the DNS is done by using the Conn structure.
// (Asynchronize) querying the DNS is done by using the Conn structure.
// Basic use pattern for creating such a resolver:
//
// func handle(d *Conn, m *Msg, q chan Query) { /* handle query */ }
@ -36,6 +26,11 @@
// d := new(Conn)
// d.RemoteAddr = "8.8.8.8:53"
//
// // Create message with the desired options.
// m.MsgHdr.Recursion_desired = true
// m.Question = make([]Question, 1)
// m.Question[0] = Question{"miek.nl", TypeSOA, ClassINET}
//
// in <- Query{Msg: m, Conn: d} // Send query using the above message
// reply := <-out // Listen for replie(s)
//
@ -112,13 +107,34 @@ type Conn struct {
// The remote addr which is going to be dialed.
RemoteAddr string
// The local addr used for outgoing queries
LocalAddr string
// Mangle the packet before writing it be feeding
// it through this function.
Mangle func([]byte) []byte
// rtt times?
}
// Dial, with minimum filled out Conn (RemoteAddr and LocalAddr)
func (d *Conn) Dial(n string) os.Error {
c, err := net.Dial(n, d.LocalAddr, d.RemoteAddr)
if err != nil {
return err
}
switch n {
case "tcp":
d.TCP = c.(*net.TCPConn)
d.Addr = d.TCP.RemoteAddr()
d.Port = d.TCP.RemoteAddr().(*net.TCPAddr).Port
case "udp":
d.UDP = c.(*net.UDPConn)
d.Addr = d.UDP.RemoteAddr()
d.Port = d.UDP.RemoteAddr().(*net.UDPAddr).Port
}
return nil
}
// Dial connects to the remote address raddr on the network net.
// If the string laddr is not empty, it is used as the local address
// for the connection. Any errors are return in err otherwise err is nil.
@ -148,6 +164,8 @@ func (d *Conn) SetTCPConn(l *net.TCPConn, a net.Addr) {
d.UDP = nil
if a == nil {
d.Addr = l.RemoteAddr()
} else {
d.Addr = a
}
d.Port = d.Addr.(*net.TCPAddr).Port
}
@ -159,6 +177,8 @@ func (d *Conn) SetUDPConn(l *net.UDPConn, a net.Addr) {
d.UDP = l
if a == nil {
d.Addr = l.RemoteAddr()
} else {
d.Addr = a
}
d.Port = d.Addr.(*net.UDPAddr).Port
}

View File

@ -17,7 +17,8 @@ type Query struct {
// The query message.
Msg *Msg
// A Conn. Its only required to fill out Conn.RemoteAddr.
// The rest of the structure is filled in by the Query Functions.
// Optionally you may set Conn.Tsig.
// The rest of the structure is filled by the Query Functions.
Conn *Conn
// Any erros when querying are returned in Err. The caller
// should just set this to nil.
@ -30,7 +31,6 @@ type Query struct {
func QueryUDP(in, out chan Query, f func(*Conn, *Msg, chan Query)) {
query("udp", in, out, f)
}
// Shoudl the chan be *Query??
// QueryTCP handles one query. It reads an incoming request from
// the in channel. The function f is executed in a seperate
@ -46,7 +46,7 @@ func query(n string, in, out chan Query, f func(*Conn, *Msg, chan Query)) {
case q := <-in:
c, err := net.Dial(n, "", q.Conn.RemoteAddr)
if err != nil {
//out <- nil
out <- Query{Err: err}
}
if n == "tcp" {
q.Conn.SetTCPConn(c.(*net.TCPConn), nil)

9
xfr.go
View File

@ -21,6 +21,15 @@ type Xfr struct {
// section contains an AXFR type an Axfr is performed. If q's question
// section contains an IXFR type an Ixfr is performed.
func (d *Conn) XfrRead(q *Msg, m chan Xfr) {
if d.TCP == nil && d.UDP == nil {
// No connection yet
if err := d.Dial("tcp"); err != nil {
m <- Xfr{true, nil, err}
close(m)
return
}
}
// Send q first.
err := d.WriteMsg(q)
if err != nil {