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