Dmitry Shmidt | 8d520ff | 2011-05-09 14:06:53 -0700 | [diff] [blame] | 1 | /* |
| 2 | * win_if_list - Display network interfaces with description (for Windows) |
| 3 | * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> |
| 4 | * |
Dmitry Shmidt | c5ec7f5 | 2012-03-06 16:33:24 -0800 | [diff] [blame^] | 5 | * This software may be distributed under the terms of the BSD license. |
| 6 | * See README for more details. |
Dmitry Shmidt | 8d520ff | 2011-05-09 14:06:53 -0700 | [diff] [blame] | 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | } |