diff --git a/capture-pcap-util.c b/capture-pcap-util.c index e1ce888695..7e843220b1 100644 --- a/capture-pcap-util.c +++ b/capture-pcap-util.c @@ -62,6 +62,10 @@ if_info_t * if_info_new(const char *name, const char *description, gboolean loopback) { if_info_t *if_info; +#ifdef _WIN32 + const char *guid_text; + GUID guid; +#endif if_info = (if_info_t *)g_malloc(sizeof (if_info_t)); if_info->name = g_strdup(name); @@ -71,8 +75,37 @@ if_info_new(const char *name, const char *description, gboolean loopback) * and the friendly name isn't returned by WinPcap. * Fetch it ourselves. */ - if_info->friendly_name = get_windows_interface_friendly_name(name); - if_info->vendor_description = g_strdup(description); + + /* + * Skip over the "\Device\NPF_" prefix in the device name, + * if present. + */ + if (strncmp("\\Device\\NPF_", name, 12) == 0) + guid_text = name + 12; + else + guid_text = name; + + /* Now try to parse what remains as a GUID. */ + if (parse_as_guid(guid_text, &guid)) { + /* + * Success. Try to get a friendly name using the GUID. + * As this is a regular interface, the description is a + * vendor description. + */ + if_info->friendly_name = get_interface_friendly_name_from_device_guid(&guid); + if_info->vendor_description = g_strdup(description); + } else { + /* + * This is probably not a regular interface; we only + * support NT 5 (W2K) and later, so all regular interfaces + * should have GUIDs at the end of the name. Therefore, + * the description, if supplied, is a friendly name + * provided by WinPcap, and there is no vendor + * description. + */ + if_info->friendly_name = g_strdup(description); + if_info->description = NULL; + } #else /* * On UN*X, if there is a description, it's a friendly diff --git a/capture_win_ifnames.c b/capture_win_ifnames.c index 1e4aac497a..a20945cc80 100644 --- a/capture_win_ifnames.c +++ b/capture_win_ifnames.c @@ -53,6 +53,151 @@ #include "capture_win_ifnames.h" #include "wsutil/file_util.h" +static int gethexdigit(const char *p) +{ + if(*p >= '0' && *p <= '9'){ + return *p - '0'; + }else if(*p >= 'A' && *p <= 'F'){ + return *p - 'A' + 0xA; + }else if(*p >= 'a' && *p <= 'f'){ + return *p - 'a' + 0xa; + }else{ + return -1; /* Not a hex digit */ + } +} + +static gboolean get8hexdigits(const char *p, DWORD *d) +{ + int digit; + DWORD val; + int i; + + val = 0; + for(i = 0; i < 8; i++){ + digit = gethexdigit(p++); + if(digit == -1){ + return FALSE; /* Not a hex digit */ + } + val = (val << 4) | digit; + } + *d = val; + return TRUE; +} + +static gboolean get4hexdigits(const char *p, WORD *w) +{ + int digit; + WORD val; + int i; + + val = 0; + for(i = 0; i < 4; i++){ + digit = gethexdigit(p++); + if(digit == -1){ + return FALSE; /* Not a hex digit */ + } + val = (val << 4) | digit; + } + *w = val; + return TRUE; +} + +/* + * If a string is a GUID in {}, fill in a GUID structure with the GUID + * value and return TRUE; otherwise, if the string is not a valid GUID + * in {}, return FALSE. + */ +gboolean +parse_as_guid(const char *guid_text, GUID *guid) +{ + int i; + int digit1, digit2; + + if(*guid_text != '{'){ + return FALSE; /* Nope, not enclosed in {} */ + } + guid_text++; + /* There must be 8 hex digits; if so, they go into guid->Data1 */ + if(!get8hexdigits(guid_text, &guid->Data1)){ + return FALSE; /* nope, not 8 hex digits */ + } + guid_text += 8; + /* Now there must be a hyphen */ + if(*guid_text != '-'){ + return FALSE; /* Nope */ + } + guid_text++; + /* There must be 4 hex digits; if so, they go into guid->Data2 */ + if(!get4hexdigits(guid_text, &guid->Data2)){ + return FALSE; /* nope, not 4 hex digits */ + } + guid_text += 4; + /* Now there must be a hyphen */ + if(*guid_text != '-'){ + return FALSE; /* Nope */ + } + guid_text++; + /* There must be 4 hex digits; if so, they go into guid->Data3 */ + if(!get4hexdigits(guid_text, &guid->Data3)){ + return FALSE; /* nope, not 4 hex digits */ + } + guid_text += 4; + /* Now there must be a hyphen */ + if(*guid_text != '-'){ + return FALSE; /* Nope */ + } + guid_text++; + /* + * There must be 4 hex digits; if so, they go into the first 2 bytes + * of guid->Data4. + */ + for(i = 0; i < 2; i++){ + digit1 = gethexdigit(guid_text); + if(digit1 == -1){ + return FALSE; /* Not a hex digit */ + } + guid_text++; + digit2 = gethexdigit(guid_text); + if(digit2 == -1){ + return FALSE; /* Not a hex digit */ + } + guid_text++; + guid->Data4[i] = (digit1 << 4)|(digit2); + } + /* Now there must be a hyphen */ + if(*guid_text != '-'){ + return FALSE; /* Nope */ + } + guid_text++; + /* + * There must be 12 hex digits; if so,t hey go into the next 6 bytes + * of guid->Data4. + */ + for(i = 0; i < 6; i++){ + digit1 = gethexdigit(guid_text); + if(digit1 == -1){ + return FALSE; /* Not a hex digit */ + } + guid_text++; + digit2 = gethexdigit(guid_text); + if(digit2 == -1){ + return FALSE; /* Not a hex digit */ + } + guid_text++; + guid->Data4[i+2] = (digit1 << 4)|(digit2); + } + /* Now there must be a closing } */ + if(*guid_text != '}'){ + return FALSE; /* Nope */ + } + guid_text++; + /* And that must be the end of the string */ + if(*guid_text != '\0'){ + return FALSE; /* Nope */ + } + return TRUE; +} + /**********************************************************************************/ gboolean IsWindowsVistaOrLater() { @@ -68,9 +213,9 @@ gboolean IsWindowsVistaOrLater() } /**********************************************************************************/ -/* Get the Connection Name for the given GUID */ -static char * -GetInterfaceFriendlyNameFromDeviceGuid(__in GUID *guid) +/* Get the friendly name for the given GUID */ +char * +get_interface_friendly_name_from_device_guid(__in GUID *guid) { HMODULE hIPHlpApi; HRESULT status; @@ -161,7 +306,8 @@ GetInterfaceFriendlyNameFromDeviceGuid(__in GUID *guid) return NULL; } - /* Get the required buffer size, and then convert the string */ + /* Get the required buffer size, and then convert the string + * from UTF-16 to UTF-8. */ size=WideCharToMultiByte(CP_UTF8, 0, wName, -1, NULL, 0, NULL, NULL); name=(char *) g_malloc(size); if (name == NULL){ @@ -176,65 +322,18 @@ GetInterfaceFriendlyNameFromDeviceGuid(__in GUID *guid) return name; } -static int gethexdigit(const char *p) -{ - if(*p >= '0' && *p <= '9'){ - return *p - '0'; - }else if(*p >= 'A' && *p <= 'F'){ - return *p - 'A' + 0xA; - }else if(*p >= 'a' && *p <= 'f'){ - return *p - 'a' + 0xa; - }else{ - return -1; /* Not a hex digit */ - } -} - -static gboolean get8hexdigits(const char *p, DWORD *d) -{ - int digit; - DWORD val; - int i; - - val = 0; - for(i = 0; i < 8; i++){ - digit = gethexdigit(p++); - if(digit == -1){ - return FALSE; /* Not a hex digit */ - } - val = (val << 4) | digit; - } - *d = val; - return TRUE; -} - -static gboolean get4hexdigits(const char *p, WORD *w) -{ - int digit; - WORD val; - int i; - - val = 0; - for(i = 0; i < 4; i++){ - digit = gethexdigit(p++); - if(digit == -1){ - return FALSE; /* Not a hex digit */ - } - val = (val << 4) | digit; - } - *w = val; - return TRUE; -} - -/**********************************************************************************/ -/* returns the interface friendly name for a device name, if it is unable to -* resolve the name, "" is returned */ +/* + * Given an interface name, try to extract the GUID from it and parse it. + * If that fails, return NULL; if that succeeds, attempt to get the + * friendly name for the interface in question. If that fails, return + * NULL, otherwise return the friendly name, allocated with g_malloc() + * (so that it must be freed with g_free()). + */ char * -get_windows_interface_friendly_name(/* IN */ const char *interface_devicename) +get_windows_interface_friendly_name(const char *interface_devicename) { const char* guid_text; GUID guid; - int i; - int digit1, digit2; /* Extract the guid text from the interface device name */ if(strncmp("\\Device\\NPF_", interface_devicename, 12)==0){ @@ -243,95 +342,12 @@ get_windows_interface_friendly_name(/* IN */ const char *interface_devicename) guid_text=interface_devicename; } - /* - * If what follows is a GUID in {}, then convert it to a GUID structure - * and use that to look up the interface to get its friendly name. - */ - if(*guid_text != '{'){ - return NULL; /* Nope, not enclosed in {} */ - } - guid_text++; - /* There must be 8 hex digits; if so, they go into guid.Data1 */ - if(!get8hexdigits(guid_text, &guid.Data1)){ - return NULL; /* nope, not 8 hex digits */ - } - guid_text += 8; - /* Now there must be a hyphen */ - if(*guid_text != '-'){ - return NULL; /* Nope */ - } - guid_text++; - /* There must be 4 hex digits; if so, they go into guid.Data2 */ - if(!get4hexdigits(guid_text, &guid.Data2)){ - return NULL; /* nope, not 4 hex digits */ - } - guid_text += 4; - /* Now there must be a hyphen */ - if(*guid_text != '-'){ - return NULL; /* Nope */ - } - guid_text++; - /* There must be 4 hex digits; if so, they go into guid.Data3 */ - if(!get4hexdigits(guid_text, &guid.Data3)){ - return NULL; /* nope, not 4 hex digits */ - } - guid_text += 4; - /* Now there must be a hyphen */ - if(*guid_text != '-'){ - return NULL; /* Nope */ - } - guid_text++; - /* - * There must be 4 hex digits; if so, they go into the first 2 bytes - * of guid.Data4. - */ - for(i = 0; i < 2; i++){ - digit1 = gethexdigit(guid_text); - if(digit1 == -1){ - return NULL; /* Not a hex digit */ - } - guid_text++; - digit2 = gethexdigit(guid_text); - if(digit2 == -1){ - return NULL; /* Not a hex digit */ - } - guid_text++; - guid.Data4[i] = (digit1 << 4)|(digit2); - } - /* Now there must be a hyphen */ - if(*guid_text != '-'){ - return NULL; /* Nope */ - } - guid_text++; - /* - * There must be 12 hex digits; if so,t hey go into the next 6 bytes - * of guid.Data4. - */ - for(i = 0; i < 6; i++){ - digit1 = gethexdigit(guid_text); - if(digit1 == -1){ - return NULL; /* Not a hex digit */ - } - guid_text++; - digit2 = gethexdigit(guid_text); - if(digit2 == -1){ - return NULL; /* Not a hex digit */ - } - guid_text++; - guid.Data4[i+2] = (digit1 << 4)|(digit2); - } - /* Now there must be a closing } */ - if(*guid_text != '}'){ - return NULL; /* Nope */ - } - guid_text++; - /* And that must be the end of the string */ - if(*guid_text != '\0'){ - return NULL; /* Nope */ + if (!parse_as_guid(guid_text, &guid)){ + return NULL; /* not a GUID, so no friendly name */ } /* guid okay, get the interface friendly name associated with the guid */ - return GetInterfaceFriendlyNameFromDeviceGuid(&guid); + return get_interface_friendly_name_from_device_guid(&guid); } /**************************************************************************************/ diff --git a/capture_win_ifnames.h b/capture_win_ifnames.h index 564c4d14a1..513ac74296 100644 --- a/capture_win_ifnames.h +++ b/capture_win_ifnames.h @@ -26,6 +26,23 @@ #ifndef CAPTURE_WIN_IFNAMES_H #define CAPTURE_WIN_IFNAMES_H -char *get_windows_interface_friendly_name(/* IN */ const char *interface_devicename); +/* + * If a string is a GUID in {}, fill in a GUID structure with the GUID + * value and return TRUE; otherwise, if the string is not a valid GUID + * in {}, return FALSE. + */ +extern gboolean parse_as_guid(const char *guid_text, GUID *guid); + +/* Get the friendly name for the given GUID */ +extern char *get_interface_friendly_name_from_device_guid(GUID *guid); + +/* + * Given an interface name, try to extract the GUID from it and parse it. + * If that fails, return NULL; if that succeeds, attempt to get the + * friendly name for the interface in question. If that fails, return + * NULL, otherwise return the friendly name, allocated with g_malloc() + * (so that it must be freed with g_free()). + */ +extern char *get_windows_interface_friendly_name(const char *interface_devicename); #endif