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++11/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
#pragma once
// 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 <memory>
#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 = nullptr, ipv4_packet_t* p__root = nullptr);
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 = nullptr, ipv4_packet_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~ipv4_options_t();
private:
std::unique_ptr<std::vector<std::unique_ptr<ipv4_option_t>>> m_entries;
ipv4_packet_t* m__root;
ipv4_packet_t* m__parent;
public:
std::vector<std::unique_ptr<ipv4_option_t>>* entries() const { return m_entries.get(); }
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 = nullptr, ipv4_packet_t* p__root = nullptr);
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;
std::unique_ptr<ipv4_options_t> m_options;
std::unique_ptr<protocol_body_t> m_body;
ipv4_packet_t* m__root;
kaitai::kstruct* m__parent;
std::string m__raw_options;
std::unique_ptr<kaitai::kstream> m__io__raw_options;
std::string m__raw_body;
std::unique_ptr<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.get(); }
protocol_body_t* body() const { return m_body.get(); }
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.get(); }
std::string _raw_body() const { return m__raw_body; }
kaitai::kstream* _io__raw_body() const { return m__io__raw_body.get(); }
};
// 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 = nullptr;
m__io__raw_options = nullptr;
m_body = nullptr;
m__io__raw_body = nullptr;
f_version = false;
f_ihl = false;
f_ihl_bytes = false;
_read();
}
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 = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_options));
m_options = std::unique_ptr<ipv4_options_t>(new ipv4_options_t(m__io__raw_options.get(), this, m__root));
m__raw_body = m__io->read_bytes((total_length() - ihl_bytes()));
m__io__raw_body = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_body));
m_body = std::unique_ptr<protocol_body_t>(new protocol_body_t(protocol(), m__io__raw_body.get()));
}
ipv4_packet_t::~ipv4_packet_t() {
_clean_up();
}
void ipv4_packet_t::_clean_up() {
}
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 = nullptr;
_read();
}
void ipv4_packet_t::ipv4_options_t::_read() {
m_entries = std::unique_ptr<std::vector<std::unique_ptr<ipv4_option_t>>>(new std::vector<std::unique_ptr<ipv4_option_t>>());
{
int i = 0;
while (!m__io->is_eof()) {
m_entries->push_back(std::move(std::unique_ptr<ipv4_option_t>(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() {
}
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;
_read();
}
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;
}