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
38typedef 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
48static 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
74static 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
125static 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
137static void show_dev(pcap_if_t *dev)
138{
139	printf("ifname: %s\ndescription: %s\n\n",
140	       dev->name, dev->description);
141}
142
143
144static 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
164int 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