This page hosts a formal specification of IPv4 network 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++98/STL generated by Kaitai Struct depends on the C++/STL runtime library. You have to install it before you can parse data.
For C++, the easiest way is to clone the runtime library sources and build them along with your project.
Using Kaitai Struct in C++/STL usually consists of 3 steps.
std::istream
). One can open local file for that, or use existing std::string
or char*
buffer.
#include <fstream>
std::ifstream is("path/to/local/file.bin", std::ifstream::binary);
#include <sstream>
std::istringstream is(str);
#include <sstream>
const char buf[] = { ... };
std::string str(buf, sizeof buf);
std::istringstream is(str);
#include "kaitai/kaitaistream.h"
kaitai::kstream ks(&is);
ipv4_packet_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.b1() // => get b1
#ifndef IPV4_PACKET_H_
#define IPV4_PACKET_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "kaitai/kaitaistruct.h"
#include <stdint.h>
#include "protocol_body.h"
#include <vector>
#if KAITAI_STRUCT_VERSION < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif
class protocol_body_t;
class ipv4_packet_t : public kaitai::kstruct {
public:
class ipv4_options_t;
class ipv4_option_t;
ipv4_packet_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, ipv4_packet_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~ipv4_packet_t();
class ipv4_options_t : public kaitai::kstruct {
public:
ipv4_options_t(kaitai::kstream* p__io, ipv4_packet_t* p__parent = 0, ipv4_packet_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~ipv4_options_t();
private:
std::vector<ipv4_option_t*>* m_entries;
ipv4_packet_t* m__root;
ipv4_packet_t* m__parent;
public:
std::vector<ipv4_option_t*>* entries() const { return m_entries; }
ipv4_packet_t* _root() const { return m__root; }
ipv4_packet_t* _parent() const { return m__parent; }
};
class ipv4_option_t : public kaitai::kstruct {
public:
ipv4_option_t(kaitai::kstream* p__io, ipv4_packet_t::ipv4_options_t* p__parent = 0, ipv4_packet_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~ipv4_option_t();
private:
bool f_copy;
int32_t m_copy;
public:
int32_t copy();
private:
bool f_opt_class;
int32_t m_opt_class;
public:
int32_t opt_class();
private:
bool f_number;
int32_t m_number;
public:
int32_t number();
private:
uint8_t m_b1;
uint8_t m_len;
std::string m_body;
ipv4_packet_t* m__root;
ipv4_packet_t::ipv4_options_t* m__parent;
public:
uint8_t b1() const { return m_b1; }
uint8_t len() const { return m_len; }
std::string body() const { return m_body; }
ipv4_packet_t* _root() const { return m__root; }
ipv4_packet_t::ipv4_options_t* _parent() const { return m__parent; }
};
private:
bool f_version;
int32_t m_version;
public:
int32_t version();
private:
bool f_ihl;
int32_t m_ihl;
public:
int32_t ihl();
private:
bool f_ihl_bytes;
int32_t m_ihl_bytes;
public:
int32_t ihl_bytes();
private:
uint8_t m_b1;
uint8_t m_b2;
uint16_t m_total_length;
uint16_t m_identification;
uint16_t m_b67;
uint8_t m_ttl;
uint8_t m_protocol;
uint16_t m_header_checksum;
std::string m_src_ip_addr;
std::string m_dst_ip_addr;
ipv4_options_t* m_options;
protocol_body_t* m_body;
ipv4_packet_t* m__root;
kaitai::kstruct* m__parent;
std::string m__raw_options;
kaitai::kstream* m__io__raw_options;
std::string m__raw_body;
kaitai::kstream* m__io__raw_body;
public:
uint8_t b1() const { return m_b1; }
uint8_t b2() const { return m_b2; }
uint16_t total_length() const { return m_total_length; }
uint16_t identification() const { return m_identification; }
uint16_t b67() const { return m_b67; }
uint8_t ttl() const { return m_ttl; }
uint8_t protocol() const { return m_protocol; }
uint16_t header_checksum() const { return m_header_checksum; }
std::string src_ip_addr() const { return m_src_ip_addr; }
std::string dst_ip_addr() const { return m_dst_ip_addr; }
ipv4_options_t* options() const { return m_options; }
protocol_body_t* body() const { return m_body; }
ipv4_packet_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
std::string _raw_options() const { return m__raw_options; }
kaitai::kstream* _io__raw_options() const { return m__io__raw_options; }
std::string _raw_body() const { return m__raw_body; }
kaitai::kstream* _io__raw_body() const { return m__io__raw_body; }
};
#endif // IPV4_PACKET_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "ipv4_packet.h"
ipv4_packet_t::ipv4_packet_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, ipv4_packet_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_options = 0;
m__io__raw_options = 0;
m_body = 0;
m__io__raw_body = 0;
f_version = false;
f_ihl = false;
f_ihl_bytes = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void ipv4_packet_t::_read() {
m_b1 = m__io->read_u1();
m_b2 = m__io->read_u1();
m_total_length = m__io->read_u2be();
m_identification = m__io->read_u2be();
m_b67 = m__io->read_u2be();
m_ttl = m__io->read_u1();
m_protocol = m__io->read_u1();
m_header_checksum = m__io->read_u2be();
m_src_ip_addr = m__io->read_bytes(4);
m_dst_ip_addr = m__io->read_bytes(4);
m__raw_options = m__io->read_bytes((ihl_bytes() - 20));
m__io__raw_options = new kaitai::kstream(m__raw_options);
m_options = new ipv4_options_t(m__io__raw_options, this, m__root);
m__raw_body = m__io->read_bytes((total_length() - ihl_bytes()));
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new protocol_body_t(protocol(), m__io__raw_body);
}
ipv4_packet_t::~ipv4_packet_t() {
_clean_up();
}
void ipv4_packet_t::_clean_up() {
if (m__io__raw_options) {
delete m__io__raw_options; m__io__raw_options = 0;
}
if (m_options) {
delete m_options; m_options = 0;
}
if (m__io__raw_body) {
delete m__io__raw_body; m__io__raw_body = 0;
}
if (m_body) {
delete m_body; m_body = 0;
}
}
ipv4_packet_t::ipv4_options_t::ipv4_options_t(kaitai::kstream* p__io, ipv4_packet_t* p__parent, ipv4_packet_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_entries = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void ipv4_packet_t::ipv4_options_t::_read() {
m_entries = new std::vector<ipv4_option_t*>();
{
int i = 0;
while (!m__io->is_eof()) {
m_entries->push_back(new ipv4_option_t(m__io, this, m__root));
i++;
}
}
}
ipv4_packet_t::ipv4_options_t::~ipv4_options_t() {
_clean_up();
}
void ipv4_packet_t::ipv4_options_t::_clean_up() {
if (m_entries) {
for (std::vector<ipv4_option_t*>::iterator it = m_entries->begin(); it != m_entries->end(); ++it) {
delete *it;
}
delete m_entries; m_entries = 0;
}
}
ipv4_packet_t::ipv4_option_t::ipv4_option_t(kaitai::kstream* p__io, ipv4_packet_t::ipv4_options_t* p__parent, ipv4_packet_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
f_copy = false;
f_opt_class = false;
f_number = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void ipv4_packet_t::ipv4_option_t::_read() {
m_b1 = m__io->read_u1();
m_len = m__io->read_u1();
m_body = m__io->read_bytes(((len() > 2) ? ((len() - 2)) : (0)));
}
ipv4_packet_t::ipv4_option_t::~ipv4_option_t() {
_clean_up();
}
void ipv4_packet_t::ipv4_option_t::_clean_up() {
}
int32_t ipv4_packet_t::ipv4_option_t::copy() {
if (f_copy)
return m_copy;
m_copy = ((b1() & 128) >> 7);
f_copy = true;
return m_copy;
}
int32_t ipv4_packet_t::ipv4_option_t::opt_class() {
if (f_opt_class)
return m_opt_class;
m_opt_class = ((b1() & 96) >> 5);
f_opt_class = true;
return m_opt_class;
}
int32_t ipv4_packet_t::ipv4_option_t::number() {
if (f_number)
return m_number;
m_number = (b1() & 31);
f_number = true;
return m_number;
}
int32_t ipv4_packet_t::version() {
if (f_version)
return m_version;
m_version = ((b1() & 240) >> 4);
f_version = true;
return m_version;
}
int32_t ipv4_packet_t::ihl() {
if (f_ihl)
return m_ihl;
m_ihl = (b1() & 15);
f_ihl = true;
return m_ihl;
}
int32_t ipv4_packet_t::ihl_bytes() {
if (f_ihl_bytes)
return m_ihl_bytes;
m_ihl_bytes = (ihl() * 4);
f_ihl_bytes = true;
return m_ihl_bytes;
}