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)
too. Both client and server side programming is supported.
Sample programs can be found in the _examples directory. They can
be build with: make examples (after the dns package has been installed)
Sample programs can be found in the `_examples` directory. They can
be build with: `make examples` (after the dns package has been installed)
The major omission at the moment is parsing Resource Records from
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.
Have fun!
Miek Gieben - 2010, 2011 - miek@miek.nl
Supported RFCs and features include:
## Supported RFCs and features include:
* 1034/1035 - DNS standard
* 1982 - Serial Arithmetic
@ -37,11 +38,12 @@ Supported RFCs and features include:
* 4255 - SSHFP
* 4408 - SPF
* 5001 - NSID
* 5155 - NSEC -- todo
* 5155 - NSEC
* 5936 - AXFR
Loosely based upon:
* ldns
* NSD
* Net::DNS
* GRONG
## Loosely based upon:
* `ldns`
* `NSD`
* `Net::DNS`
* `GRONG`

View File

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

View File

@ -7,7 +7,6 @@ import (
"dns"
"fmt"
"time"
"dns/resolver"
)
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
}
func delay(m *dns.Msg, ok bool) *dns.Msg {
func delay(m *dns.Msg, ok bool) (out *dns.Msg) {
var ok1 bool
switch ok {
case true:
@ -55,26 +54,21 @@ func delay(m *dns.Msg, ok bool) *dns.Msg {
if !ok1 {
fmt.Fprintf(os.Stderr, "Info: Dropping: too often\n")
time.Sleep(NSECDELAY)
return nil
return
} else {
fmt.Fprintf(os.Stderr, "Info: Ok: let it through\n")
var in resolver.Msg
for _, r := range qr {
r <- resolver.Msg{m, nil, nil}
in = <-r
out, _ = r.Query(m)
}
return in.Dns
return
}
case false:
var in resolver.Msg
for _, r := range qr {
r <- resolver.Msg{m, nil, nil}
in = <-r
out, _ = r.Query(m)
}
return in.Dns
return in.Dns
return
}
return nil
return
}
// Return the configration

View File

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

View File

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

View File

@ -21,7 +21,7 @@ import (
type server dns.Server
// 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
var f *Funkensturm
@ -151,7 +151,7 @@ func doFunkensturm(i []byte) ([]byte, os.Error) {
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)
if err != nil {
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 {
responder.SendUDP(out, c, a)
dns.SendUDP(out, c, a)
}
// 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)
if err != nil {
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 {
responder.SendTCP(out, c)
dns.SendTCP(out, c, a)
}
// 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
// TODO IPv6
func splitAddrPort(s string) (a, p string) {
items := strings.Split(s, ":", 2)
a = items[0]
p = items[1]
return
items := strings.Split(s, ":", 2)
a = items[0]
p = items[1]
return
}
func main() {
@ -197,15 +197,13 @@ func main() {
flag.Parse()
resolvers := strings.Split(*rserver, ",", -1)
qr = make([]chan resolver.Msg, len(resolvers))
qr = make([]*dns.Resolver, len(resolvers))
for i, ra := range resolvers {
addr, port := splitAddrPort(ra)
// TODO error checking
// The resolver(s)
r := new(resolver.Resolver)
r := new(dns.Resolver)
r.Servers = []string{addr}
r.Port = port
qr[i] = r.NewQuerier() // connect to global qr[i
qr[i] = r
}
f = funkensturm()
@ -215,14 +213,10 @@ func main() {
return
}
// The responder
addr, port := splitAddrPort(*sserver)
s := new(responder.Server)
s.Address = addr
s.Port = port
// The server
var srv *server
rs := make(chan os.Error)
go s.NewResponder(srv, rs)
quit := make(chan bool)
go dns.ListenAndServe(*sserver, srv, quit)
forever:
for {
@ -230,15 +224,9 @@ forever:
select {
case <-signal.Incoming:
println("Signal received, stopping")
rs <- nil // shutdown responder
quit <- true
break forever
}
}
close(rs)
// And the resolvers
for _, q := range qr {
q <- resolver.Msg{}
<-q
}
close(quit)
}

View File

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