16d49e1aeSJan Lentfer /*
26d49e1aeSJan Lentfer  * win_if_list - Display network interfaces with description (for Windows)
36d49e1aeSJan Lentfer  * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer  *
5*3ff40c12SJohn Marino  * This software may be distributed under the terms of the BSD license.
6*3ff40c12SJohn Marino  * See README for more details.
76d49e1aeSJan Lentfer  *
86d49e1aeSJan Lentfer  * This small tool is for the Windows build to provide an easy way of fetching
96d49e1aeSJan Lentfer  * a list of available network interfaces.
106d49e1aeSJan Lentfer  */
116d49e1aeSJan Lentfer 
126d49e1aeSJan Lentfer #include "includes.h"
136d49e1aeSJan Lentfer #include <stdio.h>
146d49e1aeSJan Lentfer #ifdef CONFIG_USE_NDISUIO
156d49e1aeSJan Lentfer #include <winsock2.h>
166d49e1aeSJan Lentfer #include <ntddndis.h>
176d49e1aeSJan Lentfer #else /* CONFIG_USE_NDISUIO */
186d49e1aeSJan Lentfer #include "pcap.h"
196d49e1aeSJan Lentfer #include <winsock.h>
206d49e1aeSJan Lentfer #endif /* CONFIG_USE_NDISUIO */
216d49e1aeSJan Lentfer 
226d49e1aeSJan Lentfer #ifdef CONFIG_USE_NDISUIO
236d49e1aeSJan Lentfer 
246d49e1aeSJan Lentfer /* from nuiouser.h */
256d49e1aeSJan Lentfer #define FSCTL_NDISUIO_BASE      FILE_DEVICE_NETWORK
266d49e1aeSJan Lentfer 
276d49e1aeSJan Lentfer #define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \
286d49e1aeSJan Lentfer 	CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access)
296d49e1aeSJan Lentfer 
306d49e1aeSJan Lentfer #define IOCTL_NDISUIO_QUERY_BINDING \
316d49e1aeSJan Lentfer 	_NDISUIO_CTL_CODE(0x203, METHOD_BUFFERED, \
326d49e1aeSJan Lentfer 			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
336d49e1aeSJan Lentfer 
346d49e1aeSJan Lentfer #define IOCTL_NDISUIO_BIND_WAIT \
356d49e1aeSJan Lentfer 	_NDISUIO_CTL_CODE(0x204, METHOD_BUFFERED, \
366d49e1aeSJan Lentfer 			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
376d49e1aeSJan Lentfer 
386d49e1aeSJan Lentfer typedef struct _NDISUIO_QUERY_BINDING
396d49e1aeSJan Lentfer {
406d49e1aeSJan Lentfer 	ULONG BindingIndex;
416d49e1aeSJan Lentfer 	ULONG DeviceNameOffset;
426d49e1aeSJan Lentfer 	ULONG DeviceNameLength;
436d49e1aeSJan Lentfer 	ULONG DeviceDescrOffset;
446d49e1aeSJan Lentfer 	ULONG DeviceDescrLength;
456d49e1aeSJan Lentfer } NDISUIO_QUERY_BINDING, *PNDISUIO_QUERY_BINDING;
466d49e1aeSJan Lentfer 
476d49e1aeSJan Lentfer 
ndisuio_open(void)486d49e1aeSJan Lentfer static HANDLE ndisuio_open(void)
496d49e1aeSJan Lentfer {
506d49e1aeSJan Lentfer 	DWORD written;
516d49e1aeSJan Lentfer 	HANDLE h;
526d49e1aeSJan Lentfer 
536d49e1aeSJan Lentfer 	h = CreateFile(TEXT("\\\\.\\\\Ndisuio"),
546d49e1aeSJan Lentfer 		       GENERIC_READ | GENERIC_WRITE, 0, NULL,
556d49e1aeSJan Lentfer 		       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
566d49e1aeSJan Lentfer 		       INVALID_HANDLE_VALUE);
576d49e1aeSJan Lentfer 	if (h == INVALID_HANDLE_VALUE)
586d49e1aeSJan Lentfer 		return h;
596d49e1aeSJan Lentfer 
606d49e1aeSJan Lentfer #ifndef _WIN32_WCE
616d49e1aeSJan Lentfer 	if (!DeviceIoControl(h, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, NULL, 0,
626d49e1aeSJan Lentfer 			     &written, NULL)) {
636d49e1aeSJan Lentfer 		printf("IOCTL_NDISUIO_BIND_WAIT failed: %d",
646d49e1aeSJan Lentfer 		       (int) GetLastError());
656d49e1aeSJan Lentfer 		CloseHandle(h);
666d49e1aeSJan Lentfer 		return INVALID_HANDLE_VALUE;
676d49e1aeSJan Lentfer 	}
686d49e1aeSJan Lentfer #endif /* _WIN32_WCE */
696d49e1aeSJan Lentfer 
706d49e1aeSJan Lentfer 	return h;
716d49e1aeSJan Lentfer }
726d49e1aeSJan Lentfer 
736d49e1aeSJan Lentfer 
ndisuio_query_bindings(HANDLE ndisuio)746d49e1aeSJan Lentfer static void ndisuio_query_bindings(HANDLE ndisuio)
756d49e1aeSJan Lentfer {
766d49e1aeSJan Lentfer 	NDISUIO_QUERY_BINDING *b;
776d49e1aeSJan Lentfer 	size_t blen = sizeof(*b) + 1024;
786d49e1aeSJan Lentfer 	int i, error;
796d49e1aeSJan Lentfer 	DWORD written;
806d49e1aeSJan Lentfer 	char name[256], desc[256];
816d49e1aeSJan Lentfer 	WCHAR *pos;
826d49e1aeSJan Lentfer 	size_t j, len;
836d49e1aeSJan Lentfer 
846d49e1aeSJan Lentfer 	b = malloc(blen);
856d49e1aeSJan Lentfer 	if (b == NULL)
866d49e1aeSJan Lentfer 		return;
876d49e1aeSJan Lentfer 
886d49e1aeSJan Lentfer 	for (i = 0; ; i++) {
896d49e1aeSJan Lentfer 		memset(b, 0, blen);
906d49e1aeSJan Lentfer 		b->BindingIndex = i;
916d49e1aeSJan Lentfer 		if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_QUERY_BINDING,
926d49e1aeSJan Lentfer 				     b, sizeof(NDISUIO_QUERY_BINDING), b,
936d49e1aeSJan Lentfer 				     (DWORD) blen, &written, NULL)) {
946d49e1aeSJan Lentfer 			error = (int) GetLastError();
956d49e1aeSJan Lentfer 			if (error == ERROR_NO_MORE_ITEMS)
966d49e1aeSJan Lentfer 				break;
976d49e1aeSJan Lentfer 			printf("IOCTL_NDISUIO_QUERY_BINDING failed: %d",
986d49e1aeSJan Lentfer 			       error);
996d49e1aeSJan Lentfer 			break;
1006d49e1aeSJan Lentfer 		}
1016d49e1aeSJan Lentfer 
1026d49e1aeSJan Lentfer 		pos = (WCHAR *) ((char *) b + b->DeviceNameOffset);
1036d49e1aeSJan Lentfer 		len = b->DeviceNameLength;
1046d49e1aeSJan Lentfer 		if (len >= sizeof(name))
1056d49e1aeSJan Lentfer 			len = sizeof(name) - 1;
1066d49e1aeSJan Lentfer 		for (j = 0; j < len; j++)
1076d49e1aeSJan Lentfer 			name[j] = (char) pos[j];
1086d49e1aeSJan Lentfer 		name[len] = '\0';
1096d49e1aeSJan Lentfer 
1106d49e1aeSJan Lentfer 		pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset);
1116d49e1aeSJan Lentfer 		len = b->DeviceDescrLength;
1126d49e1aeSJan Lentfer 		if (len >= sizeof(desc))
1136d49e1aeSJan Lentfer 			len = sizeof(desc) - 1;
1146d49e1aeSJan Lentfer 		for (j = 0; j < len; j++)
1156d49e1aeSJan Lentfer 			desc[j] = (char) pos[j];
1166d49e1aeSJan Lentfer 		desc[len] = '\0';
1176d49e1aeSJan Lentfer 
1186d49e1aeSJan Lentfer 		printf("ifname: %s\ndescription: %s\n\n", name, desc);
1196d49e1aeSJan Lentfer 	}
1206d49e1aeSJan Lentfer 
1216d49e1aeSJan Lentfer 	free(b);
1226d49e1aeSJan Lentfer }
1236d49e1aeSJan Lentfer 
1246d49e1aeSJan Lentfer 
ndisuio_enum_bindings(void)1256d49e1aeSJan Lentfer static void ndisuio_enum_bindings(void)
1266d49e1aeSJan Lentfer {
1276d49e1aeSJan Lentfer 	HANDLE ndisuio = ndisuio_open();
1286d49e1aeSJan Lentfer 	if (ndisuio == INVALID_HANDLE_VALUE)
1296d49e1aeSJan Lentfer 		return;
1306d49e1aeSJan Lentfer 
1316d49e1aeSJan Lentfer 	ndisuio_query_bindings(ndisuio);
1326d49e1aeSJan Lentfer 	CloseHandle(ndisuio);
1336d49e1aeSJan Lentfer }
1346d49e1aeSJan Lentfer 
1356d49e1aeSJan Lentfer #else /* CONFIG_USE_NDISUIO */
1366d49e1aeSJan Lentfer 
show_dev(pcap_if_t * dev)1376d49e1aeSJan Lentfer static void show_dev(pcap_if_t *dev)
1386d49e1aeSJan Lentfer {
1396d49e1aeSJan Lentfer 	printf("ifname: %s\ndescription: %s\n\n",
1406d49e1aeSJan Lentfer 	       dev->name, dev->description);
1416d49e1aeSJan Lentfer }
1426d49e1aeSJan Lentfer 
1436d49e1aeSJan Lentfer 
pcap_enum_devs(void)1446d49e1aeSJan Lentfer static void pcap_enum_devs(void)
1456d49e1aeSJan Lentfer {
1466d49e1aeSJan Lentfer 	pcap_if_t *devs, *dev;
1476d49e1aeSJan Lentfer 	char err[PCAP_ERRBUF_SIZE + 1];
1486d49e1aeSJan Lentfer 
1496d49e1aeSJan Lentfer 	if (pcap_findalldevs(&devs, err) < 0) {
1506d49e1aeSJan Lentfer 		fprintf(stderr, "Error - pcap_findalldevs: %s\n", err);
1516d49e1aeSJan Lentfer 		return;
1526d49e1aeSJan Lentfer 	}
1536d49e1aeSJan Lentfer 
1546d49e1aeSJan Lentfer 	for (dev = devs; dev; dev = dev->next) {
1556d49e1aeSJan Lentfer 		show_dev(dev);
1566d49e1aeSJan Lentfer 	}
1576d49e1aeSJan Lentfer 
1586d49e1aeSJan Lentfer 	pcap_freealldevs(devs);
1596d49e1aeSJan Lentfer }
1606d49e1aeSJan Lentfer 
1616d49e1aeSJan Lentfer #endif /* CONFIG_USE_NDISUIO */
1626d49e1aeSJan Lentfer 
1636d49e1aeSJan Lentfer 
main(int argc,char * argv[])1646d49e1aeSJan Lentfer int main(int argc, char *argv[])
1656d49e1aeSJan Lentfer {
1666d49e1aeSJan Lentfer #ifdef CONFIG_USE_NDISUIO
1676d49e1aeSJan Lentfer 	ndisuio_enum_bindings();
1686d49e1aeSJan Lentfer #else /* CONFIG_USE_NDISUIO */
1696d49e1aeSJan Lentfer 	pcap_enum_devs();
1706d49e1aeSJan Lentfer #endif /* CONFIG_USE_NDISUIO */
1716d49e1aeSJan Lentfer 
1726d49e1aeSJan Lentfer 	return 0;
1736d49e1aeSJan Lentfer }
174