fad-win32.c revision 127664
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.7.2.1 2003/11/15 23:26:40 guy 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, (char *)name, 0, (char *)desc, 159 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[8192]; 225 ULONG NameLength = 8192; 226 char *name; 227 228 if (!PacketGetAdapterNames(AdaptersName, &NameLength)) { 229 snprintf(errbuf, PCAP_ERRBUF_SIZE, 230 "PacketGetAdapterNames: %s", 231 pcap_win32strerror()); 232 return (-1); 233 } 234 235 /* 236 * "PacketGetAdapterNames()" returned a list of 237 * null-terminated ASCII interface name strings, 238 * terminated by a null string, followed by a list 239 * of null-terminated ASCII interface description 240 * strings, terminated by a null string. 241 * This means there are two ASCII nulls at the end 242 * of the first list. 243 * 244 * Find the end of the first list; that's the 245 * beginning of the second list. 246 */ 247 desc = &AdaptersName[0]; 248 while (*desc != '\0' || *(desc + 1) != '\0') 249 desc++; 250 251 /* 252 * Found it - "desc" points to the first of the two 253 * nulls at the end of the list of names, so the 254 * first byte of the list of descriptions is two bytes 255 * after it. 256 */ 257 desc += 2; 258 259 /* 260 * Loop over the elements in the first list. 261 */ 262 name = &AdaptersName[0]; 263 while (*name != '\0') { 264 /* 265 * Add an entry for this interface. 266 */ 267 if (pcap_add_if_win32(&devlist, name, desc, 268 errbuf) == -1) { 269 /* 270 * Failure. 271 */ 272 ret = -1; 273 break; 274 } 275 name += strlen(name) + 1; 276 desc += strlen(desc) + 1; 277 } 278 279 if (ret == -1) { 280 /* 281 * We had an error; free the list we've been constructing. 282 */ 283 if (devlist != NULL) { 284 pcap_freealldevs(devlist); 285 devlist = NULL; 286 } 287 } 288 289 *alldevsp = devlist; 290 return (ret); 291} 292