2011-03-17 02:21:35 +11:00
package dns
2013-10-03 05:35:13 +10:00
import (
2017-06-04 22:30:08 +10:00
"fmt"
2013-10-03 05:35:13 +10:00
"time"
)
2013-09-29 05:32:38 +10:00
2013-10-13 05:01:29 +11:00
// Envelope is used when doing a zone transfer with a remote server.
2012-12-02 18:47:32 +11:00
type Envelope struct {
2013-10-13 05:01:29 +11:00
RR [ ] RR // The set of RRs in the answer section of the xfr reply message.
2012-12-02 18:41:49 +11:00
Error error // If something went wrong, this contains the error.
2012-08-08 17:44:34 +10:00
}
2013-10-13 05:01:29 +11:00
// A Transfer defines parameters that are used during a zone transfer.
2013-10-03 05:35:13 +10:00
type Transfer struct {
2013-10-12 08:34:04 +11:00
* Conn
2015-01-16 09:11:11 +11:00
DialTimeout time . Duration // net.DialTimeout, defaults to 2 seconds
ReadTimeout time . Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
WriteTimeout time . Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
2022-02-05 11:23:49 +11:00
TsigProvider TsigProvider // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations.
2017-11-18 00:17:47 +11:00
TsigSecret map [ string ] string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
2013-10-12 03:36:37 +11:00
tsigTimersOnly bool
2013-10-03 05:35:13 +10:00
}
2022-02-05 11:23:49 +11:00
func ( t * Transfer ) tsigProvider ( ) TsigProvider {
if t . TsigProvider != nil {
return t . TsigProvider
}
if t . TsigSecret != nil {
return tsigSecretProvider ( t . TsigSecret )
}
return nil
}
// TODO: Think we need to away to stop the transfer
2014-06-04 20:21:27 +10:00
2013-10-12 06:10:57 +11:00
// In performs an incoming transfer with the server in a.
2015-09-23 01:44:44 +10:00
// If you would like to set the source IP, or some other attribute
// of a Dialer for a Transfer, you can do so by specifying the attributes
// in the Transfer.Conn:
//
// d := net.Dialer{LocalAddr: transfer_source}
2015-09-24 01:48:28 +10:00
// con, err := d.Dial("tcp", master)
2015-09-23 01:44:44 +10:00
// dnscon := &dns.Conn{Conn:con}
// transfer = &dns.Transfer{Conn: dnscon}
2015-09-24 01:48:28 +10:00
// channel, err := transfer.In(message, master)
2015-09-23 01:44:44 +10:00
//
2013-10-12 06:10:57 +11:00
func ( t * Transfer ) In ( q * Msg , a string ) ( env chan * Envelope , err error ) {
2019-01-04 19:14:40 +11:00
switch q . Question [ 0 ] . Qtype {
case TypeAXFR , TypeIXFR :
default :
return nil , & Error { "unsupported question type" }
}
2013-10-03 05:35:13 +10:00
timeout := dnsTimeout
if t . DialTimeout != 0 {
timeout = t . DialTimeout
2011-09-12 06:10:04 +10:00
}
2019-01-04 19:14:40 +11:00
2015-09-23 01:44:44 +10:00
if t . Conn == nil {
t . Conn , err = DialTimeout ( "tcp" , a , timeout )
if err != nil {
return nil , err
}
2011-04-19 06:08:12 +10:00
}
2019-01-04 19:14:40 +11:00
2013-10-12 22:32:14 +11:00
if err := t . WriteMsg ( q ) ; err != nil {
return nil , err
2011-03-22 02:28:13 +11:00
}
2019-01-04 19:14:40 +11:00
2013-10-12 06:10:57 +11:00
env = make ( chan * Envelope )
2019-01-04 19:14:40 +11:00
switch q . Question [ 0 ] . Qtype {
case TypeAXFR :
go t . inAxfr ( q , env )
case TypeIXFR :
go t . inIxfr ( q , env )
}
2013-10-12 06:10:57 +11:00
return env , nil
2011-03-22 01:44:51 +11:00
}
2017-10-14 02:21:31 +11:00
func ( t * Transfer ) inAxfr ( q * Msg , c chan * Envelope ) {
2011-04-19 06:08:12 +10:00
first := true
2013-10-11 06:01:35 +11:00
defer t . Close ( )
2012-05-18 20:06:31 +10:00
defer close ( c )
2013-10-12 03:36:37 +11:00
timeout := dnsTimeout
if t . ReadTimeout != 0 {
timeout = t . ReadTimeout
}
2011-03-22 01:44:51 +11:00
for {
2013-10-12 22:32:14 +11:00
t . Conn . SetReadDeadline ( time . Now ( ) . Add ( timeout ) )
2013-10-11 06:01:35 +11:00
in , err := t . ReadMsg ( )
2011-03-22 01:44:51 +11:00
if err != nil {
2012-12-02 18:47:32 +11:00
c <- & Envelope { nil , err }
2011-09-10 22:48:22 +10:00
return
2011-03-22 01:44:51 +11:00
}
2017-10-14 02:21:31 +11:00
if q . Id != in . Id {
2012-12-02 18:47:32 +11:00
c <- & Envelope { in . Answer , ErrId }
2011-09-12 01:01:55 +10:00
return
}
2011-03-22 01:44:51 +11:00
if first {
2017-06-04 22:30:08 +10:00
if in . Rcode != RcodeSuccess {
c <- & Envelope { in . Answer , & Error { err : fmt . Sprintf ( errXFR , in . Rcode ) } }
return
}
2013-10-12 03:18:37 +11:00
if ! isSOAFirst ( in ) {
2012-12-02 18:47:32 +11:00
c <- & Envelope { in . Answer , ErrSoa }
2011-09-10 22:48:22 +10:00
return
2011-03-22 01:44:51 +11:00
}
first = ! first
2013-07-11 16:42:32 +10:00
// only one answer that is SOA, receive more
2013-09-06 19:49:07 +10:00
if len ( in . Answer ) == 1 {
2013-10-12 03:18:37 +11:00
t . tsigTimersOnly = true
2013-07-11 16:42:32 +10:00
c <- & Envelope { in . Answer , nil }
continue
}
2011-03-22 01:44:51 +11:00
}
2011-03-19 00:13:42 +11:00
2011-03-22 01:44:51 +11:00
if ! first {
2013-10-12 03:18:37 +11:00
t . tsigTimersOnly = true // Subsequent envelopes use this.
if isSOALast ( in ) {
2012-12-02 18:47:32 +11:00
c <- & Envelope { in . Answer , nil }
2011-09-10 22:48:22 +10:00
return
2011-03-22 01:44:51 +11:00
}
2012-12-02 18:47:32 +11:00
c <- & Envelope { in . Answer , nil }
2011-03-22 01:44:51 +11:00
}
}
2011-04-18 17:58:15 +10:00
}
2017-10-14 02:21:31 +11:00
func ( t * Transfer ) inIxfr ( q * Msg , c chan * Envelope ) {
2019-01-04 21:30:55 +11:00
var serial uint32 // The first serial seen is the current server serial
2017-10-14 02:21:31 +11:00
axfr := true
n := 0
qser := q . Ns [ 0 ] . ( * SOA ) . Serial
2013-10-12 03:36:37 +11:00
defer t . Close ( )
2012-05-18 20:06:31 +10:00
defer close ( c )
2013-10-12 03:36:37 +11:00
timeout := dnsTimeout
2013-10-03 05:35:13 +10:00
if t . ReadTimeout != 0 {
timeout = t . ReadTimeout
}
2011-03-22 01:44:51 +11:00
for {
2013-10-12 03:36:37 +11:00
t . SetReadDeadline ( time . Now ( ) . Add ( timeout ) )
in , err := t . ReadMsg ( )
2011-09-12 06:10:04 +10:00
if err != nil {
2015-06-05 22:59:53 +10:00
c <- & Envelope { nil , err }
2011-09-12 06:10:04 +10:00
return
}
2017-10-14 02:21:31 +11:00
if q . Id != in . Id {
2012-12-02 18:47:32 +11:00
c <- & Envelope { in . Answer , ErrId }
2011-03-22 01:44:51 +11:00
return
}
2017-10-14 02:21:31 +11:00
if in . Rcode != RcodeSuccess {
c <- & Envelope { in . Answer , & Error { err : fmt . Sprintf ( errXFR , in . Rcode ) } }
return
}
if n == 0 {
2011-09-11 00:49:22 +10:00
// Check if the returned answer is ok
2013-10-12 03:36:37 +11:00
if ! isSOAFirst ( in ) {
2012-12-02 18:47:32 +11:00
c <- & Envelope { in . Answer , ErrSoa }
2011-03-22 01:44:51 +11:00
return
}
// This serial is important
2012-12-10 05:23:25 +11:00
serial = in . Answer [ 0 ] . ( * SOA ) . Serial
2017-10-14 02:21:31 +11:00
// Check if there are no changes in zone
if qser >= serial {
c <- & Envelope { in . Answer , nil }
return
}
2011-03-22 01:44:51 +11:00
}
// Now we need to check each message for SOA records, to see what we need to do
2017-10-14 02:21:31 +11:00
t . tsigTimersOnly = true
for _ , rr := range in . Answer {
if v , ok := rr . ( * SOA ) ; ok {
2011-09-12 06:10:04 +10:00
if v . Serial == serial {
2017-10-14 02:21:31 +11:00
n ++
// quit if it's a full axfr or the the servers' SOA is repeated the third time
if axfr && n == 2 || n == 3 {
c <- & Envelope { in . Answer , nil }
return
}
} else if axfr {
// it's an ixfr
axfr = false
2011-09-12 06:10:04 +10:00
}
}
2011-03-22 01:44:51 +11:00
}
2017-10-14 02:21:31 +11:00
c <- & Envelope { in . Answer , nil }
2011-03-22 01:44:51 +11:00
}
2011-03-19 00:13:42 +11:00
}
2011-09-12 01:24:52 +10:00
2013-10-13 02:26:25 +11:00
// Out performs an outgoing transfer with the client connecting in w.
// Basic use pattern:
2013-05-06 04:30:44 +10:00
//
2013-10-13 02:26:25 +11:00
// ch := make(chan *dns.Envelope)
// tr := new(dns.Transfer)
2019-12-20 00:11:22 +11:00
// var wg sync.WaitGroup
// go func() {
// tr.Out(w, r, ch)
// wg.Done()
// }()
2016-03-29 01:45:23 +11:00
// ch <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}}
2013-10-13 02:26:25 +11:00
// close(ch)
2019-12-20 00:11:22 +11:00
// wg.Wait() // wait until everything is written out
// w.Close() // close connection
2012-08-28 19:03:41 +10:00
//
2019-12-20 00:11:22 +11:00
// The server is responsible for sending the correct sequence of RRs through the channel ch.
2013-10-13 02:12:21 +11:00
func ( t * Transfer ) Out ( w ResponseWriter , q * Msg , ch chan * Envelope ) error {
2015-01-15 21:39:47 +11:00
for x := range ch {
2015-01-15 21:57:52 +11:00
r := new ( Msg )
// Compress?
r . SetReply ( q )
r . Authoritative = true
2015-01-15 21:39:47 +11:00
// assume it fits TODO(miek): fix
r . Answer = append ( r . Answer , x . RR ... )
2019-05-12 18:15:21 +10:00
if tsig := q . IsTsig ( ) ; tsig != nil && w . TsigStatus ( ) == nil {
r . SetTsig ( tsig . Hdr . Name , tsig . Algorithm , tsig . Fudge , time . Now ( ) . Unix ( ) )
}
2015-01-15 21:39:47 +11:00
if err := w . WriteMsg ( r ) ; err != nil {
return err
2013-10-12 03:18:37 +11:00
}
2019-05-12 18:15:21 +10:00
w . TsigTimersOnly ( true )
2015-01-15 21:39:47 +11:00
}
2013-10-13 02:12:21 +11:00
return nil
2013-10-03 05:35:13 +10:00
}
// ReadMsg reads a message from the transfer connection t.
func ( t * Transfer ) ReadMsg ( ) ( * Msg , error ) {
m := new ( Msg )
p := make ( [ ] byte , MaxMsgSize )
2013-10-11 06:01:35 +11:00
n , err := t . Read ( p )
2013-10-03 05:35:13 +10:00
if err != nil && n == 0 {
2012-05-18 20:06:31 +10:00
return nil , err
2011-09-10 22:59:21 +10:00
}
2013-10-03 05:35:13 +10:00
p = p [ : n ]
if err := m . Unpack ( p ) ; err != nil {
2012-05-18 20:06:31 +10:00
return nil , err
2011-04-19 06:08:12 +10:00
}
2022-02-05 11:23:49 +11:00
if ts , tp := m . IsTsig ( ) , t . tsigProvider ( ) ; ts != nil && tp != nil {
2013-10-03 05:35:13 +10:00
// Need to work on the original message p, as that was used to calculate the tsig.
2022-02-05 11:23:49 +11:00
err = tsigVerifyProvider ( p , tp , t . tsigRequestMAC , t . tsigTimersOnly )
2015-02-25 01:45:03 +11:00
t . tsigRequestMAC = ts . MAC
2013-10-03 05:35:13 +10:00
}
return m , err
2011-09-10 22:59:21 +10:00
}
2013-10-13 05:01:29 +11:00
// WriteMsg writes a message through the transfer connection t.
2013-10-03 05:35:13 +10:00
func ( t * Transfer ) WriteMsg ( m * Msg ) ( err error ) {
var out [ ] byte
2022-02-05 11:23:49 +11:00
if ts , tp := m . IsTsig ( ) , t . tsigProvider ( ) ; ts != nil && tp != nil {
out , t . tsigRequestMAC , err = tsigGenerateProvider ( m , tp , t . tsigRequestMAC , t . tsigTimersOnly )
2013-10-03 05:35:13 +10:00
} else {
out , err = m . Pack ( )
2012-08-28 04:58:58 +10:00
}
2013-10-03 05:35:13 +10:00
if err != nil {
return err
}
2019-01-04 21:19:42 +11:00
_ , err = t . Write ( out )
return err
2013-10-03 05:35:13 +10:00
}
2013-10-12 03:18:37 +11:00
func isSOAFirst ( in * Msg ) bool {
2019-01-04 21:19:42 +11:00
return len ( in . Answer ) > 0 &&
in . Answer [ 0 ] . Header ( ) . Rrtype == TypeSOA
2013-10-11 06:01:35 +11:00
}
2013-10-12 03:18:37 +11:00
func isSOALast ( in * Msg ) bool {
2019-01-04 21:19:42 +11:00
return len ( in . Answer ) > 0 &&
in . Answer [ len ( in . Answer ) - 1 ] . Header ( ) . Rrtype == TypeSOA
2012-08-28 04:58:58 +10:00
}
2017-06-04 22:30:08 +10:00
const errXFR = "bad xfr rcode: %d"