Question

I'm parsing a PCAP file and I need to extract TCP flags (SYN, ACK, PSH, URG, ...). I'm using the packet['TCP'].flags value to obtain all the flags at once.

pkts = PcapReader(infile)
for p in pkts:
        F = bin(p['TCP'].flags)
        print F, bin(F), p.summary()
        # manual flags extraction from F

Is there a way to obtain a single TCP flag without manually extract it from packet['TCP'].flags value?

Was it helpful?

Solution

Normally, the usual way to handle FLAGS is with a bitmap and bitwise operators. If your Packet class doesn't have specific method to test for flags, the best thing you can do IMHO is to:

FIN = 0x01
SYN = 0x02
RST = 0x04
PSH = 0x08
ACK = 0x10
URG = 0x20
ECE = 0x40
CWR = 0x80

And test them like this:

F = p['TCP'].flags    # this should give you an integer
if F & FIN:
    # FIN flag activated
if F & SYN:
    # SYN flag activated
# rest of the flags here

Sadly, python doesn't have a switch statement to make this more elegant but it doesn't really matter much.

Hope this helps!

OTHER TIPS

You can use the Packet.sprintf() method:

>>> p = IP()/TCP(flags=18)
>>> p.sprintf('%TCP.flags%')
'SA'

If you want the "long" names, use a dict instead of a long if...elif... expression (dict are often used in Python when you would use a switch in other languages):

>>> flags = {
    'F': 'FIN',
    'S': 'SYN',
    'R': 'RST',
    'P': 'PSH',
    'A': 'ACK',
    'U': 'URG',
    'E': 'ECE',
    'C': 'CWR',
}
>>> [flags[x] for x in p.sprintf('%TCP.flags%')]
['SYN', 'ACK']

This also works.

if packet[TCP].flags.F:
    print('FIN received')

Another option, for the record, which did not exist by the time this question was asked. It works with current Scapy development version (the first release including this change will be 2.4.0; 2.4.0rc* also include it).

You can now use str() on the flag value:

>>> p = IP()/TCP(flags=18)
>>> p[TCP].flags
<Flag 18 (SA)>
>>> str(p[TCP].flags)
'SA'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top