From 5786959b98b33b5ec0f621b6685d734250bb1a8d Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Tue, 18 Jan 2011 21:01:08 +0100 Subject: [PATCH] Test Nameserver Inside responder pkg --- TODO | 1 + _examples/reflect/reflect.go | 6 +-- dns.go | 4 +- resolver/resolver.go | 4 +- responder/responder.go | 92 +++++++++++++++++++++++++++++++----- responder/responder_test.go | 54 ++++++++++++++------- 6 files changed, 128 insertions(+), 33 deletions(-) diff --git a/TODO b/TODO index 75b18170..91419fc5 100644 --- a/TODO +++ b/TODO @@ -3,6 +3,7 @@ Todo: * Tsig testing * Private key file parsing use io.Reader (or the like) * Parsing from /etc/resolv.conf - clean up the code, use normal packages +* IP6 testing Longer term: * Parsing from strings, going with goyacc and own lexer diff --git a/_examples/reflect/reflect.go b/_examples/reflect/reflect.go index cf0f2a82..9e676e1a 100644 --- a/_examples/reflect/reflect.go +++ b/_examples/reflect/reflect.go @@ -29,10 +29,10 @@ type server responder.Server func (s *server) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) { inmsg := new(dns.Msg) if !inmsg.Unpack(in) { - // NXdomain 'n stuff + // FormErr println("Unpacking failed") } - if inmsg.Hdr.Response == true { + if inmsg.MsgHdr.Response == true { return // Don't answer responses } m := new(dns.Msg) @@ -71,7 +71,7 @@ func (s *server) ResponderTCP(c *net.TCPConn, in []byte) { // NXdomain 'n stuff println("Unpacking failed") } - if inmsg.Hdr.Response == true { + if inmsg.MsgHdr.Response == true { return // Don't answer responses } return // we are lazy and don't support tcp diff --git a/dns.go b/dns.go index 203cb37b..410e4d29 100644 --- a/dns.go +++ b/dns.go @@ -65,7 +65,9 @@ func (m *Meta) String() string { s += "\n;; MSG SIZE rcvd: " + strconv.Itoa(m.RLen) + ", sent: " + strconv.Itoa(m.QLen) rf := float32(m.RLen) qf := float32(m.QLen) - s += " (" + strconv.Ftoa32(rf/qf, 'f', 2) + ":1)" + if qf != 0 { + s += " (" + strconv.Ftoa32(rf/qf, 'f', 2) + ":1)" + } // WHEN?? return s } diff --git a/resolver/resolver.go b/resolver/resolver.go index e83b4e3e..170a3d74 100644 --- a/resolver/resolver.go +++ b/resolver/resolver.go @@ -128,7 +128,9 @@ func query(res *Resolver, msg chan Msg) { } break } - meta.QLen = len(sending) + if sending != nil { + meta.QLen = len(sending) + } if err != nil { msg <- Msg{nil, meta, err} } else { diff --git a/responder/responder.go b/responder/responder.go index fbe0aba2..3bafa5cd 100644 --- a/responder/responder.go +++ b/responder/responder.go @@ -13,12 +13,12 @@ // func (s *myserv) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) { /* UDP reply */ } // func (s *myserv) ResponderTCP(c *net.TCPConn, in []byte) { /* TCP reply */} // -// su := new(Server) // create new sever -// su.Address = "127.0.0.1" // listen address -// su.Port = "8053" // listen port -// var us *myserv -// uch :=make(chan bool) -// go su.NewResponder(us, uch) // start the responder +// s := new(Server) // create new sever +// s.Address = "127.0.0.1" // listen address +// s.Port = "8053" // listen port +// var m *myserv +// ch :=make(chan bool) +// go s.NewResponder(m, ch) // start the responder package responder import ( @@ -41,7 +41,6 @@ type msg struct { addr net.Addr // remote address msg []byte // raw dns message err os.Error // any errors - // Meta stuff } // Every nameserver implements the Responder interface. It defines @@ -86,9 +85,13 @@ func (res *Server) NewResponder(h Responder, stop chan bool) os.Error { break foreverTCP case s := <-tch: if s.err != nil { - //continue - } - go h.ResponderTCP(s.ct, s.msg) + // always fatal?? + println(s.err.String()) + close(stop) + return s.err + } else { + go h.ResponderTCP(s.ct, s.msg) + } } } @@ -105,8 +108,10 @@ func (res *Server) NewResponder(h Responder, stop chan bool) os.Error { break foreverUDP case s := <-uch: if s.err != nil { - println(s.err) - //continue? + //continue + println(s.err.String()) + close(stop) + return s.err } else { go h.ResponderUDP(s.cu, s.addr, s.msg) } @@ -207,3 +212,66 @@ func SendUDP(m []byte, c *net.UDPConn, a net.Addr) os.Error { } return nil } + +// Basic implementation of a reflector nameserver which responds +// to queries for A types and replies with the qname as the ownername +// and querier's IP as the rdata +type reflectServer Server +func (s *reflectServer) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) { + o, ok := makePkt(a, in) + if ok { + out, ok1 := o.Pack() + if ok1 { + SendUDP(out, c, a) + } + } +} + +func (s *reflectServer) ResponderTCP(c *net.TCPConn, in []byte) { + o, ok := makePkt(c.RemoteAddr(), in) + if ok { + out, ok1 := o.Pack() + if ok1 { + SendTCP(out, c) + } + } +} + +func makePkt(a net.Addr, i []byte) (*dns.Msg, bool) { + msg := new(dns.Msg) + if !msg.Unpack(i) { + return nil, false + } + if msg.MsgHdr.Response == true { + return nil, false + } + m := new(dns.Msg) + m.MsgHdr.Id = msg.MsgHdr.Id + m.MsgHdr.Authoritative = true + m.MsgHdr.Response = true + m.MsgHdr.Opcode = dns.OpcodeQuery + m.MsgHdr.Rcode = dns.RcodeSuccess + m.Question = make([]dns.Question, 1) + m.Question[0] = msg.Question[0] + if msg.Question[0].Qtype != dns.TypeA { + // wrong question + m.MsgHdr.Rcode = dns.RcodeFormatError + return m ,true + } + m.Answer = make([]dns.RR, 1) + r := new(dns.RR_A) + r.Hdr = dns.RR_Header{Name: msg.Question[0].Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0} + ip, _ := net.ResolveUDPAddr(a.String()) + r.A = ip.IP.To4() + m.Answer[0] = r + return m, true +} + +// A simple nameserver implementation. It reponds to queries for the A record and replies +// with the qname as the ownername and the rdata of the A record set to the senders address. +// +// Sample (udp) usage: +// stop := make(chan bool) +// s := new(Server) +// go s.NewResponder(Reflector, stop) +var Reflector *reflectServer diff --git a/responder/responder_test.go b/responder/responder_test.go index cec31b76..17460c69 100644 --- a/responder/responder_test.go +++ b/responder/responder_test.go @@ -36,25 +36,25 @@ func createpkg(id uint16, tcp bool, remove net.Addr) []byte { func (s *myserv) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) { inmsg := new(dns.Msg) inmsg.Unpack(in) - if inmsg.MsgHdr.Response == true { - // Uh... answering to an response?? - // dont think so - return - } + if inmsg.MsgHdr.Response == true { + // Uh... answering to an response?? + // dont think so + return + } out := createpkg(inmsg.MsgHdr.Id, false, a) SendUDP(out, c, a) - // Meta.QLen/RLen/QueryStart/QueryEnd can be filled in at - // this point for logging purposses or anything else + // Meta.QLen/RLen/QueryStart/QueryEnd can be filled in at + // this point for logging purposses or anything else } func (s *myserv) ResponderTCP(c *net.TCPConn, in []byte) { inmsg := new(dns.Msg) inmsg.Unpack(in) - if inmsg.MsgHdr.Response == true { - // Uh... answering to an response?? - // dont think so - return - } + if inmsg.MsgHdr.Response == true { + // Uh... answering to an response?? + // dont think so + return + } out := createpkg(inmsg.MsgHdr.Id, true, c.RemoteAddr()) SendTCP(out, c) } @@ -77,8 +77,30 @@ func TestResponder(t *testing.T) { tch := make(chan bool) go st.NewResponder(ts, tch) time.Sleep(1 * 1e9) - uch<-true - tch<-true - <-uch - <-tch + uch <- true + tch <- true + <-uch + <-tch +} + +func TestReflectorResponder(t *testing.T) { + stop := make(chan bool) + s := new(Server) + s.Port = "8053" + s.Address = "127.0.0.1" + + stoptcp := make(chan bool) + stcp := new(Server) + stcp.Port = "8053" + stcp.Address = "127.0.0.1" + stcp.Tcp = true + + go stcp.NewResponder(Reflector, stoptcp) + go s.NewResponder(Reflector, stop) + + time.Sleep(1 * 1e9) + stop <- true + stoptcp <- true + <-stop + <-stoptcp }