To parse the frame, I looked at this page .
Now in Perl ...
my $l3protlen = ord substr $raw_bytes, 14, 1;
Extract the 15th byte (character) from $raw_bytes and convert it to its ordinal value (for example, the character "A" will be converted to an integer 65 (0x41), assuming the character set is ASCII). This way Perl can process binary data as if it were a string (for example, passing it to substr ), but then letting you return binary values โโand treat them as numbers. (But remember TMTOWTDI .)
In an IPv4 frame, the first 14 bytes represent the MAC header (6 bytes for the destination and MAC address of the source, followed by a 2-byte Ethertype, which is probably 0x8000 - you could check that). After that, the 15th byte is the beginning of the Ethernet data payload: the first byte contains the version (upper 4 bytes) and the header length in DWORD (below 4 bytes).
Now it seems to me that there is an error in the next line of this sample code, but maybe this works fine with fluke!
my $l3prot = $l3protlen & 0xf0 >> 2;
In Perl >> takes precedence over & , so this would be equivalent
my $l3prot = $l3protlen & (0xf0 >> 2);
or if you prefer
my $l3prot = $l3protlen & 0x3c;
So, this extracts bits 2 - 5 from the value of $l3prot : mask value 0x3c is 0011 1100 in binary format. So, for example, a value of 0x86 (in binary terms, 1000 0110) becomes 0x04 (binary 0000 0100). In fact, the โnormalโ IPv4 value is 0x45, that is, protocol type 4, header length 5 words. The mask, which is with 0x3c and you get ... 4! But only from fluke: you checked the top 2 bits of the length, not the protocol type!
This line should be
my $l3prot = ($l3protlen & 0xf0) >> 4;
(note the brackets for priority and a shift of 4 bits, not 2). (I found the same error in the CPAN documentation, so I assume it is probably pretty widespread.)
return unless $l3prot == 4;
For IPv4, we expect this to be 4 โ if not, jump out of the function right away. (Thus, the incorrect code above gives a result that allows it to be interpreted as an IPv4 packet, but only for good luck.)
my $l4prot = ord substr $packet, 23, 1;
Now extract the 24th byte and convert to an ordinal value in the same way. This is the protocol byte from the IP header:
return unless $l4prot == '7';
We expect this to be 7 - unless it jumps out of the function right away. (According to IANA , 7 is โkernel-based treesโ ... but I think you know which protocols you are interested in!)