Framework for xfr started in resolver

This commit is contained in:
Miek Gieben 2010-12-31 17:05:11 +01:00
parent 82c954bead
commit 1c9282ed7e
2 changed files with 95 additions and 27 deletions

51
msg.go
View File

@ -27,6 +27,31 @@ import (
const DefaultMsgSize = 4096
// A manually-unpacked version of (id, bits).
// This is in its own struct for easy printing.
type MsgHdr struct {
Id uint16
Response bool
Opcode int
Authoritative bool
Truncated bool
RecursionDesired bool
RecursionAvailable bool
Zero bool
AuthenticatedData bool
CheckingDisabled bool
Rcode int
}
// The layout of a DNS message.
type Msg struct {
MsgHdr
Question []Question
Answer []RR
Ns []RR
Extra []RR
}
// Packing and unpacking.
//
// All the packers and unpackers take a (msg []byte, off int)
@ -536,22 +561,6 @@ func unpackRR(msg []byte, off int) (rr RR, off1 int, ok bool) {
// Usable representation of a DNS packet.
// A manually-unpacked version of (id, bits).
// This is in its own struct for easy printing.
type MsgHdr struct {
Id uint16
Response bool
Opcode int
Authoritative bool
Truncated bool
RecursionDesired bool
RecursionAvailable bool
Zero bool
AuthenticatedData bool
CheckingDisabled bool
Rcode int
}
// Convert a MsgHdr to a string, mimic the way Dig displays headers:
//;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48404
//;; flags: qr aa rd ra;
@ -594,16 +603,6 @@ func (h *MsgHdr) String() string {
return s
}
// The layout of a DNS message.
type Msg struct {
MsgHdr
Question []Question
Answer []RR
Ns []RR
Extra []RR
}
func (dns *Msg) Pack() (msg []byte, ok bool) {
var dh Header

View File

@ -60,7 +60,7 @@ func NewQuerier(res *Resolver) (ch chan DnsMsg) {
// The query function.
func query(res *Resolver, msg chan DnsMsg) {
// TODO port number, error checking, robustness
// error checking, robustness
var c net.Conn
var err os.Error
var in *dns.Msg
@ -138,6 +138,61 @@ func NewXfer(res *Resolver) (ch chan DnsMsg) {
}
func axfr(res *Resolver, msg chan DnsMsg) {
// open socket
// call exchange_tcp
// check for soa
// repeat if no soa
// close channel
var port string
var err os.Error
var in *dns.Msg
if res.Port == "" {
port = "53"
} else {
port = res.Port
}
var sending []byte
// out.Dns.Id = uint16(rand.Int()) ^ uint16(time.Nanoseconds())
// sending, ok := out.Dns.Pack()
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
}
first := true
for {
in, cerr = exchange_tcp(c, sending, res)
if cerr != nil {
err = cerr
continue
}
if first {
if ! checkSOA(in, true) {
// SOA record not there...
return // ?
}
first = !first
// send in to message
continue
} else {
if ! checkSOA(in, false) {
// Soa record not the last one
// return packet
// next
} else {
// last one
// close channel
}
}
}
}
err = err
return
}
@ -254,3 +309,17 @@ func exchange_tcp(c net.Conn, m []byte, r *Resolver) (*dns.Msg, os.Error) {
}
return nil, nil // todo error
}
// Check if he SOA record exists in the Answer section of
// the packet. If first is true the first RR must be a soa
// if false, the last one should be a SOA
func checkSOA(in *dns.Msg, first bool) bool {
if len(in.Answer) > 0 {
if first {
return in.Answer[0].Header().Rrtype == dns.TypeSOA
} else {
return in.Answer[len(in.Answer)].Header().Rrtype == dns.TypeSOA
}
}
return false
}