1127664Sbms/* 2172677Smlaier * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy) 3172677Smlaier * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California) 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. 15172677Smlaier * 3. Neither the name of the Politecnico di Torino, CACE Technologies 16172677Smlaier * nor the names of its contributors may be used to endorse or promote 17172677Smlaier * products derived from this software without specific prior written 18172677Smlaier * permission. 19127664Sbms * 20127664Sbms * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21127664Sbms * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22127664Sbms * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23127664Sbms * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24127664Sbms * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25127664Sbms * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26127664Sbms * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27127664Sbms * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28127664Sbms * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29127664Sbms * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30127664Sbms * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31127664Sbms * 32127664Sbms */ 33127664Sbms 34127664Sbms#ifndef lint 35127664Sbmsstatic const char rcsid[] _U_ = 36214518Srpaulo "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.15 2007-09-25 20:34:36 guy Exp $ (LBL)"; 37127664Sbms#endif 38127664Sbms 39127664Sbms#ifdef HAVE_CONFIG_H 40127664Sbms#include "config.h" 41127664Sbms#endif 42127664Sbms 43127664Sbms#include <pcap.h> 44127664Sbms#include <pcap-int.h> 45172677Smlaier#include <Packet32.h> 46127664Sbms 47127664Sbms#include <errno.h> 48127664Sbms 49127664Sbms/* 50127664Sbms * Add an entry to the list of addresses for an interface. 51127664Sbms * "curdev" is the entry for that interface. 52127664Sbms */ 53127664Sbmsstatic int 54127664Sbmsadd_addr_to_list(pcap_if_t *curdev, struct sockaddr *addr, 55127664Sbms struct sockaddr *netmask, struct sockaddr *broadaddr, 56127664Sbms struct sockaddr *dstaddr, char *errbuf) 57127664Sbms{ 58127664Sbms pcap_addr_t *curaddr, *prevaddr, *nextaddr; 59127664Sbms 60127664Sbms /* 61127664Sbms * Allocate the new entry and fill it in. 62127664Sbms */ 63127664Sbms curaddr = (pcap_addr_t*)malloc(sizeof(pcap_addr_t)); 64127664Sbms if (curaddr == NULL) { 65127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 66127664Sbms "malloc: %s", pcap_strerror(errno)); 67127664Sbms return (-1); 68127664Sbms } 69127664Sbms 70127664Sbms curaddr->next = NULL; 71127664Sbms if (addr != NULL) { 72127664Sbms curaddr->addr = (struct sockaddr*)dup_sockaddr(addr, sizeof(struct sockaddr_storage)); 73127664Sbms if (curaddr->addr == NULL) { 74127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 75127664Sbms "malloc: %s", pcap_strerror(errno)); 76127664Sbms free(curaddr); 77127664Sbms return (-1); 78127664Sbms } 79127664Sbms } else 80127664Sbms curaddr->addr = NULL; 81127664Sbms 82127664Sbms if (netmask != NULL) { 83127664Sbms curaddr->netmask = (struct sockaddr*)dup_sockaddr(netmask, sizeof(struct sockaddr_storage)); 84127664Sbms if (curaddr->netmask == NULL) { 85127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 86127664Sbms "malloc: %s", pcap_strerror(errno)); 87127664Sbms free(curaddr); 88127664Sbms return (-1); 89127664Sbms } 90127664Sbms } else 91127664Sbms curaddr->netmask = NULL; 92127664Sbms 93127664Sbms if (broadaddr != NULL) { 94127664Sbms curaddr->broadaddr = (struct sockaddr*)dup_sockaddr(broadaddr, sizeof(struct sockaddr_storage)); 95127664Sbms if (curaddr->broadaddr == NULL) { 96127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 97127664Sbms "malloc: %s", pcap_strerror(errno)); 98127664Sbms free(curaddr); 99127664Sbms return (-1); 100127664Sbms } 101127664Sbms } else 102127664Sbms curaddr->broadaddr = NULL; 103127664Sbms 104127664Sbms if (dstaddr != NULL) { 105127664Sbms curaddr->dstaddr = (struct sockaddr*)dup_sockaddr(dstaddr, sizeof(struct sockaddr_storage)); 106127664Sbms if (curaddr->dstaddr == NULL) { 107127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 108127664Sbms "malloc: %s", pcap_strerror(errno)); 109127664Sbms free(curaddr); 110127664Sbms return (-1); 111127664Sbms } 112127664Sbms } else 113127664Sbms curaddr->dstaddr = NULL; 114127664Sbms 115127664Sbms /* 116127664Sbms * Find the end of the list of addresses. 117127664Sbms */ 118127664Sbms for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) { 119127664Sbms nextaddr = prevaddr->next; 120127664Sbms if (nextaddr == NULL) { 121127664Sbms /* 122127664Sbms * This is the end of the list. 123127664Sbms */ 124127664Sbms break; 125127664Sbms } 126127664Sbms } 127127664Sbms 128127664Sbms if (prevaddr == NULL) { 129127664Sbms /* 130127664Sbms * The list was empty; this is the first member. 131127664Sbms */ 132127664Sbms curdev->addresses = curaddr; 133127664Sbms } else { 134127664Sbms /* 135127664Sbms * "prevaddr" is the last member of the list; append 136127664Sbms * this member to it. 137127664Sbms */ 138127664Sbms prevaddr->next = curaddr; 139127664Sbms } 140127664Sbms 141127664Sbms return (0); 142127664Sbms} 143127664Sbms 144127664Sbms 145127664Sbmsstatic int 146127664Sbmspcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc, 147127664Sbms char *errbuf) 148127664Sbms{ 149127664Sbms pcap_if_t *curdev; 150127664Sbms npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; 151127664Sbms LONG if_addr_size; 152127664Sbms int res = 0; 153127664Sbms 154127664Sbms if_addr_size = MAX_NETWORK_ADDRESSES; 155127664Sbms 156127664Sbms /* 157127664Sbms * Add an entry for this interface, with no addresses. 158127664Sbms */ 159146768Ssam if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) { 160127664Sbms /* 161127664Sbms * Failure. 162127664Sbms */ 163127664Sbms return (-1); 164127664Sbms } 165127664Sbms 166127664Sbms /* 167127664Sbms * Get the list of addresses for the interface. 168127664Sbms */ 169127664Sbms if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) { 170127664Sbms /* 171127664Sbms * Failure. 172127664Sbms * 173127664Sbms * We don't return an error, because this can happen with 174127664Sbms * NdisWan interfaces, and we want to supply them even 175127664Sbms * if we can't supply their addresses. 176127664Sbms * 177127664Sbms * We return an entry with an empty address list. 178127664Sbms */ 179127664Sbms return (0); 180127664Sbms } 181127664Sbms 182127664Sbms /* 183127664Sbms * Now add the addresses. 184127664Sbms */ 185127664Sbms while (if_addr_size-- > 0) { 186127664Sbms /* 187127664Sbms * "curdev" is an entry for this interface; add an entry for 188127664Sbms * this address to its list of addresses. 189127664Sbms */ 190127664Sbms if(curdev == NULL) 191127664Sbms break; 192127664Sbms res = add_addr_to_list(curdev, 193127664Sbms (struct sockaddr *)&if_addrs[if_addr_size].IPAddress, 194127664Sbms (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask, 195127664Sbms (struct sockaddr *)&if_addrs[if_addr_size].Broadcast, 196127664Sbms NULL, 197127664Sbms errbuf); 198127664Sbms if (res == -1) { 199127664Sbms /* 200127664Sbms * Failure. 201127664Sbms */ 202127664Sbms break; 203127664Sbms } 204127664Sbms } 205127664Sbms 206127664Sbms return (res); 207127664Sbms} 208127664Sbms 209127664Sbms 210127664Sbms/* 211127664Sbms * Get a list of all interfaces that are up and that we can open. 212127664Sbms * Returns -1 on error, 0 otherwise. 213127664Sbms * The list, as returned through "alldevsp", may be null if no interfaces 214127664Sbms * were up and could be opened. 215127664Sbms * 216127664Sbms * Win32 implementation, based on WinPcap 217127664Sbms */ 218127664Sbmsint 219127664Sbmspcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) 220127664Sbms{ 221127664Sbms pcap_if_t *devlist = NULL; 222127664Sbms int ret = 0; 223127664Sbms const char *desc; 224146768Ssam char *AdaptersName; 225146768Ssam ULONG NameLength; 226127664Sbms char *name; 227127664Sbms 228172677Smlaier if (!PacketGetAdapterNames(NULL, &NameLength)) 229162012Ssam { 230172677Smlaier DWORD last_error = GetLastError(); 231172677Smlaier 232172677Smlaier if (last_error != ERROR_INSUFFICIENT_BUFFER) 233172677Smlaier { 234172677Smlaier snprintf(errbuf, PCAP_ERRBUF_SIZE, 235172677Smlaier "PacketGetAdapterNames: %s", 236172677Smlaier pcap_win32strerror()); 237172677Smlaier return (-1); 238172677Smlaier } 239162012Ssam } 240146768Ssam 241146768Ssam if (NameLength > 0) 242146768Ssam AdaptersName = (char*) malloc(NameLength); 243146768Ssam else 244146768Ssam { 245146768Ssam *alldevsp = NULL; 246146768Ssam return 0; 247146768Ssam } 248146768Ssam if (AdaptersName == NULL) 249146768Ssam { 250146768Ssam snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters."); 251146768Ssam return (-1); 252146768Ssam } 253146768Ssam 254127664Sbms if (!PacketGetAdapterNames(AdaptersName, &NameLength)) { 255127664Sbms snprintf(errbuf, PCAP_ERRBUF_SIZE, 256127664Sbms "PacketGetAdapterNames: %s", 257127664Sbms pcap_win32strerror()); 258146768Ssam free(AdaptersName); 259127664Sbms return (-1); 260127664Sbms } 261127664Sbms 262127664Sbms /* 263127664Sbms * "PacketGetAdapterNames()" returned a list of 264127664Sbms * null-terminated ASCII interface name strings, 265127664Sbms * terminated by a null string, followed by a list 266127664Sbms * of null-terminated ASCII interface description 267127664Sbms * strings, terminated by a null string. 268127664Sbms * This means there are two ASCII nulls at the end 269127664Sbms * of the first list. 270127664Sbms * 271127664Sbms * Find the end of the first list; that's the 272127664Sbms * beginning of the second list. 273127664Sbms */ 274127664Sbms desc = &AdaptersName[0]; 275127664Sbms while (*desc != '\0' || *(desc + 1) != '\0') 276127664Sbms desc++; 277127664Sbms 278127664Sbms /* 279127664Sbms * Found it - "desc" points to the first of the two 280127664Sbms * nulls at the end of the list of names, so the 281127664Sbms * first byte of the list of descriptions is two bytes 282127664Sbms * after it. 283127664Sbms */ 284127664Sbms desc += 2; 285127664Sbms 286127664Sbms /* 287127664Sbms * Loop over the elements in the first list. 288127664Sbms */ 289127664Sbms name = &AdaptersName[0]; 290127664Sbms while (*name != '\0') { 291146768Ssam /* 292146768Ssam * Add an entry for this interface. 293146768Ssam */ 294146768Ssam if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) { 295127664Sbms /* 296146768Ssam * Failure. 297146768Ssam */ 298127664Sbms ret = -1; 299127664Sbms break; 300127664Sbms } 301127664Sbms name += strlen(name) + 1; 302127664Sbms desc += strlen(desc) + 1; 303127664Sbms } 304190225Srpaulo 305190225Srpaulo if (ret != -1) { 306190225Srpaulo /* 307190225Srpaulo * We haven't had any errors yet; do any platform-specific 308190225Srpaulo * operations to add devices. 309190225Srpaulo */ 310190225Srpaulo if (pcap_platform_finddevs(&devlist, errbuf) < 0) 311190225Srpaulo ret = -1; 312190225Srpaulo } 313127664Sbms 314127664Sbms if (ret == -1) { 315146768Ssam /* 316146768Ssam * We had an error; free the list we've been constructing. 317146768Ssam */ 318146768Ssam if (devlist != NULL) { 319127664Sbms pcap_freealldevs(devlist); 320127664Sbms devlist = NULL; 321127664Sbms } 322127664Sbms } 323127664Sbms 324127664Sbms *alldevsp = devlist; 325146768Ssam free(AdaptersName); 326127664Sbms return (ret); 327127664Sbms} 328