Class: PacketGen::Header::Base Abstract

Inherits:
Types::Fields show all
Defined in:
lib/packetgen/header/base.rb

Overview

This class is abstract.

Base class for all header types. Subclasses may define magic methods:

Defined Under Namespace

Classes: Binding, Bindings, ProcBinding

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Types::Fields

#[], #[]=, #body=, define_bit_fields_on, define_field, define_field_after, define_field_before, delete_field, #fields, #force_binary, #initialize, #inspect, #is_optional?, #is_present?, #optional_fields, #read, #sz, #to_h, #to_s

Constructor Details

This class inherits a constructor from PacketGen::Types::Fields

Instance Attribute Details

#packetObject

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.

Reference on packet which owns this header



132
133
134
# File 'lib/packetgen/header/base.rb', line 132

def packet
  @packet
end

Class Method Details

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

This method returns an undefined value.

Bind a upper header to current class

Header1.bind_header Header2, field1: 43
Header1.bind_header Header3, field1: 43, field2: 43
Header1.bind_header Header4, op: :and, field1: 43, field2: 43
Header1.bind_header Header5, field1: ->(v) { v.nil? ? 128 : v > 127 }
Header1.bind_header Header6, proc: ->(pkt) { pkt.header1.field1 == 1 && pkt.header1.body[0..1] == "\x00\x00" }

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. Given value may be a lambda, whose alone argument is the value extracted from header field (or nil when lambda is used to set field while adding a header).

    If multiple fields are given, a special key :op may be given to set parse operation on this binding. By default, :op is :or (at least one binding must match to parse it). It also may be set to :and (all bindings must match to parse it).



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/packetgen/header/base.rb', line 159

def self.bind_header(header_klass, args={})
  op = args.delete(:op) || :or
  if @known_headers[header_klass].nil? || @known_headers[header_klass].op != op
    bindings = Bindings.new(op)
    @known_headers[header_klass] = bindings
  else
    bindings = @known_headers[header_klass]
  end
  args.each do |key, value|
    if key == :procs
      bindings << ProcBinding.new(value)
    else
      bindings << Binding.new(key, value)
    end
  end
end

.inherited(klass) ⇒ void

This method returns an undefined value.

On inheritage, create @known_headers class variable

Parameters:

  • klass (Class)


137
138
139
140
# File 'lib/packetgen/header/base.rb', line 137

def self.inherited(klass)
  super
  klass.class_eval { @known_headers = {} }
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: hashes



186
187
188
# File 'lib/packetgen/header/base.rb', line 186

def self.known_headers
  @known_headers
end

.protocol_nameString

Give protocol name for this class

Returns:

  • (String)

Since:

  • 2.0.0



179
180
181
# File 'lib/packetgen/header/base.rb', line 179

def self.protocol_name
  self.new.protocol_name
end

Instance Method Details

#header_id(header) ⇒ Integer

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 header id in packet headers array

Parameters:

Returns:

  • (Integer)

Raises:

  • FormatError header not in a packet



225
226
227
228
229
230
231
232
# File 'lib/packetgen/header/base.rb', line 225

def header_id(header)
  raise FormatError, "header of type #{header.class} not in a packet" if packet.nil?
  id = packet.headers.index(header)
  if id.nil?
    raise FormatError, "header of type #{header.class} not in packet #{packet}"
  end
  id
end

#ip_header(header) ⇒ Header

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 IP or IPv6 previous header from header

Parameters:

Returns:

Raises:

  • FormatError no IP or IPv6 header previous header in packet

  • FormatError header not in a packet



240
241
242
243
244
245
# File 'lib/packetgen/header/base.rb', line 240

def ip_header(header)
  hid = header_id(header)
  iph = packet.headers[0...hid].reverse.find { |h| h.is_a? IP or h.is_a? IPv6 }
  raise FormatError, 'no IP or IPv6 header in packet' if iph.nil?
  iph
end

#method_nameString

return header method name

Returns:

  • (String)

Since:

  • 2.0.0



206
207
208
209
210
# File 'lib/packetgen/header/base.rb', line 206

def method_name
  return @method_name if @method_name

  @method_name = protocol_name.downcase.sub(/::/, '_')
end

#parse?Boolean

This method is abstract.

Should be redefined by subclasses. This method should check invariant fields from header.

Call by Packet#parse when guessing first header to check if header is correct

Returns:

  • (Boolean)


216
217
218
# File 'lib/packetgen/header/base.rb', line 216

def parse?
  true
end

#protocol_nameString

Return header protocol name

Returns:

  • (String)


192
193
194
195
196
197
198
199
200
201
# File 'lib/packetgen/header/base.rb', line 192

def protocol_name
  return @protocol_name if @protocol_name

  classname = self.class.to_s
  @protocol_name = if classname.start_with?('PacketGen::Header')
                     classname.sub(/.*Header::/, '')
                   else
                     classname.sub(/.*::/, '')
                   end
end