1 /*
2  * win_if_list - Display network interfaces with description (for Windows)
3  * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  *
14  * This small tool is for the Windows build to provide an easy way of fetching
15  * a list of available network interfaces.
16  */
17 
18 #include "includes.h"
19 #include <stdio.h>
20 #ifdef CONFIG_USE_NDISUIO
21 #include <winsock2.h>
22 #include <ntddndis.h>
23 #else /* CONFIG_USE_NDISUIO */
24 #include "pcap.h"
25 #include <winsock.h>
26 #endif /* CONFIG_USE_NDISUIO */
27 
28 #ifdef CONFIG_USE_NDISUIO
29 
30 /* from nuiouser.h */
31 #define FSCTL_NDISUIO_BASE      FILE_DEVICE_NETWORK
32 
33 #define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \
34 	CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access)
35 
36 #define IOCTL_NDISUIO_QUERY_BINDING \
37 	_NDISUIO_CTL_CODE(0x203, METHOD_BUFFERED, \
38 			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
39 
40 #define IOCTL_NDISUIO_BIND_WAIT \
41 	_NDISUIO_CTL_CODE(0x204, METHOD_BUFFERED, \
42 			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
43 
44 typedef struct _NDISUIO_QUERY_BINDING
45 {
46 	ULONG BindingIndex;
47 	ULONG DeviceNameOffset;
48 	ULONG DeviceNameLength;
49 	ULONG DeviceDescrOffset;
50 	ULONG DeviceDescrLength;
51 } NDISUIO_QUERY_BINDING, *PNDISUIO_QUERY_BINDING;
52 
53 
54 static HANDLE ndisuio_open(void)
55 {
56 	DWORD written;
57 	HANDLE h;
58 
59 	h = CreateFile(TEXT("\\\\.\\\\Ndisuio"),
60 		       GENERIC_READ | GENERIC_WRITE, 0, NULL,
61 		       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
62 		       INVALID_HANDLE_VALUE);
63 	if (h == INVALID_HANDLE_VALUE)
64 		return h;
65 
66 #ifndef _WIN32_WCE
67 	if (!DeviceIoControl(h, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, NULL, 0,
68 			     &written, NULL)) {
69 		printf("IOCTL_NDISUIO_BIND_WAIT failed: %d",
70 		       (int) GetLastError());
71 		CloseHandle(h);
72 		return INVALID_HANDLE_VALUE;
73 	}
74 #endif /* _WIN32_WCE */
75 
76 	return h;
77 }
78 
79 
80 static void ndisuio_query_bindings(HANDLE ndisuio)
81 {
82 	NDISUIO_QUERY_BINDING *b;
83 	size_t blen = sizeof(*b) + 1024;
84 	int i, error;
85 	DWORD written;
86 	char name[256], desc[256];
87 	WCHAR *pos;
88 	size_t j, len;
89 
90 	b = malloc(blen);
91 	if (b == NULL)
92 		return;
93 
94 	for (i = 0; ; i++) {
95 		memset(b, 0, blen);
96 		b->BindingIndex = i;
97 		if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_QUERY_BINDING,
98 				     b, sizeof(NDISUIO_QUERY_BINDING), b,
99 				     (DWORD) blen, &written, NULL)) {
100 			error = (int) GetLastError();
101 			if (error == ERROR_NO_MORE_ITEMS)
102 				break;
103 			printf("IOCTL_NDISUIO_QUERY_BINDING failed: %d",
104 			       error);
105 			break;
106 		}
107 
108 		pos = (WCHAR *) ((char *) b + b->DeviceNameOffset);
109 		len = b->DeviceNameLength;
110 		if (len >= sizeof(name))
111 			len = sizeof(name) - 1;
112 		for (j = 0; j < len; j++)
113 			name[j] = (char) pos[j];
114 		name[len] = '\0';
115 
116 		pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset);
117 		len = b->DeviceDescrLength;
118 		if (len >= sizeof(desc))
119 			len = sizeof(desc) - 1;
120 		for (j = 0; j < len; j++)
121 			desc[j] = (char) pos[j];
122 		desc[len] = '\0';
123 
124 		printf("ifname: %s\ndescription: %s\n\n", name, desc);
125 	}
126 
127 	free(b);
128 }
129 
130 
131 static void ndisuio_enum_bindings(void)
132 {
133 	HANDLE ndisuio = ndisuio_open();
134 	if (ndisuio == INVALID_HANDLE_VALUE)
135 		return;
136 
137 	ndisuio_query_bindings(ndisuio);
138 	CloseHandle(ndisuio);
139 }
140 
141 #else /* CONFIG_USE_NDISUIO */
142 
143 static void show_dev(pcap_if_t *dev)
144 {
145 	printf("ifname: %s\ndescription: %s\n\n",
146 	       dev->name, dev->description);
147 }
148 
149 
150 static void pcap_enum_devs(void)
151 {
152 	pcap_if_t *devs, *dev;
153 	char err[PCAP_ERRBUF_SIZE + 1];
154 
155 	if (pcap_findalldevs(&devs, err) < 0) {
156 		fprintf(stderr, "Error - pcap_findalldevs: %s\n", err);
157 		return;
158 	}
159 
160 	for (dev = devs; dev; dev = dev->next) {
161 		show_dev(dev);
162 	}
163 
164 	pcap_freealldevs(devs);
165 }
166 
167 #endif /* CONFIG_USE_NDISUIO */
168 
169 
170 int main(int argc, char *argv[])
171 {
172 #ifdef CONFIG_USE_NDISUIO
173 	ndisuio_enum_bindings();
174 #else /* CONFIG_USE_NDISUIO */
175 	pcap_enum_devs();
176 #endif /* CONFIG_USE_NDISUIO */
177 
178 	return 0;
179 }
180