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