This page hosts a formal specification of ICMP 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);
icmp_packet_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.icmp_type() // => get icmp type
#ifndef ICMP_PACKET_H_
#define ICMP_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>
#if KAITAI_STRUCT_VERSION < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif
class icmp_packet_t : public kaitai::kstruct {
public:
class destination_unreachable_msg_t;
class time_exceeded_msg_t;
class echo_msg_t;
enum icmp_type_enum_t {
ICMP_TYPE_ENUM_ECHO_REPLY = 0,
ICMP_TYPE_ENUM_DESTINATION_UNREACHABLE = 3,
ICMP_TYPE_ENUM_SOURCE_QUENCH = 4,
ICMP_TYPE_ENUM_REDIRECT = 5,
ICMP_TYPE_ENUM_ECHO = 8,
ICMP_TYPE_ENUM_TIME_EXCEEDED = 11
};
icmp_packet_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, icmp_packet_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~icmp_packet_t();
class destination_unreachable_msg_t : public kaitai::kstruct {
public:
enum destination_unreachable_code_t {
DESTINATION_UNREACHABLE_CODE_NET_UNREACHABLE = 0,
DESTINATION_UNREACHABLE_CODE_HOST_UNREACHABLE = 1,
DESTINATION_UNREACHABLE_CODE_PROTOCOL_UNREACHABLE = 2,
DESTINATION_UNREACHABLE_CODE_PORT_UNREACHABLE = 3,
DESTINATION_UNREACHABLE_CODE_FRAGMENTATION_NEEDED_AND_DF_SET = 4,
DESTINATION_UNREACHABLE_CODE_SOURCE_ROUTE_FAILED = 5,
DESTINATION_UNREACHABLE_CODE_DST_NET_UNKOWN = 6,
DESTINATION_UNREACHABLE_CODE_SDT_HOST_UNKOWN = 7,
DESTINATION_UNREACHABLE_CODE_SRC_ISOLATED = 8,
DESTINATION_UNREACHABLE_CODE_NET_PROHIBITED_BY_ADMIN = 9,
DESTINATION_UNREACHABLE_CODE_HOST_PROHIBITED_BY_ADMIN = 10,
DESTINATION_UNREACHABLE_CODE_NET_UNREACHABLE_FOR_TOS = 11,
DESTINATION_UNREACHABLE_CODE_HOST_UNREACHABLE_FOR_TOS = 12,
DESTINATION_UNREACHABLE_CODE_COMMUNICATION_PROHIBITED_BY_ADMIN = 13,
DESTINATION_UNREACHABLE_CODE_HOST_PRECEDENCE_VIOLATION = 14,
DESTINATION_UNREACHABLE_CODE_PRECEDENCE_CUTTOFF_IN_EFFECT = 15
};
destination_unreachable_msg_t(kaitai::kstream* p__io, icmp_packet_t* p__parent = 0, icmp_packet_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~destination_unreachable_msg_t();
private:
destination_unreachable_code_t m_code;
uint16_t m_checksum;
icmp_packet_t* m__root;
icmp_packet_t* m__parent;
public:
destination_unreachable_code_t code() const { return m_code; }
uint16_t checksum() const { return m_checksum; }
icmp_packet_t* _root() const { return m__root; }
icmp_packet_t* _parent() const { return m__parent; }
};
class time_exceeded_msg_t : public kaitai::kstruct {
public:
enum time_exceeded_code_t {
TIME_EXCEEDED_CODE_TIME_TO_LIVE_EXCEEDED_IN_TRANSIT = 0,
TIME_EXCEEDED_CODE_FRAGMENT_REASSEMBLY_TIME_EXCEEDED = 1
};
time_exceeded_msg_t(kaitai::kstream* p__io, icmp_packet_t* p__parent = 0, icmp_packet_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~time_exceeded_msg_t();
private:
time_exceeded_code_t m_code;
uint16_t m_checksum;
icmp_packet_t* m__root;
icmp_packet_t* m__parent;
public:
time_exceeded_code_t code() const { return m_code; }
uint16_t checksum() const { return m_checksum; }
icmp_packet_t* _root() const { return m__root; }
icmp_packet_t* _parent() const { return m__parent; }
};
class echo_msg_t : public kaitai::kstruct {
public:
echo_msg_t(kaitai::kstream* p__io, icmp_packet_t* p__parent = 0, icmp_packet_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~echo_msg_t();
private:
std::string m_code;
uint16_t m_checksum;
uint16_t m_identifier;
uint16_t m_seq_num;
std::string m_data;
icmp_packet_t* m__root;
icmp_packet_t* m__parent;
public:
std::string code() const { return m_code; }
uint16_t checksum() const { return m_checksum; }
uint16_t identifier() const { return m_identifier; }
uint16_t seq_num() const { return m_seq_num; }
std::string data() const { return m_data; }
icmp_packet_t* _root() const { return m__root; }
icmp_packet_t* _parent() const { return m__parent; }
};
private:
icmp_type_enum_t m_icmp_type;
destination_unreachable_msg_t* m_destination_unreachable;
bool n_destination_unreachable;
public:
bool _is_null_destination_unreachable() { destination_unreachable(); return n_destination_unreachable; };
private:
time_exceeded_msg_t* m_time_exceeded;
bool n_time_exceeded;
public:
bool _is_null_time_exceeded() { time_exceeded(); return n_time_exceeded; };
private:
echo_msg_t* m_echo;
bool n_echo;
public:
bool _is_null_echo() { echo(); return n_echo; };
private:
icmp_packet_t* m__root;
kaitai::kstruct* m__parent;
public:
icmp_type_enum_t icmp_type() const { return m_icmp_type; }
destination_unreachable_msg_t* destination_unreachable() const { return m_destination_unreachable; }
time_exceeded_msg_t* time_exceeded() const { return m_time_exceeded; }
echo_msg_t* echo() const { return m_echo; }
icmp_packet_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
#endif // ICMP_PACKET_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "icmp_packet.h"
#include "kaitai/exceptions.h"
icmp_packet_t::icmp_packet_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, icmp_packet_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_destination_unreachable = 0;
m_time_exceeded = 0;
m_echo = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void icmp_packet_t::_read() {
m_icmp_type = static_cast<icmp_packet_t::icmp_type_enum_t>(m__io->read_u1());
n_destination_unreachable = true;
if (icmp_type() == icmp_packet_t::ICMP_TYPE_ENUM_DESTINATION_UNREACHABLE) {
n_destination_unreachable = false;
m_destination_unreachable = new destination_unreachable_msg_t(m__io, this, m__root);
}
n_time_exceeded = true;
if (icmp_type() == icmp_packet_t::ICMP_TYPE_ENUM_TIME_EXCEEDED) {
n_time_exceeded = false;
m_time_exceeded = new time_exceeded_msg_t(m__io, this, m__root);
}
n_echo = true;
if ( ((icmp_type() == icmp_packet_t::ICMP_TYPE_ENUM_ECHO) || (icmp_type() == icmp_packet_t::ICMP_TYPE_ENUM_ECHO_REPLY)) ) {
n_echo = false;
m_echo = new echo_msg_t(m__io, this, m__root);
}
}
icmp_packet_t::~icmp_packet_t() {
_clean_up();
}
void icmp_packet_t::_clean_up() {
if (!n_destination_unreachable) {
if (m_destination_unreachable) {
delete m_destination_unreachable; m_destination_unreachable = 0;
}
}
if (!n_time_exceeded) {
if (m_time_exceeded) {
delete m_time_exceeded; m_time_exceeded = 0;
}
}
if (!n_echo) {
if (m_echo) {
delete m_echo; m_echo = 0;
}
}
}
icmp_packet_t::destination_unreachable_msg_t::destination_unreachable_msg_t(kaitai::kstream* p__io, icmp_packet_t* p__parent, icmp_packet_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void icmp_packet_t::destination_unreachable_msg_t::_read() {
m_code = static_cast<icmp_packet_t::destination_unreachable_msg_t::destination_unreachable_code_t>(m__io->read_u1());
m_checksum = m__io->read_u2be();
}
icmp_packet_t::destination_unreachable_msg_t::~destination_unreachable_msg_t() {
_clean_up();
}
void icmp_packet_t::destination_unreachable_msg_t::_clean_up() {
}
icmp_packet_t::time_exceeded_msg_t::time_exceeded_msg_t(kaitai::kstream* p__io, icmp_packet_t* p__parent, icmp_packet_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void icmp_packet_t::time_exceeded_msg_t::_read() {
m_code = static_cast<icmp_packet_t::time_exceeded_msg_t::time_exceeded_code_t>(m__io->read_u1());
m_checksum = m__io->read_u2be();
}
icmp_packet_t::time_exceeded_msg_t::~time_exceeded_msg_t() {
_clean_up();
}
void icmp_packet_t::time_exceeded_msg_t::_clean_up() {
}
icmp_packet_t::echo_msg_t::echo_msg_t(kaitai::kstream* p__io, icmp_packet_t* p__parent, icmp_packet_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void icmp_packet_t::echo_msg_t::_read() {
m_code = m__io->read_bytes(1);
if (!(code() == std::string("\x00", 1))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x00", 1), code(), _io(), std::string("/types/echo_msg/seq/0"));
}
m_checksum = m__io->read_u2be();
m_identifier = m__io->read_u2be();
m_seq_num = m__io->read_u2be();
m_data = m__io->read_bytes_full();
}
icmp_packet_t::echo_msg_t::~echo_msg_t() {
_clean_up();
}
void icmp_packet_t::echo_msg_t::_clean_up() {
}