diff --git a/TODO.markdown b/TODO.markdown index ef72c6ec..f4356b08 100644 --- a/TODO.markdown +++ b/TODO.markdown @@ -5,7 +5,6 @@ need to be fixed. * Speed, we can always go faster. A simple reflect server now hits 35/45K qps * go test; only works correct on my machine - * privatekey.Precompute() when signing? ## Examples to add diff --git a/client.go b/client.go index 65c7d914..3f160509 100644 --- a/client.go +++ b/client.go @@ -220,7 +220,11 @@ func ListenAndQuery(request chan *Request, handler QueryHandler) { // Write returns the original question and the answer on the // reply channel of the client. func (w *reply) Write(m *Msg) error { - w.Client().ReplyChan <- &Exchange{Request: w.req, Reply: m, Rtt: w.rtt} + if w.conn == nil { + w.Client().ReplyChan <- &Exchange{Request: w.req, Reply: m, Rtt: w.rtt} + } else { + w.Client().ReplyChan <- &Exchange{Request: w.req, Reply: m, Rtt: w.rtt, RemoteAddr: w.conn.RemoteAddr()} + } return nil } @@ -258,12 +262,12 @@ func (c *Client) exchangeBuffer(inbuf []byte, a string, outbuf []byte) (n int, w // Exchange performs an synchronous query. It sends the message m to the address // contained in a and waits for an reply. -func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) { +func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, addr net.Addr, err error) { var n int var w *reply out, ok := m.Pack() if !ok { - return nil, 0, ErrPack + return nil, 0, nil, ErrPack } var in []byte switch c.Net { @@ -279,13 +283,13 @@ func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro in = make([]byte, size) } if n, w, err = c.exchangeBuffer(out, a, in); err != nil { - return nil, 0, err + return nil, 0, w.conn.RemoteAddr(), err } r = new(Msg) if ok := r.Unpack(in[:n]); !ok { - return nil, w.rtt, ErrUnpack + return nil, w.rtt, w.conn.RemoteAddr(), ErrUnpack } - return r, w.rtt, nil + return r, w.rtt, w.conn.RemoteAddr(), nil } // Dial connects to the address addr for the network set in c.Net diff --git a/dns.go b/dns.go index 30621d2e..2ddc458a 100644 --- a/dns.go +++ b/dns.go @@ -117,10 +117,11 @@ type RR interface { // Exchange is used in communicating with the resolver. type Exchange struct { - Request *Msg // the question sent - Reply *Msg // the answer to the question that was sent - Rtt time.Duration // Round trip time - Error error // if something went wrong, this contains the error + Request *Msg // the question sent + Reply *Msg // the answer to the question that was sent + Rtt time.Duration // Round trip time + RemoteAddr net.Addr // Client address + Error error // if something went wrong, this contains the error } // DNS resource records. diff --git a/ex/mx/mx.go b/ex/mx/mx.go index 30543bf3..3e926121 100644 --- a/ex/mx/mx.go +++ b/ex/mx/mx.go @@ -1,4 +1,5 @@ package main + // Print the MX records of a domain // (c) Miek Gieben - 2011 import ( @@ -22,7 +23,7 @@ func main() { m.MsgHdr.RecursionDesired = true // Simple sync query, nothing fancy - r, _, err := c.Exchange(m, config.Servers[0] + ":" + config.Port) + r, _, _, err := c.Exchange(m, config.Servers[0]+":"+config.Port) if err != nil { fmt.Printf("%s\n", err.Error()) os.Exit(1) diff --git a/ex/q/q.go b/ex/q/q.go index 46a02a4d..de445e18 100644 --- a/ex/q/q.go +++ b/ex/q/q.go @@ -36,7 +36,7 @@ func main() { short := flag.Bool("short", false, "abbreviate long DNSSEC records") check := flag.Bool("check", false, "check internal DNSSEC consistency") anchor := flag.String("anchor", "", "use the DNSKEY in this file for interal DNSSEC consistency") - tsig := flag.String("tsig", "", "request tsig with key: [hmac:]name:key") + tsig := flag.String("tsig", "", "request tsig with key: [hmac:]name:key") port := flag.Int("port", 53, "port number to use") aa := flag.Bool("aa", false, "set AA flag in query") ad := flag.Bool("ad", false, "set AD flag in query") @@ -191,7 +191,7 @@ forever: } if r.Reply.MsgHdr.Truncated && *fallback { if c.Net != "tcp" { - if ! *dnssec { + if !*dnssec { fmt.Printf(";; Truncated, trying %d bytes bufsize\n", dns.DefaultMsgSize) o := new(dns.RR_OPT) o.Hdr.Name = "." @@ -222,7 +222,7 @@ forever: } fmt.Printf("%v", r.Reply) - fmt.Printf("\n;; Query time: %.3d µs\n", r.Rtt/1e3) + fmt.Printf("\n;; query time: %.3d µs, server: %s(%s)\n", r.Rtt/1e3, r.RemoteAddr, r.RemoteAddr.Network()) // Server maybe } i++ @@ -270,7 +270,7 @@ func sectionCheck(set []dns.RR, server string, tcp bool) { where = "disk" } if err := rr.(*dns.RR_RRSIG).Verify(key, rrset); err != nil { - fmt.Printf(";- Bogus signature, %s does not validate (DNSKEY %s/%d/%s) [%s]\n", + fmt.Printf(";- Bogus signature, %s does not validate (DNSKEY %s/%d/%s) [%s]\n", shortSig(rr.(*dns.RR_RRSIG)), key.Header().Name, key.KeyTag(), where, err.Error()) } else { fmt.Printf(";+ Secure signature, %s validates (DNSKEY %s/%d/%s)\n", shortSig(rr.(*dns.RR_RRSIG)), key.Header().Name, key.KeyTag(), where) @@ -341,7 +341,7 @@ func getKey(name string, keytag uint16, server string, tcp bool) *dns.RR_DNSKEY m := new(dns.Msg) m.SetQuestion(name, dns.TypeDNSKEY) m.SetEdns0(4096, true) - r, _, err := c.Exchange(m, server) + r, _, _, err := c.Exchange(m, server) if err != nil { return nil } diff --git a/xfr.go b/xfr.go index 9e541802..3d3b908c 100644 --- a/xfr.go +++ b/xfr.go @@ -33,16 +33,16 @@ func (w *reply) axfrReceive() { for { in, err := w.Receive() if err != nil { - w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, err} + w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, w.conn.RemoteAddr(), err} return } if w.req.Id != in.Id { - w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, ErrId} + w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, w.conn.RemoteAddr(), ErrId} return } if first { if !checkXfrSOA(in, true) { - w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, ErrXfrSoa} + w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, w.conn.RemoteAddr(), ErrXfrSoa} return } first = !first @@ -51,10 +51,10 @@ func (w *reply) axfrReceive() { if !first { w.tsigTimersOnly = true // Subsequent envelopes use this. if checkXfrSOA(in, false) { - w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, ErrXfrLast} + w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, w.conn.RemoteAddr(), ErrXfrLast} return } - w.Client().ReplyChan <- &Exchange{Request: w.req, Reply: in} + w.Client().ReplyChan <- &Exchange{Request: w.req, Reply: in, Rtt: w.rtt, RemoteAddr: w.conn.RemoteAddr(), Error: nil} } } panic("not reached") @@ -68,24 +68,24 @@ func (w *reply) ixfrReceive() { for { in, err := w.Receive() if err != nil { - w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, err} + w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, w.conn.RemoteAddr(), err} return } if w.req.Id != in.Id { - w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, ErrId} + w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, w.conn.RemoteAddr(), ErrId} return } if first { // A single SOA RR signals "no changes" if len(in.Answer) == 1 && checkXfrSOA(in, true) { - w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, ErrXfrLast} + w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, w.conn.RemoteAddr(), ErrXfrLast} return } // Check if the returned answer is ok if !checkXfrSOA(in, true) { - w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, ErrXfrSoa} + w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, w.conn.RemoteAddr(), ErrXfrSoa} return } // This serial is important @@ -99,7 +99,7 @@ func (w *reply) ixfrReceive() { // If the last record in the IXFR contains the servers' SOA, we should quit if v, ok := in.Answer[len(in.Answer)-1].(*RR_SOA); ok { if v.Serial == serial { - w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, ErrXfrLast} + w.Client().ReplyChan <- &Exchange{w.req, in, w.rtt, w.conn.RemoteAddr(), ErrXfrLast} return } }