Ethernet frame (layer 2, IEEE 802.3): Ruby parsing library

Ethernet frame is a OSI data link layer (layer 2) protocol data unit for Ethernet networks. In practice, many other networks and/or in-file dumps adopted the same format for encapsulation purposes.

KS implementation details

License: CC0-1.0
Minimal Kaitai Struct required: 0.8

References

This page hosts a formal specification of Ethernet frame (layer 2, IEEE 802.3) using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Usage

Parse a local file and get structure in memory:

data = EthernetFrame.from_file("path/to/local/file.Ethernet frame (layer 2, IEEE 802.3)")

Or parse structure from a string of bytes:

bytes = "\x00\x01\x02..."
data = EthernetFrame.new(Kaitai::Struct::Stream.new(bytes))

After that, one can get various attributes from the structure by invoking getter methods like:

data.dst_mac # => Destination MAC address.

Ruby source code to parse Ethernet frame (layer 2, IEEE 802.3)

ethernet_frame.rb

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

require 'kaitai/struct/struct'

unless Gem::Version.new(Kaitai::Struct::VERSION) >= Gem::Version.new('0.7')
  raise "Incompatible Kaitai Struct Ruby API: 0.7 or later is required, but you have #{Kaitai::Struct::VERSION}"
end


##
# Ethernet frame is a OSI data link layer (layer 2) protocol data unit
# for Ethernet networks. In practice, many other networks and/or
# in-file dumps adopted the same format for encapsulation purposes.
# @see https://ieeexplore.ieee.org/document/7428776 Source
class EthernetFrame < Kaitai::Struct::Struct

  ETHER_TYPE_ENUM = {
    2048 => :ether_type_enum_ipv4,
    2049 => :ether_type_enum_x_75_internet,
    2050 => :ether_type_enum_nbs_internet,
    2051 => :ether_type_enum_ecma_internet,
    2052 => :ether_type_enum_chaosnet,
    2053 => :ether_type_enum_x_25_level_3,
    2054 => :ether_type_enum_arp,
    34525 => :ether_type_enum_ipv6,
  }
  I__ETHER_TYPE_ENUM = ETHER_TYPE_ENUM.invert
  def initialize(_io, _parent = nil, _root = self)
    super(_io, _parent, _root)
    _read
  end

  def _read
    @dst_mac = @_io.read_bytes(6)
    @src_mac = @_io.read_bytes(6)
    @ether_type = Kaitai::Struct::Stream::resolve_enum(ETHER_TYPE_ENUM, @_io.read_u2be)
    case ether_type
    when :ether_type_enum_ipv4
      @_raw_body = @_io.read_bytes_full
      io = Kaitai::Struct::Stream.new(@_raw_body)
      @body = Ipv4Packet.new(io)
    when :ether_type_enum_ipv6
      @_raw_body = @_io.read_bytes_full
      io = Kaitai::Struct::Stream.new(@_raw_body)
      @body = Ipv6Packet.new(io)
    else
      @body = @_io.read_bytes_full
    end
    self
  end

  ##
  # Destination MAC address.
  attr_reader :dst_mac

  ##
  # Source MAC address.
  attr_reader :src_mac
  attr_reader :ether_type
  attr_reader :body
  attr_reader :_raw_body
end