1

I used the dpkt python package to parse a pcap file, and did the following to get the tcp packets:

f = open(fname)
pcap = dpkt.pcap.Reader(f)
tcps = []
for ts, buff in pcap_in:
    eth = dpkt.ethernet.Ethernet(buff)
    ip = eth.data
    tcp = ip.data

Now I want to see which ones had both SYN and ACK flags. I tried to put those with both of those flags in a list as follows:

syn_plus_ack = []
for tcp in tcps:
    if ((tcp.flags & dpkt.tcp.TH_SYN) and (tcp.flags & dpkt.tcp.TH_ACK)):
        syn_plus_ack.append(tcp)

I am not sure if this is doing what I want it to do, because I tried it on a sample pcap file and there were so many packets with a high number of SYNs but no ACK+SYNs.

I noticed the value of tcp.flags in those in syn_plus_ack is 18, dpkt.tcp.TH_SYN is 2, and dpkt.tcp.TH_ACK is 16. Is the tcp.flags value the sum of the value of all flags in the packet? Is there something I am doing wrong?

nara
  • 176
  • 1
  • 7
  • Yes. Its `16|2`, which is `18`. Can you share the pcap file that you are using? Or can you post the results for the pcap at https://github.com/kbandla/dpkt/blob/master/examples/data/http.pcap?raw=true – Kiran Bandla Mar 01 '18 at 01:24
  • @KiranBandla Sorry, I can't share the pcap file, but your answer did solve my question. Thanks! – nara Mar 01 '18 at 03:04

1 Answers1

4

This is probably happening because you assume that all the packets in the pcap are TCP. You need to make sure that a packet is infact TCP before you parse its headers for flags. This can be done by checking for the p field in the ip header to be 6 (dpkt.ip.IP_PROTO_TCP):

import dpkt

def parse_pcap(filepath):
    f = open(filepath)
    pcap = dpkt.pcap.Reader(f)
    for num, (ts, buff) in  enumerate(pcap):
        eth = dpkt.ethernet.Ethernet(buff)
        if eth.type != dpkt.ethernet.ETH_TYPE_IP:
            # We are only interested in IP packets
            continue
        ip = eth.data
        if ip.p != dpkt.ip.IP_PROTO_TCP:
            # We are only interested in TCP
            continue
        tcp = ip.data
        if ((tcp.flags & dpkt.tcp.TH_SYN) and (tcp.flags & dpkt.tcp.TH_ACK)):
            # TCP SYN and ACK
            print('Found TCP SYN & ACK in Packet #%d'%num)
        print('Packet #{1:d} : {0:b} = 0x{0:x}'.format(tcp.flags, num))

I just tried this on the http.pcap file available here and here is the result:

Packet #0 : 10 = 0x2
Found TCP SYN & ACK in Packet #1
Packet #1 : 10010 = 0x12
Packet #2 : 10000 = 0x10
Packet #3 : 11000 = 0x18
Kiran Bandla
  • 686
  • 4
  • 10