1// Copyright 2009 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Package dnsmessage provides a mostly RFC 1035 compliant implementation of 6// DNS message packing and unpacking. 7// 8// The package also supports messages with Extension Mechanisms for DNS 9// (EDNS(0)) as defined in RFC 6891. 10// 11// This implementation is designed to minimize heap allocations and avoid 12// unnecessary packing and unpacking as much as possible. 13// 14// This is a patched version of golang.org/x/net/dns/dnsmessage to support 15// compressed SRV record as allowed by mdns spec. 16// See https://github.com/golang/go/issues/24870 for more info. 17package dnsmessage 18 19import ( 20 "errors" 21 "sort" 22) 23 24// Message formats 25 26// A Type is a type of DNS request and response. 27type Type uint16 28 29const ( 30 // ResourceHeader.Type and Question.Type 31 TypeA Type = 1 32 TypeNS Type = 2 33 TypeCNAME Type = 5 34 TypeSOA Type = 6 35 TypePTR Type = 12 36 TypeMX Type = 15 37 TypeTXT Type = 16 38 TypeAAAA Type = 28 39 TypeSRV Type = 33 40 TypeOPT Type = 41 41 TypeSVCB Type = 64 42 TypeHTTPS Type = 65 43 44 // Question.Type 45 TypeWKS Type = 11 46 TypeHINFO Type = 13 47 TypeMINFO Type = 14 48 TypeAXFR Type = 252 49 TypeALL Type = 255 50) 51 52var typeNames = map[Type]string{ 53 TypeA: "TypeA", 54 TypeNS: "TypeNS", 55 TypeCNAME: "TypeCNAME", 56 TypeSOA: "TypeSOA", 57 TypePTR: "TypePTR", 58 TypeMX: "TypeMX", 59 TypeTXT: "TypeTXT", 60 TypeAAAA: "TypeAAAA", 61 TypeSRV: "TypeSRV", 62 TypeOPT: "TypeOPT", 63 TypeWKS: "TypeWKS", 64 TypeHINFO: "TypeHINFO", 65 TypeMINFO: "TypeMINFO", 66 TypeAXFR: "TypeAXFR", 67 TypeALL: "TypeALL", 68} 69 70// String implements fmt.Stringer.String. 71func (t Type) String() string { 72 if n, ok := typeNames[t]; ok { 73 return n 74 } 75 return printUint16(uint16(t)) 76} 77 78// GoString implements fmt.GoStringer.GoString. 79func (t Type) GoString() string { 80 if n, ok := typeNames[t]; ok { 81 return "dnsmessage." + n 82 } 83 return printUint16(uint16(t)) 84} 85 86// A Class is a type of network. 87type Class uint16 88 89const ( 90 // ResourceHeader.Class and Question.Class 91 ClassINET Class = 1 92 ClassCSNET Class = 2 93 ClassCHAOS Class = 3 94 ClassHESIOD Class = 4 95 96 // Question.Class 97 ClassANY Class = 255 98) 99 100var classNames = map[Class]string{ 101 ClassINET: "ClassINET", 102 ClassCSNET: "ClassCSNET", 103 ClassCHAOS: "ClassCHAOS", 104 ClassHESIOD: "ClassHESIOD", 105 ClassANY: "ClassANY", 106} 107 108// String implements fmt.Stringer.String. 109func (c Class) String() string { 110 if n, ok := classNames[c]; ok { 111 return n 112 } 113 return printUint16(uint16(c)) 114} 115 116// GoString implements fmt.GoStringer.GoString. 117func (c Class) GoString() string { 118 if n, ok := classNames[c]; ok { 119 return "dnsmessage." + n 120 } 121 return printUint16(uint16(c)) 122} 123 124// An OpCode is a DNS operation code. 125type OpCode uint16 126 127// GoString implements fmt.GoStringer.GoString. 128func (o OpCode) GoString() string { 129 return printUint16(uint16(o)) 130} 131 132// An RCode is a DNS response status code. 133type RCode uint16 134 135const ( 136 // Message.Rcode 137 RCodeSuccess RCode = 0 138 RCodeFormatError RCode = 1 139 RCodeServerFailure RCode = 2 140 RCodeNameError RCode = 3 141 RCodeNotImplemented RCode = 4 142 RCodeRefused RCode = 5 143) 144 145var rCodeNames = map[RCode]string{ 146 RCodeSuccess: "RCodeSuccess", 147 RCodeFormatError: "RCodeFormatError", 148 RCodeServerFailure: "RCodeServerFailure", 149 RCodeNameError: "RCodeNameError", 150 RCodeNotImplemented: "RCodeNotImplemented", 151 RCodeRefused: "RCodeRefused", 152} 153 154// String implements fmt.Stringer.String. 155func (r RCode) String() string { 156 if n, ok := rCodeNames[r]; ok { 157 return n 158 } 159 return printUint16(uint16(r)) 160} 161 162// GoString implements fmt.GoStringer.GoString. 163func (r RCode) GoString() string { 164 if n, ok := rCodeNames[r]; ok { 165 return "dnsmessage." + n 166 } 167 return printUint16(uint16(r)) 168} 169 170func printPaddedUint8(i uint8) string { 171 b := byte(i) 172 return string([]byte{ 173 b/100 + '0', 174 b/10%10 + '0', 175 b%10 + '0', 176 }) 177} 178 179func printUint8Bytes(buf []byte, i uint8) []byte { 180 b := byte(i) 181 if i >= 100 { 182 buf = append(buf, b/100+'0') 183 } 184 if i >= 10 { 185 buf = append(buf, b/10%10+'0') 186 } 187 return append(buf, b%10+'0') 188} 189 190func printByteSlice(b []byte) string { 191 if len(b) == 0 { 192 return "" 193 } 194 buf := make([]byte, 0, 5*len(b)) 195 buf = printUint8Bytes(buf, uint8(b[0])) 196 for _, n := range b[1:] { 197 buf = append(buf, ',', ' ') 198 buf = printUint8Bytes(buf, uint8(n)) 199 } 200 return string(buf) 201} 202 203const hexDigits = "0123456789abcdef" 204 205func printString(str []byte) string { 206 buf := make([]byte, 0, len(str)) 207 for i := 0; i < len(str); i++ { 208 c := str[i] 209 if c == '.' || c == '-' || c == ' ' || 210 'A' <= c && c <= 'Z' || 211 'a' <= c && c <= 'z' || 212 '0' <= c && c <= '9' { 213 buf = append(buf, c) 214 continue 215 } 216 217 upper := c >> 4 218 lower := (c << 4) >> 4 219 buf = append( 220 buf, 221 '\\', 222 'x', 223 hexDigits[upper], 224 hexDigits[lower], 225 ) 226 } 227 return string(buf) 228} 229 230func printUint16(i uint16) string { 231 return printUint32(uint32(i)) 232} 233 234func printUint32(i uint32) string { 235 // Max value is 4294967295. 236 buf := make([]byte, 10) 237 for b, d := buf, uint32(1000000000); d > 0; d /= 10 { 238 b[0] = byte(i/d%10 + '0') 239 if b[0] == '0' && len(b) == len(buf) && len(buf) > 1 { 240 buf = buf[1:] 241 } 242 b = b[1:] 243 i %= d 244 } 245 return string(buf) 246} 247 248func printBool(b bool) string { 249 if b { 250 return "true" 251 } 252 return "false" 253} 254 255var ( 256 // ErrNotStarted indicates that the prerequisite information isn't 257 // available yet because the previous records haven't been appropriately 258 // parsed, skipped or finished. 259 ErrNotStarted = errors.New("parsing/packing of this type isn't available yet") 260 261 // ErrSectionDone indicated that all records in the section have been 262 // parsed or finished. 263 ErrSectionDone = errors.New("parsing/packing of this section has completed") 264 265 errBaseLen = errors.New("insufficient data for base length type") 266 errCalcLen = errors.New("insufficient data for calculated length type") 267 errReserved = errors.New("segment prefix is reserved") 268 errTooManyPtr = errors.New("too many pointers (>10)") 269 errInvalidPtr = errors.New("invalid pointer") 270 errNilResouceBody = errors.New("nil resource body") 271 errResourceLen = errors.New("insufficient data for resource body length") 272 errSegTooLong = errors.New("segment length too long") 273 errZeroSegLen = errors.New("zero length segment") 274 errResTooLong = errors.New("resource length too long") 275 errTooManyQuestions = errors.New("too many Questions to pack (>65535)") 276 errTooManyAnswers = errors.New("too many Answers to pack (>65535)") 277 errTooManyAuthorities = errors.New("too many Authorities to pack (>65535)") 278 errTooManyAdditionals = errors.New("too many Additionals to pack (>65535)") 279 errNonCanonicalName = errors.New("name is not in canonical format (it must end with a .)") 280 errStringTooLong = errors.New("character string exceeds maximum length (255)") 281 errCompressedSRV = errors.New("compressed name in SRV resource data") 282) 283 284// Internal constants. 285const ( 286 // packStartingCap is the default initial buffer size allocated during 287 // packing. 288 // 289 // The starting capacity doesn't matter too much, but most DNS responses 290 // Will be <= 512 bytes as it is the limit for DNS over UDP. 291 packStartingCap = 512 292 293 // uint16Len is the length (in bytes) of a uint16. 294 uint16Len = 2 295 296 // uint32Len is the length (in bytes) of a uint32. 297 uint32Len = 4 298 299 // headerLen is the length (in bytes) of a DNS header. 300 // 301 // A header is comprised of 6 uint16s and no padding. 302 headerLen = 6 * uint16Len 303) 304 305type nestedError struct { 306 // s is the current level's error message. 307 s string 308 309 // err is the nested error. 310 err error 311} 312 313// nestedError implements error.Error. 314func (e *nestedError) Error() string { 315 return e.s + ": " + e.err.Error() 316} 317 318// Header is a representation of a DNS message header. 319type Header struct { 320 ID uint16 321 Response bool 322 OpCode OpCode 323 Authoritative bool 324 Truncated bool 325 RecursionDesired bool 326 RecursionAvailable bool 327 RCode RCode 328} 329 330func (m *Header) pack() (id uint16, bits uint16) { 331 id = m.ID 332 bits = uint16(m.OpCode)<<11 | uint16(m.RCode) 333 if m.RecursionAvailable { 334 bits |= headerBitRA 335 } 336 if m.RecursionDesired { 337 bits |= headerBitRD 338 } 339 if m.Truncated { 340 bits |= headerBitTC 341 } 342 if m.Authoritative { 343 bits |= headerBitAA 344 } 345 if m.Response { 346 bits |= headerBitQR 347 } 348 return 349} 350 351// GoString implements fmt.GoStringer.GoString. 352func (m *Header) GoString() string { 353 return "dnsmessage.Header{" + 354 "ID: " + printUint16(m.ID) + ", " + 355 "Response: " + printBool(m.Response) + ", " + 356 "OpCode: " + m.OpCode.GoString() + ", " + 357 "Authoritative: " + printBool(m.Authoritative) + ", " + 358 "Truncated: " + printBool(m.Truncated) + ", " + 359 "RecursionDesired: " + printBool(m.RecursionDesired) + ", " + 360 "RecursionAvailable: " + printBool(m.RecursionAvailable) + ", " + 361 "RCode: " + m.RCode.GoString() + "}" 362} 363 364// Message is a representation of a DNS message. 365type Message struct { 366 Header 367 Questions []Question 368 Answers []Resource 369 Authorities []Resource 370 Additionals []Resource 371} 372 373type section uint8 374 375const ( 376 sectionNotStarted section = iota 377 sectionHeader 378 sectionQuestions 379 sectionAnswers 380 sectionAuthorities 381 sectionAdditionals 382 sectionDone 383 384 headerBitQR = 1 << 15 // query/response (response=1) 385 headerBitAA = 1 << 10 // authoritative 386 headerBitTC = 1 << 9 // truncated 387 headerBitRD = 1 << 8 // recursion desired 388 headerBitRA = 1 << 7 // recursion available 389) 390 391var sectionNames = map[section]string{ 392 sectionHeader: "header", 393 sectionQuestions: "Question", 394 sectionAnswers: "Answer", 395 sectionAuthorities: "Authority", 396 sectionAdditionals: "Additional", 397} 398 399// header is the wire format for a DNS message header. 400type header struct { 401 id uint16 402 bits uint16 403 questions uint16 404 answers uint16 405 authorities uint16 406 additionals uint16 407} 408 409func (h *header) count(sec section) uint16 { 410 switch sec { 411 case sectionQuestions: 412 return h.questions 413 case sectionAnswers: 414 return h.answers 415 case sectionAuthorities: 416 return h.authorities 417 case sectionAdditionals: 418 return h.additionals 419 } 420 return 0 421} 422 423// pack appends the wire format of the header to msg. 424func (h *header) pack(msg []byte) []byte { 425 msg = packUint16(msg, h.id) 426 msg = packUint16(msg, h.bits) 427 msg = packUint16(msg, h.questions) 428 msg = packUint16(msg, h.answers) 429 msg = packUint16(msg, h.authorities) 430 return packUint16(msg, h.additionals) 431} 432 433func (h *header) unpack(msg []byte, off int) (int, error) { 434 newOff := off 435 var err error 436 if h.id, newOff, err = unpackUint16(msg, newOff); err != nil { 437 return off, &nestedError{"id", err} 438 } 439 if h.bits, newOff, err = unpackUint16(msg, newOff); err != nil { 440 return off, &nestedError{"bits", err} 441 } 442 if h.questions, newOff, err = unpackUint16(msg, newOff); err != nil { 443 return off, &nestedError{"questions", err} 444 } 445 if h.answers, newOff, err = unpackUint16(msg, newOff); err != nil { 446 return off, &nestedError{"answers", err} 447 } 448 if h.authorities, newOff, err = unpackUint16(msg, newOff); err != nil { 449 return off, &nestedError{"authorities", err} 450 } 451 if h.additionals, newOff, err = unpackUint16(msg, newOff); err != nil { 452 return off, &nestedError{"additionals", err} 453 } 454 return newOff, nil 455} 456 457func (h *header) header() Header { 458 return Header{ 459 ID: h.id, 460 Response: (h.bits & headerBitQR) != 0, 461 OpCode: OpCode(h.bits>>11) & 0xF, 462 Authoritative: (h.bits & headerBitAA) != 0, 463 Truncated: (h.bits & headerBitTC) != 0, 464 RecursionDesired: (h.bits & headerBitRD) != 0, 465 RecursionAvailable: (h.bits & headerBitRA) != 0, 466 RCode: RCode(h.bits & 0xF), 467 } 468} 469 470// A Resource is a DNS resource record. 471type Resource struct { 472 Header ResourceHeader 473 Body ResourceBody 474} 475 476func (r *Resource) GoString() string { 477 return "dnsmessage.Resource{" + 478 "Header: " + r.Header.GoString() + 479 ", Body: &" + r.Body.GoString() + 480 "}" 481} 482 483// A ResourceBody is a DNS resource record minus the header. 484type ResourceBody interface { 485 // pack packs a Resource except for its header. 486 pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) 487 488 // realType returns the actual type of the Resource. This is used to 489 // fill in the header Type field. 490 realType() Type 491 492 // GoString implements fmt.GoStringer.GoString. 493 GoString() string 494} 495 496// pack appends the wire format of the Resource to msg. 497func (r *Resource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 498 if r.Body == nil { 499 return msg, errNilResouceBody 500 } 501 oldMsg := msg 502 r.Header.Type = r.Body.realType() 503 msg, lenOff, err := r.Header.pack(msg, compression, compressionOff) 504 if err != nil { 505 return msg, &nestedError{"ResourceHeader", err} 506 } 507 preLen := len(msg) 508 msg, err = r.Body.pack(msg, compression, compressionOff) 509 if err != nil { 510 return msg, &nestedError{"content", err} 511 } 512 if err := r.Header.fixLen(msg, lenOff, preLen); err != nil { 513 return oldMsg, err 514 } 515 return msg, nil 516} 517 518// A Parser allows incrementally parsing a DNS message. 519// 520// When parsing is started, the Header is parsed. Next, each Question can be 521// either parsed or skipped. Alternatively, all Questions can be skipped at 522// once. When all Questions have been parsed, attempting to parse Questions 523// will return (nil, nil) and attempting to skip Questions will return 524// (true, nil). After all Questions have been either parsed or skipped, all 525// Answers, Authorities and Additionals can be either parsed or skipped in the 526// same way, and each type of Resource must be fully parsed or skipped before 527// proceeding to the next type of Resource. 528// 529// Note that there is no requirement to fully skip or parse the message. 530type Parser struct { 531 msg []byte 532 header header 533 534 section section 535 off int 536 index int 537 resHeaderValid bool 538 resHeader ResourceHeader 539} 540 541// Start parses the header and enables the parsing of Questions. 542func (p *Parser) Start(msg []byte) (Header, error) { 543 if p.msg != nil { 544 *p = Parser{} 545 } 546 p.msg = msg 547 var err error 548 if p.off, err = p.header.unpack(msg, 0); err != nil { 549 return Header{}, &nestedError{"unpacking header", err} 550 } 551 p.section = sectionQuestions 552 return p.header.header(), nil 553} 554 555func (p *Parser) checkAdvance(sec section) error { 556 if p.section < sec { 557 return ErrNotStarted 558 } 559 if p.section > sec { 560 return ErrSectionDone 561 } 562 p.resHeaderValid = false 563 if p.index == int(p.header.count(sec)) { 564 p.index = 0 565 p.section++ 566 return ErrSectionDone 567 } 568 return nil 569} 570 571func (p *Parser) resource(sec section) (Resource, error) { 572 var r Resource 573 var err error 574 r.Header, err = p.resourceHeader(sec) 575 if err != nil { 576 return r, err 577 } 578 p.resHeaderValid = false 579 r.Body, p.off, err = unpackResourceBody(p.msg, p.off, r.Header) 580 if err != nil { 581 return Resource{}, &nestedError{"unpacking " + sectionNames[sec], err} 582 } 583 p.index++ 584 return r, nil 585} 586 587func (p *Parser) resourceHeader(sec section) (ResourceHeader, error) { 588 if p.resHeaderValid { 589 return p.resHeader, nil 590 } 591 if err := p.checkAdvance(sec); err != nil { 592 return ResourceHeader{}, err 593 } 594 var hdr ResourceHeader 595 off, err := hdr.unpack(p.msg, p.off) 596 if err != nil { 597 return ResourceHeader{}, err 598 } 599 p.resHeaderValid = true 600 p.resHeader = hdr 601 p.off = off 602 return hdr, nil 603} 604 605func (p *Parser) skipResource(sec section) error { 606 if p.resHeaderValid { 607 newOff := p.off + int(p.resHeader.Length) 608 if newOff > len(p.msg) { 609 return errResourceLen 610 } 611 p.off = newOff 612 p.resHeaderValid = false 613 p.index++ 614 return nil 615 } 616 if err := p.checkAdvance(sec); err != nil { 617 return err 618 } 619 var err error 620 p.off, err = skipResource(p.msg, p.off) 621 if err != nil { 622 return &nestedError{"skipping: " + sectionNames[sec], err} 623 } 624 p.index++ 625 return nil 626} 627 628// Question parses a single Question. 629func (p *Parser) Question() (Question, error) { 630 if err := p.checkAdvance(sectionQuestions); err != nil { 631 return Question{}, err 632 } 633 var name Name 634 off, err := name.unpack(p.msg, p.off) 635 if err != nil { 636 return Question{}, &nestedError{"unpacking Question.Name", err} 637 } 638 typ, off, err := unpackType(p.msg, off) 639 if err != nil { 640 return Question{}, &nestedError{"unpacking Question.Type", err} 641 } 642 class, off, err := unpackClass(p.msg, off) 643 if err != nil { 644 return Question{}, &nestedError{"unpacking Question.Class", err} 645 } 646 p.off = off 647 p.index++ 648 return Question{name, typ, class}, nil 649} 650 651// AllQuestions parses all Questions. 652func (p *Parser) AllQuestions() ([]Question, error) { 653 // Multiple questions are valid according to the spec, 654 // but servers don't actually support them. There will 655 // be at most one question here. 656 // 657 // Do not pre-allocate based on info in p.header, since 658 // the data is untrusted. 659 qs := []Question{} 660 for { 661 q, err := p.Question() 662 if err == ErrSectionDone { 663 return qs, nil 664 } 665 if err != nil { 666 return nil, err 667 } 668 qs = append(qs, q) 669 } 670} 671 672// SkipQuestion skips a single Question. 673func (p *Parser) SkipQuestion() error { 674 if err := p.checkAdvance(sectionQuestions); err != nil { 675 return err 676 } 677 off, err := skipName(p.msg, p.off) 678 if err != nil { 679 return &nestedError{"skipping Question Name", err} 680 } 681 if off, err = skipType(p.msg, off); err != nil { 682 return &nestedError{"skipping Question Type", err} 683 } 684 if off, err = skipClass(p.msg, off); err != nil { 685 return &nestedError{"skipping Question Class", err} 686 } 687 p.off = off 688 p.index++ 689 return nil 690} 691 692// SkipAllQuestions skips all Questions. 693func (p *Parser) SkipAllQuestions() error { 694 for { 695 if err := p.SkipQuestion(); err == ErrSectionDone { 696 return nil 697 } else if err != nil { 698 return err 699 } 700 } 701} 702 703// AnswerHeader parses a single Answer ResourceHeader. 704func (p *Parser) AnswerHeader() (ResourceHeader, error) { 705 return p.resourceHeader(sectionAnswers) 706} 707 708// Answer parses a single Answer Resource. 709func (p *Parser) Answer() (Resource, error) { 710 return p.resource(sectionAnswers) 711} 712 713// AllAnswers parses all Answer Resources. 714func (p *Parser) AllAnswers() ([]Resource, error) { 715 // The most common query is for A/AAAA, which usually returns 716 // a handful of IPs. 717 // 718 // Pre-allocate up to a certain limit, since p.header is 719 // untrusted data. 720 n := int(p.header.answers) 721 if n > 20 { 722 n = 20 723 } 724 as := make([]Resource, 0, n) 725 for { 726 a, err := p.Answer() 727 if err == ErrSectionDone { 728 return as, nil 729 } 730 if err != nil { 731 return nil, err 732 } 733 as = append(as, a) 734 } 735} 736 737// SkipAnswer skips a single Answer Resource. 738func (p *Parser) SkipAnswer() error { 739 return p.skipResource(sectionAnswers) 740} 741 742// SkipAllAnswers skips all Answer Resources. 743func (p *Parser) SkipAllAnswers() error { 744 for { 745 if err := p.SkipAnswer(); err == ErrSectionDone { 746 return nil 747 } else if err != nil { 748 return err 749 } 750 } 751} 752 753// AuthorityHeader parses a single Authority ResourceHeader. 754func (p *Parser) AuthorityHeader() (ResourceHeader, error) { 755 return p.resourceHeader(sectionAuthorities) 756} 757 758// Authority parses a single Authority Resource. 759func (p *Parser) Authority() (Resource, error) { 760 return p.resource(sectionAuthorities) 761} 762 763// AllAuthorities parses all Authority Resources. 764func (p *Parser) AllAuthorities() ([]Resource, error) { 765 // Authorities contains SOA in case of NXDOMAIN and friends, 766 // otherwise it is empty. 767 // 768 // Pre-allocate up to a certain limit, since p.header is 769 // untrusted data. 770 n := int(p.header.authorities) 771 if n > 10 { 772 n = 10 773 } 774 as := make([]Resource, 0, n) 775 for { 776 a, err := p.Authority() 777 if err == ErrSectionDone { 778 return as, nil 779 } 780 if err != nil { 781 return nil, err 782 } 783 as = append(as, a) 784 } 785} 786 787// SkipAuthority skips a single Authority Resource. 788func (p *Parser) SkipAuthority() error { 789 return p.skipResource(sectionAuthorities) 790} 791 792// SkipAllAuthorities skips all Authority Resources. 793func (p *Parser) SkipAllAuthorities() error { 794 for { 795 if err := p.SkipAuthority(); err == ErrSectionDone { 796 return nil 797 } else if err != nil { 798 return err 799 } 800 } 801} 802 803// AdditionalHeader parses a single Additional ResourceHeader. 804func (p *Parser) AdditionalHeader() (ResourceHeader, error) { 805 return p.resourceHeader(sectionAdditionals) 806} 807 808// Additional parses a single Additional Resource. 809func (p *Parser) Additional() (Resource, error) { 810 return p.resource(sectionAdditionals) 811} 812 813// AllAdditionals parses all Additional Resources. 814func (p *Parser) AllAdditionals() ([]Resource, error) { 815 // Additionals usually contain OPT, and sometimes A/AAAA 816 // glue records. 817 // 818 // Pre-allocate up to a certain limit, since p.header is 819 // untrusted data. 820 n := int(p.header.additionals) 821 if n > 10 { 822 n = 10 823 } 824 as := make([]Resource, 0, n) 825 for { 826 a, err := p.Additional() 827 if err == ErrSectionDone { 828 return as, nil 829 } 830 if err != nil { 831 return nil, err 832 } 833 as = append(as, a) 834 } 835} 836 837// SkipAdditional skips a single Additional Resource. 838func (p *Parser) SkipAdditional() error { 839 return p.skipResource(sectionAdditionals) 840} 841 842// SkipAllAdditionals skips all Additional Resources. 843func (p *Parser) SkipAllAdditionals() error { 844 for { 845 if err := p.SkipAdditional(); err == ErrSectionDone { 846 return nil 847 } else if err != nil { 848 return err 849 } 850 } 851} 852 853// CNAMEResource parses a single CNAMEResource. 854// 855// One of the XXXHeader methods must have been called before calling this 856// method. 857func (p *Parser) CNAMEResource() (CNAMEResource, error) { 858 if !p.resHeaderValid || p.resHeader.Type != TypeCNAME { 859 return CNAMEResource{}, ErrNotStarted 860 } 861 r, err := unpackCNAMEResource(p.msg, p.off) 862 if err != nil { 863 return CNAMEResource{}, err 864 } 865 p.off += int(p.resHeader.Length) 866 p.resHeaderValid = false 867 p.index++ 868 return r, nil 869} 870 871// MXResource parses a single MXResource. 872// 873// One of the XXXHeader methods must have been called before calling this 874// method. 875func (p *Parser) MXResource() (MXResource, error) { 876 if !p.resHeaderValid || p.resHeader.Type != TypeMX { 877 return MXResource{}, ErrNotStarted 878 } 879 r, err := unpackMXResource(p.msg, p.off) 880 if err != nil { 881 return MXResource{}, err 882 } 883 p.off += int(p.resHeader.Length) 884 p.resHeaderValid = false 885 p.index++ 886 return r, nil 887} 888 889// NSResource parses a single NSResource. 890// 891// One of the XXXHeader methods must have been called before calling this 892// method. 893func (p *Parser) NSResource() (NSResource, error) { 894 if !p.resHeaderValid || p.resHeader.Type != TypeNS { 895 return NSResource{}, ErrNotStarted 896 } 897 r, err := unpackNSResource(p.msg, p.off) 898 if err != nil { 899 return NSResource{}, err 900 } 901 p.off += int(p.resHeader.Length) 902 p.resHeaderValid = false 903 p.index++ 904 return r, nil 905} 906 907// PTRResource parses a single PTRResource. 908// 909// One of the XXXHeader methods must have been called before calling this 910// method. 911func (p *Parser) PTRResource() (PTRResource, error) { 912 if !p.resHeaderValid || p.resHeader.Type != TypePTR { 913 return PTRResource{}, ErrNotStarted 914 } 915 r, err := unpackPTRResource(p.msg, p.off) 916 if err != nil { 917 return PTRResource{}, err 918 } 919 p.off += int(p.resHeader.Length) 920 p.resHeaderValid = false 921 p.index++ 922 return r, nil 923} 924 925// SOAResource parses a single SOAResource. 926// 927// One of the XXXHeader methods must have been called before calling this 928// method. 929func (p *Parser) SOAResource() (SOAResource, error) { 930 if !p.resHeaderValid || p.resHeader.Type != TypeSOA { 931 return SOAResource{}, ErrNotStarted 932 } 933 r, err := unpackSOAResource(p.msg, p.off) 934 if err != nil { 935 return SOAResource{}, err 936 } 937 p.off += int(p.resHeader.Length) 938 p.resHeaderValid = false 939 p.index++ 940 return r, nil 941} 942 943// TXTResource parses a single TXTResource. 944// 945// One of the XXXHeader methods must have been called before calling this 946// method. 947func (p *Parser) TXTResource() (TXTResource, error) { 948 if !p.resHeaderValid || p.resHeader.Type != TypeTXT { 949 return TXTResource{}, ErrNotStarted 950 } 951 r, err := unpackTXTResource(p.msg, p.off, p.resHeader.Length) 952 if err != nil { 953 return TXTResource{}, err 954 } 955 p.off += int(p.resHeader.Length) 956 p.resHeaderValid = false 957 p.index++ 958 return r, nil 959} 960 961// SRVResource parses a single SRVResource. 962// 963// One of the XXXHeader methods must have been called before calling this 964// method. 965func (p *Parser) SRVResource() (SRVResource, error) { 966 if !p.resHeaderValid || p.resHeader.Type != TypeSRV { 967 return SRVResource{}, ErrNotStarted 968 } 969 r, err := unpackSRVResource(p.msg, p.off) 970 if err != nil { 971 return SRVResource{}, err 972 } 973 p.off += int(p.resHeader.Length) 974 p.resHeaderValid = false 975 p.index++ 976 return r, nil 977} 978 979// AResource parses a single AResource. 980// 981// One of the XXXHeader methods must have been called before calling this 982// method. 983func (p *Parser) AResource() (AResource, error) { 984 if !p.resHeaderValid || p.resHeader.Type != TypeA { 985 return AResource{}, ErrNotStarted 986 } 987 r, err := unpackAResource(p.msg, p.off) 988 if err != nil { 989 return AResource{}, err 990 } 991 p.off += int(p.resHeader.Length) 992 p.resHeaderValid = false 993 p.index++ 994 return r, nil 995} 996 997// AAAAResource parses a single AAAAResource. 998// 999// One of the XXXHeader methods must have been called before calling this 1000// method. 1001func (p *Parser) AAAAResource() (AAAAResource, error) { 1002 if !p.resHeaderValid || p.resHeader.Type != TypeAAAA { 1003 return AAAAResource{}, ErrNotStarted 1004 } 1005 r, err := unpackAAAAResource(p.msg, p.off) 1006 if err != nil { 1007 return AAAAResource{}, err 1008 } 1009 p.off += int(p.resHeader.Length) 1010 p.resHeaderValid = false 1011 p.index++ 1012 return r, nil 1013} 1014 1015// OPTResource parses a single OPTResource. 1016// 1017// One of the XXXHeader methods must have been called before calling this 1018// method. 1019func (p *Parser) OPTResource() (OPTResource, error) { 1020 if !p.resHeaderValid || p.resHeader.Type != TypeOPT { 1021 return OPTResource{}, ErrNotStarted 1022 } 1023 r, err := unpackOPTResource(p.msg, p.off, p.resHeader.Length) 1024 if err != nil { 1025 return OPTResource{}, err 1026 } 1027 p.off += int(p.resHeader.Length) 1028 p.resHeaderValid = false 1029 p.index++ 1030 return r, nil 1031} 1032 1033// SVCBResource parses a single SVCBResource. 1034// 1035// One of the XXXHeader methods must have been called before calling this 1036// method. 1037func (p *Parser) SVCBResource() (SVCBResource, error) { 1038 if !p.resHeaderValid || p.resHeader.Type != TypeSVCB { 1039 return SVCBResource{}, ErrNotStarted 1040 } 1041 r, err := unpackSVCBResource(p.msg, p.off, p.resHeader.Length) 1042 if err != nil { 1043 return SVCBResource{}, err 1044 } 1045 p.off += int(p.resHeader.Length) 1046 p.resHeaderValid = false 1047 p.index++ 1048 return r, nil 1049} 1050 1051// HTTPSResource parses a single HTTPSResource. 1052// 1053// One of the XXXHeader methods must have been called before calling this 1054// method. 1055func (p *Parser) HTTPSResource() (HTTPSResource, error) { 1056 if !p.resHeaderValid || p.resHeader.Type != TypeHTTPS { 1057 return HTTPSResource{}, ErrNotStarted 1058 } 1059 r, err := unpackHTTPSResource(p.msg, p.off, p.resHeader.Length) 1060 if err != nil { 1061 return HTTPSResource{}, err 1062 } 1063 p.off += int(p.resHeader.Length) 1064 p.resHeaderValid = false 1065 p.index++ 1066 return r, nil 1067} 1068 1069// Unpack parses a full Message. 1070func (m *Message) Unpack(msg []byte) error { 1071 var p Parser 1072 var err error 1073 if m.Header, err = p.Start(msg); err != nil { 1074 return err 1075 } 1076 if m.Questions, err = p.AllQuestions(); err != nil { 1077 return err 1078 } 1079 if m.Answers, err = p.AllAnswers(); err != nil { 1080 return err 1081 } 1082 if m.Authorities, err = p.AllAuthorities(); err != nil { 1083 return err 1084 } 1085 if m.Additionals, err = p.AllAdditionals(); err != nil { 1086 return err 1087 } 1088 return nil 1089} 1090 1091// Pack packs a full Message. 1092func (m *Message) Pack() ([]byte, error) { 1093 return m.AppendPack(make([]byte, 0, packStartingCap)) 1094} 1095 1096// AppendPack is like Pack but appends the full Message to b and returns the 1097// extended buffer. 1098func (m *Message) AppendPack(b []byte) ([]byte, error) { 1099 // Validate the lengths. It is very unlikely that anyone will try to 1100 // pack more than 65535 of any particular type, but it is possible and 1101 // we should fail gracefully. 1102 if len(m.Questions) > int(^uint16(0)) { 1103 return nil, errTooManyQuestions 1104 } 1105 if len(m.Answers) > int(^uint16(0)) { 1106 return nil, errTooManyAnswers 1107 } 1108 if len(m.Authorities) > int(^uint16(0)) { 1109 return nil, errTooManyAuthorities 1110 } 1111 if len(m.Additionals) > int(^uint16(0)) { 1112 return nil, errTooManyAdditionals 1113 } 1114 1115 var h header 1116 h.id, h.bits = m.Header.pack() 1117 1118 h.questions = uint16(len(m.Questions)) 1119 h.answers = uint16(len(m.Answers)) 1120 h.authorities = uint16(len(m.Authorities)) 1121 h.additionals = uint16(len(m.Additionals)) 1122 1123 compressionOff := len(b) 1124 msg := h.pack(b) 1125 1126 // RFC 1035 allows (but does not require) compression for packing. RFC 1127 // 1035 requires unpacking implementations to support compression, so 1128 // unconditionally enabling it is fine. 1129 // 1130 // DNS lookups are typically done over UDP, and RFC 1035 states that UDP 1131 // DNS messages can be a maximum of 512 bytes long. Without compression, 1132 // many DNS response messages are over this limit, so enabling 1133 // compression will help ensure compliance. 1134 compression := map[string]int{} 1135 1136 for i := range m.Questions { 1137 var err error 1138 if msg, err = m.Questions[i].pack(msg, compression, compressionOff); err != nil { 1139 return nil, &nestedError{"packing Question", err} 1140 } 1141 } 1142 for i := range m.Answers { 1143 var err error 1144 if msg, err = m.Answers[i].pack(msg, compression, compressionOff); err != nil { 1145 return nil, &nestedError{"packing Answer", err} 1146 } 1147 } 1148 for i := range m.Authorities { 1149 var err error 1150 if msg, err = m.Authorities[i].pack(msg, compression, compressionOff); err != nil { 1151 return nil, &nestedError{"packing Authority", err} 1152 } 1153 } 1154 for i := range m.Additionals { 1155 var err error 1156 if msg, err = m.Additionals[i].pack(msg, compression, compressionOff); err != nil { 1157 return nil, &nestedError{"packing Additional", err} 1158 } 1159 } 1160 1161 return msg, nil 1162} 1163 1164// GoString implements fmt.GoStringer.GoString. 1165func (m *Message) GoString() string { 1166 s := "dnsmessage.Message{Header: " + m.Header.GoString() + ", " + 1167 "Questions: []dnsmessage.Question{" 1168 if len(m.Questions) > 0 { 1169 s += m.Questions[0].GoString() 1170 for _, q := range m.Questions[1:] { 1171 s += ", " + q.GoString() 1172 } 1173 } 1174 s += "}, Answers: []dnsmessage.Resource{" 1175 if len(m.Answers) > 0 { 1176 s += m.Answers[0].GoString() 1177 for _, a := range m.Answers[1:] { 1178 s += ", " + a.GoString() 1179 } 1180 } 1181 s += "}, Authorities: []dnsmessage.Resource{" 1182 if len(m.Authorities) > 0 { 1183 s += m.Authorities[0].GoString() 1184 for _, a := range m.Authorities[1:] { 1185 s += ", " + a.GoString() 1186 } 1187 } 1188 s += "}, Additionals: []dnsmessage.Resource{" 1189 if len(m.Additionals) > 0 { 1190 s += m.Additionals[0].GoString() 1191 for _, a := range m.Additionals[1:] { 1192 s += ", " + a.GoString() 1193 } 1194 } 1195 return s + "}}" 1196} 1197 1198// A Builder allows incrementally packing a DNS message. 1199// 1200// Example usage: 1201// buf := make([]byte, 2, 514) 1202// b := NewBuilder(buf, Header{...}) 1203// b.EnableCompression() 1204// // Optionally start a section and add things to that section. 1205// // Repeat adding sections as necessary. 1206// buf, err := b.Finish() 1207// // If err is nil, buf[2:] will contain the built bytes. 1208type Builder struct { 1209 // msg is the storage for the message being built. 1210 msg []byte 1211 1212 // section keeps track of the current section being built. 1213 section section 1214 1215 // header keeps track of what should go in the header when Finish is 1216 // called. 1217 header header 1218 1219 // start is the starting index of the bytes allocated in msg for header. 1220 start int 1221 1222 // compression is a mapping from name suffixes to their starting index 1223 // in msg. 1224 compression map[string]int 1225} 1226 1227// NewBuilder creates a new builder with compression disabled. 1228// 1229// Note: Most users will want to immediately enable compression with the 1230// EnableCompression method. See that method's comment for why you may or may 1231// not want to enable compression. 1232// 1233// The DNS message is appended to the provided initial buffer buf (which may be 1234// nil) as it is built. The final message is returned by the (*Builder).Finish 1235// method, which may return the same underlying array if there was sufficient 1236// capacity in the slice. 1237func NewBuilder(buf []byte, h Header) Builder { 1238 if buf == nil { 1239 buf = make([]byte, 0, packStartingCap) 1240 } 1241 b := Builder{msg: buf, start: len(buf)} 1242 b.header.id, b.header.bits = h.pack() 1243 var hb [headerLen]byte 1244 b.msg = append(b.msg, hb[:]...) 1245 b.section = sectionHeader 1246 return b 1247} 1248 1249// EnableCompression enables compression in the Builder. 1250// 1251// Leaving compression disabled avoids compression related allocations, but can 1252// result in larger message sizes. Be careful with this mode as it can cause 1253// messages to exceed the UDP size limit. 1254// 1255// According to RFC 1035, section 4.1.4, the use of compression is optional, but 1256// all implementations must accept both compressed and uncompressed DNS 1257// messages. 1258// 1259// Compression should be enabled before any sections are added for best results. 1260func (b *Builder) EnableCompression() { 1261 b.compression = map[string]int{} 1262} 1263 1264func (b *Builder) startCheck(s section) error { 1265 if b.section <= sectionNotStarted { 1266 return ErrNotStarted 1267 } 1268 if b.section > s { 1269 return ErrSectionDone 1270 } 1271 return nil 1272} 1273 1274// StartQuestions prepares the builder for packing Questions. 1275func (b *Builder) StartQuestions() error { 1276 if err := b.startCheck(sectionQuestions); err != nil { 1277 return err 1278 } 1279 b.section = sectionQuestions 1280 return nil 1281} 1282 1283// StartAnswers prepares the builder for packing Answers. 1284func (b *Builder) StartAnswers() error { 1285 if err := b.startCheck(sectionAnswers); err != nil { 1286 return err 1287 } 1288 b.section = sectionAnswers 1289 return nil 1290} 1291 1292// StartAuthorities prepares the builder for packing Authorities. 1293func (b *Builder) StartAuthorities() error { 1294 if err := b.startCheck(sectionAuthorities); err != nil { 1295 return err 1296 } 1297 b.section = sectionAuthorities 1298 return nil 1299} 1300 1301// StartAdditionals prepares the builder for packing Additionals. 1302func (b *Builder) StartAdditionals() error { 1303 if err := b.startCheck(sectionAdditionals); err != nil { 1304 return err 1305 } 1306 b.section = sectionAdditionals 1307 return nil 1308} 1309 1310func (b *Builder) incrementSectionCount() error { 1311 var count *uint16 1312 var err error 1313 switch b.section { 1314 case sectionQuestions: 1315 count = &b.header.questions 1316 err = errTooManyQuestions 1317 case sectionAnswers: 1318 count = &b.header.answers 1319 err = errTooManyAnswers 1320 case sectionAuthorities: 1321 count = &b.header.authorities 1322 err = errTooManyAuthorities 1323 case sectionAdditionals: 1324 count = &b.header.additionals 1325 err = errTooManyAdditionals 1326 } 1327 if *count == ^uint16(0) { 1328 return err 1329 } 1330 *count++ 1331 return nil 1332} 1333 1334// Question adds a single Question. 1335func (b *Builder) Question(q Question) error { 1336 if b.section < sectionQuestions { 1337 return ErrNotStarted 1338 } 1339 if b.section > sectionQuestions { 1340 return ErrSectionDone 1341 } 1342 msg, err := q.pack(b.msg, b.compression, b.start) 1343 if err != nil { 1344 return err 1345 } 1346 if err := b.incrementSectionCount(); err != nil { 1347 return err 1348 } 1349 b.msg = msg 1350 return nil 1351} 1352 1353func (b *Builder) checkResourceSection() error { 1354 if b.section < sectionAnswers { 1355 return ErrNotStarted 1356 } 1357 if b.section > sectionAdditionals { 1358 return ErrSectionDone 1359 } 1360 return nil 1361} 1362 1363// CNAMEResource adds a single CNAMEResource. 1364func (b *Builder) CNAMEResource(h ResourceHeader, r CNAMEResource) error { 1365 if err := b.checkResourceSection(); err != nil { 1366 return err 1367 } 1368 h.Type = r.realType() 1369 msg, lenOff, err := h.pack(b.msg, b.compression, b.start) 1370 if err != nil { 1371 return &nestedError{"ResourceHeader", err} 1372 } 1373 preLen := len(msg) 1374 if msg, err = r.pack(msg, b.compression, b.start); err != nil { 1375 return &nestedError{"CNAMEResource body", err} 1376 } 1377 if err := h.fixLen(msg, lenOff, preLen); err != nil { 1378 return err 1379 } 1380 if err := b.incrementSectionCount(); err != nil { 1381 return err 1382 } 1383 b.msg = msg 1384 return nil 1385} 1386 1387// MXResource adds a single MXResource. 1388func (b *Builder) MXResource(h ResourceHeader, r MXResource) error { 1389 if err := b.checkResourceSection(); err != nil { 1390 return err 1391 } 1392 h.Type = r.realType() 1393 msg, lenOff, err := h.pack(b.msg, b.compression, b.start) 1394 if err != nil { 1395 return &nestedError{"ResourceHeader", err} 1396 } 1397 preLen := len(msg) 1398 if msg, err = r.pack(msg, b.compression, b.start); err != nil { 1399 return &nestedError{"MXResource body", err} 1400 } 1401 if err := h.fixLen(msg, lenOff, preLen); err != nil { 1402 return err 1403 } 1404 if err := b.incrementSectionCount(); err != nil { 1405 return err 1406 } 1407 b.msg = msg 1408 return nil 1409} 1410 1411// NSResource adds a single NSResource. 1412func (b *Builder) NSResource(h ResourceHeader, r NSResource) error { 1413 if err := b.checkResourceSection(); err != nil { 1414 return err 1415 } 1416 h.Type = r.realType() 1417 msg, lenOff, err := h.pack(b.msg, b.compression, b.start) 1418 if err != nil { 1419 return &nestedError{"ResourceHeader", err} 1420 } 1421 preLen := len(msg) 1422 if msg, err = r.pack(msg, b.compression, b.start); err != nil { 1423 return &nestedError{"NSResource body", err} 1424 } 1425 if err := h.fixLen(msg, lenOff, preLen); err != nil { 1426 return err 1427 } 1428 if err := b.incrementSectionCount(); err != nil { 1429 return err 1430 } 1431 b.msg = msg 1432 return nil 1433} 1434 1435// PTRResource adds a single PTRResource. 1436func (b *Builder) PTRResource(h ResourceHeader, r PTRResource) error { 1437 if err := b.checkResourceSection(); err != nil { 1438 return err 1439 } 1440 h.Type = r.realType() 1441 msg, lenOff, err := h.pack(b.msg, b.compression, b.start) 1442 if err != nil { 1443 return &nestedError{"ResourceHeader", err} 1444 } 1445 preLen := len(msg) 1446 if msg, err = r.pack(msg, b.compression, b.start); err != nil { 1447 return &nestedError{"PTRResource body", err} 1448 } 1449 if err := h.fixLen(msg, lenOff, preLen); err != nil { 1450 return err 1451 } 1452 if err := b.incrementSectionCount(); err != nil { 1453 return err 1454 } 1455 b.msg = msg 1456 return nil 1457} 1458 1459// SOAResource adds a single SOAResource. 1460func (b *Builder) SOAResource(h ResourceHeader, r SOAResource) error { 1461 if err := b.checkResourceSection(); err != nil { 1462 return err 1463 } 1464 h.Type = r.realType() 1465 msg, lenOff, err := h.pack(b.msg, b.compression, b.start) 1466 if err != nil { 1467 return &nestedError{"ResourceHeader", err} 1468 } 1469 preLen := len(msg) 1470 if msg, err = r.pack(msg, b.compression, b.start); err != nil { 1471 return &nestedError{"SOAResource body", err} 1472 } 1473 if err := h.fixLen(msg, lenOff, preLen); err != nil { 1474 return err 1475 } 1476 if err := b.incrementSectionCount(); err != nil { 1477 return err 1478 } 1479 b.msg = msg 1480 return nil 1481} 1482 1483// TXTResource adds a single TXTResource. 1484func (b *Builder) TXTResource(h ResourceHeader, r TXTResource) error { 1485 if err := b.checkResourceSection(); err != nil { 1486 return err 1487 } 1488 h.Type = r.realType() 1489 msg, lenOff, err := h.pack(b.msg, b.compression, b.start) 1490 if err != nil { 1491 return &nestedError{"ResourceHeader", err} 1492 } 1493 preLen := len(msg) 1494 if msg, err = r.pack(msg, b.compression, b.start); err != nil { 1495 return &nestedError{"TXTResource body", err} 1496 } 1497 if err := h.fixLen(msg, lenOff, preLen); err != nil { 1498 return err 1499 } 1500 if err := b.incrementSectionCount(); err != nil { 1501 return err 1502 } 1503 b.msg = msg 1504 return nil 1505} 1506 1507// SRVResource adds a single SRVResource. 1508func (b *Builder) SRVResource(h ResourceHeader, r SRVResource) error { 1509 if err := b.checkResourceSection(); err != nil { 1510 return err 1511 } 1512 h.Type = r.realType() 1513 msg, lenOff, err := h.pack(b.msg, b.compression, b.start) 1514 if err != nil { 1515 return &nestedError{"ResourceHeader", err} 1516 } 1517 preLen := len(msg) 1518 if msg, err = r.pack(msg, b.compression, b.start); err != nil { 1519 return &nestedError{"SRVResource body", err} 1520 } 1521 if err := h.fixLen(msg, lenOff, preLen); err != nil { 1522 return err 1523 } 1524 if err := b.incrementSectionCount(); err != nil { 1525 return err 1526 } 1527 b.msg = msg 1528 return nil 1529} 1530 1531// AResource adds a single AResource. 1532func (b *Builder) AResource(h ResourceHeader, r AResource) error { 1533 if err := b.checkResourceSection(); err != nil { 1534 return err 1535 } 1536 h.Type = r.realType() 1537 msg, lenOff, err := h.pack(b.msg, b.compression, b.start) 1538 if err != nil { 1539 return &nestedError{"ResourceHeader", err} 1540 } 1541 preLen := len(msg) 1542 if msg, err = r.pack(msg, b.compression, b.start); err != nil { 1543 return &nestedError{"AResource body", err} 1544 } 1545 if err := h.fixLen(msg, lenOff, preLen); err != nil { 1546 return err 1547 } 1548 if err := b.incrementSectionCount(); err != nil { 1549 return err 1550 } 1551 b.msg = msg 1552 return nil 1553} 1554 1555// AAAAResource adds a single AAAAResource. 1556func (b *Builder) AAAAResource(h ResourceHeader, r AAAAResource) error { 1557 if err := b.checkResourceSection(); err != nil { 1558 return err 1559 } 1560 h.Type = r.realType() 1561 msg, lenOff, err := h.pack(b.msg, b.compression, b.start) 1562 if err != nil { 1563 return &nestedError{"ResourceHeader", err} 1564 } 1565 preLen := len(msg) 1566 if msg, err = r.pack(msg, b.compression, b.start); err != nil { 1567 return &nestedError{"AAAAResource body", err} 1568 } 1569 if err := h.fixLen(msg, lenOff, preLen); err != nil { 1570 return err 1571 } 1572 if err := b.incrementSectionCount(); err != nil { 1573 return err 1574 } 1575 b.msg = msg 1576 return nil 1577} 1578 1579// OPTResource adds a single OPTResource. 1580func (b *Builder) OPTResource(h ResourceHeader, r OPTResource) error { 1581 if err := b.checkResourceSection(); err != nil { 1582 return err 1583 } 1584 h.Type = r.realType() 1585 msg, lenOff, err := h.pack(b.msg, b.compression, b.start) 1586 if err != nil { 1587 return &nestedError{"ResourceHeader", err} 1588 } 1589 preLen := len(msg) 1590 if msg, err = r.pack(msg, b.compression, b.start); err != nil { 1591 return &nestedError{"OPTResource body", err} 1592 } 1593 if err := h.fixLen(msg, lenOff, preLen); err != nil { 1594 return err 1595 } 1596 if err := b.incrementSectionCount(); err != nil { 1597 return err 1598 } 1599 b.msg = msg 1600 return nil 1601} 1602 1603// Finish ends message building and generates a binary message. 1604func (b *Builder) Finish() ([]byte, error) { 1605 if b.section < sectionHeader { 1606 return nil, ErrNotStarted 1607 } 1608 b.section = sectionDone 1609 // Space for the header was allocated in NewBuilder. 1610 b.header.pack(b.msg[b.start:b.start]) 1611 return b.msg, nil 1612} 1613 1614// A ResourceHeader is the header of a DNS resource record. There are 1615// many types of DNS resource records, but they all share the same header. 1616type ResourceHeader struct { 1617 // Name is the domain name for which this resource record pertains. 1618 Name Name 1619 1620 // Type is the type of DNS resource record. 1621 // 1622 // This field will be set automatically during packing. 1623 Type Type 1624 1625 // Class is the class of network to which this DNS resource record 1626 // pertains. 1627 Class Class 1628 1629 // TTL is the length of time (measured in seconds) which this resource 1630 // record is valid for (time to live). All Resources in a set should 1631 // have the same TTL (RFC 2181 Section 5.2). 1632 TTL uint32 1633 1634 // Length is the length of data in the resource record after the header. 1635 // 1636 // This field will be set automatically during packing. 1637 Length uint16 1638} 1639 1640// GoString implements fmt.GoStringer.GoString. 1641func (h *ResourceHeader) GoString() string { 1642 return "dnsmessage.ResourceHeader{" + 1643 "Name: " + h.Name.GoString() + ", " + 1644 "Type: " + h.Type.GoString() + ", " + 1645 "Class: " + h.Class.GoString() + ", " + 1646 "TTL: " + printUint32(h.TTL) + ", " + 1647 "Length: " + printUint16(h.Length) + "}" 1648} 1649 1650// pack appends the wire format of the ResourceHeader to oldMsg. 1651// 1652// lenOff is the offset in msg where the Length field was packed. 1653func (h *ResourceHeader) pack(oldMsg []byte, compression map[string]int, compressionOff int) (msg []byte, lenOff int, err error) { 1654 msg = oldMsg 1655 if msg, err = h.Name.pack(msg, compression, compressionOff); err != nil { 1656 return oldMsg, 0, &nestedError{"Name", err} 1657 } 1658 msg = packType(msg, h.Type) 1659 msg = packClass(msg, h.Class) 1660 msg = packUint32(msg, h.TTL) 1661 lenOff = len(msg) 1662 msg = packUint16(msg, h.Length) 1663 return msg, lenOff, nil 1664} 1665 1666func (h *ResourceHeader) unpack(msg []byte, off int) (int, error) { 1667 newOff := off 1668 var err error 1669 if newOff, err = h.Name.unpack(msg, newOff); err != nil { 1670 return off, &nestedError{"Name", err} 1671 } 1672 if h.Type, newOff, err = unpackType(msg, newOff); err != nil { 1673 return off, &nestedError{"Type", err} 1674 } 1675 if h.Class, newOff, err = unpackClass(msg, newOff); err != nil { 1676 return off, &nestedError{"Class", err} 1677 } 1678 if h.TTL, newOff, err = unpackUint32(msg, newOff); err != nil { 1679 return off, &nestedError{"TTL", err} 1680 } 1681 if h.Length, newOff, err = unpackUint16(msg, newOff); err != nil { 1682 return off, &nestedError{"Length", err} 1683 } 1684 return newOff, nil 1685} 1686 1687// fixLen updates a packed ResourceHeader to include the length of the 1688// ResourceBody. 1689// 1690// lenOff is the offset of the ResourceHeader.Length field in msg. 1691// 1692// preLen is the length that msg was before the ResourceBody was packed. 1693func (h *ResourceHeader) fixLen(msg []byte, lenOff int, preLen int) error { 1694 conLen := len(msg) - preLen 1695 if conLen > int(^uint16(0)) { 1696 return errResTooLong 1697 } 1698 1699 // Fill in the length now that we know how long the content is. 1700 packUint16(msg[lenOff:lenOff], uint16(conLen)) 1701 h.Length = uint16(conLen) 1702 1703 return nil 1704} 1705 1706// EDNS(0) wire constants. 1707const ( 1708 edns0Version = 0 1709 1710 edns0DNSSECOK = 0x00008000 1711 ednsVersionMask = 0x00ff0000 1712 edns0DNSSECOKMask = 0x00ff8000 1713) 1714 1715// SetEDNS0 configures h for EDNS(0). 1716// 1717// The provided extRCode must be an extedned RCode. 1718func (h *ResourceHeader) SetEDNS0(udpPayloadLen int, extRCode RCode, dnssecOK bool) error { 1719 h.Name = Name{Data: [nameLen]byte{'.'}, Length: 1} // RFC 6891 section 6.1.2 1720 h.Type = TypeOPT 1721 h.Class = Class(udpPayloadLen) 1722 h.TTL = uint32(extRCode) >> 4 << 24 1723 if dnssecOK { 1724 h.TTL |= edns0DNSSECOK 1725 } 1726 return nil 1727} 1728 1729// DNSSECAllowed reports whether the DNSSEC OK bit is set. 1730func (h *ResourceHeader) DNSSECAllowed() bool { 1731 return h.TTL&edns0DNSSECOKMask == edns0DNSSECOK // RFC 6891 section 6.1.3 1732} 1733 1734// ExtendedRCode returns an extended RCode. 1735// 1736// The provided rcode must be the RCode in DNS message header. 1737func (h *ResourceHeader) ExtendedRCode(rcode RCode) RCode { 1738 if h.TTL&ednsVersionMask == edns0Version { // RFC 6891 section 6.1.3 1739 return RCode(h.TTL>>24<<4) | rcode 1740 } 1741 return rcode 1742} 1743 1744func skipResource(msg []byte, off int) (int, error) { 1745 newOff, err := skipName(msg, off) 1746 if err != nil { 1747 return off, &nestedError{"Name", err} 1748 } 1749 if newOff, err = skipType(msg, newOff); err != nil { 1750 return off, &nestedError{"Type", err} 1751 } 1752 if newOff, err = skipClass(msg, newOff); err != nil { 1753 return off, &nestedError{"Class", err} 1754 } 1755 if newOff, err = skipUint32(msg, newOff); err != nil { 1756 return off, &nestedError{"TTL", err} 1757 } 1758 length, newOff, err := unpackUint16(msg, newOff) 1759 if err != nil { 1760 return off, &nestedError{"Length", err} 1761 } 1762 if newOff += int(length); newOff > len(msg) { 1763 return off, errResourceLen 1764 } 1765 return newOff, nil 1766} 1767 1768// packUint16 appends the wire format of field to msg. 1769func packUint16(msg []byte, field uint16) []byte { 1770 return append(msg, byte(field>>8), byte(field)) 1771} 1772 1773func unpackUint16(msg []byte, off int) (uint16, int, error) { 1774 if off+uint16Len > len(msg) { 1775 return 0, off, errBaseLen 1776 } 1777 return uint16(msg[off])<<8 | uint16(msg[off+1]), off + uint16Len, nil 1778} 1779 1780func skipUint16(msg []byte, off int) (int, error) { 1781 if off+uint16Len > len(msg) { 1782 return off, errBaseLen 1783 } 1784 return off + uint16Len, nil 1785} 1786 1787// packType appends the wire format of field to msg. 1788func packType(msg []byte, field Type) []byte { 1789 return packUint16(msg, uint16(field)) 1790} 1791 1792func unpackType(msg []byte, off int) (Type, int, error) { 1793 t, o, err := unpackUint16(msg, off) 1794 return Type(t), o, err 1795} 1796 1797func skipType(msg []byte, off int) (int, error) { 1798 return skipUint16(msg, off) 1799} 1800 1801// packClass appends the wire format of field to msg. 1802func packClass(msg []byte, field Class) []byte { 1803 return packUint16(msg, uint16(field)) 1804} 1805 1806func unpackClass(msg []byte, off int) (Class, int, error) { 1807 c, o, err := unpackUint16(msg, off) 1808 return Class(c), o, err 1809} 1810 1811func skipClass(msg []byte, off int) (int, error) { 1812 return skipUint16(msg, off) 1813} 1814 1815// packUint32 appends the wire format of field to msg. 1816func packUint32(msg []byte, field uint32) []byte { 1817 return append( 1818 msg, 1819 byte(field>>24), 1820 byte(field>>16), 1821 byte(field>>8), 1822 byte(field), 1823 ) 1824} 1825 1826func unpackUint32(msg []byte, off int) (uint32, int, error) { 1827 if off+uint32Len > len(msg) { 1828 return 0, off, errBaseLen 1829 } 1830 v := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3]) 1831 return v, off + uint32Len, nil 1832} 1833 1834func skipUint32(msg []byte, off int) (int, error) { 1835 if off+uint32Len > len(msg) { 1836 return off, errBaseLen 1837 } 1838 return off + uint32Len, nil 1839} 1840 1841// packText appends the wire format of field to msg. 1842func packText(msg []byte, field string) ([]byte, error) { 1843 l := len(field) 1844 if l > 255 { 1845 return nil, errStringTooLong 1846 } 1847 msg = append(msg, byte(l)) 1848 msg = append(msg, field...) 1849 1850 return msg, nil 1851} 1852 1853func unpackText(msg []byte, off int) (string, int, error) { 1854 if off >= len(msg) { 1855 return "", off, errBaseLen 1856 } 1857 beginOff := off + 1 1858 endOff := beginOff + int(msg[off]) 1859 if endOff > len(msg) { 1860 return "", off, errCalcLen 1861 } 1862 return string(msg[beginOff:endOff]), endOff, nil 1863} 1864 1865func skipText(msg []byte, off int) (int, error) { 1866 if off >= len(msg) { 1867 return off, errBaseLen 1868 } 1869 endOff := off + 1 + int(msg[off]) 1870 if endOff > len(msg) { 1871 return off, errCalcLen 1872 } 1873 return endOff, nil 1874} 1875 1876// packBytes appends the wire format of field to msg. 1877func packBytes(msg []byte, field []byte) []byte { 1878 return append(msg, field...) 1879} 1880 1881func unpackBytes(msg []byte, off int, field []byte) (int, error) { 1882 newOff := off + len(field) 1883 if newOff > len(msg) { 1884 return off, errBaseLen 1885 } 1886 copy(field, msg[off:newOff]) 1887 return newOff, nil 1888} 1889 1890func skipBytes(msg []byte, off int, field []byte) (int, error) { 1891 newOff := off + len(field) 1892 if newOff > len(msg) { 1893 return off, errBaseLen 1894 } 1895 return newOff, nil 1896} 1897 1898const nameLen = 255 1899 1900// A Name is a non-encoded domain name. It is used instead of strings to avoid 1901// allocations. 1902type Name struct { 1903 Data [nameLen]byte 1904 Length uint8 1905} 1906 1907// NewName creates a new Name from a string. 1908func NewName(name string) (Name, error) { 1909 if len([]byte(name)) > nameLen { 1910 return Name{}, errCalcLen 1911 } 1912 n := Name{Length: uint8(len(name))} 1913 copy(n.Data[:], []byte(name)) 1914 return n, nil 1915} 1916 1917// MustNewName creates a new Name from a string and panics on error. 1918func MustNewName(name string) Name { 1919 n, err := NewName(name) 1920 if err != nil { 1921 panic("creating name: " + err.Error()) 1922 } 1923 return n 1924} 1925 1926// String implements fmt.Stringer.String. 1927func (n Name) String() string { 1928 return string(n.Data[:n.Length]) 1929} 1930 1931// GoString implements fmt.GoStringer.GoString. 1932func (n *Name) GoString() string { 1933 return `dnsmessage.MustNewName("` + printString(n.Data[:n.Length]) + `")` 1934} 1935 1936// pack appends the wire format of the Name to msg. 1937// 1938// Domain names are a sequence of counted strings split at the dots. They end 1939// with a zero-length string. Compression can be used to reuse domain suffixes. 1940// 1941// The compression map will be updated with new domain suffixes. If compression 1942// is nil, compression will not be used. 1943func (n *Name) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 1944 oldMsg := msg 1945 1946 // Add a trailing dot to canonicalize name. 1947 if n.Length == 0 || n.Data[n.Length-1] != '.' { 1948 return oldMsg, errNonCanonicalName 1949 } 1950 1951 // Allow root domain. 1952 if n.Data[0] == '.' && n.Length == 1 { 1953 return append(msg, 0), nil 1954 } 1955 1956 // Emit sequence of counted strings, chopping at dots. 1957 for i, begin := 0, 0; i < int(n.Length); i++ { 1958 // Check for the end of the segment. 1959 if n.Data[i] == '.' { 1960 // The two most significant bits have special meaning. 1961 // It isn't allowed for segments to be long enough to 1962 // need them. 1963 if i-begin >= 1<<6 { 1964 return oldMsg, errSegTooLong 1965 } 1966 1967 // Segments must have a non-zero length. 1968 if i-begin == 0 { 1969 return oldMsg, errZeroSegLen 1970 } 1971 1972 msg = append(msg, byte(i-begin)) 1973 1974 for j := begin; j < i; j++ { 1975 msg = append(msg, n.Data[j]) 1976 } 1977 1978 begin = i + 1 1979 continue 1980 } 1981 1982 // We can only compress domain suffixes starting with a new 1983 // segment. A pointer is two bytes with the two most significant 1984 // bits set to 1 to indicate that it is a pointer. 1985 if (i == 0 || n.Data[i-1] == '.') && compression != nil { 1986 if ptr, ok := compression[string(n.Data[i:])]; ok { 1987 // Hit. Emit a pointer instead of the rest of 1988 // the domain. 1989 return append(msg, byte(ptr>>8|0xC0), byte(ptr)), nil 1990 } 1991 1992 // Miss. Add the suffix to the compression table if the 1993 // offset can be stored in the available 14 bytes. 1994 if len(msg) <= int(^uint16(0)>>2) { 1995 compression[string(n.Data[i:])] = len(msg) - compressionOff 1996 } 1997 } 1998 } 1999 return append(msg, 0), nil 2000} 2001 2002// unpack unpacks a domain name. 2003func (n *Name) unpack(msg []byte, off int) (int, error) { 2004 return n.unpackCompressed(msg, off, true /* allowCompression */) 2005} 2006 2007func (n *Name) unpackCompressed(msg []byte, off int, allowCompression bool) (int, error) { 2008 // currOff is the current working offset. 2009 currOff := off 2010 2011 // newOff is the offset where the next record will start. Pointers lead 2012 // to data that belongs to other names and thus doesn't count towards to 2013 // the usage of this name. 2014 newOff := off 2015 2016 // ptr is the number of pointers followed. 2017 var ptr int 2018 2019 // Name is a slice representation of the name data. 2020 name := n.Data[:0] 2021 2022Loop: 2023 for { 2024 if currOff >= len(msg) { 2025 return off, errBaseLen 2026 } 2027 c := int(msg[currOff]) 2028 currOff++ 2029 switch c & 0xC0 { 2030 case 0x00: // String segment 2031 if c == 0x00 { 2032 // A zero length signals the end of the name. 2033 break Loop 2034 } 2035 endOff := currOff + c 2036 if endOff > len(msg) { 2037 return off, errCalcLen 2038 } 2039 name = append(name, msg[currOff:endOff]...) 2040 name = append(name, '.') 2041 currOff = endOff 2042 case 0xC0: // Pointer 2043 if !allowCompression { 2044 return off, errCompressedSRV 2045 } 2046 if currOff >= len(msg) { 2047 return off, errInvalidPtr 2048 } 2049 c1 := msg[currOff] 2050 currOff++ 2051 if ptr == 0 { 2052 newOff = currOff 2053 } 2054 // Don't follow too many pointers, maybe there's a loop. 2055 if ptr++; ptr > 10 { 2056 return off, errTooManyPtr 2057 } 2058 currOff = (c^0xC0)<<8 | int(c1) 2059 default: 2060 // Prefixes 0x80 and 0x40 are reserved. 2061 return off, errReserved 2062 } 2063 } 2064 if len(name) == 0 { 2065 name = append(name, '.') 2066 } 2067 if len(name) > len(n.Data) { 2068 return off, errCalcLen 2069 } 2070 n.Length = uint8(len(name)) 2071 if ptr == 0 { 2072 newOff = currOff 2073 } 2074 return newOff, nil 2075} 2076 2077func skipName(msg []byte, off int) (int, error) { 2078 // newOff is the offset where the next record will start. Pointers lead 2079 // to data that belongs to other names and thus doesn't count towards to 2080 // the usage of this name. 2081 newOff := off 2082 2083Loop: 2084 for { 2085 if newOff >= len(msg) { 2086 return off, errBaseLen 2087 } 2088 c := int(msg[newOff]) 2089 newOff++ 2090 switch c & 0xC0 { 2091 case 0x00: 2092 if c == 0x00 { 2093 // A zero length signals the end of the name. 2094 break Loop 2095 } 2096 // literal string 2097 newOff += c 2098 if newOff > len(msg) { 2099 return off, errCalcLen 2100 } 2101 case 0xC0: 2102 // Pointer to somewhere else in msg. 2103 2104 // Pointers are two bytes. 2105 newOff++ 2106 2107 // Don't follow the pointer as the data here has ended. 2108 break Loop 2109 default: 2110 // Prefixes 0x80 and 0x40 are reserved. 2111 return off, errReserved 2112 } 2113 } 2114 2115 return newOff, nil 2116} 2117 2118// A Question is a DNS query. 2119type Question struct { 2120 Name Name 2121 Type Type 2122 Class Class 2123} 2124 2125// pack appends the wire format of the Question to msg. 2126func (q *Question) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2127 msg, err := q.Name.pack(msg, compression, compressionOff) 2128 if err != nil { 2129 return msg, &nestedError{"Name", err} 2130 } 2131 msg = packType(msg, q.Type) 2132 return packClass(msg, q.Class), nil 2133} 2134 2135// GoString implements fmt.GoStringer.GoString. 2136func (q *Question) GoString() string { 2137 return "dnsmessage.Question{" + 2138 "Name: " + q.Name.GoString() + ", " + 2139 "Type: " + q.Type.GoString() + ", " + 2140 "Class: " + q.Class.GoString() + "}" 2141} 2142 2143func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody, int, error) { 2144 var ( 2145 r ResourceBody 2146 err error 2147 name string 2148 ) 2149 switch hdr.Type { 2150 case TypeA: 2151 var rb AResource 2152 rb, err = unpackAResource(msg, off) 2153 r = &rb 2154 name = "A" 2155 case TypeNS: 2156 var rb NSResource 2157 rb, err = unpackNSResource(msg, off) 2158 r = &rb 2159 name = "NS" 2160 case TypeCNAME: 2161 var rb CNAMEResource 2162 rb, err = unpackCNAMEResource(msg, off) 2163 r = &rb 2164 name = "CNAME" 2165 case TypeSOA: 2166 var rb SOAResource 2167 rb, err = unpackSOAResource(msg, off) 2168 r = &rb 2169 name = "SOA" 2170 case TypePTR: 2171 var rb PTRResource 2172 rb, err = unpackPTRResource(msg, off) 2173 r = &rb 2174 name = "PTR" 2175 case TypeMX: 2176 var rb MXResource 2177 rb, err = unpackMXResource(msg, off) 2178 r = &rb 2179 name = "MX" 2180 case TypeTXT: 2181 var rb TXTResource 2182 rb, err = unpackTXTResource(msg, off, hdr.Length) 2183 r = &rb 2184 name = "TXT" 2185 case TypeAAAA: 2186 var rb AAAAResource 2187 rb, err = unpackAAAAResource(msg, off) 2188 r = &rb 2189 name = "AAAA" 2190 case TypeSRV: 2191 var rb SRVResource 2192 rb, err = unpackSRVResource(msg, off) 2193 r = &rb 2194 name = "SRV" 2195 case TypeOPT: 2196 var rb OPTResource 2197 rb, err = unpackOPTResource(msg, off, hdr.Length) 2198 r = &rb 2199 name = "OPT" 2200 case TypeSVCB: 2201 var rb SVCBResource 2202 rb, err = unpackSVCBResource(msg, off, hdr.Length) 2203 r = &rb 2204 name = "SVCB" 2205 case TypeHTTPS: 2206 var rb HTTPSResource 2207 rb, err = unpackHTTPSResource(msg, off, hdr.Length) 2208 r = &rb 2209 name = "HTTPS" 2210 } 2211 if err != nil { 2212 return nil, off, &nestedError{name + " record", err} 2213 } 2214 if r == nil { 2215 return nil, off, errors.New("invalid resource type: " + hdr.Type.String()) 2216 } 2217 return r, off + int(hdr.Length), nil 2218} 2219 2220// A CNAMEResource is a CNAME Resource record. 2221type CNAMEResource struct { 2222 CNAME Name 2223} 2224 2225func (r *CNAMEResource) realType() Type { 2226 return TypeCNAME 2227} 2228 2229// pack appends the wire format of the CNAMEResource to msg. 2230func (r *CNAMEResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2231 return r.CNAME.pack(msg, compression, compressionOff) 2232} 2233 2234// GoString implements fmt.GoStringer.GoString. 2235func (r *CNAMEResource) GoString() string { 2236 return "dnsmessage.CNAMEResource{CNAME: " + r.CNAME.GoString() + "}" 2237} 2238 2239func unpackCNAMEResource(msg []byte, off int) (CNAMEResource, error) { 2240 var cname Name 2241 if _, err := cname.unpack(msg, off); err != nil { 2242 return CNAMEResource{}, err 2243 } 2244 return CNAMEResource{cname}, nil 2245} 2246 2247// An MXResource is an MX Resource record. 2248type MXResource struct { 2249 Pref uint16 2250 MX Name 2251} 2252 2253func (r *MXResource) realType() Type { 2254 return TypeMX 2255} 2256 2257// pack appends the wire format of the MXResource to msg. 2258func (r *MXResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2259 oldMsg := msg 2260 msg = packUint16(msg, r.Pref) 2261 msg, err := r.MX.pack(msg, compression, compressionOff) 2262 if err != nil { 2263 return oldMsg, &nestedError{"MXResource.MX", err} 2264 } 2265 return msg, nil 2266} 2267 2268// GoString implements fmt.GoStringer.GoString. 2269func (r *MXResource) GoString() string { 2270 return "dnsmessage.MXResource{" + 2271 "Pref: " + printUint16(r.Pref) + ", " + 2272 "MX: " + r.MX.GoString() + "}" 2273} 2274 2275func unpackMXResource(msg []byte, off int) (MXResource, error) { 2276 pref, off, err := unpackUint16(msg, off) 2277 if err != nil { 2278 return MXResource{}, &nestedError{"Pref", err} 2279 } 2280 var mx Name 2281 if _, err := mx.unpack(msg, off); err != nil { 2282 return MXResource{}, &nestedError{"MX", err} 2283 } 2284 return MXResource{pref, mx}, nil 2285} 2286 2287// An NSResource is an NS Resource record. 2288type NSResource struct { 2289 NS Name 2290} 2291 2292func (r *NSResource) realType() Type { 2293 return TypeNS 2294} 2295 2296// pack appends the wire format of the NSResource to msg. 2297func (r *NSResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2298 return r.NS.pack(msg, compression, compressionOff) 2299} 2300 2301// GoString implements fmt.GoStringer.GoString. 2302func (r *NSResource) GoString() string { 2303 return "dnsmessage.NSResource{NS: " + r.NS.GoString() + "}" 2304} 2305 2306func unpackNSResource(msg []byte, off int) (NSResource, error) { 2307 var ns Name 2308 if _, err := ns.unpack(msg, off); err != nil { 2309 return NSResource{}, err 2310 } 2311 return NSResource{ns}, nil 2312} 2313 2314// A PTRResource is a PTR Resource record. 2315type PTRResource struct { 2316 PTR Name 2317} 2318 2319func (r *PTRResource) realType() Type { 2320 return TypePTR 2321} 2322 2323// pack appends the wire format of the PTRResource to msg. 2324func (r *PTRResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2325 return r.PTR.pack(msg, compression, compressionOff) 2326} 2327 2328// GoString implements fmt.GoStringer.GoString. 2329func (r *PTRResource) GoString() string { 2330 return "dnsmessage.PTRResource{PTR: " + r.PTR.GoString() + "}" 2331} 2332 2333func unpackPTRResource(msg []byte, off int) (PTRResource, error) { 2334 var ptr Name 2335 if _, err := ptr.unpack(msg, off); err != nil { 2336 return PTRResource{}, err 2337 } 2338 return PTRResource{ptr}, nil 2339} 2340 2341// An SOAResource is an SOA Resource record. 2342type SOAResource struct { 2343 NS Name 2344 MBox Name 2345 Serial uint32 2346 Refresh uint32 2347 Retry uint32 2348 Expire uint32 2349 2350 // MinTTL the is the default TTL of Resources records which did not 2351 // contain a TTL value and the TTL of negative responses. (RFC 2308 2352 // Section 4) 2353 MinTTL uint32 2354} 2355 2356func (r *SOAResource) realType() Type { 2357 return TypeSOA 2358} 2359 2360// pack appends the wire format of the SOAResource to msg. 2361func (r *SOAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2362 oldMsg := msg 2363 msg, err := r.NS.pack(msg, compression, compressionOff) 2364 if err != nil { 2365 return oldMsg, &nestedError{"SOAResource.NS", err} 2366 } 2367 msg, err = r.MBox.pack(msg, compression, compressionOff) 2368 if err != nil { 2369 return oldMsg, &nestedError{"SOAResource.MBox", err} 2370 } 2371 msg = packUint32(msg, r.Serial) 2372 msg = packUint32(msg, r.Refresh) 2373 msg = packUint32(msg, r.Retry) 2374 msg = packUint32(msg, r.Expire) 2375 return packUint32(msg, r.MinTTL), nil 2376} 2377 2378// GoString implements fmt.GoStringer.GoString. 2379func (r *SOAResource) GoString() string { 2380 return "dnsmessage.SOAResource{" + 2381 "NS: " + r.NS.GoString() + ", " + 2382 "MBox: " + r.MBox.GoString() + ", " + 2383 "Serial: " + printUint32(r.Serial) + ", " + 2384 "Refresh: " + printUint32(r.Refresh) + ", " + 2385 "Retry: " + printUint32(r.Retry) + ", " + 2386 "Expire: " + printUint32(r.Expire) + ", " + 2387 "MinTTL: " + printUint32(r.MinTTL) + "}" 2388} 2389 2390func unpackSOAResource(msg []byte, off int) (SOAResource, error) { 2391 var ns Name 2392 off, err := ns.unpack(msg, off) 2393 if err != nil { 2394 return SOAResource{}, &nestedError{"NS", err} 2395 } 2396 var mbox Name 2397 if off, err = mbox.unpack(msg, off); err != nil { 2398 return SOAResource{}, &nestedError{"MBox", err} 2399 } 2400 serial, off, err := unpackUint32(msg, off) 2401 if err != nil { 2402 return SOAResource{}, &nestedError{"Serial", err} 2403 } 2404 refresh, off, err := unpackUint32(msg, off) 2405 if err != nil { 2406 return SOAResource{}, &nestedError{"Refresh", err} 2407 } 2408 retry, off, err := unpackUint32(msg, off) 2409 if err != nil { 2410 return SOAResource{}, &nestedError{"Retry", err} 2411 } 2412 expire, off, err := unpackUint32(msg, off) 2413 if err != nil { 2414 return SOAResource{}, &nestedError{"Expire", err} 2415 } 2416 minTTL, _, err := unpackUint32(msg, off) 2417 if err != nil { 2418 return SOAResource{}, &nestedError{"MinTTL", err} 2419 } 2420 return SOAResource{ns, mbox, serial, refresh, retry, expire, minTTL}, nil 2421} 2422 2423// A TXTResource is a TXT Resource record. 2424type TXTResource struct { 2425 TXT []string 2426} 2427 2428func (r *TXTResource) realType() Type { 2429 return TypeTXT 2430} 2431 2432// pack appends the wire format of the TXTResource to msg. 2433func (r *TXTResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2434 oldMsg := msg 2435 for _, s := range r.TXT { 2436 var err error 2437 msg, err = packText(msg, s) 2438 if err != nil { 2439 return oldMsg, err 2440 } 2441 } 2442 return msg, nil 2443} 2444 2445// GoString implements fmt.GoStringer.GoString. 2446func (r *TXTResource) GoString() string { 2447 s := "dnsmessage.TXTResource{TXT: []string{" 2448 if len(r.TXT) == 0 { 2449 return s + "}}" 2450 } 2451 s += `"` + printString([]byte(r.TXT[0])) 2452 for _, t := range r.TXT[1:] { 2453 s += `", "` + printString([]byte(t)) 2454 } 2455 return s + `"}}` 2456} 2457 2458func unpackTXTResource(msg []byte, off int, length uint16) (TXTResource, error) { 2459 txts := make([]string, 0, 1) 2460 for n := uint16(0); n < length; { 2461 var t string 2462 var err error 2463 if t, off, err = unpackText(msg, off); err != nil { 2464 return TXTResource{}, &nestedError{"text", err} 2465 } 2466 // Check if we got too many bytes. 2467 if length-n < uint16(len(t))+1 { 2468 return TXTResource{}, errCalcLen 2469 } 2470 n += uint16(len(t)) + 1 2471 txts = append(txts, t) 2472 } 2473 return TXTResource{txts}, nil 2474} 2475 2476// An SRVResource is an SRV Resource record. 2477type SRVResource struct { 2478 Priority uint16 2479 Weight uint16 2480 Port uint16 2481 Target Name // Not compressed as per RFC 2782. 2482} 2483 2484func (r *SRVResource) realType() Type { 2485 return TypeSRV 2486} 2487 2488// pack appends the wire format of the SRVResource to msg. 2489func (r *SRVResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2490 oldMsg := msg 2491 msg = packUint16(msg, r.Priority) 2492 msg = packUint16(msg, r.Weight) 2493 msg = packUint16(msg, r.Port) 2494 msg, err := r.Target.pack(msg, nil, compressionOff) 2495 if err != nil { 2496 return oldMsg, &nestedError{"SRVResource.Target", err} 2497 } 2498 return msg, nil 2499} 2500 2501// GoString implements fmt.GoStringer.GoString. 2502func (r *SRVResource) GoString() string { 2503 return "dnsmessage.SRVResource{" + 2504 "Priority: " + printUint16(r.Priority) + ", " + 2505 "Weight: " + printUint16(r.Weight) + ", " + 2506 "Port: " + printUint16(r.Port) + ", " + 2507 "Target: " + r.Target.GoString() + "}" 2508} 2509 2510func unpackSRVResource(msg []byte, off int) (SRVResource, error) { 2511 priority, off, err := unpackUint16(msg, off) 2512 if err != nil { 2513 return SRVResource{}, &nestedError{"Priority", err} 2514 } 2515 weight, off, err := unpackUint16(msg, off) 2516 if err != nil { 2517 return SRVResource{}, &nestedError{"Weight", err} 2518 } 2519 port, off, err := unpackUint16(msg, off) 2520 if err != nil { 2521 return SRVResource{}, &nestedError{"Port", err} 2522 } 2523 var target Name 2524 if _, err := target.unpackCompressed(msg, off, true /* allowCompression */); err != nil { 2525 return SRVResource{}, &nestedError{"Target", err} 2526 } 2527 return SRVResource{priority, weight, port, target}, nil 2528} 2529 2530// An AResource is an A Resource record. 2531type AResource struct { 2532 A [4]byte 2533} 2534 2535func (r *AResource) realType() Type { 2536 return TypeA 2537} 2538 2539// pack appends the wire format of the AResource to msg. 2540func (r *AResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2541 return packBytes(msg, r.A[:]), nil 2542} 2543 2544// GoString implements fmt.GoStringer.GoString. 2545func (r *AResource) GoString() string { 2546 return "dnsmessage.AResource{" + 2547 "A: [4]byte{" + printByteSlice(r.A[:]) + "}}" 2548} 2549 2550func unpackAResource(msg []byte, off int) (AResource, error) { 2551 var a [4]byte 2552 if _, err := unpackBytes(msg, off, a[:]); err != nil { 2553 return AResource{}, err 2554 } 2555 return AResource{a}, nil 2556} 2557 2558// An AAAAResource is an AAAA Resource record. 2559type AAAAResource struct { 2560 AAAA [16]byte 2561} 2562 2563func (r *AAAAResource) realType() Type { 2564 return TypeAAAA 2565} 2566 2567// GoString implements fmt.GoStringer.GoString. 2568func (r *AAAAResource) GoString() string { 2569 return "dnsmessage.AAAAResource{" + 2570 "AAAA: [16]byte{" + printByteSlice(r.AAAA[:]) + "}}" 2571} 2572 2573// pack appends the wire format of the AAAAResource to msg. 2574func (r *AAAAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2575 return packBytes(msg, r.AAAA[:]), nil 2576} 2577 2578func unpackAAAAResource(msg []byte, off int) (AAAAResource, error) { 2579 var aaaa [16]byte 2580 if _, err := unpackBytes(msg, off, aaaa[:]); err != nil { 2581 return AAAAResource{}, err 2582 } 2583 return AAAAResource{aaaa}, nil 2584} 2585 2586// An OPTResource is an OPT pseudo Resource record. 2587// 2588// The pseudo resource record is part of the extension mechanisms for DNS 2589// as defined in RFC 6891. 2590type OPTResource struct { 2591 Options []Option 2592} 2593 2594// An Option represents a DNS message option within OPTResource. 2595// 2596// The message option is part of the extension mechanisms for DNS as 2597// defined in RFC 6891. 2598type Option struct { 2599 Code uint16 // option code 2600 Data []byte 2601} 2602 2603// GoString implements fmt.GoStringer.GoString. 2604func (o *Option) GoString() string { 2605 return "dnsmessage.Option{" + 2606 "Code: " + printUint16(o.Code) + ", " + 2607 "Data: []byte{" + printByteSlice(o.Data) + "}}" 2608} 2609 2610func (r *OPTResource) realType() Type { 2611 return TypeOPT 2612} 2613 2614func (r *OPTResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2615 for _, opt := range r.Options { 2616 msg = packUint16(msg, opt.Code) 2617 l := uint16(len(opt.Data)) 2618 msg = packUint16(msg, l) 2619 msg = packBytes(msg, opt.Data) 2620 } 2621 return msg, nil 2622} 2623 2624// GoString implements fmt.GoStringer.GoString. 2625func (r *OPTResource) GoString() string { 2626 s := "dnsmessage.OPTResource{Options: []dnsmessage.Option{" 2627 if len(r.Options) == 0 { 2628 return s + "}}" 2629 } 2630 s += r.Options[0].GoString() 2631 for _, o := range r.Options[1:] { 2632 s += ", " + o.GoString() 2633 } 2634 return s + "}}" 2635} 2636 2637func unpackOPTResource(msg []byte, off int, length uint16) (OPTResource, error) { 2638 var opts []Option 2639 for oldOff := off; off < oldOff+int(length); { 2640 var err error 2641 var o Option 2642 o.Code, off, err = unpackUint16(msg, off) 2643 if err != nil { 2644 return OPTResource{}, &nestedError{"Code", err} 2645 } 2646 var l uint16 2647 l, off, err = unpackUint16(msg, off) 2648 if err != nil { 2649 return OPTResource{}, &nestedError{"Data", err} 2650 } 2651 o.Data = make([]byte, l) 2652 if copy(o.Data, msg[off:]) != int(l) { 2653 return OPTResource{}, &nestedError{"Data", errCalcLen} 2654 } 2655 off += int(l) 2656 opts = append(opts, o) 2657 } 2658 return OPTResource{opts}, nil 2659} 2660 2661// An SVCBResource is an SVCB Resource record. 2662type SVCBResource struct { 2663 Priority uint16 2664 Target Name 2665 Params []Param 2666} 2667 2668type ParamKey uint16 2669 2670const ( 2671 ParamMandatory ParamKey = 0 2672 ParamALPN ParamKey = 1 2673 ParamNoDefaultALPN ParamKey = 2 2674 ParamPort ParamKey = 3 2675 ParamIPv4Hint ParamKey = 4 2676 ParamECHConfig ParamKey = 5 2677 ParamIPv6Hint ParamKey = 6 2678) 2679 2680var paramNames = map[ParamKey]string{ 2681 ParamMandatory: "mandatory", 2682 ParamALPN: "alpn", 2683 ParamNoDefaultALPN: "no-default-alpn", 2684 ParamPort: "port", 2685 ParamIPv4Hint: "ipv4hint", 2686 ParamECHConfig: "echconfig", 2687 ParamIPv6Hint: "ipv6hint", 2688} 2689 2690var paramGoNames = map[ParamKey]string{ 2691 ParamMandatory: "ParamMandatory", 2692 ParamALPN: "ParamALPN", 2693 ParamNoDefaultALPN: "ParamNoDefaultALPN", 2694 ParamPort: "ParamPort", 2695 ParamIPv4Hint: "ParamIPv4Hint", 2696 ParamECHConfig: "ParamECHConfig", 2697 ParamIPv6Hint: "ParamIPv6Hint", 2698} 2699 2700// String implements fmt.Stringer.String. 2701func (t ParamKey) String() string { 2702 if n, ok := paramNames[t]; ok { 2703 return n 2704 } 2705 return "key" + printUint16(uint16(t)) 2706} 2707 2708// GoString implements fmt.GoStringer.GoString. 2709func (t ParamKey) GoString() string { 2710 if n, ok := paramGoNames[t]; ok { 2711 return "dnsmessage." + n 2712 } 2713 return printUint16(uint16(t)) 2714} 2715 2716type Param struct { 2717 Key ParamKey 2718 Value []byte 2719} 2720 2721func (p Param) GoString() string { 2722 return "dnsmessage.Param{" + 2723 "Key: " + p.Key.GoString() + ", " + 2724 `Value: "` + printString(p.Value) + `"}` 2725} 2726 2727func (r *SVCBResource) realType() Type { 2728 return TypeSVCB 2729} 2730 2731// pack appends the wire format of the SVCBResource to msg. 2732func (r *SVCBResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2733 return svcbPack(*r, "SVCBResource", msg, compression, compressionOff) 2734} 2735 2736func svcbPack(r SVCBResource, rrTypeName string, msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2737 oldMsg := msg 2738 msg = packUint16(msg, r.Priority) 2739 msg, err := r.Target.pack(msg, nil, compressionOff) 2740 if err != nil { 2741 return oldMsg, &nestedError{rrTypeName + ".Target", err} 2742 } 2743 if len(r.Params) == 0 { 2744 return msg, nil 2745 } 2746 // SvcParamKeys SHALL appear in increasing numeric order 2747 params := append([]Param{}, r.Params...) 2748 sort.Slice(params, func(i, j int) bool { 2749 return params[i].Key < params[j].Key 2750 }) 2751 for _, p := range params { 2752 msg = packUint16(msg, uint16(p.Key)) 2753 l := uint16(len(p.Value)) 2754 msg = packUint16(msg, l) 2755 msg = packBytes(msg, p.Value) 2756 } 2757 return msg, nil 2758} 2759 2760// GoString implements fmt.GoStringer.GoString. 2761func (r *SVCBResource) GoString() string { 2762 s := "dnsmessage.SVCBResource{" + 2763 "Priority: " + printUint16(r.Priority) + ", " + 2764 "Target: " + r.Target.GoString() + 2765 "Params: []dnsmessage.Param{" 2766 if len(r.Params) == 0 { 2767 return s + "}}" 2768 } 2769 s += r.Params[0].GoString() 2770 for _, p := range r.Params[1:] { 2771 s += ", " + p.GoString() 2772 } 2773 return s + "}}" 2774} 2775 2776func unpackSVCBResource(msg []byte, off int, length uint16) (SVCBResource, error) { 2777 endOff := off + int(length) 2778 priority, off, err := unpackUint16(msg, off) 2779 if err != nil { 2780 return SVCBResource{}, &nestedError{"Priority", err} 2781 } 2782 var target Name 2783 if off, err = target.unpackCompressed(msg, off, true /* allowCompression */); err != nil { 2784 return SVCBResource{}, &nestedError{"Target", err} 2785 } 2786 var params []Param 2787 for off < endOff { 2788 var err error 2789 var p Param 2790 var k uint16 2791 k, off, err = unpackUint16(msg, off) 2792 p.Key = ParamKey(k) 2793 if err != nil { 2794 return SVCBResource{}, &nestedError{"Key", err} 2795 } 2796 var l uint16 2797 l, off, err = unpackUint16(msg, off) 2798 if err != nil { 2799 return SVCBResource{}, &nestedError{"Value", err} 2800 } 2801 p.Value = make([]byte, l) 2802 if copy(p.Value, msg[off:]) != int(l) { 2803 return SVCBResource{}, &nestedError{"Value", errCalcLen} 2804 } 2805 off += int(l) 2806 params = append(params, p) 2807 } 2808 return SVCBResource{priority, target, params}, nil 2809} 2810 2811type HTTPSResource struct { 2812 Priority uint16 2813 Target Name 2814 Params []Param 2815} 2816 2817func (r *HTTPSResource) realType() Type { 2818 return TypeHTTPS 2819} 2820 2821// pack appends the wire format of the SVCBResource to msg. 2822func (r *HTTPSResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { 2823 return svcbPack(SVCBResource(*r), "HTTPSResource", msg, compression, compressionOff) 2824} 2825 2826// GoString implements fmt.GoStringer.GoString. 2827func (r *HTTPSResource) GoString() string { 2828 s := "dnsmessage.HTTPSResource{" + 2829 "Priority: " + printUint16(r.Priority) + ", " + 2830 "Target: " + r.Target.GoString() + 2831 "Params: []dnsmessage.Param{" 2832 if len(r.Params) == 0 { 2833 return s + "}}" 2834 } 2835 s += r.Params[0].GoString() 2836 for _, p := range r.Params[1:] { 2837 s += ", " + p.GoString() 2838 } 2839 return s + "}}" 2840} 2841 2842func unpackHTTPSResource(msg []byte, off int, length uint16) (HTTPSResource, error) { 2843 r, err := unpackSVCBResource(msg, off, length) 2844 return HTTPSResource(r), err 2845} 2846