1package dns 2 3import ( 4 "fmt" 5 "net" 6 "strconv" 7 "strings" 8 "time" 9) 10 11type ( 12 // Type is a DNS type. 13 Type uint16 14 // Class is a DNS class. 15 Class uint16 16 // Name is a DNS domain name. 17 Name string 18) 19 20// Packet formats 21 22// Wire constants and supported types. 23const ( 24 // valid RR_Header.Rrtype and Question.qtype 25 26 TypeNone uint16 = 0 27 TypeA uint16 = 1 28 TypeNS uint16 = 2 29 TypeMD uint16 = 3 30 TypeMF uint16 = 4 31 TypeCNAME uint16 = 5 32 TypeSOA uint16 = 6 33 TypeMB uint16 = 7 34 TypeMG uint16 = 8 35 TypeMR uint16 = 9 36 TypeNULL uint16 = 10 37 TypePTR uint16 = 12 38 TypeHINFO uint16 = 13 39 TypeMINFO uint16 = 14 40 TypeMX uint16 = 15 41 TypeTXT uint16 = 16 42 TypeRP uint16 = 17 43 TypeAFSDB uint16 = 18 44 TypeX25 uint16 = 19 45 TypeISDN uint16 = 20 46 TypeRT uint16 = 21 47 TypeNSAPPTR uint16 = 23 48 TypeSIG uint16 = 24 49 TypeKEY uint16 = 25 50 TypePX uint16 = 26 51 TypeGPOS uint16 = 27 52 TypeAAAA uint16 = 28 53 TypeLOC uint16 = 29 54 TypeNXT uint16 = 30 55 TypeEID uint16 = 31 56 TypeNIMLOC uint16 = 32 57 TypeSRV uint16 = 33 58 TypeATMA uint16 = 34 59 TypeNAPTR uint16 = 35 60 TypeKX uint16 = 36 61 TypeCERT uint16 = 37 62 TypeDNAME uint16 = 39 63 TypeOPT uint16 = 41 // EDNS 64 TypeDS uint16 = 43 65 TypeSSHFP uint16 = 44 66 TypeRRSIG uint16 = 46 67 TypeNSEC uint16 = 47 68 TypeDNSKEY uint16 = 48 69 TypeDHCID uint16 = 49 70 TypeNSEC3 uint16 = 50 71 TypeNSEC3PARAM uint16 = 51 72 TypeTLSA uint16 = 52 73 TypeSMIMEA uint16 = 53 74 TypeHIP uint16 = 55 75 TypeNINFO uint16 = 56 76 TypeRKEY uint16 = 57 77 TypeTALINK uint16 = 58 78 TypeCDS uint16 = 59 79 TypeCDNSKEY uint16 = 60 80 TypeOPENPGPKEY uint16 = 61 81 TypeCSYNC uint16 = 62 82 TypeSPF uint16 = 99 83 TypeUINFO uint16 = 100 84 TypeUID uint16 = 101 85 TypeGID uint16 = 102 86 TypeUNSPEC uint16 = 103 87 TypeNID uint16 = 104 88 TypeL32 uint16 = 105 89 TypeL64 uint16 = 106 90 TypeLP uint16 = 107 91 TypeEUI48 uint16 = 108 92 TypeEUI64 uint16 = 109 93 TypeURI uint16 = 256 94 TypeCAA uint16 = 257 95 TypeAVC uint16 = 258 96 97 TypeTKEY uint16 = 249 98 TypeTSIG uint16 = 250 99 100 // valid Question.Qtype only 101 TypeIXFR uint16 = 251 102 TypeAXFR uint16 = 252 103 TypeMAILB uint16 = 253 104 TypeMAILA uint16 = 254 105 TypeANY uint16 = 255 106 107 TypeTA uint16 = 32768 108 TypeDLV uint16 = 32769 109 TypeReserved uint16 = 65535 110 111 // valid Question.Qclass 112 ClassINET = 1 113 ClassCSNET = 2 114 ClassCHAOS = 3 115 ClassHESIOD = 4 116 ClassNONE = 254 117 ClassANY = 255 118 119 // Message Response Codes, see https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml 120 RcodeSuccess = 0 // NoError - No Error [DNS] 121 RcodeFormatError = 1 // FormErr - Format Error [DNS] 122 RcodeServerFailure = 2 // ServFail - Server Failure [DNS] 123 RcodeNameError = 3 // NXDomain - Non-Existent Domain [DNS] 124 RcodeNotImplemented = 4 // NotImp - Not Implemented [DNS] 125 RcodeRefused = 5 // Refused - Query Refused [DNS] 126 RcodeYXDomain = 6 // YXDomain - Name Exists when it should not [DNS Update] 127 RcodeYXRrset = 7 // YXRRSet - RR Set Exists when it should not [DNS Update] 128 RcodeNXRrset = 8 // NXRRSet - RR Set that should exist does not [DNS Update] 129 RcodeNotAuth = 9 // NotAuth - Server Not Authoritative for zone [DNS Update] 130 RcodeNotZone = 10 // NotZone - Name not contained in zone [DNS Update/TSIG] 131 RcodeBadSig = 16 // BADSIG - TSIG Signature Failure [TSIG] 132 RcodeBadVers = 16 // BADVERS - Bad OPT Version [EDNS0] 133 RcodeBadKey = 17 // BADKEY - Key not recognized [TSIG] 134 RcodeBadTime = 18 // BADTIME - Signature out of time window [TSIG] 135 RcodeBadMode = 19 // BADMODE - Bad TKEY Mode [TKEY] 136 RcodeBadName = 20 // BADNAME - Duplicate key name [TKEY] 137 RcodeBadAlg = 21 // BADALG - Algorithm not supported [TKEY] 138 RcodeBadTrunc = 22 // BADTRUNC - Bad Truncation [TSIG] 139 RcodeBadCookie = 23 // BADCOOKIE - Bad/missing Server Cookie [DNS Cookies] 140 141 // Message Opcodes. There is no 3. 142 OpcodeQuery = 0 143 OpcodeIQuery = 1 144 OpcodeStatus = 2 145 OpcodeNotify = 4 146 OpcodeUpdate = 5 147) 148 149// Header is the wire format for the DNS packet header. 150type Header struct { 151 Id uint16 152 Bits uint16 153 Qdcount, Ancount, Nscount, Arcount uint16 154} 155 156const ( 157 headerSize = 12 158 159 // Header.Bits 160 _QR = 1 << 15 // query/response (response=1) 161 _AA = 1 << 10 // authoritative 162 _TC = 1 << 9 // truncated 163 _RD = 1 << 8 // recursion desired 164 _RA = 1 << 7 // recursion available 165 _Z = 1 << 6 // Z 166 _AD = 1 << 5 // authticated data 167 _CD = 1 << 4 // checking disabled 168) 169 170// Various constants used in the LOC RR, See RFC 1887. 171const ( 172 LOC_EQUATOR = 1 << 31 // RFC 1876, Section 2. 173 LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2. 174 LOC_HOURS = 60 * 1000 175 LOC_DEGREES = 60 * LOC_HOURS 176 LOC_ALTITUDEBASE = 100000 177) 178 179// Different Certificate Types, see RFC 4398, Section 2.1 180const ( 181 CertPKIX = 1 + iota 182 CertSPKI 183 CertPGP 184 CertIPIX 185 CertISPKI 186 CertIPGP 187 CertACPKIX 188 CertIACPKIX 189 CertURI = 253 190 CertOID = 254 191) 192 193// CertTypeToString converts the Cert Type to its string representation. 194// See RFC 4398 and RFC 6944. 195var CertTypeToString = map[uint16]string{ 196 CertPKIX: "PKIX", 197 CertSPKI: "SPKI", 198 CertPGP: "PGP", 199 CertIPIX: "IPIX", 200 CertISPKI: "ISPKI", 201 CertIPGP: "IPGP", 202 CertACPKIX: "ACPKIX", 203 CertIACPKIX: "IACPKIX", 204 CertURI: "URI", 205 CertOID: "OID", 206} 207 208// StringToCertType is the reverseof CertTypeToString. 209var StringToCertType = reverseInt16(CertTypeToString) 210 211//go:generate go run types_generate.go 212 213// Question holds a DNS question. There can be multiple questions in the 214// question section of a message. Usually there is just one. 215type Question struct { 216 Name string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed) 217 Qtype uint16 218 Qclass uint16 219} 220 221func (q *Question) len() int { 222 return len(q.Name) + 1 + 2 + 2 223} 224 225func (q *Question) String() (s string) { 226 // prefix with ; (as in dig) 227 s = ";" + sprintName(q.Name) + "\t" 228 s += Class(q.Qclass).String() + "\t" 229 s += " " + Type(q.Qtype).String() 230 return s 231} 232 233// ANY is a wildcard record. See RFC 1035, Section 3.2.3. ANY 234// is named "*" there. 235type ANY struct { 236 Hdr RR_Header 237 // Does not have any rdata 238} 239 240func (rr *ANY) String() string { return rr.Hdr.String() } 241 242// CNAME RR. See RFC 1034. 243type CNAME struct { 244 Hdr RR_Header 245 Target string `dns:"cdomain-name"` 246} 247 248func (rr *CNAME) String() string { return rr.Hdr.String() + sprintName(rr.Target) } 249 250// HINFO RR. See RFC 1034. 251type HINFO struct { 252 Hdr RR_Header 253 Cpu string 254 Os string 255} 256 257func (rr *HINFO) String() string { 258 return rr.Hdr.String() + sprintTxt([]string{rr.Cpu, rr.Os}) 259} 260 261// MB RR. See RFC 1035. 262type MB struct { 263 Hdr RR_Header 264 Mb string `dns:"cdomain-name"` 265} 266 267func (rr *MB) String() string { return rr.Hdr.String() + sprintName(rr.Mb) } 268 269// MG RR. See RFC 1035. 270type MG struct { 271 Hdr RR_Header 272 Mg string `dns:"cdomain-name"` 273} 274 275func (rr *MG) String() string { return rr.Hdr.String() + sprintName(rr.Mg) } 276 277// MINFO RR. See RFC 1035. 278type MINFO struct { 279 Hdr RR_Header 280 Rmail string `dns:"cdomain-name"` 281 Email string `dns:"cdomain-name"` 282} 283 284func (rr *MINFO) String() string { 285 return rr.Hdr.String() + sprintName(rr.Rmail) + " " + sprintName(rr.Email) 286} 287 288// MR RR. See RFC 1035. 289type MR struct { 290 Hdr RR_Header 291 Mr string `dns:"cdomain-name"` 292} 293 294func (rr *MR) String() string { 295 return rr.Hdr.String() + sprintName(rr.Mr) 296} 297 298// MF RR. See RFC 1035. 299type MF struct { 300 Hdr RR_Header 301 Mf string `dns:"cdomain-name"` 302} 303 304func (rr *MF) String() string { 305 return rr.Hdr.String() + sprintName(rr.Mf) 306} 307 308// MD RR. See RFC 1035. 309type MD struct { 310 Hdr RR_Header 311 Md string `dns:"cdomain-name"` 312} 313 314func (rr *MD) String() string { 315 return rr.Hdr.String() + sprintName(rr.Md) 316} 317 318// MX RR. See RFC 1035. 319type MX struct { 320 Hdr RR_Header 321 Preference uint16 322 Mx string `dns:"cdomain-name"` 323} 324 325func (rr *MX) String() string { 326 return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Mx) 327} 328 329// AFSDB RR. See RFC 1183. 330type AFSDB struct { 331 Hdr RR_Header 332 Subtype uint16 333 Hostname string `dns:"domain-name"` 334} 335 336func (rr *AFSDB) String() string { 337 return rr.Hdr.String() + strconv.Itoa(int(rr.Subtype)) + " " + sprintName(rr.Hostname) 338} 339 340// X25 RR. See RFC 1183, Section 3.1. 341type X25 struct { 342 Hdr RR_Header 343 PSDNAddress string 344} 345 346func (rr *X25) String() string { 347 return rr.Hdr.String() + rr.PSDNAddress 348} 349 350// RT RR. See RFC 1183, Section 3.3. 351type RT struct { 352 Hdr RR_Header 353 Preference uint16 354 Host string `dns:"cdomain-name"` 355} 356 357func (rr *RT) String() string { 358 return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Host) 359} 360 361// NS RR. See RFC 1035. 362type NS struct { 363 Hdr RR_Header 364 Ns string `dns:"cdomain-name"` 365} 366 367func (rr *NS) String() string { 368 return rr.Hdr.String() + sprintName(rr.Ns) 369} 370 371// PTR RR. See RFC 1035. 372type PTR struct { 373 Hdr RR_Header 374 Ptr string `dns:"cdomain-name"` 375} 376 377func (rr *PTR) String() string { 378 return rr.Hdr.String() + sprintName(rr.Ptr) 379} 380 381// RP RR. See RFC 1138, Section 2.2. 382type RP struct { 383 Hdr RR_Header 384 Mbox string `dns:"domain-name"` 385 Txt string `dns:"domain-name"` 386} 387 388func (rr *RP) String() string { 389 return rr.Hdr.String() + rr.Mbox + " " + sprintTxt([]string{rr.Txt}) 390} 391 392// SOA RR. See RFC 1035. 393type SOA struct { 394 Hdr RR_Header 395 Ns string `dns:"cdomain-name"` 396 Mbox string `dns:"cdomain-name"` 397 Serial uint32 398 Refresh uint32 399 Retry uint32 400 Expire uint32 401 Minttl uint32 402} 403 404func (rr *SOA) String() string { 405 return rr.Hdr.String() + sprintName(rr.Ns) + " " + sprintName(rr.Mbox) + 406 " " + strconv.FormatInt(int64(rr.Serial), 10) + 407 " " + strconv.FormatInt(int64(rr.Refresh), 10) + 408 " " + strconv.FormatInt(int64(rr.Retry), 10) + 409 " " + strconv.FormatInt(int64(rr.Expire), 10) + 410 " " + strconv.FormatInt(int64(rr.Minttl), 10) 411} 412 413// TXT RR. See RFC 1035. 414type TXT struct { 415 Hdr RR_Header 416 Txt []string `dns:"txt"` 417} 418 419func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) } 420 421func sprintName(s string) string { 422 var dst strings.Builder 423 dst.Grow(len(s)) 424 for i := 0; i < len(s); { 425 if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' { 426 dst.WriteString(s[i : i+2]) 427 i += 2 428 continue 429 } 430 431 b, n := nextByte(s, i) 432 switch { 433 case n == 0: 434 i++ // dangling back slash 435 case b == '.': 436 dst.WriteByte('.') 437 default: 438 writeDomainNameByte(&dst, b) 439 } 440 i += n 441 } 442 return dst.String() 443} 444 445func sprintTxtOctet(s string) string { 446 var dst strings.Builder 447 dst.Grow(2 + len(s)) 448 dst.WriteByte('"') 449 for i := 0; i < len(s); { 450 if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' { 451 dst.WriteString(s[i : i+2]) 452 i += 2 453 continue 454 } 455 456 b, n := nextByte(s, i) 457 switch { 458 case n == 0: 459 i++ // dangling back slash 460 case b == '.': 461 dst.WriteByte('.') 462 case b < ' ' || b > '~': 463 writeEscapedByte(&dst, b) 464 default: 465 dst.WriteByte(b) 466 } 467 i += n 468 } 469 dst.WriteByte('"') 470 return dst.String() 471} 472 473func sprintTxt(txt []string) string { 474 var out strings.Builder 475 for i, s := range txt { 476 out.Grow(3 + len(s)) 477 if i > 0 { 478 out.WriteString(` "`) 479 } else { 480 out.WriteByte('"') 481 } 482 for j := 0; j < len(s); { 483 b, n := nextByte(s, j) 484 if n == 0 { 485 break 486 } 487 writeTXTStringByte(&out, b) 488 j += n 489 } 490 out.WriteByte('"') 491 } 492 return out.String() 493} 494 495func writeDomainNameByte(s *strings.Builder, b byte) { 496 switch b { 497 case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape 498 s.WriteByte('\\') 499 s.WriteByte(b) 500 default: 501 writeTXTStringByte(s, b) 502 } 503} 504 505func writeTXTStringByte(s *strings.Builder, b byte) { 506 switch { 507 case b == '"' || b == '\\': 508 s.WriteByte('\\') 509 s.WriteByte(b) 510 case b < ' ' || b > '~': 511 writeEscapedByte(s, b) 512 default: 513 s.WriteByte(b) 514 } 515} 516 517func writeEscapedByte(s *strings.Builder, b byte) { 518 var buf [3]byte 519 bufs := strconv.AppendInt(buf[:0], int64(b), 10) 520 s.WriteByte('\\') 521 for i := len(bufs); i < 3; i++ { 522 s.WriteByte('0') 523 } 524 s.Write(bufs) 525} 526 527func nextByte(s string, offset int) (byte, int) { 528 if offset >= len(s) { 529 return 0, 0 530 } 531 if s[offset] != '\\' { 532 // not an escape sequence 533 return s[offset], 1 534 } 535 switch len(s) - offset { 536 case 1: // dangling escape 537 return 0, 0 538 case 2, 3: // too short to be \ddd 539 default: // maybe \ddd 540 if isDigit(s[offset+1]) && isDigit(s[offset+2]) && isDigit(s[offset+3]) { 541 return dddStringToByte(s[offset+1:]), 4 542 } 543 } 544 // not \ddd, just an RFC 1035 "quoted" character 545 return s[offset+1], 2 546} 547 548// SPF RR. See RFC 4408, Section 3.1.1. 549type SPF struct { 550 Hdr RR_Header 551 Txt []string `dns:"txt"` 552} 553 554func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) } 555 556// AVC RR. See https://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template. 557type AVC struct { 558 Hdr RR_Header 559 Txt []string `dns:"txt"` 560} 561 562func (rr *AVC) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) } 563 564// SRV RR. See RFC 2782. 565type SRV struct { 566 Hdr RR_Header 567 Priority uint16 568 Weight uint16 569 Port uint16 570 Target string `dns:"domain-name"` 571} 572 573func (rr *SRV) String() string { 574 return rr.Hdr.String() + 575 strconv.Itoa(int(rr.Priority)) + " " + 576 strconv.Itoa(int(rr.Weight)) + " " + 577 strconv.Itoa(int(rr.Port)) + " " + sprintName(rr.Target) 578} 579 580// NAPTR RR. See RFC 2915. 581type NAPTR struct { 582 Hdr RR_Header 583 Order uint16 584 Preference uint16 585 Flags string 586 Service string 587 Regexp string 588 Replacement string `dns:"domain-name"` 589} 590 591func (rr *NAPTR) String() string { 592 return rr.Hdr.String() + 593 strconv.Itoa(int(rr.Order)) + " " + 594 strconv.Itoa(int(rr.Preference)) + " " + 595 "\"" + rr.Flags + "\" " + 596 "\"" + rr.Service + "\" " + 597 "\"" + rr.Regexp + "\" " + 598 rr.Replacement 599} 600 601// CERT RR. See RFC 4398. 602type CERT struct { 603 Hdr RR_Header 604 Type uint16 605 KeyTag uint16 606 Algorithm uint8 607 Certificate string `dns:"base64"` 608} 609 610func (rr *CERT) String() string { 611 var ( 612 ok bool 613 certtype, algorithm string 614 ) 615 if certtype, ok = CertTypeToString[rr.Type]; !ok { 616 certtype = strconv.Itoa(int(rr.Type)) 617 } 618 if algorithm, ok = AlgorithmToString[rr.Algorithm]; !ok { 619 algorithm = strconv.Itoa(int(rr.Algorithm)) 620 } 621 return rr.Hdr.String() + certtype + 622 " " + strconv.Itoa(int(rr.KeyTag)) + 623 " " + algorithm + 624 " " + rr.Certificate 625} 626 627// DNAME RR. See RFC 2672. 628type DNAME struct { 629 Hdr RR_Header 630 Target string `dns:"domain-name"` 631} 632 633func (rr *DNAME) String() string { 634 return rr.Hdr.String() + sprintName(rr.Target) 635} 636 637// A RR. See RFC 1035. 638type A struct { 639 Hdr RR_Header 640 A net.IP `dns:"a"` 641} 642 643func (rr *A) String() string { 644 if rr.A == nil { 645 return rr.Hdr.String() 646 } 647 return rr.Hdr.String() + rr.A.String() 648} 649 650// AAAA RR. See RFC 3596. 651type AAAA struct { 652 Hdr RR_Header 653 AAAA net.IP `dns:"aaaa"` 654} 655 656func (rr *AAAA) String() string { 657 if rr.AAAA == nil { 658 return rr.Hdr.String() 659 } 660 return rr.Hdr.String() + rr.AAAA.String() 661} 662 663// PX RR. See RFC 2163. 664type PX struct { 665 Hdr RR_Header 666 Preference uint16 667 Map822 string `dns:"domain-name"` 668 Mapx400 string `dns:"domain-name"` 669} 670 671func (rr *PX) String() string { 672 return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Map822) + " " + sprintName(rr.Mapx400) 673} 674 675// GPOS RR. See RFC 1712. 676type GPOS struct { 677 Hdr RR_Header 678 Longitude string 679 Latitude string 680 Altitude string 681} 682 683func (rr *GPOS) String() string { 684 return rr.Hdr.String() + rr.Longitude + " " + rr.Latitude + " " + rr.Altitude 685} 686 687// LOC RR. See RFC RFC 1876. 688type LOC struct { 689 Hdr RR_Header 690 Version uint8 691 Size uint8 692 HorizPre uint8 693 VertPre uint8 694 Latitude uint32 695 Longitude uint32 696 Altitude uint32 697} 698 699// cmToM takes a cm value expressed in RFC1876 SIZE mantissa/exponent 700// format and returns a string in m (two decimals for the cm) 701func cmToM(m, e uint8) string { 702 if e < 2 { 703 if e == 1 { 704 m *= 10 705 } 706 707 return fmt.Sprintf("0.%02d", m) 708 } 709 710 s := fmt.Sprintf("%d", m) 711 for e > 2 { 712 s += "0" 713 e-- 714 } 715 return s 716} 717 718func (rr *LOC) String() string { 719 s := rr.Hdr.String() 720 721 lat := rr.Latitude 722 ns := "N" 723 if lat > LOC_EQUATOR { 724 lat = lat - LOC_EQUATOR 725 } else { 726 ns = "S" 727 lat = LOC_EQUATOR - lat 728 } 729 h := lat / LOC_DEGREES 730 lat = lat % LOC_DEGREES 731 m := lat / LOC_HOURS 732 lat = lat % LOC_HOURS 733 s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lat)/1000, ns) 734 735 lon := rr.Longitude 736 ew := "E" 737 if lon > LOC_PRIMEMERIDIAN { 738 lon = lon - LOC_PRIMEMERIDIAN 739 } else { 740 ew = "W" 741 lon = LOC_PRIMEMERIDIAN - lon 742 } 743 h = lon / LOC_DEGREES 744 lon = lon % LOC_DEGREES 745 m = lon / LOC_HOURS 746 lon = lon % LOC_HOURS 747 s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lon)/1000, ew) 748 749 var alt = float64(rr.Altitude) / 100 750 alt -= LOC_ALTITUDEBASE 751 if rr.Altitude%100 != 0 { 752 s += fmt.Sprintf("%.2fm ", alt) 753 } else { 754 s += fmt.Sprintf("%.0fm ", alt) 755 } 756 757 s += cmToM(rr.Size&0xf0>>4, rr.Size&0x0f) + "m " 758 s += cmToM(rr.HorizPre&0xf0>>4, rr.HorizPre&0x0f) + "m " 759 s += cmToM(rr.VertPre&0xf0>>4, rr.VertPre&0x0f) + "m" 760 761 return s 762} 763 764// SIG RR. See RFC 2535. The SIG RR is identical to RRSIG and nowadays only used for SIG(0), See RFC 2931. 765type SIG struct { 766 RRSIG 767} 768 769// RRSIG RR. See RFC 4034 and RFC 3755. 770type RRSIG struct { 771 Hdr RR_Header 772 TypeCovered uint16 773 Algorithm uint8 774 Labels uint8 775 OrigTtl uint32 776 Expiration uint32 777 Inception uint32 778 KeyTag uint16 779 SignerName string `dns:"domain-name"` 780 Signature string `dns:"base64"` 781} 782 783func (rr *RRSIG) String() string { 784 s := rr.Hdr.String() 785 s += Type(rr.TypeCovered).String() 786 s += " " + strconv.Itoa(int(rr.Algorithm)) + 787 " " + strconv.Itoa(int(rr.Labels)) + 788 " " + strconv.FormatInt(int64(rr.OrigTtl), 10) + 789 " " + TimeToString(rr.Expiration) + 790 " " + TimeToString(rr.Inception) + 791 " " + strconv.Itoa(int(rr.KeyTag)) + 792 " " + sprintName(rr.SignerName) + 793 " " + rr.Signature 794 return s 795} 796 797// NSEC RR. See RFC 4034 and RFC 3755. 798type NSEC struct { 799 Hdr RR_Header 800 NextDomain string `dns:"domain-name"` 801 TypeBitMap []uint16 `dns:"nsec"` 802} 803 804func (rr *NSEC) String() string { 805 s := rr.Hdr.String() + sprintName(rr.NextDomain) 806 for i := 0; i < len(rr.TypeBitMap); i++ { 807 s += " " + Type(rr.TypeBitMap[i]).String() 808 } 809 return s 810} 811 812func (rr *NSEC) len() int { 813 l := rr.Hdr.len() + len(rr.NextDomain) + 1 814 lastwindow := uint32(2 ^ 32 + 1) 815 for _, t := range rr.TypeBitMap { 816 window := t / 256 817 if uint32(window) != lastwindow { 818 l += 1 + 32 819 } 820 lastwindow = uint32(window) 821 } 822 return l 823} 824 825// DLV RR. See RFC 4431. 826type DLV struct{ DS } 827 828// CDS RR. See RFC 7344. 829type CDS struct{ DS } 830 831// DS RR. See RFC 4034 and RFC 3658. 832type DS struct { 833 Hdr RR_Header 834 KeyTag uint16 835 Algorithm uint8 836 DigestType uint8 837 Digest string `dns:"hex"` 838} 839 840func (rr *DS) String() string { 841 return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) + 842 " " + strconv.Itoa(int(rr.Algorithm)) + 843 " " + strconv.Itoa(int(rr.DigestType)) + 844 " " + strings.ToUpper(rr.Digest) 845} 846 847// KX RR. See RFC 2230. 848type KX struct { 849 Hdr RR_Header 850 Preference uint16 851 Exchanger string `dns:"domain-name"` 852} 853 854func (rr *KX) String() string { 855 return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + 856 " " + sprintName(rr.Exchanger) 857} 858 859// TA RR. See http://www.watson.org/~weiler/INI1999-19.pdf. 860type TA struct { 861 Hdr RR_Header 862 KeyTag uint16 863 Algorithm uint8 864 DigestType uint8 865 Digest string `dns:"hex"` 866} 867 868func (rr *TA) String() string { 869 return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) + 870 " " + strconv.Itoa(int(rr.Algorithm)) + 871 " " + strconv.Itoa(int(rr.DigestType)) + 872 " " + strings.ToUpper(rr.Digest) 873} 874 875// TALINK RR. See https://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template. 876type TALINK struct { 877 Hdr RR_Header 878 PreviousName string `dns:"domain-name"` 879 NextName string `dns:"domain-name"` 880} 881 882func (rr *TALINK) String() string { 883 return rr.Hdr.String() + 884 sprintName(rr.PreviousName) + " " + sprintName(rr.NextName) 885} 886 887// SSHFP RR. See RFC RFC 4255. 888type SSHFP struct { 889 Hdr RR_Header 890 Algorithm uint8 891 Type uint8 892 FingerPrint string `dns:"hex"` 893} 894 895func (rr *SSHFP) String() string { 896 return rr.Hdr.String() + strconv.Itoa(int(rr.Algorithm)) + 897 " " + strconv.Itoa(int(rr.Type)) + 898 " " + strings.ToUpper(rr.FingerPrint) 899} 900 901// KEY RR. See RFC RFC 2535. 902type KEY struct { 903 DNSKEY 904} 905 906// CDNSKEY RR. See RFC 7344. 907type CDNSKEY struct { 908 DNSKEY 909} 910 911// DNSKEY RR. See RFC 4034 and RFC 3755. 912type DNSKEY struct { 913 Hdr RR_Header 914 Flags uint16 915 Protocol uint8 916 Algorithm uint8 917 PublicKey string `dns:"base64"` 918} 919 920func (rr *DNSKEY) String() string { 921 return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) + 922 " " + strconv.Itoa(int(rr.Protocol)) + 923 " " + strconv.Itoa(int(rr.Algorithm)) + 924 " " + rr.PublicKey 925} 926 927// RKEY RR. See https://www.iana.org/assignments/dns-parameters/RKEY/rkey-completed-template. 928type RKEY struct { 929 Hdr RR_Header 930 Flags uint16 931 Protocol uint8 932 Algorithm uint8 933 PublicKey string `dns:"base64"` 934} 935 936func (rr *RKEY) String() string { 937 return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) + 938 " " + strconv.Itoa(int(rr.Protocol)) + 939 " " + strconv.Itoa(int(rr.Algorithm)) + 940 " " + rr.PublicKey 941} 942 943// NSAPPTR RR. See RFC 1348. 944type NSAPPTR struct { 945 Hdr RR_Header 946 Ptr string `dns:"domain-name"` 947} 948 949func (rr *NSAPPTR) String() string { return rr.Hdr.String() + sprintName(rr.Ptr) } 950 951// NSEC3 RR. See RFC 5155. 952type NSEC3 struct { 953 Hdr RR_Header 954 Hash uint8 955 Flags uint8 956 Iterations uint16 957 SaltLength uint8 958 Salt string `dns:"size-hex:SaltLength"` 959 HashLength uint8 960 NextDomain string `dns:"size-base32:HashLength"` 961 TypeBitMap []uint16 `dns:"nsec"` 962} 963 964func (rr *NSEC3) String() string { 965 s := rr.Hdr.String() 966 s += strconv.Itoa(int(rr.Hash)) + 967 " " + strconv.Itoa(int(rr.Flags)) + 968 " " + strconv.Itoa(int(rr.Iterations)) + 969 " " + saltToString(rr.Salt) + 970 " " + rr.NextDomain 971 for i := 0; i < len(rr.TypeBitMap); i++ { 972 s += " " + Type(rr.TypeBitMap[i]).String() 973 } 974 return s 975} 976 977func (rr *NSEC3) len() int { 978 l := rr.Hdr.len() + 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1 979 lastwindow := uint32(2 ^ 32 + 1) 980 for _, t := range rr.TypeBitMap { 981 window := t / 256 982 if uint32(window) != lastwindow { 983 l += 1 + 32 984 } 985 lastwindow = uint32(window) 986 } 987 return l 988} 989 990// NSEC3PARAM RR. See RFC 5155. 991type NSEC3PARAM struct { 992 Hdr RR_Header 993 Hash uint8 994 Flags uint8 995 Iterations uint16 996 SaltLength uint8 997 Salt string `dns:"size-hex:SaltLength"` 998} 999 1000func (rr *NSEC3PARAM) String() string { 1001 s := rr.Hdr.String() 1002 s += strconv.Itoa(int(rr.Hash)) + 1003 " " + strconv.Itoa(int(rr.Flags)) + 1004 " " + strconv.Itoa(int(rr.Iterations)) + 1005 " " + saltToString(rr.Salt) 1006 return s 1007} 1008 1009// TKEY RR. See RFC 2930. 1010type TKEY struct { 1011 Hdr RR_Header 1012 Algorithm string `dns:"domain-name"` 1013 Inception uint32 1014 Expiration uint32 1015 Mode uint16 1016 Error uint16 1017 KeySize uint16 1018 Key string `dns:"size-hex:KeySize"` 1019 OtherLen uint16 1020 OtherData string `dns:"size-hex:OtherLen"` 1021} 1022 1023// TKEY has no official presentation format, but this will suffice. 1024func (rr *TKEY) String() string { 1025 s := "\n;; TKEY PSEUDOSECTION:\n" 1026 s += rr.Hdr.String() + " " + rr.Algorithm + " " + 1027 strconv.Itoa(int(rr.KeySize)) + " " + rr.Key + " " + 1028 strconv.Itoa(int(rr.OtherLen)) + " " + rr.OtherData 1029 return s 1030} 1031 1032// RFC3597 represents an unknown/generic RR. See RFC 3597. 1033type RFC3597 struct { 1034 Hdr RR_Header 1035 Rdata string `dns:"hex"` 1036} 1037 1038func (rr *RFC3597) String() string { 1039 // Let's call it a hack 1040 s := rfc3597Header(rr.Hdr) 1041 1042 s += "\\# " + strconv.Itoa(len(rr.Rdata)/2) + " " + rr.Rdata 1043 return s 1044} 1045 1046func rfc3597Header(h RR_Header) string { 1047 var s string 1048 1049 s += sprintName(h.Name) + "\t" 1050 s += strconv.FormatInt(int64(h.Ttl), 10) + "\t" 1051 s += "CLASS" + strconv.Itoa(int(h.Class)) + "\t" 1052 s += "TYPE" + strconv.Itoa(int(h.Rrtype)) + "\t" 1053 return s 1054} 1055 1056// URI RR. See RFC 7553. 1057type URI struct { 1058 Hdr RR_Header 1059 Priority uint16 1060 Weight uint16 1061 Target string `dns:"octet"` 1062} 1063 1064func (rr *URI) String() string { 1065 return rr.Hdr.String() + strconv.Itoa(int(rr.Priority)) + 1066 " " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target) 1067} 1068 1069// DHCID RR. See RFC 4701. 1070type DHCID struct { 1071 Hdr RR_Header 1072 Digest string `dns:"base64"` 1073} 1074 1075func (rr *DHCID) String() string { return rr.Hdr.String() + rr.Digest } 1076 1077// TLSA RR. See RFC 6698. 1078type TLSA struct { 1079 Hdr RR_Header 1080 Usage uint8 1081 Selector uint8 1082 MatchingType uint8 1083 Certificate string `dns:"hex"` 1084} 1085 1086func (rr *TLSA) String() string { 1087 return rr.Hdr.String() + 1088 strconv.Itoa(int(rr.Usage)) + 1089 " " + strconv.Itoa(int(rr.Selector)) + 1090 " " + strconv.Itoa(int(rr.MatchingType)) + 1091 " " + rr.Certificate 1092} 1093 1094// SMIMEA RR. See RFC 8162. 1095type SMIMEA struct { 1096 Hdr RR_Header 1097 Usage uint8 1098 Selector uint8 1099 MatchingType uint8 1100 Certificate string `dns:"hex"` 1101} 1102 1103func (rr *SMIMEA) String() string { 1104 s := rr.Hdr.String() + 1105 strconv.Itoa(int(rr.Usage)) + 1106 " " + strconv.Itoa(int(rr.Selector)) + 1107 " " + strconv.Itoa(int(rr.MatchingType)) 1108 1109 // Every Nth char needs a space on this output. If we output 1110 // this as one giant line, we can't read it can in because in some cases 1111 // the cert length overflows scan.maxTok (2048). 1112 sx := splitN(rr.Certificate, 1024) // conservative value here 1113 s += " " + strings.Join(sx, " ") 1114 return s 1115} 1116 1117// HIP RR. See RFC 8005. 1118type HIP struct { 1119 Hdr RR_Header 1120 HitLength uint8 1121 PublicKeyAlgorithm uint8 1122 PublicKeyLength uint16 1123 Hit string `dns:"size-hex:HitLength"` 1124 PublicKey string `dns:"size-base64:PublicKeyLength"` 1125 RendezvousServers []string `dns:"domain-name"` 1126} 1127 1128func (rr *HIP) String() string { 1129 s := rr.Hdr.String() + 1130 strconv.Itoa(int(rr.PublicKeyAlgorithm)) + 1131 " " + rr.Hit + 1132 " " + rr.PublicKey 1133 for _, d := range rr.RendezvousServers { 1134 s += " " + sprintName(d) 1135 } 1136 return s 1137} 1138 1139// NINFO RR. See https://www.iana.org/assignments/dns-parameters/NINFO/ninfo-completed-template. 1140type NINFO struct { 1141 Hdr RR_Header 1142 ZSData []string `dns:"txt"` 1143} 1144 1145func (rr *NINFO) String() string { return rr.Hdr.String() + sprintTxt(rr.ZSData) } 1146 1147// NID RR. See RFC RFC 6742. 1148type NID struct { 1149 Hdr RR_Header 1150 Preference uint16 1151 NodeID uint64 1152} 1153 1154func (rr *NID) String() string { 1155 s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) 1156 node := fmt.Sprintf("%0.16x", rr.NodeID) 1157 s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16] 1158 return s 1159} 1160 1161// L32 RR, See RFC 6742. 1162type L32 struct { 1163 Hdr RR_Header 1164 Preference uint16 1165 Locator32 net.IP `dns:"a"` 1166} 1167 1168func (rr *L32) String() string { 1169 if rr.Locator32 == nil { 1170 return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) 1171 } 1172 return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + 1173 " " + rr.Locator32.String() 1174} 1175 1176// L64 RR, See RFC 6742. 1177type L64 struct { 1178 Hdr RR_Header 1179 Preference uint16 1180 Locator64 uint64 1181} 1182 1183func (rr *L64) String() string { 1184 s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) 1185 node := fmt.Sprintf("%0.16X", rr.Locator64) 1186 s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16] 1187 return s 1188} 1189 1190// LP RR. See RFC 6742. 1191type LP struct { 1192 Hdr RR_Header 1193 Preference uint16 1194 Fqdn string `dns:"domain-name"` 1195} 1196 1197func (rr *LP) String() string { 1198 return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Fqdn) 1199} 1200 1201// EUI48 RR. See RFC 7043. 1202type EUI48 struct { 1203 Hdr RR_Header 1204 Address uint64 `dns:"uint48"` 1205} 1206 1207func (rr *EUI48) String() string { return rr.Hdr.String() + euiToString(rr.Address, 48) } 1208 1209// EUI64 RR. See RFC 7043. 1210type EUI64 struct { 1211 Hdr RR_Header 1212 Address uint64 1213} 1214 1215func (rr *EUI64) String() string { return rr.Hdr.String() + euiToString(rr.Address, 64) } 1216 1217// CAA RR. See RFC 6844. 1218type CAA struct { 1219 Hdr RR_Header 1220 Flag uint8 1221 Tag string 1222 Value string `dns:"octet"` 1223} 1224 1225func (rr *CAA) String() string { 1226 return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintTxtOctet(rr.Value) 1227} 1228 1229// UID RR. Deprecated, IANA-Reserved. 1230type UID struct { 1231 Hdr RR_Header 1232 Uid uint32 1233} 1234 1235func (rr *UID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Uid), 10) } 1236 1237// GID RR. Deprecated, IANA-Reserved. 1238type GID struct { 1239 Hdr RR_Header 1240 Gid uint32 1241} 1242 1243func (rr *GID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Gid), 10) } 1244 1245// UINFO RR. Deprecated, IANA-Reserved. 1246type UINFO struct { 1247 Hdr RR_Header 1248 Uinfo string 1249} 1250 1251func (rr *UINFO) String() string { return rr.Hdr.String() + sprintTxt([]string{rr.Uinfo}) } 1252 1253// EID RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt. 1254type EID struct { 1255 Hdr RR_Header 1256 Endpoint string `dns:"hex"` 1257} 1258 1259func (rr *EID) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Endpoint) } 1260 1261// NIMLOC RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt. 1262type NIMLOC struct { 1263 Hdr RR_Header 1264 Locator string `dns:"hex"` 1265} 1266 1267func (rr *NIMLOC) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Locator) } 1268 1269// OPENPGPKEY RR. See RFC 7929. 1270type OPENPGPKEY struct { 1271 Hdr RR_Header 1272 PublicKey string `dns:"base64"` 1273} 1274 1275func (rr *OPENPGPKEY) String() string { return rr.Hdr.String() + rr.PublicKey } 1276 1277// CSYNC RR. See RFC 7477. 1278type CSYNC struct { 1279 Hdr RR_Header 1280 Serial uint32 1281 Flags uint16 1282 TypeBitMap []uint16 `dns:"nsec"` 1283} 1284 1285func (rr *CSYNC) String() string { 1286 s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags)) 1287 1288 for i := 0; i < len(rr.TypeBitMap); i++ { 1289 s += " " + Type(rr.TypeBitMap[i]).String() 1290 } 1291 return s 1292} 1293 1294func (rr *CSYNC) len() int { 1295 l := rr.Hdr.len() + 4 + 2 1296 lastwindow := uint32(2 ^ 32 + 1) 1297 for _, t := range rr.TypeBitMap { 1298 window := t / 256 1299 if uint32(window) != lastwindow { 1300 l += 1 + 32 1301 } 1302 lastwindow = uint32(window) 1303 } 1304 return l 1305} 1306 1307// TimeToString translates the RRSIG's incep. and expir. times to the 1308// string representation used when printing the record. 1309// It takes serial arithmetic (RFC 1982) into account. 1310func TimeToString(t uint32) string { 1311 mod := (int64(t)-time.Now().Unix())/year68 - 1 1312 if mod < 0 { 1313 mod = 0 1314 } 1315 ti := time.Unix(int64(t)-mod*year68, 0).UTC() 1316 return ti.Format("20060102150405") 1317} 1318 1319// StringToTime translates the RRSIG's incep. and expir. times from 1320// string values like "20110403154150" to an 32 bit integer. 1321// It takes serial arithmetic (RFC 1982) into account. 1322func StringToTime(s string) (uint32, error) { 1323 t, err := time.Parse("20060102150405", s) 1324 if err != nil { 1325 return 0, err 1326 } 1327 mod := t.Unix()/year68 - 1 1328 if mod < 0 { 1329 mod = 0 1330 } 1331 return uint32(t.Unix() - mod*year68), nil 1332} 1333 1334// saltToString converts a NSECX salt to uppercase and returns "-" when it is empty. 1335func saltToString(s string) string { 1336 if len(s) == 0 { 1337 return "-" 1338 } 1339 return strings.ToUpper(s) 1340} 1341 1342func euiToString(eui uint64, bits int) (hex string) { 1343 switch bits { 1344 case 64: 1345 hex = fmt.Sprintf("%16.16x", eui) 1346 hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] + 1347 "-" + hex[8:10] + "-" + hex[10:12] + "-" + hex[12:14] + "-" + hex[14:16] 1348 case 48: 1349 hex = fmt.Sprintf("%12.12x", eui) 1350 hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] + 1351 "-" + hex[8:10] + "-" + hex[10:12] 1352 } 1353 return 1354} 1355 1356// copyIP returns a copy of ip. 1357func copyIP(ip net.IP) net.IP { 1358 p := make(net.IP, len(ip)) 1359 copy(p, ip) 1360 return p 1361} 1362 1363// SplitN splits a string into N sized string chunks. 1364// This might become an exported function once. 1365func splitN(s string, n int) []string { 1366 if len(s) < n { 1367 return []string{s} 1368 } 1369 sx := []string{} 1370 p, i := 0, n 1371 for { 1372 if i <= len(s) { 1373 sx = append(sx, s[p:i]) 1374 } else { 1375 sx = append(sx, s[p:]) 1376 break 1377 1378 } 1379 p, i = p+n, i+n 1380 } 1381 1382 return sx 1383} 1384