/* Program to extract TCP connection-level information */ /* from a TCP/IP packet trace file. */ /* */ /* Usage: gcc -o tcpreader tcpreader.c */ /* ./tcpreader < infile > outfile */ /* */ /* Reads the input trace file with TCP/IP pkt info. */ /* Produces output file summarizing TCP connections. */ /* */ /* Sample code provided by Carey Williamson, Jan 2012 */ #include #include #include /* Manifest constants */ #define MAX_CONNS 1000 #define IP_ADDR_LENGTH 16 #define IP_ACK_SIZE 52 #define FLAG_LENGTH 5 /* Debugging flag */ /* #define DEBUG 1 */ /* A TCP connection is uniquely identified by a 4-tuple: */ /* IPSrcAddr, SrcPort, IPDstAddr, DstPort */ /* In the best of worlds, we always see the SYN (start) and */ /* FIN (end) of each connection, and can count all of the */ /* packets and bytes that occur during the connection. */ /* Can also determine conn duration, from start and end times. */ /* In the real (finite) trace, we might miss the start or end */ /* of some connections, but we can still keep stats on them. */ /* Note that the mapping of "client" and "server" to IP source */ /* and IP destination address is unpredictable, since we don't */ /* always see the first packet of each connection. */ /* Data structure for TCP connection state information */ struct TCP_Conn_Descriptor { char IPSrcAddr[IP_ADDR_LENGTH]; /* IP source address */ char IPDstAddr[IP_ADDR_LENGTH]; /* IP destination address */ int SrcPort; /* Port number used by IP source */ int DstPort; /* Port number used by IP destination */ int SrctoDst_pkts; /* number of IP pkts from S->D */ int DsttoSrc_pkts; /* number of IP pkts from D->S */ }; /* Global data structures and variables */ struct TCP_Conn_Descriptor TCP_Conn_Array[MAX_CONNS]; int total_conns, total_pkts; /* Variables for reading in a line of trace file, which has following form: */ /* time IPsrc IPdst IPsize TCPseq srcPort dstPort TCPack TCPflags */ /* 0.000000 192.168.1.201 -> 192.168.1.200 60 TCP 4297 80 4040844510 : 4040844510 0 win: 5840 S */ float tstamp; char S_Addr[IP_ADDR_LENGTH]; char D_Addr[IP_ADDR_LENGTH]; int S_port, D_port; int ipSize; unsigned long seqNum, ackNum, seqNum2; char flags[FLAG_LENGTH]; /* Forward definitions of procedures and functions */ int find_conn(void); void process_new_packet(void); void Initialize(void); void clear_strings(void); main(void) { FILE *fp; int index; int i; char garbage[10]; /* to read various delimiters as needed */ /* Initialization */ Initialize(); clear_strings(); total_conns = 0; total_pkts = 0; /* main loop: process each line of the input file */ /* time IPsrc -> IPdst IPsize prot srcPort dstPort TCPseq : TCPseq2 TCPack win: winsize TCPflags */ /* 0.000000 192.168.1.201 -> 192.168.1.200 60 TCP 4297 80 4040844510 : 4040844510 0 win: 5840 S */ while(scanf(" %f %s %s %s %d %s %d %d %u %s %u %u %s %s %[SFPAR]", &tstamp, S_Addr, garbage, D_Addr, &ipSize, garbage, &S_port, &D_port, &seqNum, garbage, &seqNum2, &ackNum, garbage, garbage, flags) != EOF) { process_new_packet(); } /*end while loop*/ /* now print the results summary */ printf("Total Packets Seen: %d\n", total_pkts); printf("Total Connections Seen: %d\n", total_conns); /* now print the results for each connection in the table */ printf("Conn IPsrc port IPdst port sentpkts recdpkts\n"); for( i = 0; i < total_conns; i++) { printf("%d %s %d %s %d %3d %3d\n", i, TCP_Conn_Array[i].IPSrcAddr, TCP_Conn_Array[i].SrcPort, TCP_Conn_Array[i].IPDstAddr, TCP_Conn_Array[i].DstPort, TCP_Conn_Array[i].SrctoDst_pkts, TCP_Conn_Array[i].DsttoSrc_pkts); } } /* Search the TCP connection table for a match. */ /* Note that S_Addr, S_port, D_Addr, D_port are globals, */ /* which were set when reading in the current input line. */ /* Return index where a match is found, or -1 otherwise. */ int find_conn(void) { int i; for( i = 0; i < total_conns; i++ ) { if( (strcmp(TCP_Conn_Array[i].IPSrcAddr, S_Addr) == 0) && (TCP_Conn_Array[i].SrcPort == S_port) && (strcmp(TCP_Conn_Array[i].IPDstAddr, D_Addr) == 0) && (TCP_Conn_Array[i].DstPort == D_port) ) return( i ); if( (strcmp(TCP_Conn_Array[i].IPSrcAddr, D_Addr) == 0) && (TCP_Conn_Array[i].SrcPort == D_port) && (strcmp(TCP_Conn_Array[i].IPDstAddr, S_Addr) == 0) && (TCP_Conn_Array[i].DstPort == S_port) ) return( i ); } return( -1 ); } /* Clear out the TCP connection table data structure */ void Initialize(void) { int i, j; for( i = 0; i < MAX_CONNS; i++ ) { for( j = 0; j < IP_ADDR_LENGTH; j++ ) { TCP_Conn_Array[i].IPSrcAddr[j] = '\0'; TCP_Conn_Array[i].IPDstAddr[j] = '\0'; } TCP_Conn_Array[i].SrcPort = 0; TCP_Conn_Array[i].DstPort = 0; TCP_Conn_Array[i].DsttoSrc_pkts = 0; TCP_Conn_Array[i].SrctoDst_pkts = 0; } } /* Clear out string variables, since not all IP addresses are same length */ void clear_strings(void) { int i; for( i = 0; i < IP_ADDR_LENGTH; i++ ) { S_Addr[i] = '\0'; D_Addr[i] = '\0'; } flags[0] = '\0'; flags[1] = '\0'; } /* Process a new packet (i.e., one line of the trace file) */ void process_new_packet(void) { int i, forward, index; total_pkts++; #ifdef DEBUG printf("%f %s %d %s %d %d %u %u %s\n", tstamp, S_Addr, S_port, D_Addr, D_port, ipSize, seqNum, ackNum, flags); #endif index = find_conn(); if( index < 0 ) { #ifdef DEBUG printf("Setting up new connection record %d...\n", total_conns); #endif /* no record of this TCP connection yet, so add it */ index = total_conns++; if( index == MAX_CONNS ) { fprintf(stderr, "Whoa!! Too many connections for me to handle!!\n"); exit(0); } /* record the IP addresses and port numbers */ for( i = 0; i < IP_ADDR_LENGTH; i++ ) { TCP_Conn_Array[index].IPSrcAddr[i] = S_Addr[i]; TCP_Conn_Array[index].IPDstAddr[i] = D_Addr[i]; } TCP_Conn_Array[index].SrcPort = S_port; TCP_Conn_Array[index].DstPort = D_port; } else { #ifdef DEBUG printf("Updating existing connection record %d...\n", index); #endif } /* when we get here, 'index' tells us which conn in the table */ /* we are working with. It may have existed before, or has */ /* just been added. In either case, update the statistics. */ /* see if this is a SrctoDst or a DsttoSrc packet, */ /* compared to the first packet of the connection */ if( strcmp(S_Addr, TCP_Conn_Array[index].IPSrcAddr) == 0 ) forward = 1; else forward = 0; /* count the number of SYN (start) pkts seen in the handshake */ /* update packet count */ if( forward ) TCP_Conn_Array[index].SrctoDst_pkts++; else /* reverse direction traffic */ TCP_Conn_Array[index].DsttoSrc_pkts++; }