commit 521607802a026aae130395eb147b81d480b94e34 from: Oliver Lowe date: Thu Dec 16 09:11:37 2021 UTC dns: Separate sending messages from sending bytes That made it easy to then let us ResponseWriter to implement io.Writer commit - 554ced8329b2f5a7abf40a2131cf5e869c1e17d4 commit + 521607802a026aae130395eb147b81d480b94e34 blob - 84bb734d39653450ad3e041fc53deb0556863a97 blob + 015729f39f39fb70f98b95524ea9c361113fabc9 --- dns.go +++ dns.go @@ -152,7 +152,7 @@ func ExchangeTLS(msg dnsmessage.Message, addr string) } func exchange(msg dnsmessage.Message, conn net.Conn) (dnsmessage.Message, error) { - if err := send(msg, conn); err != nil { + if err := sendMsg(msg, conn); err != nil { return dnsmessage.Message{}, err } rmsg, err := receive(conn) @@ -165,31 +165,30 @@ func exchange(msg dnsmessage.Message, conn net.Conn) ( return rmsg, nil } -func send(msg dnsmessage.Message, conn net.Conn) error { +func sendMsg(msg dnsmessage.Message, conn net.Conn) error { packed, err := msg.Pack() if err != nil { return err } + _, err = send(packed, conn) + return err +} + +func send(p []byte, conn net.Conn) (int, error) { if _, ok := conn.(net.PacketConn); ok { - if _, err := conn.Write(packed); err != nil { - return err - } - return nil + return conn.Write(p) } // DNS over TCP requires you to prepend the message with a // 2-octet length field. - l := len(packed) + l := len(p) m := make([]byte, 2+l) m[0] = byte(l >> 8) m[1] = byte(l) - copy(m[2:], packed) - if _, err := conn.Write(m); err != nil { - return err - } - return nil + copy(m[2:], p) + return conn.Write(m) } -func sendPacket(msg dnsmessage.Message, conn net.PacketConn, addr net.Addr) error { +func sendMsgTo(msg dnsmessage.Message, conn net.PacketConn, addr net.Addr) error { packed, err := msg.Pack() if err != nil { return err blob - f466d64cb021a02fb3bd2d78a942e323f3a79938 blob + ac93f9f087c23094a08b505f4f7223c263180ef9 --- server.go +++ server.go @@ -5,6 +5,12 @@ import ( "net" ) +type Zone struct { + Name dnsmessage.Name + SOA dnsmessage.SOAResource + Resources []dnsmessage.Resource +} + // Server contains settings for running a DNS server. An empty Server // with a nil Handler is a valid configuration. type Server struct { @@ -21,16 +27,25 @@ type response struct { conn net.Conn } +func (r *response) Write(p []byte) (n int, err error) { + if r.pconn != nil { + return r.pconn.WriteTo(p, r.raddr) + } + return send(p, r.conn) +} + func (r *response) WriteMsg(msg dnsmessage.Message) error { if r.pconn != nil { - return sendPacket(msg, r.pconn, r.raddr) + return sendMsgTo(msg, r.pconn, r.raddr) } - return send(msg, r.conn) + return sendMsg(msg, r.conn) } // The ResponseWriter interface is used by a Handler to reply to // DNS requests. type ResponseWriter interface { + // Write writes the data to the underlying connection as a DNS response. + Write(p []byte) (n int, err error) // WriteMsg writes the DNS message to the connection. WriteMsg(dnsmessage.Message) error } @@ -53,7 +68,7 @@ func (srv *Server) ServePacket(conn net.PacketConn) er var msg dnsmessage.Message if err := msg.Unpack(buf[:n]); err != nil { msg.Header.RCode = dnsmessage.RCodeRefused - sendPacket(msg, conn, raddr) + sendMsgTo(msg, conn, raddr) return } resp := &response{raddr: raddr, pconn: conn}