(No support for Auth-Name + Add-Name for simplicity)
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.
All parsing code for C# generated by Kaitai Struct depends on the C# runtime library. You have to install it before you can parse data.
The C# runtime library is available in the NuGet Gallery. Installation instructions can also be found there.
Parse a local file and get structure in memory:
var data = DnsPacket.FromFile("path/to/local/file.bin");
Or parse structure from a byte array:
byte[] someArray = new byte[] { ... };
var data = new DnsPacket(new KaitaiStream(someArray));
After that, one can get various attributes from the structure by accessing properties like:
data.TransactionId // => ID to keep track of request/responces
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
using System.Collections.Generic;
namespace Kaitai
{
/// <summary>
/// (No support for Auth-Name + Add-Name for simplicity)
/// </summary>
public partial class DnsPacket : KaitaiStruct
{
public static DnsPacket FromFile(string fileName)
{
return new DnsPacket(new KaitaiStream(fileName));
}
public enum ClassType
{
InClass = 1,
Cs = 2,
Ch = 3,
Hs = 4,
}
public enum TypeType
{
A = 1,
Ns = 2,
Md = 3,
Mf = 4,
Cname = 5,
Soa = 6,
Mb = 7,
Mg = 8,
Mr = 9,
Null = 10,
Wks = 11,
Ptr = 12,
Hinfo = 13,
Minfo = 14,
Mx = 15,
Txt = 16,
Aaaa = 28,
Srv = 33,
}
public DnsPacket(KaitaiStream p__io, KaitaiStruct p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root ?? this;
_read();
}
private void _read()
{
_transactionId = m_io.ReadU2be();
_flags = new PacketFlags(m_io, this, m_root);
if (Flags.IsOpcodeValid) {
_qdcount = m_io.ReadU2be();
}
if (Flags.IsOpcodeValid) {
_ancount = m_io.ReadU2be();
}
if (Flags.IsOpcodeValid) {
_nscount = m_io.ReadU2be();
}
if (Flags.IsOpcodeValid) {
_arcount = m_io.ReadU2be();
}
if (Flags.IsOpcodeValid) {
_queries = new List<Query>();
for (var i = 0; i < Qdcount; i++)
{
_queries.Add(new Query(m_io, this, m_root));
}
}
if (Flags.IsOpcodeValid) {
_answers = new List<Answer>();
for (var i = 0; i < Ancount; i++)
{
_answers.Add(new Answer(m_io, this, m_root));
}
}
if (Flags.IsOpcodeValid) {
_authorities = new List<Answer>();
for (var i = 0; i < Nscount; i++)
{
_authorities.Add(new Answer(m_io, this, m_root));
}
}
if (Flags.IsOpcodeValid) {
_additionals = new List<Answer>();
for (var i = 0; i < Arcount; i++)
{
_additionals.Add(new Answer(m_io, this, m_root));
}
}
}
public partial class MxInfo : KaitaiStruct
{
public static MxInfo FromFile(string fileName)
{
return new MxInfo(new KaitaiStream(fileName));
}
public MxInfo(KaitaiStream p__io, DnsPacket.Answer p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_preference = m_io.ReadU2be();
_mx = new DomainName(m_io, this, m_root);
}
private ushort _preference;
private DomainName _mx;
private DnsPacket m_root;
private DnsPacket.Answer m_parent;
public ushort Preference { get { return _preference; } }
public DomainName Mx { get { return _mx; } }
public DnsPacket M_Root { get { return m_root; } }
public DnsPacket.Answer M_Parent { get { return m_parent; } }
}
public partial class PointerStruct : KaitaiStruct
{
public static PointerStruct FromFile(string fileName)
{
return new PointerStruct(new KaitaiStream(fileName));
}
public PointerStruct(KaitaiStream p__io, DnsPacket.Label p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
f_contents = false;
_read();
}
private void _read()
{
_value = m_io.ReadU1();
}
private bool f_contents;
private DomainName _contents;
public DomainName Contents
{
get
{
if (f_contents)
return _contents;
KaitaiStream io = M_Root.M_Io;
long _pos = io.Pos;
io.Seek((Value + ((M_Parent.Length - 192) << 8)));
_contents = new DomainName(io, this, m_root);
io.Seek(_pos);
f_contents = true;
return _contents;
}
}
private byte _value;
private DnsPacket m_root;
private DnsPacket.Label m_parent;
/// <summary>
/// Read one byte, then offset to that position, read one domain-name and return
/// </summary>
public byte Value { get { return _value; } }
public DnsPacket M_Root { get { return m_root; } }
public DnsPacket.Label M_Parent { get { return m_parent; } }
}
public partial class Label : KaitaiStruct
{
public static Label FromFile(string fileName)
{
return new Label(new KaitaiStream(fileName));
}
public Label(KaitaiStream p__io, DnsPacket.DomainName p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
f_isPointer = false;
_read();
}
private void _read()
{
_length = m_io.ReadU1();
if (IsPointer) {
_pointer = new PointerStruct(m_io, this, m_root);
}
if (!(IsPointer)) {
_name = System.Text.Encoding.GetEncoding("utf-8").GetString(m_io.ReadBytes(Length));
}
}
private bool f_isPointer;
private bool _isPointer;
public bool IsPointer
{
get
{
if (f_isPointer)
return _isPointer;
_isPointer = (bool) (Length >= 192);
f_isPointer = true;
return _isPointer;
}
}
private byte _length;
private PointerStruct _pointer;
private string _name;
private DnsPacket m_root;
private DnsPacket.DomainName m_parent;
/// <summary>
/// RFC1035 4.1.4: If the first two bits are raised it's a pointer-offset to a previously defined name
/// </summary>
public byte Length { get { return _length; } }
public PointerStruct Pointer { get { return _pointer; } }
/// <summary>
/// Otherwise its a string the length of the length value
/// </summary>
public string Name { get { return _name; } }
public DnsPacket M_Root { get { return m_root; } }
public DnsPacket.DomainName M_Parent { get { return m_parent; } }
}
public partial class Query : KaitaiStruct
{
public static Query FromFile(string fileName)
{
return new Query(new KaitaiStream(fileName));
}
public Query(KaitaiStream p__io, DnsPacket p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_name = new DomainName(m_io, this, m_root);
_type = ((DnsPacket.TypeType) m_io.ReadU2be());
_queryClass = ((DnsPacket.ClassType) m_io.ReadU2be());
}
private DomainName _name;
private TypeType _type;
private ClassType _queryClass;
private DnsPacket m_root;
private DnsPacket m_parent;
public DomainName Name { get { return _name; } }
public TypeType Type { get { return _type; } }
public ClassType QueryClass { get { return _queryClass; } }
public DnsPacket M_Root { get { return m_root; } }
public DnsPacket M_Parent { get { return m_parent; } }
}
public partial class DomainName : KaitaiStruct
{
public static DomainName FromFile(string fileName)
{
return new DomainName(new KaitaiStream(fileName));
}
public DomainName(KaitaiStream p__io, KaitaiStruct p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_name = new List<Label>();
{
var i = 0;
Label M_;
do {
M_ = new Label(m_io, this, m_root);
_name.Add(M_);
i++;
} while (!( ((M_.Length == 0) || (M_.Length >= 192)) ));
}
}
private List<Label> _name;
private DnsPacket m_root;
private KaitaiStruct m_parent;
/// <summary>
/// Repeat until the length is 0 or it is a pointer (bit-hack to get around lack of OR operator)
/// </summary>
public List<Label> Name { get { return _name; } }
public DnsPacket M_Root { get { return m_root; } }
public KaitaiStruct M_Parent { get { return m_parent; } }
}
public partial class AddressV6 : KaitaiStruct
{
public static AddressV6 FromFile(string fileName)
{
return new AddressV6(new KaitaiStream(fileName));
}
public AddressV6(KaitaiStream p__io, DnsPacket.Answer p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_ipV6 = m_io.ReadBytes(16);
}
private byte[] _ipV6;
private DnsPacket m_root;
private DnsPacket.Answer m_parent;
public byte[] IpV6 { get { return _ipV6; } }
public DnsPacket M_Root { get { return m_root; } }
public DnsPacket.Answer M_Parent { get { return m_parent; } }
}
public partial class Service : KaitaiStruct
{
public static Service FromFile(string fileName)
{
return new Service(new KaitaiStream(fileName));
}
public Service(KaitaiStream p__io, DnsPacket.Answer p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_priority = m_io.ReadU2be();
_weight = m_io.ReadU2be();
_port = m_io.ReadU2be();
_target = new DomainName(m_io, this, m_root);
}
private ushort _priority;
private ushort _weight;
private ushort _port;
private DomainName _target;
private DnsPacket m_root;
private DnsPacket.Answer m_parent;
public ushort Priority { get { return _priority; } }
public ushort Weight { get { return _weight; } }
public ushort Port { get { return _port; } }
public DomainName Target { get { return _target; } }
public DnsPacket M_Root { get { return m_root; } }
public DnsPacket.Answer M_Parent { get { return m_parent; } }
}
public partial class Txt : KaitaiStruct
{
public static Txt FromFile(string fileName)
{
return new Txt(new KaitaiStream(fileName));
}
public Txt(KaitaiStream p__io, DnsPacket.TxtBody p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_length = m_io.ReadU1();
_text = System.Text.Encoding.GetEncoding("utf-8").GetString(m_io.ReadBytes(Length));
}
private byte _length;
private string _text;
private DnsPacket m_root;
private DnsPacket.TxtBody m_parent;
public byte Length { get { return _length; } }
public string Text { get { return _text; } }
public DnsPacket M_Root { get { return m_root; } }
public DnsPacket.TxtBody M_Parent { get { return m_parent; } }
}
public partial class TxtBody : KaitaiStruct
{
public static TxtBody FromFile(string fileName)
{
return new TxtBody(new KaitaiStream(fileName));
}
public TxtBody(KaitaiStream p__io, DnsPacket.Answer p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_data = new List<Txt>();
{
var i = 0;
while (!m_io.IsEof) {
_data.Add(new Txt(m_io, this, m_root));
i++;
}
}
}
private List<Txt> _data;
private DnsPacket m_root;
private DnsPacket.Answer m_parent;
public List<Txt> Data { get { return _data; } }
public DnsPacket M_Root { get { return m_root; } }
public DnsPacket.Answer M_Parent { get { return m_parent; } }
}
public partial class Address : KaitaiStruct
{
public static Address FromFile(string fileName)
{
return new Address(new KaitaiStream(fileName));
}
public Address(KaitaiStream p__io, DnsPacket.Answer p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_ip = m_io.ReadBytes(4);
}
private byte[] _ip;
private DnsPacket m_root;
private DnsPacket.Answer m_parent;
public byte[] Ip { get { return _ip; } }
public DnsPacket M_Root { get { return m_root; } }
public DnsPacket.Answer M_Parent { get { return m_parent; } }
}
public partial class Answer : KaitaiStruct
{
public static Answer FromFile(string fileName)
{
return new Answer(new KaitaiStream(fileName));
}
public Answer(KaitaiStream p__io, DnsPacket p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_name = new DomainName(m_io, this, m_root);
_type = ((DnsPacket.TypeType) m_io.ReadU2be());
_answerClass = ((DnsPacket.ClassType) m_io.ReadU2be());
_ttl = m_io.ReadS4be();
_rdlength = m_io.ReadU2be();
switch (Type) {
case DnsPacket.TypeType.Srv: {
__raw_payload = m_io.ReadBytes(Rdlength);
var io___raw_payload = new KaitaiStream(__raw_payload);
_payload = new Service(io___raw_payload, this, m_root);
break;
}
case DnsPacket.TypeType.A: {
__raw_payload = m_io.ReadBytes(Rdlength);
var io___raw_payload = new KaitaiStream(__raw_payload);
_payload = new Address(io___raw_payload, this, m_root);
break;
}
case DnsPacket.TypeType.Cname: {
__raw_payload = m_io.ReadBytes(Rdlength);
var io___raw_payload = new KaitaiStream(__raw_payload);
_payload = new DomainName(io___raw_payload, this, m_root);
break;
}
case DnsPacket.TypeType.Ns: {
__raw_payload = m_io.ReadBytes(Rdlength);
var io___raw_payload = new KaitaiStream(__raw_payload);
_payload = new DomainName(io___raw_payload, this, m_root);
break;
}
case DnsPacket.TypeType.Soa: {
__raw_payload = m_io.ReadBytes(Rdlength);
var io___raw_payload = new KaitaiStream(__raw_payload);
_payload = new AuthorityInfo(io___raw_payload, this, m_root);
break;
}
case DnsPacket.TypeType.Mx: {
__raw_payload = m_io.ReadBytes(Rdlength);
var io___raw_payload = new KaitaiStream(__raw_payload);
_payload = new MxInfo(io___raw_payload, this, m_root);
break;
}
case DnsPacket.TypeType.Txt: {
__raw_payload = m_io.ReadBytes(Rdlength);
var io___raw_payload = new KaitaiStream(__raw_payload);
_payload = new TxtBody(io___raw_payload, this, m_root);
break;
}
case DnsPacket.TypeType.Ptr: {
__raw_payload = m_io.ReadBytes(Rdlength);
var io___raw_payload = new KaitaiStream(__raw_payload);
_payload = new DomainName(io___raw_payload, this, m_root);
break;
}
case DnsPacket.TypeType.Aaaa: {
__raw_payload = m_io.ReadBytes(Rdlength);
var io___raw_payload = new KaitaiStream(__raw_payload);
_payload = new AddressV6(io___raw_payload, this, m_root);
break;
}
default: {
_payload = m_io.ReadBytes(Rdlength);
break;
}
}
}
private DomainName _name;
private TypeType _type;
private ClassType _answerClass;
private int _ttl;
private ushort _rdlength;
private object _payload;
private DnsPacket m_root;
private DnsPacket m_parent;
private byte[] __raw_payload;
public DomainName Name { get { return _name; } }
public TypeType Type { get { return _type; } }
public ClassType AnswerClass { get { return _answerClass; } }
/// <summary>
/// Time to live (in seconds)
/// </summary>
public int Ttl { get { return _ttl; } }
/// <summary>
/// Length in octets of the following payload
/// </summary>
public ushort Rdlength { get { return _rdlength; } }
public object Payload { get { return _payload; } }
public DnsPacket M_Root { get { return m_root; } }
public DnsPacket M_Parent { get { return m_parent; } }
public byte[] M_RawPayload { get { return __raw_payload; } }
}
public partial class PacketFlags : KaitaiStruct
{
public static PacketFlags FromFile(string fileName)
{
return new PacketFlags(new KaitaiStream(fileName));
}
public PacketFlags(KaitaiStream p__io, DnsPacket p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
f_qr = false;
f_ra = false;
f_tc = false;
f_isOpcodeValid = false;
f_rcode = false;
f_opcode = false;
f_aa = false;
f_z = false;
f_rd = false;
f_cd = false;
f_ad = false;
_read();
}
private void _read()
{
_flag = m_io.ReadU2be();
}
private bool f_qr;
private int _qr;
public int Qr
{
get
{
if (f_qr)
return _qr;
_qr = (int) (((Flag & 32768) >> 15));
f_qr = true;
return _qr;
}
}
private bool f_ra;
private int _ra;
public int Ra
{
get
{
if (f_ra)
return _ra;
_ra = (int) (((Flag & 128) >> 7));
f_ra = true;
return _ra;
}
}
private bool f_tc;
private int _tc;
public int Tc
{
get
{
if (f_tc)
return _tc;
_tc = (int) (((Flag & 512) >> 9));
f_tc = true;
return _tc;
}
}
private bool f_isOpcodeValid;
private bool _isOpcodeValid;
public bool IsOpcodeValid
{
get
{
if (f_isOpcodeValid)
return _isOpcodeValid;
_isOpcodeValid = (bool) ( ((Opcode == 0) || (Opcode == 1) || (Opcode == 2)) );
f_isOpcodeValid = true;
return _isOpcodeValid;
}
}
private bool f_rcode;
private int _rcode;
public int Rcode
{
get
{
if (f_rcode)
return _rcode;
_rcode = (int) (((Flag & 15) >> 0));
f_rcode = true;
return _rcode;
}
}
private bool f_opcode;
private int _opcode;
public int Opcode
{
get
{
if (f_opcode)
return _opcode;
_opcode = (int) (((Flag & 30720) >> 11));
f_opcode = true;
return _opcode;
}
}
private bool f_aa;
private int _aa;
public int Aa
{
get
{
if (f_aa)
return _aa;
_aa = (int) (((Flag & 1024) >> 10));
f_aa = true;
return _aa;
}
}
private bool f_z;
private int _z;
public int Z
{
get
{
if (f_z)
return _z;
_z = (int) (((Flag & 64) >> 6));
f_z = true;
return _z;
}
}
private bool f_rd;
private int _rd;
public int Rd
{
get
{
if (f_rd)
return _rd;
_rd = (int) (((Flag & 256) >> 8));
f_rd = true;
return _rd;
}
}
private bool f_cd;
private int _cd;
public int Cd
{
get
{
if (f_cd)
return _cd;
_cd = (int) (((Flag & 16) >> 4));
f_cd = true;
return _cd;
}
}
private bool f_ad;
private int _ad;
public int Ad
{
get
{
if (f_ad)
return _ad;
_ad = (int) (((Flag & 32) >> 5));
f_ad = true;
return _ad;
}
}
private ushort _flag;
private DnsPacket m_root;
private DnsPacket m_parent;
public ushort Flag { get { return _flag; } }
public DnsPacket M_Root { get { return m_root; } }
public DnsPacket M_Parent { get { return m_parent; } }
}
public partial class AuthorityInfo : KaitaiStruct
{
public static AuthorityInfo FromFile(string fileName)
{
return new AuthorityInfo(new KaitaiStream(fileName));
}
public AuthorityInfo(KaitaiStream p__io, DnsPacket.Answer p__parent = null, DnsPacket p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_primaryNs = new DomainName(m_io, this, m_root);
_resoponsibleMailbox = new DomainName(m_io, this, m_root);
_serial = m_io.ReadU4be();
_refreshInterval = m_io.ReadU4be();
_retryInterval = m_io.ReadU4be();
_expireLimit = m_io.ReadU4be();
_minTtl = m_io.ReadU4be();
}
private DomainName _primaryNs;
private DomainName _resoponsibleMailbox;
private uint _serial;
private uint _refreshInterval;
private uint _retryInterval;
private uint _expireLimit;
private uint _minTtl;
private DnsPacket m_root;
private DnsPacket.Answer m_parent;
public DomainName PrimaryNs { get { return _primaryNs; } }
public DomainName ResoponsibleMailbox { get { return _resoponsibleMailbox; } }
public uint Serial { get { return _serial; } }
public uint RefreshInterval { get { return _refreshInterval; } }
public uint RetryInterval { get { return _retryInterval; } }
public uint ExpireLimit { get { return _expireLimit; } }
public uint MinTtl { get { return _minTtl; } }
public DnsPacket M_Root { get { return m_root; } }
public DnsPacket.Answer M_Parent { get { return m_parent; } }
}
private ushort _transactionId;
private PacketFlags _flags;
private ushort? _qdcount;
private ushort? _ancount;
private ushort? _nscount;
private ushort? _arcount;
private List<Query> _queries;
private List<Answer> _answers;
private List<Answer> _authorities;
private List<Answer> _additionals;
private DnsPacket m_root;
private KaitaiStruct m_parent;
/// <summary>
/// ID to keep track of request/responces
/// </summary>
public ushort TransactionId { get { return _transactionId; } }
public PacketFlags Flags { get { return _flags; } }
/// <summary>
/// How many questions are there
/// </summary>
public ushort? Qdcount { get { return _qdcount; } }
/// <summary>
/// Number of resource records answering the question
/// </summary>
public ushort? Ancount { get { return _ancount; } }
/// <summary>
/// Number of resource records pointing toward an authority
/// </summary>
public ushort? Nscount { get { return _nscount; } }
/// <summary>
/// Number of resource records holding additional information
/// </summary>
public ushort? Arcount { get { return _arcount; } }
public List<Query> Queries { get { return _queries; } }
public List<Answer> Answers { get { return _answers; } }
public List<Answer> Authorities { get { return _authorities; } }
public List<Answer> Additionals { get { return _additionals; } }
public DnsPacket M_Root { get { return m_root; } }
public KaitaiStruct M_Parent { get { return m_parent; } }
}
}