blob: b639dec15dc1a1852987f5890c38638e7cbee300 [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301// 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 rr.DataLength > 0 {
724 if err = rr.decodeRData(data[:end], endq+10, buffer); err != nil {
725 return 0, err
726 }
727 }
728
729 return endq + 10 + int(rr.DataLength), nil
730}
731
732func encodeName(name []byte, data []byte, offset int) int {
733 l := 0
734 for i := range name {
735 if name[i] == '.' {
736 data[offset+i-l] = byte(l)
737 l = 0
738 } else {
739 // skip one to write the length
740 data[offset+i+1] = name[i]
741 l++
742 }
743 }
744
745 if len(name) == 0 {
746 data[offset] = 0x00 // terminal
747 return offset + 1
748 }
749
750 // length for final portion
751 data[offset+len(name)-l] = byte(l)
752 data[offset+len(name)+1] = 0x00 // terminal
753 return offset + len(name) + 2
754}
755
756func (rr *DNSResourceRecord) encode(data []byte, offset int, opts gopacket.SerializeOptions) (int, error) {
757
758 noff := encodeName(rr.Name, data, offset)
759 nSz := noff - offset
760
761 binary.BigEndian.PutUint16(data[noff:], uint16(rr.Type))
762 binary.BigEndian.PutUint16(data[noff+2:], uint16(rr.Class))
763 binary.BigEndian.PutUint32(data[noff+4:], uint32(rr.TTL))
764
765 switch rr.Type {
766 case DNSTypeA:
767 copy(data[noff+10:], rr.IP.To4())
768 case DNSTypeAAAA:
769 copy(data[noff+10:], rr.IP)
770 case DNSTypeNS:
771 encodeName(rr.NS, data, noff+10)
772 case DNSTypeCNAME:
773 encodeName(rr.CNAME, data, noff+10)
774 case DNSTypePTR:
775 encodeName(rr.PTR, data, noff+10)
776 case DNSTypeSOA:
777 noff2 := encodeName(rr.SOA.MName, data, noff+10)
778 noff2 = encodeName(rr.SOA.RName, data, noff2)
779 binary.BigEndian.PutUint32(data[noff2:], rr.SOA.Serial)
780 binary.BigEndian.PutUint32(data[noff2+4:], rr.SOA.Refresh)
781 binary.BigEndian.PutUint32(data[noff2+8:], rr.SOA.Retry)
782 binary.BigEndian.PutUint32(data[noff2+12:], rr.SOA.Expire)
783 binary.BigEndian.PutUint32(data[noff2+16:], rr.SOA.Minimum)
784 case DNSTypeMX:
785 binary.BigEndian.PutUint16(data[noff+10:], rr.MX.Preference)
786 encodeName(rr.MX.Name, data, noff+12)
787 case DNSTypeTXT:
788 noff2 := noff + 10
789 for _, txt := range rr.TXTs {
790 data[noff2] = byte(len(txt))
791 copy(data[noff2+1:], txt)
792 noff2 += 1 + len(txt)
793 }
794 case DNSTypeSRV:
795 binary.BigEndian.PutUint16(data[noff+10:], rr.SRV.Priority)
796 binary.BigEndian.PutUint16(data[noff+12:], rr.SRV.Weight)
797 binary.BigEndian.PutUint16(data[noff+14:], rr.SRV.Port)
798 encodeName(rr.SRV.Name, data, noff+16)
799 case DNSTypeURI:
800 binary.BigEndian.PutUint16(data[noff+10:], rr.URI.Priority)
801 binary.BigEndian.PutUint16(data[noff+12:], rr.URI.Weight)
802 copy(data[noff+14:], rr.URI.Target)
803 case DNSTypeOPT:
804 noff2 := noff + 10
805 for _, opt := range rr.OPT {
806 binary.BigEndian.PutUint16(data[noff2:], uint16(opt.Code))
807 binary.BigEndian.PutUint16(data[noff2+2:], uint16(len(opt.Data)))
808 copy(data[noff2+4:], opt.Data)
809 noff2 += 4 + len(opt.Data)
810 }
811 default:
812 return 0, fmt.Errorf("serializing resource record of type %v not supported", rr.Type)
813 }
814
815 // DataLength
816 dSz := recSize(rr)
817 binary.BigEndian.PutUint16(data[noff+8:], uint16(dSz))
818
819 if opts.FixLengths {
820 rr.DataLength = uint16(dSz)
821 }
822
823 return nSz + 10 + dSz, nil
824}
825
826func (rr *DNSResourceRecord) String() string {
827
828 if rr.Type == DNSTypeOPT {
829 opts := make([]string, len(rr.OPT))
830 for i, opt := range rr.OPT {
831 opts[i] = opt.String()
832 }
833 return "OPT " + strings.Join(opts, ",")
834 }
835 if rr.Type == DNSTypeURI {
836 return fmt.Sprintf("URI %d %d %s", rr.URI.Priority, rr.URI.Weight, string(rr.URI.Target))
837 }
838 if rr.Class == DNSClassIN {
839 switch rr.Type {
840 case DNSTypeA, DNSTypeAAAA:
841 return rr.IP.String()
842 case DNSTypeNS:
843 return "NS " + string(rr.NS)
844 case DNSTypeCNAME:
845 return "CNAME " + string(rr.CNAME)
846 case DNSTypePTR:
847 return "PTR " + string(rr.PTR)
848 case DNSTypeTXT:
849 return "TXT " + string(rr.TXT)
850 }
851 }
852
853 return fmt.Sprintf("<%v, %v>", rr.Class, rr.Type)
854}
855
856func decodeCharacterStrings(data []byte) ([][]byte, error) {
857 strings := make([][]byte, 0, 1)
858 end := len(data)
859 for index, index2 := 0, 0; index != end; index = index2 {
860 index2 = index + 1 + int(data[index]) // index increases by 1..256 and does not overflow
861 if index2 > end {
862 return nil, errCharStringMissData
863 }
864 strings = append(strings, data[index+1:index2])
865 }
866 return strings, nil
867}
868
869func decodeOPTs(data []byte, offset int) ([]DNSOPT, error) {
870 allOPT := []DNSOPT{}
871 end := len(data)
872
873 if offset == end {
874 return allOPT, nil // There is no data to read
875 }
876
877 if offset+4 > end {
878 return allOPT, fmt.Errorf("DNSOPT record is of length %d, it should be at least length 4", end-offset)
879 }
880
881 for i := offset; i < end; {
882 opt := DNSOPT{}
883 if len(data) < i+4 {
884 return allOPT, fmt.Errorf("Malformed DNSOPT record. Length %d < %d", len(data), i+4)
885 }
886 opt.Code = DNSOptionCode(binary.BigEndian.Uint16(data[i : i+2]))
887 l := binary.BigEndian.Uint16(data[i+2 : i+4])
888 if i+4+int(l) > end {
889 return allOPT, fmt.Errorf("Malformed DNSOPT record. The length (%d) field implies a packet larger than the one received", l)
890 }
891 opt.Data = data[i+4 : i+4+int(l)]
892 allOPT = append(allOPT, opt)
893 i += int(l) + 4
894 }
895 return allOPT, nil
896}
897
898func (rr *DNSResourceRecord) decodeRData(data []byte, offset int, buffer *[]byte) error {
899 switch rr.Type {
900 case DNSTypeA:
901 rr.IP = rr.Data
902 case DNSTypeAAAA:
903 rr.IP = rr.Data
904 case DNSTypeTXT, DNSTypeHINFO:
905 rr.TXT = rr.Data
906 txts, err := decodeCharacterStrings(rr.Data)
907 if err != nil {
908 return err
909 }
910 rr.TXTs = txts
911 case DNSTypeNS:
912 name, _, err := decodeName(data, offset, buffer, 1)
913 if err != nil {
914 return err
915 }
916 rr.NS = name
917 case DNSTypeCNAME:
918 name, _, err := decodeName(data, offset, buffer, 1)
919 if err != nil {
920 return err
921 }
922 rr.CNAME = name
923 case DNSTypePTR:
924 name, _, err := decodeName(data, offset, buffer, 1)
925 if err != nil {
926 return err
927 }
928 rr.PTR = name
929 case DNSTypeSOA:
930 name, endq, err := decodeName(data, offset, buffer, 1)
931 if err != nil {
932 return err
933 }
934 rr.SOA.MName = name
935 name, endq, err = decodeName(data, endq, buffer, 1)
936 if err != nil {
937 return err
938 }
939 if len(data) < endq+20 {
940 return errors.New("SOA too small")
941 }
942 rr.SOA.RName = name
943 rr.SOA.Serial = binary.BigEndian.Uint32(data[endq : endq+4])
944 rr.SOA.Refresh = binary.BigEndian.Uint32(data[endq+4 : endq+8])
945 rr.SOA.Retry = binary.BigEndian.Uint32(data[endq+8 : endq+12])
946 rr.SOA.Expire = binary.BigEndian.Uint32(data[endq+12 : endq+16])
947 rr.SOA.Minimum = binary.BigEndian.Uint32(data[endq+16 : endq+20])
948 case DNSTypeMX:
949 if len(data) < offset+2 {
950 return errors.New("MX too small")
951 }
952 rr.MX.Preference = binary.BigEndian.Uint16(data[offset : offset+2])
953 name, _, err := decodeName(data, offset+2, buffer, 1)
954 if err != nil {
955 return err
956 }
957 rr.MX.Name = name
958 case DNSTypeURI:
959 if len(rr.Data) < 4 {
960 return errors.New("URI too small")
961 }
962 rr.URI.Priority = binary.BigEndian.Uint16(data[offset : offset+2])
963 rr.URI.Weight = binary.BigEndian.Uint16(data[offset+2 : offset+4])
964 rr.URI.Target = rr.Data[4:]
965 case DNSTypeSRV:
966 if len(data) < offset+6 {
967 return errors.New("SRV too small")
968 }
969 rr.SRV.Priority = binary.BigEndian.Uint16(data[offset : offset+2])
970 rr.SRV.Weight = binary.BigEndian.Uint16(data[offset+2 : offset+4])
971 rr.SRV.Port = binary.BigEndian.Uint16(data[offset+4 : offset+6])
972 name, _, err := decodeName(data, offset+6, buffer, 1)
973 if err != nil {
974 return err
975 }
976 rr.SRV.Name = name
977 case DNSTypeOPT:
978 allOPT, err := decodeOPTs(data, offset)
979 if err != nil {
980 return err
981 }
982 rr.OPT = allOPT
983 }
984 return nil
985}
986
987// DNSSOA is a Start of Authority record. Each domain requires a SOA record at
988// the cutover where a domain is delegated from its parent.
989type DNSSOA struct {
990 MName, RName []byte
991 Serial, Refresh, Retry, Expire, Minimum uint32
992}
993
994// DNSSRV is a Service record, defining a location (hostname/port) of a
995// server/service.
996type DNSSRV struct {
997 Priority, Weight, Port uint16
998 Name []byte
999}
1000
1001// DNSMX is a mail exchange record, defining a mail server for a recipient's
1002// domain.
1003type DNSMX struct {
1004 Preference uint16
1005 Name []byte
1006}
1007
1008// DNSURI is a URI record, defining a target (URI) of a server/service
1009type DNSURI struct {
1010 Priority, Weight uint16
1011 Target []byte
1012}
1013
1014// DNSOptionCode represents the code of a DNS Option, see RFC6891, section 6.1.2
1015type DNSOptionCode uint16
1016
1017func (doc DNSOptionCode) String() string {
1018 switch doc {
1019 default:
1020 return "Unknown"
1021 case DNSOptionCodeNSID:
1022 return "NSID"
1023 case DNSOptionCodeDAU:
1024 return "DAU"
1025 case DNSOptionCodeDHU:
1026 return "DHU"
1027 case DNSOptionCodeN3U:
1028 return "N3U"
1029 case DNSOptionCodeEDNSClientSubnet:
1030 return "EDNSClientSubnet"
1031 case DNSOptionCodeEDNSExpire:
1032 return "EDNSExpire"
1033 case DNSOptionCodeCookie:
1034 return "Cookie"
1035 case DNSOptionCodeEDNSKeepAlive:
1036 return "EDNSKeepAlive"
1037 case DNSOptionCodePadding:
1038 return "CodePadding"
1039 case DNSOptionCodeChain:
1040 return "CodeChain"
1041 case DNSOptionCodeEDNSKeyTag:
1042 return "CodeEDNSKeyTag"
1043 case DNSOptionCodeEDNSClientTag:
1044 return "EDNSClientTag"
1045 case DNSOptionCodeEDNSServerTag:
1046 return "EDNSServerTag"
1047 case DNSOptionCodeDeviceID:
1048 return "DeviceID"
1049 }
1050}
1051
1052// DNSOptionCode known values. See IANA
1053const (
1054 DNSOptionCodeNSID DNSOptionCode = 3
1055 DNSOptionCodeDAU DNSOptionCode = 5
1056 DNSOptionCodeDHU DNSOptionCode = 6
1057 DNSOptionCodeN3U DNSOptionCode = 7
1058 DNSOptionCodeEDNSClientSubnet DNSOptionCode = 8
1059 DNSOptionCodeEDNSExpire DNSOptionCode = 9
1060 DNSOptionCodeCookie DNSOptionCode = 10
1061 DNSOptionCodeEDNSKeepAlive DNSOptionCode = 11
1062 DNSOptionCodePadding DNSOptionCode = 12
1063 DNSOptionCodeChain DNSOptionCode = 13
1064 DNSOptionCodeEDNSKeyTag DNSOptionCode = 14
1065 DNSOptionCodeEDNSClientTag DNSOptionCode = 16
1066 DNSOptionCodeEDNSServerTag DNSOptionCode = 17
1067 DNSOptionCodeDeviceID DNSOptionCode = 26946
1068)
1069
1070// DNSOPT is a DNS Option, see RFC6891, section 6.1.2
1071type DNSOPT struct {
1072 Code DNSOptionCode
1073 Data []byte
1074}
1075
1076func (opt DNSOPT) String() string {
1077 return fmt.Sprintf("%s=%x", opt.Code, opt.Data)
1078}
1079
1080var (
1081 errMaxRecursion = errors.New("max DNS recursion level hit")
1082
1083 errDNSNameOffsetTooHigh = errors.New("dns name offset too high")
1084 errDNSNameOffsetNegative = errors.New("dns name offset is negative")
1085 errDNSPacketTooShort = errors.New("DNS packet too short")
1086 errDNSNameTooLong = errors.New("dns name is too long")
1087 errDNSNameInvalidIndex = errors.New("dns name uncomputable: invalid index")
1088 errDNSPointerOffsetTooHigh = errors.New("dns offset pointer too high")
1089 errDNSIndexOutOfRange = errors.New("dns index walked out of range")
1090 errDNSNameHasNoData = errors.New("no dns data found for name")
1091
1092 errCharStringMissData = errors.New("Insufficient data for a <character-string>")
1093
1094 errDecodeRecordLength = errors.New("resource record length exceeds data")
1095
1096 errDecodeQueryBadQDCount = errors.New("Invalid query decoding, not the right number of questions")
1097 errDecodeQueryBadANCount = errors.New("Invalid query decoding, not the right number of answers")
1098 errDecodeQueryBadNSCount = errors.New("Invalid query decoding, not the right number of authorities")
1099 errDecodeQueryBadARCount = errors.New("Invalid query decoding, not the right number of additionals info")
1100)