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