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,
-
#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 @old_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. -
#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
#[], #[]=, #body=, define_bit_fields_on, define_field, define_field_after, define_field_before, delete_field, #fields, #force_binary, #initialize, #inspect, #is_optional?, #is_present?, #offset_of, #optional_fields, #read, #sz, #to_h, #to_s
Constructor Details
This class inherits a constructor from PacketGen::Types::Fields
Instance Attribute Details
#packet ⇒ Packet?
Reference on packet which owns this header
164 165 166 |
# File 'lib/packetgen/header/base.rb', line 164 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" }]
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/packetgen/header/base.rb', line 244 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" }]
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/packetgen/header/base.rb', line 197 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.
273 274 275 276 277 278 279 280 |
# File 'lib/packetgen/header/base.rb', line 273 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 @old_known_header class variable
169 170 171 172 |
# File 'lib/packetgen/header/base.rb', line 169 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
285 286 287 |
# File 'lib/packetgen/header/base.rb', line 285 def self.known_headers @known_headers end |
.protocol_name ⇒ String
Give protocol name for this class
264 265 266 |
# File 'lib/packetgen/header/base.rb', line 264 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.
335 |
# File 'lib/packetgen/header/base.rb', line 335 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
342 343 344 345 346 347 348 349 |
# File 'lib/packetgen/header/base.rb', line 342 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
357 358 359 360 361 362 |
# File 'lib/packetgen/header/base.rb', line 357 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
370 371 372 373 374 375 |
# File 'lib/packetgen/header/base.rb', line 370 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
305 306 307 308 309 |
# File 'lib/packetgen/header/base.rb', line 305 def method_name return @method_name if @method_name @method_name = protocol_name.downcase.sub(/::/, '_') 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
315 316 317 |
# File 'lib/packetgen/header/base.rb', line 315 def parse? true end |
#protocol_name ⇒ String
Return header protocol name
291 292 293 294 295 296 297 298 299 300 |
# File 'lib/packetgen/header/base.rb', line 291 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 |