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