Class: PacketGen::Header::Base Abstract
- Inherits:
-
Types::Fields
- Object
- Types::Fields
- PacketGen::Header::Base
- Defined in:
- lib/packetgen/header/base.rb
Overview
Base class for all header types. Subclasses may define magic methods:
-
#calc_checksum, which computes header checksum, -
#calc_length, which computes header length, -
#parse?, -
#reply!, which inverts needed fields to forge a response.
Direct Known Subclasses
ARP, BOOTP, DHCP, DHCPv6, DHCPv6::Relay, DNS, DNS::Question, Dot11, Dot11::SubMngt, Dot1q, Dot1x, EAP, ESP, Eth, GRE, HTTP::Request, HTTP::Response, ICMP, IGMP, IGMPv3::MQ, IGMPv3::MR, IKE, IKE::Payload, IP, IPv6, IPv6::Extension, LLC, MLD, MLDv2::MLR, NetBIOS::Datagram, NetBIOS::Session, NonESPMarker, OSPFv2, OSPFv2::DbDescription, OSPFv2::Hello, OSPFv2::LSAck, OSPFv2::LSRequest, OSPFv2::LSUpdate, OSPFv3, OSPFv3::DbDescription, OSPFv3::Hello, OSPFv3::LSAck, OSPFv3::LSRequest, OSPFv3::LSUpdate, PPI, RadioTap, SNAP, TCP, TCP::Option, TFTP, UDP
Defined Under Namespace
Classes: Binding, Bindings, ProcBinding
Instance Attribute Summary collapse
-
#packet ⇒ Packet?
Reference on packet which owns this header.
Class Method Summary collapse
-
.bind(header_klass, args = {}) ⇒ void
Bind a upper header to current one.
-
.bind_header(header_klass, args = {}) ⇒ void
deprecated
Deprecated.
Use Base.bind instead.
-
.calculate_and_set_length(hdr, header_in_size: true) ⇒ Object
Helper method to calculate length of
hdrand set itslengthfield. -
.inherited(klass) ⇒ void
On inheritage, create @known_header class variable.
-
.known_headers ⇒ Hash
private
Get known headers.
-
.protocol_name ⇒ String
Give protocol name for this class.
Instance Method Summary collapse
- #added_to_packet(packet) ⇒ void abstract
-
#header_id(header) ⇒ Integer
private
Get
headerid in packet headers array. -
#initialize(options = {}) ⇒ Base
constructor
A new instance of Base.
-
#ip_header(header) ⇒ Header
private
Get IP or IPv6 previous header from
header. -
#ll_header(header) ⇒ Header
private
Get link layer header from given header.
-
#method_name ⇒ String
return header method name.
-
#parse? ⇒ Boolean
abstract
Call by Packet#parse when guessing first header to check if header is correct.
-
#protocol_name ⇒ String
Return header protocol name.
Methods inherited from Types::Fields
#[], #[]=, #bits_on, #body=, define_bit_fields_on, define_field, define_field_after, define_field_before, delete_field, fields, #fields, #force_binary, #inspect, #is_optional?, #is_present?, #offset_of, #optional?, #optional_fields, #present?, #read, remove_bit_fields_on, remove_field, #sz, #to_h, #to_s, update_field
Constructor Details
#initialize(options = {}) ⇒ Base
Returns a new instance of Base.
288 289 290 291 |
# File 'lib/packetgen/header/base.rb', line 288 def initialize(={}) @packet = .delete(:packet) if .key?(:packet) super end |
Instance Attribute Details
#packet ⇒ Packet?
Reference on packet which owns this header
162 163 164 |
# File 'lib/packetgen/header/base.rb', line 162 def packet @packet end |
Class Method Details
.bind(header_klass, args = {}) ⇒ void
This method returns an undefined value.
Bind a upper header to current one.
# Bind Header2 to Header1 when field1 from Header1 has a value of 42
Header1.bind Header2, field1: 42
# Bind Header3 to Header1 when field1 from Header1 has a value of 43
# and field2 has value 43 or 44
Header1.bind Header3, field1: 43, field2: 43
Header1.bind Header3, field1: 43, field2: 44
# Bind Header4 to Header1 when field1 from Header1 has a value
# greater or equal to 44. When adding a Header2 to a Header1
# with Packet#add, force value to 44.
Header1.bind Header4, field1: ->(v) { v.nil? ? 44 : v >= 44 }
# Bind Header5 to Header1 when field1 from Header1 has a value of 41
# and first two bytes of header1's body are null.
# When adding a Header2 to a Header1 with Packet#add, force value to 44.
Header1.bind Header5, procs: [->(hdr) { hdr.field1 = 41 }
->(hdr) { hdr.field1 == 41 && hdr.body[0..1] == "\x00\x00" }]
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/packetgen/header/base.rb', line 242 def self.bind(header_klass, args={}) if @known_headers[header_klass].nil? bindings = Bindings.new(:newstyle) @known_headers[header_klass] = bindings else bindings = @known_headers[header_klass] end bindings.new_set args.each do |key, value| bindings << if key == :procs ProcBinding.new(value) else Binding.new(key, value) end end end |
.bind_header(header_klass, args = {}) ⇒ void
Use bind instead.
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, procs: [->(hdr) { hdr.field1 = 1 }
->(hdr) { hdr.field1 == 1 && hdr.body[0..1] == "\x00\x00" }]
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/packetgen/header/base.rb', line 195 def self.bind_header(header_klass, args={}) Deprecation.deprecated(self, __method__, 'bind', klass_method: true) 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| bindings << if key == :procs ProcBinding.new(value) else Binding.new(key, value) end end end |
.calculate_and_set_length(hdr, header_in_size: true) ⇒ Object
Helper method to calculate length of hdr and set its length field. To be used by #calc_length in Base subclasses.
271 272 273 274 275 276 277 278 |
# File 'lib/packetgen/header/base.rb', line 271 def self.calculate_and_set_length(hdr, header_in_size: true) length = if header_in_size hdr.sz else hdr.body.sz end hdr.length = length end |
.inherited(klass) ⇒ void
This method returns an undefined value.
On inheritage, create @known_header class variable
167 168 169 170 |
# File 'lib/packetgen/header/base.rb', line 167 def self.inherited(klass) super klass.class_eval { @known_headers = {} } end |
.known_headers ⇒ Hash
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 known headers
283 284 285 |
# File 'lib/packetgen/header/base.rb', line 283 def self.known_headers @known_headers end |
.protocol_name ⇒ String
Give protocol name for this class
262 263 264 |
# File 'lib/packetgen/header/base.rb', line 262 def self.protocol_name new.protocol_name end |
Instance Method Details
#added_to_packet(packet) ⇒ void
This method is called when a header is added to a packet. This base method does nothing but may be overriden by subclasses.
This method returns an undefined value.
340 |
# File 'lib/packetgen/header/base.rb', line 340 def added_to_packet(packet) end |
#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
347 348 349 350 351 352 353 354 |
# File 'lib/packetgen/header/base.rb', line 347 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
362 363 364 365 366 367 |
# File 'lib/packetgen/header/base.rb', line 362 def ip_header(header) hid = header_id(header) iph = packet.headers[0...hid].reverse.find { |h| h.is_a?(IP) || h.is_a?(IPv6) } raise FormatError, 'no IP or IPv6 header in packet' if iph.nil? iph end |
#ll_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 link layer header from given header
375 376 377 378 379 380 |
# File 'lib/packetgen/header/base.rb', line 375 def ll_header(header) hid = header_id(header) llh = packet.headers[0...hid].reverse.find { |h| h.is_a?(Eth) || h.is_a?(Dot11) } raise FormatError, 'no link layer header in packet' if llh.nil? llh end |
#method_name ⇒ String
return header method name
310 311 312 313 314 |
# File 'lib/packetgen/header/base.rb', line 310 def method_name return @method_name if @method_name @method_name = protocol_name.downcase.gsub(/::/, '_') end |
#parse? ⇒ Boolean
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
320 321 322 |
# File 'lib/packetgen/header/base.rb', line 320 def parse? true end |
#protocol_name ⇒ String
Return header protocol name
295 296 297 298 299 300 301 302 303 304 |
# File 'lib/packetgen/header/base.rb', line 295 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 |