| Class | PacketFu::Packet |
| In: |
lib/packetfu/packet.rb
|
| Parent: | Object |
| flavor | [R] | |
| headers | [RW] |
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.
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.
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.
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.
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.
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"]
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.
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!
Put the entire packet on the wire by creating a temporary PacketFu::Inject object. TODO: Do something with auto-checksumming?