#include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include /* the L2 protocols */ enum {LEVEL_RAW, LEVEL_DGRAM, LEVEL_ETH, LEVEL_IP, LEVEL_UDP, LEVEL_ICMP, LEVEL_TCP, LEVEL_ARP}; int decode(const int level,const unsigned char *buffer,const int len) { switch(level) { case LEVEL_ETH: { unsigned int ethertype; if (len < ETH_HLEN) { printf("ETH: Incomplete header, packet corrupt\n"); return 1; } printf( "%02x:%02x:%02x:%02x:%02x:%02x -> %02x:%02x:%02x:%02x:%02x:%02x\n", buffer[6], buffer[7], buffer[8], buffer[9], buffer[10], buffer[11], buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); ethertype=buffer[12]<<8|buffer[13]; switch(ethertype) { case ETHERTYPE_IP: return decode(LEVEL_IP,buffer+ETH_HLEN,len-ETH_HLEN); // ETH_HLEN=14 case ETHERTYPE_ARP: /* 0x0806 */ return decode(LEVEL_ARP,buffer+ETH_HLEN,len-ETH_HLEN); case 0x809B: printf("Appletalk\n"); break; case 0x8018: printf("DOMAIN\n"); break; case 0x0835: printf("RARP\n"); break; default: printf("Type %04X\n",ethertype); break; } } return 0; case LEVEL_ARP: printf("Arp\n"); return 0; case LEVEL_IP: { unsigned int proto=buffer[0x09]; unsigned int offset=(buffer[0]&0x0F)<<2; if(len<20 || len %d.%d.%d.%d\n", buffer[0x0C], buffer[0x0D], buffer[0x0E], buffer[0x0F], buffer[0x10], buffer[0x11], buffer[0x12], buffer[0x13]); switch(proto) { case 1: return decode(LEVEL_ICMP,buffer+offset,len-offset); case 6: return decode(LEVEL_TCP,buffer+offset,len-offset); case 17: return decode(LEVEL_UDP,buffer+offset,len-offset); default: printf("Proto %02X\n",proto); break; } } return 0; case LEVEL_TCP: printf("TCP %u->%u\n",buffer[0]<<8|buffer[1],buffer[2]<<8|buffer[3]); return 0; case LEVEL_UDP: printf("UDP %u->%u\n",buffer[0]<<8|buffer[1],buffer[2]<<8|buffer[3]); return 0; case LEVEL_ICMP: printf("ICMP type=%u, code=%u ", buffer[0],buffer[1]); switch(buffer[0]) { case 0: printf("Echo reply"); break; case 3: printf("Destination unreachable"); break; case 8: printf("Echo request"); break; case 11: printf("Time exceeded"); break; case 30: printf("Traceroute"); break; } printf("\n"); return 0; } return 1; } int datalinkoffset(int type) { switch (type) { case DLT_EN10MB: return 14; case DLT_PPP: return 4; case DLT_PPP_BSDOS: return 24; case DLT_SLIP: return 16; case DLT_SLIP_BSDOS: return 24; case DLT_FDDI: return 21; case DLT_IEEE802: return 22; case DLT_RAW: return 0; case DLT_LINUX_SLL: return 16; default: printf("type=%d(0x%x)",type,type); return -1; } } struct singleton { struct pcap_pkthdr *hdr; const u_char *pkt; }; static void pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt) { struct singleton *sp = (struct singleton *)userData; *sp->hdr = *h; sp->pkt = pkt; } struct s_user { int datalink; int offset; pcap_dumper_t *handle_out; }; /* * * Called by pcap_loop upon reciept of each packet * */ void callback(unsigned char *user, struct pcap_pkthdr *header, unsigned char *packet) { static int nbr=1; struct s_user *my_data=(struct s_user*)user; printf("%d =====> Packet intercepted, %d bytes sniffed <=====\n", nbr++,header->len); switch(my_data->datalink) { case DLT_EN10MB: decode(LEVEL_ETH,packet,header->caplen); break; case DLT_LINUX_SLL: switch(packet[14]<<8|packet[15]) { case ETHERTYPE_ARP: decode(LEVEL_ARP,packet+my_data->offset,header->caplen-my_data->offset); break; case ETHERTYPE_IP: decode(LEVEL_IP,packet+my_data->offset,header->caplen-my_data->offset); break; } break; } pcap_dump((u_char *)(my_data->handle_out), header, packet); } int main(int argc, char **argv) { pcap_t *handle; /* Session handle */ char *dev="any"; /* The device to sniff on */ char *filter_app = ""; /* The filter expression */ struct bpf_program filter; /* The compiled filter */ char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */ bpf_u_int32 mask; /* Our netmask */ bpf_u_int32 net; /* Our IP */ struct pcap_pkthdr header; /* The header that pcap gives us */ const u_char *packet; /* The actual packet */ int datalink; int offset; struct singleton s; struct s_user user_data; pcap_dumper_t *dumper_out; #ifdef OLD /* Define the device */ printf("device %s\n",dev); /* Open the session in promiscuous mode */ handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf); #else handle= pcap_open_offline("snort.log", errbuf); #endif if(!handle) { perror("pcap_open_live failed "); return 1; } user_data.handle_out=pcap_dump_open(handle, "snort2.log"); /* Grab a packet */ user_data.datalink = pcap_datalink(handle); user_data.offset = datalinkoffset(user_data.datalink); if(argc>2) filter_app=argv[2]; /* Compile and apply the filter */ if(pcap_compile(handle, &filter, filter_app, 0, mask)<0) { printf("error: %s\n",pcap_geterr(handle)); return 1; } pcap_setfilter(handle, &filter); if(pcap_loop(handle,-1,(pcap_handler)callback,(u_char *)&user_data)<0) { fprintf(stderr, "%s: pcap_loop: %s\n", argv[0], pcap_geterr(handle)); } /* And close the session */ printf("pcap_close\n"); pcap_close(handle); pcap_dump_close(user_data.handle_out); return(0); }