1/* 2 * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy) 3 * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California) 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the Politecnico di Torino, CACE Technologies 16 * nor the names of its contributors may be used to endorse or promote 17 * products derived from this software without specific prior written 18 * permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 */ 33 34#ifndef lint 35static const char rcsid[] _U_ = 36 "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.11.2.3 2006/02/22 17:09:32 gianluca Exp $ (LBL)"; 37#endif 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/* 50 * Add an entry to the list of addresses for an interface. 51 * "curdev" is the entry for that interface. 52 */ 53static int 54add_addr_to_list(pcap_if_t *curdev, struct sockaddr *addr, 55 struct sockaddr *netmask, struct sockaddr *broadaddr, 56 struct sockaddr *dstaddr, char *errbuf) 57{ 58 pcap_addr_t *curaddr, *prevaddr, *nextaddr; 59 60 /* 61 * Allocate the new entry and fill it in. 62 */ 63 curaddr = (pcap_addr_t*)malloc(sizeof(pcap_addr_t)); 64 if (curaddr == NULL) { 65 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 66 "malloc: %s", pcap_strerror(errno)); 67 return (-1); 68 } 69 70 curaddr->next = NULL; 71 if (addr != NULL) { 72 curaddr->addr = (struct sockaddr*)dup_sockaddr(addr, sizeof(struct sockaddr_storage)); 73 if (curaddr->addr == NULL) { 74 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 75 "malloc: %s", pcap_strerror(errno)); 76 free(curaddr); 77 return (-1); 78 } 79 } else 80 curaddr->addr = NULL; 81 82 if (netmask != NULL) { 83 curaddr->netmask = (struct sockaddr*)dup_sockaddr(netmask, sizeof(struct sockaddr_storage)); 84 if (curaddr->netmask == NULL) { 85 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 86 "malloc: %s", pcap_strerror(errno)); 87 free(curaddr); 88 return (-1); 89 } 90 } else 91 curaddr->netmask = NULL; 92 93 if (broadaddr != NULL) { 94 curaddr->broadaddr = (struct sockaddr*)dup_sockaddr(broadaddr, sizeof(struct sockaddr_storage)); 95 if (curaddr->broadaddr == NULL) { 96 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 97 "malloc: %s", pcap_strerror(errno)); 98 free(curaddr); 99 return (-1); 100 } 101 } else 102 curaddr->broadaddr = NULL; 103 104 if (dstaddr != NULL) { 105 curaddr->dstaddr = (struct sockaddr*)dup_sockaddr(dstaddr, sizeof(struct sockaddr_storage)); 106 if (curaddr->dstaddr == NULL) { 107 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 108 "malloc: %s", pcap_strerror(errno)); 109 free(curaddr); 110 return (-1); 111 } 112 } else 113 curaddr->dstaddr = NULL; 114 115 /* 116 * Find the end of the list of addresses. 117 */ 118 for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) { 119 nextaddr = prevaddr->next; 120 if (nextaddr == NULL) { 121 /* 122 * This is the end of the list. 123 */ 124 break; 125 } 126 } 127 128 if (prevaddr == NULL) { 129 /* 130 * The list was empty; this is the first member. 131 */ 132 curdev->addresses = curaddr; 133 } else { 134 /* 135 * "prevaddr" is the last member of the list; append 136 * this member to it. 137 */ 138 prevaddr->next = curaddr; 139 } 140 141 return (0); 142} 143 144 145static int 146pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc, 147 char *errbuf) 148{ 149 pcap_if_t *curdev; 150 npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; 151 LONG if_addr_size; 152 int res = 0; 153 154 if_addr_size = MAX_NETWORK_ADDRESSES; 155 156 /* 157 * Add an entry for this interface, with no addresses. 158 */ 159 if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) { 160 /* 161 * Failure. 162 */ 163 return (-1); 164 } 165 166 /* 167 * Get the list of addresses for the interface. 168 */ 169 if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) { 170 /* 171 * Failure. 172 * 173 * We don't return an error, because this can happen with 174 * NdisWan interfaces, and we want to supply them even 175 * if we can't supply their addresses. 176 * 177 * We return an entry with an empty address list. 178 */ 179 return (0); 180 } 181 182 /* 183 * Now add the addresses. 184 */ 185 while (if_addr_size-- > 0) { 186 /* 187 * "curdev" is an entry for this interface; add an entry for 188 * this address to its list of addresses. 189 */ 190 if(curdev == NULL) 191 break; 192 res = add_addr_to_list(curdev, 193 (struct sockaddr *)&if_addrs[if_addr_size].IPAddress, 194 (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask, 195 (struct sockaddr *)&if_addrs[if_addr_size].Broadcast, 196 NULL, 197 errbuf); 198 if (res == -1) { 199 /* 200 * Failure. 201 */ 202 break; 203 } 204 } 205 206 return (res); 207} 208 209 210/* 211 * Get a list of all interfaces that are up and that we can open. 212 * Returns -1 on error, 0 otherwise. 213 * The list, as returned through "alldevsp", may be null if no interfaces 214 * were up and could be opened. 215 * 216 * Win32 implementation, based on WinPcap 217 */ 218int 219pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) 220{ 221 pcap_if_t *devlist = NULL; 222 int ret = 0; 223 const char *desc; 224 char *AdaptersName; 225 ULONG NameLength; 226 char *name; 227 228 if (!PacketGetAdapterNames(NULL, &NameLength)) 229 { 230 DWORD last_error = GetLastError(); 231 232 if (last_error != ERROR_INSUFFICIENT_BUFFER) 233 { 234 snprintf(errbuf, PCAP_ERRBUF_SIZE, 235 "PacketGetAdapterNames: %s", 236 pcap_win32strerror()); 237 return (-1); 238 } 239 } 240 241 if (NameLength > 0) 242 AdaptersName = (char*) malloc(NameLength); 243 else 244 { 245 *alldevsp = NULL; 246 return 0; 247 } 248 if (AdaptersName == NULL) 249 { 250 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters."); 251 return (-1); 252 } 253 254 if (!PacketGetAdapterNames(AdaptersName, &NameLength)) { 255 snprintf(errbuf, PCAP_ERRBUF_SIZE, 256 "PacketGetAdapterNames: %s", 257 pcap_win32strerror()); 258 free(AdaptersName); 259 return (-1); 260 } 261 262 /* 263 * "PacketGetAdapterNames()" returned a list of 264 * null-terminated ASCII interface name strings, 265 * terminated by a null string, followed by a list 266 * of null-terminated ASCII interface description 267 * strings, terminated by a null string. 268 * This means there are two ASCII nulls at the end 269 * of the first list. 270 * 271 * Find the end of the first list; that's the 272 * beginning of the second list. 273 */ 274 desc = &AdaptersName[0]; 275 while (*desc != '\0' || *(desc + 1) != '\0') 276 desc++; 277 278 /* 279 * Found it - "desc" points to the first of the two 280 * nulls at the end of the list of names, so the 281 * first byte of the list of descriptions is two bytes 282 * after it. 283 */ 284 desc += 2; 285 286 /* 287 * Loop over the elements in the first list. 288 */ 289 name = &AdaptersName[0]; 290 while (*name != '\0') { 291 /* 292 * Add an entry for this interface. 293 */ 294 if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) { 295 /* 296 * Failure. 297 */ 298 ret = -1; 299 break; 300 } 301 name += strlen(name) + 1; 302 desc += strlen(desc) + 1; 303 } 304 305 if (ret == -1) { 306 /* 307 * We had an error; free the list we've been constructing. 308 */ 309 if (devlist != NULL) { 310 pcap_freealldevs(devlist); 311 devlist = NULL; 312 } 313 } 314 315 *alldevsp = devlist; 316 free(AdaptersName); 317 return (ret); 318} 319