edns.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. package dns
  2. import (
  3. "encoding/binary"
  4. "encoding/hex"
  5. "errors"
  6. "fmt"
  7. "net"
  8. "strconv"
  9. )
  10. // EDNS0 Option codes.
  11. const (
  12. EDNS0LLQ = 0x1 // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
  13. EDNS0UL = 0x2 // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
  14. EDNS0NSID = 0x3 // nsid (See RFC 5001)
  15. EDNS0DAU = 0x5 // DNSSEC Algorithm Understood
  16. EDNS0DHU = 0x6 // DS Hash Understood
  17. EDNS0N3U = 0x7 // NSEC3 Hash Understood
  18. EDNS0SUBNET = 0x8 // client-subnet (See RFC 7871)
  19. EDNS0EXPIRE = 0x9 // EDNS0 expire
  20. EDNS0COOKIE = 0xa // EDNS0 Cookie
  21. EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (See RFC 7828)
  22. EDNS0PADDING = 0xc // EDNS0 padding (See RFC 7830)
  23. EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (See RFC 6891)
  24. EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (See RFC 6891)
  25. _DO = 1 << 15 // DNSSEC OK
  26. )
  27. // OPT is the EDNS0 RR appended to messages to convey extra (meta) information.
  28. // See RFC 6891.
  29. type OPT struct {
  30. Hdr RR_Header
  31. Option []EDNS0 `dns:"opt"`
  32. }
  33. func (rr *OPT) String() string {
  34. s := "\n;; OPT PSEUDOSECTION:\n; EDNS: version " + strconv.Itoa(int(rr.Version())) + "; "
  35. if rr.Do() {
  36. s += "flags: do; "
  37. } else {
  38. s += "flags: ; "
  39. }
  40. s += "udp: " + strconv.Itoa(int(rr.UDPSize()))
  41. for _, o := range rr.Option {
  42. switch o.(type) {
  43. case *EDNS0_NSID:
  44. s += "\n; NSID: " + o.String()
  45. h, e := o.pack()
  46. var r string
  47. if e == nil {
  48. for _, c := range h {
  49. r += "(" + string(c) + ")"
  50. }
  51. s += " " + r
  52. }
  53. case *EDNS0_SUBNET:
  54. s += "\n; SUBNET: " + o.String()
  55. case *EDNS0_COOKIE:
  56. s += "\n; COOKIE: " + o.String()
  57. case *EDNS0_UL:
  58. s += "\n; UPDATE LEASE: " + o.String()
  59. case *EDNS0_LLQ:
  60. s += "\n; LONG LIVED QUERIES: " + o.String()
  61. case *EDNS0_DAU:
  62. s += "\n; DNSSEC ALGORITHM UNDERSTOOD: " + o.String()
  63. case *EDNS0_DHU:
  64. s += "\n; DS HASH UNDERSTOOD: " + o.String()
  65. case *EDNS0_N3U:
  66. s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
  67. case *EDNS0_LOCAL:
  68. s += "\n; LOCAL OPT: " + o.String()
  69. case *EDNS0_PADDING:
  70. s += "\n; PADDING: " + o.String()
  71. }
  72. }
  73. return s
  74. }
  75. func (rr *OPT) len(off int, compression map[string]struct{}) int {
  76. l := rr.Hdr.len(off, compression)
  77. for i := 0; i < len(rr.Option); i++ {
  78. l += 4 // Account for 2-byte option code and 2-byte option length.
  79. lo, _ := rr.Option[i].pack()
  80. l += len(lo)
  81. }
  82. return l
  83. }
  84. func (rr *OPT) parse(c *zlexer, origin, file string) *ParseError {
  85. panic("dns: internal error: parse should never be called on OPT")
  86. }
  87. func (r1 *OPT) isDuplicate(r2 RR) bool { return false }
  88. // return the old value -> delete SetVersion?
  89. // Version returns the EDNS version used. Only zero is defined.
  90. func (rr *OPT) Version() uint8 {
  91. return uint8(rr.Hdr.Ttl & 0x00FF0000 >> 16)
  92. }
  93. // SetVersion sets the version of EDNS. This is usually zero.
  94. func (rr *OPT) SetVersion(v uint8) {
  95. rr.Hdr.Ttl = rr.Hdr.Ttl&0xFF00FFFF | uint32(v)<<16
  96. }
  97. // ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
  98. func (rr *OPT) ExtendedRcode() int {
  99. return int(rr.Hdr.Ttl&0xFF000000>>24) << 4
  100. }
  101. // SetExtendedRcode sets the EDNS extended RCODE field.
  102. //
  103. // If the RCODE is not an extended RCODE, will reset the extended RCODE field to 0.
  104. func (rr *OPT) SetExtendedRcode(v uint16) {
  105. rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | uint32(v>>4)<<24
  106. }
  107. // UDPSize returns the UDP buffer size.
  108. func (rr *OPT) UDPSize() uint16 {
  109. return rr.Hdr.Class
  110. }
  111. // SetUDPSize sets the UDP buffer size.
  112. func (rr *OPT) SetUDPSize(size uint16) {
  113. rr.Hdr.Class = size
  114. }
  115. // Do returns the value of the DO (DNSSEC OK) bit.
  116. func (rr *OPT) Do() bool {
  117. return rr.Hdr.Ttl&_DO == _DO
  118. }
  119. // SetDo sets the DO (DNSSEC OK) bit.
  120. // If we pass an argument, set the DO bit to that value.
  121. // It is possible to pass 2 or more arguments. Any arguments after the 1st is silently ignored.
  122. func (rr *OPT) SetDo(do ...bool) {
  123. if len(do) == 1 {
  124. if do[0] {
  125. rr.Hdr.Ttl |= _DO
  126. } else {
  127. rr.Hdr.Ttl &^= _DO
  128. }
  129. } else {
  130. rr.Hdr.Ttl |= _DO
  131. }
  132. }
  133. // EDNS0 defines an EDNS0 Option. An OPT RR can have multiple options appended to it.
  134. type EDNS0 interface {
  135. // Option returns the option code for the option.
  136. Option() uint16
  137. // pack returns the bytes of the option data.
  138. pack() ([]byte, error)
  139. // unpack sets the data as found in the buffer. Is also sets
  140. // the length of the slice as the length of the option data.
  141. unpack([]byte) error
  142. // String returns the string representation of the option.
  143. String() string
  144. // copy returns a deep-copy of the option.
  145. copy() EDNS0
  146. }
  147. // EDNS0_NSID option is used to retrieve a nameserver
  148. // identifier. When sending a request Nsid must be set to the empty string
  149. // The identifier is an opaque string encoded as hex.
  150. // Basic use pattern for creating an nsid option:
  151. //
  152. // o := new(dns.OPT)
  153. // o.Hdr.Name = "."
  154. // o.Hdr.Rrtype = dns.TypeOPT
  155. // e := new(dns.EDNS0_NSID)
  156. // e.Code = dns.EDNS0NSID
  157. // e.Nsid = "AA"
  158. // o.Option = append(o.Option, e)
  159. type EDNS0_NSID struct {
  160. Code uint16 // Always EDNS0NSID
  161. Nsid string // This string needs to be hex encoded
  162. }
  163. func (e *EDNS0_NSID) pack() ([]byte, error) {
  164. h, err := hex.DecodeString(e.Nsid)
  165. if err != nil {
  166. return nil, err
  167. }
  168. return h, nil
  169. }
  170. // Option implements the EDNS0 interface.
  171. func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID } // Option returns the option code.
  172. func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
  173. func (e *EDNS0_NSID) String() string { return e.Nsid }
  174. func (e *EDNS0_NSID) copy() EDNS0 { return &EDNS0_NSID{e.Code, e.Nsid} }
  175. // EDNS0_SUBNET is the subnet option that is used to give the remote nameserver
  176. // an idea of where the client lives. See RFC 7871. It can then give back a different
  177. // answer depending on the location or network topology.
  178. // Basic use pattern for creating an subnet option:
  179. //
  180. // o := new(dns.OPT)
  181. // o.Hdr.Name = "."
  182. // o.Hdr.Rrtype = dns.TypeOPT
  183. // e := new(dns.EDNS0_SUBNET)
  184. // e.Code = dns.EDNS0SUBNET
  185. // e.Family = 1 // 1 for IPv4 source address, 2 for IPv6
  186. // e.SourceNetmask = 32 // 32 for IPV4, 128 for IPv6
  187. // e.SourceScope = 0
  188. // e.Address = net.ParseIP("127.0.0.1").To4() // for IPv4
  189. // // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6
  190. // o.Option = append(o.Option, e)
  191. //
  192. // This code will parse all the available bits when unpacking (up to optlen).
  193. // When packing it will apply SourceNetmask. If you need more advanced logic,
  194. // patches welcome and good luck.
  195. type EDNS0_SUBNET struct {
  196. Code uint16 // Always EDNS0SUBNET
  197. Family uint16 // 1 for IP, 2 for IP6
  198. SourceNetmask uint8
  199. SourceScope uint8
  200. Address net.IP
  201. }
  202. // Option implements the EDNS0 interface.
  203. func (e *EDNS0_SUBNET) Option() uint16 { return EDNS0SUBNET }
  204. func (e *EDNS0_SUBNET) pack() ([]byte, error) {
  205. b := make([]byte, 4)
  206. binary.BigEndian.PutUint16(b[0:], e.Family)
  207. b[2] = e.SourceNetmask
  208. b[3] = e.SourceScope
  209. switch e.Family {
  210. case 0:
  211. // "dig" sets AddressFamily to 0 if SourceNetmask is also 0
  212. // We might don't need to complain either
  213. if e.SourceNetmask != 0 {
  214. return nil, errors.New("dns: bad address family")
  215. }
  216. case 1:
  217. if e.SourceNetmask > net.IPv4len*8 {
  218. return nil, errors.New("dns: bad netmask")
  219. }
  220. if len(e.Address.To4()) != net.IPv4len {
  221. return nil, errors.New("dns: bad address")
  222. }
  223. ip := e.Address.To4().Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv4len*8))
  224. needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up
  225. b = append(b, ip[:needLength]...)
  226. case 2:
  227. if e.SourceNetmask > net.IPv6len*8 {
  228. return nil, errors.New("dns: bad netmask")
  229. }
  230. if len(e.Address) != net.IPv6len {
  231. return nil, errors.New("dns: bad address")
  232. }
  233. ip := e.Address.Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv6len*8))
  234. needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up
  235. b = append(b, ip[:needLength]...)
  236. default:
  237. return nil, errors.New("dns: bad address family")
  238. }
  239. return b, nil
  240. }
  241. func (e *EDNS0_SUBNET) unpack(b []byte) error {
  242. if len(b) < 4 {
  243. return ErrBuf
  244. }
  245. e.Family = binary.BigEndian.Uint16(b)
  246. e.SourceNetmask = b[2]
  247. e.SourceScope = b[3]
  248. switch e.Family {
  249. case 0:
  250. // "dig" sets AddressFamily to 0 if SourceNetmask is also 0
  251. // It's okay to accept such a packet
  252. if e.SourceNetmask != 0 {
  253. return errors.New("dns: bad address family")
  254. }
  255. e.Address = net.IPv4(0, 0, 0, 0)
  256. case 1:
  257. if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
  258. return errors.New("dns: bad netmask")
  259. }
  260. addr := make(net.IP, net.IPv4len)
  261. copy(addr, b[4:])
  262. e.Address = addr.To16()
  263. case 2:
  264. if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
  265. return errors.New("dns: bad netmask")
  266. }
  267. addr := make(net.IP, net.IPv6len)
  268. copy(addr, b[4:])
  269. e.Address = addr
  270. default:
  271. return errors.New("dns: bad address family")
  272. }
  273. return nil
  274. }
  275. func (e *EDNS0_SUBNET) String() (s string) {
  276. if e.Address == nil {
  277. s = "<nil>"
  278. } else if e.Address.To4() != nil {
  279. s = e.Address.String()
  280. } else {
  281. s = "[" + e.Address.String() + "]"
  282. }
  283. s += "/" + strconv.Itoa(int(e.SourceNetmask)) + "/" + strconv.Itoa(int(e.SourceScope))
  284. return
  285. }
  286. func (e *EDNS0_SUBNET) copy() EDNS0 {
  287. return &EDNS0_SUBNET{
  288. e.Code,
  289. e.Family,
  290. e.SourceNetmask,
  291. e.SourceScope,
  292. e.Address,
  293. }
  294. }
  295. // The EDNS0_COOKIE option is used to add a DNS Cookie to a message.
  296. //
  297. // o := new(dns.OPT)
  298. // o.Hdr.Name = "."
  299. // o.Hdr.Rrtype = dns.TypeOPT
  300. // e := new(dns.EDNS0_COOKIE)
  301. // e.Code = dns.EDNS0COOKIE
  302. // e.Cookie = "24a5ac.."
  303. // o.Option = append(o.Option, e)
  304. //
  305. // The Cookie field consists out of a client cookie (RFC 7873 Section 4), that is
  306. // always 8 bytes. It may then optionally be followed by the server cookie. The server
  307. // cookie is of variable length, 8 to a maximum of 32 bytes. In other words:
  308. //
  309. // cCookie := o.Cookie[:16]
  310. // sCookie := o.Cookie[16:]
  311. //
  312. // There is no guarantee that the Cookie string has a specific length.
  313. type EDNS0_COOKIE struct {
  314. Code uint16 // Always EDNS0COOKIE
  315. Cookie string // Hex-encoded cookie data
  316. }
  317. func (e *EDNS0_COOKIE) pack() ([]byte, error) {
  318. h, err := hex.DecodeString(e.Cookie)
  319. if err != nil {
  320. return nil, err
  321. }
  322. return h, nil
  323. }
  324. // Option implements the EDNS0 interface.
  325. func (e *EDNS0_COOKIE) Option() uint16 { return EDNS0COOKIE }
  326. func (e *EDNS0_COOKIE) unpack(b []byte) error { e.Cookie = hex.EncodeToString(b); return nil }
  327. func (e *EDNS0_COOKIE) String() string { return e.Cookie }
  328. func (e *EDNS0_COOKIE) copy() EDNS0 { return &EDNS0_COOKIE{e.Code, e.Cookie} }
  329. // The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set
  330. // an expiration on an update RR. This is helpful for clients that cannot clean
  331. // up after themselves. This is a draft RFC and more information can be found at
  332. // http://files.dns-sd.org/draft-sekar-dns-ul.txt
  333. //
  334. // o := new(dns.OPT)
  335. // o.Hdr.Name = "."
  336. // o.Hdr.Rrtype = dns.TypeOPT
  337. // e := new(dns.EDNS0_UL)
  338. // e.Code = dns.EDNS0UL
  339. // e.Lease = 120 // in seconds
  340. // o.Option = append(o.Option, e)
  341. type EDNS0_UL struct {
  342. Code uint16 // Always EDNS0UL
  343. Lease uint32
  344. }
  345. // Option implements the EDNS0 interface.
  346. func (e *EDNS0_UL) Option() uint16 { return EDNS0UL }
  347. func (e *EDNS0_UL) String() string { return strconv.FormatUint(uint64(e.Lease), 10) }
  348. func (e *EDNS0_UL) copy() EDNS0 { return &EDNS0_UL{e.Code, e.Lease} }
  349. // Copied: http://golang.org/src/pkg/net/dnsmsg.go
  350. func (e *EDNS0_UL) pack() ([]byte, error) {
  351. b := make([]byte, 4)
  352. binary.BigEndian.PutUint32(b, e.Lease)
  353. return b, nil
  354. }
  355. func (e *EDNS0_UL) unpack(b []byte) error {
  356. if len(b) < 4 {
  357. return ErrBuf
  358. }
  359. e.Lease = binary.BigEndian.Uint32(b)
  360. return nil
  361. }
  362. // EDNS0_LLQ stands for Long Lived Queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
  363. // Implemented for completeness, as the EDNS0 type code is assigned.
  364. type EDNS0_LLQ struct {
  365. Code uint16 // Always EDNS0LLQ
  366. Version uint16
  367. Opcode uint16
  368. Error uint16
  369. Id uint64
  370. LeaseLife uint32
  371. }
  372. // Option implements the EDNS0 interface.
  373. func (e *EDNS0_LLQ) Option() uint16 { return EDNS0LLQ }
  374. func (e *EDNS0_LLQ) pack() ([]byte, error) {
  375. b := make([]byte, 18)
  376. binary.BigEndian.PutUint16(b[0:], e.Version)
  377. binary.BigEndian.PutUint16(b[2:], e.Opcode)
  378. binary.BigEndian.PutUint16(b[4:], e.Error)
  379. binary.BigEndian.PutUint64(b[6:], e.Id)
  380. binary.BigEndian.PutUint32(b[14:], e.LeaseLife)
  381. return b, nil
  382. }
  383. func (e *EDNS0_LLQ) unpack(b []byte) error {
  384. if len(b) < 18 {
  385. return ErrBuf
  386. }
  387. e.Version = binary.BigEndian.Uint16(b[0:])
  388. e.Opcode = binary.BigEndian.Uint16(b[2:])
  389. e.Error = binary.BigEndian.Uint16(b[4:])
  390. e.Id = binary.BigEndian.Uint64(b[6:])
  391. e.LeaseLife = binary.BigEndian.Uint32(b[14:])
  392. return nil
  393. }
  394. func (e *EDNS0_LLQ) String() string {
  395. s := strconv.FormatUint(uint64(e.Version), 10) + " " + strconv.FormatUint(uint64(e.Opcode), 10) +
  396. " " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(e.Id, 10) +
  397. " " + strconv.FormatUint(uint64(e.LeaseLife), 10)
  398. return s
  399. }
  400. func (e *EDNS0_LLQ) copy() EDNS0 {
  401. return &EDNS0_LLQ{e.Code, e.Version, e.Opcode, e.Error, e.Id, e.LeaseLife}
  402. }
  403. // EDNS0_DUA implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
  404. type EDNS0_DAU struct {
  405. Code uint16 // Always EDNS0DAU
  406. AlgCode []uint8
  407. }
  408. // Option implements the EDNS0 interface.
  409. func (e *EDNS0_DAU) Option() uint16 { return EDNS0DAU }
  410. func (e *EDNS0_DAU) pack() ([]byte, error) { return e.AlgCode, nil }
  411. func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = b; return nil }
  412. func (e *EDNS0_DAU) String() string {
  413. s := ""
  414. for i := 0; i < len(e.AlgCode); i++ {
  415. if a, ok := AlgorithmToString[e.AlgCode[i]]; ok {
  416. s += " " + a
  417. } else {
  418. s += " " + strconv.Itoa(int(e.AlgCode[i]))
  419. }
  420. }
  421. return s
  422. }
  423. func (e *EDNS0_DAU) copy() EDNS0 { return &EDNS0_DAU{e.Code, e.AlgCode} }
  424. // EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
  425. type EDNS0_DHU struct {
  426. Code uint16 // Always EDNS0DHU
  427. AlgCode []uint8
  428. }
  429. // Option implements the EDNS0 interface.
  430. func (e *EDNS0_DHU) Option() uint16 { return EDNS0DHU }
  431. func (e *EDNS0_DHU) pack() ([]byte, error) { return e.AlgCode, nil }
  432. func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = b; return nil }
  433. func (e *EDNS0_DHU) String() string {
  434. s := ""
  435. for i := 0; i < len(e.AlgCode); i++ {
  436. if a, ok := HashToString[e.AlgCode[i]]; ok {
  437. s += " " + a
  438. } else {
  439. s += " " + strconv.Itoa(int(e.AlgCode[i]))
  440. }
  441. }
  442. return s
  443. }
  444. func (e *EDNS0_DHU) copy() EDNS0 { return &EDNS0_DHU{e.Code, e.AlgCode} }
  445. // EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
  446. type EDNS0_N3U struct {
  447. Code uint16 // Always EDNS0N3U
  448. AlgCode []uint8
  449. }
  450. // Option implements the EDNS0 interface.
  451. func (e *EDNS0_N3U) Option() uint16 { return EDNS0N3U }
  452. func (e *EDNS0_N3U) pack() ([]byte, error) { return e.AlgCode, nil }
  453. func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil }
  454. func (e *EDNS0_N3U) String() string {
  455. // Re-use the hash map
  456. s := ""
  457. for i := 0; i < len(e.AlgCode); i++ {
  458. if a, ok := HashToString[e.AlgCode[i]]; ok {
  459. s += " " + a
  460. } else {
  461. s += " " + strconv.Itoa(int(e.AlgCode[i]))
  462. }
  463. }
  464. return s
  465. }
  466. func (e *EDNS0_N3U) copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} }
  467. // EDNS0_EXPIRE implementes the EDNS0 option as described in RFC 7314.
  468. type EDNS0_EXPIRE struct {
  469. Code uint16 // Always EDNS0EXPIRE
  470. Expire uint32
  471. }
  472. // Option implements the EDNS0 interface.
  473. func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
  474. func (e *EDNS0_EXPIRE) String() string { return strconv.FormatUint(uint64(e.Expire), 10) }
  475. func (e *EDNS0_EXPIRE) copy() EDNS0 { return &EDNS0_EXPIRE{e.Code, e.Expire} }
  476. func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
  477. b := make([]byte, 4)
  478. binary.BigEndian.PutUint32(b, e.Expire)
  479. return b, nil
  480. }
  481. func (e *EDNS0_EXPIRE) unpack(b []byte) error {
  482. if len(b) < 4 {
  483. return ErrBuf
  484. }
  485. e.Expire = binary.BigEndian.Uint32(b)
  486. return nil
  487. }
  488. // The EDNS0_LOCAL option is used for local/experimental purposes. The option
  489. // code is recommended to be within the range [EDNS0LOCALSTART, EDNS0LOCALEND]
  490. // (RFC6891), although any unassigned code can actually be used. The content of
  491. // the option is made available in Data, unaltered.
  492. // Basic use pattern for creating a local option:
  493. //
  494. // o := new(dns.OPT)
  495. // o.Hdr.Name = "."
  496. // o.Hdr.Rrtype = dns.TypeOPT
  497. // e := new(dns.EDNS0_LOCAL)
  498. // e.Code = dns.EDNS0LOCALSTART
  499. // e.Data = []byte{72, 82, 74}
  500. // o.Option = append(o.Option, e)
  501. type EDNS0_LOCAL struct {
  502. Code uint16
  503. Data []byte
  504. }
  505. // Option implements the EDNS0 interface.
  506. func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
  507. func (e *EDNS0_LOCAL) String() string {
  508. return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
  509. }
  510. func (e *EDNS0_LOCAL) copy() EDNS0 {
  511. b := make([]byte, len(e.Data))
  512. copy(b, e.Data)
  513. return &EDNS0_LOCAL{e.Code, b}
  514. }
  515. func (e *EDNS0_LOCAL) pack() ([]byte, error) {
  516. b := make([]byte, len(e.Data))
  517. copied := copy(b, e.Data)
  518. if copied != len(e.Data) {
  519. return nil, ErrBuf
  520. }
  521. return b, nil
  522. }
  523. func (e *EDNS0_LOCAL) unpack(b []byte) error {
  524. e.Data = make([]byte, len(b))
  525. copied := copy(e.Data, b)
  526. if copied != len(b) {
  527. return ErrBuf
  528. }
  529. return nil
  530. }
  531. // EDNS0_TCP_KEEPALIVE is an EDNS0 option that instructs the server to keep
  532. // the TCP connection alive. See RFC 7828.
  533. type EDNS0_TCP_KEEPALIVE struct {
  534. Code uint16 // Always EDNSTCPKEEPALIVE
  535. Length uint16 // the value 0 if the TIMEOUT is omitted, the value 2 if it is present;
  536. Timeout uint16 // an idle timeout value for the TCP connection, specified in units of 100 milliseconds, encoded in network byte order.
  537. }
  538. // Option implements the EDNS0 interface.
  539. func (e *EDNS0_TCP_KEEPALIVE) Option() uint16 { return EDNS0TCPKEEPALIVE }
  540. func (e *EDNS0_TCP_KEEPALIVE) pack() ([]byte, error) {
  541. if e.Timeout != 0 && e.Length != 2 {
  542. return nil, errors.New("dns: timeout specified but length is not 2")
  543. }
  544. if e.Timeout == 0 && e.Length != 0 {
  545. return nil, errors.New("dns: timeout not specified but length is not 0")
  546. }
  547. b := make([]byte, 4+e.Length)
  548. binary.BigEndian.PutUint16(b[0:], e.Code)
  549. binary.BigEndian.PutUint16(b[2:], e.Length)
  550. if e.Length == 2 {
  551. binary.BigEndian.PutUint16(b[4:], e.Timeout)
  552. }
  553. return b, nil
  554. }
  555. func (e *EDNS0_TCP_KEEPALIVE) unpack(b []byte) error {
  556. if len(b) < 4 {
  557. return ErrBuf
  558. }
  559. e.Length = binary.BigEndian.Uint16(b[2:4])
  560. if e.Length != 0 && e.Length != 2 {
  561. return errors.New("dns: length mismatch, want 0/2 but got " + strconv.FormatUint(uint64(e.Length), 10))
  562. }
  563. if e.Length == 2 {
  564. if len(b) < 6 {
  565. return ErrBuf
  566. }
  567. e.Timeout = binary.BigEndian.Uint16(b[4:6])
  568. }
  569. return nil
  570. }
  571. func (e *EDNS0_TCP_KEEPALIVE) String() (s string) {
  572. s = "use tcp keep-alive"
  573. if e.Length == 0 {
  574. s += ", timeout omitted"
  575. } else {
  576. s += fmt.Sprintf(", timeout %dms", e.Timeout*100)
  577. }
  578. return
  579. }
  580. func (e *EDNS0_TCP_KEEPALIVE) copy() EDNS0 { return &EDNS0_TCP_KEEPALIVE{e.Code, e.Length, e.Timeout} }
  581. // EDNS0_PADDING option is used to add padding to a request/response. The default
  582. // value of padding SHOULD be 0x0 but other values MAY be used, for instance if
  583. // compression is applied before encryption which may break signatures.
  584. type EDNS0_PADDING struct {
  585. Padding []byte
  586. }
  587. // Option implements the EDNS0 interface.
  588. func (e *EDNS0_PADDING) Option() uint16 { return EDNS0PADDING }
  589. func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil }
  590. func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = b; return nil }
  591. func (e *EDNS0_PADDING) String() string { return fmt.Sprintf("%0X", e.Padding) }
  592. func (e *EDNS0_PADDING) copy() EDNS0 {
  593. b := make([]byte, len(e.Padding))
  594. copy(b, e.Padding)
  595. return &EDNS0_PADDING{b}
  596. }