github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/src/net/dnsmsg.go (about) 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 // DNS packet assembly. See RFC 1035. 6 // 7 // This is intended to support name resolution during Dial. 8 // It doesn't have to be blazing fast. 9 // 10 // Each message structure has a Walk method that is used by 11 // a generic pack/unpack routine. Thus, if in the future we need 12 // to define new message structs, no new pack/unpack/printing code 13 // needs to be written. 14 // 15 // The first half of this file defines the DNS message formats. 16 // The second half implements the conversion to and from wire format. 17 // A few of the structure elements have string tags to aid the 18 // generic pack/unpack routines. 19 // 20 // TODO(rsc): There are enough names defined in this file that they're all 21 // prefixed with dns. Perhaps put this in its own package later. 22 23 package net 24 25 // Packet formats 26 27 // Wire constants. 28 const ( 29 // valid dnsRR_Header.Rrtype and dnsQuestion.qtype 30 dnsTypeA = 1 31 dnsTypeNS = 2 32 dnsTypeMD = 3 33 dnsTypeMF = 4 34 dnsTypeCNAME = 5 35 dnsTypeSOA = 6 36 dnsTypeMB = 7 37 dnsTypeMG = 8 38 dnsTypeMR = 9 39 dnsTypeNULL = 10 40 dnsTypeWKS = 11 41 dnsTypePTR = 12 42 dnsTypeHINFO = 13 43 dnsTypeMINFO = 14 44 dnsTypeMX = 15 45 dnsTypeTXT = 16 46 dnsTypeAAAA = 28 47 dnsTypeSRV = 33 48 49 // valid dnsQuestion.qtype only 50 dnsTypeAXFR = 252 51 dnsTypeMAILB = 253 52 dnsTypeMAILA = 254 53 dnsTypeALL = 255 54 55 // valid dnsQuestion.qclass 56 dnsClassINET = 1 57 dnsClassCSNET = 2 58 dnsClassCHAOS = 3 59 dnsClassHESIOD = 4 60 dnsClassANY = 255 61 62 // dnsMsg.rcode 63 dnsRcodeSuccess = 0 64 dnsRcodeFormatError = 1 65 dnsRcodeServerFailure = 2 66 dnsRcodeNameError = 3 67 dnsRcodeNotImplemented = 4 68 dnsRcodeRefused = 5 69 ) 70 71 // A dnsStruct describes how to iterate over its fields to emulate 72 // reflective marshaling. 73 type dnsStruct interface { 74 // Walk iterates over fields of a structure and calls f 75 // with a reference to that field, the name of the field 76 // and a tag ("", "domain", "ipv4", "ipv6") specifying 77 // particular encodings. Possible concrete types 78 // for v are *uint16, *uint32, *string, or []byte, and 79 // *int, *bool in the case of dnsMsgHdr. 80 // Whenever f returns false, Walk must stop and return 81 // false, and otherwise return true. 82 Walk(f func(v interface{}, name, tag string) (ok bool)) (ok bool) 83 } 84 85 // The wire format for the DNS packet header. 86 type dnsHeader struct { 87 Id uint16 88 Bits uint16 89 Qdcount, Ancount, Nscount, Arcount uint16 90 } 91 92 func (h *dnsHeader) Walk(f func(v interface{}, name, tag string) bool) bool { 93 return f(&h.Id, "Id", "") && 94 f(&h.Bits, "Bits", "") && 95 f(&h.Qdcount, "Qdcount", "") && 96 f(&h.Ancount, "Ancount", "") && 97 f(&h.Nscount, "Nscount", "") && 98 f(&h.Arcount, "Arcount", "") 99 } 100 101 const ( 102 // dnsHeader.Bits 103 _QR = 1 << 15 // query/response (response=1) 104 _AA = 1 << 10 // authoritative 105 _TC = 1 << 9 // truncated 106 _RD = 1 << 8 // recursion desired 107 _RA = 1 << 7 // recursion available 108 ) 109 110 // DNS queries. 111 type dnsQuestion struct { 112 Name string 113 Qtype uint16 114 Qclass uint16 115 } 116 117 func (q *dnsQuestion) Walk(f func(v interface{}, name, tag string) bool) bool { 118 return f(&q.Name, "Name", "domain") && 119 f(&q.Qtype, "Qtype", "") && 120 f(&q.Qclass, "Qclass", "") 121 } 122 123 // DNS responses (resource records). 124 // There are many types of messages, 125 // but they all share the same header. 126 type dnsRR_Header struct { 127 Name string 128 Rrtype uint16 129 Class uint16 130 Ttl uint32 131 Rdlength uint16 // length of data after header 132 } 133 134 func (h *dnsRR_Header) Header() *dnsRR_Header { 135 return h 136 } 137 138 func (h *dnsRR_Header) Walk(f func(v interface{}, name, tag string) bool) bool { 139 return f(&h.Name, "Name", "domain") && 140 f(&h.Rrtype, "Rrtype", "") && 141 f(&h.Class, "Class", "") && 142 f(&h.Ttl, "Ttl", "") && 143 f(&h.Rdlength, "Rdlength", "") 144 } 145 146 type dnsRR interface { 147 dnsStruct 148 Header() *dnsRR_Header 149 } 150 151 // Specific DNS RR formats for each query type. 152 153 type dnsRR_CNAME struct { 154 Hdr dnsRR_Header 155 Cname string 156 } 157 158 func (rr *dnsRR_CNAME) Header() *dnsRR_Header { 159 return &rr.Hdr 160 } 161 162 func (rr *dnsRR_CNAME) Walk(f func(v interface{}, name, tag string) bool) bool { 163 return rr.Hdr.Walk(f) && f(&rr.Cname, "Cname", "domain") 164 } 165 166 type dnsRR_MX struct { 167 Hdr dnsRR_Header 168 Pref uint16 169 Mx string 170 } 171 172 func (rr *dnsRR_MX) Header() *dnsRR_Header { 173 return &rr.Hdr 174 } 175 176 func (rr *dnsRR_MX) Walk(f func(v interface{}, name, tag string) bool) bool { 177 return rr.Hdr.Walk(f) && f(&rr.Pref, "Pref", "") && f(&rr.Mx, "Mx", "domain") 178 } 179 180 type dnsRR_NS struct { 181 Hdr dnsRR_Header 182 Ns string 183 } 184 185 func (rr *dnsRR_NS) Header() *dnsRR_Header { 186 return &rr.Hdr 187 } 188 189 func (rr *dnsRR_NS) Walk(f func(v interface{}, name, tag string) bool) bool { 190 return rr.Hdr.Walk(f) && f(&rr.Ns, "Ns", "domain") 191 } 192 193 type dnsRR_PTR struct { 194 Hdr dnsRR_Header 195 Ptr string 196 } 197 198 func (rr *dnsRR_PTR) Header() *dnsRR_Header { 199 return &rr.Hdr 200 } 201 202 func (rr *dnsRR_PTR) Walk(f func(v interface{}, name, tag string) bool) bool { 203 return rr.Hdr.Walk(f) && f(&rr.Ptr, "Ptr", "domain") 204 } 205 206 type dnsRR_SOA struct { 207 Hdr dnsRR_Header 208 Ns string 209 Mbox string 210 Serial uint32 211 Refresh uint32 212 Retry uint32 213 Expire uint32 214 Minttl uint32 215 } 216 217 func (rr *dnsRR_SOA) Header() *dnsRR_Header { 218 return &rr.Hdr 219 } 220 221 func (rr *dnsRR_SOA) Walk(f func(v interface{}, name, tag string) bool) bool { 222 return rr.Hdr.Walk(f) && 223 f(&rr.Ns, "Ns", "domain") && 224 f(&rr.Mbox, "Mbox", "domain") && 225 f(&rr.Serial, "Serial", "") && 226 f(&rr.Refresh, "Refresh", "") && 227 f(&rr.Retry, "Retry", "") && 228 f(&rr.Expire, "Expire", "") && 229 f(&rr.Minttl, "Minttl", "") 230 } 231 232 type dnsRR_TXT struct { 233 Hdr dnsRR_Header 234 Txt string // not domain name 235 } 236 237 func (rr *dnsRR_TXT) Header() *dnsRR_Header { 238 return &rr.Hdr 239 } 240 241 func (rr *dnsRR_TXT) Walk(f func(v interface{}, name, tag string) bool) bool { 242 if !rr.Hdr.Walk(f) { 243 return false 244 } 245 var n uint16 = 0 246 for n < rr.Hdr.Rdlength { 247 var txt string 248 if !f(&txt, "Txt", "") { 249 return false 250 } 251 // more bytes than rr.Hdr.Rdlength said there would be 252 if rr.Hdr.Rdlength-n < uint16(len(txt))+1 { 253 return false 254 } 255 n += uint16(len(txt)) + 1 256 rr.Txt += txt 257 } 258 return true 259 } 260 261 type dnsRR_SRV struct { 262 Hdr dnsRR_Header 263 Priority uint16 264 Weight uint16 265 Port uint16 266 Target string 267 } 268 269 func (rr *dnsRR_SRV) Header() *dnsRR_Header { 270 return &rr.Hdr 271 } 272 273 func (rr *dnsRR_SRV) Walk(f func(v interface{}, name, tag string) bool) bool { 274 return rr.Hdr.Walk(f) && 275 f(&rr.Priority, "Priority", "") && 276 f(&rr.Weight, "Weight", "") && 277 f(&rr.Port, "Port", "") && 278 f(&rr.Target, "Target", "domain") 279 } 280 281 type dnsRR_A struct { 282 Hdr dnsRR_Header 283 A uint32 284 } 285 286 func (rr *dnsRR_A) Header() *dnsRR_Header { 287 return &rr.Hdr 288 } 289 290 func (rr *dnsRR_A) Walk(f func(v interface{}, name, tag string) bool) bool { 291 return rr.Hdr.Walk(f) && f(&rr.A, "A", "ipv4") 292 } 293 294 type dnsRR_AAAA struct { 295 Hdr dnsRR_Header 296 AAAA [16]byte 297 } 298 299 func (rr *dnsRR_AAAA) Header() *dnsRR_Header { 300 return &rr.Hdr 301 } 302 303 func (rr *dnsRR_AAAA) Walk(f func(v interface{}, name, tag string) bool) bool { 304 return rr.Hdr.Walk(f) && f(rr.AAAA[:], "AAAA", "ipv6") 305 } 306 307 // Packing and unpacking. 308 // 309 // All the packers and unpackers take a (msg []byte, off int) 310 // and return (off1 int, ok bool). If they return ok==false, they 311 // also return off1==len(msg), so that the next unpacker will 312 // also fail. This lets us avoid checks of ok until the end of a 313 // packing sequence. 314 315 // Map of constructors for each RR wire type. 316 var rr_mk = map[int]func() dnsRR{ 317 dnsTypeCNAME: func() dnsRR { return new(dnsRR_CNAME) }, 318 dnsTypeMX: func() dnsRR { return new(dnsRR_MX) }, 319 dnsTypeNS: func() dnsRR { return new(dnsRR_NS) }, 320 dnsTypePTR: func() dnsRR { return new(dnsRR_PTR) }, 321 dnsTypeSOA: func() dnsRR { return new(dnsRR_SOA) }, 322 dnsTypeTXT: func() dnsRR { return new(dnsRR_TXT) }, 323 dnsTypeSRV: func() dnsRR { return new(dnsRR_SRV) }, 324 dnsTypeA: func() dnsRR { return new(dnsRR_A) }, 325 dnsTypeAAAA: func() dnsRR { return new(dnsRR_AAAA) }, 326 } 327 328 // Pack a domain name s into msg[off:]. 329 // Domain names are a sequence of counted strings 330 // split at the dots. They end with a zero-length string. 331 func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) { 332 // Add trailing dot to canonicalize name. 333 if n := len(s); n == 0 || s[n-1] != '.' { 334 s += "." 335 } 336 337 // Allow root domain. 338 if s == "." { 339 msg[off] = 0 340 off++ 341 return off, true 342 } 343 344 // Each dot ends a segment of the name. 345 // We trade each dot byte for a length byte. 346 // There is also a trailing zero. 347 // Check that we have all the space we need. 348 tot := len(s) + 1 349 if off+tot > len(msg) { 350 return len(msg), false 351 } 352 353 // Emit sequence of counted strings, chopping at dots. 354 begin := 0 355 for i := 0; i < len(s); i++ { 356 if s[i] == '.' { 357 if i-begin >= 1<<6 { // top two bits of length must be clear 358 return len(msg), false 359 } 360 if i-begin == 0 { 361 return len(msg), false 362 } 363 364 msg[off] = byte(i - begin) 365 off++ 366 367 for j := begin; j < i; j++ { 368 msg[off] = s[j] 369 off++ 370 } 371 begin = i + 1 372 } 373 } 374 msg[off] = 0 375 off++ 376 return off, true 377 } 378 379 // Unpack a domain name. 380 // In addition to the simple sequences of counted strings above, 381 // domain names are allowed to refer to strings elsewhere in the 382 // packet, to avoid repeating common suffixes when returning 383 // many entries in a single domain. The pointers are marked 384 // by a length byte with the top two bits set. Ignoring those 385 // two bits, that byte and the next give a 14 bit offset from msg[0] 386 // where we should pick up the trail. 387 // Note that if we jump elsewhere in the packet, 388 // we return off1 == the offset after the first pointer we found, 389 // which is where the next record will start. 390 // In theory, the pointers are only allowed to jump backward. 391 // We let them jump anywhere and stop jumping after a while. 392 func unpackDomainName(msg []byte, off int) (s string, off1 int, ok bool) { 393 s = "" 394 ptr := 0 // number of pointers followed 395 Loop: 396 for { 397 if off >= len(msg) { 398 return "", len(msg), false 399 } 400 c := int(msg[off]) 401 off++ 402 switch c & 0xC0 { 403 case 0x00: 404 if c == 0x00 { 405 // end of name 406 break Loop 407 } 408 // literal string 409 if off+c > len(msg) { 410 return "", len(msg), false 411 } 412 s += string(msg[off:off+c]) + "." 413 off += c 414 case 0xC0: 415 // pointer to somewhere else in msg. 416 // remember location after first ptr, 417 // since that's how many bytes we consumed. 418 // also, don't follow too many pointers -- 419 // maybe there's a loop. 420 if off >= len(msg) { 421 return "", len(msg), false 422 } 423 c1 := msg[off] 424 off++ 425 if ptr == 0 { 426 off1 = off 427 } 428 if ptr++; ptr > 10 { 429 return "", len(msg), false 430 } 431 off = (c^0xC0)<<8 | int(c1) 432 default: 433 // 0x80 and 0x40 are reserved 434 return "", len(msg), false 435 } 436 } 437 if len(s) == 0 { 438 s = "." 439 } 440 if ptr == 0 { 441 off1 = off 442 } 443 return s, off1, true 444 } 445 446 // packStruct packs a structure into msg at specified offset off, and 447 // returns off1 such that msg[off:off1] is the encoded data. 448 func packStruct(any dnsStruct, msg []byte, off int) (off1 int, ok bool) { 449 ok = any.Walk(func(field interface{}, name, tag string) bool { 450 switch fv := field.(type) { 451 default: 452 println("net: dns: unknown packing type") 453 return false 454 case *uint16: 455 i := *fv 456 if off+2 > len(msg) { 457 return false 458 } 459 msg[off] = byte(i >> 8) 460 msg[off+1] = byte(i) 461 off += 2 462 case *uint32: 463 i := *fv 464 msg[off] = byte(i >> 24) 465 msg[off+1] = byte(i >> 16) 466 msg[off+2] = byte(i >> 8) 467 msg[off+3] = byte(i) 468 off += 4 469 case []byte: 470 n := len(fv) 471 if off+n > len(msg) { 472 return false 473 } 474 copy(msg[off:off+n], fv) 475 off += n 476 case *string: 477 s := *fv 478 switch tag { 479 default: 480 println("net: dns: unknown string tag", tag) 481 return false 482 case "domain": 483 off, ok = packDomainName(s, msg, off) 484 if !ok { 485 return false 486 } 487 case "": 488 // Counted string: 1 byte length. 489 if len(s) > 255 || off+1+len(s) > len(msg) { 490 return false 491 } 492 msg[off] = byte(len(s)) 493 off++ 494 off += copy(msg[off:], s) 495 } 496 } 497 return true 498 }) 499 if !ok { 500 return len(msg), false 501 } 502 return off, true 503 } 504 505 // unpackStruct decodes msg[off:] into the given structure, and 506 // returns off1 such that msg[off:off1] is the encoded data. 507 func unpackStruct(any dnsStruct, msg []byte, off int) (off1 int, ok bool) { 508 ok = any.Walk(func(field interface{}, name, tag string) bool { 509 switch fv := field.(type) { 510 default: 511 println("net: dns: unknown packing type") 512 return false 513 case *uint16: 514 if off+2 > len(msg) { 515 return false 516 } 517 *fv = uint16(msg[off])<<8 | uint16(msg[off+1]) 518 off += 2 519 case *uint32: 520 if off+4 > len(msg) { 521 return false 522 } 523 *fv = uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | 524 uint32(msg[off+2])<<8 | uint32(msg[off+3]) 525 off += 4 526 case []byte: 527 n := len(fv) 528 if off+n > len(msg) { 529 return false 530 } 531 copy(fv, msg[off:off+n]) 532 off += n 533 case *string: 534 var s string 535 switch tag { 536 default: 537 println("net: dns: unknown string tag", tag) 538 return false 539 case "domain": 540 s, off, ok = unpackDomainName(msg, off) 541 if !ok { 542 return false 543 } 544 case "": 545 if off >= len(msg) || off+1+int(msg[off]) > len(msg) { 546 return false 547 } 548 n := int(msg[off]) 549 off++ 550 b := make([]byte, n) 551 for i := 0; i < n; i++ { 552 b[i] = msg[off+i] 553 } 554 off += n 555 s = string(b) 556 } 557 *fv = s 558 } 559 return true 560 }) 561 if !ok { 562 return len(msg), false 563 } 564 return off, true 565 } 566 567 // Generic struct printer. Prints fields with tag "ipv4" or "ipv6" 568 // as IP addresses. 569 func printStruct(any dnsStruct) string { 570 s := "{" 571 i := 0 572 any.Walk(func(val interface{}, name, tag string) bool { 573 i++ 574 if i > 1 { 575 s += ", " 576 } 577 s += name + "=" 578 switch tag { 579 case "ipv4": 580 i := *val.(*uint32) 581 s += IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i)).String() 582 case "ipv6": 583 i := val.([]byte) 584 s += IP(i).String() 585 default: 586 var i int64 587 switch v := val.(type) { 588 default: 589 // can't really happen. 590 s += "<unknown type>" 591 return true 592 case *string: 593 s += *v 594 return true 595 case []byte: 596 s += string(v) 597 return true 598 case *bool: 599 if *v { 600 s += "true" 601 } else { 602 s += "false" 603 } 604 return true 605 case *int: 606 i = int64(*v) 607 case *uint: 608 i = int64(*v) 609 case *uint8: 610 i = int64(*v) 611 case *uint16: 612 i = int64(*v) 613 case *uint32: 614 i = int64(*v) 615 case *uint64: 616 i = int64(*v) 617 case *uintptr: 618 i = int64(*v) 619 } 620 s += itoa(int(i)) 621 } 622 return true 623 }) 624 s += "}" 625 return s 626 } 627 628 // Resource record packer. 629 func packRR(rr dnsRR, msg []byte, off int) (off2 int, ok bool) { 630 var off1 int 631 // pack twice, once to find end of header 632 // and again to find end of packet. 633 // a bit inefficient but this doesn't need to be fast. 634 // off1 is end of header 635 // off2 is end of rr 636 off1, ok = packStruct(rr.Header(), msg, off) 637 if !ok { 638 return len(msg), false 639 } 640 off2, ok = packStruct(rr, msg, off) 641 if !ok { 642 return len(msg), false 643 } 644 // pack a third time; redo header with correct data length 645 rr.Header().Rdlength = uint16(off2 - off1) 646 packStruct(rr.Header(), msg, off) 647 return off2, true 648 } 649 650 // Resource record unpacker. 651 func unpackRR(msg []byte, off int) (rr dnsRR, off1 int, ok bool) { 652 // unpack just the header, to find the rr type and length 653 var h dnsRR_Header 654 off0 := off 655 if off, ok = unpackStruct(&h, msg, off); !ok { 656 return nil, len(msg), false 657 } 658 end := off + int(h.Rdlength) 659 660 // make an rr of that type and re-unpack. 661 // again inefficient but doesn't need to be fast. 662 mk, known := rr_mk[int(h.Rrtype)] 663 if !known { 664 return &h, end, true 665 } 666 rr = mk() 667 off, ok = unpackStruct(rr, msg, off0) 668 if off != end { 669 return &h, end, true 670 } 671 return rr, off, ok 672 } 673 674 // Usable representation of a DNS packet. 675 676 // A manually-unpacked version of (id, bits). 677 // This is in its own struct for easy printing. 678 type dnsMsgHdr struct { 679 id uint16 680 response bool 681 opcode int 682 authoritative bool 683 truncated bool 684 recursion_desired bool 685 recursion_available bool 686 rcode int 687 } 688 689 func (h *dnsMsgHdr) Walk(f func(v interface{}, name, tag string) bool) bool { 690 return f(&h.id, "id", "") && 691 f(&h.response, "response", "") && 692 f(&h.opcode, "opcode", "") && 693 f(&h.authoritative, "authoritative", "") && 694 f(&h.truncated, "truncated", "") && 695 f(&h.recursion_desired, "recursion_desired", "") && 696 f(&h.recursion_available, "recursion_available", "") && 697 f(&h.rcode, "rcode", "") 698 } 699 700 type dnsMsg struct { 701 dnsMsgHdr 702 question []dnsQuestion 703 answer []dnsRR 704 ns []dnsRR 705 extra []dnsRR 706 } 707 708 func (dns *dnsMsg) Pack() (msg []byte, ok bool) { 709 var dh dnsHeader 710 711 // Convert convenient dnsMsg into wire-like dnsHeader. 712 dh.Id = dns.id 713 dh.Bits = uint16(dns.opcode)<<11 | uint16(dns.rcode) 714 if dns.recursion_available { 715 dh.Bits |= _RA 716 } 717 if dns.recursion_desired { 718 dh.Bits |= _RD 719 } 720 if dns.truncated { 721 dh.Bits |= _TC 722 } 723 if dns.authoritative { 724 dh.Bits |= _AA 725 } 726 if dns.response { 727 dh.Bits |= _QR 728 } 729 730 // Prepare variable sized arrays. 731 question := dns.question 732 answer := dns.answer 733 ns := dns.ns 734 extra := dns.extra 735 736 dh.Qdcount = uint16(len(question)) 737 dh.Ancount = uint16(len(answer)) 738 dh.Nscount = uint16(len(ns)) 739 dh.Arcount = uint16(len(extra)) 740 741 // Could work harder to calculate message size, 742 // but this is far more than we need and not 743 // big enough to hurt the allocator. 744 msg = make([]byte, 2000) 745 746 // Pack it in: header and then the pieces. 747 off := 0 748 off, ok = packStruct(&dh, msg, off) 749 if !ok { 750 return nil, false 751 } 752 for i := 0; i < len(question); i++ { 753 off, ok = packStruct(&question[i], msg, off) 754 if !ok { 755 return nil, false 756 } 757 } 758 for i := 0; i < len(answer); i++ { 759 off, ok = packRR(answer[i], msg, off) 760 if !ok { 761 return nil, false 762 } 763 } 764 for i := 0; i < len(ns); i++ { 765 off, ok = packRR(ns[i], msg, off) 766 if !ok { 767 return nil, false 768 } 769 } 770 for i := 0; i < len(extra); i++ { 771 off, ok = packRR(extra[i], msg, off) 772 if !ok { 773 return nil, false 774 } 775 } 776 return msg[0:off], true 777 } 778 779 func (dns *dnsMsg) Unpack(msg []byte) bool { 780 // Header. 781 var dh dnsHeader 782 off := 0 783 var ok bool 784 if off, ok = unpackStruct(&dh, msg, off); !ok { 785 return false 786 } 787 dns.id = dh.Id 788 dns.response = (dh.Bits & _QR) != 0 789 dns.opcode = int(dh.Bits>>11) & 0xF 790 dns.authoritative = (dh.Bits & _AA) != 0 791 dns.truncated = (dh.Bits & _TC) != 0 792 dns.recursion_desired = (dh.Bits & _RD) != 0 793 dns.recursion_available = (dh.Bits & _RA) != 0 794 dns.rcode = int(dh.Bits & 0xF) 795 796 // Arrays. 797 dns.question = make([]dnsQuestion, dh.Qdcount) 798 dns.answer = make([]dnsRR, 0, dh.Ancount) 799 dns.ns = make([]dnsRR, 0, dh.Nscount) 800 dns.extra = make([]dnsRR, 0, dh.Arcount) 801 802 var rec dnsRR 803 804 for i := 0; i < len(dns.question); i++ { 805 off, ok = unpackStruct(&dns.question[i], msg, off) 806 if !ok { 807 return false 808 } 809 } 810 for i := 0; i < int(dh.Ancount); i++ { 811 rec, off, ok = unpackRR(msg, off) 812 if !ok { 813 return false 814 } 815 dns.answer = append(dns.answer, rec) 816 } 817 for i := 0; i < int(dh.Nscount); i++ { 818 rec, off, ok = unpackRR(msg, off) 819 if !ok { 820 return false 821 } 822 dns.ns = append(dns.ns, rec) 823 } 824 for i := 0; i < int(dh.Arcount); i++ { 825 rec, off, ok = unpackRR(msg, off) 826 if !ok { 827 return false 828 } 829 dns.extra = append(dns.extra, rec) 830 } 831 // if off != len(msg) { 832 // println("extra bytes in dns packet", off, "<", len(msg)); 833 // } 834 return true 835 } 836 837 func (dns *dnsMsg) String() string { 838 s := "DNS: " + printStruct(&dns.dnsMsgHdr) + "\n" 839 if len(dns.question) > 0 { 840 s += "-- Questions\n" 841 for i := 0; i < len(dns.question); i++ { 842 s += printStruct(&dns.question[i]) + "\n" 843 } 844 } 845 if len(dns.answer) > 0 { 846 s += "-- Answers\n" 847 for i := 0; i < len(dns.answer); i++ { 848 s += printStruct(dns.answer[i]) + "\n" 849 } 850 } 851 if len(dns.ns) > 0 { 852 s += "-- Name servers\n" 853 for i := 0; i < len(dns.ns); i++ { 854 s += printStruct(dns.ns[i]) + "\n" 855 } 856 } 857 if len(dns.extra) > 0 { 858 s += "-- Extra\n" 859 for i := 0; i < len(dns.extra); i++ { 860 s += printStruct(dns.extra[i]) + "\n" 861 } 862 } 863 return s 864 } 865 866 // IsResponseTo reports whether m is an acceptable response to query. 867 func (m *dnsMsg) IsResponseTo(query *dnsMsg) bool { 868 if !m.response { 869 return false 870 } 871 if m.id != query.id { 872 return false 873 } 874 if len(m.question) != len(query.question) { 875 return false 876 } 877 for i, q := range m.question { 878 q2 := query.question[i] 879 if !equalASCIILabel(q.Name, q2.Name) || q.Qtype != q2.Qtype || q.Qclass != q2.Qclass { 880 return false 881 } 882 } 883 return true 884 }