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?
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!
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']
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'
This also works.
if packet[TCP].flags.F:
print('FIN received')