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:"cdomain-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 src := []byte(s) 423 dst := make([]byte, 0, len(src)) 424 for i := 0; i < len(src); { 425 if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' { 426 dst = append(dst, src[i:i+2]...) 427 i += 2 428 } else { 429 b, n := nextByte(src, i) 430 if n == 0 { 431 i++ // dangling back slash 432 } else if b == '.' { 433 dst = append(dst, b) 434 } else { 435 dst = appendDomainNameByte(dst, b) 436 } 437 i += n 438 } 439 } 440 return string(dst) 441} 442 443func sprintTxtOctet(s string) string { 444 src := []byte(s) 445 dst := make([]byte, 0, len(src)) 446 dst = append(dst, '"') 447 for i := 0; i < len(src); { 448 if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' { 449 dst = append(dst, src[i:i+2]...) 450 i += 2 451 } else { 452 b, n := nextByte(src, i) 453 if n == 0 { 454 i++ // dangling back slash 455 } else if b == '.' { 456 dst = append(dst, b) 457 } else { 458 if b < ' ' || b > '~' { 459 dst = appendByte(dst, b) 460 } else { 461 dst = append(dst, b) 462 } 463 } 464 i += n 465 } 466 } 467 dst = append(dst, '"') 468 return string(dst) 469} 470 471func sprintTxt(txt []string) string { 472 var out []byte 473 for i, s := range txt { 474 if i > 0 { 475 out = append(out, ` "`...) 476 } else { 477 out = append(out, '"') 478 } 479 bs := []byte(s) 480 for j := 0; j < len(bs); { 481 b, n := nextByte(bs, j) 482 if n == 0 { 483 break 484 } 485 out = appendTXTStringByte(out, b) 486 j += n 487 } 488 out = append(out, '"') 489 } 490 return string(out) 491} 492 493func appendDomainNameByte(s []byte, b byte) []byte { 494 switch b { 495 case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape 496 return append(s, '\\', b) 497 } 498 return appendTXTStringByte(s, b) 499} 500 501func appendTXTStringByte(s []byte, b byte) []byte { 502 switch b { 503 case '"', '\\': 504 return append(s, '\\', b) 505 } 506 if b < ' ' || b > '~' { 507 return appendByte(s, b) 508 } 509 return append(s, b) 510} 511 512func appendByte(s []byte, b byte) []byte { 513 var buf [3]byte 514 bufs := strconv.AppendInt(buf[:0], int64(b), 10) 515 s = append(s, '\\') 516 for i := 0; i < 3-len(bufs); i++ { 517 s = append(s, '0') 518 } 519 for _, r := range bufs { 520 s = append(s, r) 521 } 522 return s 523} 524 525func nextByte(b []byte, offset int) (byte, int) { 526 if offset >= len(b) { 527 return 0, 0 528 } 529 if b[offset] != '\\' { 530 // not an escape sequence 531 return b[offset], 1 532 } 533 switch len(b) - offset { 534 case 1: // dangling escape 535 return 0, 0 536 case 2, 3: // too short to be \ddd 537 default: // maybe \ddd 538 if isDigit(b[offset+1]) && isDigit(b[offset+2]) && isDigit(b[offset+3]) { 539 return dddToByte(b[offset+1:]), 4 540 } 541 } 542 // not \ddd, just an RFC 1035 "quoted" character 543 return b[offset+1], 2 544} 545 546// SPF RR. See RFC 4408, Section 3.1.1. 547type SPF struct { 548 Hdr RR_Header 549 Txt []string `dns:"txt"` 550} 551 552func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) } 553 554// AVC RR. See https://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template. 555type AVC struct { 556 Hdr RR_Header 557 Txt []string `dns:"txt"` 558} 559 560func (rr *AVC) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) } 561 562// SRV RR. See RFC 2782. 563type SRV struct { 564 Hdr RR_Header 565 Priority uint16 566 Weight uint16 567 Port uint16 568 Target string `dns:"domain-name"` 569} 570 571func (rr *SRV) String() string { 572 return rr.Hdr.String() + 573 strconv.Itoa(int(rr.Priority)) + " " + 574 strconv.Itoa(int(rr.Weight)) + " " + 575 strconv.Itoa(int(rr.Port)) + " " + sprintName(rr.Target) 576} 577 578// NAPTR RR. See RFC 2915. 579type NAPTR struct { 580 Hdr RR_Header 581 Order uint16 582 Preference uint16 583 Flags string 584 Service string 585 Regexp string 586 Replacement string `dns:"domain-name"` 587} 588 589func (rr *NAPTR) String() string { 590 return rr.Hdr.String() + 591 strconv.Itoa(int(rr.Order)) + " " + 592 strconv.Itoa(int(rr.Preference)) + " " + 593 "\"" + rr.Flags + "\" " + 594 "\"" + rr.Service + "\" " + 595 "\"" + rr.Regexp + "\" " + 596 rr.Replacement 597} 598 599// CERT RR. See RFC 4398. 600type CERT struct { 601 Hdr RR_Header 602 Type uint16 603 KeyTag uint16 604 Algorithm uint8 605 Certificate string `dns:"base64"` 606} 607 608func (rr *CERT) String() string { 609 var ( 610 ok bool 611 certtype, algorithm string 612 ) 613 if certtype, ok = CertTypeToString[rr.Type]; !ok { 614 certtype = strconv.Itoa(int(rr.Type)) 615 } 616 if algorithm, ok = AlgorithmToString[rr.Algorithm]; !ok { 617 algorithm = strconv.Itoa(int(rr.Algorithm)) 618 } 619 return rr.Hdr.String() + certtype + 620 " " + strconv.Itoa(int(rr.KeyTag)) + 621 " " + algorithm + 622 " " + rr.Certificate 623} 624 625// DNAME RR. See RFC 2672. 626type DNAME struct { 627 Hdr RR_Header 628 Target string `dns:"domain-name"` 629} 630 631func (rr *DNAME) String() string { 632 return rr.Hdr.String() + sprintName(rr.Target) 633} 634 635// A RR. See RFC 1035. 636type A struct { 637 Hdr RR_Header 638 A net.IP `dns:"a"` 639} 640 641func (rr *A) String() string { 642 if rr.A == nil { 643 return rr.Hdr.String() 644 } 645 return rr.Hdr.String() + rr.A.String() 646} 647 648// AAAA RR. See RFC 3596. 649type AAAA struct { 650 Hdr RR_Header 651 AAAA net.IP `dns:"aaaa"` 652} 653 654func (rr *AAAA) String() string { 655 if rr.AAAA == nil { 656 return rr.Hdr.String() 657 } 658 return rr.Hdr.String() + rr.AAAA.String() 659} 660 661// PX RR. See RFC 2163. 662type PX struct { 663 Hdr RR_Header 664 Preference uint16 665 Map822 string `dns:"domain-name"` 666 Mapx400 string `dns:"domain-name"` 667} 668 669func (rr *PX) String() string { 670 return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Map822) + " " + sprintName(rr.Mapx400) 671} 672 673// GPOS RR. See RFC 1712. 674type GPOS struct { 675 Hdr RR_Header 676 Longitude string 677 Latitude string 678 Altitude string 679} 680 681func (rr *GPOS) String() string { 682 return rr.Hdr.String() + rr.Longitude + " " + rr.Latitude + " " + rr.Altitude 683} 684 685// LOC RR. See RFC RFC 1876. 686type LOC struct { 687 Hdr RR_Header 688 Version uint8 689 Size uint8 690 HorizPre uint8 691 VertPre uint8 692 Latitude uint32 693 Longitude uint32 694 Altitude uint32 695} 696 697// cmToM takes a cm value expressed in RFC1876 SIZE mantissa/exponent 698// format and returns a string in m (two decimals for the cm) 699func cmToM(m, e uint8) string { 700 if e < 2 { 701 if e == 1 { 702 m *= 10 703 } 704 705 return fmt.Sprintf("0.%02d", m) 706 } 707 708 s := fmt.Sprintf("%d", m) 709 for e > 2 { 710 s += "0" 711 e-- 712 } 713 return s 714} 715 716func (rr *LOC) String() string { 717 s := rr.Hdr.String() 718 719 lat := rr.Latitude 720 ns := "N" 721 if lat > LOC_EQUATOR { 722 lat = lat - LOC_EQUATOR 723 } else { 724 ns = "S" 725 lat = LOC_EQUATOR - lat 726 } 727 h := lat / LOC_DEGREES 728 lat = lat % LOC_DEGREES 729 m := lat / LOC_HOURS 730 lat = lat % LOC_HOURS 731 s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lat) / 1000), ns) 732 733 lon := rr.Longitude 734 ew := "E" 735 if lon > LOC_PRIMEMERIDIAN { 736 lon = lon - LOC_PRIMEMERIDIAN 737 } else { 738 ew = "W" 739 lon = LOC_PRIMEMERIDIAN - lon 740 } 741 h = lon / LOC_DEGREES 742 lon = lon % LOC_DEGREES 743 m = lon / LOC_HOURS 744 lon = lon % LOC_HOURS 745 s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lon) / 1000), ew) 746 747 var alt = float64(rr.Altitude) / 100 748 alt -= LOC_ALTITUDEBASE 749 if rr.Altitude%100 != 0 { 750 s += fmt.Sprintf("%.2fm ", alt) 751 } else { 752 s += fmt.Sprintf("%.0fm ", alt) 753 } 754 755 s += cmToM((rr.Size&0xf0)>>4, rr.Size&0x0f) + "m " 756 s += cmToM((rr.HorizPre&0xf0)>>4, rr.HorizPre&0x0f) + "m " 757 s += cmToM((rr.VertPre&0xf0)>>4, rr.VertPre&0x0f) + "m" 758 759 return s 760} 761 762// SIG RR. See RFC 2535. The SIG RR is identical to RRSIG and nowadays only used for SIG(0), See RFC 2931. 763type SIG struct { 764 RRSIG 765} 766 767// RRSIG RR. See RFC 4034 and RFC 3755. 768type RRSIG struct { 769 Hdr RR_Header 770 TypeCovered uint16 771 Algorithm uint8 772 Labels uint8 773 OrigTtl uint32 774 Expiration uint32 775 Inception uint32 776 KeyTag uint16 777 SignerName string `dns:"domain-name"` 778 Signature string `dns:"base64"` 779} 780 781func (rr *RRSIG) String() string { 782 s := rr.Hdr.String() 783 s += Type(rr.TypeCovered).String() 784 s += " " + strconv.Itoa(int(rr.Algorithm)) + 785 " " + strconv.Itoa(int(rr.Labels)) + 786 " " + strconv.FormatInt(int64(rr.OrigTtl), 10) + 787 " " + TimeToString(rr.Expiration) + 788 " " + TimeToString(rr.Inception) + 789 " " + strconv.Itoa(int(rr.KeyTag)) + 790 " " + sprintName(rr.SignerName) + 791 " " + rr.Signature 792 return s 793} 794 795// NSEC RR. See RFC 4034 and RFC 3755. 796type NSEC struct { 797 Hdr RR_Header 798 NextDomain string `dns:"domain-name"` 799 TypeBitMap []uint16 `dns:"nsec"` 800} 801 802func (rr *NSEC) String() string { 803 s := rr.Hdr.String() + sprintName(rr.NextDomain) 804 for i := 0; i < len(rr.TypeBitMap); i++ { 805 s += " " + Type(rr.TypeBitMap[i]).String() 806 } 807 return s 808} 809 810func (rr *NSEC) len() int { 811 l := rr.Hdr.len() + len(rr.NextDomain) + 1 812 lastwindow := uint32(2 ^ 32 + 1) 813 for _, t := range rr.TypeBitMap { 814 window := t / 256 815 if uint32(window) != lastwindow { 816 l += 1 + 32 817 } 818 lastwindow = uint32(window) 819 } 820 return l 821} 822 823// DLV RR. See RFC 4431. 824type DLV struct{ DS } 825 826// CDS RR. See RFC 7344. 827type CDS struct{ DS } 828 829// DS RR. See RFC 4034 and RFC 3658. 830type DS struct { 831 Hdr RR_Header 832 KeyTag uint16 833 Algorithm uint8 834 DigestType uint8 835 Digest string `dns:"hex"` 836} 837 838func (rr *DS) String() string { 839 return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) + 840 " " + strconv.Itoa(int(rr.Algorithm)) + 841 " " + strconv.Itoa(int(rr.DigestType)) + 842 " " + strings.ToUpper(rr.Digest) 843} 844 845// KX RR. See RFC 2230. 846type KX struct { 847 Hdr RR_Header 848 Preference uint16 849 Exchanger string `dns:"domain-name"` 850} 851 852func (rr *KX) String() string { 853 return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + 854 " " + sprintName(rr.Exchanger) 855} 856 857// TA RR. See http://www.watson.org/~weiler/INI1999-19.pdf. 858type TA struct { 859 Hdr RR_Header 860 KeyTag uint16 861 Algorithm uint8 862 DigestType uint8 863 Digest string `dns:"hex"` 864} 865 866func (rr *TA) String() string { 867 return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) + 868 " " + strconv.Itoa(int(rr.Algorithm)) + 869 " " + strconv.Itoa(int(rr.DigestType)) + 870 " " + strings.ToUpper(rr.Digest) 871} 872 873// TALINK RR. See https://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template. 874type TALINK struct { 875 Hdr RR_Header 876 PreviousName string `dns:"domain-name"` 877 NextName string `dns:"domain-name"` 878} 879 880func (rr *TALINK) String() string { 881 return rr.Hdr.String() + 882 sprintName(rr.PreviousName) + " " + sprintName(rr.NextName) 883} 884 885// SSHFP RR. See RFC RFC 4255. 886type SSHFP struct { 887 Hdr RR_Header 888 Algorithm uint8 889 Type uint8 890 FingerPrint string `dns:"hex"` 891} 892 893func (rr *SSHFP) String() string { 894 return rr.Hdr.String() + strconv.Itoa(int(rr.Algorithm)) + 895 " " + strconv.Itoa(int(rr.Type)) + 896 " " + strings.ToUpper(rr.FingerPrint) 897} 898 899// KEY RR. See RFC RFC 2535. 900type KEY struct { 901 DNSKEY 902} 903 904// CDNSKEY RR. See RFC 7344. 905type CDNSKEY struct { 906 DNSKEY 907} 908 909// DNSKEY RR. See RFC 4034 and RFC 3755. 910type DNSKEY struct { 911 Hdr RR_Header 912 Flags uint16 913 Protocol uint8 914 Algorithm uint8 915 PublicKey string `dns:"base64"` 916} 917 918func (rr *DNSKEY) String() string { 919 return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) + 920 " " + strconv.Itoa(int(rr.Protocol)) + 921 " " + strconv.Itoa(int(rr.Algorithm)) + 922 " " + rr.PublicKey 923} 924 925// RKEY RR. See https://www.iana.org/assignments/dns-parameters/RKEY/rkey-completed-template. 926type RKEY struct { 927 Hdr RR_Header 928 Flags uint16 929 Protocol uint8 930 Algorithm uint8 931 PublicKey string `dns:"base64"` 932} 933 934func (rr *RKEY) String() string { 935 return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) + 936 " " + strconv.Itoa(int(rr.Protocol)) + 937 " " + strconv.Itoa(int(rr.Algorithm)) + 938 " " + rr.PublicKey 939} 940 941// NSAPPTR RR. See RFC 1348. 942type NSAPPTR struct { 943 Hdr RR_Header 944 Ptr string `dns:"domain-name"` 945} 946 947func (rr *NSAPPTR) String() string { return rr.Hdr.String() + sprintName(rr.Ptr) } 948 949// NSEC3 RR. See RFC 5155. 950type NSEC3 struct { 951 Hdr RR_Header 952 Hash uint8 953 Flags uint8 954 Iterations uint16 955 SaltLength uint8 956 Salt string `dns:"size-hex:SaltLength"` 957 HashLength uint8 958 NextDomain string `dns:"size-base32:HashLength"` 959 TypeBitMap []uint16 `dns:"nsec"` 960} 961 962func (rr *NSEC3) String() string { 963 s := rr.Hdr.String() 964 s += strconv.Itoa(int(rr.Hash)) + 965 " " + strconv.Itoa(int(rr.Flags)) + 966 " " + strconv.Itoa(int(rr.Iterations)) + 967 " " + saltToString(rr.Salt) + 968 " " + rr.NextDomain 969 for i := 0; i < len(rr.TypeBitMap); i++ { 970 s += " " + Type(rr.TypeBitMap[i]).String() 971 } 972 return s 973} 974 975func (rr *NSEC3) len() int { 976 l := rr.Hdr.len() + 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1 977 lastwindow := uint32(2 ^ 32 + 1) 978 for _, t := range rr.TypeBitMap { 979 window := t / 256 980 if uint32(window) != lastwindow { 981 l += 1 + 32 982 } 983 lastwindow = uint32(window) 984 } 985 return l 986} 987 988// NSEC3PARAM RR. See RFC 5155. 989type NSEC3PARAM struct { 990 Hdr RR_Header 991 Hash uint8 992 Flags uint8 993 Iterations uint16 994 SaltLength uint8 995 Salt string `dns:"size-hex:SaltLength"` 996} 997 998func (rr *NSEC3PARAM) String() string { 999 s := rr.Hdr.String() 1000 s += strconv.Itoa(int(rr.Hash)) + 1001 " " + strconv.Itoa(int(rr.Flags)) + 1002 " " + strconv.Itoa(int(rr.Iterations)) + 1003 " " + saltToString(rr.Salt) 1004 return s 1005} 1006 1007// TKEY RR. See RFC 2930. 1008type TKEY struct { 1009 Hdr RR_Header 1010 Algorithm string `dns:"domain-name"` 1011 Inception uint32 1012 Expiration uint32 1013 Mode uint16 1014 Error uint16 1015 KeySize uint16 1016 Key string `dns:"size-hex:KeySize"` 1017 OtherLen uint16 1018 OtherData string `dns:"size-hex:OtherLen"` 1019} 1020 1021// TKEY has no official presentation format, but this will suffice. 1022func (rr *TKEY) String() string { 1023 s := "\n;; TKEY PSEUDOSECTION:\n" 1024 s += rr.Hdr.String() + " " + rr.Algorithm + " " + 1025 strconv.Itoa(int(rr.KeySize)) + " " + rr.Key + " " + 1026 strconv.Itoa(int(rr.OtherLen)) + " " + rr.OtherData 1027 return s 1028} 1029 1030// RFC3597 represents an unknown/generic RR. See RFC 3597. 1031type RFC3597 struct { 1032 Hdr RR_Header 1033 Rdata string `dns:"hex"` 1034} 1035 1036func (rr *RFC3597) String() string { 1037 // Let's call it a hack 1038 s := rfc3597Header(rr.Hdr) 1039 1040 s += "\\# " + strconv.Itoa(len(rr.Rdata)/2) + " " + rr.Rdata 1041 return s 1042} 1043 1044func rfc3597Header(h RR_Header) string { 1045 var s string 1046 1047 s += sprintName(h.Name) + "\t" 1048 s += strconv.FormatInt(int64(h.Ttl), 10) + "\t" 1049 s += "CLASS" + strconv.Itoa(int(h.Class)) + "\t" 1050 s += "TYPE" + strconv.Itoa(int(h.Rrtype)) + "\t" 1051 return s 1052} 1053 1054// URI RR. See RFC 7553. 1055type URI struct { 1056 Hdr RR_Header 1057 Priority uint16 1058 Weight uint16 1059 Target string `dns:"octet"` 1060} 1061 1062func (rr *URI) String() string { 1063 return rr.Hdr.String() + strconv.Itoa(int(rr.Priority)) + 1064 " " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target) 1065} 1066 1067// DHCID RR. See RFC 4701. 1068type DHCID struct { 1069 Hdr RR_Header 1070 Digest string `dns:"base64"` 1071} 1072 1073func (rr *DHCID) String() string { return rr.Hdr.String() + rr.Digest } 1074 1075// TLSA RR. See RFC 6698. 1076type TLSA struct { 1077 Hdr RR_Header 1078 Usage uint8 1079 Selector uint8 1080 MatchingType uint8 1081 Certificate string `dns:"hex"` 1082} 1083 1084func (rr *TLSA) String() string { 1085 return rr.Hdr.String() + 1086 strconv.Itoa(int(rr.Usage)) + 1087 " " + strconv.Itoa(int(rr.Selector)) + 1088 " " + strconv.Itoa(int(rr.MatchingType)) + 1089 " " + rr.Certificate 1090} 1091 1092// SMIMEA RR. See RFC 8162. 1093type SMIMEA struct { 1094 Hdr RR_Header 1095 Usage uint8 1096 Selector uint8 1097 MatchingType uint8 1098 Certificate string `dns:"hex"` 1099} 1100 1101func (rr *SMIMEA) String() string { 1102 s := rr.Hdr.String() + 1103 strconv.Itoa(int(rr.Usage)) + 1104 " " + strconv.Itoa(int(rr.Selector)) + 1105 " " + strconv.Itoa(int(rr.MatchingType)) 1106 1107 // Every Nth char needs a space on this output. If we output 1108 // this as one giant line, we can't read it can in because in some cases 1109 // the cert length overflows scan.maxTok (2048). 1110 sx := splitN(rr.Certificate, 1024) // conservative value here 1111 s += " " + strings.Join(sx, " ") 1112 return s 1113} 1114 1115// HIP RR. See RFC 8005. 1116type HIP struct { 1117 Hdr RR_Header 1118 HitLength uint8 1119 PublicKeyAlgorithm uint8 1120 PublicKeyLength uint16 1121 Hit string `dns:"size-hex:HitLength"` 1122 PublicKey string `dns:"size-base64:PublicKeyLength"` 1123 RendezvousServers []string `dns:"domain-name"` 1124} 1125 1126func (rr *HIP) String() string { 1127 s := rr.Hdr.String() + 1128 strconv.Itoa(int(rr.PublicKeyAlgorithm)) + 1129 " " + rr.Hit + 1130 " " + rr.PublicKey 1131 for _, d := range rr.RendezvousServers { 1132 s += " " + sprintName(d) 1133 } 1134 return s 1135} 1136 1137// NINFO RR. See https://www.iana.org/assignments/dns-parameters/NINFO/ninfo-completed-template. 1138type NINFO struct { 1139 Hdr RR_Header 1140 ZSData []string `dns:"txt"` 1141} 1142 1143func (rr *NINFO) String() string { return rr.Hdr.String() + sprintTxt(rr.ZSData) } 1144 1145// NID RR. See RFC RFC 6742. 1146type NID struct { 1147 Hdr RR_Header 1148 Preference uint16 1149 NodeID uint64 1150} 1151 1152func (rr *NID) String() string { 1153 s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) 1154 node := fmt.Sprintf("%0.16x", rr.NodeID) 1155 s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16] 1156 return s 1157} 1158 1159// L32 RR, See RFC 6742. 1160type L32 struct { 1161 Hdr RR_Header 1162 Preference uint16 1163 Locator32 net.IP `dns:"a"` 1164} 1165 1166func (rr *L32) String() string { 1167 if rr.Locator32 == nil { 1168 return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) 1169 } 1170 return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + 1171 " " + rr.Locator32.String() 1172} 1173 1174// L64 RR, See RFC 6742. 1175type L64 struct { 1176 Hdr RR_Header 1177 Preference uint16 1178 Locator64 uint64 1179} 1180 1181func (rr *L64) String() string { 1182 s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) 1183 node := fmt.Sprintf("%0.16X", rr.Locator64) 1184 s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16] 1185 return s 1186} 1187 1188// LP RR. See RFC 6742. 1189type LP struct { 1190 Hdr RR_Header 1191 Preference uint16 1192 Fqdn string `dns:"domain-name"` 1193} 1194 1195func (rr *LP) String() string { 1196 return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Fqdn) 1197} 1198 1199// EUI48 RR. See RFC 7043. 1200type EUI48 struct { 1201 Hdr RR_Header 1202 Address uint64 `dns:"uint48"` 1203} 1204 1205func (rr *EUI48) String() string { return rr.Hdr.String() + euiToString(rr.Address, 48) } 1206 1207// EUI64 RR. See RFC 7043. 1208type EUI64 struct { 1209 Hdr RR_Header 1210 Address uint64 1211} 1212 1213func (rr *EUI64) String() string { return rr.Hdr.String() + euiToString(rr.Address, 64) } 1214 1215// CAA RR. See RFC 6844. 1216type CAA struct { 1217 Hdr RR_Header 1218 Flag uint8 1219 Tag string 1220 Value string `dns:"octet"` 1221} 1222 1223func (rr *CAA) String() string { 1224 return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintTxtOctet(rr.Value) 1225} 1226 1227// UID RR. Deprecated, IANA-Reserved. 1228type UID struct { 1229 Hdr RR_Header 1230 Uid uint32 1231} 1232 1233func (rr *UID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Uid), 10) } 1234 1235// GID RR. Deprecated, IANA-Reserved. 1236type GID struct { 1237 Hdr RR_Header 1238 Gid uint32 1239} 1240 1241func (rr *GID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Gid), 10) } 1242 1243// UINFO RR. Deprecated, IANA-Reserved. 1244type UINFO struct { 1245 Hdr RR_Header 1246 Uinfo string 1247} 1248 1249func (rr *UINFO) String() string { return rr.Hdr.String() + sprintTxt([]string{rr.Uinfo}) } 1250 1251// EID RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt. 1252type EID struct { 1253 Hdr RR_Header 1254 Endpoint string `dns:"hex"` 1255} 1256 1257func (rr *EID) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Endpoint) } 1258 1259// NIMLOC RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt. 1260type NIMLOC struct { 1261 Hdr RR_Header 1262 Locator string `dns:"hex"` 1263} 1264 1265func (rr *NIMLOC) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Locator) } 1266 1267// OPENPGPKEY RR. See RFC 7929. 1268type OPENPGPKEY struct { 1269 Hdr RR_Header 1270 PublicKey string `dns:"base64"` 1271} 1272 1273func (rr *OPENPGPKEY) String() string { return rr.Hdr.String() + rr.PublicKey } 1274 1275// CSYNC RR. See RFC 7477. 1276type CSYNC struct { 1277 Hdr RR_Header 1278 Serial uint32 1279 Flags uint16 1280 TypeBitMap []uint16 `dns:"nsec"` 1281} 1282 1283func (rr *CSYNC) String() string { 1284 s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags)) 1285 1286 for i := 0; i < len(rr.TypeBitMap); i++ { 1287 s += " " + Type(rr.TypeBitMap[i]).String() 1288 } 1289 return s 1290} 1291 1292func (rr *CSYNC) len() int { 1293 l := rr.Hdr.len() + 4 + 2 1294 lastwindow := uint32(2 ^ 32 + 1) 1295 for _, t := range rr.TypeBitMap { 1296 window := t / 256 1297 if uint32(window) != lastwindow { 1298 l += 1 + 32 1299 } 1300 lastwindow = uint32(window) 1301 } 1302 return l 1303} 1304 1305// TimeToString translates the RRSIG's incep. and expir. times to the 1306// string representation used when printing the record. 1307// It takes serial arithmetic (RFC 1982) into account. 1308func TimeToString(t uint32) string { 1309 mod := ((int64(t) - time.Now().Unix()) / year68) - 1 1310 if mod < 0 { 1311 mod = 0 1312 } 1313 ti := time.Unix(int64(t)-(mod*year68), 0).UTC() 1314 return ti.Format("20060102150405") 1315} 1316 1317// StringToTime translates the RRSIG's incep. and expir. times from 1318// string values like "20110403154150" to an 32 bit integer. 1319// It takes serial arithmetic (RFC 1982) into account. 1320func StringToTime(s string) (uint32, error) { 1321 t, err := time.Parse("20060102150405", s) 1322 if err != nil { 1323 return 0, err 1324 } 1325 mod := (t.Unix() / year68) - 1 1326 if mod < 0 { 1327 mod = 0 1328 } 1329 return uint32(t.Unix() - (mod * year68)), nil 1330} 1331 1332// saltToString converts a NSECX salt to uppercase and returns "-" when it is empty. 1333func saltToString(s string) string { 1334 if len(s) == 0 { 1335 return "-" 1336 } 1337 return strings.ToUpper(s) 1338} 1339 1340func euiToString(eui uint64, bits int) (hex string) { 1341 switch bits { 1342 case 64: 1343 hex = fmt.Sprintf("%16.16x", eui) 1344 hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] + 1345 "-" + hex[8:10] + "-" + hex[10:12] + "-" + hex[12:14] + "-" + hex[14:16] 1346 case 48: 1347 hex = fmt.Sprintf("%12.12x", eui) 1348 hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] + 1349 "-" + hex[8:10] + "-" + hex[10:12] 1350 } 1351 return 1352} 1353 1354// copyIP returns a copy of ip. 1355func copyIP(ip net.IP) net.IP { 1356 p := make(net.IP, len(ip)) 1357 copy(p, ip) 1358 return p 1359} 1360 1361// SplitN splits a string into N sized string chunks. 1362// This might become an exported function once. 1363func splitN(s string, n int) []string { 1364 if len(s) < n { 1365 return []string{s} 1366 } 1367 sx := []string{} 1368 p, i := 0, n 1369 for { 1370 if i <= len(s) { 1371 sx = append(sx, s[p:i]) 1372 } else { 1373 sx = append(sx, s[p:]) 1374 break 1375 1376 } 1377 p, i = p+n, i+n 1378 } 1379 1380 return sx 1381} 1382