diff --git a/dns.go b/dns.go index 131242f8..b86d4dce 100644 --- a/dns.go +++ b/dns.go @@ -7,12 +7,37 @@ // The package allows full control over what is send out to the DNS. // // Resource Records are native types. They are not stored in wire format. -// Basic usage pattern for creating new Resource Record: +// Basic usage pattern for creating a new Resource Record: // // r := new(RR_TXT) // r.Hdr = RR_Header{Name: "a.miek.nl", Rrtype: TypeTXT, Class: ClassINET, Ttl: 3600} // r.TXT = "This is the content of the TXT record" // +// The package dns supports normal querying, incoming/outgoing Axfr/Ixfr, TSIG, EDNS0, +// dynamic updates, notifies and DNSSEC validation/signing. +// +// Basic use pattern for creating a resolver: +// +// 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) +// +// +// Basic use pattern for creating an UDP DNS server: +// +// func handle(d *dns.Conn, i *dns.Msg) { /* handle request */ } +// +// func listen(addr string, e chan os.Error) { +// err := dns.ListenAndServeUDP(addr, handle) +// e <- err +// } +// err := make(chan os.Error) +// go listen("127.0.0.1:8053", err) +// package dns // ErrShortWrite is defined in io, use that! @@ -27,7 +52,7 @@ const ( Year68 = 2 << (32 - 1) // For RFC1982 (Serial Arithmetic) calculations in 32 bits. DefaultMsgSize = 4096 // A standard default for larger than 512 packets. MaxMsgSize = 65536 // Largest possible DNS packet. - DefaultTtl = 3600 // Default Ttl, used in New() for instance. + DefaultTtl = 3600 // Default Ttl. ) // Error represents a DNS error @@ -45,9 +70,9 @@ func (e *Error) String() string { return e.Error } -// A Conn is the lowest primative in this DNS library +// A Conn is the lowest primative in this dns package. // A Conn holds both the UDP and TCP connection, but only one -// at any given time. +// can be active any given time. type Conn struct { // The current UDP connection. UDP *net.UDPConn @@ -289,7 +314,7 @@ func (d *Conn) SetTimeout() (err os.Error) { } // Exchange combines a Write and a Read. -// First request is written to d and then it waits +// First the request is written to d and then it waits // for a reply with Read. // If nosend is true, the write is skipped. func (d *Conn) Exchange(request []byte, nosend bool) (reply []byte, err os.Error) { diff --git a/msg.go b/msg.go index cc1ab7c0..b0042b17 100644 --- a/msg.go +++ b/msg.go @@ -1057,8 +1057,8 @@ func (dns *Msg) String() string { return s } -// Return a 16 bits random number to be used as -// msg id +// Return a 16 bits random number to be used as a +// message id. The random provided should be good enough. func Id() uint16 { return uint16(rand.Int()) ^ uint16(time.Nanoseconds()) } diff --git a/resolver.go b/resolver.go index 2c3366d7..83ae926b 100644 --- a/resolver.go +++ b/resolver.go @@ -12,7 +12,9 @@ import ( "time" ) +// Todo(MG) put in dns.go const ErrPack = "Failed to pack message" +const ErrUnpack = "" const ErrServ = "No servers could be reached" const ErrTsigKey = "" const ErrTsigTime = "" @@ -31,22 +33,12 @@ type Resolver struct { Rrb int // Last used server (for round robin) } -// Basic usage pattern for setting up a resolver: -// -// res := new(Resolver) -// res.Servers = []string{"127.0.0.1"} // set the nameserver -// -// m := new(Msg) // prepare a new message -// m.MsgHdr.Recursion_desired = true // header bits -// m.Question = make([]Question, 1) // 1 RR in question section -// m.Question[0] = Question{"miek.nl", TypeSOA, ClassINET} -// in, err := res.Query(m, nil) // Ask the question -// -// Note that message id checking is left to the caller. +// Send a query to the nameserver using the res. func (res *Resolver) Query(q *Msg) (d *Msg, err os.Error) { return res.QueryTsig(q, nil) } +// Send a query to the nameserver using res, but perform TSIG validation. func (res *Resolver) QueryTsig(q *Msg, tsig *Tsig) (d *Msg, err os.Error) { var c net.Conn var inb []byte diff --git a/server.go b/server.go index c8cd1408..554c4ab7 100644 --- a/server.go +++ b/server.go @@ -11,9 +11,10 @@ import ( "net" ) -// For both -> logging -// Add tsig stuff as in resolver.go - +// HandleUDP handles one UDP connection. It reads the incoming +// message and then calls the function f. +// The function f is executed +// in a seperate goroutine at which point HandleUDP returns. func HandleUDP(l *net.UDPConn, f func(*Conn, *Msg)) os.Error { for { m := make([]byte, DefaultMsgSize) @@ -37,6 +38,10 @@ func HandleUDP(l *net.UDPConn, f func(*Conn, *Msg)) os.Error { panic("not reached") } +// HandleTCP handles one TCP connection. It reads the incoming +// message and then calls the function f. +// The function f is executed +// in a seperate goroutine at which point HandleTCP returns. func HandleTCP(l *net.TCPListener, f func(*Conn, *Msg)) os.Error { for { c, e := l.AcceptTCP() @@ -60,11 +65,13 @@ func HandleTCP(l *net.TCPListener, f func(*Conn, *Msg)) os.Error { panic("not reached") } -// config functions Config -// ListenAndServeTCPTsig -// ListenAndServeUDPTsig - +// ListenAndServerTCP listens on the TCP network address addr and +// then calls HandleTCP with f to handle requests on incoming +// connections. The function f may not be nil. func ListenAndServeTCP(addr string, f func(*Conn, *Msg)) os.Error { + if f == nil { + return &Error{Error: "The handle function may not be nil"} + } a, err := net.ResolveTCPAddr(addr) if err != nil { return err @@ -77,7 +84,13 @@ func ListenAndServeTCP(addr string, f func(*Conn, *Msg)) os.Error { return err } +// ListenAndServerUDP listens on the UDP network address addr and +// then calls HandleUDP with f to handle requests on incoming +// connections. The function f may not be nil. func ListenAndServeUDP(addr string, f func(*Conn, *Msg)) os.Error { + if f == nil { + return &Error{Error: "The handle function may not be nil"} + } a, err := net.ResolveUDPAddr(addr) if err != nil { return err diff --git a/xfr.go b/xfr.go index 1f617210..77379a61 100644 --- a/xfr.go +++ b/xfr.go @@ -15,7 +15,9 @@ type Xfr struct { Err os.Error } -// Msg tells use what to do +// Perform an incoming Ixfr or Axfr. If the message q's question +// 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) { // Send q first. err := d.WriteMsg(q) @@ -30,6 +32,10 @@ func (d *Conn) XfrRead(q *Msg, m chan Xfr) { } } +// Perform an outgoing Ixfr or Axfr. If the message q's question +// section contains an AXFR type an Axfr is performed. If q's question +// section contains an IXFR type an Ixfr is performed. +// The message q is written to the connection in d. func (d *Conn) XfrWrite(q *Msg, m chan Xfr) { switch q.Question[0].Qtype { case TypeAXFR: