aboutsummaryrefslogtreecommitdiffstats
path: root/capture_win_ifnames.c
diff options
context:
space:
mode:
Diffstat (limited to 'capture_win_ifnames.c')
-rw-r--r--capture_win_ifnames.c319
1 files changed, 319 insertions, 0 deletions
diff --git a/capture_win_ifnames.c b/capture_win_ifnames.c
new file mode 100644
index 0000000000..d4b5ad0d03
--- /dev/null
+++ b/capture_win_ifnames.c
@@ -0,0 +1,319 @@
+/* capture_win_ifnames.c
+* Routines supporting the use of Windows friendly interface names within Wireshark
+* Copyright 2011-2012, Mike Garratt <wireshark@evn.co.nz>
+*
+* $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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#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 <iphlpapi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <wtap.h>
+#include <libpcap.h>
+#include <glib.h>
+
+#include <ntddndis.h>
+
+#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")
+
+/**********************************************************************************/
+gboolean IsWindowsVistaOrLater()
+{
+ OSVERSIONINFO osvi;
+
+ SecureZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ if(GetVersionEx(&osvi)){
+ 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);
+
+}
+
+#define g_log ifnames_log
+/**********************************************************************************/
+/* Get the Connection Name for the given GUID */
+static int GetInterfaceFriendlyNameFromDeviceGuid(__in GUID *guid, __out char **Name)
+{
+ HMODULE hIPHlpApi;
+ HRESULT status;
+ WCHAR wName[NDIS_IF_MAX_STRING_SIZE + 1];
+ HRESULT hr;
+ gboolean fallbackToUnpublishedApi=TRUE;
+ gboolean haveInterfaceFriendlyName=FALSE;
+
+ /* check we have a parameter */
+ if(Name==NULL){
+ return -1;
+ }
+
+ /* 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;
+ }
+
+ 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)
+ * - We do however fallback to trying undocumented API if the published API is not available (Windows XP/2k3 scenario)
+ */
+
+ if(IsWindowsVistaOrLater()){
+ /* Published API function prototypes (for Windows Vista/Windows Server 2008+) */
+ typedef NETIO_STATUS (WINAPI *ProcAddr_CIG2L) (__in CONST GUID *InterfaceGuid, __out PNET_LUID InterfaceLuid);
+ typedef NETIO_STATUS (WINAPI *ProcAddr_CIL2A) ( __in CONST NET_LUID *InterfaceLuid,__out_ecount(Length) PWSTR InterfaceAlias, __in SIZE_T Length);
+
+ /* Attempt to do the conversion using Published API functions */
+ ProcAddr_CIG2L proc_ConvertInterfaceGuidToLuid=(ProcAddr_CIG2L) GetProcAddress(hIPHlpApi, "ConvertInterfaceGuidToLuid");
+ if(proc_ConvertInterfaceGuidToLuid!=NULL){
+ ProcAddr_CIL2A Proc_ConvertInterfaceLuidToAlias=(ProcAddr_CIL2A) GetProcAddress(hIPHlpApi, "ConvertInterfaceLuidToAlias");
+ if(Proc_ConvertInterfaceLuidToAlias!=NULL){
+ /* we have our functions ready to go, attempt to convert interface guid->luid->friendlyname */
+ NET_LUID InterfaceLuid;
+ hr = proc_ConvertInterfaceGuidToLuid(guid, &InterfaceLuid);
+ if(hr==NO_ERROR){
+ /* guid->luid success */
+ hr = Proc_ConvertInterfaceLuidToAlias(&InterfaceLuid, wName, NDIS_IF_MAX_STRING_SIZE+1);
+
+ 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());
+ }
+ }
+
+
+ if(fallbackToUnpublishedApi && !haveInterfaceFriendlyName){
+ /* Didn't manage to get the friendly name using published api functions
+ * (most likely cause wireshark is running on Windows XP/Server 2003)
+ * Retry using nhGetInterfaceNameFromGuid (an older unpublished API function) */
+ typedef HRESULT (WINAPI *ProcAddr_nhGINFG) (__in GUID *InterfaceGuid, __out PCWSTR InterfaceAlias, __inout DWORD *LengthAddress, wchar_t *a4, wchar_t *a5);
+
+ ProcAddr_nhGINFG Proc_nhGetInterfaceNameFromGuid = NULL;
+ Proc_nhGetInterfaceNameFromGuid = (ProcAddr_nhGINFG) GetProcAddress(hIPHlpApi, "NhGetInterfaceNameFromGuid");
+ if (Proc_nhGetInterfaceNameFromGuid!= NULL) {
+ 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.*/
+ NameSize = sizeof(wName);
+
+ /* 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 */
+ FreeLibrary(hIPHlpApi);
+
+ if(!haveInterfaceFriendlyName){
+ /* failed to get the friendly name, nothing further to do */
+ return -1;
+ }
+
+ /* 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;
+ }
+ return 0;
+}
+
+
+/**********************************************************************************/
+/* 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)
+{
+ 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_DEBUG, "open_raw_pipe sdfsd");
+ fflush(stderr);
+ fflush(stdout);
+ 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 */
+ }else{
+ guid_text=interface_devicename;
+ }
+
+ /*** Convert the guid text the GUID structure */
+ {
+ /* Part 1: guid_text to unicode, dynamically allocating sufficent memory for conversion*/
+ 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 unicode conversion failed */
+ 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: unicode guid text to GUID structure */
+ hr = CLSIDFromString(wGuidText, (LPCLSID)&guid);
+ if (hr != S_OK){
+ /* guid text to unicode conversion failed */
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_ERROR,
+ "Failed to convert interface devicename guid to GUID structure, convert result=0x%08x, guid input ='%s', LastErrorCode=0x%08x.",
+ hr, guid_text, GetLastError());
+ return;
+ }
+ }
+
+ /* guid okay, get the interface friendly name associated with the guid */
+ {
+ int r=GetInterfaceFriendlyNameFromDeviceGuid(&guid, interface_friendlyname);
+ if(r!=NO_ERROR){
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_ERROR,
+ "Failed to retrieve interface friendly name associated with interface '%s', LastErrorCode=0x%08x.",
+ interface_devicename, GetLastError());
+ *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;
+}
+
+#undef g_log
+
+/**************************************************************************************/
+#endif
+