diff --git a/ex/reflect/reflect.go b/ex/reflect/reflect.go index 56eba1fe..2ef054b1 100644 --- a/ex/reflect/reflect.go +++ b/ex/reflect/reflect.go @@ -76,6 +76,22 @@ func handleReflect(w dns.ResponseWriter, r *dns.Msg) { t.Txt = []string{str} switch r.Question[0].Qtype { + case dns.TypeAXFR: + c := make(chan *dns.XfrToken) + var e *error + if err := dns.XfrSend(w, r, c, e); err != nil { + close(c) + return + } + soa, _ := dns.NewRR(`miek.nl. IN SOA elektron.atoom.net. miekg.atoom.net. ( + 2009032802 + 21600 + 7200 + 604800 + 3600)`) + c <- &dns.XfrToken{RR: []dns.RR{soa, t, rr, soa}} + close(c) + return case dns.TypeTXT: m.Answer = append(m.Answer, t) m.Extra = append(m.Extra, rr) diff --git a/server.go b/server.go index ad3eec32..d52cceaa 100644 --- a/server.go +++ b/server.go @@ -26,6 +26,8 @@ type ResponseWriter interface { Write(*Msg) error // WriteBuf writes a raw buffer back to the client. WriteBuf([]byte) error + // Close closes the connection. + Close() error // TsigStatus returns the status of the Tsig. TsigStatus() error // TsigTimersOnly sets the tsig timers only boolean. @@ -303,18 +305,6 @@ func newConn(t *net.TCPConn, u *net.UDPConn, a net.Addr, buf []byte, handler Han return c, nil } -// Close the connection. -func (c *conn) close() { - switch { - case c._UDP != nil: - c._UDP.Close() - c._UDP = nil - case c._TCP != nil: - c._TCP.Close() - c._TCP = nil - } -} - // Serve a new connection. func (c *conn) serve() { // for block to make it easy to break out to close the tcp connection @@ -349,7 +339,8 @@ func (c *conn) serve() { break } if c._TCP != nil { - c.close() // Listen and Serve is closed then + c._TCP.Close() + c._TCP = nil } } @@ -425,3 +416,19 @@ func (w *response) TsigStatus() error { return w.tsigStatus } // TsigTimersOnly implements the ResponseWriter.TsigTimersOnly method. func (w *response) TsigTimersOnly(b bool) { w.tsigTimersOnly = b } + +// Close implements the ResponseWriter.Close method +func (w *response) Close() error { + if w.conn._UDP != nil { + e := w.conn._UDP.Close() + w.conn._UDP = nil + return e + } + if w.conn._TCP != nil { + e := w.conn._TCP.Close() + w.conn._TCP = nil + return e + } + // no-op + return nil +} diff --git a/xfr.go b/xfr.go index c27a41c9..f7686019 100644 --- a/xfr.go +++ b/xfr.go @@ -145,7 +145,7 @@ func checkXfrSOA(in *Msg, first bool) bool { // XfrSend performs an outgoing [AI]xfr depending on the request message. The // caller is responsible for sending the correct sequence of RR sets through -// the channel c. +// the channel c. For reasons of symmetry XfrToken is re-used. // Errors are signaled via the error pointer, when an error occurs the function // sets the error and returns (it does not close the channel). // TSIG and enveloping is handled by XfrSend. @@ -157,7 +157,7 @@ func checkXfrSOA(in *Msg, first bool) bool { // var e *error // err := XfrSend(w, q, c, e) // for _, rrset := range rrsets { // rrset is a []RR -// c <- rrset +// c <- &{XfrToken{RR: rrset} // if e != nil { // close(c) // break @@ -180,15 +180,17 @@ func axfrSend(w ResponseWriter, req *Msg, c chan *XfrToken, e *error) { rep.SetReply(req) rep.MsgHdr.Authoritative = true - first := true for x := range c { + println("got some", len(x.RR)) // assume it fits rep.Answer = append(rep.Answer, x.RR...) + println(rep.String()) if err := w.Write(rep); e != nil { *e = err return } - w.TsigTimersOnly(first) + w.TsigTimersOnly(true) rep.Answer = nil } + w.Close() // Hijack }