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  }