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
44typedef 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
54static 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
80static 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
131static 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
143static void show_dev(pcap_if_t *dev)
144{
145	printf("ifname: %s\ndescription: %s\n\n",
146	       dev->name, dev->description);
147}
148
149
150static 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
170int 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