dnsmsg.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // DNS packet assembly. See RFC 1035.
  5. //
  6. // This is intended to support name resolution during Dial.
  7. // It doesn't have to be blazing fast.
  8. //
  9. // Each message structure has a Walk method that is used by
  10. // a generic pack/unpack routine. Thus, if in the future we need
  11. // to define new message structs, no new pack/unpack/printing code
  12. // needs to be written.
  13. //
  14. // The first half of this file defines the DNS message formats.
  15. // The second half implements the conversion to and from wire format.
  16. // A few of the structure elements have string tags to aid the
  17. // generic pack/unpack routines.
  18. //
  19. // TODO(rsc): There are enough names defined in this file that they're all
  20. // prefixed with dns. Perhaps put this in its own package later.
  21. package net
  22. // Packet formats
  23. // Wire constants.
  24. const (
  25. // valid dnsRR_Header.Rrtype and dnsQuestion.qtype
  26. dnsTypeA = 1
  27. dnsTypeNS = 2
  28. dnsTypeMD = 3
  29. dnsTypeMF = 4
  30. dnsTypeCNAME = 5
  31. dnsTypeSOA = 6
  32. dnsTypeMB = 7
  33. dnsTypeMG = 8
  34. dnsTypeMR = 9
  35. dnsTypeNULL = 10
  36. dnsTypeWKS = 11
  37. dnsTypePTR = 12
  38. dnsTypeHINFO = 13
  39. dnsTypeMINFO = 14
  40. dnsTypeMX = 15
  41. dnsTypeTXT = 16
  42. dnsTypeAAAA = 28
  43. dnsTypeSRV = 33
  44. // valid dnsQuestion.qtype only
  45. dnsTypeAXFR = 252
  46. dnsTypeMAILB = 253
  47. dnsTypeMAILA = 254
  48. dnsTypeALL = 255
  49. // valid dnsQuestion.qclass
  50. dnsClassINET = 1
  51. dnsClassCSNET = 2
  52. dnsClassCHAOS = 3
  53. dnsClassHESIOD = 4
  54. dnsClassANY = 255
  55. // dnsMsg.rcode
  56. dnsRcodeSuccess = 0
  57. dnsRcodeFormatError = 1
  58. dnsRcodeServerFailure = 2
  59. dnsRcodeNameError = 3
  60. dnsRcodeNotImplemented = 4
  61. dnsRcodeRefused = 5
  62. )
  63. // A dnsStruct describes how to iterate over its fields to emulate
  64. // reflective marshalling.
  65. type dnsStruct interface {
  66. // Walk iterates over fields of a structure and calls f
  67. // with a reference to that field, the name of the field
  68. // and a tag ("", "domain", "ipv4", "ipv6") specifying
  69. // particular encodings. Possible concrete types
  70. // for v are *uint16, *uint32, *string, or []byte, and
  71. // *int, *bool in the case of dnsMsgHdr.
  72. // Whenever f returns false, Walk must stop and return
  73. // false, and otherwise return true.
  74. Walk(f func(v interface{}, name, tag string) (ok bool)) (ok bool)
  75. }
  76. // The wire format for the DNS packet header.
  77. type dnsHeader struct {
  78. Id uint16
  79. Bits uint16
  80. Qdcount, Ancount, Nscount, Arcount uint16
  81. }
  82. func (h *dnsHeader) Walk(f func(v interface{}, name, tag string) bool) bool {
  83. return f(&h.Id, "Id", "") &&
  84. f(&h.Bits, "Bits", "") &&
  85. f(&h.Qdcount, "Qdcount", "") &&
  86. f(&h.Ancount, "Ancount", "") &&
  87. f(&h.Nscount, "Nscount", "") &&
  88. f(&h.Arcount, "Arcount", "")
  89. }
  90. const (
  91. // dnsHeader.Bits
  92. _QR = 1 << 15 // query/response (response=1)
  93. _AA = 1 << 10 // authoritative
  94. _TC = 1 << 9 // truncated
  95. _RD = 1 << 8 // recursion desired
  96. _RA = 1 << 7 // recursion available
  97. )
  98. // DNS queries.
  99. type dnsQuestion struct {
  100. Name string `net:"domain-name"` // `net:"domain-name"` specifies encoding; see packers below
  101. Qtype uint16
  102. Qclass uint16
  103. }
  104. func (q *dnsQuestion) Walk(f func(v interface{}, name, tag string) bool) bool {
  105. return f(&q.Name, "Name", "domain") &&
  106. f(&q.Qtype, "Qtype", "") &&
  107. f(&q.Qclass, "Qclass", "")
  108. }
  109. // DNS responses (resource records).
  110. // There are many types of messages,
  111. // but they all share the same header.
  112. type dnsRR_Header struct {
  113. Name string `net:"domain-name"`
  114. Rrtype uint16
  115. Class uint16
  116. Ttl uint32
  117. Rdlength uint16 // length of data after header
  118. }
  119. func (h *dnsRR_Header) Header() *dnsRR_Header {
  120. return h
  121. }
  122. func (h *dnsRR_Header) Walk(f func(v interface{}, name, tag string) bool) bool {
  123. return f(&h.Name, "Name", "domain") &&
  124. f(&h.Rrtype, "Rrtype", "") &&
  125. f(&h.Class, "Class", "") &&
  126. f(&h.Ttl, "Ttl", "") &&
  127. f(&h.Rdlength, "Rdlength", "")
  128. }
  129. type dnsRR interface {
  130. dnsStruct
  131. Header() *dnsRR_Header
  132. }
  133. // Specific DNS RR formats for each query type.
  134. type dnsRR_CNAME struct {
  135. Hdr dnsRR_Header
  136. Cname string `net:"domain-name"`
  137. }
  138. func (rr *dnsRR_CNAME) Header() *dnsRR_Header {
  139. return &rr.Hdr
  140. }
  141. func (rr *dnsRR_CNAME) Walk(f func(v interface{}, name, tag string) bool) bool {
  142. return rr.Hdr.Walk(f) && f(&rr.Cname, "Cname", "domain")
  143. }
  144. type dnsRR_HINFO struct {
  145. Hdr dnsRR_Header
  146. Cpu string
  147. Os string
  148. }
  149. func (rr *dnsRR_HINFO) Header() *dnsRR_Header {
  150. return &rr.Hdr
  151. }
  152. func (rr *dnsRR_HINFO) Walk(f func(v interface{}, name, tag string) bool) bool {
  153. return rr.Hdr.Walk(f) && f(&rr.Cpu, "Cpu", "") && f(&rr.Os, "Os", "")
  154. }
  155. type dnsRR_MB struct {
  156. Hdr dnsRR_Header
  157. Mb string `net:"domain-name"`
  158. }
  159. func (rr *dnsRR_MB) Header() *dnsRR_Header {
  160. return &rr.Hdr
  161. }
  162. func (rr *dnsRR_MB) Walk(f func(v interface{}, name, tag string) bool) bool {
  163. return rr.Hdr.Walk(f) && f(&rr.Mb, "Mb", "domain")
  164. }
  165. type dnsRR_MG struct {
  166. Hdr dnsRR_Header
  167. Mg string `net:"domain-name"`
  168. }
  169. func (rr *dnsRR_MG) Header() *dnsRR_Header {
  170. return &rr.Hdr
  171. }
  172. func (rr *dnsRR_MG) Walk(f func(v interface{}, name, tag string) bool) bool {
  173. return rr.Hdr.Walk(f) && f(&rr.Mg, "Mg", "domain")
  174. }
  175. type dnsRR_MINFO struct {
  176. Hdr dnsRR_Header
  177. Rmail string `net:"domain-name"`
  178. Email string `net:"domain-name"`
  179. }
  180. func (rr *dnsRR_MINFO) Header() *dnsRR_Header {
  181. return &rr.Hdr
  182. }
  183. func (rr *dnsRR_MINFO) Walk(f func(v interface{}, name, tag string) bool) bool {
  184. return rr.Hdr.Walk(f) && f(&rr.Rmail, "Rmail", "domain") && f(&rr.Email, "Email", "domain")
  185. }
  186. type dnsRR_MR struct {
  187. Hdr dnsRR_Header
  188. Mr string `net:"domain-name"`
  189. }
  190. func (rr *dnsRR_MR) Header() *dnsRR_Header {
  191. return &rr.Hdr
  192. }
  193. func (rr *dnsRR_MR) Walk(f func(v interface{}, name, tag string) bool) bool {
  194. return rr.Hdr.Walk(f) && f(&rr.Mr, "Mr", "domain")
  195. }
  196. type dnsRR_MX struct {
  197. Hdr dnsRR_Header
  198. Pref uint16
  199. Mx string `net:"domain-name"`
  200. }
  201. func (rr *dnsRR_MX) Header() *dnsRR_Header {
  202. return &rr.Hdr
  203. }
  204. func (rr *dnsRR_MX) Walk(f func(v interface{}, name, tag string) bool) bool {
  205. return rr.Hdr.Walk(f) && f(&rr.Pref, "Pref", "") && f(&rr.Mx, "Mx", "domain")
  206. }
  207. type dnsRR_NS struct {
  208. Hdr dnsRR_Header
  209. Ns string `net:"domain-name"`
  210. }
  211. func (rr *dnsRR_NS) Header() *dnsRR_Header {
  212. return &rr.Hdr
  213. }
  214. func (rr *dnsRR_NS) Walk(f func(v interface{}, name, tag string) bool) bool {
  215. return rr.Hdr.Walk(f) && f(&rr.Ns, "Ns", "domain")
  216. }
  217. type dnsRR_PTR struct {
  218. Hdr dnsRR_Header
  219. Ptr string `net:"domain-name"`
  220. }
  221. func (rr *dnsRR_PTR) Header() *dnsRR_Header {
  222. return &rr.Hdr
  223. }
  224. func (rr *dnsRR_PTR) Walk(f func(v interface{}, name, tag string) bool) bool {
  225. return rr.Hdr.Walk(f) && f(&rr.Ptr, "Ptr", "domain")
  226. }
  227. type dnsRR_SOA struct {
  228. Hdr dnsRR_Header
  229. Ns string `net:"domain-name"`
  230. Mbox string `net:"domain-name"`
  231. Serial uint32
  232. Refresh uint32
  233. Retry uint32
  234. Expire uint32
  235. Minttl uint32
  236. }
  237. func (rr *dnsRR_SOA) Header() *dnsRR_Header {
  238. return &rr.Hdr
  239. }
  240. func (rr *dnsRR_SOA) Walk(f func(v interface{}, name, tag string) bool) bool {
  241. return rr.Hdr.Walk(f) &&
  242. f(&rr.Ns, "Ns", "domain") &&
  243. f(&rr.Mbox, "Mbox", "domain") &&
  244. f(&rr.Serial, "Serial", "") &&
  245. f(&rr.Refresh, "Refresh", "") &&
  246. f(&rr.Retry, "Retry", "") &&
  247. f(&rr.Expire, "Expire", "") &&
  248. f(&rr.Minttl, "Minttl", "")
  249. }
  250. type dnsRR_TXT struct {
  251. Hdr dnsRR_Header
  252. Txt string // not domain name
  253. }
  254. func (rr *dnsRR_TXT) Header() *dnsRR_Header {
  255. return &rr.Hdr
  256. }
  257. func (rr *dnsRR_TXT) Walk(f func(v interface{}, name, tag string) bool) bool {
  258. return rr.Hdr.Walk(f) && f(&rr.Txt, "Txt", "")
  259. }
  260. type dnsRR_SRV struct {
  261. Hdr dnsRR_Header
  262. Priority uint16
  263. Weight uint16
  264. Port uint16
  265. Target string `net:"domain-name"`
  266. }
  267. func (rr *dnsRR_SRV) Header() *dnsRR_Header {
  268. return &rr.Hdr
  269. }
  270. func (rr *dnsRR_SRV) Walk(f func(v interface{}, name, tag string) bool) bool {
  271. return rr.Hdr.Walk(f) &&
  272. f(&rr.Priority, "Priority", "") &&
  273. f(&rr.Weight, "Weight", "") &&
  274. f(&rr.Port, "Port", "") &&
  275. f(&rr.Target, "Target", "domain")
  276. }
  277. type dnsRR_A struct {
  278. Hdr dnsRR_Header
  279. A uint32 `net:"ipv4"`
  280. }
  281. func (rr *dnsRR_A) Header() *dnsRR_Header {
  282. return &rr.Hdr
  283. }
  284. func (rr *dnsRR_A) Walk(f func(v interface{}, name, tag string) bool) bool {
  285. return rr.Hdr.Walk(f) && f(&rr.A, "A", "ipv4")
  286. }
  287. type dnsRR_AAAA struct {
  288. Hdr dnsRR_Header
  289. AAAA [16]byte `net:"ipv6"`
  290. }
  291. func (rr *dnsRR_AAAA) Header() *dnsRR_Header {
  292. return &rr.Hdr
  293. }
  294. func (rr *dnsRR_AAAA) Walk(f func(v interface{}, name, tag string) bool) bool {
  295. return rr.Hdr.Walk(f) && f(rr.AAAA[:], "AAAA", "ipv6")
  296. }
  297. // Packing and unpacking.
  298. //
  299. // All the packers and unpackers take a (msg []byte, off int)
  300. // and return (off1 int, ok bool). If they return ok==false, they
  301. // also return off1==len(msg), so that the next unpacker will
  302. // also fail. This lets us avoid checks of ok until the end of a
  303. // packing sequence.
  304. // Map of constructors for each RR wire type.
  305. var rr_mk = map[int]func() dnsRR{
  306. dnsTypeCNAME: func() dnsRR { return new(dnsRR_CNAME) },
  307. dnsTypeHINFO: func() dnsRR { return new(dnsRR_HINFO) },
  308. dnsTypeMB: func() dnsRR { return new(dnsRR_MB) },
  309. dnsTypeMG: func() dnsRR { return new(dnsRR_MG) },
  310. dnsTypeMINFO: func() dnsRR { return new(dnsRR_MINFO) },
  311. dnsTypeMR: func() dnsRR { return new(dnsRR_MR) },
  312. dnsTypeMX: func() dnsRR { return new(dnsRR_MX) },
  313. dnsTypeNS: func() dnsRR { return new(dnsRR_NS) },
  314. dnsTypePTR: func() dnsRR { return new(dnsRR_PTR) },
  315. dnsTypeSOA: func() dnsRR { return new(dnsRR_SOA) },
  316. dnsTypeTXT: func() dnsRR { return new(dnsRR_TXT) },
  317. dnsTypeSRV: func() dnsRR { return new(dnsRR_SRV) },
  318. dnsTypeA: func() dnsRR { return new(dnsRR_A) },
  319. dnsTypeAAAA: func() dnsRR { return new(dnsRR_AAAA) },
  320. }
  321. // Pack a domain name s into msg[off:].
  322. // Domain names are a sequence of counted strings
  323. // split at the dots. They end with a zero-length string.
  324. func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) {
  325. // Add trailing dot to canonicalize name.
  326. if n := len(s); n == 0 || s[n-1] != '.' {
  327. s += "."
  328. }
  329. // Each dot ends a segment of the name.
  330. // We trade each dot byte for a length byte.
  331. // There is also a trailing zero.
  332. // Check that we have all the space we need.
  333. tot := len(s) + 1
  334. if off+tot > len(msg) {
  335. return len(msg), false
  336. }
  337. // Emit sequence of counted strings, chopping at dots.
  338. begin := 0
  339. for i := 0; i < len(s); i++ {
  340. if s[i] == '.' {
  341. if i-begin >= 1<<6 { // top two bits of length must be clear
  342. return len(msg), false
  343. }
  344. msg[off] = byte(i - begin)
  345. off++
  346. for j := begin; j < i; j++ {
  347. msg[off] = s[j]
  348. off++
  349. }
  350. begin = i + 1
  351. }
  352. }
  353. msg[off] = 0
  354. off++
  355. return off, true
  356. }
  357. // Unpack a domain name.
  358. // In addition to the simple sequences of counted strings above,
  359. // domain names are allowed to refer to strings elsewhere in the
  360. // packet, to avoid repeating common suffixes when returning
  361. // many entries in a single domain. The pointers are marked
  362. // by a length byte with the top two bits set. Ignoring those
  363. // two bits, that byte and the next give a 14 bit offset from msg[0]
  364. // where we should pick up the trail.
  365. // Note that if we jump elsewhere in the packet,
  366. // we return off1 == the offset after the first pointer we found,
  367. // which is where the next record will start.
  368. // In theory, the pointers are only allowed to jump backward.
  369. // We let them jump anywhere and stop jumping after a while.
  370. func unpackDomainName(msg []byte, off int) (s string, off1 int, ok bool) {
  371. s = ""
  372. ptr := 0 // number of pointers followed
  373. Loop:
  374. for {
  375. if off >= len(msg) {
  376. return "", len(msg), false
  377. }
  378. c := int(msg[off])
  379. off++
  380. switch c & 0xC0 {
  381. case 0x00:
  382. if c == 0x00 {
  383. // end of name
  384. break Loop
  385. }
  386. // literal string
  387. if off+c > len(msg) {
  388. return "", len(msg), false
  389. }
  390. s += string(msg[off:off+c]) + "."
  391. off += c
  392. case 0xC0:
  393. // pointer to somewhere else in msg.
  394. // remember location after first ptr,
  395. // since that's how many bytes we consumed.
  396. // also, don't follow too many pointers --
  397. // maybe there's a loop.
  398. if off >= len(msg) {
  399. return "", len(msg), false
  400. }
  401. c1 := msg[off]
  402. off++
  403. if ptr == 0 {
  404. off1 = off
  405. }
  406. if ptr++; ptr > 10 {
  407. return "", len(msg), false
  408. }
  409. off = (c^0xC0)<<8 | int(c1)
  410. default:
  411. // 0x80 and 0x40 are reserved
  412. return "", len(msg), false
  413. }
  414. }
  415. if ptr == 0 {
  416. off1 = off
  417. }
  418. return s, off1, true
  419. }
  420. // packStruct packs a structure into msg at specified offset off, and
  421. // returns off1 such that msg[off:off1] is the encoded data.
  422. func packStruct(any dnsStruct, msg []byte, off int) (off1 int, ok bool) {
  423. ok = any.Walk(func(field interface{}, name, tag string) bool {
  424. switch fv := field.(type) {
  425. default:
  426. println("net: dns: unknown packing type")
  427. return false
  428. case *uint16:
  429. i := *fv
  430. if off+2 > len(msg) {
  431. return false
  432. }
  433. msg[off] = byte(i >> 8)
  434. msg[off+1] = byte(i)
  435. off += 2
  436. case *uint32:
  437. i := *fv
  438. msg[off] = byte(i >> 24)
  439. msg[off+1] = byte(i >> 16)
  440. msg[off+2] = byte(i >> 8)
  441. msg[off+3] = byte(i)
  442. off += 4
  443. case []byte:
  444. n := len(fv)
  445. if off+n > len(msg) {
  446. return false
  447. }
  448. copy(msg[off:off+n], fv)
  449. off += n
  450. case *string:
  451. s := *fv
  452. switch tag {
  453. default:
  454. println("net: dns: unknown string tag", tag)
  455. return false
  456. case "domain":
  457. off, ok = packDomainName(s, msg, off)
  458. if !ok {
  459. return false
  460. }
  461. case "":
  462. // Counted string: 1 byte length.
  463. if len(s) > 255 || off+1+len(s) > len(msg) {
  464. return false
  465. }
  466. msg[off] = byte(len(s))
  467. off++
  468. off += copy(msg[off:], s)
  469. }
  470. }
  471. return true
  472. })
  473. if !ok {
  474. return len(msg), false
  475. }
  476. return off, true
  477. }
  478. // unpackStruct decodes msg[off:] into the given structure, and
  479. // returns off1 such that msg[off:off1] is the encoded data.
  480. func unpackStruct(any dnsStruct, msg []byte, off int) (off1 int, ok bool) {
  481. ok = any.Walk(func(field interface{}, name, tag string) bool {
  482. switch fv := field.(type) {
  483. default:
  484. println("net: dns: unknown packing type")
  485. return false
  486. case *uint16:
  487. if off+2 > len(msg) {
  488. return false
  489. }
  490. *fv = uint16(msg[off])<<8 | uint16(msg[off+1])
  491. off += 2
  492. case *uint32:
  493. if off+4 > len(msg) {
  494. return false
  495. }
  496. *fv = uint32(msg[off])<<24 | uint32(msg[off+1])<<16 |
  497. uint32(msg[off+2])<<8 | uint32(msg[off+3])
  498. off += 4
  499. case []byte:
  500. n := len(fv)
  501. if off+n > len(msg) {
  502. return false
  503. }
  504. copy(fv, msg[off:off+n])
  505. off += n
  506. case *string:
  507. var s string
  508. switch tag {
  509. default:
  510. println("net: dns: unknown string tag", tag)
  511. return false
  512. case "domain":
  513. s, off, ok = unpackDomainName(msg, off)
  514. if !ok {
  515. return false
  516. }
  517. case "":
  518. if off >= len(msg) || off+1+int(msg[off]) > len(msg) {
  519. return false
  520. }
  521. n := int(msg[off])
  522. off++
  523. b := make([]byte, n)
  524. for i := 0; i < n; i++ {
  525. b[i] = msg[off+i]
  526. }
  527. off += n
  528. s = string(b)
  529. }
  530. *fv = s
  531. }
  532. return true
  533. })
  534. if !ok {
  535. return len(msg), false
  536. }
  537. return off, true
  538. }
  539. // Generic struct printer. Prints fields with tag "ipv4" or "ipv6"
  540. // as IP addresses.
  541. func printStruct(any dnsStruct) string {
  542. s := "{"
  543. i := 0
  544. any.Walk(func(val interface{}, name, tag string) bool {
  545. i++
  546. if i > 1 {
  547. s += ", "
  548. }
  549. s += name + "="
  550. switch tag {
  551. case "ipv4":
  552. i := *val.(*uint32)
  553. s += IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i)).String()
  554. case "ipv6":
  555. i := val.([]byte)
  556. s += IP(i).String()
  557. default:
  558. var i int64
  559. switch v := val.(type) {
  560. default:
  561. // can't really happen.
  562. s += "<unknown type>"
  563. return true
  564. case *string:
  565. s += *v
  566. return true
  567. case []byte:
  568. s += string(v)
  569. return true
  570. case *bool:
  571. if *v {
  572. s += "true"
  573. } else {
  574. s += "false"
  575. }
  576. return true
  577. case *int:
  578. i = int64(*v)
  579. case *uint:
  580. i = int64(*v)
  581. case *uint8:
  582. i = int64(*v)
  583. case *uint16:
  584. i = int64(*v)
  585. case *uint32:
  586. i = int64(*v)
  587. case *uint64:
  588. i = int64(*v)
  589. case *uintptr:
  590. i = int64(*v)
  591. }
  592. s += itoa(int(i))
  593. }
  594. return true
  595. })
  596. s += "}"
  597. return s
  598. }
  599. // Resource record packer.
  600. func packRR(rr dnsRR, msg []byte, off int) (off2 int, ok bool) {
  601. var off1 int
  602. // pack twice, once to find end of header
  603. // and again to find end of packet.
  604. // a bit inefficient but this doesn't need to be fast.
  605. // off1 is end of header
  606. // off2 is end of rr
  607. off1, ok = packStruct(rr.Header(), msg, off)
  608. off2, ok = packStruct(rr, msg, off)
  609. if !ok {
  610. return len(msg), false
  611. }
  612. // pack a third time; redo header with correct data length
  613. rr.Header().Rdlength = uint16(off2 - off1)
  614. packStruct(rr.Header(), msg, off)
  615. return off2, true
  616. }
  617. // Resource record unpacker.
  618. func unpackRR(msg []byte, off int) (rr dnsRR, off1 int, ok bool) {
  619. // unpack just the header, to find the rr type and length
  620. var h dnsRR_Header
  621. off0 := off
  622. if off, ok = unpackStruct(&h, msg, off); !ok {
  623. return nil, len(msg), false
  624. }
  625. end := off + int(h.Rdlength)
  626. // make an rr of that type and re-unpack.
  627. // again inefficient but doesn't need to be fast.
  628. mk, known := rr_mk[int(h.Rrtype)]
  629. if !known {
  630. return &h, end, true
  631. }
  632. rr = mk()
  633. off, ok = unpackStruct(rr, msg, off0)
  634. if off != end {
  635. return &h, end, true
  636. }
  637. return rr, off, ok
  638. }
  639. // Usable representation of a DNS packet.
  640. // A manually-unpacked version of (id, bits).
  641. // This is in its own struct for easy printing.
  642. type dnsMsgHdr struct {
  643. id uint16
  644. response bool
  645. opcode int
  646. authoritative bool
  647. truncated bool
  648. recursion_desired bool
  649. recursion_available bool
  650. rcode int
  651. }
  652. func (h *dnsMsgHdr) Walk(f func(v interface{}, name, tag string) bool) bool {
  653. return f(&h.id, "id", "") &&
  654. f(&h.response, "response", "") &&
  655. f(&h.opcode, "opcode", "") &&
  656. f(&h.authoritative, "authoritative", "") &&
  657. f(&h.truncated, "truncated", "") &&
  658. f(&h.recursion_desired, "recursion_desired", "") &&
  659. f(&h.recursion_available, "recursion_available", "") &&
  660. f(&h.rcode, "rcode", "")
  661. }
  662. type dnsMsg struct {
  663. dnsMsgHdr
  664. question []dnsQuestion
  665. answer []dnsRR
  666. ns []dnsRR
  667. extra []dnsRR
  668. }
  669. func (dns *dnsMsg) Pack() (msg []byte, ok bool) {
  670. var dh dnsHeader
  671. // Convert convenient dnsMsg into wire-like dnsHeader.
  672. dh.Id = dns.id
  673. dh.Bits = uint16(dns.opcode)<<11 | uint16(dns.rcode)
  674. if dns.recursion_available {
  675. dh.Bits |= _RA
  676. }
  677. if dns.recursion_desired {
  678. dh.Bits |= _RD
  679. }
  680. if dns.truncated {
  681. dh.Bits |= _TC
  682. }
  683. if dns.authoritative {
  684. dh.Bits |= _AA
  685. }
  686. if dns.response {
  687. dh.Bits |= _QR
  688. }
  689. // Prepare variable sized arrays.
  690. question := dns.question
  691. answer := dns.answer
  692. ns := dns.ns
  693. extra := dns.extra
  694. dh.Qdcount = uint16(len(question))
  695. dh.Ancount = uint16(len(answer))
  696. dh.Nscount = uint16(len(ns))
  697. dh.Arcount = uint16(len(extra))
  698. // Could work harder to calculate message size,
  699. // but this is far more than we need and not
  700. // big enough to hurt the allocator.
  701. msg = make([]byte, 2000)
  702. // Pack it in: header and then the pieces.
  703. off := 0
  704. off, ok = packStruct(&dh, msg, off)
  705. for i := 0; i < len(question); i++ {
  706. off, ok = packStruct(&question[i], msg, off)
  707. }
  708. for i := 0; i < len(answer); i++ {
  709. off, ok = packRR(answer[i], msg, off)
  710. }
  711. for i := 0; i < len(ns); i++ {
  712. off, ok = packRR(ns[i], msg, off)
  713. }
  714. for i := 0; i < len(extra); i++ {
  715. off, ok = packRR(extra[i], msg, off)
  716. }
  717. if !ok {
  718. return nil, false
  719. }
  720. return msg[0:off], true
  721. }
  722. func (dns *dnsMsg) Unpack(msg []byte) bool {
  723. // Header.
  724. var dh dnsHeader
  725. off := 0
  726. var ok bool
  727. if off, ok = unpackStruct(&dh, msg, off); !ok {
  728. return false
  729. }
  730. dns.id = dh.Id
  731. dns.response = (dh.Bits & _QR) != 0
  732. dns.opcode = int(dh.Bits>>11) & 0xF
  733. dns.authoritative = (dh.Bits & _AA) != 0
  734. dns.truncated = (dh.Bits & _TC) != 0
  735. dns.recursion_desired = (dh.Bits & _RD) != 0
  736. dns.recursion_available = (dh.Bits & _RA) != 0
  737. dns.rcode = int(dh.Bits & 0xF)
  738. // Arrays.
  739. dns.question = make([]dnsQuestion, dh.Qdcount)
  740. dns.answer = make([]dnsRR, 0, dh.Ancount)
  741. dns.ns = make([]dnsRR, 0, dh.Nscount)
  742. dns.extra = make([]dnsRR, 0, dh.Arcount)
  743. var rec dnsRR
  744. for i := 0; i < len(dns.question); i++ {
  745. off, ok = unpackStruct(&dns.question[i], msg, off)
  746. }
  747. for i := 0; i < int(dh.Ancount); i++ {
  748. rec, off, ok = unpackRR(msg, off)
  749. if !ok {
  750. return false
  751. }
  752. dns.answer = append(dns.answer, rec)
  753. }
  754. for i := 0; i < int(dh.Nscount); i++ {
  755. rec, off, ok = unpackRR(msg, off)
  756. if !ok {
  757. return false
  758. }
  759. dns.ns = append(dns.ns, rec)
  760. }
  761. for i := 0; i < int(dh.Arcount); i++ {
  762. rec, off, ok = unpackRR(msg, off)
  763. if !ok {
  764. return false
  765. }
  766. dns.extra = append(dns.extra, rec)
  767. }
  768. // if off != len(msg) {
  769. // println("extra bytes in dns packet", off, "<", len(msg));
  770. // }
  771. return true
  772. }
  773. func (dns *dnsMsg) String() string {
  774. s := "DNS: " + printStruct(&dns.dnsMsgHdr) + "\n"
  775. if len(dns.question) > 0 {
  776. s += "-- Questions\n"
  777. for i := 0; i < len(dns.question); i++ {
  778. s += printStruct(&dns.question[i]) + "\n"
  779. }
  780. }
  781. if len(dns.answer) > 0 {
  782. s += "-- Answers\n"
  783. for i := 0; i < len(dns.answer); i++ {
  784. s += printStruct(dns.answer[i]) + "\n"
  785. }
  786. }
  787. if len(dns.ns) > 0 {
  788. s += "-- Name servers\n"
  789. for i := 0; i < len(dns.ns); i++ {
  790. s += printStruct(dns.ns[i]) + "\n"
  791. }
  792. }
  793. if len(dns.extra) > 0 {
  794. s += "-- Extra\n"
  795. for i := 0; i < len(dns.extra); i++ {
  796. s += printStruct(dns.extra[i]) + "\n"
  797. }
  798. }
  799. return s
  800. }