1 /* capture_win_ifnames.c
2 * Routines supporting the use of Windows friendly interface names within Wireshark
3 * Copyright 2011-2012, Mike Garratt <wireshark@evn.co.nz>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
42 #ifndef NDIS_IF_MAX_STRING_SIZE
43 #define NDIS_IF_MAX_STRING_SIZE IF_MAX_STRING_SIZE /* =256 in <ifdef.h> */
47 #define NETIO_STATUS DWORD
52 #include "capture_ifinfo.h"
53 #include "capture_win_ifnames.h"
54 #include "wsutil/file_util.h"
56 /**********************************************************************************/
57 gboolean IsWindowsVistaOrLater()
61 SecureZeroMemory(&osvi, sizeof(OSVERSIONINFO));
62 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
64 if(GetVersionEx(&osvi)){
65 return osvi.dwMajorVersion >= 6;
70 /**********************************************************************************/
71 /* Get the Connection Name for the given GUID */
73 GetInterfaceFriendlyNameFromDeviceGuid(__in GUID *guid)
77 WCHAR wName[NDIS_IF_MAX_STRING_SIZE + 1];
79 gboolean fallbackToUnpublishedApi=TRUE;
80 gboolean haveInterfaceFriendlyName=FALSE;
84 /* Load the ip helper api DLL */
85 hIPHlpApi = LoadLibrary(TEXT("iphlpapi.dll"));
86 if (hIPHlpApi == NULL) {
87 /* Load failed - DLL should always be available in XP+*/
91 /* Need to convert an Interface GUID to the interface friendly name (e.g. "Local Area Connection")
92 * The functions required to do this all reside within iphlpapi.dll
93 * - The preferred approach is to use published API functions (Available since Windows Vista)
94 * - We do however fallback to trying undocumented API if the published API is not available (Windows XP/2k3 scenario)
97 if(IsWindowsVistaOrLater()){
98 /* Published API function prototypes (for Windows Vista/Windows Server 2008+) */
99 typedef NETIO_STATUS (WINAPI *ProcAddr_CIG2L) (__in CONST GUID *InterfaceGuid, __out PNET_LUID InterfaceLuid);
100 typedef NETIO_STATUS (WINAPI *ProcAddr_CIL2A) ( __in CONST NET_LUID *InterfaceLuid,__out_ecount(Length) PWSTR InterfaceAlias, __in SIZE_T Length);
102 /* Attempt to do the conversion using Published API functions */
103 ProcAddr_CIG2L proc_ConvertInterfaceGuidToLuid=(ProcAddr_CIG2L) GetProcAddress(hIPHlpApi, "ConvertInterfaceGuidToLuid");
104 if(proc_ConvertInterfaceGuidToLuid!=NULL){
105 ProcAddr_CIL2A Proc_ConvertInterfaceLuidToAlias=(ProcAddr_CIL2A) GetProcAddress(hIPHlpApi, "ConvertInterfaceLuidToAlias");
106 if(Proc_ConvertInterfaceLuidToAlias!=NULL){
107 /* we have our functions ready to go, attempt to convert interface guid->luid->friendlyname */
108 NET_LUID InterfaceLuid;
109 hr = proc_ConvertInterfaceGuidToLuid(guid, &InterfaceLuid);
111 /* guid->luid success */
112 hr = Proc_ConvertInterfaceLuidToAlias(&InterfaceLuid, wName, NDIS_IF_MAX_STRING_SIZE+1);
115 /* luid->friendly name success */
116 haveInterfaceFriendlyName=TRUE; /* success */
118 /* luid->friendly name failed */
119 fallbackToUnpublishedApi=FALSE;
122 fallbackToUnpublishedApi=FALSE;
130 if(fallbackToUnpublishedApi && !haveInterfaceFriendlyName){
131 /* Didn't manage to get the friendly name using published api functions
132 * (most likely cause wireshark is running on Windows XP/Server 2003)
133 * Retry using nhGetInterfaceNameFromGuid (an older unpublished API function) */
134 typedef HRESULT (WINAPI *ProcAddr_nhGINFG) (__in GUID *InterfaceGuid, __out PCWSTR InterfaceAlias, __inout DWORD *LengthAddress, wchar_t *a4, wchar_t *a5);
136 ProcAddr_nhGINFG Proc_nhGetInterfaceNameFromGuid = NULL;
137 Proc_nhGetInterfaceNameFromGuid = (ProcAddr_nhGINFG) GetProcAddress(hIPHlpApi, "NhGetInterfaceNameFromGuid");
138 if (Proc_nhGetInterfaceNameFromGuid!= NULL) {
139 wchar_t *p4=NULL, *p5=NULL;
142 /* testing of nhGetInterfaceNameFromGuid indicates the unpublished API function expects the 3rd parameter
143 * to be the available space in bytes (as compared to wchar's) available in the second parameter buffer
144 * to receive the friendly name (in unicode format) including the space for the nul termination.*/
145 NameSize = sizeof(wName);
147 /* do the guid->friendlyname lookup */
148 status = Proc_nhGetInterfaceNameFromGuid(guid, wName, &NameSize, p4, p5);
151 haveInterfaceFriendlyName=TRUE; /* success */
156 /* we have finished with iphlpapi.dll - release it */
157 FreeLibrary(hIPHlpApi);
159 if(!haveInterfaceFriendlyName){
160 /* failed to get the friendly name, nothing further to do */
164 /* Get the required buffer size, and then convert the string */
165 size=WideCharToMultiByte(CP_UTF8, 0, wName, -1, NULL, 0, NULL, NULL);
166 name=(char *) g_malloc(size);
170 size=WideCharToMultiByte(CP_UTF8, 0, wName, -1, name, size, NULL, NULL);
172 /* bytes written == 0, indicating some form of error*/
179 static int gethexdigit(const char *p)
181 if(*p >= '0' && *p <= '9'){
183 }else if(*p >= 'A' && *p <= 'F'){
184 return *p - 'A' + 0xA;
185 }else if(*p >= 'a' && *p <= 'f'){
186 return *p - 'a' + 0xa;
188 return -1; /* Not a hex digit */
192 static gboolean get8hexdigits(const char *p, DWORD *d)
199 for(i = 0; i < 8; i++){
200 digit = gethexdigit(p++);
202 return FALSE; /* Not a hex digit */
204 val = (val << 4) | digit;
210 static gboolean get4hexdigits(const char *p, WORD *w)
217 for(i = 0; i < 4; i++){
218 digit = gethexdigit(p++);
220 return FALSE; /* Not a hex digit */
222 val = (val << 4) | digit;
228 /**********************************************************************************/
229 /* returns the interface friendly name for a device name, if it is unable to
230 * resolve the name, "" is returned */
232 get_windows_interface_friendly_name(/* IN */ char *interface_devicename)
234 const char* guid_text;
239 /* ensure we can return a result */
240 if(interface_friendlyname==NULL){
243 /* start on the basis we know nothing */
244 interface_friendlyname=NULL;
246 /* Extract the guid text from the interface device name */
247 if(strncmp("\\Device\\NPF_", interface_devicename, 12)==0){
248 guid_text=interface_devicename+12; /* skip over the '\Device\NPF_' prefix, assume the rest is the guid text */
250 guid_text=interface_devicename;
254 * If what follows is a GUID in {}, then convert it to a GUID structure
255 * and use that to look up the interface to get its friendly name.
257 if(*guid_text != '{'){
258 return NULL; /* Nope, not enclosed in {} */
261 /* There must be 8 hex digits; if so, they go into guid.Data1 */
262 if(!get8hexdigits(guid_text, &guid.Data1)){
263 return NULL; /* nope, not 8 hex digits */
266 /* Now there must be a hyphen */
267 if(*guid_text != '-'){
268 return NULL; /* Nope */
271 /* There must be 4 hex digits; if so, they go into guid.Data2 */
272 if(!get4hexdigits(guid_text, &guid.Data2)){
273 return NULL; /* nope, not 4 hex digits */
276 /* Now there must be a hyphen */
277 if(*guid_text != '-'){
278 return NULL; /* Nope */
281 /* There must be 4 hex digits; if so, they go into guid.Data3 */
282 if(!get4hexdigits(guid_text, &guid.Data3)){
283 return NULL; /* nope, not 4 hex digits */
286 /* Now there must be a hyphen */
287 if(*guid_text != '-'){
288 return NULL; /* Nope */
292 * There must be 4 hex digits; if so, they go into the first 2 bytes
295 for(i = 0; i < 2; i++){
296 digit1 = gethexdigit(guid_text);
298 return NULL; /* Not a hex digit */
301 digit2 = gethexdigit(guid_text);
303 return NULL; /* Not a hex digit */
306 guid.Data4[i] = (digit1 << 4)|(digit2);
308 /* Now there must be a hyphen */
309 if(*guid_text != '-'){
310 return NULL; /* Nope */
314 * There must be 12 hex digits; if so,t hey go into the next 6 bytes
317 for(i = 0; i < 6; i++){
318 digit1 = gethexdigit(guid_text);
320 return NULL; /* Not a hex digit */
323 digit2 = gethexdigit(guid_text);
325 return NULL; /* Not a hex digit */
328 guid.Data4[i+2] = (digit1 << 4)|(digit2);
330 /* Now there must be a closing } */
331 if(*guid_text != '}'){
332 return NULL; /* Nope */
335 /* And that must be the end of the string */
336 if(*guid_text != '\0'){
337 return NULL; /* Nope */
340 /* guid okay, get the interface friendly name associated with the guid */
341 return GetInterfaceFriendlyNameFromDeviceGuid(&guid);
344 /**************************************************************************************/