/*
* win_if_list - Display network interfaces with description (for Windows)
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*
* This small tool is for the Windows build to provide an easy way of fetching
* a list of available network interfaces.
*/
#include "includes.h"
#include <stdio.h>
#ifdef CONFIG_USE_NDISUIO
#include <winsock2.h>
#include <ntddndis.h>
#else /* CONFIG_USE_NDISUIO */
#include "pcap.h"
#include <winsock.h>
#endif /* CONFIG_USE_NDISUIO */
#ifdef CONFIG_USE_NDISUIO
/* from nuiouser.h */
#define FSCTL_NDISUIO_BASE FILE_DEVICE_NETWORK
#define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \
CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access)
#define IOCTL_NDISUIO_QUERY_BINDING \
_NDISUIO_CTL_CODE(0x203, METHOD_BUFFERED, \
FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_NDISUIO_BIND_WAIT \
_NDISUIO_CTL_CODE(0x204, METHOD_BUFFERED, \
FILE_READ_ACCESS | FILE_WRITE_ACCESS)
typedef struct _NDISUIO_QUERY_BINDING
{
ULONG BindingIndex;
ULONG DeviceNameOffset;
ULONG DeviceNameLength;
ULONG DeviceDescrOffset;
ULONG DeviceDescrLength;
} NDISUIO_QUERY_BINDING, *PNDISUIO_QUERY_BINDING;
static HANDLE ndisuio_open(void)
{
DWORD written;
HANDLE h;
h = CreateFile(TEXT("\\\\.\\\\Ndisuio"),
GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
INVALID_HANDLE_VALUE);
if (h == INVALID_HANDLE_VALUE)
return h;
#ifndef _WIN32_WCE
if (!DeviceIoControl(h, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, NULL, 0,
&written, NULL)) {
printf("IOCTL_NDISUIO_BIND_WAIT failed: %d",
(int) GetLastError());
CloseHandle(h);
return INVALID_HANDLE_VALUE;
}
#endif /* _WIN32_WCE */
return h;
}
static void ndisuio_query_bindings(HANDLE ndisuio)
{
NDISUIO_QUERY_BINDING *b;
size_t blen = sizeof(*b) + 1024;
int i, error;
DWORD written;
char name[256], desc[256];
WCHAR *pos;
size_t j, len;
b = malloc(blen);
if (b == NULL)
return;
for (i = 0; ; i++) {
memset(b, 0, blen);
b->BindingIndex = i;
if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_QUERY_BINDING,
b, sizeof(NDISUIO_QUERY_BINDING), b,
(DWORD) blen, &written, NULL)) {
error = (int) GetLastError();
if (error == ERROR_NO_MORE_ITEMS)
break;
printf("IOCTL_NDISUIO_QUERY_BINDING failed: %d",
error);
break;
}
pos = (WCHAR *) ((char *) b + b->DeviceNameOffset);
len = b->DeviceNameLength;
if (len >= sizeof(name))
len = sizeof(name) - 1;
for (j = 0; j < len; j++)
name[j] = (char) pos[j];
name[len] = '\0';
pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset);
len = b->DeviceDescrLength;
if (len >= sizeof(desc))
len = sizeof(desc) - 1;
for (j = 0; j < len; j++)
desc[j] = (char) pos[j];
desc[len] = '\0';
printf("ifname: %s\ndescription: %s\n\n", name, desc);
}
free(b);
}
static void ndisuio_enum_bindings(void)
{
HANDLE ndisuio = ndisuio_open();
if (ndisuio == INVALID_HANDLE_VALUE)
return;
ndisuio_query_bindings(ndisuio);
CloseHandle(ndisuio);
}
#else /* CONFIG_USE_NDISUIO */
static void show_dev(pcap_if_t *dev)
{
printf("ifname: %s\ndescription: %s\n\n",
dev->name, dev->description);
}
static void pcap_enum_devs(void)
{
pcap_if_t *devs, *dev;
char err[PCAP_ERRBUF_SIZE + 1];
if (pcap_findalldevs(&devs, err) < 0) {
fprintf(stderr, "Error - pcap_findalldevs: %s\n", err);
return;
}
for (dev = devs; dev; dev = dev->next) {
show_dev(dev);
}
pcap_freealldevs(devs);
}
#endif /* CONFIG_USE_NDISUIO */
int main(int argc, char *argv[])
{
#ifdef CONFIG_USE_NDISUIO
ndisuio_enum_bindings();
#else /* CONFIG_USE_NDISUIO */
pcap_enum_devs();
#endif /* CONFIG_USE_NDISUIO */
return 0;
}