Bring funkensturm up to date for the new api

This commit is contained in:
Miek Gieben 2011-02-10 12:26:26 +01:00
parent dd6d245488
commit 61925e2002
7 changed files with 201 additions and 226 deletions

View File

@ -5,8 +5,8 @@ supported. DNSSEC types too.
EDNS0 is (see edns.go), UDP/TCP queries, TSIG, AXFR (and IXFR probably) EDNS0 is (see edns.go), UDP/TCP queries, TSIG, AXFR (and IXFR probably)
too. Both client and server side programming is supported. too. Both client and server side programming is supported.
Sample programs can be found in the _examples directory. They can Sample programs can be found in the `_examples` directory. They can
be build with: make examples (after the dns package has been installed) be build with: `make examples` (after the dns package has been installed)
The major omission at the moment is parsing Resource Records from The major omission at the moment is parsing Resource Records from
strings. (i.e. supporting the RFC 1035 zone file format). strings. (i.e. supporting the RFC 1035 zone file format).
@ -15,9 +15,10 @@ Also the IPv6 support needs to be tested
Everything else should be present and working. If not, drop me an email. Everything else should be present and working. If not, drop me an email.
Have fun! Have fun!
Miek Gieben - 2010, 2011 - miek@miek.nl Miek Gieben - 2010, 2011 - miek@miek.nl
Supported RFCs and features include: ## Supported RFCs and features include:
* 1034/1035 - DNS standard * 1034/1035 - DNS standard
* 1982 - Serial Arithmetic * 1982 - Serial Arithmetic
@ -37,11 +38,12 @@ Supported RFCs and features include:
* 4255 - SSHFP * 4255 - SSHFP
* 4408 - SPF * 4408 - SPF
* 5001 - NSID * 5001 - NSID
* 5155 - NSEC -- todo * 5155 - NSEC
* 5936 - AXFR * 5936 - AXFR
Loosely based upon: ## Loosely based upon:
* ldns
* NSD * `ldns`
* Net::DNS * `NSD`
* GRONG * `Net::DNS`
* `GRONG`

View File

@ -2,7 +2,6 @@ package main
import ( import (
"dns" "dns"
"dns/resolver"
) )
func match(m *dns.Msg, d int) (*dns.Msg, bool) { func match(m *dns.Msg, d int) (*dns.Msg, bool) {
@ -26,17 +25,15 @@ func match(m *dns.Msg, d int) (*dns.Msg, bool) {
return m, true return m, true
} }
func send(m *dns.Msg, ok bool) *dns.Msg { func send(m *dns.Msg, ok bool) (out *dns.Msg) {
switch ok { switch ok {
case true, false: case true, false:
var in resolver.Msg
for _, r := range qr { for _, r := range qr {
r <- resolver.Msg{m, nil, nil} out, _ = r.Query(m)
in = <-r
} }
return in.Dns // return the last return
} }
return nil return
} }
// Return the configration // Return the configration

View File

@ -7,7 +7,6 @@ import (
"dns" "dns"
"fmt" "fmt"
"time" "time"
"dns/resolver"
) )
const NSECDELAY = 1 * 1e9 // 1 second, meaning 1 qps (smaller means higher qps) const NSECDELAY = 1 * 1e9 // 1 second, meaning 1 qps (smaller means higher qps)
@ -47,7 +46,7 @@ func match(m *dns.Msg, d int) (*dns.Msg, bool) {
return m, ok return m, ok
} }
func delay(m *dns.Msg, ok bool) *dns.Msg { func delay(m *dns.Msg, ok bool) (out *dns.Msg) {
var ok1 bool var ok1 bool
switch ok { switch ok {
case true: case true:
@ -55,26 +54,21 @@ func delay(m *dns.Msg, ok bool) *dns.Msg {
if !ok1 { if !ok1 {
fmt.Fprintf(os.Stderr, "Info: Dropping: too often\n") fmt.Fprintf(os.Stderr, "Info: Dropping: too often\n")
time.Sleep(NSECDELAY) time.Sleep(NSECDELAY)
return nil return
} else { } else {
fmt.Fprintf(os.Stderr, "Info: Ok: let it through\n") fmt.Fprintf(os.Stderr, "Info: Ok: let it through\n")
var in resolver.Msg
for _, r := range qr { for _, r := range qr {
r <- resolver.Msg{m, nil, nil} out, _ = r.Query(m)
in = <-r
} }
return in.Dns return
} }
case false: case false:
var in resolver.Msg
for _, r := range qr { for _, r := range qr {
r <- resolver.Msg{m, nil, nil} out, _ = r.Query(m)
in = <-r
} }
return in.Dns return
return in.Dns
} }
return nil return
} }
// Return the configration // Return the configration

View File

@ -2,7 +2,6 @@ package main
import ( import (
"dns" "dns"
"dns/resolver"
) )
func match(m *dns.Msg, d int) (*dns.Msg, bool) { func match(m *dns.Msg, d int) (*dns.Msg, bool) {
@ -26,17 +25,15 @@ func match(m *dns.Msg, d int) (*dns.Msg, bool) {
return m, true return m, true
} }
func send(m *dns.Msg, ok bool) *dns.Msg { func send(m *dns.Msg, ok bool) (out *dns.Msg) {
switch ok { switch ok {
case true, false: case true, false:
var in resolver.Msg
for _, r := range qr { for _, r := range qr {
r <- resolver.Msg{m, nil, nil} out, _ = r.Query(m)
in = <-r
} }
return in.Dns return
} }
return nil return
} }
// Return the configration // Return the configration

View File

@ -7,7 +7,6 @@ package main
// We could also use one 1 key for multiple domains. // We could also use one 1 key for multiple domains.
import ( import (
"dns" "dns"
"dns/resolver"
"crypto/rsa" "crypto/rsa"
) )
@ -59,17 +58,15 @@ func match(m *dns.Msg, d int) (*dns.Msg, bool) {
return m, true return m, true
} }
func send(m *dns.Msg, ok bool) *dns.Msg { func send(m *dns.Msg, ok bool) (out *dns.Msg) {
switch ok { switch ok {
case true, false: case true, false:
var in resolver.Msg
for _, r := range qr { for _, r := range qr {
r <- resolver.Msg{m, nil, nil} out, _ = r.Query(m)
in = <-r
} }
return in.Dns // return the last return
} }
return nil return
} }
var pubkey *dns.RR_DNSKEY var pubkey *dns.RR_DNSKEY

View File

@ -21,7 +21,7 @@ import (
type server dns.Server type server dns.Server
// Define a slice of channels for the resolver for sending the queries somewhere else. // Define a slice of channels for the resolver for sending the queries somewhere else.
var qr []chan resolver.Msg var qr []*dns.Resolver
// The configuration of Funkensturm // The configuration of Funkensturm
var f *Funkensturm var f *Funkensturm
@ -151,7 +151,7 @@ func doFunkensturm(i []byte) ([]byte, os.Error) {
return out, nil return out, nil
} }
func (s *server) ResponderUDP(c *net.UDPConn, a net.Addr, i []byte) { func (s *server) ReplyUDP(c *net.UDPConn, a net.Addr, i []byte) {
out, err := doFunkensturm(i) out, err := doFunkensturm(i)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err.String()) fmt.Fprintf(os.Stderr, "Error: %s\n", err.String())
@ -159,12 +159,12 @@ func (s *server) ResponderUDP(c *net.UDPConn, a net.Addr, i []byte) {
} }
if out != nil { if out != nil {
responder.SendUDP(out, c, a) dns.SendUDP(out, c, a)
} }
// nothing is send back // nothing is send back
} }
func (s *server) ResponderTCP(c *net.TCPConn, i []byte) { func (s *server) ReplyTCP(c *net.TCPConn, a net.Addr, i []byte) {
out, err := doFunkensturm(i) out, err := doFunkensturm(i)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err.String()) fmt.Fprintf(os.Stderr, "Error: %s\n", err.String())
@ -172,7 +172,7 @@ func (s *server) ResponderTCP(c *net.TCPConn, i []byte) {
} }
if out != nil { if out != nil {
responder.SendTCP(out, c) dns.SendTCP(out, c, a)
} }
// nothing is send back // nothing is send back
} }
@ -180,10 +180,10 @@ func (s *server) ResponderTCP(c *net.TCPConn, i []byte) {
// split 127.0.0.1:53 into components // split 127.0.0.1:53 into components
// TODO IPv6 // TODO IPv6
func splitAddrPort(s string) (a, p string) { func splitAddrPort(s string) (a, p string) {
items := strings.Split(s, ":", 2) items := strings.Split(s, ":", 2)
a = items[0] a = items[0]
p = items[1] p = items[1]
return return
} }
func main() { func main() {
@ -197,15 +197,13 @@ func main() {
flag.Parse() flag.Parse()
resolvers := strings.Split(*rserver, ",", -1) resolvers := strings.Split(*rserver, ",", -1)
qr = make([]chan resolver.Msg, len(resolvers)) qr = make([]*dns.Resolver, len(resolvers))
for i, ra := range resolvers { for i, ra := range resolvers {
addr, port := splitAddrPort(ra) addr, port := splitAddrPort(ra)
// TODO error checking r := new(dns.Resolver)
// The resolver(s)
r := new(resolver.Resolver)
r.Servers = []string{addr} r.Servers = []string{addr}
r.Port = port r.Port = port
qr[i] = r.NewQuerier() // connect to global qr[i qr[i] = r
} }
f = funkensturm() f = funkensturm()
@ -215,14 +213,10 @@ func main() {
return return
} }
// The responder // The server
addr, port := splitAddrPort(*sserver)
s := new(responder.Server)
s.Address = addr
s.Port = port
var srv *server var srv *server
rs := make(chan os.Error) quit := make(chan bool)
go s.NewResponder(srv, rs) go dns.ListenAndServe(*sserver, srv, quit)
forever: forever:
for { for {
@ -230,15 +224,9 @@ forever:
select { select {
case <-signal.Incoming: case <-signal.Incoming:
println("Signal received, stopping") println("Signal received, stopping")
rs <- nil // shutdown responder quit <- true
break forever break forever
} }
} }
close(rs) close(quit)
// And the resolvers
for _, q := range qr {
q <- resolver.Msg{}
<-q
}
} }

View File

@ -42,7 +42,7 @@ type Resolver struct {
Rotate bool // round robin among servers -- TODO Rotate bool // round robin among servers -- TODO
Tcp bool // use TCP Tcp bool // use TCP
Mangle func([]byte) []byte // mangle the packet Mangle func([]byte) []byte // mangle the packet
// rtt map[string]int server->int, smaller is faster 0, -1 is unreacheble // rtt map[string]int server->int, smaller is faster 0, -1 is unreacheble
} }
// Send a query using *res, q holds the question to be asked. // Send a query using *res, q holds the question to be asked.
@ -50,136 +50,136 @@ type Resolver struct {
func (res *Resolver) Query(q *Msg) (d *Msg, err os.Error) { func (res *Resolver) Query(q *Msg) (d *Msg, err os.Error) {
var ( var (
c net.Conn c net.Conn
in *Msg in *Msg
port string port string
) )
if len(res.Servers) == 0 { if len(res.Servers) == 0 {
return nil, &Error{Error: "No servers defined"} return nil, &Error{Error: "No servers defined"}
} }
// len(res.Server) == 0 can be perfectly valid, when setting up the resolver // len(res.Server) == 0 can be perfectly valid, when setting up the resolver
// It is now // It is now
if res.Port == "" { if res.Port == "" {
port = "53" port = "53"
} else { } else {
port = res.Port port = res.Port
} }
if q.Id == 0 { if q.Id == 0 {
// No Id sed, set it // No Id sed, set it
q.SetId() q.SetId()
} }
sending, ok := q.Pack() sending, ok := q.Pack()
if !ok { if !ok {
return nil, &Error{Error: packErr} return nil, &Error{Error: packErr}
} }
for i := 0; i < len(res.Servers); i++ { for i := 0; i < len(res.Servers); i++ {
server := res.Servers[i] + ":" + port server := res.Servers[i] + ":" + port
if res.Tcp { if res.Tcp {
c, err = net.Dial("tcp", "", server) c, err = net.Dial("tcp", "", server)
} else { } else {
c, err = net.Dial("udp", "", server) c, err = net.Dial("udp", "", server)
} }
if err != nil { if err != nil {
continue continue
} }
if res.Tcp { if res.Tcp {
in, err = exchangeTCP(c, sending, res, true) in, err = exchangeTCP(c, sending, res, true)
} else { } else {
in, err = exchangeUDP(c, sending, res, true) in, err = exchangeUDP(c, sending, res, true)
} }
// Check id in.id != out.id, should be checked in the client! // Check id in.id != out.id, should be checked in the client!
c.Close() c.Close()
if err != nil { if err != nil {
continue continue
} }
break break
} }
if err != nil { if err != nil {
return nil, err return nil, err
} }
return in, nil return in, nil
} }
// q holds the inital query // q holds the inital query
// channel is closed by AXfr // channel is closed by AXfr
func (res *Resolver) Axfr(q *Msg, m chan *Msg) { func (res *Resolver) Axfr(q *Msg, m chan *Msg) {
var port string var port string
var err os.Error var err os.Error
var in *Msg var in *Msg
if res.Port == "" { if res.Port == "" {
port = "53" port = "53"
} else { } else {
port = res.Port port = res.Port
} }
var _ = err // TODO(mg) var _ = err // TODO(mg)
if q.Id == 0 { if q.Id == 0 {
q.SetId() q.SetId()
}
sending, ok := q.Pack()
if !ok {
m <- nil
return
} }
SERVER: sending, ok := q.Pack()
for i := 0; i < len(res.Servers); i++ { if !ok {
server := res.Servers[i] + ":" + port m <- nil
c, cerr := net.Dial("tcp", "", server) return
if cerr != nil { }
err = cerr
continue SERVER
}
first := true
// Start the AXFR
for {
if first {
in, cerr = exchangeTCP(c, sending, res, true)
} else {
in, err = exchangeTCP(c, sending, res, false)
}
if cerr != nil { SERVER:
// Failed to send, try the next for i := 0; i < len(res.Servers); i++ {
err = cerr server := res.Servers[i] + ":" + port
c.Close() c, cerr := net.Dial("tcp", "", server)
continue SERVER if cerr != nil {
} err = cerr
if in.Id != q.Id { continue SERVER
m <- nil }
return first := true
} // Start the AXFR
for {
if first {
in, cerr = exchangeTCP(c, sending, res, true)
} else {
in, err = exchangeTCP(c, sending, res, false)
}
if first { if cerr != nil {
if !checkSOA(in, true) { // Failed to send, try the next
c.Close() err = cerr
continue SERVER c.Close()
} continue SERVER
m <- in }
first = !first if in.Id != q.Id {
} m <- nil
return
}
if !first { if first {
if !checkSOA(in, false) { if !checkSOA(in, true) {
// Soa record not the last one c.Close()
m <- in continue SERVER
continue }
} else { m <- in
c.Close() first = !first
m <- in }
close(m)
return if !first {
} if !checkSOA(in, false) {
} // Soa record not the last one
} m <- in
println("Should never be reached") continue
return } else {
} c.Close()
close(m) m <- in
close(m)
return
}
}
}
println("Should never be reached")
return
}
close(m)
return return
} }
@ -251,7 +251,7 @@ func exchangeTCP(c net.Conn, m []byte, r *Resolver, send bool) (*Msg, os.Error)
for a := 0; a < attempts; a++ { for a := 0; a < attempts; a++ {
// only send something when told so // only send something when told so
if send { if send {
err := sendTCP(m,c) err := sendTCP(m, c)
if err != nil { if err != nil {
if e, ok := err.(net.Error); ok && e.Timeout() { if e, ok := err.(net.Error); ok && e.Timeout() {
continue continue
@ -278,66 +278,66 @@ func exchangeTCP(c net.Conn, m []byte, r *Resolver, send bool) (*Msg, os.Error)
return nil, &Error{Error: servErr} return nil, &Error{Error: servErr}
} }
func sendUDP(m []byte,c net.Conn) os.Error { func sendUDP(m []byte, c net.Conn) os.Error {
_, err := c.Write(m) _, err := c.Write(m)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
func recvUDP(c net.Conn) ([]byte, os.Error) { func recvUDP(c net.Conn) ([]byte, os.Error) {
m := make([]byte, DefaultMsgSize) // More than enough??? m := make([]byte, DefaultMsgSize) // More than enough???
n, err := c.Read(m) n, err := c.Read(m)
if err != nil { if err != nil {
return nil, err return nil, err
} }
m = m[:n] m = m[:n]
return m, nil return m, nil
} }
func sendTCP(m []byte, c net.Conn) os.Error { func sendTCP(m []byte, c net.Conn) os.Error {
l := make([]byte, 2) l := make([]byte, 2)
l[0] = byte(len(m) >> 8) l[0] = byte(len(m) >> 8)
l[1] = byte(len(m)) l[1] = byte(len(m))
// First we send the length // First we send the length
_, err := c.Write(l) _, err := c.Write(l)
if err != nil { if err != nil {
return err return err
} }
// And the the message // And the the message
_, err = c.Write(m) _, err = c.Write(m)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
func recvTCP(c net.Conn) ([]byte, os.Error) { func recvTCP(c net.Conn) ([]byte, os.Error) {
l := make([]byte, 2) // receiver length l := make([]byte, 2) // receiver length
// The server replies with two bytes length // The server replies with two bytes length
_, err := c.Read(l) _, err := c.Read(l)
if err != nil { if err != nil {
return nil,err return nil, err
} }
length := uint16(l[0])<<8 | uint16(l[1]) length := uint16(l[0])<<8 | uint16(l[1])
if length == 0 { if length == 0 {
return nil, &Error{Error: "received nil msg length", Server: c.RemoteAddr().String()} return nil, &Error{Error: "received nil msg length", Server: c.RemoteAddr().String()}
} }
m := make([]byte, length) m := make([]byte, length)
n, cerr := c.Read(m) n, cerr := c.Read(m)
if cerr != nil { if cerr != nil {
return nil, cerr return nil, cerr
} }
i := n i := n
if i < int(length) { if i < int(length) {
n, err = c.Read(m[i:]) n, err = c.Read(m[i:])
if err != nil { if err != nil {
return nil, err return nil, err
} }
i += n i += n
} }
return m, nil return m, nil
} }
// Check if he SOA record exists in the Answer section of // Check if he SOA record exists in the Answer section of