/********************************************************************** * * Adopted from Martin Casado, * http://yuba.stanford.edu/~casado/pcap/section3.html * * See also: http://www.devdungeon.com/content/using-libpcap-c * **********************************************************************/ #include #include #include #include #include #include // use these to further dissect packets #include #include #include // global: datalink type and header size int dltype; int dlt_size; struct my_pcap_context { int cnt; }; void callback(u_char *, const struct pcap_pkthdr*, const u_char*); void callback(u_char *user, // pass data between the calls with this const struct pcap_pkthdr* pkthdr, // pcap header, metadata about the packet const u_char* packet) // bytes on the wire, starting with Layer2 (e.g., Ethernet) { int i; // struct ether_header *eptr; /* net/ethernet.h */ // IP header (or another layer 3 protocol header, e.g., ARP) // will be found at the offset dlt_size . printf("\nFrame %d: %d bytes on the wire, %d captured\n", ((struct my_pcap_context*) user)->cnt++, pkthdr->len, pkthdr->caplen); for (i = 0; i < (bpf_u_int32) pkthdr->caplen; i++) { printf("%02X%s", (uint8_t)packet[i], (i + 1)%16 ? " " : "\n"); } printf("\n"); } int main(int argc,char **argv) { char *dev; char errbuf[PCAP_ERRBUF_SIZE]; pcap_t* cap; struct bpf_program fp; /* hold compiled program */ bpf_u_int32 maskp; /* subnet mask */ bpf_u_int32 netp; /* ip */ if(argc != 3){ fprintf(stdout,"Usage: %s interface \"filter program\"\n", argv[0]); return 0; } dev = argv[1]; /* open device for reading this time lets set it in promiscuous * mode so we can monitor traffic to another machine */ cap = pcap_open_live(dev, IP_MAXPACKET, // snaplen, truncate packets at this size (0 will do) 1, 1000, errbuf); // promiscuous mode? , timeout if(cap == NULL){ printf("pcap_open_live(): %s\n", errbuf); exit(1); } /* ask pcap for the network address and mask of the device */ if( pcap_lookupnet(dev, &netp, &maskp, errbuf) < 0 ){ printf("pcap_open_live(): %s\n", errbuf); exit(1); } // Datalink is important because the packet will start with a datalink-specific // header, which we must skip to get to IP. But how many bytes to skip? // Different DLTs have different lengths. We can either hard-code them, // or try setting DLT_RAW, to get rid of the datalink header entirely. // This will lose us info such as on which intreface the packet arrived, // and from what MAC address. --SB: RAW does not work on "any". dltype = pcap_datalink(cap); printf("Datalink type (see DLT_* in pcap/bpf.h and 'man pcap-linktype'): %d\n", dltype); switch(dltype){ // this seems like something PCAP would have a function for... case PCAP_ERROR_NOT_ACTIVATED: fprintf(stderr, "Failed to get data link type, bailing.\n"); exit(1); case DLT_RAW: dlt_size = 0; break; case DLT_LINUX_SLL: // "any" for device will give you this dlt_size = 16; break; case DLT_EN10MB: dlt_size = 14; break; default: fprintf(stderr, "Unknown data link type %d, bailing.\n", dltype ); exit(1); } /* Lets try and compile the program.. non-optimized */ /* Instead of netp, you can use PCAP_NETMASK_UNKNOWN if you don't need to use the broadcast-related filtering; this saves a call to pcap_lookupnet() above. */ if(pcap_compile(cap, &fp, argv[2], 0, netp) == -1){ fprintf(stderr, "Error calling pcap_compile (filter: %s)\n", argv[2]); exit(1); } /* set the compiled program as the filter */ if(pcap_setfilter(cap, &fp) == -1){ fprintf(stderr, "Error setting filter\n"); exit(1); } struct my_pcap_context mydata = { .cnt = 0 }; /* ... and loop */ pcap_loop(cap, -1, callback, (u_char*) &mydata); //cast to avoid type warning return 0; }