Test Nameserver Inside responder pkg

This commit is contained in:
Miek Gieben 2011-01-18 21:01:08 +01:00
parent 04f2bf449a
commit 5786959b98
6 changed files with 128 additions and 33 deletions

1
TODO
View File

@ -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

View File

@ -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

4
dns.go
View File

@ -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
}

View File

@ -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 {

View File

@ -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

View File

@ -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
}