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#ifdef HAVE_CONFIG_H 35127664Sbms#include "config.h" 36127664Sbms#endif 37127664Sbms 38127664Sbms#include <pcap.h> 39127664Sbms#include <pcap-int.h> 40172677Smlaier#include <Packet32.h> 41127664Sbms 42127664Sbms#include <errno.h> 43127664Sbms 44127664Sbmsstatic int 45127664Sbmspcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc, 46127664Sbms char *errbuf) 47127664Sbms{ 48127664Sbms pcap_if_t *curdev; 49127664Sbms npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; 50127664Sbms LONG if_addr_size; 51127664Sbms int res = 0; 52127664Sbms 53127664Sbms if_addr_size = MAX_NETWORK_ADDRESSES; 54127664Sbms 55127664Sbms /* 56127664Sbms * Add an entry for this interface, with no addresses. 57127664Sbms */ 58146768Ssam if (add_or_find_if(&curdev, devlist, name, 0, desc, errbuf) == -1) { 59127664Sbms /* 60127664Sbms * Failure. 61127664Sbms */ 62127664Sbms return (-1); 63127664Sbms } 64127664Sbms 65127664Sbms /* 66127664Sbms * Get the list of addresses for the interface. 67127664Sbms */ 68127664Sbms if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) { 69127664Sbms /* 70127664Sbms * Failure. 71127664Sbms * 72127664Sbms * We don't return an error, because this can happen with 73127664Sbms * NdisWan interfaces, and we want to supply them even 74127664Sbms * if we can't supply their addresses. 75127664Sbms * 76127664Sbms * We return an entry with an empty address list. 77127664Sbms */ 78127664Sbms return (0); 79127664Sbms } 80127664Sbms 81127664Sbms /* 82127664Sbms * Now add the addresses. 83127664Sbms */ 84127664Sbms while (if_addr_size-- > 0) { 85127664Sbms /* 86127664Sbms * "curdev" is an entry for this interface; add an entry for 87127664Sbms * this address to its list of addresses. 88127664Sbms */ 89127664Sbms if(curdev == NULL) 90127664Sbms break; 91276768Sdelphij res = add_addr_to_dev(curdev, 92127664Sbms (struct sockaddr *)&if_addrs[if_addr_size].IPAddress, 93276768Sdelphij sizeof (struct sockaddr_storage), 94127664Sbms (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask, 95276768Sdelphij sizeof (struct sockaddr_storage), 96127664Sbms (struct sockaddr *)&if_addrs[if_addr_size].Broadcast, 97276768Sdelphij sizeof (struct sockaddr_storage), 98127664Sbms NULL, 99276768Sdelphij 0, 100276768Sdelphij errbuf); 101127664Sbms if (res == -1) { 102127664Sbms /* 103127664Sbms * Failure. 104127664Sbms */ 105127664Sbms break; 106127664Sbms } 107127664Sbms } 108127664Sbms 109127664Sbms return (res); 110127664Sbms} 111127664Sbms 112127664Sbms 113127664Sbms/* 114127664Sbms * Get a list of all interfaces that are up and that we can open. 115127664Sbms * Returns -1 on error, 0 otherwise. 116127664Sbms * The list, as returned through "alldevsp", may be null if no interfaces 117127664Sbms * were up and could be opened. 118127664Sbms * 119127664Sbms * Win32 implementation, based on WinPcap 120127664Sbms */ 121127664Sbmsint 122276768Sdelphijpcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) 123127664Sbms{ 124127664Sbms pcap_if_t *devlist = NULL; 125127664Sbms int ret = 0; 126127664Sbms const char *desc; 127146768Ssam char *AdaptersName; 128146768Ssam ULONG NameLength; 129127664Sbms char *name; 130127664Sbms 131276768Sdelphij /* 132276768Sdelphij * Find out how big a buffer we need. 133276768Sdelphij * 134276768Sdelphij * This call should always return FALSE; if the error is 135276768Sdelphij * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to 136276768Sdelphij * the size of the buffer we need, otherwise there's a 137276768Sdelphij * problem, and NameLength should be set to 0. 138276768Sdelphij * 139276768Sdelphij * It shouldn't require NameLength to be set, but, 140276768Sdelphij * at least as of WinPcap 4.1.3, it checks whether 141276768Sdelphij * NameLength is big enough before it checks for a 142276768Sdelphij * NULL buffer argument, so, while it'll still do 143276768Sdelphij * the right thing if NameLength is uninitialized and 144276768Sdelphij * whatever junk happens to be there is big enough 145276768Sdelphij * (because the pointer argument will be null), it's 146276768Sdelphij * still reading an uninitialized variable. 147276768Sdelphij */ 148276768Sdelphij NameLength = 0; 149172677Smlaier if (!PacketGetAdapterNames(NULL, &NameLength)) 150162012Ssam { 151172677Smlaier DWORD last_error = GetLastError(); 152172677Smlaier 153172677Smlaier if (last_error != ERROR_INSUFFICIENT_BUFFER) 154172677Smlaier { 155172677Smlaier snprintf(errbuf, PCAP_ERRBUF_SIZE, 156172677Smlaier "PacketGetAdapterNames: %s", 157172677Smlaier pcap_win32strerror()); 158172677Smlaier return (-1); 159172677Smlaier } 160162012Ssam } 161146768Ssam 162146768Ssam if (NameLength > 0) 163146768Ssam AdaptersName = (char*) malloc(NameLength); 164146768Ssam else 165146768Ssam { 166146768Ssam *alldevsp = NULL; 167146768Ssam return 0; 168146768Ssam } 169146768Ssam if (AdaptersName == NULL) 170146768Ssam { 171146768Ssam snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters."); 172146768Ssam return (-1); 173146768Ssam } 174146768Ssam 175127664Sbms if (!PacketGetAdapterNames(AdaptersName, &NameLength)) { 176127664Sbms snprintf(errbuf, PCAP_ERRBUF_SIZE, 177127664Sbms "PacketGetAdapterNames: %s", 178127664Sbms pcap_win32strerror()); 179146768Ssam free(AdaptersName); 180127664Sbms return (-1); 181127664Sbms } 182127664Sbms 183127664Sbms /* 184127664Sbms * "PacketGetAdapterNames()" returned a list of 185127664Sbms * null-terminated ASCII interface name strings, 186127664Sbms * terminated by a null string, followed by a list 187127664Sbms * of null-terminated ASCII interface description 188127664Sbms * strings, terminated by a null string. 189127664Sbms * This means there are two ASCII nulls at the end 190127664Sbms * of the first list. 191127664Sbms * 192127664Sbms * Find the end of the first list; that's the 193127664Sbms * beginning of the second list. 194127664Sbms */ 195127664Sbms desc = &AdaptersName[0]; 196127664Sbms while (*desc != '\0' || *(desc + 1) != '\0') 197127664Sbms desc++; 198127664Sbms 199127664Sbms /* 200127664Sbms * Found it - "desc" points to the first of the two 201127664Sbms * nulls at the end of the list of names, so the 202127664Sbms * first byte of the list of descriptions is two bytes 203127664Sbms * after it. 204127664Sbms */ 205127664Sbms desc += 2; 206127664Sbms 207127664Sbms /* 208127664Sbms * Loop over the elements in the first list. 209127664Sbms */ 210127664Sbms name = &AdaptersName[0]; 211127664Sbms while (*name != '\0') { 212146768Ssam /* 213146768Ssam * Add an entry for this interface. 214146768Ssam */ 215146768Ssam if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) { 216127664Sbms /* 217146768Ssam * Failure. 218146768Ssam */ 219127664Sbms ret = -1; 220127664Sbms break; 221127664Sbms } 222127664Sbms name += strlen(name) + 1; 223127664Sbms desc += strlen(desc) + 1; 224127664Sbms } 225190225Srpaulo 226190225Srpaulo if (ret != -1) { 227190225Srpaulo /* 228190225Srpaulo * We haven't had any errors yet; do any platform-specific 229190225Srpaulo * operations to add devices. 230190225Srpaulo */ 231190225Srpaulo if (pcap_platform_finddevs(&devlist, errbuf) < 0) 232190225Srpaulo ret = -1; 233190225Srpaulo } 234127664Sbms 235127664Sbms if (ret == -1) { 236146768Ssam /* 237146768Ssam * We had an error; free the list we've been constructing. 238146768Ssam */ 239146768Ssam if (devlist != NULL) { 240127664Sbms pcap_freealldevs(devlist); 241127664Sbms devlist = NULL; 242127664Sbms } 243127664Sbms } 244127664Sbms 245127664Sbms *alldevsp = devlist; 246146768Ssam free(AdaptersName); 247127664Sbms return (ret); 248127664Sbms} 249