func (rr *DNSResourceRecord) decode(data []byte, offset int, df gopacket.DecodeFeedback, buffer *[]byte) (int, error) {
	name, endq, err := decodeName(data, offset, buffer, 1)
	if err != nil {
		return 0, err
	}
	rr.Name = name
	rr.Type = DNSType(binary.BigEndian.Uint16(data[endq : endq+2]))
	rr.Class = DNSClass(binary.BigEndian.Uint16(data[endq+2 : endq+4]))
	rr.TTL = binary.BigEndian.Uint32(data[endq+4 : endq+8])
	rr.DataLength = binary.BigEndian.Uint16(data[endq+8 : endq+10])
	end := endq + 10 + int(rr.DataLength)
	if end > len(data) {
		return 0, errDecodeRecordLength
	}
	rr.Data = data[endq+10 : end]
	if err = rr.decodeRData(data, endq+10, buffer); err != nil {
		return 0, err
	}
	return endq + 10 + int(rr.DataLength), nil
}
decode decodes the resource record, returning the total length of the record.
package layers
import (
	"encoding/binary"
	"errors"
	"fmt"
	"net"
	"strings"
	"github.com/google/gopacket"
)
type DNSClass uint16
const (
	DNSClassIN  DNSClass = 1    
	DNSClassCS  DNSClass = 2    
	DNSClassCH  DNSClass = 3    
	DNSClassHS  DNSClass = 4    
	DNSClassAny DNSClass = 255  
)
func (dc DNSClass) String() string {
	switch dc {
	default:
		return "Unknown"
	case DNSClassIN:
		return "IN"
	case DNSClassCS:
		return "CS"
	case DNSClassCH:
		return "CH"
	case DNSClassHS:
		return "HS"
	case DNSClassAny:
		return "Any"
	}
}
type DNSType uint16
const (
	DNSTypeA     DNSType = 1   
	DNSTypeNS    DNSType = 2   
	DNSTypeMD    DNSType = 3   
	DNSTypeMF    DNSType = 4   
	DNSTypeCNAME DNSType = 5   
	DNSTypeSOA   DNSType = 6   
	DNSTypeMB    DNSType = 7   
	DNSTypeMG    DNSType = 8   
	DNSTypeMR    DNSType = 9   
	DNSTypeNULL  DNSType = 10  
	DNSTypeWKS   DNSType = 11  
	DNSTypePTR   DNSType = 12  
	DNSTypeHINFO DNSType = 13  
	DNSTypeMINFO DNSType = 14  
	DNSTypeMX    DNSType = 15  
	DNSTypeTXT   DNSType = 16  
	DNSTypeAAAA  DNSType = 28  
	DNSTypeSRV   DNSType = 33  
	DNSTypeOPT   DNSType = 41  
)
func (dt DNSType) String() string {
	switch dt {
	default:
		return "Unknown"
	case DNSTypeA:
		return "A"
	case DNSTypeNS:
		return "NS"
	case DNSTypeMD:
		return "MD"
	case DNSTypeMF:
		return "MF"
	case DNSTypeCNAME:
		return "CNAME"
	case DNSTypeSOA:
		return "SOA"
	case DNSTypeMB:
		return "MB"
	case DNSTypeMG:
		return "MG"
	case DNSTypeMR:
		return "MR"
	case DNSTypeNULL:
		return "NULL"
	case DNSTypeWKS:
		return "WKS"
	case DNSTypePTR:
		return "PTR"
	case DNSTypeHINFO:
		return "HINFO"
	case DNSTypeMINFO:
		return "MINFO"
	case DNSTypeMX:
		return "MX"
	case DNSTypeTXT:
		return "TXT"
	case DNSTypeAAAA:
		return "AAAA"
	case DNSTypeSRV:
		return "SRV"
	case DNSTypeOPT:
		return "OPT"
	}
}
type DNSResponseCode uint8
const (
	DNSResponseCodeNoErr    DNSResponseCode = 0   
	DNSResponseCodeFormErr  DNSResponseCode = 1   
	DNSResponseCodeServFail DNSResponseCode = 2   
	DNSResponseCodeNXDomain DNSResponseCode = 3   
	DNSResponseCodeNotImp   DNSResponseCode = 4   
	DNSResponseCodeRefused  DNSResponseCode = 5   
	DNSResponseCodeYXDomain DNSResponseCode = 6   
	DNSResponseCodeYXRRSet  DNSResponseCode = 7   
	DNSResponseCodeNXRRSet  DNSResponseCode = 8   
	DNSResponseCodeNotAuth  DNSResponseCode = 9   
	DNSResponseCodeNotZone  DNSResponseCode = 10  
	DNSResponseCodeBadVers  DNSResponseCode = 16  
	DNSResponseCodeBadSig   DNSResponseCode = 16  
	DNSResponseCodeBadKey   DNSResponseCode = 17  
	DNSResponseCodeBadTime  DNSResponseCode = 18  
	DNSResponseCodeBadMode  DNSResponseCode = 19  
	DNSResponseCodeBadName  DNSResponseCode = 20  
	DNSResponseCodeBadAlg   DNSResponseCode = 21  
	DNSResponseCodeBadTruc  DNSResponseCode = 22  
)
func (drc DNSResponseCode) String() string {
	switch drc {
	default:
		return "Unknown"
	case DNSResponseCodeNoErr:
		return "No Error"
	case DNSResponseCodeFormErr:
		return "Format Error"
	case DNSResponseCodeServFail:
		return "Server Failure "
	case DNSResponseCodeNXDomain:
		return "Non-Existent Domain"
	case DNSResponseCodeNotImp:
		return "Not Implemented"
	case DNSResponseCodeRefused:
		return "Query Refused"
	case DNSResponseCodeYXDomain:
		return "Name Exists when it should not"
	case DNSResponseCodeYXRRSet:
		return "RR Set Exists when it should not"
	case DNSResponseCodeNXRRSet:
		return "RR Set that should exist does not"
	case DNSResponseCodeNotAuth:
		return "Server Not Authoritative for zone"
	case DNSResponseCodeNotZone:
		return "Name not contained in zone"
	case DNSResponseCodeBadVers:
		return "Bad OPT Version"
	case DNSResponseCodeBadKey:
		return "Key not recognized"
	case DNSResponseCodeBadTime:
		return "Signature out of time window"
	case DNSResponseCodeBadMode:
		return "Bad TKEY Mode"
	case DNSResponseCodeBadName:
		return "Duplicate key name"
	case DNSResponseCodeBadAlg:
		return "Algorithm not supported"
	case DNSResponseCodeBadTruc:
		return "Bad Truncation"
	}
}
type DNSOpCode uint8
const (
	DNSOpCodeQuery  DNSOpCode = 0  
	DNSOpCodeIQuery DNSOpCode = 1  
	DNSOpCodeStatus DNSOpCode = 2  
	DNSOpCodeNotify DNSOpCode = 4  
	DNSOpCodeUpdate DNSOpCode = 5  
)
func (doc DNSOpCode) String() string {
	switch doc {
	default:
		return "Unknown"
	case DNSOpCodeQuery:
		return "Query"
	case DNSOpCodeIQuery:
		return "Inverse Query"
	case DNSOpCodeStatus:
		return "Status"
	case DNSOpCodeNotify:
		return "Notify"
	case DNSOpCodeUpdate:
		return "Update"
	}
}
type DNS struct {
	BaseLayer
	ID     uint16
	QR     bool
	OpCode DNSOpCode
	AA bool   
	TC bool   
	RD bool   
	RA bool   
	Z  uint8  
	ResponseCode DNSResponseCode
	QDCount      uint16  
	ANCount      uint16  
	NSCount      uint16  
	ARCount      uint16  
	Questions   []DNSQuestion
	Answers     []DNSResourceRecord
	Authorities []DNSResourceRecord
	Additionals []DNSResourceRecord
	buffer []byte
}
func (d *DNS) LayerType() gopacket.LayerType { return LayerTypeDNS }
func decodeDNS(data []byte, p gopacket.PacketBuilder) error {
	d := &DNS{}
	err := d.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	p.AddLayer(d)
	p.SetApplicationLayer(d)
	return nil
}
func (d *DNS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
	d.buffer = d.buffer[:0]
	if len(data) < 12 {
		df.SetTruncated()
		return errDNSPacketTooShort
	}
	d.BaseLayer = BaseLayer{Contents: data[:len(data)]}
	d.ID = binary.BigEndian.Uint16(data[:2])
	d.QR = data[2]&0x80 != 0
	d.OpCode = DNSOpCode(data[2]>>3) & 0x0F
	d.AA = data[2]&0x04 != 0
	d.TC = data[2]&0x02 != 0
	d.RD = data[2]&0x01 != 0
	d.RA = data[3]&0x80 != 0
	d.Z = uint8(data[3]>>4) & 0x7
	d.ResponseCode = DNSResponseCode(data[3] & 0xF)
	d.QDCount = binary.BigEndian.Uint16(data[4:6])
	d.ANCount = binary.BigEndian.Uint16(data[6:8])
	d.NSCount = binary.BigEndian.Uint16(data[8:10])
	d.ARCount = binary.BigEndian.Uint16(data[10:12])
	d.Questions = d.Questions[:0]
	d.Answers = d.Answers[:0]
	d.Authorities = d.Authorities[:0]
	d.Additionals = d.Additionals[:0]
	offset := 12
	var err error
	for i := 0; i < int(d.QDCount); i++ {
		var q DNSQuestion
		if offset, err = q.decode(data, offset, df, &d.buffer); err != nil {
			return err
		}
		d.Questions = append(d.Questions, q)
	}
	for i := 0; i < int(d.ANCount); i++ {
		d.Answers = append(d.Answers, DNSResourceRecord{})
		if offset, err = d.Answers[i].decode(data, offset, df, &d.buffer); err != nil {
			d.Answers = d.Answers[:i]  
			return err
		}
	}
	for i := 0; i < int(d.NSCount); i++ {
		d.Authorities = append(d.Authorities, DNSResourceRecord{})
		if offset, err = d.Authorities[i].decode(data, offset, df, &d.buffer); err != nil {
			d.Authorities = d.Authorities[:i]  
			return err
		}
	}
	for i := 0; i < int(d.ARCount); i++ {
		d.Additionals = append(d.Additionals, DNSResourceRecord{})
		if offset, err = d.Additionals[i].decode(data, offset, df, &d.buffer); err != nil {
			d.Additionals = d.Additionals[:i]  
			return err
		}
	}
	if uint16(len(d.Questions)) != d.QDCount {
		return errDecodeQueryBadQDCount
	} else if uint16(len(d.Answers)) != d.ANCount {
		return errDecodeQueryBadANCount
	} else if uint16(len(d.Authorities)) != d.NSCount {
		return errDecodeQueryBadNSCount
	} else if uint16(len(d.Additionals)) != d.ARCount {
		return errDecodeQueryBadARCount
	}
	return nil
}
func (d *DNS) CanDecode() gopacket.LayerClass {
	return LayerTypeDNS
}
func (d *DNS) NextLayerType() gopacket.LayerType {
	return gopacket.LayerTypePayload
}
func (d *DNS) Payload() []byte {
	return nil
}
func b2i(b bool) int {
	if b {
		return 1
	}
	return 0
}
func recSize(rr *DNSResourceRecord) int {
	switch rr.Type {
	case DNSTypeA:
		return 4
	case DNSTypeAAAA:
		return 16
	case DNSTypeNS:
		return len(rr.NS) + 2
	case DNSTypeCNAME:
		return len(rr.CNAME) + 2
	case DNSTypePTR:
		return len(rr.PTR) + 2
	case DNSTypeSOA:
		return len(rr.SOA.MName) + 2 + len(rr.SOA.RName) + 2 + 20
	case DNSTypeMX:
		return 2 + len(rr.MX.Name) + 2
	case DNSTypeTXT:
		l := len(rr.TXTs)
		for _, txt := range rr.TXTs {
			l += len(txt)
		}
		return l
	case DNSTypeSRV:
		return 6 + len(rr.SRV.Name) + 2
	case DNSTypeOPT:
		l := len(rr.OPT) * 4
		for _, opt := range rr.OPT {
			l += len(opt.Data)
		}
		return l
	}
	return 0
}
func computeSize(recs []DNSResourceRecord) int {
	sz := 0
	for _, rr := range recs {
		v := len(rr.Name)
		if v == 0 {
			sz += v + 11
		} else {
			sz += v + 12
		}
		sz += recSize(&rr)
	}
	return sz
}
func (d *DNS) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	dsz := 0
	for _, q := range d.Questions {
		dsz += len(q.Name) + 6
	}
	dsz += computeSize(d.Answers)
	dsz += computeSize(d.Authorities)
	dsz += computeSize(d.Additionals)
	bytes, err := b.PrependBytes(12 + dsz)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes, d.ID)
	bytes[2] = byte((b2i(d.QR) << 7) | (int(d.OpCode) << 3) | (b2i(d.AA) << 2) | (b2i(d.TC) << 1) | b2i(d.RD))
	bytes[3] = byte((b2i(d.RA) << 7) | (int(d.Z) << 4) | int(d.ResponseCode))
	if opts.FixLengths {
		d.QDCount = uint16(len(d.Questions))
		d.ANCount = uint16(len(d.Answers))
		d.NSCount = uint16(len(d.Authorities))
		d.ARCount = uint16(len(d.Additionals))
	}
	binary.BigEndian.PutUint16(bytes[4:], d.QDCount)
	binary.BigEndian.PutUint16(bytes[6:], d.ANCount)
	binary.BigEndian.PutUint16(bytes[8:], d.NSCount)
	binary.BigEndian.PutUint16(bytes[10:], d.ARCount)
	off := 12
	for _, qd := range d.Questions {
		n := qd.encode(bytes, off)
		off += n
	}
	for i := range d.Answers {
		qa := &d.Answers[i]
		n, err := qa.encode(bytes, off, opts)
		if err != nil {
			return err
		}
		off += n
	}
	for i := range d.Authorities {
		qa := &d.Authorities[i]
		n, err := qa.encode(bytes, off, opts)
		if err != nil {
			return err
		}
		off += n
	}
	for i := range d.Additionals {
		qa := &d.Additionals[i]
		n, err := qa.encode(bytes, off, opts)
		if err != nil {
			return err
		}
		off += n
	}
	return nil
}
const maxRecursionLevel = 255
func decodeName(data []byte, offset int, buffer *[]byte, level int) ([]byte, int, error) {
	if level > maxRecursionLevel {
		return nil, 0, errMaxRecursion
	} else if offset >= len(data) {
		return nil, 0, errDNSNameOffsetTooHigh
	} else if offset < 0 {
		return nil, 0, errDNSNameOffsetNegative
	}
	start := len(*buffer)
	index := offset
	if data[index] == 0x00 {
		return nil, index + 1, nil
	}
loop:
	for data[index] != 0x00 {
		switch data[index] & 0xc0 {
		default:
			index2 := index + int(data[index]) + 1
			if index2-offset > 255 {
				return nil, 0, errDNSNameTooLong
			} else if index2 < index+1 || index2 > len(data) {
				return nil, 0, errDNSNameInvalidIndex
			}
			*buffer = append(*buffer, '.')
			*buffer = append(*buffer, data[index+1:index2]...)
			index = index2
		case 0xc0:
			if index+2 > len(data) {
				return nil, 0, errDNSPointerOffsetTooHigh
			}
			offsetp := int(binary.BigEndian.Uint16(data[index:index+2]) & 0x3fff)
			if offsetp > len(data) {
				return nil, 0, errDNSPointerOffsetTooHigh
			}
			_, _, err := decodeName(data, offsetp, buffer, level+1)
			if err != nil {
				return nil, 0, err
			}
			index++  
			break loop
		case 0x40:  
			return nil, 0, fmt.Errorf("qname '0x40' - RFC 2673 unsupported yet (data=%x index=%d)",
				data[index], index)
		case 0x80:
			return nil, 0, fmt.Errorf("qname '0x80' unsupported yet (data=%x index=%d)",
				data[index], index)
		}
		if index >= len(data) {
			return nil, 0, errDNSIndexOutOfRange
		}
	}
	if len(*buffer) <= start {
		return (*buffer)[start:], index + 1, nil
	}
	return (*buffer)[start+1:], index + 1, nil
}
type DNSQuestion struct {
	Name  []byte
	Type  DNSType
	Class DNSClass
}
func (q *DNSQuestion) decode(data []byte, offset int, df gopacket.DecodeFeedback, buffer *[]byte) (int, error) {
	name, endq, err := decodeName(data, offset, buffer, 1)
	if err != nil {
		return 0, err
	}
	q.Name = name
	q.Type = DNSType(binary.BigEndian.Uint16(data[endq : endq+2]))
	q.Class = DNSClass(binary.BigEndian.Uint16(data[endq+2 : endq+4]))
	return endq + 4, nil
}
func (q *DNSQuestion) encode(data []byte, offset int) int {
	noff := encodeName(q.Name, data, offset)
	nSz := noff - offset
	binary.BigEndian.PutUint16(data[noff:], uint16(q.Type))
	binary.BigEndian.PutUint16(data[noff+2:], uint16(q.Class))
	return nSz + 4
}
type DNSResourceRecord struct {
	Name  []byte
	Type  DNSType
	Class DNSClass
	TTL   uint32
	DataLength uint16
	Data       []byte
	IP             net.IP
	NS, CNAME, PTR []byte
	TXTs           [][]byte
	SOA            DNSSOA
	SRV            DNSSRV
	MX             DNSMX
	OPT            []DNSOPT  
	TXT []byte
}