diff --git a/TODO b/TODO index 7139fab3..ef25f230 100644 --- a/TODO +++ b/TODO @@ -14,6 +14,7 @@ Todo: Issues: * Better sized buffers +* Make the testsuite work with public DNS servers * TC bit handling * shortened ipv6 addresses are not parsed correctly * quoted quotes in txt records diff --git a/dns.go b/dns.go index e2acdffc..4a42d071 100644 --- a/dns.go +++ b/dns.go @@ -27,6 +27,20 @@ import ( const Year68 = 2 << (32 - 1) +type DNSError struct { + Error string + Name string + Server string + IsTimeout bool +} + +func (e *DNSError) String() string { + if e == nil { + return "" + } + return e.Error +} + type RR interface { Header() *RR_Header String() string diff --git a/resolver/axfr_test.go b/resolver/axfr_test.go index 97a3a106..039360a5 100644 --- a/resolver/axfr_test.go +++ b/resolver/axfr_test.go @@ -14,8 +14,8 @@ func TestAXFR(t *testing.T) { res.Servers = []string{"127.0.0.1"} m := new(dns.Msg) m.Question = make([]dns.Question, 1) - // ask something - m.Question[0] = dns.Question{"miek.nl", dns.TypeAXFR, dns.ClassINET} + //m.Question[0] = dns.Question{"miek.nl", dns.TypeAXFR, dns.ClassINET} + m.Question[0] = dns.Question{"atoom.net", dns.TypeAXFR, dns.ClassINET} ch <- DnsMsg{m, nil} for dm := range ch { diff --git a/resolver/resolver.go b/resolver/resolver.go index 56d791a9..a98fa5e5 100644 --- a/resolver/resolver.go +++ b/resolver/resolver.go @@ -97,7 +97,7 @@ func query(res *Resolver, msg chan DnsMsg) { } else { c, cerr = net.Dial("udp", "", server) } - defer c.Close() + defer c.Close() if cerr != nil { err = cerr continue @@ -168,53 +168,53 @@ func axfr(res *Resolver, msg chan DnsMsg) { err = cerr continue SERVER } - defer c.Close() + defer c.Close() first := true - // Start the AXFR + // Start the AXFR for { - if first { - in, cerr = exchange_tcp(c, sending, res, true) - } else { - in, cerr = exchange_tcp(c, sending, res, false) - } + if first { + in, cerr = exchange_tcp(c, sending, res, true) + } else { + in, cerr = exchange_tcp(c, sending, res, false) + } if cerr != nil { - // Failed to send, try the next + // Failed to send, try the next err = cerr continue SERVER } if first { if !checkSOA(in, true) { // SOA record not there... - c.Close() - continue SERVER + c.Close() + continue SERVER } first = !first } - if !first { + if !first { if !checkSOA(in, false) { // Soa record not the last one msg <- DnsMsg{in, nil} - continue + continue // next } else { - c.Close() + c.Close() msg <- DnsMsg{in, nil} - close(msg) - return + close(msg) + return } } } - close(msg) - return + close(msg) + return } - // With 1 successfull server, we dont get here, so - // We've failed - msg <- DnsMsg{nil, err} // TODO Err - close(msg) - return + // With 1 successfull server, we dont get here, so + // We've failed + msg <- DnsMsg{nil, err} // TODO Err + close(msg) + return } } return @@ -240,13 +240,13 @@ func exchange_udp(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Er attempts = r.Attempts } for a := 0; a < attempts; a++ { - if send { - _, err := c.Write(m) - if err != nil { - //println("error writing") - return nil, err - } - } + if send { + _, err := c.Write(m) + if err != nil { + //println("error writing") + return nil, err + } + } c.SetReadTimeout(timeout * 1e9) // nanoseconds buf := make([]byte, dns.DefaultMsgSize) // More than enough??? @@ -273,7 +273,7 @@ func exchange_udp(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Er // Up to res.Attempts attempts. func exchange_tcp(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Error) { var timeout int64 - var attempts int + var attempts, n int if r.Mangle != nil { m = r.Mangle(m) } @@ -294,20 +294,20 @@ func exchange_tcp(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Er ls[0] = byte(len(m) >> 8) ls[1] = byte(len(m)) for a := 0; a < attempts; a++ { - // only send something when told so - if send { - // With DNS over TCP we first send the length - _, err := c.Write(ls) - if err != nil { - return nil, err - } + // only send something when told so + if send { + // With DNS over TCP we first send the length + _, err := c.Write(ls) + if err != nil { + return nil, err + } - // And then send the message - _, err = c.Write(m) - if err != nil { - return nil, err - } - } + // And then send the message + _, err = c.Write(m) + if err != nil { + return nil, err + } + } c.SetReadTimeout(timeout * 1e9) // nanoseconds // The server replies with two bytes length @@ -319,16 +319,19 @@ func exchange_tcp(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Er // if length is 0?? // And then the message buf := make([]byte, length) - _, err = c.Read(buf) + + n, err = c.Read(buf) if err != nil { - //println("error reading") - //println(err.String()) - // More Go foo needed - //if e, ok := err.(Error); ok && e.Timeout() { - // continue - //} return nil, err } + i := n + if i < int(length) { + n, err = c.Read(buf[i:]) + if err != nil { + return nil, err + } + i += n + } in := new(dns.Msg) if !in.Unpack(buf) { // println("unpacking went wrong")