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.
// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT.
import (
"github.com/kaitai-io/kaitai_struct_go_runtime/kaitai"
"bytes"
)
type Ipv4Packet struct {
B1 uint8
B2 uint8
TotalLength uint16
Identification uint16
B67 uint16
Ttl uint8
Protocol uint8
HeaderChecksum uint16
SrcIpAddr []byte
DstIpAddr []byte
Options *Ipv4Packet_Ipv4Options
Body *ProtocolBody
_io *kaitai.Stream
_root *Ipv4Packet
_parent kaitai.Struct
_raw_Options []byte
_raw_Body []byte
_f_ihl bool
ihl int
_f_ihlBytes bool
ihlBytes int
_f_version bool
version int
}
func NewIpv4Packet() *Ipv4Packet {
return &Ipv4Packet{
}
}
func (this Ipv4Packet) IO_() *kaitai.Stream {
return this._io
}
func (this *Ipv4Packet) Read(io *kaitai.Stream, parent kaitai.Struct, root *Ipv4Packet) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp1, err := this._io.ReadU1()
if err != nil {
return err
}
this.B1 = tmp1
tmp2, err := this._io.ReadU1()
if err != nil {
return err
}
this.B2 = tmp2
tmp3, err := this._io.ReadU2be()
if err != nil {
return err
}
this.TotalLength = uint16(tmp3)
tmp4, err := this._io.ReadU2be()
if err != nil {
return err
}
this.Identification = uint16(tmp4)
tmp5, err := this._io.ReadU2be()
if err != nil {
return err
}
this.B67 = uint16(tmp5)
tmp6, err := this._io.ReadU1()
if err != nil {
return err
}
this.Ttl = tmp6
tmp7, err := this._io.ReadU1()
if err != nil {
return err
}
this.Protocol = tmp7
tmp8, err := this._io.ReadU2be()
if err != nil {
return err
}
this.HeaderChecksum = uint16(tmp8)
tmp9, err := this._io.ReadBytes(int(4))
if err != nil {
return err
}
tmp9 = tmp9
this.SrcIpAddr = tmp9
tmp10, err := this._io.ReadBytes(int(4))
if err != nil {
return err
}
tmp10 = tmp10
this.DstIpAddr = tmp10
tmp11, err := this.IhlBytes()
if err != nil {
return err
}
tmp12, err := this._io.ReadBytes(int(tmp11 - 20))
if err != nil {
return err
}
tmp12 = tmp12
this._raw_Options = tmp12
_io__raw_Options := kaitai.NewStream(bytes.NewReader(this._raw_Options))
tmp13 := NewIpv4Packet_Ipv4Options()
err = tmp13.Read(_io__raw_Options, this, this._root)
if err != nil {
return err
}
this.Options = tmp13
tmp14, err := this.IhlBytes()
if err != nil {
return err
}
tmp15, err := this._io.ReadBytes(int(this.TotalLength - tmp14))
if err != nil {
return err
}
tmp15 = tmp15
this._raw_Body = tmp15
_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
tmp16 := NewProtocolBody(this.Protocol)
err = tmp16.Read(_io__raw_Body, nil, nil)
if err != nil {
return err
}
this.Body = tmp16
return err
}
func (this *Ipv4Packet) Ihl() (v int, err error) {
if (this._f_ihl) {
return this.ihl, nil
}
this._f_ihl = true
this.ihl = int(this.B1 & 15)
return this.ihl, nil
}
func (this *Ipv4Packet) IhlBytes() (v int, err error) {
if (this._f_ihlBytes) {
return this.ihlBytes, nil
}
this._f_ihlBytes = true
tmp17, err := this.Ihl()
if err != nil {
return 0, err
}
this.ihlBytes = int(tmp17 * 4)
return this.ihlBytes, nil
}
func (this *Ipv4Packet) Version() (v int, err error) {
if (this._f_version) {
return this.version, nil
}
this._f_version = true
this.version = int((this.B1 & 240) >> 4)
return this.version, nil
}
type Ipv4Packet_Ipv4Option struct {
B1 uint8
Len uint8
Body []byte
_io *kaitai.Stream
_root *Ipv4Packet
_parent *Ipv4Packet_Ipv4Options
_f_copy bool
copy int
_f_number bool
number int
_f_optClass bool
optClass int
}
func NewIpv4Packet_Ipv4Option() *Ipv4Packet_Ipv4Option {
return &Ipv4Packet_Ipv4Option{
}
}
func (this Ipv4Packet_Ipv4Option) IO_() *kaitai.Stream {
return this._io
}
func (this *Ipv4Packet_Ipv4Option) Read(io *kaitai.Stream, parent *Ipv4Packet_Ipv4Options, root *Ipv4Packet) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp18, err := this._io.ReadU1()
if err != nil {
return err
}
this.B1 = tmp18
tmp19, err := this._io.ReadU1()
if err != nil {
return err
}
this.Len = tmp19
var tmp20 int;
if (this.Len > 2) {
tmp20 = this.Len - 2
} else {
tmp20 = 0
}
tmp21, err := this._io.ReadBytes(int(tmp20))
if err != nil {
return err
}
tmp21 = tmp21
this.Body = tmp21
return err
}
func (this *Ipv4Packet_Ipv4Option) Copy() (v int, err error) {
if (this._f_copy) {
return this.copy, nil
}
this._f_copy = true
this.copy = int((this.B1 & 128) >> 7)
return this.copy, nil
}
func (this *Ipv4Packet_Ipv4Option) Number() (v int, err error) {
if (this._f_number) {
return this.number, nil
}
this._f_number = true
this.number = int(this.B1 & 31)
return this.number, nil
}
func (this *Ipv4Packet_Ipv4Option) OptClass() (v int, err error) {
if (this._f_optClass) {
return this.optClass, nil
}
this._f_optClass = true
this.optClass = int((this.B1 & 96) >> 5)
return this.optClass, nil
}
type Ipv4Packet_Ipv4Options struct {
Entries []*Ipv4Packet_Ipv4Option
_io *kaitai.Stream
_root *Ipv4Packet
_parent *Ipv4Packet
}
func NewIpv4Packet_Ipv4Options() *Ipv4Packet_Ipv4Options {
return &Ipv4Packet_Ipv4Options{
}
}
func (this Ipv4Packet_Ipv4Options) IO_() *kaitai.Stream {
return this._io
}
func (this *Ipv4Packet_Ipv4Options) Read(io *kaitai.Stream, parent *Ipv4Packet, root *Ipv4Packet) (err error) {
this._io = io
this._parent = parent
this._root = root
for i := 0;; i++ {
tmp22, err := this._io.EOF()
if err != nil {
return err
}
if tmp22 {
break
}
tmp23 := NewIpv4Packet_Ipv4Option()
err = tmp23.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Entries = append(this.Entries, tmp23)
}
return err
}