Home | History | Annotate | Download | only in net
      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 }
    885