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