1 // Copyright 2014 Google, Inc. All rights reserved.
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
15 "github.com/google/gopacket"
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.
22 // DNSClass known values.
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
31 func (dc DNSClass) String() string {
48 // DNSType defines the type of data being requested/returned in a
52 // DNSType known values.
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]
74 func (dt DNSType) String() string {
117 // DNSResponseCode provides response codes for question answers.
118 type DNSResponseCode uint8
120 // DNSResponseCode known values.
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]
143 func (drc DNSResponseCode) String() string {
147 case DNSResponseCodeNoErr:
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"
186 // DNSOpCode defines a set of different operation types.
189 // DNSOpCode known values.
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]
198 func (doc DNSOpCode) String() string {
204 case DNSOpCodeIQuery:
205 return "Inverse Query"
206 case DNSOpCodeStatus:
208 case DNSOpCodeNotify:
210 case DNSOpCodeUpdate:
215 // DNS is specified in RFC 1034 / RFC 1035
216 // +---------------------+
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 // +---------------------+
229 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
230 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
232 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
233 // |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
234 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
236 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
238 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
240 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
242 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
244 // DNS contains data from a single Domain Name Service packet.
253 AA bool // Authoritative answer
255 RD bool // Recursion desired
256 RA bool // Recursion available
257 Z uint8 // Resrved for future use
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
266 Questions []DNSQuestion
267 Answers []DNSResourceRecord
268 Authorities []DNSResourceRecord
269 Additionals []DNSResourceRecord
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.
277 // LayerType returns gopacket.LayerTypeDNS.
278 func (d *DNS) LayerType() gopacket.LayerType { return LayerTypeDNS }
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 {
284 err := d.DecodeFromBytes(data, p)
289 p.SetApplicationLayer(d)
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]
299 return errors.New("DNS packet too short")
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])
319 d.Questions = d.Questions[:0]
320 d.Answers = d.Answers[:0]
321 d.Authorities = d.Authorities[:0]
322 d.Additionals = d.Additionals[:0]
326 for i := 0; i < int(d.QDCount); i++ {
328 if offset, err = q.decode(data, offset, df, &d.buffer); err != nil {
331 d.Questions = append(d.Questions, q)
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 {
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
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
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
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")
380 // CanDecode implements gopacket.DecodingLayer.
381 func (d *DNS) CanDecode() gopacket.LayerClass {
385 // NextLayerType implements gopacket.DecodingLayer.
386 func (d *DNS) NextLayerType() gopacket.LayerType {
387 return gopacket.LayerTypePayload
390 // Payload returns nil.
391 func (d *DNS) Payload() []byte {
395 func b2i(b bool) int {
402 func recSize(rr *DNSResourceRecord) int {
409 return len(rr.NS) + 2
411 return len(rr.CNAME) + 2
413 return len(rr.PTR) + 2
415 return len(rr.SOA.MName) + 2 + len(rr.SOA.RName) + 2 + 20
417 return 2 + len(rr.MX.Name) + 2
420 for _, txt := range rr.TXTs {
425 return 6 + len(rr.SRV.Name) + 2
431 func computeSize(recs []DNSResourceRecord) int {
433 for _, rr := range recs {
434 sz += len(rr.Name) + 14
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 {
444 for _, q := range d.Questions {
445 dsz += len(q.Name) + 6
447 dsz += computeSize(d.Answers)
448 dsz += computeSize(d.Authorities)
449 dsz += computeSize(d.Additionals)
451 bytes, err := b.PrependBytes(12 + dsz)
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))
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))
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)
471 for _, qd := range d.Questions {
472 n := qd.encode(bytes, off)
476 for i := range d.Answers {
477 // done this way so we can modify DNSResourceRecord to fix
478 // lengths if requested
480 n, err := qa.encode(bytes, off, opts)
487 for i := range d.Authorities {
488 qa := &d.Authorities[i]
489 n, err := qa.encode(bytes, off, opts)
495 for i := range d.Additionals {
496 qa := &d.Additionals[i]
497 n, err := qa.encode(bytes, off, opts)
507 var errMaxRecursion = errors.New("max DNS recursion level hit")
509 const maxRecursionLevel = 255
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")
519 start := len(*buffer)
521 if data[index] == 0x00 {
522 return nil, index + 1, nil
525 for data[index] != 0x00 {
526 switch data[index] & 0xc0 {
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
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")
542 *buffer = append(*buffer, '.')
543 *buffer = append(*buffer, data[index+1:index2]...)
548 The pointer takes the form of a two octet sequence.
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,
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
564 - a sequence of labels ending with a pointer
566 if index+2 > len(data) {
567 return nil, 0, errors.New("dns offset pointer too high")
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")
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)
581 index++ // pointer is two bytes, so add an extra byte here.
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)",
589 return nil, 0, fmt.Errorf("qname '0x80' unsupported yet (data=%x index=%d)",
592 if index >= len(data) {
593 return nil, 0, errors.New("dns index walked out of range")
596 if len(*buffer) <= start {
597 return nil, 0, errors.New("no dns data found for name")
599 return (*buffer)[start+1:], index + 1, nil
602 // DNSQuestion wraps a single request (question) within a DNS query.
603 type DNSQuestion struct {
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)
616 q.Type = DNSType(binary.BigEndian.Uint16(data[endq : endq+2]))
617 q.Class = DNSClass(binary.BigEndian.Uint16(data[endq+2 : endq+4]))
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
630 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
631 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
636 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
638 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
640 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
643 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
645 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
648 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
650 // DNSResourceRecord wraps the data from a single DNS resource within a
652 type DNSResourceRecord struct {
663 // RDATA Decoded Values
665 NS, CNAME, PTR []byte
671 // Undecoded TXT for backward compatibility
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)
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)
689 return 0, fmt.Errorf("resource record length exceeds data")
691 rr.Data = data[endq+10 : end]
693 if err = rr.decodeRData(data, endq+10, buffer); err != nil {
697 return endq + 10 + int(rr.DataLength), nil
700 func encodeName(name []byte, data []byte, offset int) int {
702 for i := range name {
704 data[offset+i-l] = byte(l)
707 // skip one to write the length
708 data[offset+i+1] = name[i]
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
718 func (rr *DNSResourceRecord) encode(data []byte, offset int, opts gopacket.SerializeOptions) (int, error) {
720 noff := encodeName(rr.Name, data, offset)
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))
728 copy(data[noff+10:], rr.IP.To4())
730 copy(data[noff+10:], rr.IP)
732 encodeName(rr.NS, data, noff+10)
734 encodeName(rr.CNAME, data, noff+10)
736 encodeName(rr.PTR, data, noff+10)
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)
746 binary.BigEndian.PutUint16(data[noff+10:], rr.MX.Preference)
747 encodeName(rr.MX.Name, data, noff+12)
750 for _, txt := range rr.TXTs {
751 data[noff2] = byte(len(txt))
752 copy(data[noff2+1:], txt)
753 noff2 += 1 + len(txt)
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)
761 return 0, fmt.Errorf("serializing resource record of type %v not supported", rr.Type)
766 binary.BigEndian.PutUint16(data[noff+8:], uint16(dSz))
769 rr.DataLength = uint16(dSz)
772 return len(rr.Name) + 1 + 11 + dSz, nil
775 func (rr *DNSResourceRecord) String() string {
777 if rr.Class == DNSClassIN {
779 case DNSTypeA, DNSTypeAAAA:
780 return rr.IP.String()
782 return "NS " + string(rr.NS)
784 return "CNAME " + string(rr.CNAME)
786 return "PTR " + string(rr.PTR)
788 return "TXT " + string(rr.TXT)
792 return fmt.Sprintf("<%v, %v>", rr.Class, rr.Type)
795 func decodeCharacterStrings(data []byte) ([][]byte, error) {
796 strings := make([][]byte, 0, 1)
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
801 return nil, errors.New("Insufficient data for a <character-string>")
803 strings = append(strings, data[index+1:index2])
808 func (rr *DNSResourceRecord) decodeRData(data []byte, offset int, buffer *[]byte) error {
814 case DNSTypeTXT, DNSTypeHINFO:
816 txts, err := decodeCharacterStrings(rr.Data)
822 name, _, err := decodeName(data, offset, buffer, 1)
828 name, _, err := decodeName(data, offset, buffer, 1)
834 name, _, err := decodeName(data, offset, buffer, 1)
840 name, endq, err := decodeName(data, offset, buffer, 1)
845 name, endq, err = decodeName(data, endq, buffer, 1)
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])
856 rr.MX.Preference = binary.BigEndian.Uint16(data[offset : offset+2])
857 name, _, err := decodeName(data, offset+2, buffer, 1)
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)
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.
879 Serial, Refresh, Retry, Expire, Minimum uint32
882 // DNSSRV is a Service record, defining a location (hostname/port) of a
885 Priority, Weight, Port uint16
889 // DNSMX is a mail exchange record, defining a mail server for a recipient's