edns.go raw
1 package dns
2
3 import (
4 "encoding/binary"
5 "encoding/hex"
6 "errors"
7 "fmt"
8 "net"
9 "strconv"
10 )
11
12 // EDNS0 Option codes.
13 const (
14 EDNS0LLQ = 0x1 // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
15 EDNS0UL = 0x2 // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
16 EDNS0NSID = 0x3 // nsid (See RFC 5001)
17 EDNS0ESU = 0x4 // ENUM Source-URI draft: https://datatracker.ietf.org/doc/html/draft-kaplan-enum-source-uri-00
18 EDNS0DAU = 0x5 // DNSSEC Algorithm Understood
19 EDNS0DHU = 0x6 // DS Hash Understood
20 EDNS0N3U = 0x7 // NSEC3 Hash Understood
21 EDNS0SUBNET = 0x8 // client-subnet (See RFC 7871)
22 EDNS0EXPIRE = 0x9 // EDNS0 expire
23 EDNS0COOKIE = 0xa // EDNS0 Cookie
24 EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (See RFC 7828)
25 EDNS0PADDING = 0xc // EDNS0 padding (See RFC 7830)
26 EDNS0EDE = 0xf // EDNS0 extended DNS errors (See RFC 8914)
27 EDNS0REPORTING = 0x12 // EDNS0 reporting (See RFC 9567)
28 EDNS0ZONEVERSION = 0x13 // EDNS0 Zone Version (See RFC 9660)
29 EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (See RFC 6891)
30 EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (See RFC 6891)
31 _DO = 1 << 15 // DNSSEC OK
32 _CO = 1 << 14 // Compact Answers OK
33 )
34
35 // makeDataOpt is used to unpack the EDNS0 option(s) from a message.
36 func makeDataOpt(code uint16) EDNS0 {
37 // All the EDNS0.* constants above need to be in this switch.
38 switch code {
39 case EDNS0LLQ:
40 return new(EDNS0_LLQ)
41 case EDNS0UL:
42 return new(EDNS0_UL)
43 case EDNS0NSID:
44 return new(EDNS0_NSID)
45 case EDNS0DAU:
46 return new(EDNS0_DAU)
47 case EDNS0DHU:
48 return new(EDNS0_DHU)
49 case EDNS0N3U:
50 return new(EDNS0_N3U)
51 case EDNS0SUBNET:
52 return new(EDNS0_SUBNET)
53 case EDNS0EXPIRE:
54 return new(EDNS0_EXPIRE)
55 case EDNS0COOKIE:
56 return new(EDNS0_COOKIE)
57 case EDNS0TCPKEEPALIVE:
58 return new(EDNS0_TCP_KEEPALIVE)
59 case EDNS0PADDING:
60 return new(EDNS0_PADDING)
61 case EDNS0EDE:
62 return new(EDNS0_EDE)
63 case EDNS0ESU:
64 return new(EDNS0_ESU)
65 case EDNS0REPORTING:
66 return new(EDNS0_REPORTING)
67 case EDNS0ZONEVERSION:
68 return new(EDNS0_ZONEVERSION)
69 default:
70 e := new(EDNS0_LOCAL)
71 e.Code = code
72 return e
73 }
74 }
75
76 // OPT is the EDNS0 RR appended to messages to convey extra (meta) information. See RFC 6891.
77 type OPT struct {
78 Hdr RR_Header
79 Option []EDNS0 `dns:"opt"`
80 }
81
82 func (rr *OPT) String() string {
83 s := "\n;; OPT PSEUDOSECTION:\n; EDNS: version " + strconv.Itoa(int(rr.Version())) + "; "
84 s += "flags:"
85 if rr.Do() {
86 s += " do"
87 }
88 if rr.Co() {
89 s += " co"
90 }
91 s += "; "
92 if z := rr.Z(); z != 0 {
93 s += fmt.Sprintf("MBZ: 0x%04x, ", z)
94 }
95 s += "udp: " + strconv.Itoa(int(rr.UDPSize()))
96
97 for _, o := range rr.Option {
98 switch o.(type) {
99 case *EDNS0_NSID:
100 s += "\n; NSID: " + o.String()
101 h, e := o.pack()
102 var r string
103 if e == nil {
104 for _, c := range h {
105 r += "(" + string(c) + ")"
106 }
107 s += " " + r
108 }
109 case *EDNS0_SUBNET:
110 s += "\n; SUBNET: " + o.String()
111 case *EDNS0_COOKIE:
112 s += "\n; COOKIE: " + o.String()
113 case *EDNS0_EXPIRE:
114 s += "\n; EXPIRE: " + o.String()
115 case *EDNS0_TCP_KEEPALIVE:
116 s += "\n; KEEPALIVE: " + o.String()
117 case *EDNS0_UL:
118 s += "\n; UPDATE LEASE: " + o.String()
119 case *EDNS0_LLQ:
120 s += "\n; LONG LIVED QUERIES: " + o.String()
121 case *EDNS0_DAU:
122 s += "\n; DNSSEC ALGORITHM UNDERSTOOD: " + o.String()
123 case *EDNS0_DHU:
124 s += "\n; DS HASH UNDERSTOOD: " + o.String()
125 case *EDNS0_N3U:
126 s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
127 case *EDNS0_LOCAL:
128 s += "\n; LOCAL OPT: " + o.String()
129 case *EDNS0_PADDING:
130 s += "\n; PADDING: " + o.String()
131 case *EDNS0_EDE:
132 s += "\n; EDE: " + o.String()
133 case *EDNS0_ESU:
134 s += "\n; ESU: " + o.String()
135 case *EDNS0_REPORTING:
136 s += "\n; REPORT-CHANNEL: " + o.String()
137 case *EDNS0_ZONEVERSION:
138 s += "\n; ZONEVERSION: " + o.String()
139 }
140 }
141 return s
142 }
143
144 func (rr *OPT) len(off int, compression map[string]struct{}) int {
145 l := rr.Hdr.len(off, compression)
146 for _, o := range rr.Option {
147 l += 4 // Account for 2-byte option code and 2-byte option length.
148 lo, _ := o.pack()
149 l += len(lo)
150 }
151 return l
152 }
153
154 func (*OPT) parse(c *zlexer, origin string) *ParseError {
155 return &ParseError{err: "OPT records do not have a presentation format"}
156 }
157
158 func (rr *OPT) isDuplicate(r2 RR) bool { return false }
159
160 // Version returns the EDNS version used. Only zero is defined.
161 func (rr *OPT) Version() uint8 {
162 return uint8(rr.Hdr.Ttl & 0x00FF0000 >> 16)
163 }
164
165 // SetVersion sets the version of EDNS. This is usually zero.
166 func (rr *OPT) SetVersion(v uint8) {
167 rr.Hdr.Ttl = rr.Hdr.Ttl&0xFF00FFFF | uint32(v)<<16
168 }
169
170 // ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
171 func (rr *OPT) ExtendedRcode() int {
172 return int(rr.Hdr.Ttl&0xFF000000>>24) << 4
173 }
174
175 // SetExtendedRcode sets the EDNS extended RCODE field.
176 //
177 // If the RCODE is not an extended RCODE, will reset the extended RCODE field to 0.
178 func (rr *OPT) SetExtendedRcode(v uint16) {
179 rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | uint32(v>>4)<<24
180 }
181
182 // UDPSize returns the UDP buffer size.
183 func (rr *OPT) UDPSize() uint16 {
184 return rr.Hdr.Class
185 }
186
187 // SetUDPSize sets the UDP buffer size.
188 func (rr *OPT) SetUDPSize(size uint16) {
189 rr.Hdr.Class = size
190 }
191
192 // Do returns the value of the DO (DNSSEC OK) bit.
193 func (rr *OPT) Do() bool {
194 return rr.Hdr.Ttl&_DO == _DO
195 }
196
197 // SetDo sets the DO (DNSSEC OK) bit.
198 // If we pass an argument, set the DO bit to that value.
199 // It is possible to pass 2 or more arguments, but they will be ignored.
200 func (rr *OPT) SetDo(do ...bool) {
201 if len(do) == 1 {
202 if do[0] {
203 rr.Hdr.Ttl |= _DO
204 } else {
205 rr.Hdr.Ttl &^= _DO
206 }
207 } else {
208 rr.Hdr.Ttl |= _DO
209 }
210 }
211
212 // Co returns the value of the CO (Compact Answers OK) bit.
213 func (rr *OPT) Co() bool {
214 return rr.Hdr.Ttl&_CO == _CO
215 }
216
217 // SetCo sets the CO (Compact Answers OK) bit.
218 // If we pass an argument, set the CO bit to that value.
219 // It is possible to pass 2 or more arguments, but they will be ignored.
220 func (rr *OPT) SetCo(co ...bool) {
221 if len(co) == 1 {
222 if co[0] {
223 rr.Hdr.Ttl |= _CO
224 } else {
225 rr.Hdr.Ttl &^= _CO
226 }
227 } else {
228 rr.Hdr.Ttl |= _CO
229 }
230 }
231
232 // Z returns the Z part of the OPT RR as a uint16 with only the 14 least significant bits used.
233 func (rr *OPT) Z() uint16 {
234 return uint16(rr.Hdr.Ttl & 0x3FFF)
235 }
236
237 // SetZ sets the Z part of the OPT RR, note only the 14 least significant bits of z are used.
238 func (rr *OPT) SetZ(z uint16) {
239 rr.Hdr.Ttl = rr.Hdr.Ttl&^0x3FFF | uint32(z&0x3FFF)
240 }
241
242 // EDNS0 defines an EDNS0 Option. An OPT RR can have multiple options appended to it.
243 type EDNS0 interface {
244 // Option returns the option code for the option.
245 Option() uint16
246 // pack returns the bytes of the option data.
247 pack() ([]byte, error)
248 // unpack sets the data as found in the buffer. Is also sets
249 // the length of the slice as the length of the option data.
250 unpack([]byte) error
251 // String returns the string representation of the option.
252 String() string
253 // copy returns a deep-copy of the option.
254 copy() EDNS0
255 }
256
257 // EDNS0_NSID option is used to retrieve a nameserver
258 // identifier. When sending a request Nsid must be set to the empty string
259 // The identifier is an opaque string encoded as hex.
260 // Basic use pattern for creating an nsid option:
261 //
262 // o := new(dns.OPT)
263 // o.Hdr.Name = "."
264 // o.Hdr.Rrtype = dns.TypeOPT
265 // e := new(dns.EDNS0_NSID)
266 // e.Code = dns.EDNS0NSID
267 // e.Nsid = "AA"
268 // o.Option = append(o.Option, e)
269 type EDNS0_NSID struct {
270 Code uint16 // always EDNS0NSID
271 Nsid string // string needs to be hex encoded
272 }
273
274 func (e *EDNS0_NSID) pack() ([]byte, error) {
275 h, err := hex.DecodeString(e.Nsid)
276 if err != nil {
277 return nil, err
278 }
279 return h, nil
280 }
281
282 // Option implements the EDNS0 interface.
283 func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID } // Option returns the option code.
284 func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
285 func (e *EDNS0_NSID) String() string { return e.Nsid }
286 func (e *EDNS0_NSID) copy() EDNS0 { return &EDNS0_NSID{e.Code, e.Nsid} }
287
288 // EDNS0_SUBNET is the subnet option that is used to give the remote nameserver
289 // an idea of where the client lives. See RFC 7871. It can then give back a different
290 // answer depending on the location or network topology.
291 // Basic use pattern for creating an subnet option:
292 //
293 // o := new(dns.OPT)
294 // o.Hdr.Name = "."
295 // o.Hdr.Rrtype = dns.TypeOPT
296 // e := new(dns.EDNS0_SUBNET)
297 // e.Code = dns.EDNS0SUBNET // by default this is filled in through unpacking OPT packets (unpackDataOpt)
298 // e.Family = 1 // 1 for IPv4 source address, 2 for IPv6
299 // e.SourceNetmask = 32 // 32 for IPV4, 128 for IPv6
300 // e.SourceScope = 0
301 // e.Address = net.ParseIP("127.0.0.1").To4() // for IPv4
302 // // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6
303 // o.Option = append(o.Option, e)
304 //
305 // This code will parse all the available bits when unpacking (up to optlen).
306 // When packing it will apply SourceNetmask. If you need more advanced logic,
307 // patches welcome and good luck.
308 type EDNS0_SUBNET struct {
309 Code uint16 // always EDNS0SUBNET
310 Family uint16 // 1 for IP, 2 for IP6
311 SourceNetmask uint8
312 SourceScope uint8
313 Address net.IP
314 }
315
316 // Option implements the EDNS0 interface.
317 func (e *EDNS0_SUBNET) Option() uint16 { return EDNS0SUBNET }
318
319 func (e *EDNS0_SUBNET) pack() ([]byte, error) {
320 switch e.Family {
321 case 0:
322 // "dig" sets AddressFamily to 0 if SourceNetmask is also 0
323 // We might don't need to complain either
324 if e.SourceNetmask != 0 {
325 return nil, errors.New("bad address family")
326 }
327 b := make([]byte, 4)
328 b[3] = e.SourceScope
329 return b, nil
330 case 1:
331 if e.SourceNetmask > net.IPv4len*8 {
332 return nil, errors.New("bad netmask")
333 }
334 ip4 := e.Address.To4()
335 if len(ip4) != net.IPv4len {
336 return nil, errors.New("bad address")
337 }
338 needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up
339 b := make([]byte, 4+needLength)
340 binary.BigEndian.PutUint16(b[0:], e.Family)
341 b[2] = e.SourceNetmask
342 b[3] = e.SourceScope
343 if needLength > 0 {
344 ip := ip4.Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv4len*8))
345 copy(b[4:], ip[:needLength])
346 }
347 return b, nil
348 case 2:
349 if e.SourceNetmask > net.IPv6len*8 {
350 return nil, errors.New("bad netmask")
351 }
352 if len(e.Address) != net.IPv6len {
353 return nil, errors.New("bad address")
354 }
355 needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up
356 b := make([]byte, 4+needLength)
357 binary.BigEndian.PutUint16(b[0:], e.Family)
358 b[2] = e.SourceNetmask
359 b[3] = e.SourceScope
360 if needLength > 0 {
361 ip := e.Address.Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv6len*8))
362 copy(b[4:], ip[:needLength])
363 }
364 return b, nil
365 default:
366 return nil, errors.New("bad address family")
367 }
368 }
369
370 func (e *EDNS0_SUBNET) unpack(b []byte) error {
371 if len(b) < 4 {
372 return ErrBuf
373 }
374 e.Family = binary.BigEndian.Uint16(b)
375 e.SourceNetmask = b[2]
376 e.SourceScope = b[3]
377 switch e.Family {
378 case 0:
379 // "dig" sets AddressFamily to 0 if SourceNetmask is also 0
380 // It's okay to accept such a packet
381 if e.SourceNetmask != 0 {
382 return errors.New("bad address family")
383 }
384 e.Address = net.IPv4(0, 0, 0, 0)
385 case 1:
386 if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
387 return errors.New("bad netmask")
388 }
389 addr := make(net.IP, net.IPv4len)
390 copy(addr, b[4:])
391 e.Address = addr.To16()
392 case 2:
393 if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
394 return errors.New("bad netmask")
395 }
396 addr := make(net.IP, net.IPv6len)
397 copy(addr, b[4:])
398 e.Address = addr
399 default:
400 return errors.New("bad address family")
401 }
402 return nil
403 }
404
405 func (e *EDNS0_SUBNET) String() (s string) {
406 if e.Address == nil {
407 s = "<nil>"
408 } else if e.Address.To4() != nil {
409 s = e.Address.String()
410 } else {
411 s = "[" + e.Address.String() + "]"
412 }
413 s += "/" + strconv.Itoa(int(e.SourceNetmask)) + "/" + strconv.Itoa(int(e.SourceScope))
414 return
415 }
416
417 func (e *EDNS0_SUBNET) copy() EDNS0 {
418 return &EDNS0_SUBNET{
419 e.Code,
420 e.Family,
421 e.SourceNetmask,
422 e.SourceScope,
423 e.Address,
424 }
425 }
426
427 // The EDNS0_COOKIE option is used to add a DNS Cookie to a message.
428 //
429 // o := new(dns.OPT)
430 // o.Hdr.Name = "."
431 // o.Hdr.Rrtype = dns.TypeOPT
432 // e := new(dns.EDNS0_COOKIE)
433 // e.Code = dns.EDNS0COOKIE
434 // e.Cookie = "24a5ac.."
435 // o.Option = append(o.Option, e)
436 //
437 // The Cookie field consists out of a client cookie (RFC 7873 Section 4), that is
438 // always 8 bytes. It may then optionally be followed by the server cookie. The server
439 // cookie is of variable length, 8 to a maximum of 32 bytes. In other words:
440 //
441 // cCookie := o.Cookie[:16]
442 // sCookie := o.Cookie[16:]
443 //
444 // There is no guarantee that the Cookie string has a specific length.
445 type EDNS0_COOKIE struct {
446 Code uint16 // always EDNS0COOKIE
447 Cookie string // hex encoded cookie data
448 }
449
450 func (e *EDNS0_COOKIE) pack() ([]byte, error) {
451 h, err := hex.DecodeString(e.Cookie)
452 if err != nil {
453 return nil, err
454 }
455 return h, nil
456 }
457
458 // Option implements the EDNS0 interface.
459 func (e *EDNS0_COOKIE) Option() uint16 { return EDNS0COOKIE }
460 func (e *EDNS0_COOKIE) unpack(b []byte) error { e.Cookie = hex.EncodeToString(b); return nil }
461 func (e *EDNS0_COOKIE) String() string { return e.Cookie }
462 func (e *EDNS0_COOKIE) copy() EDNS0 { return &EDNS0_COOKIE{e.Code, e.Cookie} }
463
464 // The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set
465 // an expiration on an update RR. This is helpful for clients that cannot clean
466 // up after themselves. This is a draft RFC and more information can be found at
467 // https://tools.ietf.org/html/draft-sekar-dns-ul-02
468 //
469 // o := new(dns.OPT)
470 // o.Hdr.Name = "."
471 // o.Hdr.Rrtype = dns.TypeOPT
472 // e := new(dns.EDNS0_UL)
473 // e.Code = dns.EDNS0UL
474 // e.Lease = 120 // in seconds
475 // o.Option = append(o.Option, e)
476 type EDNS0_UL struct {
477 Code uint16 // always EDNS0UL
478 Lease uint32
479 KeyLease uint32
480 }
481
482 // Option implements the EDNS0 interface.
483 func (e *EDNS0_UL) Option() uint16 { return EDNS0UL }
484 func (e *EDNS0_UL) String() string { return fmt.Sprintf("%d %d", e.Lease, e.KeyLease) }
485 func (e *EDNS0_UL) copy() EDNS0 { return &EDNS0_UL{e.Code, e.Lease, e.KeyLease} }
486
487 // Copied: http://golang.org/src/pkg/net/dnsmsg.go
488 func (e *EDNS0_UL) pack() ([]byte, error) {
489 var b []byte
490 if e.KeyLease == 0 {
491 b = make([]byte, 4)
492 } else {
493 b = make([]byte, 8)
494 binary.BigEndian.PutUint32(b[4:], e.KeyLease)
495 }
496 binary.BigEndian.PutUint32(b, e.Lease)
497 return b, nil
498 }
499
500 func (e *EDNS0_UL) unpack(b []byte) error {
501 switch len(b) {
502 case 4:
503 e.KeyLease = 0
504 case 8:
505 e.KeyLease = binary.BigEndian.Uint32(b[4:])
506 default:
507 return ErrBuf
508 }
509 e.Lease = binary.BigEndian.Uint32(b)
510 return nil
511 }
512
513 // EDNS0_LLQ stands for Long Lived Queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
514 // Implemented for completeness, as the EDNS0 type code is assigned.
515 type EDNS0_LLQ struct {
516 Code uint16 // always EDNS0LLQ
517 Version uint16
518 Opcode uint16
519 Error uint16
520 Id uint64
521 LeaseLife uint32
522 }
523
524 // Option implements the EDNS0 interface.
525 func (e *EDNS0_LLQ) Option() uint16 { return EDNS0LLQ }
526
527 func (e *EDNS0_LLQ) pack() ([]byte, error) {
528 b := make([]byte, 18)
529 binary.BigEndian.PutUint16(b[0:], e.Version)
530 binary.BigEndian.PutUint16(b[2:], e.Opcode)
531 binary.BigEndian.PutUint16(b[4:], e.Error)
532 binary.BigEndian.PutUint64(b[6:], e.Id)
533 binary.BigEndian.PutUint32(b[14:], e.LeaseLife)
534 return b, nil
535 }
536
537 func (e *EDNS0_LLQ) unpack(b []byte) error {
538 if len(b) < 18 {
539 return ErrBuf
540 }
541 e.Version = binary.BigEndian.Uint16(b[0:])
542 e.Opcode = binary.BigEndian.Uint16(b[2:])
543 e.Error = binary.BigEndian.Uint16(b[4:])
544 e.Id = binary.BigEndian.Uint64(b[6:])
545 e.LeaseLife = binary.BigEndian.Uint32(b[14:])
546 return nil
547 }
548
549 func (e *EDNS0_LLQ) String() string {
550 s := strconv.FormatUint(uint64(e.Version), 10) + " " + strconv.FormatUint(uint64(e.Opcode), 10) +
551 " " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(e.Id, 10) +
552 " " + strconv.FormatUint(uint64(e.LeaseLife), 10)
553 return s
554 }
555
556 func (e *EDNS0_LLQ) copy() EDNS0 {
557 return &EDNS0_LLQ{e.Code, e.Version, e.Opcode, e.Error, e.Id, e.LeaseLife}
558 }
559
560 // EDNS0_DAU implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
561 type EDNS0_DAU struct {
562 Code uint16 // always EDNS0DAU
563 AlgCode []uint8
564 }
565
566 // Option implements the EDNS0 interface.
567 func (e *EDNS0_DAU) Option() uint16 { return EDNS0DAU }
568 func (e *EDNS0_DAU) pack() ([]byte, error) { return cloneSlice(e.AlgCode), nil }
569 func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = cloneSlice(b); return nil }
570
571 func (e *EDNS0_DAU) String() string {
572 s := ""
573 for _, alg := range e.AlgCode {
574 if a, ok := AlgorithmToString[alg]; ok {
575 s += " " + a
576 } else {
577 s += " " + strconv.Itoa(int(alg))
578 }
579 }
580 return s
581 }
582 func (e *EDNS0_DAU) copy() EDNS0 { return &EDNS0_DAU{e.Code, e.AlgCode} }
583
584 // EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
585 type EDNS0_DHU struct {
586 Code uint16 // always EDNS0DHU
587 AlgCode []uint8
588 }
589
590 // Option implements the EDNS0 interface.
591 func (e *EDNS0_DHU) Option() uint16 { return EDNS0DHU }
592 func (e *EDNS0_DHU) pack() ([]byte, error) { return cloneSlice(e.AlgCode), nil }
593 func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = cloneSlice(b); return nil }
594
595 func (e *EDNS0_DHU) String() string {
596 s := ""
597 for _, alg := range e.AlgCode {
598 if a, ok := HashToString[alg]; ok {
599 s += " " + a
600 } else {
601 s += " " + strconv.Itoa(int(alg))
602 }
603 }
604 return s
605 }
606 func (e *EDNS0_DHU) copy() EDNS0 { return &EDNS0_DHU{e.Code, e.AlgCode} }
607
608 // EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
609 type EDNS0_N3U struct {
610 Code uint16 // always EDNS0N3U
611 AlgCode []uint8
612 }
613
614 // Option implements the EDNS0 interface.
615 func (e *EDNS0_N3U) Option() uint16 { return EDNS0N3U }
616 func (e *EDNS0_N3U) pack() ([]byte, error) { return cloneSlice(e.AlgCode), nil }
617 func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = cloneSlice(b); return nil }
618
619 func (e *EDNS0_N3U) String() string {
620 // Re-use the hash map
621 s := ""
622 for _, alg := range e.AlgCode {
623 if a, ok := HashToString[alg]; ok {
624 s += " " + a
625 } else {
626 s += " " + strconv.Itoa(int(alg))
627 }
628 }
629 return s
630 }
631 func (e *EDNS0_N3U) copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} }
632
633 // EDNS0_EXPIRE implements the EDNS0 option as described in RFC 7314.
634 type EDNS0_EXPIRE struct {
635 Code uint16 // always EDNS0EXPIRE
636 Expire uint32
637 Empty bool // Empty is used to signal an empty Expire option in a backwards compatible way, it's not used on the wire.
638 }
639
640 // Option implements the EDNS0 interface.
641 func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
642 func (e *EDNS0_EXPIRE) copy() EDNS0 { return &EDNS0_EXPIRE{e.Code, e.Expire, e.Empty} }
643
644 func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
645 if e.Empty {
646 return []byte{}, nil
647 }
648 b := make([]byte, 4)
649 binary.BigEndian.PutUint32(b, e.Expire)
650 return b, nil
651 }
652
653 func (e *EDNS0_EXPIRE) unpack(b []byte) error {
654 if len(b) == 0 {
655 // zero-length EXPIRE query, see RFC 7314 Section 2
656 e.Empty = true
657 return nil
658 }
659 if len(b) < 4 {
660 return ErrBuf
661 }
662 e.Expire = binary.BigEndian.Uint32(b)
663 e.Empty = false
664 return nil
665 }
666
667 func (e *EDNS0_EXPIRE) String() (s string) {
668 if e.Empty {
669 return ""
670 }
671 return strconv.FormatUint(uint64(e.Expire), 10)
672 }
673
674 // The EDNS0_LOCAL option is used for local/experimental purposes. The option
675 // code is recommended to be within the range [EDNS0LOCALSTART, EDNS0LOCALEND]
676 // (RFC6891), although any unassigned code can actually be used. The content of
677 // the option is made available in Data, unaltered.
678 // Basic use pattern for creating a local option:
679 //
680 // o := new(dns.OPT)
681 // o.Hdr.Name = "."
682 // o.Hdr.Rrtype = dns.TypeOPT
683 // e := new(dns.EDNS0_LOCAL)
684 // e.Code = dns.EDNS0LOCALSTART
685 // e.Data = []byte{72, 82, 74}
686 // o.Option = append(o.Option, e)
687 type EDNS0_LOCAL struct {
688 Code uint16
689 Data []byte
690 }
691
692 // Option implements the EDNS0 interface.
693 func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
694
695 func (e *EDNS0_LOCAL) String() string {
696 return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
697 }
698
699 func (e *EDNS0_LOCAL) copy() EDNS0 {
700 return &EDNS0_LOCAL{e.Code, cloneSlice(e.Data)}
701 }
702
703 func (e *EDNS0_LOCAL) pack() ([]byte, error) {
704 return cloneSlice(e.Data), nil
705 }
706
707 func (e *EDNS0_LOCAL) unpack(b []byte) error {
708 e.Data = cloneSlice(b)
709 return nil
710 }
711
712 // EDNS0_TCP_KEEPALIVE is an EDNS0 option that instructs the server to keep
713 // the TCP connection alive. See RFC 7828.
714 type EDNS0_TCP_KEEPALIVE struct {
715 Code uint16 // always EDNSTCPKEEPALIVE
716
717 // Timeout is an idle timeout value for the TCP connection, specified in
718 // units of 100 milliseconds, encoded in network byte order. If set to 0,
719 // pack will return a nil slice.
720 Timeout uint16
721
722 // Length is the option's length.
723 // Deprecated: this field is deprecated and is always equal to 0.
724 Length uint16
725 }
726
727 // Option implements the EDNS0 interface.
728 func (e *EDNS0_TCP_KEEPALIVE) Option() uint16 { return EDNS0TCPKEEPALIVE }
729
730 func (e *EDNS0_TCP_KEEPALIVE) pack() ([]byte, error) {
731 if e.Timeout > 0 {
732 b := make([]byte, 2)
733 binary.BigEndian.PutUint16(b, e.Timeout)
734 return b, nil
735 }
736 return nil, nil
737 }
738
739 func (e *EDNS0_TCP_KEEPALIVE) unpack(b []byte) error {
740 switch len(b) {
741 case 0:
742 case 2:
743 e.Timeout = binary.BigEndian.Uint16(b)
744 default:
745 return fmt.Errorf("length mismatch, want 0/2 but got %d", len(b))
746 }
747 return nil
748 }
749
750 func (e *EDNS0_TCP_KEEPALIVE) String() string {
751 s := "use tcp keep-alive"
752 if e.Timeout == 0 {
753 s += ", timeout omitted"
754 } else {
755 s += fmt.Sprintf(", timeout %dms", e.Timeout*100)
756 }
757 return s
758 }
759
760 func (e *EDNS0_TCP_KEEPALIVE) copy() EDNS0 { return &EDNS0_TCP_KEEPALIVE{e.Code, e.Timeout, e.Length} }
761
762 // EDNS0_PADDING option is used to add padding to a request/response. The default
763 // value of padding SHOULD be 0x0 but other values MAY be used, for instance if
764 // compression is applied before encryption which may break signatures.
765 type EDNS0_PADDING struct {
766 Padding []byte
767 }
768
769 // Option implements the EDNS0 interface.
770 func (e *EDNS0_PADDING) Option() uint16 { return EDNS0PADDING }
771 func (e *EDNS0_PADDING) pack() ([]byte, error) { return cloneSlice(e.Padding), nil }
772 func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = cloneSlice(b); return nil }
773 func (e *EDNS0_PADDING) String() string { return fmt.Sprintf("%0X", e.Padding) }
774 func (e *EDNS0_PADDING) copy() EDNS0 { return &EDNS0_PADDING{cloneSlice(e.Padding)} }
775
776 // Extended DNS Error Codes (RFC 8914).
777 const (
778 ExtendedErrorCodeOther uint16 = iota
779 ExtendedErrorCodeUnsupportedDNSKEYAlgorithm
780 ExtendedErrorCodeUnsupportedDSDigestType
781 ExtendedErrorCodeStaleAnswer
782 ExtendedErrorCodeForgedAnswer
783 ExtendedErrorCodeDNSSECIndeterminate
784 ExtendedErrorCodeDNSBogus
785 ExtendedErrorCodeSignatureExpired
786 ExtendedErrorCodeSignatureNotYetValid
787 ExtendedErrorCodeDNSKEYMissing
788 ExtendedErrorCodeRRSIGsMissing
789 ExtendedErrorCodeNoZoneKeyBitSet
790 ExtendedErrorCodeNSECMissing
791 ExtendedErrorCodeCachedError
792 ExtendedErrorCodeNotReady
793 ExtendedErrorCodeBlocked
794 ExtendedErrorCodeCensored
795 ExtendedErrorCodeFiltered
796 ExtendedErrorCodeProhibited
797 ExtendedErrorCodeStaleNXDOMAINAnswer
798 ExtendedErrorCodeNotAuthoritative
799 ExtendedErrorCodeNotSupported
800 ExtendedErrorCodeNoReachableAuthority
801 ExtendedErrorCodeNetworkError
802 ExtendedErrorCodeInvalidData
803 ExtendedErrorCodeSignatureExpiredBeforeValid
804 ExtendedErrorCodeTooEarly
805 ExtendedErrorCodeUnsupportedNSEC3IterValue
806 ExtendedErrorCodeUnableToConformToPolicy
807 ExtendedErrorCodeSynthesized
808 ExtendedErrorCodeInvalidQueryType
809 )
810
811 // ExtendedErrorCodeToString maps extended error info codes to a human readable
812 // description.
813 var ExtendedErrorCodeToString = map[uint16]string{
814 ExtendedErrorCodeOther: "Other",
815 ExtendedErrorCodeUnsupportedDNSKEYAlgorithm: "Unsupported DNSKEY Algorithm",
816 ExtendedErrorCodeUnsupportedDSDigestType: "Unsupported DS Digest Type",
817 ExtendedErrorCodeStaleAnswer: "Stale Answer",
818 ExtendedErrorCodeForgedAnswer: "Forged Answer",
819 ExtendedErrorCodeDNSSECIndeterminate: "DNSSEC Indeterminate",
820 ExtendedErrorCodeDNSBogus: "DNSSEC Bogus",
821 ExtendedErrorCodeSignatureExpired: "Signature Expired",
822 ExtendedErrorCodeSignatureNotYetValid: "Signature Not Yet Valid",
823 ExtendedErrorCodeDNSKEYMissing: "DNSKEY Missing",
824 ExtendedErrorCodeRRSIGsMissing: "RRSIGs Missing",
825 ExtendedErrorCodeNoZoneKeyBitSet: "No Zone Key Bit Set",
826 ExtendedErrorCodeNSECMissing: "NSEC Missing",
827 ExtendedErrorCodeCachedError: "Cached Error",
828 ExtendedErrorCodeNotReady: "Not Ready",
829 ExtendedErrorCodeBlocked: "Blocked",
830 ExtendedErrorCodeCensored: "Censored",
831 ExtendedErrorCodeFiltered: "Filtered",
832 ExtendedErrorCodeProhibited: "Prohibited",
833 ExtendedErrorCodeStaleNXDOMAINAnswer: "Stale NXDOMAIN Answer",
834 ExtendedErrorCodeNotAuthoritative: "Not Authoritative",
835 ExtendedErrorCodeNotSupported: "Not Supported",
836 ExtendedErrorCodeNoReachableAuthority: "No Reachable Authority",
837 ExtendedErrorCodeNetworkError: "Network Error",
838 ExtendedErrorCodeInvalidData: "Invalid Data",
839 ExtendedErrorCodeSignatureExpiredBeforeValid: "Signature Expired Before Valid",
840 ExtendedErrorCodeTooEarly: "Too Early",
841 ExtendedErrorCodeUnsupportedNSEC3IterValue: "Unsupported NSEC3 Iterations Value",
842 ExtendedErrorCodeUnableToConformToPolicy: "Unable To Conform To Policy",
843 ExtendedErrorCodeSynthesized: "Synthesized",
844 ExtendedErrorCodeInvalidQueryType: "Invalid Query Type",
845 }
846
847 // StringToExtendedErrorCode is a map from human readable descriptions to
848 // extended error info codes.
849 var StringToExtendedErrorCode = reverseInt16(ExtendedErrorCodeToString)
850
851 // EDNS0_EDE option is used to return additional information about the cause of
852 // DNS errors.
853 type EDNS0_EDE struct {
854 InfoCode uint16
855 ExtraText string
856 }
857
858 // Option implements the EDNS0 interface.
859 func (e *EDNS0_EDE) Option() uint16 { return EDNS0EDE }
860 func (e *EDNS0_EDE) copy() EDNS0 { return &EDNS0_EDE{e.InfoCode, e.ExtraText} }
861
862 func (e *EDNS0_EDE) String() string {
863 info := strconv.FormatUint(uint64(e.InfoCode), 10)
864 if s, ok := ExtendedErrorCodeToString[e.InfoCode]; ok {
865 info += fmt.Sprintf(" (%s)", s)
866 }
867 return fmt.Sprintf("%s: (%s)", info, e.ExtraText)
868 }
869
870 func (e *EDNS0_EDE) pack() ([]byte, error) {
871 b := make([]byte, 2+len(e.ExtraText))
872 binary.BigEndian.PutUint16(b[0:], e.InfoCode)
873 copy(b[2:], e.ExtraText)
874 return b, nil
875 }
876
877 func (e *EDNS0_EDE) unpack(b []byte) error {
878 if len(b) < 2 {
879 return ErrBuf
880 }
881 e.InfoCode = binary.BigEndian.Uint16(b[0:])
882 e.ExtraText = string(b[2:])
883 return nil
884 }
885
886 // The EDNS0_ESU option for ENUM Source-URI Extension.
887 type EDNS0_ESU struct {
888 Code uint16 // always EDNS0ESU
889 Uri string
890 }
891
892 func (e *EDNS0_ESU) Option() uint16 { return EDNS0ESU }
893 func (e *EDNS0_ESU) String() string { return e.Uri }
894 func (e *EDNS0_ESU) copy() EDNS0 { return &EDNS0_ESU{e.Code, e.Uri} }
895 func (e *EDNS0_ESU) pack() ([]byte, error) { return []byte(e.Uri), nil }
896 func (e *EDNS0_ESU) unpack(b []byte) error {
897 e.Uri = string(b)
898 return nil
899 }
900
901 // EDNS0_REPORTING implements the EDNS0 Reporting Channel option (RFC 9567).
902 type EDNS0_REPORTING struct {
903 Code uint16 // always EDNS0REPORTING
904 AgentDomain string
905 }
906
907 func (e *EDNS0_REPORTING) Option() uint16 { return EDNS0REPORTING }
908 func (e *EDNS0_REPORTING) String() string { return e.AgentDomain }
909 func (e *EDNS0_REPORTING) copy() EDNS0 { return &EDNS0_REPORTING{e.Code, e.AgentDomain} }
910 func (e *EDNS0_REPORTING) pack() ([]byte, error) {
911 b := make([]byte, 255)
912 off1, err := PackDomainName(Fqdn(e.AgentDomain), b, 0, nil, false)
913 if err != nil {
914 return nil, fmt.Errorf("bad agent domain: %w", err)
915 }
916 return b[:off1], nil
917 }
918 func (e *EDNS0_REPORTING) unpack(b []byte) error {
919 domain, _, err := UnpackDomainName(b, 0)
920 if err != nil {
921 return fmt.Errorf("bad agent domain: %w", err)
922 }
923 e.AgentDomain = domain
924 return nil
925 }
926
927 // EDNS0_ZONEVERSION implements the EDNS0 Zone Version option (RFC 9660).
928 type EDNS0_ZONEVERSION struct {
929 // always EDNS0ZONEVERSION (19)
930 Code uint16
931 // An unsigned 1-octet Label Count indicating
932 // the number of labels for the name of the zone that VERSION value refers to.
933 LabelCount uint8
934 // An unsigned 1-octet type number distinguishing the format and meaning of version.
935 // 0 SOA-SERIAL, 1-245 Unassigned, 246-255 Reserved for private use, see RFC 9660.
936 Type uint8
937 // An opaque octet string conveying the zone version data (VERSION).
938 Version string
939 }
940
941 func (e *EDNS0_ZONEVERSION) Option() uint16 { return EDNS0ZONEVERSION }
942 func (e *EDNS0_ZONEVERSION) String() string { return e.Version }
943 func (e *EDNS0_ZONEVERSION) copy() EDNS0 {
944 return &EDNS0_ZONEVERSION{e.Code, e.LabelCount, e.Type, e.Version}
945 }
946 func (e *EDNS0_ZONEVERSION) pack() ([]byte, error) {
947 b := []byte{
948 // first octet label count
949 e.LabelCount,
950 // second octet is type
951 e.Type,
952 }
953 if len(e.Version) > 0 {
954 b = append(b, []byte(e.Version)...)
955 }
956 return b, nil
957 }
958 func (e *EDNS0_ZONEVERSION) unpack(b []byte) error {
959 if len(b) < 2 {
960 return ErrBuf
961 }
962 e.LabelCount = b[0]
963 e.Type = b[1]
964 if len(b) > 2 {
965 e.Version = string(b[2:])
966 } else {
967 e.Version = ""
968 }
969 return nil
970 }
971