inet.c revision 190225
198530Sfenner/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ 217683Spst/* 339291Sfenner * Copyright (c) 1994, 1995, 1996, 1997, 1998 417683Spst * The Regents of the University of California. All rights reserved. 517683Spst * 617683Spst * Redistribution and use in source and binary forms, with or without 717683Spst * modification, are permitted provided that the following conditions 817683Spst * are met: 917683Spst * 1. Redistributions of source code must retain the above copyright 1017683Spst * notice, this list of conditions and the following disclaimer. 1117683Spst * 2. Redistributions in binary form must reproduce the above copyright 1217683Spst * notice, this list of conditions and the following disclaimer in the 1317683Spst * documentation and/or other materials provided with the distribution. 1417683Spst * 3. All advertising materials mentioning features or use of this software 1517683Spst * must display the following acknowledgement: 1617683Spst * This product includes software developed by the Computer Systems 1717683Spst * Engineering Group at Lawrence Berkeley Laboratory. 1817683Spst * 4. Neither the name of the University nor of the Laboratory may be used 1917683Spst * to endorse or promote products derived from this software without 2017683Spst * specific prior written permission. 2117683Spst * 2217683Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2317683Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2417683Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2517683Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2617683Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2717683Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2817683Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2917683Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3017683Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3117683Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3217683Spst * SUCH DAMAGE. 3317683Spst */ 3417683Spst 3517683Spst#ifndef lint 36127664Sbmsstatic const char rcsid[] _U_ = 37190225Srpaulo "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.75.2.4 2008-04-20 18:19:24 guy Exp $ (LBL)"; 3817683Spst#endif 3917683Spst 4075107Sfenner#ifdef HAVE_CONFIG_H 4175107Sfenner#include "config.h" 4275107Sfenner#endif 4375107Sfenner 44127664Sbms#ifdef WIN32 45127664Sbms#include <pcap-stdinc.h> 46127664Sbms#else /* WIN32 */ 47127664Sbms 4817683Spst#include <sys/param.h> 49146768Ssam#ifndef MSDOS 5017683Spst#include <sys/file.h> 51146768Ssam#endif 5217683Spst#include <sys/ioctl.h> 5317683Spst#include <sys/socket.h> 5417683Spst#ifdef HAVE_SYS_SOCKIO_H 5517683Spst#include <sys/sockio.h> 5617683Spst#endif 5717683Spst 58127664Sbmsstruct mbuf; /* Squelch compiler warnings on some platforms for */ 59127664Sbmsstruct rtentry; /* declarations in <net/if.h> */ 6017683Spst#include <net/if.h> 6117683Spst#include <netinet/in.h> 62127664Sbms#endif /* WIN32 */ 6317683Spst 6417683Spst#include <ctype.h> 6517683Spst#include <errno.h> 6617683Spst#include <memory.h> 6717683Spst#include <stdio.h> 6817683Spst#include <stdlib.h> 6917683Spst#include <string.h> 70146768Ssam#if !defined(WIN32) && !defined(__BORLANDC__) 7117683Spst#include <unistd.h> 72146768Ssam#endif /* !WIN32 && !__BORLANDC__ */ 7398530Sfenner#ifdef HAVE_LIMITS_H 7498530Sfenner#include <limits.h> 7598530Sfenner#else 7698530Sfenner#define INT_MAX 2147483647 7798530Sfenner#endif 7817683Spst 7917683Spst#include "pcap-int.h" 8017683Spst 8117683Spst#ifdef HAVE_OS_PROTO_H 8217683Spst#include "os-proto.h" 8317683Spst#endif 8417683Spst 8517683Spst/* Not all systems have IFF_LOOPBACK */ 8617683Spst#ifdef IFF_LOOPBACK 8798530Sfenner#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK) 8817683Spst#else 8998530Sfenner#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \ 9098530Sfenner (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0')) 9117683Spst#endif 9217683Spst 93127664Sbmsstruct sockaddr * 94127664Sbmsdup_sockaddr(struct sockaddr *sa, size_t sa_length) 9517683Spst{ 9698530Sfenner struct sockaddr *newsa; 97127664Sbms 98127664Sbms if ((newsa = malloc(sa_length)) == NULL) 9998530Sfenner return (NULL); 100127664Sbms return (memcpy(newsa, sa, sa_length)); 10198530Sfenner} 10298530Sfenner 10398530Sfennerstatic int 104127664Sbmsget_instance(const char *name) 10598530Sfenner{ 106127664Sbms const char *cp, *endcp; 10798530Sfenner int n; 10898530Sfenner 10998530Sfenner if (strcmp(name, "any") == 0) { 11098530Sfenner /* 11198530Sfenner * Give the "any" device an artificially high instance 11298530Sfenner * number, so it shows up after all other non-loopback 11398530Sfenner * interfaces. 11498530Sfenner */ 11598530Sfenner return INT_MAX; 11698530Sfenner } 11798530Sfenner 11898530Sfenner endcp = name + strlen(name); 11998530Sfenner for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp) 12098530Sfenner continue; 12198530Sfenner 12298530Sfenner if (isdigit((unsigned char)*cp)) 12398530Sfenner n = atoi(cp); 12498530Sfenner else 12598530Sfenner n = 0; 12698530Sfenner return (n); 12798530Sfenner} 12898530Sfenner 129127664Sbmsint 130127664Sbmsadd_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name, 13198530Sfenner u_int flags, const char *description, char *errbuf) 13298530Sfenner{ 133146768Ssam pcap_t *p; 13498530Sfenner pcap_if_t *curdev, *prevdev, *nextdev; 13598530Sfenner int this_instance; 13698530Sfenner 13798530Sfenner /* 13898530Sfenner * Is there already an entry in the list for this interface? 13998530Sfenner */ 14098530Sfenner for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) { 14198530Sfenner if (strcmp(name, curdev->name) == 0) 14298530Sfenner break; /* yes, we found it */ 14398530Sfenner } 144172677Smlaier 14598530Sfenner if (curdev == NULL) { 14698530Sfenner /* 14798530Sfenner * No, we didn't find it. 148172677Smlaier * 149172677Smlaier * Can we open this interface for live capture? 150172677Smlaier * 151172677Smlaier * We do this check so that interfaces that are 152172677Smlaier * supplied by the interface enumeration mechanism 153172677Smlaier * we're using but that don't support packet capture 154172677Smlaier * aren't included in the list. Loopback interfaces 155172677Smlaier * on Solaris are an example of this; we don't just 156172677Smlaier * omit loopback interfaces on all platforms because 157172677Smlaier * you *can* capture on loopback interfaces on some 158172677Smlaier * OSes. 159172677Smlaier * 160172677Smlaier * On OS X, we don't do this check if the device 161172677Smlaier * name begins with "wlt"; at least some versions 162172677Smlaier * of OS X offer monitor mode capturing by having 163172677Smlaier * a separate "monitor mode" device for each wireless 164172677Smlaier * adapter, rather than by implementing the ioctls 165172677Smlaier * that {Free,Net,Open,DragonFly}BSD provide. 166172677Smlaier * Opening that device puts the adapter into monitor 167172677Smlaier * mode, which, at least for some adapters, causes 168172677Smlaier * them to deassociate from the network with which 169172677Smlaier * they're associated. 170172677Smlaier * 171172677Smlaier * Instead, we try to open the corresponding "en" 172172677Smlaier * device (so that we don't end up with, for users 173172677Smlaier * without sufficient privilege to open capture 174172677Smlaier * devices, a list of adapters that only includes 175172677Smlaier * the wlt devices). 176172677Smlaier */ 177172677Smlaier#ifdef __APPLE__ 178172677Smlaier if (strncmp(name, "wlt", 3) == 0) { 179172677Smlaier char *en_name; 180172677Smlaier size_t en_name_len; 181172677Smlaier 182172677Smlaier /* 183172677Smlaier * Try to allocate a buffer for the "en" 184172677Smlaier * device's name. 185172677Smlaier */ 186172677Smlaier en_name_len = strlen(name) - 1; 187172677Smlaier en_name = malloc(en_name_len + 1); 188172677Smlaier if (en_name == NULL) { 189172677Smlaier (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 190172677Smlaier "malloc: %s", pcap_strerror(errno)); 191172677Smlaier return (-1); 192172677Smlaier } 193172677Smlaier strcpy(en_name, "en"); 194172677Smlaier strcat(en_name, name + 3); 195172677Smlaier p = pcap_open_live(en_name, 68, 0, 0, errbuf); 196172677Smlaier free(en_name); 197172677Smlaier } else 198172677Smlaier#endif /* __APPLE */ 199172677Smlaier p = pcap_open_live(name, 68, 0, 0, errbuf); 200172677Smlaier if (p == NULL) { 201172677Smlaier /* 202172677Smlaier * No. Don't bother including it. 203172677Smlaier * Don't treat this as an error, though. 204172677Smlaier */ 205172677Smlaier *curdev_ret = NULL; 206172677Smlaier return (0); 207172677Smlaier } 208172677Smlaier pcap_close(p); 209172677Smlaier 210172677Smlaier /* 211172677Smlaier * Yes, we can open it. 21298530Sfenner * Allocate a new entry. 21398530Sfenner */ 21498530Sfenner curdev = malloc(sizeof(pcap_if_t)); 21598530Sfenner if (curdev == NULL) { 21698530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 21798530Sfenner "malloc: %s", pcap_strerror(errno)); 21898530Sfenner return (-1); 21998530Sfenner } 220127664Sbms 22198530Sfenner /* 22298530Sfenner * Fill in the entry. 22398530Sfenner */ 22498530Sfenner curdev->next = NULL; 225172677Smlaier curdev->name = strdup(name); 226172677Smlaier if (curdev->name == NULL) { 227172677Smlaier (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 228172677Smlaier "malloc: %s", pcap_strerror(errno)); 229172677Smlaier free(curdev); 230172677Smlaier return (-1); 231172677Smlaier } 23298530Sfenner if (description != NULL) { 23398530Sfenner /* 23498530Sfenner * We have a description for this interface. 23598530Sfenner */ 236172677Smlaier curdev->description = strdup(description); 237172677Smlaier if (curdev->description == NULL) { 238172677Smlaier (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 239172677Smlaier "malloc: %s", pcap_strerror(errno)); 240172677Smlaier free(curdev->name); 241172677Smlaier free(curdev); 242172677Smlaier return (-1); 243172677Smlaier } 24498530Sfenner } else { 24598530Sfenner /* 24698530Sfenner * We don't. 24798530Sfenner */ 24898530Sfenner curdev->description = NULL; 24998530Sfenner } 25098530Sfenner curdev->addresses = NULL; /* list starts out as empty */ 25198530Sfenner curdev->flags = 0; 25298530Sfenner if (ISLOOPBACK(name, flags)) 25398530Sfenner curdev->flags |= PCAP_IF_LOOPBACK; 25498530Sfenner 25598530Sfenner /* 25698530Sfenner * Add it to the list, in the appropriate location. 25798530Sfenner * First, get the instance number of this interface. 25898530Sfenner */ 25998530Sfenner this_instance = get_instance(name); 26098530Sfenner 26198530Sfenner /* 26298530Sfenner * Now look for the last interface with an instance number 26398530Sfenner * less than or equal to the new interface's instance 26498530Sfenner * number - except that non-loopback interfaces are 26598530Sfenner * arbitrarily treated as having interface numbers less 26698530Sfenner * than those of loopback interfaces, so the loopback 26798530Sfenner * interfaces are put at the end of the list. 26898530Sfenner * 26998530Sfenner * We start with "prevdev" being NULL, meaning we're before 27098530Sfenner * the first element in the list. 27198530Sfenner */ 27298530Sfenner prevdev = NULL; 27398530Sfenner for (;;) { 27498530Sfenner /* 27598530Sfenner * Get the interface after this one. 27698530Sfenner */ 27798530Sfenner if (prevdev == NULL) { 27898530Sfenner /* 27998530Sfenner * The next element is the first element. 28098530Sfenner */ 28198530Sfenner nextdev = *alldevs; 28298530Sfenner } else 28398530Sfenner nextdev = prevdev->next; 28498530Sfenner 28598530Sfenner /* 28698530Sfenner * Are we at the end of the list? 28798530Sfenner */ 28898530Sfenner if (nextdev == NULL) { 28998530Sfenner /* 29098530Sfenner * Yes - we have to put the new entry 29198530Sfenner * after "prevdev". 29298530Sfenner */ 29398530Sfenner break; 29498530Sfenner } 29598530Sfenner 29698530Sfenner /* 29798530Sfenner * Is the new interface a non-loopback interface 29898530Sfenner * and the next interface a loopback interface? 29998530Sfenner */ 30098530Sfenner if (!(curdev->flags & PCAP_IF_LOOPBACK) && 30198530Sfenner (nextdev->flags & PCAP_IF_LOOPBACK)) { 30298530Sfenner /* 30398530Sfenner * Yes, we should put the new entry 30498530Sfenner * before "nextdev", i.e. after "prevdev". 30598530Sfenner */ 30698530Sfenner break; 30798530Sfenner } 30898530Sfenner 30998530Sfenner /* 31098530Sfenner * Is the new interface's instance number less 31198530Sfenner * than the next interface's instance number, 31298530Sfenner * and is it the case that the new interface is a 31398530Sfenner * non-loopback interface or the next interface is 31498530Sfenner * a loopback interface? 31598530Sfenner * 31698530Sfenner * (The goal of both loopback tests is to make 31798530Sfenner * sure that we never put a loopback interface 31898530Sfenner * before any non-loopback interface and that we 31998530Sfenner * always put a non-loopback interface before all 32098530Sfenner * loopback interfaces.) 32198530Sfenner */ 32298530Sfenner if (this_instance < get_instance(nextdev->name) && 32398530Sfenner (!(curdev->flags & PCAP_IF_LOOPBACK) || 32498530Sfenner (nextdev->flags & PCAP_IF_LOOPBACK))) { 32598530Sfenner /* 32698530Sfenner * Yes - we should put the new entry 32798530Sfenner * before "nextdev", i.e. after "prevdev". 32898530Sfenner */ 32998530Sfenner break; 33098530Sfenner } 33198530Sfenner 33298530Sfenner prevdev = nextdev; 33398530Sfenner } 33498530Sfenner 33598530Sfenner /* 33698530Sfenner * Insert before "nextdev". 33798530Sfenner */ 33898530Sfenner curdev->next = nextdev; 33998530Sfenner 34098530Sfenner /* 34198530Sfenner * Insert after "prevdev" - unless "prevdev" is null, 34298530Sfenner * in which case this is the first interface. 34398530Sfenner */ 34498530Sfenner if (prevdev == NULL) { 34598530Sfenner /* 34698530Sfenner * This is the first interface. Pass back a 34798530Sfenner * pointer to it, and put "curdev" before 34898530Sfenner * "nextdev". 34998530Sfenner */ 35098530Sfenner *alldevs = curdev; 35198530Sfenner } else 35298530Sfenner prevdev->next = curdev; 35398530Sfenner } 354127664Sbms 35598530Sfenner *curdev_ret = curdev; 35698530Sfenner return (0); 35798530Sfenner} 35898530Sfenner 359190225Srpaulo/* 360190225Srpaulo * XXX - on FreeBSDs that support it, should it get the sysctl named 361190225Srpaulo * "dev.{adapter family name}.{adapter unit}.%desc" to get a description 362190225Srpaulo * of the adapter? Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800" 363190225Srpaulo * with my Cisco 350 card, so the name isn't entirely descriptive. The 364190225Srpaulo * "dev.an.0.%pnpinfo" has a better description, although one might argue 365190225Srpaulo * that the problem is really a driver bug - if it can find out that it's 366190225Srpaulo * a Cisco 340 or 350, rather than an old Aironet card, it should use 367190225Srpaulo * that in the description. 368190225Srpaulo * 369190225Srpaulo * Do NetBSD, DragonflyBSD, or OpenBSD support this as well? OpenBSD 370190225Srpaulo * lets you get a description, but it's not generated by the OS, it's 371190225Srpaulo * set with another ioctl that ifconfig supports; we use that to get 372190225Srpaulo * the description in OpenBSD. 373190225Srpaulo * 374190225Srpaulo * In OS X, the System Configuration framework can apparently return 375190225Srpaulo * names in 10.4 and later; it also appears that freedesktop.org's HAL 376190225Srpaulo * offers an "info.product" string, but the HAL specification says 377190225Srpaulo * it "should not be used in any UI" and "subsystem/capability 378190225Srpaulo * specific properties" should be used instead. Using that would 379190225Srpaulo * require that libpcap applications be linked with the frameworks/ 380190225Srpaulo * libraries in question, which would be a bit of a pain unless we 381190225Srpaulo * offer, for example, a pkg-config: 382190225Srpaulo * 383190225Srpaulo * http://pkg-config.freedesktop.org/wiki/ 384190225Srpaulo * 385190225Srpaulo * script, so applications can just use that script to find out what 386190225Srpaulo * libraries you need to link with when linking with libpcap. 387190225Srpaulo * pkg-config is GPLed; I don't know whether that would prevent its 388190225Srpaulo * use with a BSD-licensed library such as libpcap. 389190225Srpaulo * 390190225Srpaulo * Do any other UN*Xes, or desktop environments support getting a 391190225Srpaulo * description? 392190225Srpaulo */ 393127664Sbmsint 394146768Ssamadd_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags, 395127664Sbms struct sockaddr *addr, size_t addr_size, 396127664Sbms struct sockaddr *netmask, size_t netmask_size, 397127664Sbms struct sockaddr *broadaddr, size_t broadaddr_size, 398127664Sbms struct sockaddr *dstaddr, size_t dstaddr_size, 399127664Sbms char *errbuf) 40098530Sfenner{ 40198530Sfenner pcap_if_t *curdev; 402190225Srpaulo char *description = NULL; 40398530Sfenner pcap_addr_t *curaddr, *prevaddr, *nextaddr; 404190225Srpaulo#ifdef SIOCGIFDESCR 405190225Srpaulo struct ifreq ifrdesc; 406190225Srpaulo char ifdescr[IFDESCRSIZE]; 407190225Srpaulo int s; 408190225Srpaulo#endif 40998530Sfenner 410190225Srpaulo#ifdef SIOCGIFDESCR 411190225Srpaulo /* 412190225Srpaulo * Get the description for the interface. 413190225Srpaulo */ 414190225Srpaulo memset(&ifrdesc, 0, sizeof ifrdesc); 415190225Srpaulo strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name); 416190225Srpaulo ifrdesc.ifr_data = (caddr_t)&ifdescr; 417190225Srpaulo s = socket(AF_INET, SOCK_DGRAM, 0); 418190225Srpaulo if (s >= 0) { 419190225Srpaulo if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0 && 420190225Srpaulo strlen(ifrdesc.ifr_data) != 0) 421190225Srpaulo description = ifrdesc.ifr_data; 422190225Srpaulo close(s); 423190225Srpaulo } 424190225Srpaulo#endif 425190225Srpaulo 426190225Srpaulo if (add_or_find_if(&curdev, alldevs, name, flags, description, 427190225Srpaulo errbuf) == -1) { 42898530Sfenner /* 42998530Sfenner * Error - give up. 43098530Sfenner */ 43198530Sfenner return (-1); 43298530Sfenner } 43398530Sfenner if (curdev == NULL) { 43498530Sfenner /* 43598530Sfenner * Device wasn't added because it can't be opened. 43698530Sfenner * Not a fatal error. 43798530Sfenner */ 43898530Sfenner return (0); 43998530Sfenner } 44098530Sfenner 44198530Sfenner /* 44298530Sfenner * "curdev" is an entry for this interface; add an entry for this 44398530Sfenner * address to its list of addresses. 44498530Sfenner * 44598530Sfenner * Allocate the new entry and fill it in. 44698530Sfenner */ 44798530Sfenner curaddr = malloc(sizeof(pcap_addr_t)); 44898530Sfenner if (curaddr == NULL) { 44998530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 45098530Sfenner "malloc: %s", pcap_strerror(errno)); 45198530Sfenner return (-1); 45298530Sfenner } 45398530Sfenner 45498530Sfenner curaddr->next = NULL; 45598530Sfenner if (addr != NULL) { 456127664Sbms curaddr->addr = dup_sockaddr(addr, addr_size); 45798530Sfenner if (curaddr->addr == NULL) { 45898530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 45998530Sfenner "malloc: %s", pcap_strerror(errno)); 46098530Sfenner free(curaddr); 46198530Sfenner return (-1); 46298530Sfenner } 46398530Sfenner } else 46498530Sfenner curaddr->addr = NULL; 46598530Sfenner 46698530Sfenner if (netmask != NULL) { 467127664Sbms curaddr->netmask = dup_sockaddr(netmask, netmask_size); 46898530Sfenner if (curaddr->netmask == NULL) { 46998530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 47098530Sfenner "malloc: %s", pcap_strerror(errno)); 471172677Smlaier if (curaddr->addr != NULL) 472172677Smlaier free(curaddr->addr); 47398530Sfenner free(curaddr); 47498530Sfenner return (-1); 47598530Sfenner } 47698530Sfenner } else 47798530Sfenner curaddr->netmask = NULL; 478127664Sbms 47998530Sfenner if (broadaddr != NULL) { 480127664Sbms curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size); 48198530Sfenner if (curaddr->broadaddr == NULL) { 48298530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 48398530Sfenner "malloc: %s", pcap_strerror(errno)); 484172677Smlaier if (curaddr->netmask != NULL) 485172677Smlaier free(curaddr->netmask); 486172677Smlaier if (curaddr->addr != NULL) 487172677Smlaier free(curaddr->addr); 48898530Sfenner free(curaddr); 48998530Sfenner return (-1); 49098530Sfenner } 49198530Sfenner } else 49298530Sfenner curaddr->broadaddr = NULL; 493127664Sbms 49498530Sfenner if (dstaddr != NULL) { 495127664Sbms curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size); 49698530Sfenner if (curaddr->dstaddr == NULL) { 49798530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 49898530Sfenner "malloc: %s", pcap_strerror(errno)); 499172677Smlaier if (curaddr->broadaddr != NULL) 500172677Smlaier free(curaddr->broadaddr); 501172677Smlaier if (curaddr->netmask != NULL) 502172677Smlaier free(curaddr->netmask); 503172677Smlaier if (curaddr->addr != NULL) 504172677Smlaier free(curaddr->addr); 50598530Sfenner free(curaddr); 50698530Sfenner return (-1); 50798530Sfenner } 50898530Sfenner } else 50998530Sfenner curaddr->dstaddr = NULL; 510127664Sbms 51198530Sfenner /* 51298530Sfenner * Find the end of the list of addresses. 51398530Sfenner */ 51498530Sfenner for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) { 51598530Sfenner nextaddr = prevaddr->next; 51698530Sfenner if (nextaddr == NULL) { 51798530Sfenner /* 51898530Sfenner * This is the end of the list. 51998530Sfenner */ 52098530Sfenner break; 52198530Sfenner } 52298530Sfenner } 52398530Sfenner 52498530Sfenner if (prevaddr == NULL) { 52598530Sfenner /* 52698530Sfenner * The list was empty; this is the first member. 52798530Sfenner */ 52898530Sfenner curdev->addresses = curaddr; 52998530Sfenner } else { 53098530Sfenner /* 53198530Sfenner * "prevaddr" is the last member of the list; append 53298530Sfenner * this member to it. 53398530Sfenner */ 53498530Sfenner prevaddr->next = curaddr; 53598530Sfenner } 53698530Sfenner 53798530Sfenner return (0); 53898530Sfenner} 53998530Sfenner 540127664Sbmsint 541146768Ssampcap_add_if(pcap_if_t **devlist, const char *name, u_int flags, 54298530Sfenner const char *description, char *errbuf) 54398530Sfenner{ 54498530Sfenner pcap_if_t *curdev; 54598530Sfenner 54698530Sfenner return (add_or_find_if(&curdev, devlist, name, flags, description, 54798530Sfenner errbuf)); 54898530Sfenner} 54998530Sfenner 55075107Sfenner 55198530Sfenner/* 55298530Sfenner * Free a list of interfaces. 55398530Sfenner */ 55498530Sfennervoid 55598530Sfennerpcap_freealldevs(pcap_if_t *alldevs) 55698530Sfenner{ 55798530Sfenner pcap_if_t *curdev, *nextdev; 55898530Sfenner pcap_addr_t *curaddr, *nextaddr; 55998530Sfenner 56098530Sfenner for (curdev = alldevs; curdev != NULL; curdev = nextdev) { 56198530Sfenner nextdev = curdev->next; 56298530Sfenner 56398530Sfenner /* 56498530Sfenner * Free all addresses. 56598530Sfenner */ 56698530Sfenner for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) { 56798530Sfenner nextaddr = curaddr->next; 56898530Sfenner if (curaddr->addr) 56998530Sfenner free(curaddr->addr); 57098530Sfenner if (curaddr->netmask) 57198530Sfenner free(curaddr->netmask); 57298530Sfenner if (curaddr->broadaddr) 57398530Sfenner free(curaddr->broadaddr); 57498530Sfenner if (curaddr->dstaddr) 57598530Sfenner free(curaddr->dstaddr); 57698530Sfenner free(curaddr); 57798530Sfenner } 57898530Sfenner 57998530Sfenner /* 58098530Sfenner * Free the name string. 58198530Sfenner */ 58298530Sfenner free(curdev->name); 58398530Sfenner 58498530Sfenner /* 58598530Sfenner * Free the description string, if any. 58698530Sfenner */ 58798530Sfenner if (curdev->description != NULL) 58898530Sfenner free(curdev->description); 58998530Sfenner 59098530Sfenner /* 59198530Sfenner * Free the interface. 59298530Sfenner */ 59398530Sfenner free(curdev); 59498530Sfenner } 59598530Sfenner} 59698530Sfenner 597146768Ssam#if !defined(WIN32) && !defined(MSDOS) 598127664Sbms 59998530Sfenner/* 60098530Sfenner * Return the name of a network interface attached to the system, or NULL 60198530Sfenner * if none can be found. The interface must be configured up; the 60298530Sfenner * lowest unit number is preferred; loopback is ignored. 60398530Sfenner */ 60498530Sfennerchar * 60598530Sfennerpcap_lookupdev(errbuf) 60698530Sfenner register char *errbuf; 60798530Sfenner{ 60898530Sfenner pcap_if_t *alldevs; 60998530Sfenner/* for old BSD systems, including bsdi3 */ 61098530Sfenner#ifndef IF_NAMESIZE 61198530Sfenner#define IF_NAMESIZE IFNAMSIZ 61298530Sfenner#endif 61398530Sfenner static char device[IF_NAMESIZE + 1]; 61498530Sfenner char *ret; 61598530Sfenner 61698530Sfenner if (pcap_findalldevs(&alldevs, errbuf) == -1) 61798530Sfenner return (NULL); 618127664Sbms 61998530Sfenner if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) { 62098530Sfenner /* 62198530Sfenner * There are no devices on the list, or the first device 62298530Sfenner * on the list is a loopback device, which means there 62398530Sfenner * are no non-loopback devices on the list. This means 62498530Sfenner * we can't return any device. 62598530Sfenner * 62698530Sfenner * XXX - why not return a loopback device? If we can't 62798530Sfenner * capture on it, it won't be on the list, and if it's 62898530Sfenner * on the list, there aren't any non-loopback devices, 62998530Sfenner * so why not just supply it as the default device? 63098530Sfenner */ 63175107Sfenner (void)strlcpy(errbuf, "no suitable device found", 63275107Sfenner PCAP_ERRBUF_SIZE); 63398530Sfenner ret = NULL; 63498530Sfenner } else { 63598530Sfenner /* 63698530Sfenner * Return the name of the first device on the list. 63798530Sfenner */ 63898530Sfenner (void)strlcpy(device, alldevs->name, sizeof(device)); 63998530Sfenner ret = device; 64017683Spst } 64117683Spst 64298530Sfenner pcap_freealldevs(alldevs); 64398530Sfenner return (ret); 64417683Spst} 64517683Spst 64617683Spstint 64717683Spstpcap_lookupnet(device, netp, maskp, errbuf) 648127664Sbms register const char *device; 64917683Spst register bpf_u_int32 *netp, *maskp; 65017683Spst register char *errbuf; 65117683Spst{ 65217683Spst register int fd; 653172677Smlaier register struct sockaddr_in *sin4; 65417683Spst struct ifreq ifr; 65517683Spst 656127664Sbms /* 65775107Sfenner * The pseudo-device "any" listens on all interfaces and therefore 65875107Sfenner * has the network address and -mask "0.0.0.0" therefore catching 65975107Sfenner * all traffic. Using NULL for the interface is the same as "any". 66075107Sfenner */ 661127664Sbms if (!device || strcmp(device, "any") == 0 662127664Sbms#ifdef HAVE_DAG_API 663127664Sbms || strstr(device, "dag") != NULL 664127664Sbms#endif 665147894Ssam#ifdef HAVE_SEPTEL_API 666147894Ssam || strstr(device, "septel") != NULL 667147894Ssam#endif 668190225Srpaulo#ifdef PCAP_SUPPORT_BT 669190225Srpaulo || strstr(device, "bluetooth") != NULL 670190225Srpaulo#endif 671190225Srpaulo#ifdef PCAP_SUPPORT_USB 672190225Srpaulo || strstr(device, "usb") != NULL 673190225Srpaulo#endif 674127664Sbms ) { 67575107Sfenner *netp = *maskp = 0; 67675107Sfenner return 0; 67775107Sfenner } 67875107Sfenner 67917683Spst fd = socket(AF_INET, SOCK_DGRAM, 0); 68017683Spst if (fd < 0) { 68175107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", 68275107Sfenner pcap_strerror(errno)); 68317683Spst return (-1); 68417683Spst } 68517683Spst memset(&ifr, 0, sizeof(ifr)); 68617683Spst#ifdef linux 68717683Spst /* XXX Work around Linux kernel bug */ 68817683Spst ifr.ifr_addr.sa_family = AF_INET; 68917683Spst#endif 69017683Spst (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 69117683Spst if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { 69256889Sfenner if (errno == EADDRNOTAVAIL) { 69375107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 69475107Sfenner "%s: no IPv4 address assigned", device); 69556889Sfenner } else { 69675107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 69775107Sfenner "SIOCGIFADDR: %s: %s", 69856889Sfenner device, pcap_strerror(errno)); 69956889Sfenner } 70017683Spst (void)close(fd); 70117683Spst return (-1); 70217683Spst } 703172677Smlaier sin4 = (struct sockaddr_in *)&ifr.ifr_addr; 704172677Smlaier *netp = sin4->sin_addr.s_addr; 70517683Spst if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { 70675107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 70775107Sfenner "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno)); 70817683Spst (void)close(fd); 70917683Spst return (-1); 71017683Spst } 71117683Spst (void)close(fd); 712172677Smlaier *maskp = sin4->sin_addr.s_addr; 71317683Spst if (*maskp == 0) { 71417683Spst if (IN_CLASSA(*netp)) 71517683Spst *maskp = IN_CLASSA_NET; 71617683Spst else if (IN_CLASSB(*netp)) 71717683Spst *maskp = IN_CLASSB_NET; 71817683Spst else if (IN_CLASSC(*netp)) 71917683Spst *maskp = IN_CLASSC_NET; 72017683Spst else { 72175107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 72275107Sfenner "inet class for 0x%x unknown", *netp); 72317683Spst return (-1); 72417683Spst } 72517683Spst } 72617683Spst *netp &= *maskp; 72717683Spst return (0); 72817683Spst} 729127664Sbms 730146768Ssam#elif defined(WIN32) 731127664Sbms 732127664Sbms/* 733127664Sbms * Return the name of a network interface attached to the system, or NULL 734127664Sbms * if none can be found. The interface must be configured up; the 735127664Sbms * lowest unit number is preferred; loopback is ignored. 736127664Sbms */ 737127664Sbmschar * 738127664Sbmspcap_lookupdev(errbuf) 739127664Sbms register char *errbuf; 740127664Sbms{ 741127664Sbms DWORD dwVersion; 742127664Sbms DWORD dwWindowsMajorVersion; 743127664Sbms dwVersion = GetVersion(); /* get the OS version */ 744127664Sbms dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); 745127664Sbms 746127664Sbms if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) { 747127664Sbms /* 748127664Sbms * Windows 95, 98, ME. 749127664Sbms */ 750127664Sbms ULONG NameLength = 8192; 751127664Sbms static char AdaptersName[8192]; 752127664Sbms 753146768Ssam if (PacketGetAdapterNames(AdaptersName,&NameLength) ) 754146768Ssam return (AdaptersName); 755146768Ssam else 756146768Ssam return NULL; 757127664Sbms } else { 758127664Sbms /* 759127664Sbms * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility 760127664Sbms */ 761127664Sbms ULONG NameLength = 8192; 762127664Sbms static WCHAR AdaptersName[8192]; 763127664Sbms char *tAstr; 764127664Sbms WCHAR *tUstr; 765127664Sbms WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR)); 766127664Sbms int NAdapts = 0; 767127664Sbms 768127664Sbms if(TAdaptersName == NULL) 769127664Sbms { 770127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure"); 771127664Sbms return NULL; 772127664Sbms } 773127664Sbms 774146768Ssam if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) ) 775146768Ssam { 776146768Ssam (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 777146768Ssam "PacketGetAdapterNames: %s", 778146768Ssam pcap_win32strerror()); 779146768Ssam free(TAdaptersName); 780146768Ssam return NULL; 781146768Ssam } 782127664Sbms 783146768Ssam 784127664Sbms tAstr = (char*)TAdaptersName; 785127664Sbms tUstr = (WCHAR*)AdaptersName; 786127664Sbms 787127664Sbms /* 788127664Sbms * Convert and copy the device names 789127664Sbms */ 790127664Sbms while(sscanf(tAstr, "%S", tUstr) > 0) 791127664Sbms { 792127664Sbms tAstr += strlen(tAstr) + 1; 793127664Sbms tUstr += wcslen(tUstr) + 1; 794127664Sbms NAdapts ++; 795127664Sbms } 796127664Sbms 797127664Sbms tAstr++; 798127664Sbms *tUstr = 0; 799127664Sbms tUstr++; 800127664Sbms 801127664Sbms /* 802127664Sbms * Copy the descriptions 803127664Sbms */ 804127664Sbms while(NAdapts--) 805127664Sbms { 806127664Sbms strcpy((char*)tUstr, tAstr); 807127664Sbms (char*)tUstr += strlen(tAstr) + 1;; 808127664Sbms tAstr += strlen(tAstr) + 1; 809127664Sbms } 810127664Sbms 811146768Ssam free(TAdaptersName); 812127664Sbms return (char *)(AdaptersName); 813127664Sbms } 814127664Sbms} 815127664Sbms 816127664Sbms 817127664Sbmsint 818127664Sbmspcap_lookupnet(device, netp, maskp, errbuf) 819146768Ssam register const char *device; 820127664Sbms register bpf_u_int32 *netp, *maskp; 821127664Sbms register char *errbuf; 822127664Sbms{ 823127664Sbms /* 824127664Sbms * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo() 825127664Sbms * in order to skip non IPv4 (i.e. IPv6 addresses) 826127664Sbms */ 827127664Sbms npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; 828127664Sbms LONG if_addr_size = 1; 829127664Sbms struct sockaddr_in *t_addr; 830127664Sbms unsigned int i; 831127664Sbms 832127664Sbms if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) { 833127664Sbms *netp = *maskp = 0; 834127664Sbms return (0); 835127664Sbms } 836127664Sbms 837127664Sbms for(i=0; i<MAX_NETWORK_ADDRESSES; i++) 838127664Sbms { 839127664Sbms if(if_addrs[i].IPAddress.ss_family == AF_INET) 840127664Sbms { 841127664Sbms t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress); 842127664Sbms *netp = t_addr->sin_addr.S_un.S_addr; 843127664Sbms t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask); 844127664Sbms *maskp = t_addr->sin_addr.S_un.S_addr; 845127664Sbms 846127664Sbms *netp &= *maskp; 847127664Sbms return (0); 848127664Sbms } 849127664Sbms 850127664Sbms } 851127664Sbms 852127664Sbms *netp = *maskp = 0; 853127664Sbms return (0); 854127664Sbms} 855127664Sbms 856146768Ssam#endif /* !WIN32 && !MSDOS */ 857