DNS (Domain Name Service) packet: Go parsing library

(No support for Auth-Name + Add-Name for simplicity)

KS implementation details

License: CC0-1.0

References

This page hosts a formal specification of DNS (Domain Name Service) packet using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Go source code to parse DNS (Domain Name Service) packet

dns_packet.go

// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT.

import (
	"github.com/kaitai-io/kaitai_struct_go_runtime/kaitai"
	"bytes"
	"io"
)


/**
 * (No support for Auth-Name + Add-Name for simplicity)
 */

type DnsPacket_ClassType int
const (
	DnsPacket_ClassType__InClass DnsPacket_ClassType = 1
	DnsPacket_ClassType__Cs DnsPacket_ClassType = 2
	DnsPacket_ClassType__Ch DnsPacket_ClassType = 3
	DnsPacket_ClassType__Hs DnsPacket_ClassType = 4
)
var values_DnsPacket_ClassType = map[DnsPacket_ClassType]struct{}{1: {}, 2: {}, 3: {}, 4: {}}
func (v DnsPacket_ClassType) isDefined() bool {
	_, ok := values_DnsPacket_ClassType[v]
	return ok
}

type DnsPacket_TypeType int
const (
	DnsPacket_TypeType__A DnsPacket_TypeType = 1
	DnsPacket_TypeType__Ns DnsPacket_TypeType = 2
	DnsPacket_TypeType__Md DnsPacket_TypeType = 3
	DnsPacket_TypeType__Mf DnsPacket_TypeType = 4
	DnsPacket_TypeType__Cname DnsPacket_TypeType = 5
	DnsPacket_TypeType__Soa DnsPacket_TypeType = 6
	DnsPacket_TypeType__Mb DnsPacket_TypeType = 7
	DnsPacket_TypeType__Mg DnsPacket_TypeType = 8
	DnsPacket_TypeType__Mr DnsPacket_TypeType = 9
	DnsPacket_TypeType__Null DnsPacket_TypeType = 10
	DnsPacket_TypeType__Wks DnsPacket_TypeType = 11
	DnsPacket_TypeType__Ptr DnsPacket_TypeType = 12
	DnsPacket_TypeType__Hinfo DnsPacket_TypeType = 13
	DnsPacket_TypeType__Minfo DnsPacket_TypeType = 14
	DnsPacket_TypeType__Mx DnsPacket_TypeType = 15
	DnsPacket_TypeType__Txt DnsPacket_TypeType = 16
	DnsPacket_TypeType__Aaaa DnsPacket_TypeType = 28
	DnsPacket_TypeType__Srv DnsPacket_TypeType = 33
)
var values_DnsPacket_TypeType = map[DnsPacket_TypeType]struct{}{1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {}, 8: {}, 9: {}, 10: {}, 11: {}, 12: {}, 13: {}, 14: {}, 15: {}, 16: {}, 28: {}, 33: {}}
func (v DnsPacket_TypeType) isDefined() bool {
	_, ok := values_DnsPacket_TypeType[v]
	return ok
}
type DnsPacket struct {
	TransactionId uint16
	Flags *DnsPacket_PacketFlags
	Qdcount uint16
	Ancount uint16
	Nscount uint16
	Arcount uint16
	Queries []*DnsPacket_Query
	Answers []*DnsPacket_Answer
	Authorities []*DnsPacket_Answer
	Additionals []*DnsPacket_Answer
	_io *kaitai.Stream
	_root *DnsPacket
	_parent kaitai.Struct
}
func NewDnsPacket() *DnsPacket {
	return &DnsPacket{
	}
}

func (this DnsPacket) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket) Read(io *kaitai.Stream, parent kaitai.Struct, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp1, err := this._io.ReadU2be()
	if err != nil {
		return err
	}
	this.TransactionId = uint16(tmp1)
	tmp2 := NewDnsPacket_PacketFlags()
	err = tmp2.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Flags = tmp2
	tmp3, err := this.Flags.IsOpcodeValid()
	if err != nil {
		return err
	}
	if (tmp3) {
		tmp4, err := this._io.ReadU2be()
		if err != nil {
			return err
		}
		this.Qdcount = uint16(tmp4)
	}
	tmp5, err := this.Flags.IsOpcodeValid()
	if err != nil {
		return err
	}
	if (tmp5) {
		tmp6, err := this._io.ReadU2be()
		if err != nil {
			return err
		}
		this.Ancount = uint16(tmp6)
	}
	tmp7, err := this.Flags.IsOpcodeValid()
	if err != nil {
		return err
	}
	if (tmp7) {
		tmp8, err := this._io.ReadU2be()
		if err != nil {
			return err
		}
		this.Nscount = uint16(tmp8)
	}
	tmp9, err := this.Flags.IsOpcodeValid()
	if err != nil {
		return err
	}
	if (tmp9) {
		tmp10, err := this._io.ReadU2be()
		if err != nil {
			return err
		}
		this.Arcount = uint16(tmp10)
	}
	tmp11, err := this.Flags.IsOpcodeValid()
	if err != nil {
		return err
	}
	if (tmp11) {
		for i := 0; i < int(this.Qdcount); i++ {
			_ = i
			tmp12 := NewDnsPacket_Query()
			err = tmp12.Read(this._io, this, this._root)
			if err != nil {
				return err
			}
			this.Queries = append(this.Queries, tmp12)
		}
	}
	tmp13, err := this.Flags.IsOpcodeValid()
	if err != nil {
		return err
	}
	if (tmp13) {
		for i := 0; i < int(this.Ancount); i++ {
			_ = i
			tmp14 := NewDnsPacket_Answer()
			err = tmp14.Read(this._io, this, this._root)
			if err != nil {
				return err
			}
			this.Answers = append(this.Answers, tmp14)
		}
	}
	tmp15, err := this.Flags.IsOpcodeValid()
	if err != nil {
		return err
	}
	if (tmp15) {
		for i := 0; i < int(this.Nscount); i++ {
			_ = i
			tmp16 := NewDnsPacket_Answer()
			err = tmp16.Read(this._io, this, this._root)
			if err != nil {
				return err
			}
			this.Authorities = append(this.Authorities, tmp16)
		}
	}
	tmp17, err := this.Flags.IsOpcodeValid()
	if err != nil {
		return err
	}
	if (tmp17) {
		for i := 0; i < int(this.Arcount); i++ {
			_ = i
			tmp18 := NewDnsPacket_Answer()
			err = tmp18.Read(this._io, this, this._root)
			if err != nil {
				return err
			}
			this.Additionals = append(this.Additionals, tmp18)
		}
	}
	return err
}

/**
 * ID to keep track of request/responces
 */

/**
 * How many questions are there
 */

/**
 * Number of resource records answering the question
 */

/**
 * Number of resource records pointing toward an authority
 */

/**
 * Number of resource records holding additional information
 */
type DnsPacket_Address struct {
	Ip []byte
	_io *kaitai.Stream
	_root *DnsPacket
	_parent *DnsPacket_Answer
}
func NewDnsPacket_Address() *DnsPacket_Address {
	return &DnsPacket_Address{
	}
}

func (this DnsPacket_Address) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket_Address) Read(io *kaitai.Stream, parent *DnsPacket_Answer, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp19, err := this._io.ReadBytes(int(4))
	if err != nil {
		return err
	}
	tmp19 = tmp19
	this.Ip = tmp19
	return err
}
type DnsPacket_AddressV6 struct {
	IpV6 []byte
	_io *kaitai.Stream
	_root *DnsPacket
	_parent *DnsPacket_Answer
}
func NewDnsPacket_AddressV6() *DnsPacket_AddressV6 {
	return &DnsPacket_AddressV6{
	}
}

func (this DnsPacket_AddressV6) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket_AddressV6) Read(io *kaitai.Stream, parent *DnsPacket_Answer, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp20, err := this._io.ReadBytes(int(16))
	if err != nil {
		return err
	}
	tmp20 = tmp20
	this.IpV6 = tmp20
	return err
}
type DnsPacket_Answer struct {
	Name *DnsPacket_DomainName
	Type DnsPacket_TypeType
	AnswerClass DnsPacket_ClassType
	Ttl int32
	Rdlength uint16
	Payload interface{}
	_io *kaitai.Stream
	_root *DnsPacket
	_parent *DnsPacket
	_raw_Payload []byte
}
func NewDnsPacket_Answer() *DnsPacket_Answer {
	return &DnsPacket_Answer{
	}
}

func (this DnsPacket_Answer) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket_Answer) Read(io *kaitai.Stream, parent *DnsPacket, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp21 := NewDnsPacket_DomainName()
	err = tmp21.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Name = tmp21
	tmp22, err := this._io.ReadU2be()
	if err != nil {
		return err
	}
	this.Type = DnsPacket_TypeType(tmp22)
	tmp23, err := this._io.ReadU2be()
	if err != nil {
		return err
	}
	this.AnswerClass = DnsPacket_ClassType(tmp23)
	tmp24, err := this._io.ReadS4be()
	if err != nil {
		return err
	}
	this.Ttl = int32(tmp24)
	tmp25, err := this._io.ReadU2be()
	if err != nil {
		return err
	}
	this.Rdlength = uint16(tmp25)
	switch (this.Type) {
	case DnsPacket_TypeType__A:
		tmp26, err := this._io.ReadBytes(int(this.Rdlength))
		if err != nil {
			return err
		}
		tmp26 = tmp26
		this._raw_Payload = tmp26
		_io__raw_Payload := kaitai.NewStream(bytes.NewReader(this._raw_Payload))
		tmp27 := NewDnsPacket_Address()
		err = tmp27.Read(_io__raw_Payload, this, this._root)
		if err != nil {
			return err
		}
		this.Payload = tmp27
	case DnsPacket_TypeType__Aaaa:
		tmp28, err := this._io.ReadBytes(int(this.Rdlength))
		if err != nil {
			return err
		}
		tmp28 = tmp28
		this._raw_Payload = tmp28
		_io__raw_Payload := kaitai.NewStream(bytes.NewReader(this._raw_Payload))
		tmp29 := NewDnsPacket_AddressV6()
		err = tmp29.Read(_io__raw_Payload, this, this._root)
		if err != nil {
			return err
		}
		this.Payload = tmp29
	case DnsPacket_TypeType__Cname:
		tmp30, err := this._io.ReadBytes(int(this.Rdlength))
		if err != nil {
			return err
		}
		tmp30 = tmp30
		this._raw_Payload = tmp30
		_io__raw_Payload := kaitai.NewStream(bytes.NewReader(this._raw_Payload))
		tmp31 := NewDnsPacket_DomainName()
		err = tmp31.Read(_io__raw_Payload, this, this._root)
		if err != nil {
			return err
		}
		this.Payload = tmp31
	case DnsPacket_TypeType__Mx:
		tmp32, err := this._io.ReadBytes(int(this.Rdlength))
		if err != nil {
			return err
		}
		tmp32 = tmp32
		this._raw_Payload = tmp32
		_io__raw_Payload := kaitai.NewStream(bytes.NewReader(this._raw_Payload))
		tmp33 := NewDnsPacket_MxInfo()
		err = tmp33.Read(_io__raw_Payload, this, this._root)
		if err != nil {
			return err
		}
		this.Payload = tmp33
	case DnsPacket_TypeType__Ns:
		tmp34, err := this._io.ReadBytes(int(this.Rdlength))
		if err != nil {
			return err
		}
		tmp34 = tmp34
		this._raw_Payload = tmp34
		_io__raw_Payload := kaitai.NewStream(bytes.NewReader(this._raw_Payload))
		tmp35 := NewDnsPacket_DomainName()
		err = tmp35.Read(_io__raw_Payload, this, this._root)
		if err != nil {
			return err
		}
		this.Payload = tmp35
	case DnsPacket_TypeType__Ptr:
		tmp36, err := this._io.ReadBytes(int(this.Rdlength))
		if err != nil {
			return err
		}
		tmp36 = tmp36
		this._raw_Payload = tmp36
		_io__raw_Payload := kaitai.NewStream(bytes.NewReader(this._raw_Payload))
		tmp37 := NewDnsPacket_DomainName()
		err = tmp37.Read(_io__raw_Payload, this, this._root)
		if err != nil {
			return err
		}
		this.Payload = tmp37
	case DnsPacket_TypeType__Soa:
		tmp38, err := this._io.ReadBytes(int(this.Rdlength))
		if err != nil {
			return err
		}
		tmp38 = tmp38
		this._raw_Payload = tmp38
		_io__raw_Payload := kaitai.NewStream(bytes.NewReader(this._raw_Payload))
		tmp39 := NewDnsPacket_AuthorityInfo()
		err = tmp39.Read(_io__raw_Payload, this, this._root)
		if err != nil {
			return err
		}
		this.Payload = tmp39
	case DnsPacket_TypeType__Srv:
		tmp40, err := this._io.ReadBytes(int(this.Rdlength))
		if err != nil {
			return err
		}
		tmp40 = tmp40
		this._raw_Payload = tmp40
		_io__raw_Payload := kaitai.NewStream(bytes.NewReader(this._raw_Payload))
		tmp41 := NewDnsPacket_Service()
		err = tmp41.Read(_io__raw_Payload, this, this._root)
		if err != nil {
			return err
		}
		this.Payload = tmp41
	case DnsPacket_TypeType__Txt:
		tmp42, err := this._io.ReadBytes(int(this.Rdlength))
		if err != nil {
			return err
		}
		tmp42 = tmp42
		this._raw_Payload = tmp42
		_io__raw_Payload := kaitai.NewStream(bytes.NewReader(this._raw_Payload))
		tmp43 := NewDnsPacket_TxtBody()
		err = tmp43.Read(_io__raw_Payload, this, this._root)
		if err != nil {
			return err
		}
		this.Payload = tmp43
	default:
		tmp44, err := this._io.ReadBytes(int(this.Rdlength))
		if err != nil {
			return err
		}
		tmp44 = tmp44
		this._raw_Payload = tmp44
	}
	return err
}

/**
 * Time to live (in seconds)
 */

/**
 * Length in octets of the following payload
 */
type DnsPacket_AuthorityInfo struct {
	PrimaryNs *DnsPacket_DomainName
	ResoponsibleMailbox *DnsPacket_DomainName
	Serial uint32
	RefreshInterval uint32
	RetryInterval uint32
	ExpireLimit uint32
	MinTtl uint32
	_io *kaitai.Stream
	_root *DnsPacket
	_parent *DnsPacket_Answer
}
func NewDnsPacket_AuthorityInfo() *DnsPacket_AuthorityInfo {
	return &DnsPacket_AuthorityInfo{
	}
}

func (this DnsPacket_AuthorityInfo) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket_AuthorityInfo) Read(io *kaitai.Stream, parent *DnsPacket_Answer, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp45 := NewDnsPacket_DomainName()
	err = tmp45.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.PrimaryNs = tmp45
	tmp46 := NewDnsPacket_DomainName()
	err = tmp46.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.ResoponsibleMailbox = tmp46
	tmp47, err := this._io.ReadU4be()
	if err != nil {
		return err
	}
	this.Serial = uint32(tmp47)
	tmp48, err := this._io.ReadU4be()
	if err != nil {
		return err
	}
	this.RefreshInterval = uint32(tmp48)
	tmp49, err := this._io.ReadU4be()
	if err != nil {
		return err
	}
	this.RetryInterval = uint32(tmp49)
	tmp50, err := this._io.ReadU4be()
	if err != nil {
		return err
	}
	this.ExpireLimit = uint32(tmp50)
	tmp51, err := this._io.ReadU4be()
	if err != nil {
		return err
	}
	this.MinTtl = uint32(tmp51)
	return err
}
type DnsPacket_DomainName struct {
	Name []*DnsPacket_Label
	_io *kaitai.Stream
	_root *DnsPacket
	_parent kaitai.Struct
}
func NewDnsPacket_DomainName() *DnsPacket_DomainName {
	return &DnsPacket_DomainName{
	}
}

func (this DnsPacket_DomainName) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket_DomainName) Read(io *kaitai.Stream, parent kaitai.Struct, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	for i := 1;; i++ {
		tmp52 := NewDnsPacket_Label()
		err = tmp52.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		_it := tmp52
		this.Name = append(this.Name, _it)
		if  ((_it.Length == 0) || (_it.Length >= 192))  {
			break
		}
	}
	return err
}

/**
 * Repeat until the length is 0 or it is a pointer (bit-hack to get around lack of OR operator)
 */
type DnsPacket_Label struct {
	Length uint8
	Pointer *DnsPacket_PointerStruct
	Name string
	_io *kaitai.Stream
	_root *DnsPacket
	_parent *DnsPacket_DomainName
	_f_isPointer bool
	isPointer bool
}
func NewDnsPacket_Label() *DnsPacket_Label {
	return &DnsPacket_Label{
	}
}

func (this DnsPacket_Label) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket_Label) Read(io *kaitai.Stream, parent *DnsPacket_DomainName, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp53, err := this._io.ReadU1()
	if err != nil {
		return err
	}
	this.Length = tmp53
	tmp54, err := this.IsPointer()
	if err != nil {
		return err
	}
	if (tmp54) {
		tmp55 := NewDnsPacket_PointerStruct()
		err = tmp55.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.Pointer = tmp55
	}
	tmp56, err := this.IsPointer()
	if err != nil {
		return err
	}
	if (!(tmp56)) {
		tmp57, err := this._io.ReadBytes(int(this.Length))
		if err != nil {
			return err
		}
		tmp57 = tmp57
		this.Name = string(tmp57)
	}
	return err
}
func (this *DnsPacket_Label) IsPointer() (v bool, err error) {
	if (this._f_isPointer) {
		return this.isPointer, nil
	}
	this._f_isPointer = true
	this.isPointer = bool(this.Length >= 192)
	return this.isPointer, nil
}

/**
 * RFC1035 4.1.4: If the first two bits are raised it's a pointer-offset to a previously defined name
 */

/**
 * Otherwise its a string the length of the length value
 */
type DnsPacket_MxInfo struct {
	Preference uint16
	Mx *DnsPacket_DomainName
	_io *kaitai.Stream
	_root *DnsPacket
	_parent *DnsPacket_Answer
}
func NewDnsPacket_MxInfo() *DnsPacket_MxInfo {
	return &DnsPacket_MxInfo{
	}
}

func (this DnsPacket_MxInfo) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket_MxInfo) Read(io *kaitai.Stream, parent *DnsPacket_Answer, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp58, err := this._io.ReadU2be()
	if err != nil {
		return err
	}
	this.Preference = uint16(tmp58)
	tmp59 := NewDnsPacket_DomainName()
	err = tmp59.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Mx = tmp59
	return err
}
type DnsPacket_PacketFlags struct {
	Flag uint16
	_io *kaitai.Stream
	_root *DnsPacket
	_parent *DnsPacket
	_f_aa bool
	aa int
	_f_ad bool
	ad int
	_f_cd bool
	cd int
	_f_isOpcodeValid bool
	isOpcodeValid bool
	_f_opcode bool
	opcode int
	_f_qr bool
	qr int
	_f_ra bool
	ra int
	_f_rcode bool
	rcode int
	_f_rd bool
	rd int
	_f_tc bool
	tc int
	_f_z bool
	z int
}
func NewDnsPacket_PacketFlags() *DnsPacket_PacketFlags {
	return &DnsPacket_PacketFlags{
	}
}

func (this DnsPacket_PacketFlags) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket_PacketFlags) Read(io *kaitai.Stream, parent *DnsPacket, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp60, err := this._io.ReadU2be()
	if err != nil {
		return err
	}
	this.Flag = uint16(tmp60)
	return err
}
func (this *DnsPacket_PacketFlags) Aa() (v int, err error) {
	if (this._f_aa) {
		return this.aa, nil
	}
	this._f_aa = true
	this.aa = int((this.Flag & 1024) >> 10)
	return this.aa, nil
}
func (this *DnsPacket_PacketFlags) Ad() (v int, err error) {
	if (this._f_ad) {
		return this.ad, nil
	}
	this._f_ad = true
	this.ad = int((this.Flag & 32) >> 5)
	return this.ad, nil
}
func (this *DnsPacket_PacketFlags) Cd() (v int, err error) {
	if (this._f_cd) {
		return this.cd, nil
	}
	this._f_cd = true
	this.cd = int((this.Flag & 16) >> 4)
	return this.cd, nil
}
func (this *DnsPacket_PacketFlags) IsOpcodeValid() (v bool, err error) {
	if (this._f_isOpcodeValid) {
		return this.isOpcodeValid, nil
	}
	this._f_isOpcodeValid = true
	tmp61, err := this.Opcode()
	if err != nil {
		return false, err
	}
	tmp62, err := this.Opcode()
	if err != nil {
		return false, err
	}
	tmp63, err := this.Opcode()
	if err != nil {
		return false, err
	}
	this.isOpcodeValid = bool( ((tmp61 == 0) || (tmp62 == 1) || (tmp63 == 2)) )
	return this.isOpcodeValid, nil
}
func (this *DnsPacket_PacketFlags) Opcode() (v int, err error) {
	if (this._f_opcode) {
		return this.opcode, nil
	}
	this._f_opcode = true
	this.opcode = int((this.Flag & 30720) >> 11)
	return this.opcode, nil
}
func (this *DnsPacket_PacketFlags) Qr() (v int, err error) {
	if (this._f_qr) {
		return this.qr, nil
	}
	this._f_qr = true
	this.qr = int((this.Flag & 32768) >> 15)
	return this.qr, nil
}
func (this *DnsPacket_PacketFlags) Ra() (v int, err error) {
	if (this._f_ra) {
		return this.ra, nil
	}
	this._f_ra = true
	this.ra = int((this.Flag & 128) >> 7)
	return this.ra, nil
}
func (this *DnsPacket_PacketFlags) Rcode() (v int, err error) {
	if (this._f_rcode) {
		return this.rcode, nil
	}
	this._f_rcode = true
	this.rcode = int((this.Flag & 15) >> 0)
	return this.rcode, nil
}
func (this *DnsPacket_PacketFlags) Rd() (v int, err error) {
	if (this._f_rd) {
		return this.rd, nil
	}
	this._f_rd = true
	this.rd = int((this.Flag & 256) >> 8)
	return this.rd, nil
}
func (this *DnsPacket_PacketFlags) Tc() (v int, err error) {
	if (this._f_tc) {
		return this.tc, nil
	}
	this._f_tc = true
	this.tc = int((this.Flag & 512) >> 9)
	return this.tc, nil
}
func (this *DnsPacket_PacketFlags) Z() (v int, err error) {
	if (this._f_z) {
		return this.z, nil
	}
	this._f_z = true
	this.z = int((this.Flag & 64) >> 6)
	return this.z, nil
}
type DnsPacket_PointerStruct struct {
	Value uint8
	_io *kaitai.Stream
	_root *DnsPacket
	_parent *DnsPacket_Label
	_f_contents bool
	contents *DnsPacket_DomainName
}
func NewDnsPacket_PointerStruct() *DnsPacket_PointerStruct {
	return &DnsPacket_PointerStruct{
	}
}

func (this DnsPacket_PointerStruct) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket_PointerStruct) Read(io *kaitai.Stream, parent *DnsPacket_Label, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp64, err := this._io.ReadU1()
	if err != nil {
		return err
	}
	this.Value = tmp64
	return err
}
func (this *DnsPacket_PointerStruct) Contents() (v *DnsPacket_DomainName, err error) {
	if (this._f_contents) {
		return this.contents, nil
	}
	this._f_contents = true
	thisIo := this._root._io
	_pos, err := thisIo.Pos()
	if err != nil {
		return nil, err
	}
	_, err = thisIo.Seek(int64(this.Value + (this._parent.Length - 192) << 8), io.SeekStart)
	if err != nil {
		return nil, err
	}
	tmp65 := NewDnsPacket_DomainName()
	err = tmp65.Read(thisIo, this, this._root)
	if err != nil {
		return nil, err
	}
	this.contents = tmp65
	_, err = thisIo.Seek(_pos, io.SeekStart)
	if err != nil {
		return nil, err
	}
	return this.contents, nil
}

/**
 * Read one byte, then offset to that position, read one domain-name and return
 */
type DnsPacket_Query struct {
	Name *DnsPacket_DomainName
	Type DnsPacket_TypeType
	QueryClass DnsPacket_ClassType
	_io *kaitai.Stream
	_root *DnsPacket
	_parent *DnsPacket
}
func NewDnsPacket_Query() *DnsPacket_Query {
	return &DnsPacket_Query{
	}
}

func (this DnsPacket_Query) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket_Query) Read(io *kaitai.Stream, parent *DnsPacket, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp66 := NewDnsPacket_DomainName()
	err = tmp66.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Name = tmp66
	tmp67, err := this._io.ReadU2be()
	if err != nil {
		return err
	}
	this.Type = DnsPacket_TypeType(tmp67)
	tmp68, err := this._io.ReadU2be()
	if err != nil {
		return err
	}
	this.QueryClass = DnsPacket_ClassType(tmp68)
	return err
}
type DnsPacket_Service struct {
	Priority uint16
	Weight uint16
	Port uint16
	Target *DnsPacket_DomainName
	_io *kaitai.Stream
	_root *DnsPacket
	_parent *DnsPacket_Answer
}
func NewDnsPacket_Service() *DnsPacket_Service {
	return &DnsPacket_Service{
	}
}

func (this DnsPacket_Service) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket_Service) Read(io *kaitai.Stream, parent *DnsPacket_Answer, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp69, err := this._io.ReadU2be()
	if err != nil {
		return err
	}
	this.Priority = uint16(tmp69)
	tmp70, err := this._io.ReadU2be()
	if err != nil {
		return err
	}
	this.Weight = uint16(tmp70)
	tmp71, err := this._io.ReadU2be()
	if err != nil {
		return err
	}
	this.Port = uint16(tmp71)
	tmp72 := NewDnsPacket_DomainName()
	err = tmp72.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Target = tmp72
	return err
}
type DnsPacket_Txt struct {
	Length uint8
	Text string
	_io *kaitai.Stream
	_root *DnsPacket
	_parent *DnsPacket_TxtBody
}
func NewDnsPacket_Txt() *DnsPacket_Txt {
	return &DnsPacket_Txt{
	}
}

func (this DnsPacket_Txt) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket_Txt) Read(io *kaitai.Stream, parent *DnsPacket_TxtBody, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp73, err := this._io.ReadU1()
	if err != nil {
		return err
	}
	this.Length = tmp73
	tmp74, err := this._io.ReadBytes(int(this.Length))
	if err != nil {
		return err
	}
	tmp74 = tmp74
	this.Text = string(tmp74)
	return err
}
type DnsPacket_TxtBody struct {
	Data []*DnsPacket_Txt
	_io *kaitai.Stream
	_root *DnsPacket
	_parent *DnsPacket_Answer
}
func NewDnsPacket_TxtBody() *DnsPacket_TxtBody {
	return &DnsPacket_TxtBody{
	}
}

func (this DnsPacket_TxtBody) IO_() *kaitai.Stream {
	return this._io
}

func (this *DnsPacket_TxtBody) Read(io *kaitai.Stream, parent *DnsPacket_Answer, root *DnsPacket) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	for i := 0;; i++ {
		tmp75, err := this._io.EOF()
		if err != nil {
			return err
		}
		if tmp75 {
			break
		}
		tmp76 := NewDnsPacket_Txt()
		err = tmp76.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.Data = append(this.Data, tmp76)
	}
	return err
}