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
7package layers
8
9import (
10	"encoding/binary"
11	"errors"
12	"fmt"
13	"net"
14	"strings"
15
16	"github.com/google/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.
21type DNSClass uint16
22
23// DNSClass known values.
24const (
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
32func (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.
51type DNSType uint16
52
53// DNSType known values.
54const (
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
77func (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.
125type DNSResponseCode uint8
126
127// DNSResponseCode known values.
128const (
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
151func (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.
197type DNSOpCode uint8
198
199// DNSOpCode known values.
200const (
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
208func (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.
255type 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.
288func (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.
292func 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.
304func (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.
395func (d *DNS) CanDecode() gopacket.LayerClass {
396	return LayerTypeDNS
397}
398
399// NextLayerType implements gopacket.DecodingLayer.
400func (d *DNS) NextLayerType() gopacket.LayerType {
401	return gopacket.LayerTypePayload
402}
403
404// Payload returns nil.
405func (d *DNS) Payload() []byte {
406	return nil
407}
408
409func b2i(b bool) int {
410	if b {
411		return 1
412	}
413	return 0
414}
415
416func 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
453func 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.
471func (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
536const maxRecursionLevel = 255
537
538func 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	}
551loop:
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.
630type DNSQuestion struct {
631	Name  []byte
632	Type  DNSType
633	Class DNSClass
634}
635
636func (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	q.Name = name
643	q.Type = DNSType(binary.BigEndian.Uint16(data[endq : endq+2]))
644	q.Class = DNSClass(binary.BigEndian.Uint16(data[endq+2 : endq+4]))
645
646	return endq + 4, nil
647}
648
649func (q *DNSQuestion) encode(data []byte, offset int) int {
650	noff := encodeName(q.Name, data, offset)
651	nSz := noff - offset
652	binary.BigEndian.PutUint16(data[noff:], uint16(q.Type))
653	binary.BigEndian.PutUint16(data[noff+2:], uint16(q.Class))
654	return nSz + 4
655}
656
657//  DNSResourceRecord
658//  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
659//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
660//  |                                               |
661//  /                                               /
662//  /                      NAME                     /
663//  |                                               |
664//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
665//  |                      TYPE                     |
666//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
667//  |                     CLASS                     |
668//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
669//  |                      TTL                      |
670//  |                                               |
671//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
672//  |                   RDLENGTH                    |
673//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
674//  /                     RDATA                     /
675//  /                                               /
676//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
677
678// DNSResourceRecord wraps the data from a single DNS resource within a
679// response.
680type DNSResourceRecord struct {
681	// Header
682	Name  []byte
683	Type  DNSType
684	Class DNSClass
685	TTL   uint32
686
687	// RDATA Raw Values
688	DataLength uint16
689	Data       []byte
690
691	// RDATA Decoded Values
692	IP             net.IP
693	NS, CNAME, PTR []byte
694	TXTs           [][]byte
695	SOA            DNSSOA
696	SRV            DNSSRV
697	MX             DNSMX
698	OPT            []DNSOPT // See RFC 6891, section 6.1.2
699	URI            DNSURI
700
701	// Undecoded TXT for backward compatibility
702	TXT []byte
703}
704
705// decode decodes the resource record, returning the total length of the record.
706func (rr *DNSResourceRecord) decode(data []byte, offset int, df gopacket.DecodeFeedback, buffer *[]byte) (int, error) {
707	name, endq, err := decodeName(data, offset, buffer, 1)
708	if err != nil {
709		return 0, err
710	}
711
712	rr.Name = name
713	rr.Type = DNSType(binary.BigEndian.Uint16(data[endq : endq+2]))
714	rr.Class = DNSClass(binary.BigEndian.Uint16(data[endq+2 : endq+4]))
715	rr.TTL = binary.BigEndian.Uint32(data[endq+4 : endq+8])
716	rr.DataLength = binary.BigEndian.Uint16(data[endq+8 : endq+10])
717	end := endq + 10 + int(rr.DataLength)
718	if end > len(data) {
719		return 0, errDecodeRecordLength
720	}
721	rr.Data = data[endq+10 : end]
722
723	if err = rr.decodeRData(data[:end], endq+10, buffer); err != nil {
724		return 0, err
725	}
726
727	return endq + 10 + int(rr.DataLength), nil
728}
729
730func encodeName(name []byte, data []byte, offset int) int {
731	l := 0
732	for i := range name {
733		if name[i] == '.' {
734			data[offset+i-l] = byte(l)
735			l = 0
736		} else {
737			// skip one to write the length
738			data[offset+i+1] = name[i]
739			l++
740		}
741	}
742
743	if len(name) == 0 {
744		data[offset] = 0x00 // terminal
745		return offset + 1
746	}
747
748	// length for final portion
749	data[offset+len(name)-l] = byte(l)
750	data[offset+len(name)+1] = 0x00 // terminal
751	return offset + len(name) + 2
752}
753
754func (rr *DNSResourceRecord) encode(data []byte, offset int, opts gopacket.SerializeOptions) (int, error) {
755
756	noff := encodeName(rr.Name, data, offset)
757	nSz := noff - offset
758
759	binary.BigEndian.PutUint16(data[noff:], uint16(rr.Type))
760	binary.BigEndian.PutUint16(data[noff+2:], uint16(rr.Class))
761	binary.BigEndian.PutUint32(data[noff+4:], uint32(rr.TTL))
762
763	switch rr.Type {
764	case DNSTypeA:
765		copy(data[noff+10:], rr.IP.To4())
766	case DNSTypeAAAA:
767		copy(data[noff+10:], rr.IP)
768	case DNSTypeNS:
769		encodeName(rr.NS, data, noff+10)
770	case DNSTypeCNAME:
771		encodeName(rr.CNAME, data, noff+10)
772	case DNSTypePTR:
773		encodeName(rr.PTR, data, noff+10)
774	case DNSTypeSOA:
775		noff2 := encodeName(rr.SOA.MName, data, noff+10)
776		noff2 = encodeName(rr.SOA.RName, data, noff2)
777		binary.BigEndian.PutUint32(data[noff2:], rr.SOA.Serial)
778		binary.BigEndian.PutUint32(data[noff2+4:], rr.SOA.Refresh)
779		binary.BigEndian.PutUint32(data[noff2+8:], rr.SOA.Retry)
780		binary.BigEndian.PutUint32(data[noff2+12:], rr.SOA.Expire)
781		binary.BigEndian.PutUint32(data[noff2+16:], rr.SOA.Minimum)
782	case DNSTypeMX:
783		binary.BigEndian.PutUint16(data[noff+10:], rr.MX.Preference)
784		encodeName(rr.MX.Name, data, noff+12)
785	case DNSTypeTXT:
786		noff2 := noff + 10
787		for _, txt := range rr.TXTs {
788			data[noff2] = byte(len(txt))
789			copy(data[noff2+1:], txt)
790			noff2 += 1 + len(txt)
791		}
792	case DNSTypeSRV:
793		binary.BigEndian.PutUint16(data[noff+10:], rr.SRV.Priority)
794		binary.BigEndian.PutUint16(data[noff+12:], rr.SRV.Weight)
795		binary.BigEndian.PutUint16(data[noff+14:], rr.SRV.Port)
796		encodeName(rr.SRV.Name, data, noff+16)
797	case DNSTypeURI:
798		binary.BigEndian.PutUint16(data[noff+10:], rr.URI.Priority)
799		binary.BigEndian.PutUint16(data[noff+12:], rr.URI.Weight)
800		copy(data[noff+14:], rr.URI.Target)
801	case DNSTypeOPT:
802		noff2 := noff + 10
803		for _, opt := range rr.OPT {
804			binary.BigEndian.PutUint16(data[noff2:], uint16(opt.Code))
805			binary.BigEndian.PutUint16(data[noff2+2:], uint16(len(opt.Data)))
806			copy(data[noff2+4:], opt.Data)
807			noff2 += 4 + len(opt.Data)
808		}
809	default:
810		return 0, fmt.Errorf("serializing resource record of type %v not supported", rr.Type)
811	}
812
813	// DataLength
814	dSz := recSize(rr)
815	binary.BigEndian.PutUint16(data[noff+8:], uint16(dSz))
816
817	if opts.FixLengths {
818		rr.DataLength = uint16(dSz)
819	}
820
821	return nSz + 10 + dSz, nil
822}
823
824func (rr *DNSResourceRecord) String() string {
825
826	if rr.Type == DNSTypeOPT {
827		opts := make([]string, len(rr.OPT))
828		for i, opt := range rr.OPT {
829			opts[i] = opt.String()
830		}
831		return "OPT " + strings.Join(opts, ",")
832	}
833	if rr.Type == DNSTypeURI {
834		return fmt.Sprintf("URI %d %d %s", rr.URI.Priority, rr.URI.Weight, string(rr.URI.Target))
835	}
836	if rr.Class == DNSClassIN {
837		switch rr.Type {
838		case DNSTypeA, DNSTypeAAAA:
839			return rr.IP.String()
840		case DNSTypeNS:
841			return "NS " + string(rr.NS)
842		case DNSTypeCNAME:
843			return "CNAME " + string(rr.CNAME)
844		case DNSTypePTR:
845			return "PTR " + string(rr.PTR)
846		case DNSTypeTXT:
847			return "TXT " + string(rr.TXT)
848		}
849	}
850
851	return fmt.Sprintf("<%v, %v>", rr.Class, rr.Type)
852}
853
854func decodeCharacterStrings(data []byte) ([][]byte, error) {
855	strings := make([][]byte, 0, 1)
856	end := len(data)
857	for index, index2 := 0, 0; index != end; index = index2 {
858		index2 = index + 1 + int(data[index]) // index increases by 1..256 and does not overflow
859		if index2 > end {
860			return nil, errCharStringMissData
861		}
862		strings = append(strings, data[index+1:index2])
863	}
864	return strings, nil
865}
866
867func decodeOPTs(data []byte, offset int) ([]DNSOPT, error) {
868	allOPT := []DNSOPT{}
869	end := len(data)
870
871	if offset == end {
872		return allOPT, nil // There is no data to read
873	}
874
875	if offset+4 > end {
876		return allOPT, fmt.Errorf("DNSOPT record is of length %d, it should be at least length 4", end-offset)
877	}
878
879	for i := offset; i < end; {
880		opt := DNSOPT{}
881		if len(data) < i+4 {
882			return allOPT, fmt.Errorf("Malformed DNSOPT record.  Length %d < %d", len(data), i+4)
883		}
884		opt.Code = DNSOptionCode(binary.BigEndian.Uint16(data[i : i+2]))
885		l := binary.BigEndian.Uint16(data[i+2 : i+4])
886		if i+4+int(l) > end {
887			return allOPT, fmt.Errorf("Malformed DNSOPT record. The length (%d) field implies a packet larger than the one received", l)
888		}
889		opt.Data = data[i+4 : i+4+int(l)]
890		allOPT = append(allOPT, opt)
891		i += int(l) + 4
892	}
893	return allOPT, nil
894}
895
896func (rr *DNSResourceRecord) decodeRData(data []byte, offset int, buffer *[]byte) error {
897	switch rr.Type {
898	case DNSTypeA:
899		rr.IP = rr.Data
900	case DNSTypeAAAA:
901		rr.IP = rr.Data
902	case DNSTypeTXT, DNSTypeHINFO:
903		rr.TXT = rr.Data
904		txts, err := decodeCharacterStrings(rr.Data)
905		if err != nil {
906			return err
907		}
908		rr.TXTs = txts
909	case DNSTypeNS:
910		name, _, err := decodeName(data, offset, buffer, 1)
911		if err != nil {
912			return err
913		}
914		rr.NS = name
915	case DNSTypeCNAME:
916		name, _, err := decodeName(data, offset, buffer, 1)
917		if err != nil {
918			return err
919		}
920		rr.CNAME = name
921	case DNSTypePTR:
922		name, _, err := decodeName(data, offset, buffer, 1)
923		if err != nil {
924			return err
925		}
926		rr.PTR = name
927	case DNSTypeSOA:
928		name, endq, err := decodeName(data, offset, buffer, 1)
929		if err != nil {
930			return err
931		}
932		rr.SOA.MName = name
933		name, endq, err = decodeName(data, endq, buffer, 1)
934		if err != nil {
935			return err
936		}
937		if len(data) < endq+20 {
938			return errors.New("SOA too small")
939		}
940		rr.SOA.RName = name
941		rr.SOA.Serial = binary.BigEndian.Uint32(data[endq : endq+4])
942		rr.SOA.Refresh = binary.BigEndian.Uint32(data[endq+4 : endq+8])
943		rr.SOA.Retry = binary.BigEndian.Uint32(data[endq+8 : endq+12])
944		rr.SOA.Expire = binary.BigEndian.Uint32(data[endq+12 : endq+16])
945		rr.SOA.Minimum = binary.BigEndian.Uint32(data[endq+16 : endq+20])
946	case DNSTypeMX:
947		if len(data) < offset+2 {
948			return errors.New("MX too small")
949		}
950		rr.MX.Preference = binary.BigEndian.Uint16(data[offset : offset+2])
951		name, _, err := decodeName(data, offset+2, buffer, 1)
952		if err != nil {
953			return err
954		}
955		rr.MX.Name = name
956	case DNSTypeURI:
957		if len(rr.Data) < 4 {
958			return errors.New("URI too small")
959		}
960		rr.URI.Priority = binary.BigEndian.Uint16(data[offset : offset+2])
961		rr.URI.Weight = binary.BigEndian.Uint16(data[offset+2 : offset+4])
962		rr.URI.Target = rr.Data[4:]
963	case DNSTypeSRV:
964		if len(data) < offset+6 {
965			return errors.New("SRV too small")
966		}
967		rr.SRV.Priority = binary.BigEndian.Uint16(data[offset : offset+2])
968		rr.SRV.Weight = binary.BigEndian.Uint16(data[offset+2 : offset+4])
969		rr.SRV.Port = binary.BigEndian.Uint16(data[offset+4 : offset+6])
970		name, _, err := decodeName(data, offset+6, buffer, 1)
971		if err != nil {
972			return err
973		}
974		rr.SRV.Name = name
975	case DNSTypeOPT:
976		allOPT, err := decodeOPTs(data, offset)
977		if err != nil {
978			return err
979		}
980		rr.OPT = allOPT
981	}
982	return nil
983}
984
985// DNSSOA is a Start of Authority record.  Each domain requires a SOA record at
986// the cutover where a domain is delegated from its parent.
987type DNSSOA struct {
988	MName, RName                            []byte
989	Serial, Refresh, Retry, Expire, Minimum uint32
990}
991
992// DNSSRV is a Service record, defining a location (hostname/port) of a
993// server/service.
994type DNSSRV struct {
995	Priority, Weight, Port uint16
996	Name                   []byte
997}
998
999// DNSMX is a mail exchange record, defining a mail server for a recipient's
1000// domain.
1001type DNSMX struct {
1002	Preference uint16
1003	Name       []byte
1004}
1005
1006// DNSURI is a URI record, defining a target (URI) of a server/service
1007type DNSURI struct {
1008	Priority, Weight uint16
1009	Target           []byte
1010}
1011
1012// DNSOptionCode represents the code of a DNS Option, see RFC6891, section 6.1.2
1013type DNSOptionCode uint16
1014
1015func (doc DNSOptionCode) String() string {
1016	switch doc {
1017	default:
1018		return "Unknown"
1019	case DNSOptionCodeNSID:
1020		return "NSID"
1021	case DNSOptionCodeDAU:
1022		return "DAU"
1023	case DNSOptionCodeDHU:
1024		return "DHU"
1025	case DNSOptionCodeN3U:
1026		return "N3U"
1027	case DNSOptionCodeEDNSClientSubnet:
1028		return "EDNSClientSubnet"
1029	case DNSOptionCodeEDNSExpire:
1030		return "EDNSExpire"
1031	case DNSOptionCodeCookie:
1032		return "Cookie"
1033	case DNSOptionCodeEDNSKeepAlive:
1034		return "EDNSKeepAlive"
1035	case DNSOptionCodePadding:
1036		return "CodePadding"
1037	case DNSOptionCodeChain:
1038		return "CodeChain"
1039	case DNSOptionCodeEDNSKeyTag:
1040		return "CodeEDNSKeyTag"
1041	case DNSOptionCodeEDNSClientTag:
1042		return "EDNSClientTag"
1043	case DNSOptionCodeEDNSServerTag:
1044		return "EDNSServerTag"
1045	case DNSOptionCodeDeviceID:
1046		return "DeviceID"
1047	}
1048}
1049
1050// DNSOptionCode known values. See IANA
1051const (
1052	DNSOptionCodeNSID             DNSOptionCode = 3
1053	DNSOptionCodeDAU              DNSOptionCode = 5
1054	DNSOptionCodeDHU              DNSOptionCode = 6
1055	DNSOptionCodeN3U              DNSOptionCode = 7
1056	DNSOptionCodeEDNSClientSubnet DNSOptionCode = 8
1057	DNSOptionCodeEDNSExpire       DNSOptionCode = 9
1058	DNSOptionCodeCookie           DNSOptionCode = 10
1059	DNSOptionCodeEDNSKeepAlive    DNSOptionCode = 11
1060	DNSOptionCodePadding          DNSOptionCode = 12
1061	DNSOptionCodeChain            DNSOptionCode = 13
1062	DNSOptionCodeEDNSKeyTag       DNSOptionCode = 14
1063	DNSOptionCodeEDNSClientTag    DNSOptionCode = 16
1064	DNSOptionCodeEDNSServerTag    DNSOptionCode = 17
1065	DNSOptionCodeDeviceID         DNSOptionCode = 26946
1066)
1067
1068// DNSOPT is a DNS Option, see RFC6891, section 6.1.2
1069type DNSOPT struct {
1070	Code DNSOptionCode
1071	Data []byte
1072}
1073
1074func (opt DNSOPT) String() string {
1075	return fmt.Sprintf("%s=%x", opt.Code, opt.Data)
1076}
1077
1078var (
1079	errMaxRecursion = errors.New("max DNS recursion level hit")
1080
1081	errDNSNameOffsetTooHigh    = errors.New("dns name offset too high")
1082	errDNSNameOffsetNegative   = errors.New("dns name offset is negative")
1083	errDNSPacketTooShort       = errors.New("DNS packet too short")
1084	errDNSNameTooLong          = errors.New("dns name is too long")
1085	errDNSNameInvalidIndex     = errors.New("dns name uncomputable: invalid index")
1086	errDNSPointerOffsetTooHigh = errors.New("dns offset pointer too high")
1087	errDNSIndexOutOfRange      = errors.New("dns index walked out of range")
1088	errDNSNameHasNoData        = errors.New("no dns data found for name")
1089
1090	errCharStringMissData = errors.New("Insufficient data for a <character-string>")
1091
1092	errDecodeRecordLength = errors.New("resource record length exceeds data")
1093
1094	errDecodeQueryBadQDCount = errors.New("Invalid query decoding, not the right number of questions")
1095	errDecodeQueryBadANCount = errors.New("Invalid query decoding, not the right number of answers")
1096	errDecodeQueryBadNSCount = errors.New("Invalid query decoding, not the right number of authorities")
1097	errDecodeQueryBadARCount = errors.New("Invalid query decoding, not the right number of additionals info")
1098)
1099