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