diff options
Diffstat (limited to 'capture-wpcap.c')
-rw-r--r-- | capture-wpcap.c | 226 |
1 files changed, 202 insertions, 24 deletions
diff --git a/capture-wpcap.c b/capture-wpcap.c index 98de62ab46..88f6cbfd15 100644 --- a/capture-wpcap.c +++ b/capture-wpcap.c @@ -1,13 +1,14 @@ /* capture-wpcap.c - * Try to load WinPcap DLL at run-time. + * WinPcap-specific interfaces for capturing. We load WinPcap at run + * time, so that we only need one Ethereal binary and one Tethereal binary + * for Windows, regardless of whether WinPcap is installed or not. * - * $Id: capture-wpcap.c,v 1.3 2002/08/28 21:00:05 jmayer Exp $ + * $Id: capture-wpcap.c,v 1.4 2003/10/10 03:00:09 guy Exp $ * * Ethereal - Network traffic analyzer - * By Gerald Combs <gerald@zing.org> + * By Gerald Combs <gerald@ethereal.com> * Copyright 2001 Gerald Combs * - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -34,6 +35,9 @@ #include <pcap.h> #endif +#include "pcap-util.h" +#include "pcap-util-int.h" + /* XXX - yes, I know, I should move cppmagic.h to a generic location. */ #include "tools/lemon/cppmagic.h" @@ -41,7 +45,6 @@ gboolean has_wpcap = FALSE; #ifdef HAVE_LIBPCAP - static char* (*p_pcap_lookupdev) (char *); static void (*p_pcap_close) (pcap_t *); static int (*p_pcap_stats) (pcap_t *, struct pcap_stat *); @@ -60,29 +63,31 @@ static int (*p_pcap_loop) (pcap_t *, int, pcap_handler, guchar *); typedef struct { const char *name; gpointer *ptr; + gboolean optional; } symbol_table_t; -#define SYM(x) STRINGIFY(x) , (gpointer) &CONCAT(p_,x) +#define SYM(x, y) { STRINGIFY(x) , (gpointer) &CONCAT(p_,x), y } void load_wpcap(void) { - /* These are the symbols I need from Wpcap */ - symbol_table_t symbols[] = { - SYM(pcap_lookupdev), - SYM(pcap_close), - SYM(pcap_stats), - SYM(pcap_dispatch), - SYM(pcap_snapshot), - SYM(pcap_datalink), - SYM(pcap_setfilter), - SYM(pcap_geterr), - SYM(pcap_compile), - SYM(pcap_lookupnet), - SYM(pcap_open_live), - SYM(pcap_loop), - NULL, NULL + /* These are the symbols I need or want from Wpcap */ + static const symbol_table_t symbols[] = { + SYM(pcap_lookupdev, FALSE), + SYM(pcap_close, FALSE), + SYM(pcap_stats, FALSE), + SYM(pcap_dispatch, FALSE), + SYM(pcap_snapshot, FALSE), + SYM(pcap_datalink, FALSE), + SYM(pcap_setfilter, FALSE), + SYM(pcap_geterr, FALSE), + SYM(pcap_compile, FALSE), + SYM(pcap_lookupnet, FALSE), + SYM(pcap_open_live, FALSE), + SYM(pcap_loop, FALSE), + SYM(pcap_findalldevs, TRUE), + { NULL, NULL, FALSE } }; GModule *wh; /* wpcap handle */ @@ -95,9 +100,20 @@ load_wpcap(void) } sym = symbols; - while (sym && sym->name) { + while (sym->name) { if (!g_module_symbol(wh, sym->name, sym->ptr)) { - return; + if (sym->optional) { + /* + * We don't care if it's missing; we just + * don't use it. + */ + *sym->ptr = NULL; + } else { + /* + * We require this symbol. + */ + return; + } } sym++; } @@ -193,6 +209,169 @@ pcap_loop(pcap_t *a, int b, pcap_handler c, guchar *d) return p_pcap_loop(a, b, c, d); } +#ifdef HAVE_PCAP_FINDALLDEVS +int +pcap_findalldevs(pcap_if_t **a, char *b) +{ + g_assert(has_wpcap && p_pcap_findalldevs != NULL) + return p_pcap_findalldevs(a, b); +} +#endif + +/* + * This will use "pcap_findalldevs()" if we have it, otherwise it'll + * fall back on "pcap_lookupdev()". + */ +GList * +get_interface_list(int *err, char *err_str) +{ + GList *il = NULL; + wchar_t *names; + char *win95names; + char ascii_name[MAX_WIN_IF_NAME_LEN + 1]; + char ascii_desc[MAX_WIN_IF_NAME_LEN + 1]; + int i, j; + +#ifdef HAVE_PCAP_FINDALLDEVS + if (p_pcap_findalldevs != NULL) + return get_interface_list_findalldevs(err, errstr); +#endif + + /* + * In WinPcap, pcap_lookupdev is implemented by calling + * PacketGetAdapterNames. According to the documentation + * I could find: + * + * http://winpcap.polito.it/docs/man/html/Packet32_8c.html#a43 + * + * this means that: + * + * On Windows OT (95, 98, Me), pcap_lookupdev returns a sequence + * of bytes consisting of: + * + * a sequence of null-terminated ASCII strings (i.e., each + * one is terminated by a single 0 byte), giving the names + * of the interfaces; + * + * an empty ASCII string (i.e., a single 0 byte); + * + * a sequence of null-terminated ASCII strings, giving the + * descriptions of the interfaces; + * + * an empty ASCII string. + * + * On Windows NT (NT 4.0, W2K, WXP, W2K3, etc.), pcap_lookupdev + * returns a sequence of bytes consisting of: + * + * a sequence of null-terminated double-byte Unicode strings + * (i.e., each one consits of a sequence of double-byte + * characters, terminated by a double-byte 0), giving the + * names of the interfaces; + * + * an empty Unicode string (i.e., a double 0 byte); + * + * a sequence of null-terminated ASCII strings, giving the + * descriptions of the interfaces; + * + * an empty ASCII string. + * + * The Nth string in the first sequence is the name of the Nth + * adapter; the Nth string in the second sequence is the + * description of the Nth adapter. + */ + + names = (wchar_t *)pcap_lookupdev(err_str); + i = 0; + + if (names) { + char* desc = 0; + int desc_pos = 0; + + if (names[0]<256) { + /* + * If names[0] is less than 256 it means the first + * byte is 0. This implies that we are using Unicode + * characters. + */ + while (*(names+desc_pos) || *(names+desc_pos-1)) + desc_pos++; + desc_pos++; /* Step over the extra '\0' */ + desc = (char*)(names + desc_pos); /* cast *after* addition */ + + while (names[i] != 0) { + /* + * Copy the Unicode description to an ASCII + * string. + */ + j = 0; + while (*desc != 0) { + if (j < MAX_WIN_IF_NAME_LEN) + ascii_desc[j++] = *desc; + desc++; + } + ascii_desc[j] = '\0'; + desc++; + + /* + * Copy the Unicode name to an ASCII string. + */ + j = 0; + while (names[i] != 0) { + if (j < MAX_WIN_IF_NAME_LEN) + ascii_name[j++] = names[i++]; + } + ascii_name[j] = '\0'; + i++; + il = g_list_append(il, + if_info_new(ascii_name, ascii_desc)); + } + } else { + /* + * Otherwise we are in Windows 95/98 and using ASCII + * (8-bit) characters. + */ + win95names=(char *)names; + while (*(win95names+desc_pos) || *(win95names+desc_pos-1)) + desc_pos++; + desc_pos++; /* Step over the extra '\0' */ + desc = win95names + desc_pos; + + while (win95names[i] != '\0') { + /* + * "&win95names[i]" points to the current + * interface name, and "desc" points to + * that interface's description. + */ + il = g_list_append(il, + if_info_new(&win95names[i], desc)); + + /* + * Skip to the next description. + */ + while (*desc != 0) + desc++; + desc++; + + /* + * Skip to the next name. + */ + while (win95names[i] != 0) + i++; + i++; + } + } + } + + if (il == NULL) { + /* + * No interfaces found. + */ + *err = NO_INTERFACES_FOUND; + } + + return il; +} + #else /* HAVE_LIBPCAP */ void @@ -201,5 +380,4 @@ load_wpcap(void) return; } - #endif /* HAVE_LIBPCAP */ |