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
23package net
24
25// Packet formats
26
27// Wire constants.
28const (
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.
73type 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.
86type dnsHeader struct {
87	Id                                 uint16
88	Bits                               uint16
89	Qdcount, Ancount, Nscount, Arcount uint16
90}
91
92func (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
101const (
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.
111type dnsQuestion struct {
112	Name   string
113	Qtype  uint16
114	Qclass uint16
115}
116
117func (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.
126type 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
134func (h *dnsRR_Header) Header() *dnsRR_Header {
135	return h
136}
137
138func (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
146type dnsRR interface {
147	dnsStruct
148	Header() *dnsRR_Header
149}
150
151// Specific DNS RR formats for each query type.
152
153type dnsRR_CNAME struct {
154	Hdr   dnsRR_Header
155	Cname string
156}
157
158func (rr *dnsRR_CNAME) Header() *dnsRR_Header {
159	return &rr.Hdr
160}
161
162func (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
166type dnsRR_MX struct {
167	Hdr  dnsRR_Header
168	Pref uint16
169	Mx   string
170}
171
172func (rr *dnsRR_MX) Header() *dnsRR_Header {
173	return &rr.Hdr
174}
175
176func (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
180type dnsRR_NS struct {
181	Hdr dnsRR_Header
182	Ns  string
183}
184
185func (rr *dnsRR_NS) Header() *dnsRR_Header {
186	return &rr.Hdr
187}
188
189func (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
193type dnsRR_PTR struct {
194	Hdr dnsRR_Header
195	Ptr string
196}
197
198func (rr *dnsRR_PTR) Header() *dnsRR_Header {
199	return &rr.Hdr
200}
201
202func (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
206type 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
217func (rr *dnsRR_SOA) Header() *dnsRR_Header {
218	return &rr.Hdr
219}
220
221func (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
232type dnsRR_TXT struct {
233	Hdr dnsRR_Header
234	Txt string // not domain name
235}
236
237func (rr *dnsRR_TXT) Header() *dnsRR_Header {
238	return &rr.Hdr
239}
240
241func (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
261type dnsRR_SRV struct {
262	Hdr      dnsRR_Header
263	Priority uint16
264	Weight   uint16
265	Port     uint16
266	Target   string
267}
268
269func (rr *dnsRR_SRV) Header() *dnsRR_Header {
270	return &rr.Hdr
271}
272
273func (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
281type dnsRR_A struct {
282	Hdr dnsRR_Header
283	A   uint32
284}
285
286func (rr *dnsRR_A) Header() *dnsRR_Header {
287	return &rr.Hdr
288}
289
290func (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
294type dnsRR_AAAA struct {
295	Hdr  dnsRR_Header
296	AAAA [16]byte
297}
298
299func (rr *dnsRR_AAAA) Header() *dnsRR_Header {
300	return &rr.Hdr
301}
302
303func (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.
316var 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.
331func 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.
392func unpackDomainName(msg []byte, off int) (s string, off1 int, ok bool) {
393	s = ""
394	ptr := 0 // number of pointers followed
395Loop:
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.
448func 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.
507func 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.
569func 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.
629func 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.
651func 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.
678type 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
689func (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
700type dnsMsg struct {
701	dnsMsgHdr
702	question []dnsQuestion
703	answer   []dnsRR
704	ns       []dnsRR
705	extra    []dnsRR
706}
707
708func (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
779func (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
837func (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.
867func (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