fad-win32.c revision 146768
1127664Sbms/* 2127664Sbms * Copyright (c) 2002 - 2003 3127664Sbms * NetGroup, Politecnico di Torino (Italy) 4127664Sbms * All rights reserved. 5127664Sbms * 6127664Sbms * Redistribution and use in source and binary forms, with or without 7127664Sbms * modification, are permitted provided that the following conditions 8127664Sbms * are met: 9127664Sbms * 10127664Sbms * 1. Redistributions of source code must retain the above copyright 11127664Sbms * notice, this list of conditions and the following disclaimer. 12127664Sbms * 2. Redistributions in binary form must reproduce the above copyright 13127664Sbms * notice, this list of conditions and the following disclaimer in the 14127664Sbms * documentation and/or other materials provided with the distribution. 15127664Sbms * 3. Neither the name of the Politecnico di Torino nor the names of its 16127664Sbms * contributors may be used to endorse or promote products derived from 17127664Sbms * this software without specific prior written permission. 18127664Sbms * 19127664Sbms * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20127664Sbms * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21127664Sbms * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22127664Sbms * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23127664Sbms * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24127664Sbms * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25127664Sbms * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26127664Sbms * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27127664Sbms * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28127664Sbms * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29127664Sbms * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30127664Sbms * 31127664Sbms */ 32127664Sbms 33127664Sbms#ifndef lint 34127664Sbmsstatic const char rcsid[] _U_ = 35146768Ssam "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.11 2005/01/29 00:52:22 guy Exp $ (LBL)"; 36127664Sbms#endif 37127664Sbms 38127664Sbms#ifdef HAVE_CONFIG_H 39127664Sbms#include "config.h" 40127664Sbms#endif 41127664Sbms 42127664Sbms#include <pcap.h> 43127664Sbms#include <pcap-int.h> 44127664Sbms#include <packet32.h> 45127664Sbms 46127664Sbms#include <errno.h> 47127664Sbms 48127664Sbms/* 49127664Sbms * Add an entry to the list of addresses for an interface. 50127664Sbms * "curdev" is the entry for that interface. 51127664Sbms */ 52127664Sbmsstatic int 53127664Sbmsadd_addr_to_list(pcap_if_t *curdev, struct sockaddr *addr, 54127664Sbms struct sockaddr *netmask, struct sockaddr *broadaddr, 55127664Sbms struct sockaddr *dstaddr, char *errbuf) 56127664Sbms{ 57127664Sbms pcap_addr_t *curaddr, *prevaddr, *nextaddr; 58127664Sbms 59127664Sbms /* 60127664Sbms * Allocate the new entry and fill it in. 61127664Sbms */ 62127664Sbms curaddr = (pcap_addr_t*)malloc(sizeof(pcap_addr_t)); 63127664Sbms if (curaddr == NULL) { 64127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 65127664Sbms "malloc: %s", pcap_strerror(errno)); 66127664Sbms return (-1); 67127664Sbms } 68127664Sbms 69127664Sbms curaddr->next = NULL; 70127664Sbms if (addr != NULL) { 71127664Sbms curaddr->addr = (struct sockaddr*)dup_sockaddr(addr, sizeof(struct sockaddr_storage)); 72127664Sbms if (curaddr->addr == NULL) { 73127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 74127664Sbms "malloc: %s", pcap_strerror(errno)); 75127664Sbms free(curaddr); 76127664Sbms return (-1); 77127664Sbms } 78127664Sbms } else 79127664Sbms curaddr->addr = NULL; 80127664Sbms 81127664Sbms if (netmask != NULL) { 82127664Sbms curaddr->netmask = (struct sockaddr*)dup_sockaddr(netmask, sizeof(struct sockaddr_storage)); 83127664Sbms if (curaddr->netmask == NULL) { 84127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 85127664Sbms "malloc: %s", pcap_strerror(errno)); 86127664Sbms free(curaddr); 87127664Sbms return (-1); 88127664Sbms } 89127664Sbms } else 90127664Sbms curaddr->netmask = NULL; 91127664Sbms 92127664Sbms if (broadaddr != NULL) { 93127664Sbms curaddr->broadaddr = (struct sockaddr*)dup_sockaddr(broadaddr, sizeof(struct sockaddr_storage)); 94127664Sbms if (curaddr->broadaddr == NULL) { 95127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 96127664Sbms "malloc: %s", pcap_strerror(errno)); 97127664Sbms free(curaddr); 98127664Sbms return (-1); 99127664Sbms } 100127664Sbms } else 101127664Sbms curaddr->broadaddr = NULL; 102127664Sbms 103127664Sbms if (dstaddr != NULL) { 104127664Sbms curaddr->dstaddr = (struct sockaddr*)dup_sockaddr(dstaddr, sizeof(struct sockaddr_storage)); 105127664Sbms if (curaddr->dstaddr == NULL) { 106127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 107127664Sbms "malloc: %s", pcap_strerror(errno)); 108127664Sbms free(curaddr); 109127664Sbms return (-1); 110127664Sbms } 111127664Sbms } else 112127664Sbms curaddr->dstaddr = NULL; 113127664Sbms 114127664Sbms /* 115127664Sbms * Find the end of the list of addresses. 116127664Sbms */ 117127664Sbms for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) { 118127664Sbms nextaddr = prevaddr->next; 119127664Sbms if (nextaddr == NULL) { 120127664Sbms /* 121127664Sbms * This is the end of the list. 122127664Sbms */ 123127664Sbms break; 124127664Sbms } 125127664Sbms } 126127664Sbms 127127664Sbms if (prevaddr == NULL) { 128127664Sbms /* 129127664Sbms * The list was empty; this is the first member. 130127664Sbms */ 131127664Sbms curdev->addresses = curaddr; 132127664Sbms } else { 133127664Sbms /* 134127664Sbms * "prevaddr" is the last member of the list; append 135127664Sbms * this member to it. 136127664Sbms */ 137127664Sbms prevaddr->next = curaddr; 138127664Sbms } 139127664Sbms 140127664Sbms return (0); 141127664Sbms} 142127664Sbms 143127664Sbms 144127664Sbmsstatic int 145127664Sbmspcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc, 146127664Sbms char *errbuf) 147127664Sbms{ 148127664Sbms pcap_if_t *curdev; 149127664Sbms npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; 150127664Sbms LONG if_addr_size; 151127664Sbms int res = 0; 152127664Sbms 153127664Sbms if_addr_size = MAX_NETWORK_ADDRESSES; 154127664Sbms 155127664Sbms /* 156127664Sbms * Add an entry for this interface, with no addresses. 157127664Sbms */ 158146768Ssam if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) { 159127664Sbms /* 160127664Sbms * Failure. 161127664Sbms */ 162127664Sbms return (-1); 163127664Sbms } 164127664Sbms 165127664Sbms /* 166127664Sbms * Get the list of addresses for the interface. 167127664Sbms */ 168127664Sbms if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) { 169127664Sbms /* 170127664Sbms * Failure. 171127664Sbms * 172127664Sbms * We don't return an error, because this can happen with 173127664Sbms * NdisWan interfaces, and we want to supply them even 174127664Sbms * if we can't supply their addresses. 175127664Sbms * 176127664Sbms * We return an entry with an empty address list. 177127664Sbms */ 178127664Sbms return (0); 179127664Sbms } 180127664Sbms 181127664Sbms /* 182127664Sbms * Now add the addresses. 183127664Sbms */ 184127664Sbms while (if_addr_size-- > 0) { 185127664Sbms /* 186127664Sbms * "curdev" is an entry for this interface; add an entry for 187127664Sbms * this address to its list of addresses. 188127664Sbms */ 189127664Sbms if(curdev == NULL) 190127664Sbms break; 191127664Sbms res = add_addr_to_list(curdev, 192127664Sbms (struct sockaddr *)&if_addrs[if_addr_size].IPAddress, 193127664Sbms (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask, 194127664Sbms (struct sockaddr *)&if_addrs[if_addr_size].Broadcast, 195127664Sbms NULL, 196127664Sbms errbuf); 197127664Sbms if (res == -1) { 198127664Sbms /* 199127664Sbms * Failure. 200127664Sbms */ 201127664Sbms break; 202127664Sbms } 203127664Sbms } 204127664Sbms 205127664Sbms return (res); 206127664Sbms} 207127664Sbms 208127664Sbms 209127664Sbms/* 210127664Sbms * Get a list of all interfaces that are up and that we can open. 211127664Sbms * Returns -1 on error, 0 otherwise. 212127664Sbms * The list, as returned through "alldevsp", may be null if no interfaces 213127664Sbms * were up and could be opened. 214127664Sbms * 215127664Sbms * Win32 implementation, based on WinPcap 216127664Sbms */ 217127664Sbmsint 218127664Sbmspcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) 219127664Sbms{ 220127664Sbms pcap_if_t *devlist = NULL; 221127664Sbms int ret = 0; 222127664Sbms const char *desc; 223146768Ssam char *AdaptersName; 224146768Ssam ULONG NameLength; 225127664Sbms char *name; 226127664Sbms 227146768Ssam PacketGetAdapterNames(NULL, &NameLength); 228146768Ssam 229146768Ssam if (NameLength > 0) 230146768Ssam AdaptersName = (char*) malloc(NameLength); 231146768Ssam else 232146768Ssam { 233146768Ssam *alldevsp = NULL; 234146768Ssam return 0; 235146768Ssam } 236146768Ssam if (AdaptersName == NULL) 237146768Ssam { 238146768Ssam snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters."); 239146768Ssam return (-1); 240146768Ssam } 241146768Ssam 242127664Sbms if (!PacketGetAdapterNames(AdaptersName, &NameLength)) { 243127664Sbms snprintf(errbuf, PCAP_ERRBUF_SIZE, 244127664Sbms "PacketGetAdapterNames: %s", 245127664Sbms pcap_win32strerror()); 246146768Ssam free(AdaptersName); 247127664Sbms return (-1); 248127664Sbms } 249127664Sbms 250127664Sbms /* 251127664Sbms * "PacketGetAdapterNames()" returned a list of 252127664Sbms * null-terminated ASCII interface name strings, 253127664Sbms * terminated by a null string, followed by a list 254127664Sbms * of null-terminated ASCII interface description 255127664Sbms * strings, terminated by a null string. 256127664Sbms * This means there are two ASCII nulls at the end 257127664Sbms * of the first list. 258127664Sbms * 259127664Sbms * Find the end of the first list; that's the 260127664Sbms * beginning of the second list. 261127664Sbms */ 262127664Sbms desc = &AdaptersName[0]; 263127664Sbms while (*desc != '\0' || *(desc + 1) != '\0') 264127664Sbms desc++; 265127664Sbms 266127664Sbms /* 267127664Sbms * Found it - "desc" points to the first of the two 268127664Sbms * nulls at the end of the list of names, so the 269127664Sbms * first byte of the list of descriptions is two bytes 270127664Sbms * after it. 271127664Sbms */ 272127664Sbms desc += 2; 273127664Sbms 274127664Sbms /* 275127664Sbms * Loop over the elements in the first list. 276127664Sbms */ 277127664Sbms name = &AdaptersName[0]; 278127664Sbms while (*name != '\0') { 279146768Ssam /* 280146768Ssam * Add an entry for this interface. 281146768Ssam */ 282146768Ssam if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) { 283127664Sbms /* 284146768Ssam * Failure. 285146768Ssam */ 286127664Sbms ret = -1; 287127664Sbms break; 288127664Sbms } 289127664Sbms name += strlen(name) + 1; 290127664Sbms desc += strlen(desc) + 1; 291127664Sbms } 292127664Sbms 293127664Sbms if (ret == -1) { 294146768Ssam /* 295146768Ssam * We had an error; free the list we've been constructing. 296146768Ssam */ 297146768Ssam if (devlist != NULL) { 298127664Sbms pcap_freealldevs(devlist); 299127664Sbms devlist = NULL; 300127664Sbms } 301127664Sbms } 302127664Sbms 303127664Sbms *alldevsp = devlist; 304146768Ssam free(AdaptersName); 305127664Sbms return (ret); 306127664Sbms} 307