(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.
<?php
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
/**
* (No support for Auth-Name + Add-Name for simplicity)
*/
namespace {
class DnsPacket extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \Kaitai\Struct\Struct $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_transactionId = $this->_io->readU2be();
$this->_m_flags = new \DnsPacket\PacketFlags($this->_io, $this, $this->_root);
if ($this->flags()->isOpcodeValid()) {
$this->_m_qdcount = $this->_io->readU2be();
}
if ($this->flags()->isOpcodeValid()) {
$this->_m_ancount = $this->_io->readU2be();
}
if ($this->flags()->isOpcodeValid()) {
$this->_m_nscount = $this->_io->readU2be();
}
if ($this->flags()->isOpcodeValid()) {
$this->_m_arcount = $this->_io->readU2be();
}
if ($this->flags()->isOpcodeValid()) {
$this->_m_queries = [];
$n = $this->qdcount();
for ($i = 0; $i < $n; $i++) {
$this->_m_queries[] = new \DnsPacket\Query($this->_io, $this, $this->_root);
}
}
if ($this->flags()->isOpcodeValid()) {
$this->_m_answers = [];
$n = $this->ancount();
for ($i = 0; $i < $n; $i++) {
$this->_m_answers[] = new \DnsPacket\Answer($this->_io, $this, $this->_root);
}
}
if ($this->flags()->isOpcodeValid()) {
$this->_m_authorities = [];
$n = $this->nscount();
for ($i = 0; $i < $n; $i++) {
$this->_m_authorities[] = new \DnsPacket\Answer($this->_io, $this, $this->_root);
}
}
if ($this->flags()->isOpcodeValid()) {
$this->_m_additionals = [];
$n = $this->arcount();
for ($i = 0; $i < $n; $i++) {
$this->_m_additionals[] = new \DnsPacket\Answer($this->_io, $this, $this->_root);
}
}
}
protected $_m_transactionId;
protected $_m_flags;
protected $_m_qdcount;
protected $_m_ancount;
protected $_m_nscount;
protected $_m_arcount;
protected $_m_queries;
protected $_m_answers;
protected $_m_authorities;
protected $_m_additionals;
/**
* ID to keep track of request/responces
*/
public function transactionId() { return $this->_m_transactionId; }
public function flags() { return $this->_m_flags; }
/**
* How many questions are there
*/
public function qdcount() { return $this->_m_qdcount; }
/**
* Number of resource records answering the question
*/
public function ancount() { return $this->_m_ancount; }
/**
* Number of resource records pointing toward an authority
*/
public function nscount() { return $this->_m_nscount; }
/**
* Number of resource records holding additional information
*/
public function arcount() { return $this->_m_arcount; }
public function queries() { return $this->_m_queries; }
public function answers() { return $this->_m_answers; }
public function authorities() { return $this->_m_authorities; }
public function additionals() { return $this->_m_additionals; }
}
}
namespace DnsPacket {
class MxInfo extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \DnsPacket\Answer $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_preference = $this->_io->readU2be();
$this->_m_mx = new \DnsPacket\DomainName($this->_io, $this, $this->_root);
}
protected $_m_preference;
protected $_m_mx;
public function preference() { return $this->_m_preference; }
public function mx() { return $this->_m_mx; }
}
}
namespace DnsPacket {
class PointerStruct extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \DnsPacket\Label $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_value = $this->_io->readU1();
}
protected $_m_contents;
public function contents() {
if ($this->_m_contents !== null)
return $this->_m_contents;
$io = $this->_root()->_io();
$_pos = $io->pos();
$io->seek(($this->value() + (($this->_parent()->length() - 192) << 8)));
$this->_m_contents = new \DnsPacket\DomainName($io, $this, $this->_root);
$io->seek($_pos);
return $this->_m_contents;
}
protected $_m_value;
/**
* Read one byte, then offset to that position, read one domain-name and return
*/
public function value() { return $this->_m_value; }
}
}
namespace DnsPacket {
class Label extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \DnsPacket\DomainName $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_length = $this->_io->readU1();
if ($this->isPointer()) {
$this->_m_pointer = new \DnsPacket\PointerStruct($this->_io, $this, $this->_root);
}
if (!($this->isPointer())) {
$this->_m_name = \Kaitai\Struct\Stream::bytesToStr($this->_io->readBytes($this->length()), "utf-8");
}
}
protected $_m_isPointer;
public function isPointer() {
if ($this->_m_isPointer !== null)
return $this->_m_isPointer;
$this->_m_isPointer = $this->length() >= 192;
return $this->_m_isPointer;
}
protected $_m_length;
protected $_m_pointer;
protected $_m_name;
/**
* RFC1035 4.1.4: If the first two bits are raised it's a pointer-offset to a previously defined name
*/
public function length() { return $this->_m_length; }
public function pointer() { return $this->_m_pointer; }
/**
* Otherwise its a string the length of the length value
*/
public function name() { return $this->_m_name; }
}
}
namespace DnsPacket {
class Query extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \DnsPacket $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_name = new \DnsPacket\DomainName($this->_io, $this, $this->_root);
$this->_m_type = $this->_io->readU2be();
$this->_m_queryClass = $this->_io->readU2be();
}
protected $_m_name;
protected $_m_type;
protected $_m_queryClass;
public function name() { return $this->_m_name; }
public function type() { return $this->_m_type; }
public function queryClass() { return $this->_m_queryClass; }
}
}
namespace DnsPacket {
class DomainName extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \Kaitai\Struct\Struct $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_name = [];
$i = 0;
do {
$_ = new \DnsPacket\Label($this->_io, $this, $this->_root);
$this->_m_name[] = $_;
$i++;
} while (!( (($_->length() == 0) || ($_->length() >= 192)) ));
}
protected $_m_name;
/**
* Repeat until the length is 0 or it is a pointer (bit-hack to get around lack of OR operator)
*/
public function name() { return $this->_m_name; }
}
}
namespace DnsPacket {
class AddressV6 extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \DnsPacket\Answer $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_ipV6 = $this->_io->readBytes(16);
}
protected $_m_ipV6;
public function ipV6() { return $this->_m_ipV6; }
}
}
namespace DnsPacket {
class Service extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \DnsPacket\Answer $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_priority = $this->_io->readU2be();
$this->_m_weight = $this->_io->readU2be();
$this->_m_port = $this->_io->readU2be();
$this->_m_target = new \DnsPacket\DomainName($this->_io, $this, $this->_root);
}
protected $_m_priority;
protected $_m_weight;
protected $_m_port;
protected $_m_target;
public function priority() { return $this->_m_priority; }
public function weight() { return $this->_m_weight; }
public function port() { return $this->_m_port; }
public function target() { return $this->_m_target; }
}
}
namespace DnsPacket {
class Txt extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \DnsPacket\TxtBody $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_length = $this->_io->readU1();
$this->_m_text = \Kaitai\Struct\Stream::bytesToStr($this->_io->readBytes($this->length()), "utf-8");
}
protected $_m_length;
protected $_m_text;
public function length() { return $this->_m_length; }
public function text() { return $this->_m_text; }
}
}
namespace DnsPacket {
class TxtBody extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \DnsPacket\Answer $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_data = [];
$i = 0;
while (!$this->_io->isEof()) {
$this->_m_data[] = new \DnsPacket\Txt($this->_io, $this, $this->_root);
$i++;
}
}
protected $_m_data;
public function data() { return $this->_m_data; }
}
}
namespace DnsPacket {
class Address extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \DnsPacket\Answer $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_ip = $this->_io->readBytes(4);
}
protected $_m_ip;
public function ip() { return $this->_m_ip; }
}
}
namespace DnsPacket {
class Answer extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \DnsPacket $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_name = new \DnsPacket\DomainName($this->_io, $this, $this->_root);
$this->_m_type = $this->_io->readU2be();
$this->_m_answerClass = $this->_io->readU2be();
$this->_m_ttl = $this->_io->readS4be();
$this->_m_rdlength = $this->_io->readU2be();
switch ($this->type()) {
case \DnsPacket\TypeType::SRV:
$this->_m__raw_payload = $this->_io->readBytes($this->rdlength());
$_io__raw_payload = new \Kaitai\Struct\Stream($this->_m__raw_payload);
$this->_m_payload = new \DnsPacket\Service($_io__raw_payload, $this, $this->_root);
break;
case \DnsPacket\TypeType::A:
$this->_m__raw_payload = $this->_io->readBytes($this->rdlength());
$_io__raw_payload = new \Kaitai\Struct\Stream($this->_m__raw_payload);
$this->_m_payload = new \DnsPacket\Address($_io__raw_payload, $this, $this->_root);
break;
case \DnsPacket\TypeType::CNAME:
$this->_m__raw_payload = $this->_io->readBytes($this->rdlength());
$_io__raw_payload = new \Kaitai\Struct\Stream($this->_m__raw_payload);
$this->_m_payload = new \DnsPacket\DomainName($_io__raw_payload, $this, $this->_root);
break;
case \DnsPacket\TypeType::NS:
$this->_m__raw_payload = $this->_io->readBytes($this->rdlength());
$_io__raw_payload = new \Kaitai\Struct\Stream($this->_m__raw_payload);
$this->_m_payload = new \DnsPacket\DomainName($_io__raw_payload, $this, $this->_root);
break;
case \DnsPacket\TypeType::SOA:
$this->_m__raw_payload = $this->_io->readBytes($this->rdlength());
$_io__raw_payload = new \Kaitai\Struct\Stream($this->_m__raw_payload);
$this->_m_payload = new \DnsPacket\AuthorityInfo($_io__raw_payload, $this, $this->_root);
break;
case \DnsPacket\TypeType::MX:
$this->_m__raw_payload = $this->_io->readBytes($this->rdlength());
$_io__raw_payload = new \Kaitai\Struct\Stream($this->_m__raw_payload);
$this->_m_payload = new \DnsPacket\MxInfo($_io__raw_payload, $this, $this->_root);
break;
case \DnsPacket\TypeType::TXT:
$this->_m__raw_payload = $this->_io->readBytes($this->rdlength());
$_io__raw_payload = new \Kaitai\Struct\Stream($this->_m__raw_payload);
$this->_m_payload = new \DnsPacket\TxtBody($_io__raw_payload, $this, $this->_root);
break;
case \DnsPacket\TypeType::PTR:
$this->_m__raw_payload = $this->_io->readBytes($this->rdlength());
$_io__raw_payload = new \Kaitai\Struct\Stream($this->_m__raw_payload);
$this->_m_payload = new \DnsPacket\DomainName($_io__raw_payload, $this, $this->_root);
break;
case \DnsPacket\TypeType::AAAA:
$this->_m__raw_payload = $this->_io->readBytes($this->rdlength());
$_io__raw_payload = new \Kaitai\Struct\Stream($this->_m__raw_payload);
$this->_m_payload = new \DnsPacket\AddressV6($_io__raw_payload, $this, $this->_root);
break;
default:
$this->_m_payload = $this->_io->readBytes($this->rdlength());
break;
}
}
protected $_m_name;
protected $_m_type;
protected $_m_answerClass;
protected $_m_ttl;
protected $_m_rdlength;
protected $_m_payload;
protected $_m__raw_payload;
public function name() { return $this->_m_name; }
public function type() { return $this->_m_type; }
public function answerClass() { return $this->_m_answerClass; }
/**
* Time to live (in seconds)
*/
public function ttl() { return $this->_m_ttl; }
/**
* Length in octets of the following payload
*/
public function rdlength() { return $this->_m_rdlength; }
public function payload() { return $this->_m_payload; }
public function _raw_payload() { return $this->_m__raw_payload; }
}
}
namespace DnsPacket {
class PacketFlags extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \DnsPacket $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_flag = $this->_io->readU2be();
}
protected $_m_qr;
public function qr() {
if ($this->_m_qr !== null)
return $this->_m_qr;
$this->_m_qr = (($this->flag() & 32768) >> 15);
return $this->_m_qr;
}
protected $_m_ra;
public function ra() {
if ($this->_m_ra !== null)
return $this->_m_ra;
$this->_m_ra = (($this->flag() & 128) >> 7);
return $this->_m_ra;
}
protected $_m_tc;
public function tc() {
if ($this->_m_tc !== null)
return $this->_m_tc;
$this->_m_tc = (($this->flag() & 512) >> 9);
return $this->_m_tc;
}
protected $_m_isOpcodeValid;
public function isOpcodeValid() {
if ($this->_m_isOpcodeValid !== null)
return $this->_m_isOpcodeValid;
$this->_m_isOpcodeValid = (($this->opcode() == 0) || ($this->opcode() == 1) || ($this->opcode() == 2)) ;
return $this->_m_isOpcodeValid;
}
protected $_m_rcode;
public function rcode() {
if ($this->_m_rcode !== null)
return $this->_m_rcode;
$this->_m_rcode = (($this->flag() & 15) >> 0);
return $this->_m_rcode;
}
protected $_m_opcode;
public function opcode() {
if ($this->_m_opcode !== null)
return $this->_m_opcode;
$this->_m_opcode = (($this->flag() & 30720) >> 11);
return $this->_m_opcode;
}
protected $_m_aa;
public function aa() {
if ($this->_m_aa !== null)
return $this->_m_aa;
$this->_m_aa = (($this->flag() & 1024) >> 10);
return $this->_m_aa;
}
protected $_m_z;
public function z() {
if ($this->_m_z !== null)
return $this->_m_z;
$this->_m_z = (($this->flag() & 64) >> 6);
return $this->_m_z;
}
protected $_m_rd;
public function rd() {
if ($this->_m_rd !== null)
return $this->_m_rd;
$this->_m_rd = (($this->flag() & 256) >> 8);
return $this->_m_rd;
}
protected $_m_cd;
public function cd() {
if ($this->_m_cd !== null)
return $this->_m_cd;
$this->_m_cd = (($this->flag() & 16) >> 4);
return $this->_m_cd;
}
protected $_m_ad;
public function ad() {
if ($this->_m_ad !== null)
return $this->_m_ad;
$this->_m_ad = (($this->flag() & 32) >> 5);
return $this->_m_ad;
}
protected $_m_flag;
public function flag() { return $this->_m_flag; }
}
}
namespace DnsPacket {
class AuthorityInfo extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, \DnsPacket\Answer $_parent = null, \DnsPacket $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_primaryNs = new \DnsPacket\DomainName($this->_io, $this, $this->_root);
$this->_m_resoponsibleMailbox = new \DnsPacket\DomainName($this->_io, $this, $this->_root);
$this->_m_serial = $this->_io->readU4be();
$this->_m_refreshInterval = $this->_io->readU4be();
$this->_m_retryInterval = $this->_io->readU4be();
$this->_m_expireLimit = $this->_io->readU4be();
$this->_m_minTtl = $this->_io->readU4be();
}
protected $_m_primaryNs;
protected $_m_resoponsibleMailbox;
protected $_m_serial;
protected $_m_refreshInterval;
protected $_m_retryInterval;
protected $_m_expireLimit;
protected $_m_minTtl;
public function primaryNs() { return $this->_m_primaryNs; }
public function resoponsibleMailbox() { return $this->_m_resoponsibleMailbox; }
public function serial() { return $this->_m_serial; }
public function refreshInterval() { return $this->_m_refreshInterval; }
public function retryInterval() { return $this->_m_retryInterval; }
public function expireLimit() { return $this->_m_expireLimit; }
public function minTtl() { return $this->_m_minTtl; }
}
}
namespace DnsPacket {
class ClassType {
const IN_CLASS = 1;
const CS = 2;
const CH = 3;
const HS = 4;
}
}
namespace DnsPacket {
class TypeType {
const A = 1;
const NS = 2;
const MD = 3;
const MF = 4;
const CNAME = 5;
const SOA = 6;
const MB = 7;
const MG = 8;
const MR = 9;
const NULL = 10;
const WKS = 11;
const PTR = 12;
const HINFO = 13;
const MINFO = 14;
const MX = 15;
const TXT = 16;
const AAAA = 28;
const SRV = 33;
}
}