ipv4_packet: Perl parsing library

KS implementation details

Minimal Kaitai Struct required: 0.7

This page hosts a formal specification of ipv4_packet using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Perl source code to parse ipv4_packet

Ipv4Packet.pm

# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

use strict;
use warnings;
use IO::KaitaiStruct 0.007_000;
use TcpSegment;
use Ipv6Packet;
use UdpDatagram;
use IcmpPacket;

########################################################################
package Ipv4Packet;

our @ISA = 'IO::KaitaiStruct::Struct';

sub from_file {
    my ($class, $filename) = @_;
    my $fd;

    open($fd, '<', $filename) or return undef;
    binmode($fd);
    return new($class, IO::KaitaiStruct::Stream->new($fd));
}

our $PROTOCOL_ENUM_HOPOPT = 0;
our $PROTOCOL_ENUM_ICMP = 1;
our $PROTOCOL_ENUM_IGMP = 2;
our $PROTOCOL_ENUM_GGP = 3;
our $PROTOCOL_ENUM_IPV4 = 4;
our $PROTOCOL_ENUM_ST = 5;
our $PROTOCOL_ENUM_TCP = 6;
our $PROTOCOL_ENUM_CBT = 7;
our $PROTOCOL_ENUM_EGP = 8;
our $PROTOCOL_ENUM_IGP = 9;
our $PROTOCOL_ENUM_BBN_RCC_MON = 10;
our $PROTOCOL_ENUM_NVP_II = 11;
our $PROTOCOL_ENUM_PUP = 12;
our $PROTOCOL_ENUM_ARGUS = 13;
our $PROTOCOL_ENUM_EMCON = 14;
our $PROTOCOL_ENUM_XNET = 15;
our $PROTOCOL_ENUM_CHAOS = 16;
our $PROTOCOL_ENUM_UDP = 17;
our $PROTOCOL_ENUM_MUX = 18;
our $PROTOCOL_ENUM_DCN_MEAS = 19;
our $PROTOCOL_ENUM_HMP = 20;
our $PROTOCOL_ENUM_PRM = 21;
our $PROTOCOL_ENUM_XNS_IDP = 22;
our $PROTOCOL_ENUM_TRUNK_1 = 23;
our $PROTOCOL_ENUM_TRUNK_2 = 24;
our $PROTOCOL_ENUM_LEAF_1 = 25;
our $PROTOCOL_ENUM_LEAF_2 = 26;
our $PROTOCOL_ENUM_RDP = 27;
our $PROTOCOL_ENUM_IRTP = 28;
our $PROTOCOL_ENUM_ISO_TP4 = 29;
our $PROTOCOL_ENUM_NETBLT = 30;
our $PROTOCOL_ENUM_MFE_NSP = 31;
our $PROTOCOL_ENUM_MERIT_INP = 32;
our $PROTOCOL_ENUM_DCCP = 33;
our $PROTOCOL_ENUM_X_3PC = 34;
our $PROTOCOL_ENUM_IDPR = 35;
our $PROTOCOL_ENUM_XTP = 36;
our $PROTOCOL_ENUM_DDP = 37;
our $PROTOCOL_ENUM_IDPR_CMTP = 38;
our $PROTOCOL_ENUM_TP_PLUS_PLUS = 39;
our $PROTOCOL_ENUM_IL = 40;
our $PROTOCOL_ENUM_IPV6 = 41;
our $PROTOCOL_ENUM_SDRP = 42;
our $PROTOCOL_ENUM_IPV6_ROUTE = 43;
our $PROTOCOL_ENUM_IPV6_FRAG = 44;
our $PROTOCOL_ENUM_IDRP = 45;
our $PROTOCOL_ENUM_RSVP = 46;
our $PROTOCOL_ENUM_GRE = 47;
our $PROTOCOL_ENUM_DSR = 48;
our $PROTOCOL_ENUM_BNA = 49;
our $PROTOCOL_ENUM_ESP = 50;
our $PROTOCOL_ENUM_AH = 51;
our $PROTOCOL_ENUM_I_NLSP = 52;
our $PROTOCOL_ENUM_SWIPE = 53;
our $PROTOCOL_ENUM_NARP = 54;
our $PROTOCOL_ENUM_MOBILE = 55;
our $PROTOCOL_ENUM_TLSP = 56;
our $PROTOCOL_ENUM_SKIP = 57;
our $PROTOCOL_ENUM_IPV6_ICMP = 58;
our $PROTOCOL_ENUM_IPV6_NONXT = 59;
our $PROTOCOL_ENUM_IPV6_OPTS = 60;
our $PROTOCOL_ENUM_ANY_HOST_INTERNAL_PROTOCOL = 61;
our $PROTOCOL_ENUM_CFTP = 62;
our $PROTOCOL_ENUM_ANY_LOCAL_NETWORK = 63;
our $PROTOCOL_ENUM_SAT_EXPAK = 64;
our $PROTOCOL_ENUM_KRYPTOLAN = 65;
our $PROTOCOL_ENUM_RVD = 66;
our $PROTOCOL_ENUM_IPPC = 67;
our $PROTOCOL_ENUM_ANY_DISTRIBUTED_FILE_SYSTEM = 68;
our $PROTOCOL_ENUM_SAT_MON = 69;
our $PROTOCOL_ENUM_VISA = 70;
our $PROTOCOL_ENUM_IPCV = 71;
our $PROTOCOL_ENUM_CPNX = 72;
our $PROTOCOL_ENUM_CPHB = 73;
our $PROTOCOL_ENUM_WSN = 74;
our $PROTOCOL_ENUM_PVP = 75;
our $PROTOCOL_ENUM_BR_SAT_MON = 76;
our $PROTOCOL_ENUM_SUN_ND = 77;
our $PROTOCOL_ENUM_WB_MON = 78;
our $PROTOCOL_ENUM_WB_EXPAK = 79;
our $PROTOCOL_ENUM_ISO_IP = 80;
our $PROTOCOL_ENUM_VMTP = 81;
our $PROTOCOL_ENUM_SECURE_VMTP = 82;
our $PROTOCOL_ENUM_VINES = 83;
our $PROTOCOL_ENUM_IPTM = 84;
our $PROTOCOL_ENUM_NSFNET_IGP = 85;
our $PROTOCOL_ENUM_DGP = 86;
our $PROTOCOL_ENUM_TCF = 87;
our $PROTOCOL_ENUM_EIGRP = 88;
our $PROTOCOL_ENUM_OSPFIGP = 89;
our $PROTOCOL_ENUM_SPRITE_RPC = 90;
our $PROTOCOL_ENUM_LARP = 91;
our $PROTOCOL_ENUM_MTP = 92;
our $PROTOCOL_ENUM_AX_25 = 93;
our $PROTOCOL_ENUM_IPIP = 94;
our $PROTOCOL_ENUM_MICP = 95;
our $PROTOCOL_ENUM_SCC_SP = 96;
our $PROTOCOL_ENUM_ETHERIP = 97;
our $PROTOCOL_ENUM_ENCAP = 98;
our $PROTOCOL_ENUM_ANY_PRIVATE_ENCRYPTION_SCHEME = 99;
our $PROTOCOL_ENUM_GMTP = 100;
our $PROTOCOL_ENUM_IFMP = 101;
our $PROTOCOL_ENUM_PNNI = 102;
our $PROTOCOL_ENUM_PIM = 103;
our $PROTOCOL_ENUM_ARIS = 104;
our $PROTOCOL_ENUM_SCPS = 105;
our $PROTOCOL_ENUM_QNX = 106;
our $PROTOCOL_ENUM_A_N = 107;
our $PROTOCOL_ENUM_IPCOMP = 108;
our $PROTOCOL_ENUM_SNP = 109;
our $PROTOCOL_ENUM_COMPAQ_PEER = 110;
our $PROTOCOL_ENUM_IPX_IN_IP = 111;
our $PROTOCOL_ENUM_VRRP = 112;
our $PROTOCOL_ENUM_PGM = 113;
our $PROTOCOL_ENUM_ANY_0_HOP = 114;
our $PROTOCOL_ENUM_L2TP = 115;
our $PROTOCOL_ENUM_DDX = 116;
our $PROTOCOL_ENUM_IATP = 117;
our $PROTOCOL_ENUM_STP = 118;
our $PROTOCOL_ENUM_SRP = 119;
our $PROTOCOL_ENUM_UTI = 120;
our $PROTOCOL_ENUM_SMP = 121;
our $PROTOCOL_ENUM_SM = 122;
our $PROTOCOL_ENUM_PTP = 123;
our $PROTOCOL_ENUM_ISIS_OVER_IPV4 = 124;
our $PROTOCOL_ENUM_FIRE = 125;
our $PROTOCOL_ENUM_CRTP = 126;
our $PROTOCOL_ENUM_CRUDP = 127;
our $PROTOCOL_ENUM_SSCOPMCE = 128;
our $PROTOCOL_ENUM_IPLT = 129;
our $PROTOCOL_ENUM_SPS = 130;
our $PROTOCOL_ENUM_PIPE = 131;
our $PROTOCOL_ENUM_SCTP = 132;
our $PROTOCOL_ENUM_FC = 133;
our $PROTOCOL_ENUM_RSVP_E2E_IGNORE = 134;
our $PROTOCOL_ENUM_MOBILITY_HEADER = 135;
our $PROTOCOL_ENUM_UDPLITE = 136;
our $PROTOCOL_ENUM_MPLS_IN_IP = 137;
our $PROTOCOL_ENUM_MANET = 138;
our $PROTOCOL_ENUM_HIP = 139;
our $PROTOCOL_ENUM_SHIM6 = 140;
our $PROTOCOL_ENUM_WESP = 141;
our $PROTOCOL_ENUM_ROHC = 142;
our $PROTOCOL_ENUM_RESERVED_255 = 255;

sub new {
    my ($class, $_io, $_parent, $_root) = @_;
    my $self = IO::KaitaiStruct::Struct->new($_io);

    bless $self, $class;
    $self->{_parent} = $_parent;
    $self->{_root} = $_root || $self;;

    $self->_read();

    return $self;
}

sub _read {
    my ($self) = @_;

    $self->{b1} = $self->{_io}->read_u1();
    $self->{b2} = $self->{_io}->read_u1();
    $self->{total_length} = $self->{_io}->read_u2be();
    $self->{identification} = $self->{_io}->read_u2be();
    $self->{b67} = $self->{_io}->read_u2be();
    $self->{ttl} = $self->{_io}->read_u1();
    $self->{protocol} = $self->{_io}->read_u1();
    $self->{header_checksum} = $self->{_io}->read_u2be();
    $self->{src_ip_addr} = $self->{_io}->read_bytes(4);
    $self->{dst_ip_addr} = $self->{_io}->read_bytes(4);
    $self->{_raw_options} = $self->{_io}->read_bytes(($self->ihl_bytes() - 20));
    my $io__raw_options = IO::KaitaiStruct::Stream->new($self->{_raw_options});
    $self->{options} = Ipv4Packet::Ipv4Options->new($io__raw_options, $self, $self->{_root});
    my $_on = $self->protocol();
    if ($_on == $PROTOCOL_ENUM_TCP) {
        $self->{_raw_body} = $self->{_io}->read_bytes(($self->total_length() - $self->ihl_bytes()));
        my $io__raw_body = IO::KaitaiStruct::Stream->new($self->{_raw_body});
        $self->{body} = TcpSegment->new($io__raw_body);
    }
    elsif ($_on == $PROTOCOL_ENUM_ICMP) {
        $self->{_raw_body} = $self->{_io}->read_bytes(($self->total_length() - $self->ihl_bytes()));
        my $io__raw_body = IO::KaitaiStruct::Stream->new($self->{_raw_body});
        $self->{body} = IcmpPacket->new($io__raw_body);
    }
    elsif ($_on == $PROTOCOL_ENUM_UDP) {
        $self->{_raw_body} = $self->{_io}->read_bytes(($self->total_length() - $self->ihl_bytes()));
        my $io__raw_body = IO::KaitaiStruct::Stream->new($self->{_raw_body});
        $self->{body} = UdpDatagram->new($io__raw_body);
    }
    elsif ($_on == $PROTOCOL_ENUM_IPV6) {
        $self->{_raw_body} = $self->{_io}->read_bytes(($self->total_length() - $self->ihl_bytes()));
        my $io__raw_body = IO::KaitaiStruct::Stream->new($self->{_raw_body});
        $self->{body} = Ipv6Packet->new($io__raw_body);
    }
    else {
        $self->{body} = $self->{_io}->read_bytes(($self->total_length() - $self->ihl_bytes()));
    }
}

sub version {
    my ($self) = @_;
    return $self->{version} if ($self->{version});
    $self->{version} = (($self->b1() & 240) >> 4);
    return $self->{version};
}

sub ihl {
    my ($self) = @_;
    return $self->{ihl} if ($self->{ihl});
    $self->{ihl} = ($self->b1() & 15);
    return $self->{ihl};
}

sub ihl_bytes {
    my ($self) = @_;
    return $self->{ihl_bytes} if ($self->{ihl_bytes});
    $self->{ihl_bytes} = ($self->ihl() * 4);
    return $self->{ihl_bytes};
}

sub b1 {
    my ($self) = @_;
    return $self->{b1};
}

sub b2 {
    my ($self) = @_;
    return $self->{b2};
}

sub total_length {
    my ($self) = @_;
    return $self->{total_length};
}

sub identification {
    my ($self) = @_;
    return $self->{identification};
}

sub b67 {
    my ($self) = @_;
    return $self->{b67};
}

sub ttl {
    my ($self) = @_;
    return $self->{ttl};
}

sub protocol {
    my ($self) = @_;
    return $self->{protocol};
}

sub header_checksum {
    my ($self) = @_;
    return $self->{header_checksum};
}

sub src_ip_addr {
    my ($self) = @_;
    return $self->{src_ip_addr};
}

sub dst_ip_addr {
    my ($self) = @_;
    return $self->{dst_ip_addr};
}

sub options {
    my ($self) = @_;
    return $self->{options};
}

sub body {
    my ($self) = @_;
    return $self->{body};
}

sub _raw_options {
    my ($self) = @_;
    return $self->{_raw_options};
}

sub _raw_body {
    my ($self) = @_;
    return $self->{_raw_body};
}

########################################################################
package Ipv4Packet::Ipv4Options;

our @ISA = 'IO::KaitaiStruct::Struct';

sub from_file {
    my ($class, $filename) = @_;
    my $fd;

    open($fd, '<', $filename) or return undef;
    binmode($fd);
    return new($class, IO::KaitaiStruct::Stream->new($fd));
}

sub new {
    my ($class, $_io, $_parent, $_root) = @_;
    my $self = IO::KaitaiStruct::Struct->new($_io);

    bless $self, $class;
    $self->{_parent} = $_parent;
    $self->{_root} = $_root || $self;;

    $self->_read();

    return $self;
}

sub _read {
    my ($self) = @_;

    $self->{entries} = ();
    while (!$self->{_io}->is_eof()) {
        push @{$self->{entries}}, Ipv4Packet::Ipv4Option->new($self->{_io}, $self, $self->{_root});
    }
}

sub entries {
    my ($self) = @_;
    return $self->{entries};
}

########################################################################
package Ipv4Packet::Ipv4Option;

our @ISA = 'IO::KaitaiStruct::Struct';

sub from_file {
    my ($class, $filename) = @_;
    my $fd;

    open($fd, '<', $filename) or return undef;
    binmode($fd);
    return new($class, IO::KaitaiStruct::Stream->new($fd));
}

sub new {
    my ($class, $_io, $_parent, $_root) = @_;
    my $self = IO::KaitaiStruct::Struct->new($_io);

    bless $self, $class;
    $self->{_parent} = $_parent;
    $self->{_root} = $_root || $self;;

    $self->_read();

    return $self;
}

sub _read {
    my ($self) = @_;

    $self->{b1} = $self->{_io}->read_u1();
    $self->{len} = $self->{_io}->read_u1();
    $self->{body} = $self->{_io}->read_bytes(($self->len() > 2 ? ($self->len() - 2) : 0));
}

sub copy {
    my ($self) = @_;
    return $self->{copy} if ($self->{copy});
    $self->{copy} = (($self->b1() & 128) >> 7);
    return $self->{copy};
}

sub opt_class {
    my ($self) = @_;
    return $self->{opt_class} if ($self->{opt_class});
    $self->{opt_class} = (($self->b1() & 96) >> 5);
    return $self->{opt_class};
}

sub number {
    my ($self) = @_;
    return $self->{number} if ($self->{number});
    $self->{number} = ($self->b1() & 31);
    return $self->{number};
}

sub b1 {
    my ($self) = @_;
    return $self->{b1};
}

sub len {
    my ($self) = @_;
    return $self->{len};
}

sub body {
    my ($self) = @_;
    return $self->{body};
}

1;