Module: PacketGen::Header::HeaderClassMethods

Included in:
ARP, Eth, ICMP, IP, IPv6, TCP, UDP
Defined in:
lib/packetgen/header/header_class_methods.rb

Defined Under Namespace

Classes: Binding

Instance Method Summary collapse

Instance Method Details

#bind_header(header_klass, args = {}) ⇒ void

This method returns an undefined value.

Bind a upper header to current class

Parameters:

  • header_klass (Class)

    header class to bind to current class

  • args (Hash) (defaults to: {})

    current class field and its value when header_klass is embedded in current class



19
20
21
22
23
# File 'lib/packetgen/header/header_class_methods.rb', line 19

def bind_header(header_klass, args={})
  @known_headers ||= {}
  key = args.keys.first
  @known_headers[header_klass] = Binding.new(key, args[key])
end

#define_bit_fields_on(attr, *args) ⇒ void

This method returns an undefined value.

Define a bitfield on given attribute

class MyHeader < Struct.new(:flags)

  def initialize(options={})
    super Int16.new(options[:flags])
  end

  # define a bit field on :flag attribute:
  # flag1, flag2 and flag3 are 1-bit fields
  # type and stype are 3-bit fields. reserved is a 6-bit field
  define_bit_fields_on :flags, :flag1, :flag2, :flag3, :type, 3, :stype, 3, :reserved: 6
end

A bitfield of size 1 bit defines 2 methods:

  • #field? which returns a Boolean,

  • #field= which takes and returns a Boolean.

A bitfield of more bits defines 2 methods:

  • #field which returns an Integer,

  • #field= which takes and returns an Integer.

Parameters:

  • attr (Symbol)

    attribute name (attribute should a StructFu::Int subclass)

  • args (Array)

    list of bitfield names. Name may be followed by bitfield size. If no size is given, 1 bit is assumed.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/packetgen/header/header_class_methods.rb', line 54

def define_bit_fields_on(attr, *args)
  total_size = self.new[attr].width * 8
  idx = total_size - 1

  field = args.shift
  while field
    next unless field.is_a? Symbol
    size = if args.first.is_a? Integer
             args.shift
           else
             1
           end
    unless field == :_
      shift = idx - (size - 1)
      field_mask = (2**size - 1) << shift
      clear_mask = (2**total_size - 1) & (~field_mask & (2**total_size - 1))

      if size == 1
        class_eval <<-EOM
        def #{field}?
          val = (self[:#{attr}].to_i & #{field_mask}) >> #{shift}
          val != 0
        end
        def #{field}=(v)
          val = v ? 1 : 0
          self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
          self[:#{attr}].value |= val << #{shift}
        end
        EOM
      else
        class_eval <<-EOM
        def #{field}
          (self[:#{attr}].to_i & #{field_mask}) >> #{shift}
        end
        def #{field}=(v)
          self[:#{attr}].value = self[:#{attr}].to_i & #{clear_mask}
          self[:#{attr}].value |= (v & #{2**size - 1}) << #{shift}
        end
        EOM
      end
    end

    idx -= size
    field = args.shift
  end
end

#known_headersHash

Get knwon headers

Returns:

  • (Hash)

    keys: header classes, values: struct with methods #key and #value



27
28
29
# File 'lib/packetgen/header/header_class_methods.rb', line 27

def known_headers
  @known_headers ||= {}
end