Class PacketFu::Packet
In: lib/packetfu/packet.rb
Parent: Object

Packet is the parent class of EthPacket, IPPacket, UDPPacket, TCPPacket, and all other packets.

Methods

has_data?   hexify   inspect   inspect_hex   is_arp?   is_eth?   is_ethernet?   is_icmp?   is_invalid?   is_ip?   is_ipv6?   is_ipv6?   is_tcp?   is_udp?   length   method_missing   new   parse   payload   payload=   peek   proto   protocol   read   recalc   size   to_f   to_pcap   to_s   to_w   write  

Attributes

flavor  [R] 
headers  [RW] 

Public Class methods

Parse() creates the correct packet type based on the data, and returns the apporpiate Packet subclass.

There is an assumption here that all incoming packets are either EthPacket or InvalidPacket types.

New packet types should get an entry here.

Public Instance methods

Returns true if the outermost layer has data. Else, false.

Hexify provides a neatly-formatted dump of binary data, familar to hex readers.

For packets, inspect is overloaded as inspect_hex(0). Not sure if this is a great idea yet, but it sure makes the irb output more sane.

If you hate this, you can run PacketFu.toggle_inspect to return to the typical (and often unreadable) Object#inspect format.

Returns a hex-formatted representation of the packet.

Arguments

0..9 : If a number is given only the layer in @header[arg] will be displayed. Note that this will include all @headers included in that header. :layers : If :layers is specified, the dump will return an array of headers by layer level. :all : An alias for arg=0.

Examples

  irb(main):003:0> pkt = TCPPacket.new
  irb(main):003:0> puts pkt.inspect_hex(:layers)
  00 1a c5 00 00 00 00 1a c5 00 00 00 08 00 45 00   ..............E.
  00 28 83 ce 00 00 ff 06 38 02 00 00 00 00 00 00   .(......8.......
  00 00 a6 0f 00 00 ac 89 7b 26 00 00 00 00 50 00   ........{&....P.
  40 00 a2 25 00 00                                 @..%..
  45 00 00 28 83 ce 00 00 ff 06 38 02 00 00 00 00   E..(......8.....
  00 00 00 00 a6 0f 00 00 ac 89 7b 26 00 00 00 00   ..........{&....
  50 00 40 00 a2 25 00 00                           P.@..%..
  a6 0f 00 00 ac 89 7b 26 00 00 00 00 50 00 40 00   ......{&....P.@.
  a2 25 00 00                                       .%..
  => nil
  irb(main):004:0> puts pkt.inspect_hex(:layers)[2]
  a6 0f 00 00 ac 89 7b 26 00 00 00 00 50 00 40 00   ......{&....P.@.
  a2 25 00 00                                       .%..
  => nil

TODO: Colorize this! Everyone loves colorized irb output.

Returns true if this is an ARP packet. Else, false.

is_eth?()

Alias for is_ethernet?

Returns true if this is an Ethernet packet. Else, false.

Returns true if this is an ICMP packet. Else, false.

Returns true if this is an Invalid packet. Else, false.

Returns true if this is an IP packet. Else, false.

Returns true if this is an IPv6 packet. Else, false.

Returns true if this is an IPv6 packet. Else, false.

Returns true if this is an TCP packet. Else, false.

Returns true if this is an UDP packet. Else, false.

length()

Alias for size

method_missing() delegates protocol-specific field actions to the apporpraite class variable (which contains the associated packet type) This register-of-protocols style switch will work for the forseeable future (there aren‘t /that/ many packet types), and it‘s a handy way to know at a glance what packet types are supported.

Get the outermost payload (body) of the packet; this is why all packet headers should have a body type.

Set the outermost payload (body) of the packet.

Peek provides summary data on packet contents. Each packet type should provide its own peek method, and shouldn‘t exceed 80 characters wide (for easy reading in normal irb shells). If they don‘t, this default summary will step in.

Returns an array of protocols contained in this packet. For example:

  t = PacketFu::TCPPacket.new
  => 00 1a c5 00 00 00 00 1a c5 00 00 00 08 00 45 00   ..............E.
  00 28 3c ab 00 00 ff 06 7f 25 00 00 00 00 00 00   .(<......%......
  00 00 93 5e 00 00 ad 4f e4 a4 00 00 00 00 50 00   ...^...O......P.
  40 00 4a 92 00 00                                 @.J...
  t.proto
  => ["Eth", "IP", "TCP"]
protocol()

Alias for proto

Read() takes (and trusts) the io input and shoves it all into a well-formed Packet. Note that read is a destructive process, so any existing data will be lost.

TODO: This giant if tree is a mess, and worse, is decieving. You need to define actions both here and in parse(). All read() does is make a (good) guess as to what @headers to expect, and reads data to them.

To take strings and turn them into packets without knowing ahead of time what kind of packet it is, use Packet.parse instead; parse() handles the figuring-out part.

A note on the :strip => true argument: If :strip is set, defined lengths of data will be believed, and any trailers (such as frame check sequences) will be chopped off. This helps to ensure well-formed packets, at the cost of losing perhaps important FCS data.

If :strip is false, header lengths are /not/ believed, and all data will be piped in. When capturing from the wire, this is usually fine, but recalculating the length before saving or re-transmitting will absolutely change the data payload; FCS data will become part of the TCP data as far as tcp_len is concerned. Some effort has been made to preserve the "real" payload for the purposes of checksums, but currently, it‘s impossible to seperate new payload data from old trailers, so things like pkt.payload += "some data" will not work correctly.

So, to summarize; if you intend to alter the data, use :strip. If you don‘t, don‘t. Also, this is a horrid XXX hack. Stripping is useful (and fun!), but the default behavior really should be to create payloads correctly, and /not/ treat extra FCS data as a payload.

Update: This scheme is so lame. Need to fix. Seriously. Update: still sucks. Really.

Recalculates all the calcuated fields for all headers in the packet. This is important since read() wipes out all the calculated fields such as length and checksum and what all.

Returns the size of the packet (as a binary string)

Put the entire packet into a libpcap file. XXX: this is a hack for now just to confirm that packets are getting created correctly. Now with append! XXX: Document this!

Converts a packet to libpcap format. Bit of a hack?

Get the binary string of the entire packet.

Put the entire packet on the wire by creating a temporary PacketFu::Inject object. TODO: Do something with auto-checksumming?

In the event of no proper decoding, at least send it to the inner-most header.

[Validate]