So I’ve spent about 8 hours or so whipping this bad boy up. It’s actually fairly functional, but it only parses through the PCAP header and PACKET header at this point (as in the PCAP packet header, not the IP packet header)
Link to files (comes with test script and pcap): pcap_parser_0.01b.zip
As I mentioned in my last programming post, I’m really fed up with how inflexible the pure-python pcap libraries are when it comes to deciding exactly what part of a packet gets parsed. So…
#! /usr/local/bin/python3 import pcap p = pcap.Pcap_file("test.pcap") pkt = p.next_packet() while pkt: print(pkt) pkt = p.next_packet()
This bad boy does alot. With the default settings, we get…
PACKET( ts_sec=1374367283, ts_usec=, incl_len=66, orig_len=, endian=<,) PACKET( ts_sec=1374367283, ts_usec=, incl_len=125, orig_len=, endian=<,) PACKET( ts_sec=1374367283, ts_usec=, incl_len=66, orig_len=, endian=<,) PACKET( ts_sec=1374367283, ts_usec=, incl_len=491, orig_len=, endian=<,) PACKET( ts_sec=1374367283, ts_usec=, incl_len=66, orig_len=, endian=<,) PACKET( ts_sec=1374367283, ts_usec=, incl_len=342, orig_len=, endian=<,)
but if we add a few lines…
#! /usr/local/bin/python3 import pcap import packet pConfig = packet.PARSE_CONFIG(ts_sec=True, ts_usec=True, incl_len=True, orig_len=True) upConfig = packet.UNPACK_CONFIG(ts_sec=True, ts_usec=True, incl_len=True, orig_len=True) p = pcap.Pcap_file("test.pcap") pkt = p.next_pack(pConfig=pConfig, upConfig=upConfig) while pkt: print(pkt) pkt = p.next_pack(pConfig=pConfig, upConfig=upConfig)
we get…
PACKET( ts_sec=1374367283, ts_usec=850337, incl_len=125, orig_len=125, endian=<,) PACKET( ts_sec=1374367283, ts_usec=850478, incl_len=66, orig_len=66, endian=<,) PACKET( ts_sec=1374367283, ts_usec=850810, incl_len=491, orig_len=491, endian=<,) PACKET( ts_sec=1374367283, ts_usec=850857, incl_len=66, orig_len=66, endian=<,) PACKET( ts_sec=1374367283, ts_usec=960149, incl_len=342, orig_len=342, endian=<,)
That doesn’t look like a huge difference, but the magic is really going on behind the scenes. The difference between this and something like Scappy and DPKT is that if you don’t set values to True in the config classes, it doesn’t even read those bytes. It just moves the fuck on.
If you set them to parse but not to unpack, then they’ll stay as binary. You don’t always need to unpack, so it’s a waste of resources.
I’ll probably switch from a config class to some kind of Bitwise operations to handle configurations. So you’ll pass configuration parameters like…
pktCfg = TS_SEC | INCL_LEN | TS_SEC_UPK | INCL_LEN_UPK # 1 | 4 | 32 | 128 pkt = p.next_packet(cfg=pktCfg)
Each parser would need a default parse value, which would likely be a minimalistic approach at reaching the next header (for example, IP header would only unpack header length and next protocol value by default). Furthermore this lets a developer have control of what is parsed with flexibility, as he can simply OR/AND/XOR his default config with a new value on the fly prior to calling the parsing function.
For now…