diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c1240a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.o +driftnet +driftnet.1 diff --git a/driftnet.c b/driftnet.c index 5169a9a..8e250d4 100644 --- a/driftnet.c +++ b/driftnet.c @@ -183,7 +183,10 @@ void dump_data(FILE *fp, const unsigned char *data, const unsigned int len) { * type. This is based on init_linktype in the libpcap distribution; I * don't know why libpcap doesn't expose the information directly. The * constants here are taken from 0.6.2, but I've added #ifdefs in the hope - * that it will still compile with earlier versions. */ + * that it will still compile with earlier versions. + * The return value _must_ be checked by the caller, since -1 will be returned for + * unknown link types! + */ int get_link_level_hdr_length(int type) { switch (type) { @@ -247,11 +250,32 @@ int get_link_level_hdr_length(int type) case DLT_IEEE802_11: return 32; /* 20030606 email from Nikhil Bobb */ /*44; */ #endif - + +#ifdef DLT_IEEE802_11_RADIO /* radiotap (atheros monitoring) */ + case DLT_IEEE802_11_RADIO: + /* actually, the header size can vary from packet to packet; + * we have to look at each packet separately + */ + return 0; +#endif default:; } fprintf(stderr, PROGNAME": unknown data link type %d", type); - exit(1); + return -1; +} + +int get_frame_link_level_hdr_length(int type, const u_char *pkt) { + switch(type) { +#ifdef DLT_IEEE802_11_RADIO + case DLT_IEEE802_11_RADIO: + /* determine the length of the variable header + * and add the underlying part (we assume 802.11 for now) + */ + return *(uint16_t*)(pkt+2)+2+get_link_level_hdr_length(DLT_IEEE802_11); +#endif + default: + return get_link_level_hdr_length(type); + }; } @@ -368,18 +392,24 @@ char *connection_string(const struct in_addr s, const unsigned short s_port, con /* process_packet: * Callback which processes a packet captured by libpcap. */ -int pkt_offset; /* offset of IP packet within wire packet */ void process_packet(u_char *user, const struct pcap_pkthdr *hdr, const u_char *pkt) { struct ip ip; struct tcphdr tcp; struct in_addr s, d; int off, len, delta; + int pkt_offset; connection *C, c; if (verbose) fprintf(stderr, "."); + /* get the individual packet offset */ + pkt_offset = get_frame_link_level_hdr_length( pcap_datalink(pc), pkt ); + if (pkt_offset < 0) { /* something strange happened, we cannot handle this packet */ + return; + } + memcpy(&ip, pkt + pkt_offset, sizeof(ip)); memcpy(&s, &ip.ip_src, sizeof(ip.ip_src)); memcpy(&d, &ip.ip_dst, sizeof(ip.ip_dst)); @@ -656,14 +686,19 @@ int main(int argc, char *argv[]) { if (verbose) fprintf(stderr, PROGNAME": using temporary file directory %s\n", tmpdir); - if (!interface && !(interface = pcap_lookupdev(ebuf))) { + if (!dumpfile && !interface && !(interface = pcap_lookupdev(ebuf))) { fprintf(stderr, PROGNAME": pcap_lookupdev: %s\n", ebuf); fprintf(stderr, PROGNAME": try specifying an interface with -i\n"); return -1; } - if (verbose) - fprintf(stderr, PROGNAME": listening on %s%s\n", interface ? interface : "all interfaces", promisc ? " in promiscuous mode" : ""); + if (verbose) { + if (interface) { + fprintf(stderr, PROGNAME": listening on %s%s\n", interface ? interface : "all interfaces", promisc ? " in promiscuous mode" : ""); + } else if (dumpfile) { + fprintf(stderr, PROGNAME": processing packets from dumpfile '%s'\n", dumpfile); + } + } /* Build up filter. */ if (optind < argc) { @@ -756,12 +791,6 @@ int main(int argc, char *argv[]) { } } - /* Figure out the offset from the start of a returned packet to the data in - * it. */ - pkt_offset = get_link_level_hdr_length(pcap_datalink(pc)); - if (verbose) - fprintf(stderr, PROGNAME": link-level header length is %d bytes\n", pkt_offset); - slotsused = 0; slotsalloc = 64; slots = (connection*)xcalloc(slotsalloc, sizeof(connection));