github.com/gopacket/gopacket@v1.1.0/layers/dns.go (about)

     1  // Copyright 2014, 2018 GoPacket Authors. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style license
     4  // that can be found in the LICENSE file in the root of the source
     5  // tree.
     6  
     7  package layers
     8  
     9  import (
    10  	"encoding/binary"
    11  	"errors"
    12  	"fmt"
    13  	"net"
    14  	"strings"
    15  
    16  	"github.com/gopacket/gopacket"
    17  )
    18  
    19  // DNSClass defines the class associated with a request/response.  Different DNS
    20  // classes can be thought of as an array of parallel namespace trees.
    21  type DNSClass uint16
    22  
    23  // DNSClass known values.
    24  const (
    25  	DNSClassIN  DNSClass = 1   // Internet
    26  	DNSClassCS  DNSClass = 2   // the CSNET class (Obsolete)
    27  	DNSClassCH  DNSClass = 3   // the CHAOS class
    28  	DNSClassHS  DNSClass = 4   // Hesiod [Dyer 87]
    29  	DNSClassAny DNSClass = 255 // AnyClass
    30  )
    31  
    32  func (dc DNSClass) String() string {
    33  	switch dc {
    34  	default:
    35  		return "Unknown"
    36  	case DNSClassIN:
    37  		return "IN"
    38  	case DNSClassCS:
    39  		return "CS"
    40  	case DNSClassCH:
    41  		return "CH"
    42  	case DNSClassHS:
    43  		return "HS"
    44  	case DNSClassAny:
    45  		return "Any"
    46  	}
    47  }
    48  
    49  // DNSType defines the type of data being requested/returned in a
    50  // question/answer.
    51  type DNSType uint16
    52  
    53  // DNSType known values.
    54  const (
    55  	DNSTypeA     DNSType = 1   // a host address
    56  	DNSTypeNS    DNSType = 2   // an authoritative name server
    57  	DNSTypeMD    DNSType = 3   // a mail destination (Obsolete - use MX)
    58  	DNSTypeMF    DNSType = 4   // a mail forwarder (Obsolete - use MX)
    59  	DNSTypeCNAME DNSType = 5   // the canonical name for an alias
    60  	DNSTypeSOA   DNSType = 6   // marks the start of a zone of authority
    61  	DNSTypeMB    DNSType = 7   // a mailbox domain name (EXPERIMENTAL)
    62  	DNSTypeMG    DNSType = 8   // a mail group member (EXPERIMENTAL)
    63  	DNSTypeMR    DNSType = 9   // a mail rename domain name (EXPERIMENTAL)
    64  	DNSTypeNULL  DNSType = 10  // a null RR (EXPERIMENTAL)
    65  	DNSTypeWKS   DNSType = 11  // a well known service description
    66  	DNSTypePTR   DNSType = 12  // a domain name pointer
    67  	DNSTypeHINFO DNSType = 13  // host information
    68  	DNSTypeMINFO DNSType = 14  // mailbox or mail list information
    69  	DNSTypeMX    DNSType = 15  // mail exchange
    70  	DNSTypeTXT   DNSType = 16  // text strings
    71  	DNSTypeAAAA  DNSType = 28  // a IPv6 host address [RFC3596]
    72  	DNSTypeSRV   DNSType = 33  // server discovery [RFC2782] [RFC6195]
    73  	DNSTypeOPT   DNSType = 41  // OPT Pseudo-RR [RFC6891]
    74  	DNSTypeURI   DNSType = 256 // URI RR [RFC7553]
    75  )
    76  
    77  func (dt DNSType) String() string {
    78  	switch dt {
    79  	default:
    80  		return "Unknown"
    81  	case DNSTypeA:
    82  		return "A"
    83  	case DNSTypeNS:
    84  		return "NS"
    85  	case DNSTypeMD:
    86  		return "MD"
    87  	case DNSTypeMF:
    88  		return "MF"
    89  	case DNSTypeCNAME:
    90  		return "CNAME"
    91  	case DNSTypeSOA:
    92  		return "SOA"
    93  	case DNSTypeMB:
    94  		return "MB"
    95  	case DNSTypeMG:
    96  		return "MG"
    97  	case DNSTypeMR:
    98  		return "MR"
    99  	case DNSTypeNULL:
   100  		return "NULL"
   101  	case DNSTypeWKS:
   102  		return "WKS"
   103  	case DNSTypePTR:
   104  		return "PTR"
   105  	case DNSTypeHINFO:
   106  		return "HINFO"
   107  	case DNSTypeMINFO:
   108  		return "MINFO"
   109  	case DNSTypeMX:
   110  		return "MX"
   111  	case DNSTypeTXT:
   112  		return "TXT"
   113  	case DNSTypeAAAA:
   114  		return "AAAA"
   115  	case DNSTypeSRV:
   116  		return "SRV"
   117  	case DNSTypeOPT:
   118  		return "OPT"
   119  	case DNSTypeURI:
   120  		return "URI"
   121  	}
   122  }
   123  
   124  // DNSResponseCode provides response codes for question answers.
   125  type DNSResponseCode uint8
   126  
   127  // DNSResponseCode known values.
   128  const (
   129  	DNSResponseCodeNoErr     DNSResponseCode = 0  // No error
   130  	DNSResponseCodeFormErr   DNSResponseCode = 1  // Format Error                       [RFC1035]
   131  	DNSResponseCodeServFail  DNSResponseCode = 2  // Server Failure                     [RFC1035]
   132  	DNSResponseCodeNXDomain  DNSResponseCode = 3  // Non-Existent Domain                [RFC1035]
   133  	DNSResponseCodeNotImp    DNSResponseCode = 4  // Not Implemented                    [RFC1035]
   134  	DNSResponseCodeRefused   DNSResponseCode = 5  // Query Refused                      [RFC1035]
   135  	DNSResponseCodeYXDomain  DNSResponseCode = 6  // Name Exists when it should not     [RFC2136]
   136  	DNSResponseCodeYXRRSet   DNSResponseCode = 7  // RR Set Exists when it should not   [RFC2136]
   137  	DNSResponseCodeNXRRSet   DNSResponseCode = 8  // RR Set that should exist does not  [RFC2136]
   138  	DNSResponseCodeNotAuth   DNSResponseCode = 9  // Server Not Authoritative for zone  [RFC2136]
   139  	DNSResponseCodeNotZone   DNSResponseCode = 10 // Name not contained in zone         [RFC2136]
   140  	DNSResponseCodeBadVers   DNSResponseCode = 16 // Bad OPT Version                    [RFC2671]
   141  	DNSResponseCodeBadSig    DNSResponseCode = 16 // TSIG Signature Failure             [RFC2845]
   142  	DNSResponseCodeBadKey    DNSResponseCode = 17 // Key not recognized                 [RFC2845]
   143  	DNSResponseCodeBadTime   DNSResponseCode = 18 // Signature out of time window       [RFC2845]
   144  	DNSResponseCodeBadMode   DNSResponseCode = 19 // Bad TKEY Mode                      [RFC2930]
   145  	DNSResponseCodeBadName   DNSResponseCode = 20 // Duplicate key name                 [RFC2930]
   146  	DNSResponseCodeBadAlg    DNSResponseCode = 21 // Algorithm not supported            [RFC2930]
   147  	DNSResponseCodeBadTruc   DNSResponseCode = 22 // Bad Truncation                     [RFC4635]
   148  	DNSResponseCodeBadCookie DNSResponseCode = 23 // Bad/missing Server Cookie          [RFC7873]
   149  )
   150  
   151  func (drc DNSResponseCode) String() string {
   152  	switch drc {
   153  	default:
   154  		return "Unknown"
   155  	case DNSResponseCodeNoErr:
   156  		return "No Error"
   157  	case DNSResponseCodeFormErr:
   158  		return "Format Error"
   159  	case DNSResponseCodeServFail:
   160  		return "Server Failure "
   161  	case DNSResponseCodeNXDomain:
   162  		return "Non-Existent Domain"
   163  	case DNSResponseCodeNotImp:
   164  		return "Not Implemented"
   165  	case DNSResponseCodeRefused:
   166  		return "Query Refused"
   167  	case DNSResponseCodeYXDomain:
   168  		return "Name Exists when it should not"
   169  	case DNSResponseCodeYXRRSet:
   170  		return "RR Set Exists when it should not"
   171  	case DNSResponseCodeNXRRSet:
   172  		return "RR Set that should exist does not"
   173  	case DNSResponseCodeNotAuth:
   174  		return "Server Not Authoritative for zone"
   175  	case DNSResponseCodeNotZone:
   176  		return "Name not contained in zone"
   177  	case DNSResponseCodeBadVers:
   178  		return "Bad OPT Version"
   179  	case DNSResponseCodeBadKey:
   180  		return "Key not recognized"
   181  	case DNSResponseCodeBadTime:
   182  		return "Signature out of time window"
   183  	case DNSResponseCodeBadMode:
   184  		return "Bad TKEY Mode"
   185  	case DNSResponseCodeBadName:
   186  		return "Duplicate key name"
   187  	case DNSResponseCodeBadAlg:
   188  		return "Algorithm not supported"
   189  	case DNSResponseCodeBadTruc:
   190  		return "Bad Truncation"
   191  	case DNSResponseCodeBadCookie:
   192  		return "Bad Cookie"
   193  	}
   194  }
   195  
   196  // DNSOpCode defines a set of different operation types.
   197  type DNSOpCode uint8
   198  
   199  // DNSOpCode known values.
   200  const (
   201  	DNSOpCodeQuery  DNSOpCode = 0 // Query                  [RFC1035]
   202  	DNSOpCodeIQuery DNSOpCode = 1 // Inverse Query Obsolete [RFC3425]
   203  	DNSOpCodeStatus DNSOpCode = 2 // Status                 [RFC1035]
   204  	DNSOpCodeNotify DNSOpCode = 4 // Notify                 [RFC1996]
   205  	DNSOpCodeUpdate DNSOpCode = 5 // Update                 [RFC2136]
   206  )
   207  
   208  func (doc DNSOpCode) String() string {
   209  	switch doc {
   210  	default:
   211  		return "Unknown"
   212  	case DNSOpCodeQuery:
   213  		return "Query"
   214  	case DNSOpCodeIQuery:
   215  		return "Inverse Query"
   216  	case DNSOpCodeStatus:
   217  		return "Status"
   218  	case DNSOpCodeNotify:
   219  		return "Notify"
   220  	case DNSOpCodeUpdate:
   221  		return "Update"
   222  	}
   223  }
   224  
   225  // DNS is specified in RFC 1034 / RFC 1035
   226  // +---------------------+
   227  // |        Header       |
   228  // +---------------------+
   229  // |       Question      | the question for the name server
   230  // +---------------------+
   231  // |        Answer       | RRs answering the question
   232  // +---------------------+
   233  // |      Authority      | RRs pointing toward an authority
   234  // +---------------------+
   235  // |      Additional     | RRs holding additional information
   236  // +---------------------+
   237  //
   238  //  DNS Header
   239  //  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
   240  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   241  //  |                      ID                       |
   242  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   243  //  |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
   244  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   245  //  |                    QDCOUNT                    |
   246  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   247  //  |                    ANCOUNT                    |
   248  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   249  //  |                    NSCOUNT                    |
   250  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   251  //  |                    ARCOUNT                    |
   252  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   253  
   254  // DNS contains data from a single Domain Name Service packet.
   255  type DNS struct {
   256  	BaseLayer
   257  
   258  	// Header fields
   259  	ID     uint16
   260  	QR     bool
   261  	OpCode DNSOpCode
   262  
   263  	AA bool  // Authoritative answer
   264  	TC bool  // Truncated
   265  	RD bool  // Recursion desired
   266  	RA bool  // Recursion available
   267  	Z  uint8 // Reserved for future use
   268  
   269  	ResponseCode DNSResponseCode
   270  	QDCount      uint16 // Number of questions to expect
   271  	ANCount      uint16 // Number of answers to expect
   272  	NSCount      uint16 // Number of authorities to expect
   273  	ARCount      uint16 // Number of additional records to expect
   274  
   275  	// Entries
   276  	Questions   []DNSQuestion
   277  	Answers     []DNSResourceRecord
   278  	Authorities []DNSResourceRecord
   279  	Additionals []DNSResourceRecord
   280  
   281  	// buffer for doing name decoding.  We use a single reusable buffer to avoid
   282  	// name decoding on a single object via multiple DecodeFromBytes calls
   283  	// requiring constant allocation of small byte slices.
   284  	buffer []byte
   285  }
   286  
   287  // LayerType returns gopacket.LayerTypeDNS.
   288  func (d *DNS) LayerType() gopacket.LayerType { return LayerTypeDNS }
   289  
   290  // decodeDNS decodes the byte slice into a DNS type. It also
   291  // setups the application Layer in PacketBuilder.
   292  func decodeDNS(data []byte, p gopacket.PacketBuilder) error {
   293  	d := &DNS{}
   294  	err := d.DecodeFromBytes(data, p)
   295  	if err != nil {
   296  		return err
   297  	}
   298  	p.AddLayer(d)
   299  	p.SetApplicationLayer(d)
   300  	return nil
   301  }
   302  
   303  // DecodeFromBytes decodes the slice into the DNS struct.
   304  func (d *DNS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   305  	d.buffer = d.buffer[:0]
   306  
   307  	if len(data) < 12 {
   308  		df.SetTruncated()
   309  		return errDNSPacketTooShort
   310  	}
   311  
   312  	// since there are no further layers, the baselayer's content is
   313  	// pointing to this layer
   314  	d.BaseLayer = BaseLayer{Contents: data[:len(data)]}
   315  	d.ID = binary.BigEndian.Uint16(data[:2])
   316  	d.QR = data[2]&0x80 != 0
   317  	d.OpCode = DNSOpCode(data[2]>>3) & 0x0F
   318  	d.AA = data[2]&0x04 != 0
   319  	d.TC = data[2]&0x02 != 0
   320  	d.RD = data[2]&0x01 != 0
   321  	d.RA = data[3]&0x80 != 0
   322  	d.Z = uint8(data[3]>>4) & 0x7
   323  	d.ResponseCode = DNSResponseCode(data[3] & 0xF)
   324  	d.QDCount = binary.BigEndian.Uint16(data[4:6])
   325  	d.ANCount = binary.BigEndian.Uint16(data[6:8])
   326  	d.NSCount = binary.BigEndian.Uint16(data[8:10])
   327  	d.ARCount = binary.BigEndian.Uint16(data[10:12])
   328  
   329  	d.Questions = d.Questions[:0]
   330  	d.Answers = d.Answers[:0]
   331  	d.Authorities = d.Authorities[:0]
   332  	d.Additionals = d.Additionals[:0]
   333  
   334  	offset := 12
   335  	var err error
   336  	for i := 0; i < int(d.QDCount); i++ {
   337  		var q DNSQuestion
   338  		if offset, err = q.decode(data, offset, df, &d.buffer); err != nil {
   339  			return err
   340  		}
   341  		d.Questions = append(d.Questions, q)
   342  	}
   343  
   344  	// For some horrible reason, if we do the obvious thing in this loop:
   345  	//   var r DNSResourceRecord
   346  	//   if blah := r.decode(blah); err != nil {
   347  	//     return err
   348  	//   }
   349  	//   d.Foo = append(d.Foo, r)
   350  	// the Go compiler thinks that 'r' escapes to the heap, causing a malloc for
   351  	// every Answer, Authority, and Additional.  To get around this, we do
   352  	// something really silly:  we append an empty resource record to our slice,
   353  	// then use the last value in the slice to call decode.  Since the value is
   354  	// already in the slice, there's no WAY it can escape... on the other hand our
   355  	// code is MUCH uglier :(
   356  	for i := 0; i < int(d.ANCount); i++ {
   357  		d.Answers = append(d.Answers, DNSResourceRecord{})
   358  		if offset, err = d.Answers[i].decode(data, offset, df, &d.buffer); err != nil {
   359  			d.Answers = d.Answers[:i] // strip off erroneous value
   360  			return err
   361  		}
   362  	}
   363  	for i := 0; i < int(d.NSCount); i++ {
   364  		d.Authorities = append(d.Authorities, DNSResourceRecord{})
   365  		if offset, err = d.Authorities[i].decode(data, offset, df, &d.buffer); err != nil {
   366  			d.Authorities = d.Authorities[:i] // strip off erroneous value
   367  			return err
   368  		}
   369  	}
   370  	for i := 0; i < int(d.ARCount); i++ {
   371  		d.Additionals = append(d.Additionals, DNSResourceRecord{})
   372  		if offset, err = d.Additionals[i].decode(data, offset, df, &d.buffer); err != nil {
   373  			d.Additionals = d.Additionals[:i] // strip off erroneous value
   374  			return err
   375  		}
   376  		// extract extended RCODE from OPT RRs, RFC 6891 section 6.1.3
   377  		if d.Additionals[i].Type == DNSTypeOPT {
   378  			d.ResponseCode = DNSResponseCode(uint8(d.ResponseCode) | uint8(d.Additionals[i].TTL>>20&0xF0))
   379  		}
   380  	}
   381  
   382  	if uint16(len(d.Questions)) != d.QDCount {
   383  		return errDecodeQueryBadQDCount
   384  	} else if uint16(len(d.Answers)) != d.ANCount {
   385  		return errDecodeQueryBadANCount
   386  	} else if uint16(len(d.Authorities)) != d.NSCount {
   387  		return errDecodeQueryBadNSCount
   388  	} else if uint16(len(d.Additionals)) != d.ARCount {
   389  		return errDecodeQueryBadARCount
   390  	}
   391  	return nil
   392  }
   393  
   394  // CanDecode implements gopacket.DecodingLayer.
   395  func (d *DNS) CanDecode() gopacket.LayerClass {
   396  	return LayerTypeDNS
   397  }
   398  
   399  // NextLayerType implements gopacket.DecodingLayer.
   400  func (d *DNS) NextLayerType() gopacket.LayerType {
   401  	return gopacket.LayerTypePayload
   402  }
   403  
   404  // Payload returns nil.
   405  func (d *DNS) Payload() []byte {
   406  	return nil
   407  }
   408  
   409  func b2i(b bool) int {
   410  	if b {
   411  		return 1
   412  	}
   413  	return 0
   414  }
   415  
   416  func recSize(rr *DNSResourceRecord) int {
   417  	switch rr.Type {
   418  	case DNSTypeA:
   419  		return 4
   420  	case DNSTypeAAAA:
   421  		return 16
   422  	case DNSTypeNS:
   423  		return len(rr.NS) + 2
   424  	case DNSTypeCNAME:
   425  		return len(rr.CNAME) + 2
   426  	case DNSTypePTR:
   427  		return len(rr.PTR) + 2
   428  	case DNSTypeSOA:
   429  		return len(rr.SOA.MName) + 2 + len(rr.SOA.RName) + 2 + 20
   430  	case DNSTypeMX:
   431  		return 2 + len(rr.MX.Name) + 2
   432  	case DNSTypeTXT:
   433  		l := len(rr.TXTs)
   434  		for _, txt := range rr.TXTs {
   435  			l += len(txt)
   436  		}
   437  		return l
   438  	case DNSTypeSRV:
   439  		return 6 + len(rr.SRV.Name) + 2
   440  	case DNSTypeURI:
   441  		return 4 + len(rr.URI.Target)
   442  	case DNSTypeOPT:
   443  		l := len(rr.OPT) * 4
   444  		for _, opt := range rr.OPT {
   445  			l += len(opt.Data)
   446  		}
   447  		return l
   448  	}
   449  
   450  	return 0
   451  }
   452  
   453  func computeSize(recs []DNSResourceRecord) int {
   454  	sz := 0
   455  	for _, rr := range recs {
   456  		v := len(rr.Name)
   457  
   458  		if v == 0 {
   459  			sz += v + 11
   460  		} else {
   461  			sz += v + 12
   462  		}
   463  
   464  		sz += recSize(&rr)
   465  	}
   466  	return sz
   467  }
   468  
   469  // SerializeTo writes the serialized form of this layer into the
   470  // SerializationBuffer, implementing gopacket.SerializableLayer.
   471  func (d *DNS) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   472  	dsz := 0
   473  	for _, q := range d.Questions {
   474  		dsz += len(q.Name) + 6
   475  	}
   476  	dsz += computeSize(d.Answers)
   477  	dsz += computeSize(d.Authorities)
   478  	dsz += computeSize(d.Additionals)
   479  
   480  	bytes, err := b.PrependBytes(12 + dsz)
   481  	if err != nil {
   482  		return err
   483  	}
   484  	binary.BigEndian.PutUint16(bytes, d.ID)
   485  	bytes[2] = byte((b2i(d.QR) << 7) | (int(d.OpCode) << 3) | (b2i(d.AA) << 2) | (b2i(d.TC) << 1) | b2i(d.RD))
   486  	bytes[3] = byte((b2i(d.RA) << 7) | (int(d.Z) << 4) | int(d.ResponseCode))
   487  
   488  	if opts.FixLengths {
   489  		d.QDCount = uint16(len(d.Questions))
   490  		d.ANCount = uint16(len(d.Answers))
   491  		d.NSCount = uint16(len(d.Authorities))
   492  		d.ARCount = uint16(len(d.Additionals))
   493  	}
   494  	binary.BigEndian.PutUint16(bytes[4:], d.QDCount)
   495  	binary.BigEndian.PutUint16(bytes[6:], d.ANCount)
   496  	binary.BigEndian.PutUint16(bytes[8:], d.NSCount)
   497  	binary.BigEndian.PutUint16(bytes[10:], d.ARCount)
   498  
   499  	off := 12
   500  	for _, qd := range d.Questions {
   501  		n := qd.encode(bytes, off)
   502  		off += n
   503  	}
   504  
   505  	for i := range d.Answers {
   506  		// done this way so we can modify DNSResourceRecord to fix
   507  		// lengths if requested
   508  		qa := &d.Answers[i]
   509  		n, err := qa.encode(bytes, off, opts)
   510  		if err != nil {
   511  			return err
   512  		}
   513  		off += n
   514  	}
   515  
   516  	for i := range d.Authorities {
   517  		qa := &d.Authorities[i]
   518  		n, err := qa.encode(bytes, off, opts)
   519  		if err != nil {
   520  			return err
   521  		}
   522  		off += n
   523  	}
   524  	for i := range d.Additionals {
   525  		qa := &d.Additionals[i]
   526  		n, err := qa.encode(bytes, off, opts)
   527  		if err != nil {
   528  			return err
   529  		}
   530  		off += n
   531  	}
   532  
   533  	return nil
   534  }
   535  
   536  const maxRecursionLevel = 255
   537  
   538  func decodeName(data []byte, offset int, buffer *[]byte, level int) ([]byte, int, error) {
   539  	if level > maxRecursionLevel {
   540  		return nil, 0, errMaxRecursion
   541  	} else if offset >= len(data) {
   542  		return nil, 0, errDNSNameOffsetTooHigh
   543  	} else if offset < 0 {
   544  		return nil, 0, errDNSNameOffsetNegative
   545  	}
   546  	start := len(*buffer)
   547  	index := offset
   548  	if data[index] == 0x00 {
   549  		return nil, index + 1, nil
   550  	}
   551  loop:
   552  	for data[index] != 0x00 {
   553  		switch data[index] & 0xc0 {
   554  		default:
   555  			/* RFC 1035
   556  			   A domain name represented as a sequence of labels, where
   557  			   each label consists of a length octet followed by that
   558  			   number of octets.  The domain name terminates with the
   559  			   zero length octet for the null label of the root.  Note
   560  			   that this field may be an odd number of octets; no
   561  			   padding is used.
   562  			*/
   563  			index2 := index + int(data[index]) + 1
   564  			if index2-offset > 255 {
   565  				return nil, 0, errDNSNameTooLong
   566  			} else if index2 < index+1 || index2 > len(data) {
   567  				return nil, 0, errDNSNameInvalidIndex
   568  			}
   569  			*buffer = append(*buffer, '.')
   570  			*buffer = append(*buffer, data[index+1:index2]...)
   571  			index = index2
   572  
   573  		case 0xc0:
   574  			/* RFC 1035
   575  			   The pointer takes the form of a two octet sequence.
   576  
   577  			   The first two bits are ones.  This allows a pointer to
   578  			   be distinguished from a label, since the label must
   579  			   begin with two zero bits because labels are restricted
   580  			   to 63 octets or less.  (The 10 and 01 combinations are
   581  			   reserved for future use.)  The OFFSET field specifies
   582  			   an offset from the start of the message (i.e., the
   583  			   first octet of the ID field in the domain header).  A
   584  			   zero offset specifies the first byte of the ID field,
   585  			   etc.
   586  
   587  			   The compression scheme allows a domain name in a message to be
   588  			   represented as either:
   589  			      - a sequence of labels ending in a zero octet
   590  			      - a pointer
   591  			      - a sequence of labels ending with a pointer
   592  			*/
   593  			if index+2 > len(data) {
   594  				return nil, 0, errDNSPointerOffsetTooHigh
   595  			}
   596  			offsetp := int(binary.BigEndian.Uint16(data[index:index+2]) & 0x3fff)
   597  			if offsetp > len(data) {
   598  				return nil, 0, errDNSPointerOffsetTooHigh
   599  			}
   600  			// This looks a little tricky, but actually isn't.  Because of how
   601  			// decodeName is written, calling it appends the decoded name to the
   602  			// current buffer.  We already have the start of the buffer, then, so
   603  			// once this call is done buffer[start:] will contain our full name.
   604  			_, _, err := decodeName(data, offsetp, buffer, level+1)
   605  			if err != nil {
   606  				return nil, 0, err
   607  			}
   608  			index++ // pointer is two bytes, so add an extra byte here.
   609  			break loop
   610  		/* EDNS, or other DNS option ? */
   611  		case 0x40: // RFC 2673
   612  			return nil, 0, fmt.Errorf("qname '0x40' - RFC 2673 unsupported yet (data=%x index=%d)",
   613  				data[index], index)
   614  
   615  		case 0x80:
   616  			return nil, 0, fmt.Errorf("qname '0x80' unsupported yet (data=%x index=%d)",
   617  				data[index], index)
   618  		}
   619  		if index >= len(data) {
   620  			return nil, 0, errDNSIndexOutOfRange
   621  		}
   622  	}
   623  	if len(*buffer) <= start {
   624  		return (*buffer)[start:], index + 1, nil
   625  	}
   626  	return (*buffer)[start+1:], index + 1, nil
   627  }
   628  
   629  // DNSQuestion wraps a single request (question) within a DNS query.
   630  type DNSQuestion struct {
   631  	Name  []byte
   632  	Type  DNSType
   633  	Class DNSClass
   634  }
   635  
   636  func (q *DNSQuestion) decode(data []byte, offset int, df gopacket.DecodeFeedback, buffer *[]byte) (int, error) {
   637  	name, endq, err := decodeName(data, offset, buffer, 1)
   638  	if err != nil {
   639  		return 0, err
   640  	}
   641  
   642  	if len(data) < endq+4 {
   643  		return 0, errors.New("DNS question too small")
   644  	}
   645  
   646  	q.Name = name
   647  	q.Type = DNSType(binary.BigEndian.Uint16(data[endq : endq+2]))
   648  	q.Class = DNSClass(binary.BigEndian.Uint16(data[endq+2 : endq+4]))
   649  
   650  	return endq + 4, nil
   651  }
   652  
   653  func (q *DNSQuestion) encode(data []byte, offset int) int {
   654  	noff := encodeName(q.Name, data, offset)
   655  	nSz := noff - offset
   656  	binary.BigEndian.PutUint16(data[noff:], uint16(q.Type))
   657  	binary.BigEndian.PutUint16(data[noff+2:], uint16(q.Class))
   658  	return nSz + 4
   659  }
   660  
   661  //  DNSResourceRecord
   662  //  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
   663  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   664  //  |                                               |
   665  //  /                                               /
   666  //  /                      NAME                     /
   667  //  |                                               |
   668  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   669  //  |                      TYPE                     |
   670  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   671  //  |                     CLASS                     |
   672  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   673  //  |                      TTL                      |
   674  //  |                                               |
   675  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   676  //  |                   RDLENGTH                    |
   677  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
   678  //  /                     RDATA                     /
   679  //  /                                               /
   680  //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   681  
   682  // DNSResourceRecord wraps the data from a single DNS resource within a
   683  // response.
   684  type DNSResourceRecord struct {
   685  	// Header
   686  	Name  []byte
   687  	Type  DNSType
   688  	Class DNSClass
   689  	TTL   uint32
   690  
   691  	// RDATA Raw Values
   692  	DataLength uint16
   693  	Data       []byte
   694  
   695  	// RDATA Decoded Values
   696  	IP             net.IP
   697  	NS, CNAME, PTR []byte
   698  	TXTs           [][]byte
   699  	SOA            DNSSOA
   700  	SRV            DNSSRV
   701  	MX             DNSMX
   702  	OPT            []DNSOPT // See RFC 6891, section 6.1.2
   703  	URI            DNSURI
   704  
   705  	// Undecoded TXT for backward compatibility
   706  	TXT []byte
   707  }
   708  
   709  // decode decodes the resource record, returning the total length of the record.
   710  func (rr *DNSResourceRecord) decode(data []byte, offset int, df gopacket.DecodeFeedback, buffer *[]byte) (int, error) {
   711  	name, endq, err := decodeName(data, offset, buffer, 1)
   712  	if err != nil {
   713  		return 0, err
   714  	}
   715  
   716  	if len(data) < endq+10 {
   717  		return 0, errors.New("DNS record too small")
   718  	}
   719  
   720  	rr.Name = name
   721  	rr.Type = DNSType(binary.BigEndian.Uint16(data[endq : endq+2]))
   722  	rr.Class = DNSClass(binary.BigEndian.Uint16(data[endq+2 : endq+4]))
   723  	rr.TTL = binary.BigEndian.Uint32(data[endq+4 : endq+8])
   724  	rr.DataLength = binary.BigEndian.Uint16(data[endq+8 : endq+10])
   725  	end := endq + 10 + int(rr.DataLength)
   726  	if end > len(data) {
   727  		return 0, errDecodeRecordLength
   728  	}
   729  	rr.Data = data[endq+10 : end]
   730  
   731  	if rr.DataLength > 0 {
   732  		if err = rr.decodeRData(data[:end], endq+10, buffer); err != nil {
   733  			return 0, err
   734  		}
   735  	}
   736  
   737  	return endq + 10 + int(rr.DataLength), nil
   738  }
   739  
   740  func encodeName(name []byte, data []byte, offset int) int {
   741  	l := 0
   742  	for i := range name {
   743  		if name[i] == '.' {
   744  			data[offset+i-l] = byte(l)
   745  			l = 0
   746  		} else {
   747  			// skip one to write the length
   748  			data[offset+i+1] = name[i]
   749  			l++
   750  		}
   751  	}
   752  
   753  	if len(name) == 0 {
   754  		data[offset] = 0x00 // terminal
   755  		return offset + 1
   756  	}
   757  
   758  	// length for final portion
   759  	data[offset+len(name)-l] = byte(l)
   760  	data[offset+len(name)+1] = 0x00 // terminal
   761  	return offset + len(name) + 2
   762  }
   763  
   764  func (rr *DNSResourceRecord) encode(data []byte, offset int, opts gopacket.SerializeOptions) (int, error) {
   765  
   766  	noff := encodeName(rr.Name, data, offset)
   767  	nSz := noff - offset
   768  
   769  	binary.BigEndian.PutUint16(data[noff:], uint16(rr.Type))
   770  	binary.BigEndian.PutUint16(data[noff+2:], uint16(rr.Class))
   771  	binary.BigEndian.PutUint32(data[noff+4:], uint32(rr.TTL))
   772  
   773  	switch rr.Type {
   774  	case DNSTypeA:
   775  		copy(data[noff+10:], rr.IP.To4())
   776  	case DNSTypeAAAA:
   777  		copy(data[noff+10:], rr.IP)
   778  	case DNSTypeNS:
   779  		encodeName(rr.NS, data, noff+10)
   780  	case DNSTypeCNAME:
   781  		encodeName(rr.CNAME, data, noff+10)
   782  	case DNSTypePTR:
   783  		encodeName(rr.PTR, data, noff+10)
   784  	case DNSTypeSOA:
   785  		noff2 := encodeName(rr.SOA.MName, data, noff+10)
   786  		noff2 = encodeName(rr.SOA.RName, data, noff2)
   787  		binary.BigEndian.PutUint32(data[noff2:], rr.SOA.Serial)
   788  		binary.BigEndian.PutUint32(data[noff2+4:], rr.SOA.Refresh)
   789  		binary.BigEndian.PutUint32(data[noff2+8:], rr.SOA.Retry)
   790  		binary.BigEndian.PutUint32(data[noff2+12:], rr.SOA.Expire)
   791  		binary.BigEndian.PutUint32(data[noff2+16:], rr.SOA.Minimum)
   792  	case DNSTypeMX:
   793  		binary.BigEndian.PutUint16(data[noff+10:], rr.MX.Preference)
   794  		encodeName(rr.MX.Name, data, noff+12)
   795  	case DNSTypeTXT:
   796  		noff2 := noff + 10
   797  		for _, txt := range rr.TXTs {
   798  			data[noff2] = byte(len(txt))
   799  			copy(data[noff2+1:], txt)
   800  			noff2 += 1 + len(txt)
   801  		}
   802  	case DNSTypeSRV:
   803  		binary.BigEndian.PutUint16(data[noff+10:], rr.SRV.Priority)
   804  		binary.BigEndian.PutUint16(data[noff+12:], rr.SRV.Weight)
   805  		binary.BigEndian.PutUint16(data[noff+14:], rr.SRV.Port)
   806  		encodeName(rr.SRV.Name, data, noff+16)
   807  	case DNSTypeURI:
   808  		binary.BigEndian.PutUint16(data[noff+10:], rr.URI.Priority)
   809  		binary.BigEndian.PutUint16(data[noff+12:], rr.URI.Weight)
   810  		copy(data[noff+14:], rr.URI.Target)
   811  	case DNSTypeOPT:
   812  		noff2 := noff + 10
   813  		for _, opt := range rr.OPT {
   814  			binary.BigEndian.PutUint16(data[noff2:], uint16(opt.Code))
   815  			binary.BigEndian.PutUint16(data[noff2+2:], uint16(len(opt.Data)))
   816  			copy(data[noff2+4:], opt.Data)
   817  			noff2 += 4 + len(opt.Data)
   818  		}
   819  	default:
   820  		return 0, fmt.Errorf("serializing resource record of type %v not supported", rr.Type)
   821  	}
   822  
   823  	// DataLength
   824  	dSz := recSize(rr)
   825  	binary.BigEndian.PutUint16(data[noff+8:], uint16(dSz))
   826  
   827  	if opts.FixLengths {
   828  		rr.DataLength = uint16(dSz)
   829  	}
   830  
   831  	return nSz + 10 + dSz, nil
   832  }
   833  
   834  func (rr *DNSResourceRecord) String() string {
   835  
   836  	if rr.Type == DNSTypeOPT {
   837  		opts := make([]string, len(rr.OPT))
   838  		for i, opt := range rr.OPT {
   839  			opts[i] = opt.String()
   840  		}
   841  		return "OPT " + strings.Join(opts, ",")
   842  	}
   843  	if rr.Type == DNSTypeURI {
   844  		return fmt.Sprintf("URI %d %d %s", rr.URI.Priority, rr.URI.Weight, string(rr.URI.Target))
   845  	}
   846  	if rr.Class == DNSClassIN {
   847  		switch rr.Type {
   848  		case DNSTypeA, DNSTypeAAAA:
   849  			return rr.IP.String()
   850  		case DNSTypeNS:
   851  			return "NS " + string(rr.NS)
   852  		case DNSTypeCNAME:
   853  			return "CNAME " + string(rr.CNAME)
   854  		case DNSTypePTR:
   855  			return "PTR " + string(rr.PTR)
   856  		case DNSTypeTXT:
   857  			return "TXT " + string(rr.TXT)
   858  		}
   859  	}
   860  
   861  	return fmt.Sprintf("<%v, %v>", rr.Class, rr.Type)
   862  }
   863  
   864  func decodeCharacterStrings(data []byte) ([][]byte, error) {
   865  	strings := make([][]byte, 0, 1)
   866  	end := len(data)
   867  	for index, index2 := 0, 0; index != end; index = index2 {
   868  		index2 = index + 1 + int(data[index]) // index increases by 1..256 and does not overflow
   869  		if index2 > end {
   870  			return nil, errCharStringMissData
   871  		}
   872  		strings = append(strings, data[index+1:index2])
   873  	}
   874  	return strings, nil
   875  }
   876  
   877  func decodeOPTs(data []byte, offset int) ([]DNSOPT, error) {
   878  	allOPT := []DNSOPT{}
   879  	end := len(data)
   880  
   881  	if offset == end {
   882  		return allOPT, nil // There is no data to read
   883  	}
   884  
   885  	if offset+4 > end {
   886  		return allOPT, fmt.Errorf("DNSOPT record is of length %d, it should be at least length 4", end-offset)
   887  	}
   888  
   889  	for i := offset; i < end; {
   890  		opt := DNSOPT{}
   891  		if len(data) < i+4 {
   892  			return allOPT, fmt.Errorf("Malformed DNSOPT record.  Length %d < %d", len(data), i+4)
   893  		}
   894  		opt.Code = DNSOptionCode(binary.BigEndian.Uint16(data[i : i+2]))
   895  		l := binary.BigEndian.Uint16(data[i+2 : i+4])
   896  		if i+4+int(l) > end {
   897  			return allOPT, fmt.Errorf("Malformed DNSOPT record. The length (%d) field implies a packet larger than the one received", l)
   898  		}
   899  		opt.Data = data[i+4 : i+4+int(l)]
   900  		allOPT = append(allOPT, opt)
   901  		i += int(l) + 4
   902  	}
   903  	return allOPT, nil
   904  }
   905  
   906  func (rr *DNSResourceRecord) decodeRData(data []byte, offset int, buffer *[]byte) error {
   907  	switch rr.Type {
   908  	case DNSTypeA:
   909  		rr.IP = rr.Data
   910  	case DNSTypeAAAA:
   911  		rr.IP = rr.Data
   912  	case DNSTypeTXT, DNSTypeHINFO:
   913  		rr.TXT = rr.Data
   914  		txts, err := decodeCharacterStrings(rr.Data)
   915  		if err != nil {
   916  			return err
   917  		}
   918  		rr.TXTs = txts
   919  	case DNSTypeNS:
   920  		name, _, err := decodeName(data, offset, buffer, 1)
   921  		if err != nil {
   922  			return err
   923  		}
   924  		rr.NS = name
   925  	case DNSTypeCNAME:
   926  		name, _, err := decodeName(data, offset, buffer, 1)
   927  		if err != nil {
   928  			return err
   929  		}
   930  		rr.CNAME = name
   931  	case DNSTypePTR:
   932  		name, _, err := decodeName(data, offset, buffer, 1)
   933  		if err != nil {
   934  			return err
   935  		}
   936  		rr.PTR = name
   937  	case DNSTypeSOA:
   938  		name, endq, err := decodeName(data, offset, buffer, 1)
   939  		if err != nil {
   940  			return err
   941  		}
   942  		rr.SOA.MName = name
   943  		name, endq, err = decodeName(data, endq, buffer, 1)
   944  		if err != nil {
   945  			return err
   946  		}
   947  		if len(data) < endq+20 {
   948  			return errors.New("SOA too small")
   949  		}
   950  		rr.SOA.RName = name
   951  		rr.SOA.Serial = binary.BigEndian.Uint32(data[endq : endq+4])
   952  		rr.SOA.Refresh = binary.BigEndian.Uint32(data[endq+4 : endq+8])
   953  		rr.SOA.Retry = binary.BigEndian.Uint32(data[endq+8 : endq+12])
   954  		rr.SOA.Expire = binary.BigEndian.Uint32(data[endq+12 : endq+16])
   955  		rr.SOA.Minimum = binary.BigEndian.Uint32(data[endq+16 : endq+20])
   956  	case DNSTypeMX:
   957  		if len(data) < offset+2 {
   958  			return errors.New("MX too small")
   959  		}
   960  		rr.MX.Preference = binary.BigEndian.Uint16(data[offset : offset+2])
   961  		name, _, err := decodeName(data, offset+2, buffer, 1)
   962  		if err != nil {
   963  			return err
   964  		}
   965  		rr.MX.Name = name
   966  	case DNSTypeURI:
   967  		if len(rr.Data) < 4 {
   968  			return errors.New("URI too small")
   969  		}
   970  		rr.URI.Priority = binary.BigEndian.Uint16(data[offset : offset+2])
   971  		rr.URI.Weight = binary.BigEndian.Uint16(data[offset+2 : offset+4])
   972  		rr.URI.Target = rr.Data[4:]
   973  	case DNSTypeSRV:
   974  		if len(data) < offset+6 {
   975  			return errors.New("SRV too small")
   976  		}
   977  		rr.SRV.Priority = binary.BigEndian.Uint16(data[offset : offset+2])
   978  		rr.SRV.Weight = binary.BigEndian.Uint16(data[offset+2 : offset+4])
   979  		rr.SRV.Port = binary.BigEndian.Uint16(data[offset+4 : offset+6])
   980  		name, _, err := decodeName(data, offset+6, buffer, 1)
   981  		if err != nil {
   982  			return err
   983  		}
   984  		rr.SRV.Name = name
   985  	case DNSTypeOPT:
   986  		allOPT, err := decodeOPTs(data, offset)
   987  		if err != nil {
   988  			return err
   989  		}
   990  		rr.OPT = allOPT
   991  	}
   992  	return nil
   993  }
   994  
   995  // DNSSOA is a Start of Authority record.  Each domain requires a SOA record at
   996  // the cutover where a domain is delegated from its parent.
   997  type DNSSOA struct {
   998  	MName, RName                            []byte
   999  	Serial, Refresh, Retry, Expire, Minimum uint32
  1000  }
  1001  
  1002  // DNSSRV is a Service record, defining a location (hostname/port) of a
  1003  // server/service.
  1004  type DNSSRV struct {
  1005  	Priority, Weight, Port uint16
  1006  	Name                   []byte
  1007  }
  1008  
  1009  // DNSMX is a mail exchange record, defining a mail server for a recipient's
  1010  // domain.
  1011  type DNSMX struct {
  1012  	Preference uint16
  1013  	Name       []byte
  1014  }
  1015  
  1016  // DNSURI is a URI record, defining a target (URI) of a server/service
  1017  type DNSURI struct {
  1018  	Priority, Weight uint16
  1019  	Target           []byte
  1020  }
  1021  
  1022  // DNSOptionCode represents the code of a DNS Option, see RFC6891, section 6.1.2
  1023  type DNSOptionCode uint16
  1024  
  1025  func (doc DNSOptionCode) String() string {
  1026  	switch doc {
  1027  	default:
  1028  		return "Unknown"
  1029  	case DNSOptionCodeNSID:
  1030  		return "NSID"
  1031  	case DNSOptionCodeDAU:
  1032  		return "DAU"
  1033  	case DNSOptionCodeDHU:
  1034  		return "DHU"
  1035  	case DNSOptionCodeN3U:
  1036  		return "N3U"
  1037  	case DNSOptionCodeEDNSClientSubnet:
  1038  		return "EDNSClientSubnet"
  1039  	case DNSOptionCodeEDNSExpire:
  1040  		return "EDNSExpire"
  1041  	case DNSOptionCodeCookie:
  1042  		return "Cookie"
  1043  	case DNSOptionCodeEDNSKeepAlive:
  1044  		return "EDNSKeepAlive"
  1045  	case DNSOptionCodePadding:
  1046  		return "CodePadding"
  1047  	case DNSOptionCodeChain:
  1048  		return "CodeChain"
  1049  	case DNSOptionCodeEDNSKeyTag:
  1050  		return "CodeEDNSKeyTag"
  1051  	case DNSOptionCodeEDNSClientTag:
  1052  		return "EDNSClientTag"
  1053  	case DNSOptionCodeEDNSServerTag:
  1054  		return "EDNSServerTag"
  1055  	case DNSOptionCodeDeviceID:
  1056  		return "DeviceID"
  1057  	}
  1058  }
  1059  
  1060  // DNSOptionCode known values. See IANA
  1061  const (
  1062  	DNSOptionCodeNSID             DNSOptionCode = 3
  1063  	DNSOptionCodeDAU              DNSOptionCode = 5
  1064  	DNSOptionCodeDHU              DNSOptionCode = 6
  1065  	DNSOptionCodeN3U              DNSOptionCode = 7
  1066  	DNSOptionCodeEDNSClientSubnet DNSOptionCode = 8
  1067  	DNSOptionCodeEDNSExpire       DNSOptionCode = 9
  1068  	DNSOptionCodeCookie           DNSOptionCode = 10
  1069  	DNSOptionCodeEDNSKeepAlive    DNSOptionCode = 11
  1070  	DNSOptionCodePadding          DNSOptionCode = 12
  1071  	DNSOptionCodeChain            DNSOptionCode = 13
  1072  	DNSOptionCodeEDNSKeyTag       DNSOptionCode = 14
  1073  	DNSOptionCodeEDNSClientTag    DNSOptionCode = 16
  1074  	DNSOptionCodeEDNSServerTag    DNSOptionCode = 17
  1075  	DNSOptionCodeDeviceID         DNSOptionCode = 26946
  1076  )
  1077  
  1078  // DNSOPT is a DNS Option, see RFC6891, section 6.1.2
  1079  type DNSOPT struct {
  1080  	Code DNSOptionCode
  1081  	Data []byte
  1082  }
  1083  
  1084  func (opt DNSOPT) String() string {
  1085  	return fmt.Sprintf("%s=%x", opt.Code, opt.Data)
  1086  }
  1087  
  1088  var (
  1089  	errMaxRecursion = errors.New("max DNS recursion level hit")
  1090  
  1091  	errDNSNameOffsetTooHigh    = errors.New("dns name offset too high")
  1092  	errDNSNameOffsetNegative   = errors.New("dns name offset is negative")
  1093  	errDNSPacketTooShort       = errors.New("DNS packet too short")
  1094  	errDNSNameTooLong          = errors.New("dns name is too long")
  1095  	errDNSNameInvalidIndex     = errors.New("dns name uncomputable: invalid index")
  1096  	errDNSPointerOffsetTooHigh = errors.New("dns offset pointer too high")
  1097  	errDNSIndexOutOfRange      = errors.New("dns index walked out of range")
  1098  	errDNSNameHasNoData        = errors.New("no dns data found for name")
  1099  
  1100  	errCharStringMissData = errors.New("Insufficient data for a <character-string>")
  1101  
  1102  	errDecodeRecordLength = errors.New("resource record length exceeds data")
  1103  
  1104  	errDecodeQueryBadQDCount = errors.New("Invalid query decoding, not the right number of questions")
  1105  	errDecodeQueryBadANCount = errors.New("Invalid query decoding, not the right number of answers")
  1106  	errDecodeQueryBadNSCount = errors.New("Invalid query decoding, not the right number of authorities")
  1107  	errDecodeQueryBadARCount = errors.New("Invalid query decoding, not the right number of additionals info")
  1108  )