xfr.go 6.6 KB

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