More transfer stuff
This commit is contained in:
parent
5868ba4cc8
commit
b987dc6246
18
client.go
18
client.go
|
@ -16,12 +16,12 @@ const dnsTimeout time.Duration = 2 * 1e9
|
||||||
|
|
||||||
// A Conn represents a connection (which may be short lived) to a DNS server.
|
// A Conn represents a connection (which may be short lived) to a DNS server.
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
net.Conn // a net.Conn holding the connection
|
net.Conn // a net.Conn holding the connection
|
||||||
UDPSize uint16 // Minimum receive buffer for UDP messages
|
UDPSize uint16 // Minimum receive buffer for UDP messages
|
||||||
TsigSecret map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
|
TsigSecret map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
|
||||||
rtt time.Duration
|
rtt time.Duration
|
||||||
t time.Time
|
t time.Time
|
||||||
requestMAC string
|
tsigRequestMAC string
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Client defines parameters for a DNS client. A nil Client is usable for sending queries.
|
// A Client defines parameters for a DNS client. A nil Client is usable for sending queries.
|
||||||
|
@ -150,7 +150,7 @@ func (co *Conn) ReadMsg() (*Msg, error) {
|
||||||
return m, ErrSecret
|
return m, ErrSecret
|
||||||
}
|
}
|
||||||
// Need to work on the original message p, as that was used to calculate the tsig.
|
// Need to work on the original message p, as that was used to calculate the tsig.
|
||||||
err = TsigVerify(p, co.TsigSecret[t.Hdr.Name], co.requestMAC, false)
|
err = TsigVerify(p, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
|
||||||
}
|
}
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
@ -208,9 +208,9 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
|
||||||
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
|
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
|
||||||
return ErrSecret
|
return ErrSecret
|
||||||
}
|
}
|
||||||
out, mac, err = TsigGenerate(m, co.TsigSecret[t.Hdr.Name], co.requestMAC, false)
|
out, mac, err = TsigGenerate(m, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
|
||||||
// Set for the next read, allthough only used in zone transfers
|
// Set for the next read, allthough only used in zone transfers
|
||||||
co.requestMAC = mac
|
co.tsigRequestMAC = mac
|
||||||
} else {
|
} else {
|
||||||
out, err = m.Pack()
|
out, err = m.Pack()
|
||||||
}
|
}
|
||||||
|
|
73
xfr.go
73
xfr.go
|
@ -20,7 +20,7 @@ type Transfer struct {
|
||||||
DialTimeout time.Duration // net.DialTimeout (ns), defaults to 2 * 1e9
|
DialTimeout time.Duration // net.DialTimeout (ns), defaults to 2 * 1e9
|
||||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections (ns), defaults to 2 * 1e9
|
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections (ns), defaults to 2 * 1e9
|
||||||
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections (ns), defaults to 2 * 1e9
|
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections (ns), defaults to 2 * 1e9
|
||||||
timersOnly bool
|
tsigTimersOnly bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// In performs a [AI]XFR request (depends on the message's Qtype). It returns
|
// In performs a [AI]XFR request (depends on the message's Qtype). It returns
|
||||||
|
@ -69,27 +69,27 @@ func (t *Transfer) InAxfr(id uint16, c chan *Envelope) {
|
||||||
c <- &Envelope{nil, err}
|
c <- &Envelope{nil, err}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if id != q.Id {
|
if id != in.Id {
|
||||||
c <- &Envelope{in.Answer, ErrId}
|
c <- &Envelope{in.Answer, ErrId}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if first {
|
if first {
|
||||||
if !checkSOA(in, true) {
|
if !isSOAFirst(in) {
|
||||||
c <- &Envelope{in.Answer, ErrSoa}
|
c <- &Envelope{in.Answer, ErrSoa}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
first = !first
|
first = !first
|
||||||
// only one answer that is SOA, receive more
|
// only one answer that is SOA, receive more
|
||||||
if len(in.Answer) == 1 {
|
if len(in.Answer) == 1 {
|
||||||
w.tsigTimersOnly = true
|
t.tsigTimersOnly = true
|
||||||
c <- &Envelope{in.Answer, nil}
|
c <- &Envelope{in.Answer, nil}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !first {
|
if !first {
|
||||||
w.tsigTimersOnly = true // Subsequent envelopes use this.
|
t.tsigTimersOnly = true // Subsequent envelopes use this.
|
||||||
if checkSOA(in, false) {
|
if isSOALast(in) {
|
||||||
c <- &Envelope{in.Answer, nil}
|
c <- &Envelope{in.Answer, nil}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,7 @@ func (t *Transfer) InAxfr(id uint16, c chan *Envelope) {
|
||||||
panic("dns: not reached")
|
panic("dns: not reached")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// re-read 'n stuff must be pushed down
|
// re-read 'n stuff must be pushed down
|
||||||
timeout = dnsTimeout
|
timeout = dnsTimeout
|
||||||
if t.ReadTimeout != 0 {
|
if t.ReadTimeout != 0 {
|
||||||
|
@ -112,11 +113,24 @@ func (t *Transfer) InAxfr(id uint16, c chan *Envelope) {
|
||||||
co.SetWriteDeadline(time.Now().Add(dnsTimeout))
|
co.SetWriteDeadline(time.Now().Add(dnsTimeout))
|
||||||
defer co.Close()
|
defer co.Close()
|
||||||
return nil
|
return nil
|
||||||
}
|
*/
|
||||||
|
|
||||||
func (t *Transfer) Out(w ResponseWriter, q *Msg, a string) (chan *Envelope, error) {
|
func (t *Transfer) Out(w ResponseWriter, q *Msg, a string) (chan *Envelope, error) {
|
||||||
ch := make(chan *Envelope)
|
ch := make(chan *Envelope)
|
||||||
|
r := new(Msg)
|
||||||
|
r.SetReply(q)
|
||||||
|
r.Authoritative = true
|
||||||
|
go func() {
|
||||||
|
for x := range ch {
|
||||||
|
// assume it fits TODO(miek): fix
|
||||||
|
r.Answer = append(r.Answer, x.RR...)
|
||||||
|
if err := w.WriteMsg(r); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// w.TsigTimersOnly(true)
|
||||||
|
// rep.Answer = nil
|
||||||
|
}()
|
||||||
return ch, nil
|
return ch, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +151,7 @@ func (t *Transfer) ReadMsg() (*Msg, error) {
|
||||||
return m, ErrSecret
|
return m, ErrSecret
|
||||||
}
|
}
|
||||||
// Need to work on the original message p, as that was used to calculate the tsig.
|
// Need to work on the original message p, as that was used to calculate the tsig.
|
||||||
err = TsigVerify(p, t.TsigSecret[ts.Hdr.Name], t.requestMAC, t.timersOnly)
|
err = TsigVerify(p, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
|
||||||
}
|
}
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
@ -149,7 +163,7 @@ func (t *Transfer) WriteMsg(m *Msg) (err error) {
|
||||||
if _, ok := t.TsigSecret[ts.Hdr.Name]; !ok {
|
if _, ok := t.TsigSecret[ts.Hdr.Name]; !ok {
|
||||||
return ErrSecret
|
return ErrSecret
|
||||||
}
|
}
|
||||||
out, t.requestMAC, err = TsigGenerate(m, t.TsigSecret[ts.Hdr.Name], t.requestMAC, t.timersOnly)
|
out, t.tsigRequestMAC, err = TsigGenerate(m, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
|
||||||
} else {
|
} else {
|
||||||
out, err = m.Pack()
|
out, err = m.Pack()
|
||||||
}
|
}
|
||||||
|
@ -211,51 +225,18 @@ func (w *reply) ixfrIn(q *Msg, c chan *Envelope) {
|
||||||
}
|
}
|
||||||
panic("dns: not reached")
|
panic("dns: not reached")
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
func isSOAFirst(in *Msg) bool {
|
||||||
|
|
||||||
func checkFirstSOA(in *Msg) bool {
|
|
||||||
if len(in.Answer) > 0 {
|
if len(in.Answer) > 0 {
|
||||||
return in.Answer[0].Header().Rrtype == TypeSOA
|
return in.Answer[0].Header().Rrtype == TypeSOA
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkLastSOA(in *Msg) bool {
|
func isSOALast(in *Msg) bool {
|
||||||
if len(in.Answer) > 0 {
|
if len(in.Answer) > 0 {
|
||||||
return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
|
return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
func TransferOut(w ResponseWriter, q *Msg, c chan *Envelope, e *error) error {
|
|
||||||
switch q.Question[0].Qtype {
|
|
||||||
case TypeAXFR, TypeIXFR:
|
|
||||||
go xfrOut(w, q, c, e)
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
panic("dns: not reached")
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(mg): count the RRs and the resulting size.
|
|
||||||
func xfrOut(w ResponseWriter, req *Msg, c chan *Envelope, e *error) {
|
|
||||||
rep := new(Msg)
|
|
||||||
rep.SetReply(req)
|
|
||||||
rep.Authoritative = true
|
|
||||||
|
|
||||||
for x := range c {
|
|
||||||
// assume it fits
|
|
||||||
rep.Answer = append(rep.Answer, x.RR...)
|
|
||||||
if err := w.WriteMsg(rep); e != nil {
|
|
||||||
*e = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.TsigTimersOnly(true)
|
|
||||||
rep.Answer = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
Loading…
Reference in New Issue