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