Fix TCP sending

esp. when an imcomplete message is send back from the server.
Fix {A,I}XFR also
Add DNSError
This commit is contained in:
Miek Gieben 2011-01-01 18:47:38 +01:00
parent 43ebf75fac
commit daf625264e
4 changed files with 71 additions and 53 deletions

1
TODO
View File

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

14
dns.go
View File

@ -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 "<nil>"
}
return e.Error
}
type RR interface {
Header() *RR_Header
String() string

View File

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

View File

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