#include #include #include #include #include #include #include #include #include #include #include #include #include "packet_handler.h" #include "packet.h" #include "transaction.h" extern int CHECKID; extern struct hash_table* ConnTable; double lasttime; int firstow = TRUE; extern double offset; extern double adjust; pcap_t* descr1=NULL, *descr2=NULL; double lastReportTime=0; extern double startTime; extern unsigned int my_dest; extern unsigned int my_dmask; extern unsigned int my_source; extern unsigned int my_smask; extern char Host[17]; int isDstPort(int port) { switch(port) { case HTTP_PORT1: case HTTP_PORT2: case HTTP_PORT3: case TELNET_PORT: case SMTP_PORT1: case SMTP_PORT2: case NEWS_PORT: case IRC_PORT: case FTP_PORT1: case FTP_PORT2: case SSH_PORT: case DNS_PORT: case VOIP_PORT: case ICMP_PORT: return TRUE; default: return FALSE; } } unsigned short parse_port(unsigned char* app, int len) { int i, count=0, j; unsigned short port = 0, tport = 0; /* Look for commas */ for(i=0;iether_type) == ETHERTYPE_IP) { /* OK to proceed */ } else if (ntohs (eptr->ether_type) == ETHERTYPE_ARP) { continue; } else { /* Now a very crude fix, since it seems that some interfaces add two leading 0 bytes to everything they capture */ packet = packet + 2; eptr = (struct ether_header *) packet; if (ntohs (eptr->ether_type) == ETHERTYPE_IP) { /* OK to proceed */ } else /* Give up, not an IP packet */ continue; } ip = (struct ip*)(packet + sizeof(struct ether_header)); len = ntohs(ip->ip_len) - 4*ip->ip_hl; hdlen += 4*ip->ip_hl; srcIP = ntohl(ip->ip_src.s_addr); dstIP = ntohl(ip->ip_dst.s_addr); in.s_addr = dstIP; strcpy(Host, inet_ntoa(in)); if (ip->ip_p == IPPROTO_UDP) { unsigned char* app; udp = (struct udphdr*)((unsigned int)ip+4*ip->ip_hl); sport = ntohs(udp->source); dport = ntohs(udp->dest); len = len - 8; hdlen += 8; app = (u_char*)((unsigned int)udp+8); if (hdr.caplen >= 4+hdlen) { identification = app[0]*256+app[1]; } if (dport == VOIP_PORT) identification = ip->ip_id; } else if (ip->ip_p == IPPROTO_ICMP) { icmp = (struct icmphdr*)((unsigned int)ip+4*ip->ip_hl); /* Only consider echo packets */ if (icmp->type == ECHO_REQUEST) { identification = icmp->un.echo.id; } } else if (ip->ip_p == IPPROTO_TCP) { unsigned int seq, ack; tcp = (struct tcphdr*)((unsigned int)ip+4*ip->ip_hl); sport = ntohs(tcp->source); dport = ntohs(tcp->dest); seq = ntohl(tcp->seq); ack = ntohl(tcp->ack_seq); len = len - tcp->doff*4; identification = seq; } if ((my_dest && !compare(dstIP)) || (my_source && !compare(srcIP))) { continue; } if (identification && isDstPort(dport)) { int res; res = insert_packet(identification, dport, dtime); } } } void process_packets(u_char *args, const struct pcap_pkthdr *hdr, const u_char *packet) { struct ether_header *eptr; struct ip* ip; int i; char source[20], dest[20]; struct tcphdr* tcp; struct udphdr* udp; struct icmphdr* icmp; unsigned int srcIP, dstIP; unsigned short sport, dport; int len; double dtime; int hdlen = 0; /* lets start with the ether header... */ eptr = (struct ether_header *) packet; dtime = hdr->ts.tv_sec + (double)hdr->ts.tv_usec/1000000; lasttime = dtime; if (startTime == 0) { startTime = dtime; lastReportTime = startTime; initTransactions(); } if (dtime - lastReportTime >= REPORT_INTERVAL) { checkTransactions(dtime); lastReportTime = dtime; } /* Do a couple of checks to see what packet type we have..*/ if (ntohs (eptr->ether_type) == ETHERTYPE_IP) { /* OK to proceed */ } else if (ntohs (eptr->ether_type) == ETHERTYPE_ARP) { return; } else { /* Now a very crude fix, since it seems that some interfaces add two leading 0 bytes to everything they capture */ packet = packet + 2; eptr = (struct ether_header *) packet; if (ntohs (eptr->ether_type) == ETHERTYPE_IP) { /* OK to proceed */ } else /* Give up, not an IP packet */ return; } ip = (struct ip*)(packet + sizeof(struct ether_header)); len = ntohs(ip->ip_len) - 4*ip->ip_hl; hdlen += 4*ip->ip_hl; srcIP = ntohl(ip->ip_src.s_addr); dstIP = ntohl(ip->ip_dst.s_addr); if (ip->ip_p == IPPROTO_TCP) { int index; unsigned int seq, ack; unsigned char flags, * app; double owdelay = 0; unsigned short dataport = 0; tcp = (struct tcphdr*)((unsigned int)ip+4*ip->ip_hl); sport = ntohs(tcp->source); dport = ntohs(tcp->dest); seq = ntohl(tcp->seq); ack = ntohl(tcp->ack_seq); hdlen += tcp->doff*4; app = (u_char*)((unsigned int)tcp+tcp->doff*4); if (dport == FTP_PORT2 && (len - tcp->doff*4) > 5) { /* If this is port command parse out the port where the data transfer will occur */ if (!strncmp(app,"PORT",4)) { dataport = parse_port(app+5, len - tcp->doff*4-5); } } if (isDstPort(dport) && ((my_source && compare(srcIP)) || (my_dest && compare(dstIP))) && descr2) { /* Search for matching packet in the queue */ index = find_packet(seq, dport); if (index == NOT_FOUND) fill_queue(); index = find_packet(seq, dport); if (index != NOT_FOUND) { struct pdata* d = get_pdata(index); if (firstow) { firstow = FALSE; adjust = offset - d->timestamp[0] + dtime; } owdelay = d->timestamp[0] - dtime + adjust; // printf("owdelay %lf\n", owdelay); delete_packet(seq, dport); } else { owdelay = MAX_DELAY; printf("Could not find the packet sent at %lf\n",dtime); } } len = len - tcp->doff*4; handle_TCP_packet(dtime, srcIP, dstIP, sport, dport, seq+len, ack, tcp->syn, tcp->ack, tcp->fin, tcp->rst, len, hdlen, owdelay, dataport); } else if (ip->ip_p == IPPROTO_UDP) { int index, req = FALSE; unsigned short identification=0, j; double owdelay = 0; u_char* app; u_char id[3]; udp = (struct udphdr*)((unsigned int)ip+4*ip->ip_hl); sport = ntohs(udp->source); dport = ntohs(udp->dest); hdlen += 8; app = (u_char*)((unsigned int)udp+8); if (hdr->caplen >= 4+hdlen) { identification = app[0]*256+app[1]; } if (dport == VOIP_PORT) { identification = ip->ip_id; } if (dport == DNS_PORT) { if (app[2] & (unsigned int)0x80) req = FALSE; else req = TRUE; } else if (dport == VOIP_PORT) req = TRUE; if (isDstPort(dport) && identification && descr2) { /* Search for matching packet in the queue */ index = find_packet(identification, dport); if (index == NOT_FOUND) fill_queue(); index = find_packet(identification, dport); if (index != NOT_FOUND) { struct pdata* d = get_pdata(index); if (firstow) { firstow = FALSE; adjust = offset - d->timestamp[0] + dtime; } owdelay = d->timestamp[0] - dtime + adjust; printf("owdelay %lf\n", owdelay); delete_packet(identification, dport); } else { owdelay = MAX_DELAY; printf("Couldu not find the packet sent at %lf ID %u\n",dtime, identification); } } len = len - 8; handle_UDP_packet(dtime, srcIP, dstIP, sport, dport, len, hdlen, identification, owdelay, req); } else if (ip->ip_p == IPPROTO_ICMP) { unsigned short identification, j; double owdelay; int type; icmp = (struct icmphdr*)((unsigned int)ip+4*ip->ip_hl); sport = 0; dport = 0; /* Only consider echo packets */ if (icmp->type == ECHO_REQUEST || icmp->type == ECHO_REPLY || !CHECKID) { int index; hdlen += 8; identification = icmp->un.echo.id; if (icmp->type == ECHO_REQUEST && descr2) { index = find_packet(identification, dport); if (index == NOT_FOUND) fill_queue(); index = find_packet(identification, dport); if (index != NOT_FOUND) { struct pdata* d = get_pdata(index); if (firstow) { firstow = FALSE; adjust = offset - d->timestamp[0] + dtime; } owdelay = d->timestamp[0] - dtime + adjust; delete_packet(identification, dport); } else { owdelay = MAX_DELAY; printf("Could not find the packet sent at %lf\n",dtime); } } len = len - 8; handle_ICMP_packet(dtime, srcIP, dstIP, sport, dport, len, hdlen, identification, icmp->type, owdelay); } } } int read_pcap(int argc, char **argv) { int i; char *dev; char errbuf1[PCAP_ERRBUF_SIZE], errbuf2[PCAP_ERRBUF_SIZE]; const u_char *packet; u_char *ptr; /* printing out hardware header info */ printf("reading from files %s\n", argv[1]); descr1 = pcap_open_offline(argv[1],errbuf1); if (argc > 2) { descr2 = pcap_open_offline(argv[2],errbuf2); printf("reading from files %s\n", argv[2]); } if(descr1 == NULL) { printf("pcap_open_offline(): %s\n",errbuf1); exit(1); } pcap_loop(descr1,-1,process_packets,0); checkTransactions(lasttime); closeTransactions(lasttime); reset_packtable(); pcap_close(descr1); if (descr2) pcap_close(descr2); return 0; }