inet.c revision 214518
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_ = 37214518Srpaulo "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.79 2008-04-20 18:19:02 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 * 369214518Srpaulo * Do NetBSD, DragonflyBSD, or OpenBSD support this as well? FreeBSD 370214518Srpaulo * and OpenBSD let you get a description, but it's not generated by the OS, 371214518Srpaulo * it's set with another ioctl that ifconfig supports; we use that to get 372214518Srpaulo * a description in FreeBSD and OpenBSD, but if there is no such 373214518Srpaulo * description available, it still might be nice to get some description 374214518Srpaulo * string based on the device type or something such as that. 375190225Srpaulo * 376190225Srpaulo * In OS X, the System Configuration framework can apparently return 377214518Srpaulo * names in 10.4 and later. 378190225Srpaulo * 379214518Srpaulo * It also appears that freedesktop.org's HAL offers an "info.product" 380214518Srpaulo * string, but the HAL specification says it "should not be used in any 381214518Srpaulo * UI" and "subsystem/capability specific properties" should be used 382214518Srpaulo * instead and, in any case, I think HAL is being deprecated in 383214518Srpaulo * favor of other stuff such as DeviceKit. DeviceKit doesn't appear 384214518Srpaulo * to have any obvious product information for devices, but maybe 385214518Srpaulo * I haven't looked hard enough. 386190225Srpaulo * 387214518Srpaulo * Using the System Configuration framework, or HAL, or DeviceKit, or 388214518Srpaulo * whatever, would require that libpcap applications be linked with 389214518Srpaulo * the frameworks/libraries in question. That shouldn't be a problem 390214518Srpaulo * for programs linking with the shared version of libpcap (unless 391214518Srpaulo * you're running on AIX - which I think is the only UN*X that doesn't 392214518Srpaulo * support linking a shared library with other libraries on which it 393214518Srpaulo * depends, and having an executable linked only with the first shared 394214518Srpaulo * library automatically pick up the other libraries when started - 395214518Srpaulo * and using HAL or whatever). Programs linked with the static 396214518Srpaulo * version of libpcap would have to use pcap-config with the --static 397214518Srpaulo * flag in order to get the right linker flags in order to pick up 398214518Srpaulo * the additional libraries/frameworks; those programs need that anyway 399214518Srpaulo * for libpcap 1.1 and beyond on Linux, as, by default, it requires 400214518Srpaulo * -lnl. 401190225Srpaulo * 402190225Srpaulo * Do any other UN*Xes, or desktop environments support getting a 403190225Srpaulo * description? 404190225Srpaulo */ 405127664Sbmsint 406146768Ssamadd_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags, 407127664Sbms struct sockaddr *addr, size_t addr_size, 408127664Sbms struct sockaddr *netmask, size_t netmask_size, 409127664Sbms struct sockaddr *broadaddr, size_t broadaddr_size, 410127664Sbms struct sockaddr *dstaddr, size_t dstaddr_size, 411127664Sbms char *errbuf) 41298530Sfenner{ 41398530Sfenner pcap_if_t *curdev; 414190225Srpaulo char *description = NULL; 41598530Sfenner pcap_addr_t *curaddr, *prevaddr, *nextaddr; 416214518Srpaulo#ifdef SIOCGIFDESCR 417203052Sdelphij int s; 418190225Srpaulo struct ifreq ifrdesc; 419203052Sdelphij#ifndef IFDESCRSIZE 420214518Srpaulo size_t descrlen = 64; 421203052Sdelphij#else 422214518Srpaulo size_t descrlen = IFDESCRSIZE; 423214518Srpaulo#endif /* IFDESCRSIZE */ 424214518Srpaulo#endif /* SIOCGIFDESCR */ 42598530Sfenner 426199231Sdelphij#ifdef SIOCGIFDESCR 427190225Srpaulo /* 428190225Srpaulo * Get the description for the interface. 429190225Srpaulo */ 430190225Srpaulo memset(&ifrdesc, 0, sizeof ifrdesc); 431190225Srpaulo strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name); 432190225Srpaulo s = socket(AF_INET, SOCK_DGRAM, 0); 433190225Srpaulo if (s >= 0) { 434214518Srpaulo for (;;) { 435214518Srpaulo free(description); 436214518Srpaulo if ((description = malloc(descrlen)) != NULL) { 437214518Srpaulo#ifdef __FreeBSD__ 438214518Srpaulo ifrdesc.ifr_buffer.buffer = description; 439214518Srpaulo ifrdesc.ifr_buffer.length = descrlen; 440214518Srpaulo#else /* __FreeBSD__ */ 441214518Srpaulo ifrdesc.ifr_data = (caddr_t)description; 442214518Srpaulo#endif /* __FreeBSD__ */ 443214518Srpaulo if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) 444214518Srpaulo break; 445214518Srpaulo#ifdef __FreeBSD__ 446214518Srpaulo else if (errno == ENAMETOOLONG) 447214518Srpaulo descrlen = ifrdesc.ifr_buffer.length; 448214518Srpaulo#endif /* __FreeBSD__ */ 449214518Srpaulo else 450214518Srpaulo break; 451214518Srpaulo } else 452214518Srpaulo break; 453214518Srpaulo } 454190225Srpaulo close(s); 455214518Srpaulo if (description != NULL && strlen(description) == 0) { 456214518Srpaulo free(description); 457214518Srpaulo description = NULL; 458214518Srpaulo } 459190225Srpaulo } 460214518Srpaulo#endif /* SIOCGIFDESCR */ 461190225Srpaulo 462190225Srpaulo if (add_or_find_if(&curdev, alldevs, name, flags, description, 463190225Srpaulo errbuf) == -1) { 464214518Srpaulo free(description); 46598530Sfenner /* 46698530Sfenner * Error - give up. 46798530Sfenner */ 46898530Sfenner return (-1); 46998530Sfenner } 470214518Srpaulo free(description); 47198530Sfenner if (curdev == NULL) { 47298530Sfenner /* 47398530Sfenner * Device wasn't added because it can't be opened. 47498530Sfenner * Not a fatal error. 47598530Sfenner */ 47698530Sfenner return (0); 47798530Sfenner } 47898530Sfenner 47998530Sfenner /* 48098530Sfenner * "curdev" is an entry for this interface; add an entry for this 48198530Sfenner * address to its list of addresses. 48298530Sfenner * 48398530Sfenner * Allocate the new entry and fill it in. 48498530Sfenner */ 48598530Sfenner curaddr = malloc(sizeof(pcap_addr_t)); 48698530Sfenner if (curaddr == NULL) { 48798530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 48898530Sfenner "malloc: %s", pcap_strerror(errno)); 48998530Sfenner return (-1); 49098530Sfenner } 49198530Sfenner 49298530Sfenner curaddr->next = NULL; 49398530Sfenner if (addr != NULL) { 494127664Sbms curaddr->addr = dup_sockaddr(addr, addr_size); 49598530Sfenner if (curaddr->addr == NULL) { 49698530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 49798530Sfenner "malloc: %s", pcap_strerror(errno)); 49898530Sfenner free(curaddr); 49998530Sfenner return (-1); 50098530Sfenner } 50198530Sfenner } else 50298530Sfenner curaddr->addr = NULL; 50398530Sfenner 50498530Sfenner if (netmask != NULL) { 505127664Sbms curaddr->netmask = dup_sockaddr(netmask, netmask_size); 50698530Sfenner if (curaddr->netmask == NULL) { 50798530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 50898530Sfenner "malloc: %s", pcap_strerror(errno)); 509172677Smlaier if (curaddr->addr != NULL) 510172677Smlaier free(curaddr->addr); 51198530Sfenner free(curaddr); 51298530Sfenner return (-1); 51398530Sfenner } 51498530Sfenner } else 51598530Sfenner curaddr->netmask = NULL; 516127664Sbms 51798530Sfenner if (broadaddr != NULL) { 518127664Sbms curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size); 51998530Sfenner if (curaddr->broadaddr == NULL) { 52098530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 52198530Sfenner "malloc: %s", pcap_strerror(errno)); 522172677Smlaier if (curaddr->netmask != NULL) 523172677Smlaier free(curaddr->netmask); 524172677Smlaier if (curaddr->addr != NULL) 525172677Smlaier free(curaddr->addr); 52698530Sfenner free(curaddr); 52798530Sfenner return (-1); 52898530Sfenner } 52998530Sfenner } else 53098530Sfenner curaddr->broadaddr = NULL; 531127664Sbms 53298530Sfenner if (dstaddr != NULL) { 533127664Sbms curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size); 53498530Sfenner if (curaddr->dstaddr == NULL) { 53598530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 53698530Sfenner "malloc: %s", pcap_strerror(errno)); 537172677Smlaier if (curaddr->broadaddr != NULL) 538172677Smlaier free(curaddr->broadaddr); 539172677Smlaier if (curaddr->netmask != NULL) 540172677Smlaier free(curaddr->netmask); 541172677Smlaier if (curaddr->addr != NULL) 542172677Smlaier free(curaddr->addr); 54398530Sfenner free(curaddr); 54498530Sfenner return (-1); 54598530Sfenner } 54698530Sfenner } else 54798530Sfenner curaddr->dstaddr = NULL; 548127664Sbms 54998530Sfenner /* 55098530Sfenner * Find the end of the list of addresses. 55198530Sfenner */ 55298530Sfenner for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) { 55398530Sfenner nextaddr = prevaddr->next; 55498530Sfenner if (nextaddr == NULL) { 55598530Sfenner /* 55698530Sfenner * This is the end of the list. 55798530Sfenner */ 55898530Sfenner break; 55998530Sfenner } 56098530Sfenner } 56198530Sfenner 56298530Sfenner if (prevaddr == NULL) { 56398530Sfenner /* 56498530Sfenner * The list was empty; this is the first member. 56598530Sfenner */ 56698530Sfenner curdev->addresses = curaddr; 56798530Sfenner } else { 56898530Sfenner /* 56998530Sfenner * "prevaddr" is the last member of the list; append 57098530Sfenner * this member to it. 57198530Sfenner */ 57298530Sfenner prevaddr->next = curaddr; 57398530Sfenner } 57498530Sfenner 57598530Sfenner return (0); 57698530Sfenner} 57798530Sfenner 578127664Sbmsint 579146768Ssampcap_add_if(pcap_if_t **devlist, const char *name, u_int flags, 58098530Sfenner const char *description, char *errbuf) 58198530Sfenner{ 58298530Sfenner pcap_if_t *curdev; 58398530Sfenner 58498530Sfenner return (add_or_find_if(&curdev, devlist, name, flags, description, 58598530Sfenner errbuf)); 58698530Sfenner} 58798530Sfenner 58875107Sfenner 58998530Sfenner/* 59098530Sfenner * Free a list of interfaces. 59198530Sfenner */ 59298530Sfennervoid 59398530Sfennerpcap_freealldevs(pcap_if_t *alldevs) 59498530Sfenner{ 59598530Sfenner pcap_if_t *curdev, *nextdev; 59698530Sfenner pcap_addr_t *curaddr, *nextaddr; 59798530Sfenner 59898530Sfenner for (curdev = alldevs; curdev != NULL; curdev = nextdev) { 59998530Sfenner nextdev = curdev->next; 60098530Sfenner 60198530Sfenner /* 60298530Sfenner * Free all addresses. 60398530Sfenner */ 60498530Sfenner for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) { 60598530Sfenner nextaddr = curaddr->next; 60698530Sfenner if (curaddr->addr) 60798530Sfenner free(curaddr->addr); 60898530Sfenner if (curaddr->netmask) 60998530Sfenner free(curaddr->netmask); 61098530Sfenner if (curaddr->broadaddr) 61198530Sfenner free(curaddr->broadaddr); 61298530Sfenner if (curaddr->dstaddr) 61398530Sfenner free(curaddr->dstaddr); 61498530Sfenner free(curaddr); 61598530Sfenner } 61698530Sfenner 61798530Sfenner /* 61898530Sfenner * Free the name string. 61998530Sfenner */ 62098530Sfenner free(curdev->name); 62198530Sfenner 62298530Sfenner /* 62398530Sfenner * Free the description string, if any. 62498530Sfenner */ 62598530Sfenner if (curdev->description != NULL) 62698530Sfenner free(curdev->description); 62798530Sfenner 62898530Sfenner /* 62998530Sfenner * Free the interface. 63098530Sfenner */ 63198530Sfenner free(curdev); 63298530Sfenner } 63398530Sfenner} 63498530Sfenner 635146768Ssam#if !defined(WIN32) && !defined(MSDOS) 636127664Sbms 63798530Sfenner/* 63898530Sfenner * Return the name of a network interface attached to the system, or NULL 63998530Sfenner * if none can be found. The interface must be configured up; the 64098530Sfenner * lowest unit number is preferred; loopback is ignored. 64198530Sfenner */ 64298530Sfennerchar * 64398530Sfennerpcap_lookupdev(errbuf) 64498530Sfenner register char *errbuf; 64598530Sfenner{ 64698530Sfenner pcap_if_t *alldevs; 64798530Sfenner/* for old BSD systems, including bsdi3 */ 64898530Sfenner#ifndef IF_NAMESIZE 64998530Sfenner#define IF_NAMESIZE IFNAMSIZ 65098530Sfenner#endif 65198530Sfenner static char device[IF_NAMESIZE + 1]; 65298530Sfenner char *ret; 65398530Sfenner 65498530Sfenner if (pcap_findalldevs(&alldevs, errbuf) == -1) 65598530Sfenner return (NULL); 656127664Sbms 65798530Sfenner if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) { 65898530Sfenner /* 65998530Sfenner * There are no devices on the list, or the first device 66098530Sfenner * on the list is a loopback device, which means there 66198530Sfenner * are no non-loopback devices on the list. This means 66298530Sfenner * we can't return any device. 66398530Sfenner * 66498530Sfenner * XXX - why not return a loopback device? If we can't 66598530Sfenner * capture on it, it won't be on the list, and if it's 66698530Sfenner * on the list, there aren't any non-loopback devices, 66798530Sfenner * so why not just supply it as the default device? 66898530Sfenner */ 66975107Sfenner (void)strlcpy(errbuf, "no suitable device found", 67075107Sfenner PCAP_ERRBUF_SIZE); 67198530Sfenner ret = NULL; 67298530Sfenner } else { 67398530Sfenner /* 67498530Sfenner * Return the name of the first device on the list. 67598530Sfenner */ 67698530Sfenner (void)strlcpy(device, alldevs->name, sizeof(device)); 67798530Sfenner ret = device; 67817683Spst } 67917683Spst 68098530Sfenner pcap_freealldevs(alldevs); 68198530Sfenner return (ret); 68217683Spst} 68317683Spst 68417683Spstint 68517683Spstpcap_lookupnet(device, netp, maskp, errbuf) 686127664Sbms register const char *device; 68717683Spst register bpf_u_int32 *netp, *maskp; 68817683Spst register char *errbuf; 68917683Spst{ 69017683Spst register int fd; 691172677Smlaier register struct sockaddr_in *sin4; 69217683Spst struct ifreq ifr; 69317683Spst 694127664Sbms /* 69575107Sfenner * The pseudo-device "any" listens on all interfaces and therefore 69675107Sfenner * has the network address and -mask "0.0.0.0" therefore catching 69775107Sfenner * all traffic. Using NULL for the interface is the same as "any". 69875107Sfenner */ 699127664Sbms if (!device || strcmp(device, "any") == 0 700127664Sbms#ifdef HAVE_DAG_API 701127664Sbms || strstr(device, "dag") != NULL 702127664Sbms#endif 703147894Ssam#ifdef HAVE_SEPTEL_API 704147894Ssam || strstr(device, "septel") != NULL 705147894Ssam#endif 706190225Srpaulo#ifdef PCAP_SUPPORT_BT 707190225Srpaulo || strstr(device, "bluetooth") != NULL 708190225Srpaulo#endif 709190225Srpaulo#ifdef PCAP_SUPPORT_USB 710214518Srpaulo || strstr(device, "usbmon") != NULL 711190225Srpaulo#endif 712214518Srpaulo#ifdef HAVE_SNF_API 713214518Srpaulo || strstr(device, "snf") != NULL 714214518Srpaulo#endif 715127664Sbms ) { 71675107Sfenner *netp = *maskp = 0; 71775107Sfenner return 0; 71875107Sfenner } 71975107Sfenner 72017683Spst fd = socket(AF_INET, SOCK_DGRAM, 0); 72117683Spst if (fd < 0) { 72275107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", 72375107Sfenner pcap_strerror(errno)); 72417683Spst return (-1); 72517683Spst } 72617683Spst memset(&ifr, 0, sizeof(ifr)); 72717683Spst#ifdef linux 72817683Spst /* XXX Work around Linux kernel bug */ 72917683Spst ifr.ifr_addr.sa_family = AF_INET; 73017683Spst#endif 73117683Spst (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 73217683Spst if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { 73356889Sfenner if (errno == EADDRNOTAVAIL) { 73475107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 73575107Sfenner "%s: no IPv4 address assigned", device); 73656889Sfenner } else { 73775107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 73875107Sfenner "SIOCGIFADDR: %s: %s", 73956889Sfenner device, pcap_strerror(errno)); 74056889Sfenner } 74117683Spst (void)close(fd); 74217683Spst return (-1); 74317683Spst } 744172677Smlaier sin4 = (struct sockaddr_in *)&ifr.ifr_addr; 745172677Smlaier *netp = sin4->sin_addr.s_addr; 746214518Srpaulo memset(&ifr, 0, sizeof(ifr)); 747214518Srpaulo#ifdef linux 748214518Srpaulo /* XXX Work around Linux kernel bug */ 749214518Srpaulo ifr.ifr_addr.sa_family = AF_INET; 750214518Srpaulo#endif 751214518Srpaulo (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 75217683Spst if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { 75375107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 75475107Sfenner "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno)); 75517683Spst (void)close(fd); 75617683Spst return (-1); 75717683Spst } 75817683Spst (void)close(fd); 759172677Smlaier *maskp = sin4->sin_addr.s_addr; 76017683Spst if (*maskp == 0) { 76117683Spst if (IN_CLASSA(*netp)) 76217683Spst *maskp = IN_CLASSA_NET; 76317683Spst else if (IN_CLASSB(*netp)) 76417683Spst *maskp = IN_CLASSB_NET; 76517683Spst else if (IN_CLASSC(*netp)) 76617683Spst *maskp = IN_CLASSC_NET; 76717683Spst else { 76875107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 76975107Sfenner "inet class for 0x%x unknown", *netp); 77017683Spst return (-1); 77117683Spst } 77217683Spst } 77317683Spst *netp &= *maskp; 77417683Spst return (0); 77517683Spst} 776127664Sbms 777146768Ssam#elif defined(WIN32) 778127664Sbms 779127664Sbms/* 780127664Sbms * Return the name of a network interface attached to the system, or NULL 781127664Sbms * if none can be found. The interface must be configured up; the 782127664Sbms * lowest unit number is preferred; loopback is ignored. 783127664Sbms */ 784127664Sbmschar * 785127664Sbmspcap_lookupdev(errbuf) 786127664Sbms register char *errbuf; 787127664Sbms{ 788127664Sbms DWORD dwVersion; 789127664Sbms DWORD dwWindowsMajorVersion; 790127664Sbms dwVersion = GetVersion(); /* get the OS version */ 791127664Sbms dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); 792127664Sbms 793127664Sbms if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) { 794127664Sbms /* 795127664Sbms * Windows 95, 98, ME. 796127664Sbms */ 797127664Sbms ULONG NameLength = 8192; 798127664Sbms static char AdaptersName[8192]; 799127664Sbms 800146768Ssam if (PacketGetAdapterNames(AdaptersName,&NameLength) ) 801146768Ssam return (AdaptersName); 802146768Ssam else 803146768Ssam return NULL; 804127664Sbms } else { 805127664Sbms /* 806127664Sbms * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility 807127664Sbms */ 808127664Sbms ULONG NameLength = 8192; 809127664Sbms static WCHAR AdaptersName[8192]; 810127664Sbms char *tAstr; 811127664Sbms WCHAR *tUstr; 812127664Sbms WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR)); 813127664Sbms int NAdapts = 0; 814127664Sbms 815127664Sbms if(TAdaptersName == NULL) 816127664Sbms { 817127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure"); 818127664Sbms return NULL; 819127664Sbms } 820127664Sbms 821146768Ssam if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) ) 822146768Ssam { 823146768Ssam (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 824146768Ssam "PacketGetAdapterNames: %s", 825146768Ssam pcap_win32strerror()); 826146768Ssam free(TAdaptersName); 827146768Ssam return NULL; 828146768Ssam } 829127664Sbms 830146768Ssam 831127664Sbms tAstr = (char*)TAdaptersName; 832127664Sbms tUstr = (WCHAR*)AdaptersName; 833127664Sbms 834127664Sbms /* 835127664Sbms * Convert and copy the device names 836127664Sbms */ 837127664Sbms while(sscanf(tAstr, "%S", tUstr) > 0) 838127664Sbms { 839127664Sbms tAstr += strlen(tAstr) + 1; 840127664Sbms tUstr += wcslen(tUstr) + 1; 841127664Sbms NAdapts ++; 842127664Sbms } 843127664Sbms 844127664Sbms tAstr++; 845127664Sbms *tUstr = 0; 846127664Sbms tUstr++; 847127664Sbms 848127664Sbms /* 849127664Sbms * Copy the descriptions 850127664Sbms */ 851127664Sbms while(NAdapts--) 852127664Sbms { 853127664Sbms strcpy((char*)tUstr, tAstr); 854127664Sbms (char*)tUstr += strlen(tAstr) + 1;; 855127664Sbms tAstr += strlen(tAstr) + 1; 856127664Sbms } 857127664Sbms 858146768Ssam free(TAdaptersName); 859127664Sbms return (char *)(AdaptersName); 860127664Sbms } 861127664Sbms} 862127664Sbms 863127664Sbms 864127664Sbmsint 865127664Sbmspcap_lookupnet(device, netp, maskp, errbuf) 866146768Ssam register const char *device; 867127664Sbms register bpf_u_int32 *netp, *maskp; 868127664Sbms register char *errbuf; 869127664Sbms{ 870127664Sbms /* 871127664Sbms * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo() 872127664Sbms * in order to skip non IPv4 (i.e. IPv6 addresses) 873127664Sbms */ 874127664Sbms npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; 875127664Sbms LONG if_addr_size = 1; 876127664Sbms struct sockaddr_in *t_addr; 877127664Sbms unsigned int i; 878127664Sbms 879127664Sbms if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) { 880127664Sbms *netp = *maskp = 0; 881127664Sbms return (0); 882127664Sbms } 883127664Sbms 884127664Sbms for(i=0; i<MAX_NETWORK_ADDRESSES; i++) 885127664Sbms { 886127664Sbms if(if_addrs[i].IPAddress.ss_family == AF_INET) 887127664Sbms { 888127664Sbms t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress); 889127664Sbms *netp = t_addr->sin_addr.S_un.S_addr; 890127664Sbms t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask); 891127664Sbms *maskp = t_addr->sin_addr.S_un.S_addr; 892127664Sbms 893127664Sbms *netp &= *maskp; 894127664Sbms return (0); 895127664Sbms } 896127664Sbms 897127664Sbms } 898127664Sbms 899127664Sbms *netp = *maskp = 0; 900127664Sbms return (0); 901127664Sbms} 902127664Sbms 903146768Ssam#endif /* !WIN32 && !MSDOS */ 904