diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | Makefile.common | 1 | ||||
-rw-r--r-- | capture-pcap-util.c | 259 | ||||
-rw-r--r-- | capture_ifinfo.c | 88 | ||||
-rw-r--r-- | capture_ifinfo.h | 19 | ||||
-rw-r--r-- | capture_opts.h | 12 | ||||
-rw-r--r-- | capture_unix_ifnames.c | 116 | ||||
-rw-r--r-- | capture_unix_ifnames.h | 33 | ||||
-rw-r--r-- | dumpcap.c | 8 | ||||
-rw-r--r-- | ui/iface_lists.c | 2 |
10 files changed, 271 insertions, 270 deletions
diff --git a/Makefile.am b/Makefile.am index c3218f74db..4ee865075d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -285,8 +285,7 @@ wimaxasncp_DATA = \ wimaxasncp/dictionary.dtd PLATFORM_SRC = \ - capture-pcap-util-unix.c \ - capture_unix_ifnames.c + capture-pcap-util-unix.c if HAVE_PLUGINS -include plugins/Custom.make diff --git a/Makefile.common b/Makefile.common index 3553ab9d3e..411c8d9cda 100644 --- a/Makefile.common +++ b/Makefile.common @@ -66,7 +66,6 @@ WIRESHARK_COMMON_INCLUDES = \ svnversion.h \ capture-pcap-util.h \ capture-pcap-util-int.h \ - capture_unix_ifnames.h \ cfile.h \ cfutils.h \ clopts_common.h \ diff --git a/capture-pcap-util.c b/capture-pcap-util.c index abb220b851..f2573f06c5 100644 --- a/capture-pcap-util.c +++ b/capture-pcap-util.c @@ -54,8 +54,181 @@ #ifdef _WIN32 #include "capture_win_ifnames.h" /* windows friendly interface names */ +#endif + +/* + * Given an interface name, find the "friendly name" and interface + * type for the interface. + */ + +#if defined(__APPLE__) + +#include <CoreFoundation/CoreFoundation.h> +#include <SystemConfiguration/SystemConfiguration.h> + +#include "cfutils.h" + +/* + * On OS X, we get the "friendly name" and interface type for the interface + * from the System Configuration framework. + * + * To find the System Configuration framework information for the + * interface, we get all the interfaces that the System Configuration + * framework knows about and look for the one with a "BSD name" matching + * the interface name. + * + * If we find it, we use its "localized display name", if it has one, as + * the "friendly name". + * + * As for the interface type: + * + * Yes, fetching all the network addresses for an interface gets you an + * AF_LINK address, of type "struct sockaddr_dl", and, yes, that includes + * an SNMP MIB-II ifType value. + * + * However, it's IFT_ETHER, i.e. Ethernet, for AirPort interfaces, + * not IFT_IEEE80211 (which isn't defined in OS X in any case). + * + * Perhaps some other BSD-flavored OSes won't make this mistake; + * however, FreeBSD 7.0 and OpenBSD 4.2, at least, appear to have + * made the same mistake, at least for my Belkin ZyDAS stick. + * + * SCNetworkInterfaceGetInterfaceType() will get the interface + * type. The interface type is a CFString, and: + * + * kSCNetworkInterfaceTypeIEEE80211 means IF_WIRELESS; + * kSCNetworkInterfaceTypeBluetooth means IF_BLUETOOTH; + * kSCNetworkInterfaceTypeModem or + * kSCNetworkInterfaceTypePPP or + * maybe kSCNetworkInterfaceTypeWWAN means IF_DIALUP + */ +static void +add_unix_interface_ifinfo(if_info_t *if_info, const char *name, + const char *description _U_) +{ + CFStringRef name_CFString; + CFArrayRef interfaces; + CFIndex num_interfaces; + CFIndex i; + SCNetworkInterfaceRef interface; + CFStringRef bsdname_CFString; + CFStringRef friendly_name_CFString; + CFStringRef interface_type_CFString; + + interfaces = SCNetworkInterfaceCopyAll(); + if (interfaces == NULL) { + /* + * Couldn't get a list of interfaces. + */ + return; + } + + name_CFString = CFStringCreateWithCString(kCFAllocatorDefault, + name, kCFStringEncodingUTF8); + if (name_CFString == NULL) { + /* + * Couldn't convert the interface name to a CFString. + */ + CFRelease(interfaces); + return; + } + + num_interfaces = CFArrayGetCount(interfaces); + for (i = 0; i < num_interfaces; i++) { + interface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(interfaces, i); + bsdname_CFString = SCNetworkInterfaceGetBSDName(interface); + if (bsdname_CFString == NULL) { + /* + * This interface has no BSD name, so it's not + * a regular network interface. + */ + continue; + } + if (CFStringCompare(name_CFString, bsdname_CFString, 0) == 0) { + /* + * This is the interface. + * First, get the friendly name. + */ + friendly_name_CFString = SCNetworkInterfaceGetLocalizedDisplayName(interface); + if (friendly_name_CFString != NULL) + if_info->friendly_name = CFString_to_C_string(friendly_name_CFString); + + /* + * Now get the interface type. + */ + interface_type_CFString = SCNetworkInterfaceGetInterfaceType(interface); + if (CFStringCompare(interface_type_CFString, + kSCNetworkInterfaceTypeIEEE80211, 0) == kCFCompareEqualTo) + if_info->type = IF_WIRELESS; + else if (CFStringCompare(interface_type_CFString, + kSCNetworkInterfaceTypeBluetooth, 0) == kCFCompareEqualTo) + if_info->type = IF_BLUETOOTH; + else if (CFStringCompare(interface_type_CFString, + kSCNetworkInterfaceTypeModem, 0) == kCFCompareEqualTo) + if_info->type = IF_DIALUP; + else if (CFStringCompare(interface_type_CFString, + kSCNetworkInterfaceTypePPP, 0) == kCFCompareEqualTo) + if_info->type = IF_DIALUP; + else if (CFStringCompare(interface_type_CFString, + kSCNetworkInterfaceTypeWWAN, 0) == kCFCompareEqualTo) + if_info->type = IF_DIALUP; + else + if_info->type = IF_WIRED; + break; + } + } + + CFRelease(interfaces); +} +#elif defined(__linux__) +/* + * Linux doesn't offer any form of "friendly name", but you can + * determine an interface type to some degree. + */ +static void +add_unix_interface_ifinfo(if_info_t *if_info, const char *name, + const char *description _U_) +{ + char *wireless_path; + ws_statb64 statb; + + /* + * Look for /sys/class/net/{device}/wireless. If it exists, + * it's a wireless interface. + */ + wireless_path = g_strdup_printf("/sys/class/net/%s/wireless", name); + if (wireless_path != NULL) { + if (ws_stat64(wireless_path, &statb) == 0) + if_info->type = IF_WIRELESS; + g_free(wireless_path); + } + if (if_info->type == IF_WIRED) { + /* + * We still don't know what it is. Check for + * Bluetooth and USB devices. + */ + if (strstr(name, "bluetooth") != NULL) { + /* + * XXX - this is for raw Bluetooth capture; what + * about IP-over-Bluetooth devices? + */ + if_info->type = IF_BLUETOOTH; + } else if (strstr(name, "usbmon") != NULL) + if_info->type = IF_USB; + } +} #else -#include "capture_unix_ifnames.h" +/* + * On other UN*Xes, if there is a description, it's a friendly + * name, and there is no vendor description. ("Other UN*Xes" + * currently means "FreeBSD and OpenBSD".) + */ +void +add_unix_interface_ifinfo(if_info_t *if_info, const char *name _U_, + const char *description) +{ + if_info->friendly_name = g_strdup(description); +} #endif if_info_t * @@ -69,8 +242,48 @@ if_info_new(const char *name, const char *description, gboolean loopback) if_info = (if_info_t *)g_malloc(sizeof (if_info_t)); if_info->name = g_strdup(name); + if_info->friendly_name = NULL; /* default - unknown */ + if_info->vendor_description = NULL; + if_info->type = IF_WIRED; /* default */ #ifdef _WIN32 /* + * Get the interface type. + * + * Much digging failed to reveal any obvious way to get something + * such as the SNMP MIB-II ifType value for an interface: + * + * http://www.iana.org/assignments/ianaiftype-mib + * + * by making some NDIS request. And even if there were such + * a way, there's no guarantee that the ifType reflects an + * interface type that a user would view as correct (for + * example, some systems report Wi-Fi interfaces as + * Ethernet interfaces). + * + * So we look for keywords in the vendor's interface + * description. + */ + if (description && (strstr(description, "generic dialup") != NULL || + strstr(description, "PPP/SLIP") != NULL)) { + if_info->type = IF_DIALUP; + } else if (description && (strstr(description, "Wireless") != NULL || + strstr(description,"802.11") != NULL)) { + if_info->type = IF_WIRELESS; + } else if (description && strstr(description, "AirPcap") != NULL || + strstr(name, "airpcap") != NULL) { + if_info->type = IF_AIRPCAP; + } else if (description && strstr(description, "Bluetooth") != NULL ) { + if_info->type = IF_BLUETOOTH; + } else if (description && strstr(description, "VMware") != NULL) { + /* + * Bridge, NAT, or host-only interface on a VMware host. + * + * XXX - what about guest interfaces? + */ + if_info->type = IF_VIRTUAL; + } + + /* * On Windows, the "description" is a vendor description, * and the friendly name isn't returned by WinPcap. * Fetch it ourselves. @@ -110,21 +323,39 @@ if_info_new(const char *name, const char *description, gboolean loopback) /* * On UN*X, if there is a description, it's a friendly * name, and there is no vendor description. - * If there's no description, fetch a friendly name - * if we can; if that fails, then, for a loopback - * interface, give it the friendly name "Loopback". + * + * Try the platform's way of getting a friendly name and + * interface type first. + * + * If that fails, then, for a loopback interface, give it the + * friendly name "Loopback" and, for VMware interfaces, + * give them the type IF_VIRTUAL. */ - if_info->friendly_name = g_strdup(description); + add_unix_interface_ifinfo(if_info, name, description); + if (if_info->type == IF_WIRED) { + /* + * This is the default interface type. + * + * Bridge, NAT, or host-only interfaces on VMWare hosts + * have the name vmnet[0-9]+. Guests might use a native + * (LANCE or E1000) driver or the vmxnet driver. Check + * the name. + */ + if (g_ascii_strncasecmp(name, "vmnet", 5) == 0) + if_info->type = IF_VIRTUAL; + else if (g_ascii_strncasecmp(name, "vmxnet", 6) == 0) + if_info->type = IF_VIRTUAL; + } if (if_info->friendly_name == NULL) { - if_info->friendly_name = get_unix_interface_friendly_name(name); - if (if_info->friendly_name == NULL) { - /* - * If this is a loopback interface, give it a - * "friendly name" of "Loopback". - */ - if (loopback) - if_info->friendly_name = g_strdup("Loopback"); - } + /* + * We couldn't get interface information using platform- + * dependent calls. + * + * If this is a loopback interface, give it a + * "friendly name" of "Loopback". + */ + if (loopback) + if_info->friendly_name = g_strdup("Loopback"); } if_info->vendor_description = NULL; #endif diff --git a/capture_ifinfo.c b/capture_ifinfo.c index 7899b5f7a0..9f24f0e70a 100644 --- a/capture_ifinfo.c +++ b/capture_ifinfo.c @@ -28,6 +28,7 @@ #include <stdlib.h> #include <string.h> +#include <stdio.h> #ifdef HAVE_ARPA_INET_H #include <arpa/inet.h> @@ -141,9 +142,9 @@ capture_interface_list(int *err, char **err_str) g_free(data); for (i = 0; raw_list[i] != NULL; i++) { - if_parts = g_strsplit(raw_list[i], "\t", 5); + if_parts = g_strsplit(raw_list[i], "\t", 6); if (if_parts[0] == NULL || if_parts[1] == NULL || if_parts[2] == NULL || - if_parts[3] == NULL || if_parts[4] == NULL) { + if_parts[3] == NULL || if_parts[4] == NULL || if_parts[5] == NULL) { g_strfreev(if_parts); continue; } @@ -163,7 +164,8 @@ capture_interface_list(int *err, char **err_str) if_info->vendor_description = g_strdup(if_parts[1]); if (strlen(if_parts[2]) > 0) if_info->friendly_name = g_strdup(if_parts[2]); - addr_parts = g_strsplit(if_parts[3], ",", 0); + if_info->type = (interface_type)strtol(if_parts[3], NULL, 10); + addr_parts = g_strsplit(if_parts[4], ",", 0); for (j = 0; addr_parts[j] != NULL; j++) { if_addr = g_new0(if_addr_t,1); if (inet_pton(AF_INET, addr_parts[j], &if_addr->addr.ip4_addr)) { @@ -179,7 +181,7 @@ capture_interface_list(int *err, char **err_str) if_info->addrs = g_slist_append(if_info->addrs, if_addr); } } - if (strcmp(if_parts[4], "loopback") == 0) + if (strcmp(if_parts[5], "loopback") == 0) if_info->loopback = TRUE; g_strfreev(if_parts); g_strfreev(addr_parts); @@ -340,82 +342,4 @@ void add_interface_to_remote_list(if_info_t *if_info) remote_interface_list = g_list_append(remote_interface_list, temp); } #endif - -guint -get_interface_type(gchar *name, gchar *description) -{ -#if defined(__linux__) - ws_statb64 statb; - char *wireless_path; -#endif -#if defined(_WIN32) - /* - * Much digging failed to reveal any obvious way to get something such - * as the SNMP MIB-II ifType value for an interface: - * - * http://www.iana.org/assignments/ianaiftype-mib - * - * by making some NDIS request. - */ - if (description && (strstr(description,"generic dialup") != NULL || - strstr(description,"PPP/SLIP") != NULL )) { - return IF_DIALUP; - } else if (description && (strstr(description,"Wireless") != NULL || - strstr(description,"802.11") != NULL)) { - return IF_WIRELESS; - } else if (description && strstr(description,"AirPcap") != NULL || - strstr(name,"airpcap")) { - return IF_AIRPCAP; - } else if (description && strstr(description, "Bluetooth") != NULL ) { - return IF_BLUETOOTH; - } -#elif defined(__linux__) - /* - * Look for /sys/class/net/{device}/wireless. - */ - wireless_path = g_strdup_printf("/sys/class/net/%s/wireless", name); - if (wireless_path != NULL) { - if (ws_stat64(wireless_path, &statb) == 0) { - g_free(wireless_path); - return IF_WIRELESS; - } - g_free(wireless_path); - } - /* - * Bluetooth devices. - * - * XXX - this is for raw Bluetooth capture; what about IP-over-Bluetooth - * devices? - */ - if ( strstr(name,"bluetooth") != NULL) { - return IF_BLUETOOTH; - } - - /* - * USB devices. - */ - if ( strstr(name,"usbmon") != NULL ) { - return IF_USB; - } -#endif - /* - * Bridge, NAT, or host-only interfaces on VMWare hosts have the name - * vmnet[0-9]+ or VMnet[0-9+ on Windows. Guests might use a native - * (LANCE or E1000) driver or the vmxnet driver. These devices have an - * IFT_ of IFT_ETHER, so we have to check the name. - */ - if ( g_ascii_strncasecmp(name, "vmnet", 5) == 0) { - return IF_VIRTUAL; - } - - if ( g_ascii_strncasecmp(name, "vmxnet", 6) == 0) { - return IF_VIRTUAL; - } - - if (description && strstr(description, "VMware") != NULL ) { - return IF_VIRTUAL; - } - - return IF_WIRED; -} #endif /* HAVE_LIBPCAP */ diff --git a/capture_ifinfo.h b/capture_ifinfo.h index 7802598bef..097d9e10ba 100644 --- a/capture_ifinfo.h +++ b/capture_ifinfo.h @@ -29,6 +29,18 @@ extern "C" { #endif /* __cplusplus */ +typedef enum { + IF_WIRED, + IF_AIRPCAP, + IF_PIPE, + IF_STDIN, + IF_BLUETOOTH, + IF_WIRELESS, + IF_DIALUP, + IF_USB, + IF_VIRTUAL +} interface_type; + /* * The list of interfaces returned by "get_interface_list()" is * a list of these structures. @@ -42,6 +54,7 @@ typedef struct { e.g. "Realtek PCIe GBE Family Controller", or NULL if not available */ GSList *addrs; /* containing address values of if_addr_t */ + interface_type type; /* type of interface */ gboolean loopback; /* TRUE if loopback, FALSE otherwise */ } if_info_t; @@ -103,12 +116,6 @@ void free_if_capabilities(if_capabilities_t *caps); void add_interface_to_remote_list(if_info_t *if_info); -/** - * Get the type of an interface, given its name and description. - */ -extern guint -get_interface_type(gchar *name, gchar *description); - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/capture_opts.h b/capture_opts.h index 67a5bfe349..b6dfa80ece 100644 --- a/capture_opts.h +++ b/capture_opts.h @@ -77,18 +77,6 @@ typedef enum { } capture_sampling; #endif -typedef enum { - IF_WIRED, - IF_AIRPCAP, - IF_PIPE, - IF_STDIN, - IF_BLUETOOTH, - IF_WIRELESS, - IF_DIALUP, - IF_USB, - IF_VIRTUAL -} interface_type; - #ifdef HAVE_PCAP_REMOTE struct remote_host_info { gchar *remote_host; /**< Host name or network address for remote capturing */ diff --git a/capture_unix_ifnames.c b/capture_unix_ifnames.c deleted file mode 100644 index 42d0d7acc7..0000000000 --- a/capture_unix_ifnames.c +++ /dev/null @@ -1,116 +0,0 @@ -/* capture_unix_ifnames.c - * Routines supporting the use of UN*X friendly interface names, if any, - * within Wireshark - * - * $Id$ - * - * Wireshark - Network traffic analyzer - * By Gerald Combs <gerald@wireshark.org> - * 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 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" - -#include <glib.h> - -#include "capture_unix_ifnames.h" - -/* - * Given an interface name, find the "friendly name" for the interface. - */ - -#ifdef __APPLE__ - -#include <CoreFoundation/CoreFoundation.h> -#include <SystemConfiguration/SystemConfiguration.h> - -#include "cfutils.h" - -/* - * On OS X, we do that by getting all the interfaces that the System - * Configuration framework knows about, look for the one with a "BSD - * name" matching the interface name, and, if we find it, return its - * "localized display name", if it has one. - */ -char * -get_unix_interface_friendly_name(const char *ifname) -{ - CFStringRef ifname_CFString; - CFArrayRef interfaces; - CFIndex num_interfaces; - CFIndex i; - SCNetworkInterfaceRef interface; - CFStringRef bsdname_CFString; - CFStringRef friendly_name_CFString; - char *friendly_name = NULL; - - interfaces = SCNetworkInterfaceCopyAll(); - if (interfaces == NULL) { - /* - * Couldn't get a list of interfaces. - */ - return NULL; - } - - ifname_CFString = CFStringCreateWithCString(kCFAllocatorDefault, - ifname, kCFStringEncodingUTF8); - if (ifname_CFString == NULL) { - /* - * Couldn't convert the interface name to a CFString. - */ - CFRelease(interfaces); - return NULL; - } - - num_interfaces = CFArrayGetCount(interfaces); - for (i = 0; i < num_interfaces; i++) { - interface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(interfaces, i); - bsdname_CFString = SCNetworkInterfaceGetBSDName(interface); - if (bsdname_CFString == NULL) { - /* - * This interface has no BSD name, so it's not - * a regular network interface. - */ - continue; - } - if (CFStringCompare(ifname_CFString, bsdname_CFString, 0) == 0) { - /* - * This is the interface. - */ - friendly_name_CFString = SCNetworkInterfaceGetLocalizedDisplayName(interface); - if (friendly_name_CFString != NULL) - friendly_name = CFString_to_C_string(friendly_name_CFString); - break; - } - } - - CFRelease(interfaces); - return friendly_name; -} - -#else /* __APPLE__ */ - -/* - * Nothing supported on other platforms. - */ -char * -get_unix_interface_friendly_name(const char *ifname _U_) -{ - return NULL; -} - -#endif /* __APPLE__ */ diff --git a/capture_unix_ifnames.h b/capture_unix_ifnames.h deleted file mode 100644 index 7e93754078..0000000000 --- a/capture_unix_ifnames.h +++ /dev/null @@ -1,33 +0,0 @@ -/* capture_unix_ifnames.h - * Routines supporting the use of UN*X friendly interface names, if any, - * within Wireshark - * - * $Id$ - * - * Wireshark - Network traffic analyzer - * By Gerald Combs <gerald@wireshark.org> - * Copyright 1998 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 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef CAPTURE_UNIX_IFNAMES_H -#define CAPTURE_UNIX_IFNAMES_H - -/* returns the interface friendly name for a device name; if it is unable to - * resolve the name, NULL is returned */ -char *get_unix_interface_friendly_name(const char *ifname); - -#endif @@ -1294,7 +1294,7 @@ print_machine_readable_interfaces(GList *if_list) for (if_entry = g_list_first(if_list); if_entry != NULL; if_entry = g_list_next(if_entry)) { if_info = (if_info_t *)if_entry->data; - printf("%d. %s", i++, if_info->name); + printf("%d. %s\t", i++, if_info->name); /* * Print the contents of the if_entry struct in a parseable format. @@ -1303,9 +1303,9 @@ print_machine_readable_interfaces(GList *if_list) */ /* XXX - Make sure our description doesn't contain a tab */ if (if_info->vendor_description != NULL) - printf("\t%s\t", if_info->vendor_description); + printf("%s\t", if_info->vendor_description); else - printf("\t\t"); + printf("\t"); /* XXX - Make sure our friendly name doesn't contain a tab */ if (if_info->friendly_name != NULL) @@ -1313,6 +1313,8 @@ print_machine_readable_interfaces(GList *if_list) else printf("\t"); + printf("%u\t", if_info->type); + for (addr = g_slist_nth(if_info->addrs, 0); addr != NULL; addr = g_slist_next(addr)) { if (addr != g_slist_nth(if_info->addrs, 0)) diff --git a/ui/iface_lists.c b/ui/iface_lists.c index bbd8041a69..4483033374 100644 --- a/ui/iface_lists.c +++ b/ui/iface_lists.c @@ -159,7 +159,7 @@ scan_local_interfaces(void) if (prefs_is_capture_device_hidden(if_info->name)) { device.hidden = TRUE; } - device.type = get_interface_type(if_info->name, if_info->vendor_description); + device.type = if_info->type; monitor_mode = prefs_capture_device_monitor_mode(if_info->name); caps = capture_get_if_capabilities(if_info->name, monitor_mode, NULL); for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) { |