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