...
Run Format

Source file src/net/dnsmsg.go

     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	

View as plain text