now then
This commit is contained in:
parent
acaa2e8a37
commit
8c36c59739
1
Makefile
1
Makefile
|
@ -18,6 +18,7 @@ GOFILES=\
|
|||
nsec3.go\
|
||||
resolver.go\
|
||||
config.go\
|
||||
responder.go
|
||||
# y.go\
|
||||
|
||||
include $(GOROOT)/src/Make.pkg
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
// Copyright 2011 Miek Gieben. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// DNS server implementation
|
||||
|
||||
// Package responder implements a DNS server. Any nameserver needs to implement
|
||||
// the Responder interface to get things going. Each incoming query is handled
|
||||
// in a seperate goroutine.
|
||||
//
|
||||
// Typical usage of the package:
|
||||
//
|
||||
// type myserv Server
|
||||
// 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 */}
|
||||
//
|
||||
// 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 (
|
||||
"os"
|
||||
"net"
|
||||
"dns"
|
||||
)
|
||||
|
||||
type msg struct {
|
||||
udp *net.UDPConn // udp conn
|
||||
tcp *net.TCPConn // tcp conn
|
||||
addr net.Addr // remote address
|
||||
msg []byte // raw dns message
|
||||
err os.Error // any errors
|
||||
}
|
||||
|
||||
// Every nameserver implements the Hander interface. It defines
|
||||
// the kind of nameserver
|
||||
type Handler interface {
|
||||
// Receives the raw message content and writes back
|
||||
// an UDP response. An UDP connection needs a remote
|
||||
// address to write to. ServeUDP() must take care of sending
|
||||
// any response back to the requestor.
|
||||
ServeUDP(c *net.UDPConn, a net.Addr, in []byte)
|
||||
// Receives the raw message content and writes back
|
||||
// a TCP response. A TCP connection does need to
|
||||
// know explicitly be told the remote address. ServeTCP() must
|
||||
// take care of sending back a response to the requestor.
|
||||
ServeTCP(c *net.TCPConn, in []byte)
|
||||
}
|
||||
|
||||
func ServeUDP(l *net.UDPConn, handler Handler) os.Error {
|
||||
if handler == nil {
|
||||
// handler == DefaultServer
|
||||
}
|
||||
for {
|
||||
m := make([]byte, dns.DefaultMsgSize) // TODO(mg) out of this loop?
|
||||
n, radd, err := l.ReadFromUDP(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m = m[:n]
|
||||
go handler.ServeUDP(l, radd, m)
|
||||
}
|
||||
panic("not reached")
|
||||
}
|
||||
|
||||
func ServeTCP(l *net.TCPListener, handler Handler) os.Error {
|
||||
if handler == nil {
|
||||
// handler = DefaultServer
|
||||
}
|
||||
for {
|
||||
b := make([]byte, 2) // receiver length
|
||||
c, err := l.AcceptTCP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n, cerr := c.Read(b)
|
||||
if cerr != nil {
|
||||
return cerr
|
||||
}
|
||||
length := uint16(b[0])<<8 | uint16(b[1])
|
||||
if length == 0 {
|
||||
return &dns.Error{Error: "received nil msg length"}
|
||||
}
|
||||
m := make([]byte, length)
|
||||
|
||||
n, cerr = c.Read(m)
|
||||
if cerr != nil {
|
||||
return cerr
|
||||
}
|
||||
i := n
|
||||
if i < int(length) {
|
||||
n, err = c.Read(m[i:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i += n
|
||||
}
|
||||
go handler.ServeTCP(c, m)
|
||||
}
|
||||
panic("not reached")
|
||||
}
|
||||
|
||||
func ListenAndServeTCP(addr string, handler Handler) os.Error {
|
||||
ta, err := net.ResolveTCPAddr(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l, err := net.ListenTCP("tcp", ta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ServeTCP(l, handler)
|
||||
l.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
func ListenAndServeUDP(addr string, handler Handler) os.Error {
|
||||
ua, err := net.ResolveUDPAddr(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l, err := net.ListenUDP("udp", ua)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ServeUDP(l, handler)
|
||||
l.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
// Send a buffer on the TCP connection.
|
||||
func SendTCP(m []byte, c *net.TCPConn) os.Error {
|
||||
l := make([]byte, 2)
|
||||
l[0] = byte(len(m) >> 8)
|
||||
l[1] = byte(len(m))
|
||||
// First we send the length
|
||||
_, err := c.Write(l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// And the the message
|
||||
_, err = c.Write(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Send a buffer to the remove address. Only here because
|
||||
// of the symmetry with SendTCP().
|
||||
func SendUDP(m []byte, c *net.UDPConn, a net.Addr) os.Error {
|
||||
_, err := c.WriteTo(m, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
package responder
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"fmt"
|
||||
"dns"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
type myserv Server
|
||||
|
||||
func createpkg(id uint16, tcp bool, remove net.Addr) []byte {
|
||||
m := new(dns.Msg)
|
||||
m.MsgHdr.Id = id
|
||||
m.MsgHdr.Authoritative = true
|
||||
m.MsgHdr.AuthenticatedData = false
|
||||
m.MsgHdr.RecursionAvailable = true
|
||||
m.MsgHdr.Response = true
|
||||
m.MsgHdr.Opcode = dns.OpcodeQuery
|
||||
m.MsgHdr.Rcode = dns.RcodeSuccess
|
||||
m.Question = make([]dns.Question, 1)
|
||||
m.Question[0] = dns.Question{"miek.nl.", dns.TypeTXT, dns.ClassINET}
|
||||
m.Answer = make([]dns.RR, 1)
|
||||
t := new(dns.RR_TXT)
|
||||
t.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 3600}
|
||||
if tcp {
|
||||
t.Txt = "Dit is iets anders TCP"
|
||||
} else {
|
||||
t.Txt = "Dit is iets anders UDP"
|
||||
}
|
||||
m.Answer[0] = t
|
||||
out, _ := m.Pack()
|
||||
return out
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
out := createpkg(inmsg.MsgHdr.Id, true, c.RemoteAddr())
|
||||
SendTCP(out, c)
|
||||
}
|
||||
|
||||
func TestResponder(t *testing.T) {
|
||||
/* udp servertje */
|
||||
su := new(Server)
|
||||
su.Address = "127.0.0.1"
|
||||
su.Port = "8053"
|
||||
var us *myserv
|
||||
uch := make(chan os.Error)
|
||||
go su.NewResponder(us, uch)
|
||||
|
||||
/* tcp servertje */
|
||||
st := new(Server)
|
||||
st.Address = "127.0.0.1"
|
||||
st.Port = "8053"
|
||||
st.Tcp = true
|
||||
var ts *myserv
|
||||
tch := make(chan os.Error)
|
||||
go st.NewResponder(ts, tch)
|
||||
time.Sleep(1 * 1e9)
|
||||
uch <- nil
|
||||
tch <- nil
|
||||
}
|
||||
|
||||
/*
|
||||
func TestReflectorResponder(t *testing.T) {
|
||||
stop := make(chan os.Error)
|
||||
s := new(Server)
|
||||
s.Port = "8053"
|
||||
s.Address = "127.0.0.1"
|
||||
|
||||
stoptcp := make(chan os.Error)
|
||||
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 <- nil
|
||||
stoptcp <- nil
|
||||
}
|
||||
*/
|
||||
|
||||
type servtsig Server
|
||||
|
||||
func createpkgtsig(id uint16, tcp bool, remove net.Addr) []byte {
|
||||
m := new(dns.Msg)
|
||||
m.MsgHdr.Id = id
|
||||
m.MsgHdr.Authoritative = true
|
||||
m.MsgHdr.AuthenticatedData = false
|
||||
m.MsgHdr.RecursionAvailable = true
|
||||
m.MsgHdr.Response = true
|
||||
m.MsgHdr.Opcode = dns.OpcodeQuery
|
||||
m.MsgHdr.Rcode = dns.RcodeSuccess
|
||||
m.Question = make([]dns.Question, 1)
|
||||
m.Question[0] = dns.Question{"miek.nl.", dns.TypeTXT, dns.ClassINET}
|
||||
m.Answer = make([]dns.RR, 1)
|
||||
t := new(dns.RR_TXT)
|
||||
t.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 3600}
|
||||
if tcp {
|
||||
t.Txt = "Dit is iets anders TCP"
|
||||
} else {
|
||||
t.Txt = "Dit is iets anders UDP"
|
||||
}
|
||||
m.Answer[0] = t
|
||||
out, _ := m.Pack()
|
||||
return out
|
||||
}
|
||||
|
||||
func (s *servtsig) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) {
|
||||
inmsg := new(dns.Msg)
|
||||
inmsg.Unpack(in)
|
||||
fmt.Printf("%v\n", inmsg)
|
||||
if inmsg.MsgHdr.Response == true {
|
||||
// Uh... answering to an response??
|
||||
// dont think so
|
||||
return
|
||||
}
|
||||
rr := inmsg.Extra[len(inmsg.Extra)-1]
|
||||
switch t := rr.(type) {
|
||||
case *dns.RR_TSIG:
|
||||
v := t.Verify(inmsg, "awwLOtRfpGE+rRKF2+DEiw==")
|
||||
println(v)
|
||||
}
|
||||
|
||||
|
||||
out := createpkgtsig(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
|
||||
}
|
||||
|
||||
func (s *servtsig) 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
|
||||
}
|
||||
out := createpkgtsig(inmsg.MsgHdr.Id, true, c.RemoteAddr())
|
||||
SendTCP(out, c)
|
||||
}
|
||||
|
||||
func TestResponderTsig(t *testing.T) {
|
||||
/* udp servertje */
|
||||
su := new(Server)
|
||||
su.Address = "127.0.0.1"
|
||||
su.Port = "8053"
|
||||
var us *servtsig
|
||||
uch := make(chan os.Error)
|
||||
go su.NewResponder(us, uch)
|
||||
|
||||
/* tcp servertje */
|
||||
st := new(Server)
|
||||
st.Address = "127.0.0.1"
|
||||
st.Port = "8053"
|
||||
st.Tcp = true
|
||||
var ts *servtsig
|
||||
tch := make(chan os.Error)
|
||||
go st.NewResponder(ts, tch)
|
||||
time.Sleep(1 * 1e9)
|
||||
uch <- nil
|
||||
tch <- nil
|
||||
}
|
Loading…
Reference in New Issue