xfr.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. package dns
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. // Envelope is used when doing a zone transfer with a remote server.
  7. type Envelope struct {
  8. RR []RR // The set of RRs in the answer section of the xfr reply message.
  9. Error error // If something went wrong, this contains the error.
  10. }
  11. // A Transfer defines parameters that are used during a zone transfer.
  12. type Transfer struct {
  13. *Conn
  14. DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds
  15. ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
  16. WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
  17. TsigProvider TsigProvider // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations.
  18. 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)
  19. tsigTimersOnly bool
  20. }
  21. func (t *Transfer) tsigProvider() TsigProvider {
  22. if t.TsigProvider != nil {
  23. return t.TsigProvider
  24. }
  25. if t.TsigSecret != nil {
  26. return tsigSecretProvider(t.TsigSecret)
  27. }
  28. return nil
  29. }
  30. // TODO: Think we need to away to stop the transfer
  31. // In performs an incoming transfer with the server in a.
  32. // If you would like to set the source IP, or some other attribute
  33. // of a Dialer for a Transfer, you can do so by specifying the attributes
  34. // in the Transfer.Conn:
  35. //
  36. // d := net.Dialer{LocalAddr: transfer_source}
  37. // con, err := d.Dial("tcp", master)
  38. // dnscon := &dns.Conn{Conn:con}
  39. // transfer = &dns.Transfer{Conn: dnscon}
  40. // channel, err := transfer.In(message, master)
  41. //
  42. func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
  43. switch q.Question[0].Qtype {
  44. case TypeAXFR, TypeIXFR:
  45. default:
  46. return nil, &Error{"unsupported question type"}
  47. }
  48. timeout := dnsTimeout
  49. if t.DialTimeout != 0 {
  50. timeout = t.DialTimeout
  51. }
  52. if t.Conn == nil {
  53. t.Conn, err = DialTimeout("tcp", a, timeout)
  54. if err != nil {
  55. return nil, err
  56. }
  57. }
  58. if err := t.WriteMsg(q); err != nil {
  59. return nil, err
  60. }
  61. env = make(chan *Envelope)
  62. switch q.Question[0].Qtype {
  63. case TypeAXFR:
  64. go t.inAxfr(q, env)
  65. case TypeIXFR:
  66. go t.inIxfr(q, env)
  67. }
  68. return env, nil
  69. }
  70. func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) {
  71. first := true
  72. defer t.Close()
  73. defer close(c)
  74. timeout := dnsTimeout
  75. if t.ReadTimeout != 0 {
  76. timeout = t.ReadTimeout
  77. }
  78. for {
  79. t.Conn.SetReadDeadline(time.Now().Add(timeout))
  80. in, err := t.ReadMsg()
  81. if err != nil {
  82. c <- &Envelope{nil, err}
  83. return
  84. }
  85. if q.Id != in.Id {
  86. c <- &Envelope{in.Answer, ErrId}
  87. return
  88. }
  89. if first {
  90. if in.Rcode != RcodeSuccess {
  91. c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
  92. return
  93. }
  94. if !isSOAFirst(in) {
  95. c <- &Envelope{in.Answer, ErrSoa}
  96. return
  97. }
  98. first = !first
  99. // only one answer that is SOA, receive more
  100. if len(in.Answer) == 1 {
  101. t.tsigTimersOnly = true
  102. c <- &Envelope{in.Answer, nil}
  103. continue
  104. }
  105. }
  106. if !first {
  107. t.tsigTimersOnly = true // Subsequent envelopes use this.
  108. if isSOALast(in) {
  109. c <- &Envelope{in.Answer, nil}
  110. return
  111. }
  112. c <- &Envelope{in.Answer, nil}
  113. }
  114. }
  115. }
  116. func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
  117. var serial uint32 // The first serial seen is the current server serial
  118. axfr := true
  119. n := 0
  120. qser := q.Ns[0].(*SOA).Serial
  121. defer t.Close()
  122. defer close(c)
  123. timeout := dnsTimeout
  124. if t.ReadTimeout != 0 {
  125. timeout = t.ReadTimeout
  126. }
  127. for {
  128. t.SetReadDeadline(time.Now().Add(timeout))
  129. in, err := t.ReadMsg()
  130. if err != nil {
  131. c <- &Envelope{nil, err}
  132. return
  133. }
  134. if q.Id != in.Id {
  135. c <- &Envelope{in.Answer, ErrId}
  136. return
  137. }
  138. if in.Rcode != RcodeSuccess {
  139. c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
  140. return
  141. }
  142. if n == 0 {
  143. // Check if the returned answer is ok
  144. if !isSOAFirst(in) {
  145. c <- &Envelope{in.Answer, ErrSoa}
  146. return
  147. }
  148. // This serial is important
  149. serial = in.Answer[0].(*SOA).Serial
  150. // Check if there are no changes in zone
  151. if qser >= serial {
  152. c <- &Envelope{in.Answer, nil}
  153. return
  154. }
  155. }
  156. // Now we need to check each message for SOA records, to see what we need to do
  157. t.tsigTimersOnly = true
  158. for _, rr := range in.Answer {
  159. if v, ok := rr.(*SOA); ok {
  160. if v.Serial == serial {
  161. n++
  162. // quit if it's a full axfr or the the servers' SOA is repeated the third time
  163. if axfr && n == 2 || n == 3 {
  164. c <- &Envelope{in.Answer, nil}
  165. return
  166. }
  167. } else if axfr {
  168. // it's an ixfr
  169. axfr = false
  170. }
  171. }
  172. }
  173. c <- &Envelope{in.Answer, nil}
  174. }
  175. }
  176. // Out performs an outgoing transfer with the client connecting in w.
  177. // Basic use pattern:
  178. //
  179. // ch := make(chan *dns.Envelope)
  180. // tr := new(dns.Transfer)
  181. // var wg sync.WaitGroup
  182. // go func() {
  183. // tr.Out(w, r, ch)
  184. // wg.Done()
  185. // }()
  186. // ch <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}}
  187. // close(ch)
  188. // wg.Wait() // wait until everything is written out
  189. // w.Close() // close connection
  190. //
  191. // The server is responsible for sending the correct sequence of RRs through the channel ch.
  192. func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
  193. for x := range ch {
  194. r := new(Msg)
  195. // Compress?
  196. r.SetReply(q)
  197. r.Authoritative = true
  198. // assume it fits TODO(miek): fix
  199. r.Answer = append(r.Answer, x.RR...)
  200. if tsig := q.IsTsig(); tsig != nil && w.TsigStatus() == nil {
  201. r.SetTsig(tsig.Hdr.Name, tsig.Algorithm, tsig.Fudge, time.Now().Unix())
  202. }
  203. if err := w.WriteMsg(r); err != nil {
  204. return err
  205. }
  206. w.TsigTimersOnly(true)
  207. }
  208. return nil
  209. }
  210. // ReadMsg reads a message from the transfer connection t.
  211. func (t *Transfer) ReadMsg() (*Msg, error) {
  212. m := new(Msg)
  213. p := make([]byte, MaxMsgSize)
  214. n, err := t.Read(p)
  215. if err != nil && n == 0 {
  216. return nil, err
  217. }
  218. p = p[:n]
  219. if err := m.Unpack(p); err != nil {
  220. return nil, err
  221. }
  222. if ts, tp := m.IsTsig(), t.tsigProvider(); ts != nil && tp != nil {
  223. // Need to work on the original message p, as that was used to calculate the tsig.
  224. err = TsigVerifyWithProvider(p, tp, t.tsigRequestMAC, t.tsigTimersOnly)
  225. t.tsigRequestMAC = ts.MAC
  226. }
  227. return m, err
  228. }
  229. // WriteMsg writes a message through the transfer connection t.
  230. func (t *Transfer) WriteMsg(m *Msg) (err error) {
  231. var out []byte
  232. if ts, tp := m.IsTsig(), t.tsigProvider(); ts != nil && tp != nil {
  233. out, t.tsigRequestMAC, err = TsigGenerateWithProvider(m, tp, t.tsigRequestMAC, t.tsigTimersOnly)
  234. } else {
  235. out, err = m.Pack()
  236. }
  237. if err != nil {
  238. return err
  239. }
  240. _, err = t.Write(out)
  241. return err
  242. }
  243. func isSOAFirst(in *Msg) bool {
  244. return len(in.Answer) > 0 &&
  245. in.Answer[0].Header().Rrtype == TypeSOA
  246. }
  247. func isSOALast(in *Msg) bool {
  248. return len(in.Answer) > 0 &&
  249. in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
  250. }
  251. const errXFR = "bad xfr rcode: %d"