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