=================================================================================================
analyse_syn_packets.py
=================================================================================================
import numpy,sys
from subprocess import Popen, PIPE

"""
Script to calculate how often a ip or tcp field changes in a pcap file for a specified destination
ip address and port.

Usage: python analyse_syn_packets.py <pcap file> <dst ip address> <port> <tshark field>

Examples tshark field: ip.id, tcp.seq, tcp.srcport

"""

def CheckValues(values):
	""" Checks whether we can find how often values change
	    values: list of values to check
	    returns: period (in packets) if found, otherwise None
	"""
	
	# we collect in list l the indices (into the values list) when a value differs from its precessor
	l = [0]
	oldval = values[0]
	for i in range(1,len(values)):
		if values[i] != oldval:
			l.append(i)
			oldval = values[i]

	# numpy.ediff1d gives us for a given list the differences between each two succesive values	
	intervals = numpy.ediff1d(l)

	# calculate mean and standard deviation
	mean = numpy.mean(intervals)
	std = numpy.std(intervals)

	# If standard deviation is small, this means that values are changes periodically
	if std <= 0.001:
		return int(round(mean))
	else:
		return None

def CheckTimestamps(timestamps, values):
	""" Checks whether we can find how often values change.
	    timestamps: list of timestamps
	    values: list of values
	    returns: period (in seconds) if found, otherwise None
	"""
	# We collect a timestamp in tsList each time the next value differs from the previous one
	tsList = [timestamps[0]]
	oldvalue = values[0]
	for i in range(1,len(values)):
		if values[i] != oldvalue:
			tsList.append(timestamps[i])
			oldvalue = values[i]

	# numpy.ediff1d gives us for a given list the differences between each two succesive values
	intervals = numpy.ediff1d(tsList)

	# calculate mean and standard deviation
	mean = numpy.mean(intervals)
	std = numpy.std(intervals)

	# If standard deviation is below 1, this means that values are changes periodically
	if std <= 1:
		return int(round(mean))
	else:
		return None

# main

# Get commandline arguments
if len(sys.argv) != 5:
	print "Usage: python %s <pcap file> <ip address> <port> <tshark field>" % sys.argv[0]
	sys.exit()

pcapfile = sys.argv[1]
ipaddress = sys.argv[2]
port = sys.argv[3]
field = sys.argv[4]

# Execute tshark command
"""
Note: we have to instruct tshark to print the actual ISN's instead of relative, which seems the default by installation; hence, the '-o tcp.relative_sequence_numbers:FALSE' directive on the commandline
"""
tshark_output = Popen("tshark -r %s -R 'tcp and ip.dst == %s and tcp.port==%s and tcp.flags == 2' -T fields -e frame.time_relative -e %s -o tcp.relative_sequence_numbers:FALSE" % (pcapfile, ipaddress, port, field), shell=True, stdout=PIPE).communicate()[0]

lines=tshark_output.splitlines()
print "Found %d packet(s) that match the supplied parameters" % len(lines)

if len(lines) <= 1:
	print "Nothing to calculate. There are only %d packet(s) that match" % len(lines)
	sys.exit(0)

timestamps=[]
values=[]
for line in lines:
	try:
		ts, val = line.split()
		timestamps.append(float(ts))
		if val.startswith('0x'):
			base=16
		else:
			base=10
		values.append(int(val, base))
	except ValueError:
		print "Unable to parse output from tshark. Please check your parameters"

x=CheckValues(values)
if x != None:
	print "%s changes every" % field, x , "packet(s)."
y=CheckTimestamps(timestamps, values)
if y != None:
	print "%s changes every" % field, y, "second(s)."


