* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#if 0 /* XXX: including config.h causes compilation errors; TBD: why */
#include "config.h"
-#endif
#ifdef _WIN32
-#include <windows.h>
-#include <objbase.h> /* for CLSIDFromString() to convert guid text to a GUID */
-#include <tchar.h>
#include <winsock2.h>
+#include <windows.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <ntddndis.h>
+#ifndef NDIS_IF_MAX_STRING_SIZE
+#define NDIS_IF_MAX_STRING_SIZE IF_MAX_STRING_SIZE /* =256 in <ifdef.h> */
+#endif
+
+#ifndef NETIO_STATUS
+#define NETIO_STATUS DWORD
+#endif
+
#include "log.h"
#include "capture_ifinfo.h"
#include "capture_win_ifnames.h"
#include "wsutil/file_util.h"
-/* Link with ole32.lib - provides CLSIDFromString() to convert guid text to a GUID */
-#pragma comment(lib, "ole32.lib")
+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()
{
+#if (_MSC_VER >= 1800)
+ /*
+ * On VS2103, GetVersionEx is deprecated. Microsoft recommend to
+ * use VerifyVersionInfo instead
+ */
+ OSVERSIONINFOEX osvi;
+ DWORDLONG dwlConditionMask = 0;
+ int op = VER_GREATER_EQUAL;
+
+ SecureZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ osvi.dwMajorVersion = 6;
+ VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op);
+ return VerifyVersionInfo(&osvi, VER_MAJORVERSION, dwlConditionMask);
+#else
OSVERSIONINFO osvi;
SecureZeroMemory(&osvi, sizeof(OSVERSIONINFO));
return osvi.dwMajorVersion >= 6;
}
return FALSE;
-}
-/**********************************************************************************/
-/* The wireshark gui doesn't appear at this stage to support having logging messages
-* returned using g_log() before the interface list.
-* Below is a generic logging function that can be easily ripped out or configured to
-* redirect to g_log() if the behaviour changes in the future.
-*/
-static void ifnames_log(const gchar *log_domain, GLogLevelFlags log_level, const gchar *format, ...)
-{
- char buf[16384];
- va_list args;
-
- if(log_level!=G_LOG_LEVEL_ERROR){
- return;
- }
-
- va_start(args, format);
- vsnprintf(buf, 16383, format, args);
- va_end(args);
-
- fprintf(stderr,"%s\r\n",buf);
-
+#endif
}
-#define g_log ifnames_log
/**********************************************************************************/
-/* Get the Connection Name for the given GUID */
-static int GetInterfaceFriendlyNameFromDeviceGuid(__in GUID *guid, __out char **Name)
+/* Get the friendly name for the given GUID */
+char *
+get_interface_friendly_name_from_device_guid(__in GUID *guid)
{
HMODULE hIPHlpApi;
HRESULT status;
HRESULT hr;
gboolean fallbackToUnpublishedApi=TRUE;
gboolean haveInterfaceFriendlyName=FALSE;
-
- /* check we have a parameter */
- if(Name==NULL){
- return -1;
- }
+ int size;
+ char *name;
/* Load the ip helper api DLL */
hIPHlpApi = LoadLibrary(TEXT("iphlpapi.dll"));
if (hIPHlpApi == NULL) {
/* Load failed - DLL should always be available in XP+*/
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_ERROR,
- "Failed to load iphlpapi.dll library for interface name lookups, errorcode=0x%08x\n", GetLastError());
- return -1;
+ return NULL;
}
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Loaded iphlpapi.dll library for interface friendly name lookups");
-
/* Need to convert an Interface GUID to the interface friendly name (e.g. "Local Area Connection")
* The functions required to do this all reside within iphlpapi.dll
* - The preferred approach is to use published API functions (Available since Windows Vista)
if(hr==NO_ERROR){
/* luid->friendly name success */
haveInterfaceFriendlyName=TRUE; /* success */
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
- "converted interface guid to friendly name.");
}else{
/* luid->friendly name failed */
fallbackToUnpublishedApi=FALSE;
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE,
- "ConvertInterfaceLuidToAlias failed to convert interface luid to a friendly name, LastErrorCode=0x%08x.", GetLastError());
}
}else{
fallbackToUnpublishedApi=FALSE;
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE,
- "ConvertInterfaceGuidToLuid failed to convert interface guid to a luid, LastErrorCode=0x%08x.", GetLastError());
}
- }else{
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_ERROR,
- "Failed to find address of ConvertInterfaceLuidToAlias in iphlpapi.dll, LastErrorCode=0x%08x.", GetLastError());
}
- }else{
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_ERROR,
- "Failed to find address of ConvertInterfaceGuidToLuid in iphlpapi.dll, LastErrorCode=0x%08x.", GetLastError());
}
}
wchar_t *p4=NULL, *p5=NULL;
DWORD NameSize;
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
- "Unpublished NhGetInterfaceNameFromGuid function located in iphlpapi.dll, looking up friendly name from guid");
-
/* testing of nhGetInterfaceNameFromGuid indicates the unpublished API function expects the 3rd parameter
* to be the available space in bytes (as compared to wchar's) available in the second parameter buffer
* to receive the friendly name (in unicode format) including the space for the nul termination.*/
/* do the guid->friendlyname lookup */
status = Proc_nhGetInterfaceNameFromGuid(guid, wName, &NameSize, p4, p5);
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
- "nhGetInterfaceNameFromGuidProc status =%d, p4=%d, p5=%d, namesize=%d\n", status, (int)p4, (int)p5, NameSize);
if(status==0){
haveInterfaceFriendlyName=TRUE; /* success */
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
- "Converted interface guid to friendly name.");
}
-
- }else{
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_ERROR,
- "Failed to locate unpublished NhGetInterfaceNameFromGuid function located in iphlpapi.dll, "
- "for looking up interface friendly name, LastErrorCode=0x%08x.", GetLastError());
}
-
}
/* we have finished with iphlpapi.dll - release it */
if(!haveInterfaceFriendlyName){
/* failed to get the friendly name, nothing further to do */
- return -1;
+ return NULL;
}
- /* Get the required buffer size, and then convert the string */
- {
- int size = WideCharToMultiByte(CP_UTF8, 0, wName, -1, NULL, 0, NULL, NULL);
- char *name = (char *) g_malloc(size);
- if (name == NULL){
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_ERROR,
- "Failed to allocate memory to convert format of interface friendly name, LastErrorCode=0x%08x.", GetLastError());
- return -1;
- }
- size=WideCharToMultiByte(CP_UTF8, 0, wName, -1, name, size, NULL, NULL);
- if(size==0){
- /* bytes written == 0, indicating some form of error*/
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_ERROR,
- "Error converting format of interface friendly name, LastErrorCode=0x%08x.", GetLastError());
- g_free(name);
- return -1;
- }
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Friendly name is '%s'", name);
-
- *Name = name;
+ /* 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){
+ return NULL;
}
- return 0;
+ size=WideCharToMultiByte(CP_UTF8, 0, wName, -1, name, size, NULL, NULL);
+ if(size==0){
+ /* bytes written == 0, indicating some form of error*/
+ g_free(name);
+ return NULL;
+ }
+ return name;
}
-
-/**********************************************************************************/
-/* returns the interface friendly name for a device name, if it is unable to
-* resolve the name, "" is returned */
-void get_windows_interface_friendlyname(/* IN */ char *interface_devicename, /* OUT */char **interface_friendlyname)
+/*
+ * 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(const char *interface_devicename)
{
const char* guid_text;
GUID guid;
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "test, 1,2,3");
-
- /* ensure we can return a result */
- if(interface_friendlyname==NULL){
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_ERROR,
- "invalid interface_friendlyname parameter to get_windows_interface_friendlyname() function.");
- return;
- }
- /* start on the basis we know nothing */
- *interface_friendlyname=NULL;
-
/* Extract the guid text from the interface device name */
if(strncmp("\\Device\\NPF_", interface_devicename, 12)==0){
guid_text=interface_devicename+12; /* skip over the '\Device\NPF_' prefix, assume the rest is the guid text */
guid_text=interface_devicename;
}
- /*** Convert the GUID text to a GUID structure */
- {
- /* Part 1: (presumed) ASCII guid_text to UTF-16 */
- WCHAR wGuidText[39];
- HRESULT hr;
- int size=39; /* a guid should always been 38 unicode characters in length (+1 for null termination) */
- size=MultiByteToWideChar(CP_ACP, 0, guid_text, -1, wGuidText, size);
- if(size!=39){
- /*
- * GUID text to UTF-16 conversion failed.
- * XXX - is this assuming the GUID text is in the local
- * code page? If so, the error might just indicate that
- * it's not in the local code page; should we assume it's
- * UTF-8? If so, what if it's not *valid* UTF-8? Should
- * we just silently return "no friendly name" if this
- * fails?
- */
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_ERROR,
- "Failed the extract guid from interface devicename, unicode convert result=%d, guid input ='%s', LastErrorCode=0x%08x.",
- size, guid_text, GetLastError());
- return;
- }
- /* Part 2: UTF-16 GUID text to GUID structure */
- hr = CLSIDFromString(wGuidText, (LPCLSID)&guid);
- if (hr != S_OK){
- /*
- * GUID text to CLSID conversion failed; this probably
- * means that there isn't a GUID in the name, in which
- * case we can't get a friendly name for that name.
- *
- * Don't complain - this isn't an error; not all
- * interface names correspond to interfaces with GUIDs.
- */
- return;
- }
+ 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 */
- {
- int r=GetInterfaceFriendlyNameFromDeviceGuid(&guid, interface_friendlyname);
- if(r!=NO_ERROR){
- /* A message has been logged by GetInterfaceFriendlyNameFromDeviceGuid() */
- *interface_friendlyname=NULL; /* failed to get friendly name, ensure the ultimate result is NULL */
- return;
- }
- }
-
- /* success */
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE,
- "\nInterface %s => '%s'\n\n\n", interface_devicename, *interface_friendlyname);
-
- return;
+ return get_interface_friendly_name_from_device_guid(&guid);
}
-#undef g_log
-
/**************************************************************************************/
#endif