1 /* $NetBSD: fad-win32.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy) 5 * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California) 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the Politecnico di Torino, CACE Technologies 18 * nor the names of its contributors may be used to endorse or promote 19 * products derived from this software without specific prior written 20 * permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * 34 */ 35 36 #include <sys/cdefs.h> 37 __RCSID("$NetBSD: fad-win32.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); 38 39 #ifdef HAVE_CONFIG_H 40 #include "config.h" 41 #endif 42 43 #include <pcap.h> 44 #include <pcap-int.h> 45 #include <Packet32.h> 46 47 #include <errno.h> 48 49 static int 50 pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc, 51 char *errbuf) 52 { 53 pcap_if_t *curdev; 54 npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; 55 LONG if_addr_size; 56 int res = 0; 57 58 if_addr_size = MAX_NETWORK_ADDRESSES; 59 60 /* 61 * Add an entry for this interface, with no addresses. 62 */ 63 if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) { 64 /* 65 * Failure. 66 */ 67 return (-1); 68 } 69 70 /* 71 * Get the list of addresses for the interface. 72 */ 73 if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) { 74 /* 75 * Failure. 76 * 77 * We don't return an error, because this can happen with 78 * NdisWan interfaces, and we want to supply them even 79 * if we can't supply their addresses. 80 * 81 * We return an entry with an empty address list. 82 */ 83 return (0); 84 } 85 86 /* 87 * Now add the addresses. 88 */ 89 while (if_addr_size-- > 0) { 90 /* 91 * "curdev" is an entry for this interface; add an entry for 92 * this address to its list of addresses. 93 */ 94 if(curdev == NULL) 95 break; 96 res = add_addr_to_dev(curdev, 97 (struct sockaddr *)&if_addrs[if_addr_size].IPAddress, 98 sizeof (struct sockaddr_storage), 99 (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask, 100 sizeof (struct sockaddr_storage), 101 (struct sockaddr *)&if_addrs[if_addr_size].Broadcast, 102 sizeof (struct sockaddr_storage), 103 NULL, 104 0, 105 errbuf); 106 if (res == -1) { 107 /* 108 * Failure. 109 */ 110 break; 111 } 112 } 113 114 return (res); 115 } 116 117 118 /* 119 * Get a list of all interfaces that are up and that we can open. 120 * Returns -1 on error, 0 otherwise. 121 * The list, as returned through "alldevsp", may be null if no interfaces 122 * were up and could be opened. 123 * 124 * Win32 implementation, based on WinPcap 125 */ 126 int 127 pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) 128 { 129 pcap_if_t *devlist = NULL; 130 int ret = 0; 131 const char *desc; 132 char *AdaptersName; 133 ULONG NameLength; 134 char *name; 135 136 /* 137 * Find out how big a buffer we need. 138 * 139 * This call should always return FALSE; if the error is 140 * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to 141 * the size of the buffer we need, otherwise there's a 142 * problem, and NameLength should be set to 0. 143 * 144 * It shouldn't require NameLength to be set, but, 145 * at least as of WinPcap 4.1.3, it checks whether 146 * NameLength is big enough before it checks for a 147 * NULL buffer argument, so, while it'll still do 148 * the right thing if NameLength is uninitialized and 149 * whatever junk happens to be there is big enough 150 * (because the pointer argument will be null), it's 151 * still reading an uninitialized variable. 152 */ 153 NameLength = 0; 154 if (!PacketGetAdapterNames(NULL, &NameLength)) 155 { 156 DWORD last_error = GetLastError(); 157 158 if (last_error != ERROR_INSUFFICIENT_BUFFER) 159 { 160 snprintf(errbuf, PCAP_ERRBUF_SIZE, 161 "PacketGetAdapterNames: %s", 162 pcap_win32strerror()); 163 return (-1); 164 } 165 } 166 167 if (NameLength > 0) 168 AdaptersName = (char*) malloc(NameLength); 169 else 170 { 171 *alldevsp = NULL; 172 return 0; 173 } 174 if (AdaptersName == NULL) 175 { 176 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters."); 177 return (-1); 178 } 179 180 if (!PacketGetAdapterNames(AdaptersName, &NameLength)) { 181 snprintf(errbuf, PCAP_ERRBUF_SIZE, 182 "PacketGetAdapterNames: %s", 183 pcap_win32strerror()); 184 free(AdaptersName); 185 return (-1); 186 } 187 188 /* 189 * "PacketGetAdapterNames()" returned a list of 190 * null-terminated ASCII interface name strings, 191 * terminated by a null string, followed by a list 192 * of null-terminated ASCII interface description 193 * strings, terminated by a null string. 194 * This means there are two ASCII nulls at the end 195 * of the first list. 196 * 197 * Find the end of the first list; that's the 198 * beginning of the second list. 199 */ 200 desc = &AdaptersName[0]; 201 while (*desc != '\0' || *(desc + 1) != '\0') 202 desc++; 203 204 /* 205 * Found it - "desc" points to the first of the two 206 * nulls at the end of the list of names, so the 207 * first byte of the list of descriptions is two bytes 208 * after it. 209 */ 210 desc += 2; 211 212 /* 213 * Loop over the elements in the first list. 214 */ 215 name = &AdaptersName[0]; 216 while (*name != '\0') { 217 /* 218 * Add an entry for this interface. 219 */ 220 if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) { 221 /* 222 * Failure. 223 */ 224 ret = -1; 225 break; 226 } 227 name += strlen(name) + 1; 228 desc += strlen(desc) + 1; 229 } 230 231 if (ret != -1) { 232 /* 233 * We haven't had any errors yet; do any platform-specific 234 * operations to add devices. 235 */ 236 if (pcap_platform_finddevs(&devlist, errbuf) < 0) 237 ret = -1; 238 } 239 240 if (ret == -1) { 241 /* 242 * We had an error; free the list we've been constructing. 243 */ 244 if (devlist != NULL) { 245 pcap_freealldevs(devlist); 246 devlist = NULL; 247 } 248 } 249 250 *alldevsp = devlist; 251 free(AdaptersName); 252 return (ret); 253 } 254