/* trafique.c network traffic data Kriek Jooste/kokeycode@speakopen.org/11.10.2005 */ /* This tool uses sniffed network traffic and outputs a line of data every minute giving figures of the amount of data transferred per protocol. This data can be fed to a graphical plotting tool, e.g. ploticus, to make pretty graphs. help on usage: */ /* compile with: gcc -lpcap -o trafique trafique.c * help on usage: ./trafique -h */ #include #include #include #include #include #include #define ETHERNET_HEADER_LENGTH 14 int ip_header_len(const unsigned char *packet); int tcp_header_len(const unsigned char *packet); char printable[256]; int i; int j; int q; int koos; int sport, dport, prtcl; char remmie[10]; struct tm *hrtime; char str[64]; int plength; int dbgr; int bytelen; int iphdrlen; int tcphdrlen; int datasize; char pktdata[1024]; int pktstart; struct timeval tstamp; char pstamp[16]; int pasftp[65536][5]; int pasftp_count; int srcports[65536]; int top10[10][2]; int top_a, top_b; char topstr[256]; char topstr_tmp[256]; char topvalues[128]; char topcomma[12]; int srcports_count; int srcports_found; int osrcports[65536]; int otop10[10][2]; char otopstr[256]; char otopstr_tmp[256]; char otopvalues[128]; char otopcomma[12]; int traf_ht; int traf_ftp; int traf_tinc; int traf_tout; int traf_dns; int traf_telnet; int traf_ssh; int traf_netbios; int traf_other; unsigned int shwhdrs; unsigned int shwbody; unsigned char srcaddie[4]; unsigned char dstaddie[4]; u_int16_t fragval; unsigned char srcport[2]; unsigned char dstport[2]; time_t basetime; int mska, mskb, mskc, mskd; int p; char *subnn; char netstring[16]; int dataps; int totalpersec; char printstr[256]; int lenin; char theoutfile[128]; FILE *outfile; int livesniff; char dumpfile[128]; /* ip_header_len returns the length of the ip header. If something other than an ip packet gets passed to it, you'll just get gibberish. The packet must be a complete packet lifted from the wire including ethernet header etc. */ int ip_header_len(const unsigned char *packet){ return 4 * (packet[14] & 0x0f); } /* tcp_header_len returns the length of the tcp header. If something other than a tcp packet gets passed to it, you'll just get gibberish. The packet must be a complete packet lifted from the wire including ethernet header etc. */ int tcp_header_len(const unsigned char *packet){ return 4 * ((packet[46]) >> 4); } int hexprint(unsigned char printbyte) { if (printbyte<16) { printf("0%X", printbyte); } else { printf("%X", printbyte); } } int dprint(char dbstring[256]) { if (dbgr == 1) { printf("DEBUG: %s\n", dbstring); } } /* sorting function: this is my custom implementation of quicksort since qsort() can only deal with arrays with one item per element, and our top10 has two. */ int quicksort( a, lo, hi ) int a[10][2], hi, lo; { int h, l, p, t1, t2; if (lo < hi) { l = lo; h = hi; p = a[hi][1]; do { while ((l < h) && (a[l][1] <= p)) l = l+1; while ((h > l) && (a[h][1] >= p)) h = h-1; if (l < h) { t1 = a[l][0]; t2 = a[l][1]; a[l][0] = a[h][0]; a[l][1] = a[h][1]; a[h][0] = t1; a[h][1] = t2; } } while (l < h); t1 = a[l][0]; t2 = a[l][1]; a[l][0] = a[hi][0]; a[l][1] = a[hi][1]; a[hi][0] = t1; a[hi][1] = t2; quicksort( a, lo, l-1 ); quicksort( a, l+1, hi ); } } void captureloop(u_char *useless, const struct pcap_pkthdr* pkthdr, const u_char* packet) { plength = pkthdr->len; // subtract ethernet header length and turn into bytes bytelen = (plength-ETHERNET_HEADER_LENGTH)/8; iphdrlen = ip_header_len(packet); tcphdrlen = tcp_header_len(packet); tstamp = pkthdr->ts; pktstart = ETHERNET_HEADER_LENGTH + ip_header_len(packet) + tcp_header_len(packet); hrtime = localtime(&tstamp.tv_sec); if (tstamp.tv_sec % 60 != 0) { koos = 0; totalpersec = dataps + bytelen; dataps = totalpersec; /* gets the source and destination port, but blindly assuming that it is a tcp or udp packet in the first place */ sport = packet[34]*256+packet[35]; dport = packet[36]*256+packet[37]; /* gets the protocol (e.g. UDP, TCP, ICMP, etc.) */ prtcl = packet[23]; /* works out the most used INCOMING source ports for the minute checks if it is TCP or UDP */ /* check if incoming */ if (packet[26] != mska && packet[27] != mskb && packet[28] != mskc) { if (prtcl == 6 || prtcl == 17) { totalpersec = srcports[sport] + bytelen; srcports[sport] = totalpersec; } } else { /* outgoing */ if (prtcl == 6 || prtcl == 17) { totalpersec = osrcports[dport] + bytelen; osrcports[dport] = totalpersec; } } /* check source port number */ switch ( sport ) { case 80: totalpersec = traf_ht + bytelen; traf_ht = totalpersec; break; case 443: totalpersec = traf_ht + bytelen; traf_ht = totalpersec; break; case 20: totalpersec = traf_ftp + bytelen; traf_ftp = totalpersec; break; case 21: totalpersec = traf_ftp + bytelen; traf_ftp = totalpersec; break; case 53: totalpersec = traf_dns + bytelen; traf_dns = totalpersec; break; case 23: totalpersec = traf_telnet + bytelen; traf_telnet = totalpersec; break; case 22: totalpersec = traf_ssh + bytelen; traf_ssh = totalpersec; break; case 139: totalpersec = traf_netbios + bytelen; traf_netbios = totalpersec; break; default: totalpersec = traf_other + bytelen; traf_other = totalpersec; break; } /* check source ip and work out incoming and outgoing totals */ if (packet[26] == mska && packet[27] == mskb && packet[28] == mskc) { /* check destination ip */ if (packet[31] != 82 && packet[32] != 211 && packet[33] != 112) { /* packet from local to remote*/ totalpersec = traf_tout + bytelen; traf_tout = totalpersec; } else { /* packet from local to local */ } } else { /* packet from remote */ totalpersec = traf_tinc + bytelen; traf_tinc = totalpersec; } /* check for FTP data */ /* this section checks responses from the FTP control port and picks up when passive FTP is being used */ if (plength > 66 && packet[34]*256+packet[35] == 21) { int a, b, c, d, e, f; datasize = plength-pktstart; if (datasize > 0) { strncpy(pktdata, packet+pktstart, datasize); if(strncmp(pktdata, "227 ", 4) == 0) { sscanf(&pktdata[27], "%d,%d,%d,%d,%d,%d", &a, &b, &c, &d, &e, &f); sprintf(printstr, "pasv %d.%d.%d.%d:%d\n", a, b, c, d, (e*256+f)); dprint(printstr); pasftp[pasftp_count][0] = a; pasftp[pasftp_count][1] = b; pasftp[pasftp_count][2] = c; pasftp[pasftp_count][3] = d; pasftp[pasftp_count][4] = (e*256+f); pasftp_count++; if (dbgr == 1 ) { for (i = 0;i "); for (j=6;j<12;j++) { if (packet[j]<16) { printf("0%x:",packet[j]); } else { printf("%x:",packet[j]); } } printf("\n"); for (j=12;j %d.%d.%d.%d\n", srcaddie[0], srcaddie[1], srcaddie[2], srcaddie[3], dstaddie[0], dstaddie[1], dstaddie[2], dstaddie[3]); printf("----------------------\n"); } if (shwhdrs == 1) { if (packet[23] == 6) { printf("\ntcp header\n"); printf("----------------------\n"); printf("| srcport | dstport |\n"); printf("| "); hexprint(packet[34]); hexprint(packet[35]); printf(" | "); hexprint(packet[36]); hexprint(packet[37]); printf(" | (sport: %d, dport: %d)\n", packet[34]*256+packet[35], packet[36]*256+packet[37]); printf("----------------------\n"); } else { printf("not tcp\n"); } } // printing readable characters from the packet if (plength > 66 && shwbody == 1) { datasize = plength-pktstart; printf("------\n"); if (datasize > 0) { strncpy(pktdata, packet+pktstart, datasize); for (j=0;j interface\n"); printf("-d "); printf("print header detail (debug)\n"); printf("-o "); printf("output filename\n"); printf("-b "); printf("show printable contents "); printf("of packet (debug)\n"); printf("-r "); printf("read pcap dump file instead "); printf("of sniffing interface\n"); printf("-l local network"); printf(" prefix (eg -l 192.168.1)\n"); printf("\n"); exit(8); case 'd': shwhdrs = 1; break; case 'b': shwbody = 1; break; case 'i': if ( i+1 < argc ) { sprintf(sniffdev, "%s", argv[i+1]); } break; case 'r': if ( i+1 < argc ) { sprintf(dumpfile, "%s", argv[i+1]); livesniff = 0; } break; case 'o': if ( i+1 < argc ) { strcpy(theoutfile, argv[i+1]); } break; case 'D': dbgr = 1; break; case 'l': if ( i+1 < argc ) { strcpy(netstring, argv[i+1]); } if ((subnn = strtok(netstring, ".")) != 0 ) { mska = atoi(subnn); if ((subnn = strtok(NULL, ".")) != 0 ) { mskb = atoi(subnn); if ((subnn = strtok(NULL, ".")) != 0 ) { mskc = atoi(subnn); } } } printf("local mask: %d.%d.%d.*\n", mska, mskb, mskc); break; } } } i = 0; sprintf(printable, " \n"); printf("#output: %s\n", theoutfile); if (!strcmp("none",sniffdev)) { /* check what the default device is */ devi = pcap_lookupdev(errbuf); } else { devi = sniffdev; } if (livesniff == 1) { fprintf(stderr, "#monitoring device: %s\n", devi); /* open the default device */ descr = pcap_open_live(devi,BUFSIZ,0,0,errbuf); if(descr == NULL) { printf("pcap_open_live(): %s\n",errbuf); exit(1); } fprintf(stderr, "#opened interface\n"); } else { descr = pcap_open_offline(dumpfile, errbuf); } fprintf(stdout, "#date.time total incoming outgoing http "); fprintf(stdout, "ftp dns telnet ssh netbios other top10\n"); /* set filter sure we only get ip packets */ pcap_loop(descr,-1,captureloop,NULL); pcap_close(descr); }