/* angst - pcap.c * by Patroklos Argyroudis * * The libpcap callback function and libpcap initialization. * * $Id: pcap.c,v 1.3 2001/02/04 03:38:43 argp Exp $ */ #include "angst.h" void dissect(char *user, struct pcap_pkthdr *pkthdr, u_char *pkt) { struct in_addr shost, dhost; /* source and destination hosts */ u_short sport, dport; /* source and destination port */ struct libnet_ip_hdr *ip; /* IP protocol header */ struct libnet_tcp_hdr *tcp; /* TCP protocol header */ struct libnet_ethernet_hdr *eth; /* ethernet header */ struct libnet_arp_hdr *arph; /* ARP protocol header */ u_char *data = NULL; /* packet's payload */ u_int datalen = 0; /* payload's length */ u_int iphlen = 0; /* IP header length */ u_int iptlen = 0; /* IP total length */ u_int tcphlen = 0; /* TCP header length */ u_int buflen = 0; /* buffer's actual length */ int i, j = 0; /* counters */ u_char temp[SNAPLEN]; /* temporary buffer */ u_int templen = 0; /* temporary buffer's length */ Host *current = NULL; int find_flag = 0; /* first of all deal with ARP requests */ if(arp_flag == 1) { eth = (struct libnet_ethernet_hdr *)pkt; arph = (struct libnet_arp_hdr *)(pkt + LIBNET_ETH_H); eth->ether_type = ntohs(eth->ether_type); arph->ar_op = ntohs(arph->ar_op); /* check if it is an ARP request */ if((eth->ether_type == ETHERTYPE_ARP) && (arph->ar_op == ARPOP_REQUEST)) { /* check if the host already exists in the linked list */ for(current = head; current; current = current->next) { if((memcmp(arph->ar_tpa, current->tpa, 4)) == 0) find_flag = 1; } if(find_flag == 0) add_host(arph->ar_tpa, arph->ar_sha, arph->ar_spa); } } /* now deal with TCP packets */ if(pkthdr->caplen < LIBNET_IP_H) return; /* received truncated IP packet */ ip = (struct libnet_ip_hdr *)(pkt + hdrlen); tcp = (struct libnet_tcp_hdr *)(pkt + hdrlen + LIBNET_IP_H); if(ip->ip_p == IPPROTO_TCP) { shost = ip->ip_src; dhost = ip->ip_dst; iptlen = ntohs(ip->ip_len); /* discard fragments */ if(ntohs(ip->ip_off) & 0x1fff) return; /* throwing away fragments */ iphlen = ip->ip_hl * 4; data = pkt + hdrlen + iphlen; if(iphlen > iptlen) return; /* IP packet received truncated */ datalen = (iptlen - iphlen); if(datalen < LIBNET_TCP_H) return; /* received truncated TCP packet */ tcphlen = tcp->th_off * 4; sport = ntohs(tcp->th_sport); dport = ntohs(tcp->th_dport); data += tcphlen; datalen -= tcphlen; init_buf(temp, sizeof(temp)); for(i = 0; i <= datalen; i++) { if(isprint(data[i])) { temp[j] = data[i]; j++; } else if((data[i] == '\r') || (data[i] == '\n')) { temp[j] = '\n'; j++; } } templen = strlen(temp); strlcat(buffer, temp, sizeof(buffer)); buflen = strlen(buffer); if((tcp->th_flags & TH_FIN) || (tcp->th_flags & TH_RST) || (buflen >= BUFSIZE)) { /* dump everything to the log file when the connection * is terminated, or when the maximum number of captured * bytes per connection is reached */ fprintf(fp, "\n[ %s : %u -> ", libnet_host_lookup(shost.s_addr, resolve_flag), sport); fprintf(fp, "%s : %u ]\n\n", libnet_host_lookup(dhost.s_addr, resolve_flag), dport); fwrite(buffer, buflen, 1, fp); fprintf(fp, "\n"); fflush(fp); init_buf(buffer, sizeof(buffer)); } } } int find_header_length(int d) { #ifdef DEBUG printf("datalink: "); #endif /* DEBUG */ switch(d) { #ifdef DLT_LOOP case DLT_LOOP: #endif /* DLT_LOOP */ case DLT_NULL: #ifdef DEBUG printf("no encapsulation, loopback\n"); #endif /* DEBUG */ return(4); /* loopback header 4 bytes */ break; case DLT_EN10MB: #ifdef DEBUG printf("ethernet 10mb\n"); #endif /* DEBUG */ return(14); /* ethernet 10mb header 14 bytes */ break; case DLT_FDDI: #ifdef DEBUG printf("fddi\n"); #endif /* DEBUG */ return(21); /* fddi header 21 bytes */ break; case DLT_PPP: #ifdef DEBUG printf("point-to-point protocol\n"); #endif /* DEBUG */ return(0); /* ppp header 0 or 24 bytes? */ break; default: #ifdef DEBUG printf("not found, assuming ethernet 10mb\n"); #endif /* DEBUG */ return(14); /* ethernet 10mb header 14 bytes */ break; } } /* EOF */