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