Module: PacketGen::Header::HeaderClassMethods

Included in:
ARP, ESP, 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 fields and their value when header_klass is embedded in current class



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

def bind_header(header_klass, args={})
  @known_headers ||= {}
  @known_headers[header_klass] ||= []
  args.each do |key, value|
    @known_headers[header_klass] << Binding.new(key, value)
  end
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.



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
100
101
102
103
# File 'lib/packetgen/header/header_class_methods.rb', line 58

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

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get knwon headers

Returns:

  • (Hash)

    keys: header classes, values: array of Binding



31
32
33
# File 'lib/packetgen/header/header_class_methods.rb', line 31

def known_headers
  @known_headers ||= {}
end