inet.c revision 277722
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; 136235426Sdelphij char open_errbuf[PCAP_ERRBUF_SIZE]; 13798530Sfenner 13898530Sfenner /* 13998530Sfenner * Is there already an entry in the list for this interface? 14098530Sfenner */ 14198530Sfenner for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) { 14298530Sfenner if (strcmp(name, curdev->name) == 0) 14398530Sfenner break; /* yes, we found it */ 14498530Sfenner } 145172677Smlaier 14698530Sfenner if (curdev == NULL) { 14798530Sfenner /* 14898530Sfenner * No, we didn't find it. 149172677Smlaier * 150172677Smlaier * Can we open this interface for live capture? 151172677Smlaier * 152172677Smlaier * We do this check so that interfaces that are 153172677Smlaier * supplied by the interface enumeration mechanism 154172677Smlaier * we're using but that don't support packet capture 155172677Smlaier * aren't included in the list. Loopback interfaces 156172677Smlaier * on Solaris are an example of this; we don't just 157172677Smlaier * omit loopback interfaces on all platforms because 158172677Smlaier * you *can* capture on loopback interfaces on some 159172677Smlaier * OSes. 160172677Smlaier * 161172677Smlaier * On OS X, we don't do this check if the device 162172677Smlaier * name begins with "wlt"; at least some versions 163172677Smlaier * of OS X offer monitor mode capturing by having 164172677Smlaier * a separate "monitor mode" device for each wireless 165172677Smlaier * adapter, rather than by implementing the ioctls 166172677Smlaier * that {Free,Net,Open,DragonFly}BSD provide. 167172677Smlaier * Opening that device puts the adapter into monitor 168172677Smlaier * mode, which, at least for some adapters, causes 169172677Smlaier * them to deassociate from the network with which 170172677Smlaier * they're associated. 171172677Smlaier * 172172677Smlaier * Instead, we try to open the corresponding "en" 173172677Smlaier * device (so that we don't end up with, for users 174172677Smlaier * without sufficient privilege to open capture 175172677Smlaier * devices, a list of adapters that only includes 176172677Smlaier * the wlt devices). 177172677Smlaier */ 178172677Smlaier#ifdef __APPLE__ 179172677Smlaier if (strncmp(name, "wlt", 3) == 0) { 180172677Smlaier char *en_name; 181172677Smlaier size_t en_name_len; 182172677Smlaier 183172677Smlaier /* 184172677Smlaier * Try to allocate a buffer for the "en" 185172677Smlaier * device's name. 186172677Smlaier */ 187172677Smlaier en_name_len = strlen(name) - 1; 188172677Smlaier en_name = malloc(en_name_len + 1); 189172677Smlaier if (en_name == NULL) { 190172677Smlaier (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 191172677Smlaier "malloc: %s", pcap_strerror(errno)); 192172677Smlaier return (-1); 193172677Smlaier } 194172677Smlaier strcpy(en_name, "en"); 195172677Smlaier strcat(en_name, name + 3); 196235426Sdelphij p = pcap_open_live(en_name, 68, 0, 0, open_errbuf); 197172677Smlaier free(en_name); 198172677Smlaier } else 199172677Smlaier#endif /* __APPLE */ 200235426Sdelphij p = pcap_open_live(name, 68, 0, 0, open_errbuf); 201172677Smlaier if (p == NULL) { 202172677Smlaier /* 203172677Smlaier * No. Don't bother including it. 204172677Smlaier * Don't treat this as an error, though. 205172677Smlaier */ 206172677Smlaier *curdev_ret = NULL; 207172677Smlaier return (0); 208172677Smlaier } 209172677Smlaier pcap_close(p); 210172677Smlaier 211172677Smlaier /* 212172677Smlaier * Yes, we can open it. 21398530Sfenner * Allocate a new entry. 21498530Sfenner */ 21598530Sfenner curdev = malloc(sizeof(pcap_if_t)); 21698530Sfenner if (curdev == NULL) { 21798530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 21898530Sfenner "malloc: %s", pcap_strerror(errno)); 21998530Sfenner return (-1); 22098530Sfenner } 221127664Sbms 22298530Sfenner /* 22398530Sfenner * Fill in the entry. 22498530Sfenner */ 22598530Sfenner curdev->next = NULL; 226172677Smlaier curdev->name = strdup(name); 227172677Smlaier if (curdev->name == NULL) { 228172677Smlaier (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 229172677Smlaier "malloc: %s", pcap_strerror(errno)); 230172677Smlaier free(curdev); 231172677Smlaier return (-1); 232172677Smlaier } 23398530Sfenner if (description != NULL) { 23498530Sfenner /* 23598530Sfenner * We have a description for this interface. 23698530Sfenner */ 237172677Smlaier curdev->description = strdup(description); 238172677Smlaier if (curdev->description == NULL) { 239172677Smlaier (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 240172677Smlaier "malloc: %s", pcap_strerror(errno)); 241172677Smlaier free(curdev->name); 242172677Smlaier free(curdev); 243172677Smlaier return (-1); 244172677Smlaier } 24598530Sfenner } else { 24698530Sfenner /* 24798530Sfenner * We don't. 24898530Sfenner */ 24998530Sfenner curdev->description = NULL; 25098530Sfenner } 25198530Sfenner curdev->addresses = NULL; /* list starts out as empty */ 25298530Sfenner curdev->flags = 0; 25398530Sfenner if (ISLOOPBACK(name, flags)) 25498530Sfenner curdev->flags |= PCAP_IF_LOOPBACK; 25598530Sfenner 25698530Sfenner /* 25798530Sfenner * Add it to the list, in the appropriate location. 25898530Sfenner * First, get the instance number of this interface. 25998530Sfenner */ 26098530Sfenner this_instance = get_instance(name); 26198530Sfenner 26298530Sfenner /* 26398530Sfenner * Now look for the last interface with an instance number 26498530Sfenner * less than or equal to the new interface's instance 26598530Sfenner * number - except that non-loopback interfaces are 26698530Sfenner * arbitrarily treated as having interface numbers less 26798530Sfenner * than those of loopback interfaces, so the loopback 26898530Sfenner * interfaces are put at the end of the list. 26998530Sfenner * 27098530Sfenner * We start with "prevdev" being NULL, meaning we're before 27198530Sfenner * the first element in the list. 27298530Sfenner */ 27398530Sfenner prevdev = NULL; 27498530Sfenner for (;;) { 27598530Sfenner /* 27698530Sfenner * Get the interface after this one. 27798530Sfenner */ 27898530Sfenner if (prevdev == NULL) { 27998530Sfenner /* 28098530Sfenner * The next element is the first element. 28198530Sfenner */ 28298530Sfenner nextdev = *alldevs; 28398530Sfenner } else 28498530Sfenner nextdev = prevdev->next; 28598530Sfenner 28698530Sfenner /* 28798530Sfenner * Are we at the end of the list? 28898530Sfenner */ 28998530Sfenner if (nextdev == NULL) { 29098530Sfenner /* 29198530Sfenner * Yes - we have to put the new entry 29298530Sfenner * after "prevdev". 29398530Sfenner */ 29498530Sfenner break; 29598530Sfenner } 29698530Sfenner 29798530Sfenner /* 29898530Sfenner * Is the new interface a non-loopback interface 29998530Sfenner * and the next interface a loopback interface? 30098530Sfenner */ 30198530Sfenner if (!(curdev->flags & PCAP_IF_LOOPBACK) && 30298530Sfenner (nextdev->flags & PCAP_IF_LOOPBACK)) { 30398530Sfenner /* 30498530Sfenner * Yes, we should put the new entry 30598530Sfenner * before "nextdev", i.e. after "prevdev". 30698530Sfenner */ 30798530Sfenner break; 30898530Sfenner } 30998530Sfenner 31098530Sfenner /* 31198530Sfenner * Is the new interface's instance number less 31298530Sfenner * than the next interface's instance number, 31398530Sfenner * and is it the case that the new interface is a 31498530Sfenner * non-loopback interface or the next interface is 31598530Sfenner * a loopback interface? 31698530Sfenner * 31798530Sfenner * (The goal of both loopback tests is to make 31898530Sfenner * sure that we never put a loopback interface 31998530Sfenner * before any non-loopback interface and that we 32098530Sfenner * always put a non-loopback interface before all 32198530Sfenner * loopback interfaces.) 32298530Sfenner */ 32398530Sfenner if (this_instance < get_instance(nextdev->name) && 32498530Sfenner (!(curdev->flags & PCAP_IF_LOOPBACK) || 32598530Sfenner (nextdev->flags & PCAP_IF_LOOPBACK))) { 32698530Sfenner /* 32798530Sfenner * Yes - we should put the new entry 32898530Sfenner * before "nextdev", i.e. after "prevdev". 32998530Sfenner */ 33098530Sfenner break; 33198530Sfenner } 33298530Sfenner 33398530Sfenner prevdev = nextdev; 33498530Sfenner } 33598530Sfenner 33698530Sfenner /* 33798530Sfenner * Insert before "nextdev". 33898530Sfenner */ 33998530Sfenner curdev->next = nextdev; 34098530Sfenner 34198530Sfenner /* 34298530Sfenner * Insert after "prevdev" - unless "prevdev" is null, 34398530Sfenner * in which case this is the first interface. 34498530Sfenner */ 34598530Sfenner if (prevdev == NULL) { 34698530Sfenner /* 34798530Sfenner * This is the first interface. Pass back a 34898530Sfenner * pointer to it, and put "curdev" before 34998530Sfenner * "nextdev". 35098530Sfenner */ 35198530Sfenner *alldevs = curdev; 35298530Sfenner } else 35398530Sfenner prevdev->next = curdev; 35498530Sfenner } 355127664Sbms 35698530Sfenner *curdev_ret = curdev; 35798530Sfenner return (0); 35898530Sfenner} 35998530Sfenner 360190225Srpaulo/* 361190225Srpaulo * XXX - on FreeBSDs that support it, should it get the sysctl named 362190225Srpaulo * "dev.{adapter family name}.{adapter unit}.%desc" to get a description 363190225Srpaulo * of the adapter? Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800" 364190225Srpaulo * with my Cisco 350 card, so the name isn't entirely descriptive. The 365190225Srpaulo * "dev.an.0.%pnpinfo" has a better description, although one might argue 366190225Srpaulo * that the problem is really a driver bug - if it can find out that it's 367190225Srpaulo * a Cisco 340 or 350, rather than an old Aironet card, it should use 368190225Srpaulo * that in the description. 369190225Srpaulo * 370214518Srpaulo * Do NetBSD, DragonflyBSD, or OpenBSD support this as well? FreeBSD 371214518Srpaulo * and OpenBSD let you get a description, but it's not generated by the OS, 372214518Srpaulo * it's set with another ioctl that ifconfig supports; we use that to get 373214518Srpaulo * a description in FreeBSD and OpenBSD, but if there is no such 374214518Srpaulo * description available, it still might be nice to get some description 375214518Srpaulo * string based on the device type or something such as that. 376190225Srpaulo * 377190225Srpaulo * In OS X, the System Configuration framework can apparently return 378214518Srpaulo * names in 10.4 and later. 379190225Srpaulo * 380214518Srpaulo * It also appears that freedesktop.org's HAL offers an "info.product" 381214518Srpaulo * string, but the HAL specification says it "should not be used in any 382214518Srpaulo * UI" and "subsystem/capability specific properties" should be used 383214518Srpaulo * instead and, in any case, I think HAL is being deprecated in 384214518Srpaulo * favor of other stuff such as DeviceKit. DeviceKit doesn't appear 385214518Srpaulo * to have any obvious product information for devices, but maybe 386214518Srpaulo * I haven't looked hard enough. 387190225Srpaulo * 388214518Srpaulo * Using the System Configuration framework, or HAL, or DeviceKit, or 389214518Srpaulo * whatever, would require that libpcap applications be linked with 390214518Srpaulo * the frameworks/libraries in question. That shouldn't be a problem 391214518Srpaulo * for programs linking with the shared version of libpcap (unless 392214518Srpaulo * you're running on AIX - which I think is the only UN*X that doesn't 393214518Srpaulo * support linking a shared library with other libraries on which it 394214518Srpaulo * depends, and having an executable linked only with the first shared 395214518Srpaulo * library automatically pick up the other libraries when started - 396214518Srpaulo * and using HAL or whatever). Programs linked with the static 397214518Srpaulo * version of libpcap would have to use pcap-config with the --static 398214518Srpaulo * flag in order to get the right linker flags in order to pick up 399214518Srpaulo * the additional libraries/frameworks; those programs need that anyway 400214518Srpaulo * for libpcap 1.1 and beyond on Linux, as, by default, it requires 401214518Srpaulo * -lnl. 402190225Srpaulo * 403190225Srpaulo * Do any other UN*Xes, or desktop environments support getting a 404190225Srpaulo * description? 405190225Srpaulo */ 406127664Sbmsint 407146768Ssamadd_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags, 408127664Sbms struct sockaddr *addr, size_t addr_size, 409127664Sbms struct sockaddr *netmask, size_t netmask_size, 410127664Sbms struct sockaddr *broadaddr, size_t broadaddr_size, 411127664Sbms struct sockaddr *dstaddr, size_t dstaddr_size, 412127664Sbms char *errbuf) 41398530Sfenner{ 41498530Sfenner pcap_if_t *curdev; 415190225Srpaulo char *description = NULL; 41698530Sfenner pcap_addr_t *curaddr, *prevaddr, *nextaddr; 417214518Srpaulo#ifdef SIOCGIFDESCR 418203052Sdelphij int s; 419190225Srpaulo struct ifreq ifrdesc; 420203052Sdelphij#ifndef IFDESCRSIZE 421214518Srpaulo size_t descrlen = 64; 422203052Sdelphij#else 423214518Srpaulo size_t descrlen = IFDESCRSIZE; 424214518Srpaulo#endif /* IFDESCRSIZE */ 425214518Srpaulo#endif /* SIOCGIFDESCR */ 42698530Sfenner 427199231Sdelphij#ifdef SIOCGIFDESCR 428190225Srpaulo /* 429190225Srpaulo * Get the description for the interface. 430190225Srpaulo */ 431190225Srpaulo memset(&ifrdesc, 0, sizeof ifrdesc); 432190225Srpaulo strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name); 433190225Srpaulo s = socket(AF_INET, SOCK_DGRAM, 0); 434190225Srpaulo if (s >= 0) { 435219472Sdelphij#ifdef __FreeBSD__ 436219472Sdelphij /* 437219472Sdelphij * On FreeBSD, if the buffer isn't big enough for the 438219472Sdelphij * description, the ioctl succeeds, but the description 439219472Sdelphij * isn't copied, ifr_buffer.length is set to the description 440219472Sdelphij * length, and ifr_buffer.buffer is set to NULL. 441219472Sdelphij */ 442214518Srpaulo for (;;) { 443214518Srpaulo free(description); 444214518Srpaulo if ((description = malloc(descrlen)) != NULL) { 445214518Srpaulo ifrdesc.ifr_buffer.buffer = description; 446214518Srpaulo ifrdesc.ifr_buffer.length = descrlen; 447219472Sdelphij if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) { 448219472Sdelphij if (ifrdesc.ifr_buffer.buffer == 449219472Sdelphij description) 450219472Sdelphij break; 451219472Sdelphij else 452219472Sdelphij descrlen = ifrdesc.ifr_buffer.length; 453219472Sdelphij } else { 454219472Sdelphij /* 455219472Sdelphij * Failed to get interface description. 456219472Sdelphij */ 457219472Sdelphij free(description); 458219472Sdelphij description = NULL; 459214518Srpaulo break; 460219472Sdelphij } 461214518Srpaulo } else 462214518Srpaulo break; 463214518Srpaulo } 464219472Sdelphij#else /* __FreeBSD__ */ 465219472Sdelphij /* 466219472Sdelphij * The only other OS that currently supports 467219472Sdelphij * SIOCGIFDESCR is OpenBSD, and it has no way 468219472Sdelphij * to get the description length - it's clamped 469219472Sdelphij * to a maximum of IFDESCRSIZE. 470219472Sdelphij */ 471219472Sdelphij if ((description = malloc(descrlen)) != NULL) { 472219472Sdelphij ifrdesc.ifr_data = (caddr_t)description; 473219472Sdelphij if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) { 474219472Sdelphij /* 475219472Sdelphij * Failed to get interface description. 476219472Sdelphij */ 477219472Sdelphij free(description); 478219472Sdelphij description = NULL; 479219472Sdelphij } 480235426Sdelphij } 481219472Sdelphij#endif /* __FreeBSD__ */ 482190225Srpaulo close(s); 483214518Srpaulo if (description != NULL && strlen(description) == 0) { 484214518Srpaulo free(description); 485214518Srpaulo description = NULL; 486214518Srpaulo } 487190225Srpaulo } 488214518Srpaulo#endif /* SIOCGIFDESCR */ 489190225Srpaulo 490190225Srpaulo if (add_or_find_if(&curdev, alldevs, name, flags, description, 491190225Srpaulo errbuf) == -1) { 492214518Srpaulo free(description); 49398530Sfenner /* 49498530Sfenner * Error - give up. 49598530Sfenner */ 49698530Sfenner return (-1); 49798530Sfenner } 498214518Srpaulo free(description); 49998530Sfenner if (curdev == NULL) { 50098530Sfenner /* 50198530Sfenner * Device wasn't added because it can't be opened. 50298530Sfenner * Not a fatal error. 50398530Sfenner */ 50498530Sfenner return (0); 50598530Sfenner } 50698530Sfenner 50798530Sfenner /* 50898530Sfenner * "curdev" is an entry for this interface; add an entry for this 50998530Sfenner * address to its list of addresses. 51098530Sfenner * 51198530Sfenner * Allocate the new entry and fill it in. 51298530Sfenner */ 51398530Sfenner curaddr = malloc(sizeof(pcap_addr_t)); 51498530Sfenner if (curaddr == NULL) { 51598530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 51698530Sfenner "malloc: %s", pcap_strerror(errno)); 51798530Sfenner return (-1); 51898530Sfenner } 51998530Sfenner 52098530Sfenner curaddr->next = NULL; 52198530Sfenner if (addr != NULL) { 522127664Sbms curaddr->addr = dup_sockaddr(addr, addr_size); 52398530Sfenner if (curaddr->addr == NULL) { 52498530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 52598530Sfenner "malloc: %s", pcap_strerror(errno)); 52698530Sfenner free(curaddr); 52798530Sfenner return (-1); 52898530Sfenner } 52998530Sfenner } else 53098530Sfenner curaddr->addr = NULL; 53198530Sfenner 53298530Sfenner if (netmask != NULL) { 533127664Sbms curaddr->netmask = dup_sockaddr(netmask, netmask_size); 53498530Sfenner if (curaddr->netmask == NULL) { 53598530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 53698530Sfenner "malloc: %s", pcap_strerror(errno)); 537172677Smlaier if (curaddr->addr != NULL) 538172677Smlaier free(curaddr->addr); 53998530Sfenner free(curaddr); 54098530Sfenner return (-1); 54198530Sfenner } 54298530Sfenner } else 54398530Sfenner curaddr->netmask = NULL; 544127664Sbms 54598530Sfenner if (broadaddr != NULL) { 546127664Sbms curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size); 54798530Sfenner if (curaddr->broadaddr == NULL) { 54898530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 54998530Sfenner "malloc: %s", pcap_strerror(errno)); 550172677Smlaier if (curaddr->netmask != NULL) 551172677Smlaier free(curaddr->netmask); 552172677Smlaier if (curaddr->addr != NULL) 553172677Smlaier free(curaddr->addr); 55498530Sfenner free(curaddr); 55598530Sfenner return (-1); 55698530Sfenner } 55798530Sfenner } else 55898530Sfenner curaddr->broadaddr = NULL; 559127664Sbms 56098530Sfenner if (dstaddr != NULL) { 561127664Sbms curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size); 56298530Sfenner if (curaddr->dstaddr == NULL) { 56398530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 56498530Sfenner "malloc: %s", pcap_strerror(errno)); 565172677Smlaier if (curaddr->broadaddr != NULL) 566172677Smlaier free(curaddr->broadaddr); 567172677Smlaier if (curaddr->netmask != NULL) 568172677Smlaier free(curaddr->netmask); 569172677Smlaier if (curaddr->addr != NULL) 570172677Smlaier free(curaddr->addr); 57198530Sfenner free(curaddr); 57298530Sfenner return (-1); 57398530Sfenner } 57498530Sfenner } else 57598530Sfenner curaddr->dstaddr = NULL; 576127664Sbms 57798530Sfenner /* 57898530Sfenner * Find the end of the list of addresses. 57998530Sfenner */ 58098530Sfenner for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) { 58198530Sfenner nextaddr = prevaddr->next; 58298530Sfenner if (nextaddr == NULL) { 58398530Sfenner /* 58498530Sfenner * This is the end of the list. 58598530Sfenner */ 58698530Sfenner break; 58798530Sfenner } 58898530Sfenner } 58998530Sfenner 59098530Sfenner if (prevaddr == NULL) { 59198530Sfenner /* 59298530Sfenner * The list was empty; this is the first member. 59398530Sfenner */ 59498530Sfenner curdev->addresses = curaddr; 59598530Sfenner } else { 59698530Sfenner /* 59798530Sfenner * "prevaddr" is the last member of the list; append 59898530Sfenner * this member to it. 59998530Sfenner */ 60098530Sfenner prevaddr->next = curaddr; 60198530Sfenner } 60298530Sfenner 60398530Sfenner return (0); 60498530Sfenner} 60598530Sfenner 606127664Sbmsint 607146768Ssampcap_add_if(pcap_if_t **devlist, const char *name, u_int flags, 60898530Sfenner const char *description, char *errbuf) 60998530Sfenner{ 61098530Sfenner pcap_if_t *curdev; 61198530Sfenner 61298530Sfenner return (add_or_find_if(&curdev, devlist, name, flags, description, 61398530Sfenner errbuf)); 61498530Sfenner} 61598530Sfenner 61675107Sfenner 61798530Sfenner/* 61898530Sfenner * Free a list of interfaces. 61998530Sfenner */ 62098530Sfennervoid 62198530Sfennerpcap_freealldevs(pcap_if_t *alldevs) 62298530Sfenner{ 62398530Sfenner pcap_if_t *curdev, *nextdev; 62498530Sfenner pcap_addr_t *curaddr, *nextaddr; 62598530Sfenner 62698530Sfenner for (curdev = alldevs; curdev != NULL; curdev = nextdev) { 62798530Sfenner nextdev = curdev->next; 62898530Sfenner 62998530Sfenner /* 63098530Sfenner * Free all addresses. 63198530Sfenner */ 63298530Sfenner for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) { 63398530Sfenner nextaddr = curaddr->next; 63498530Sfenner if (curaddr->addr) 63598530Sfenner free(curaddr->addr); 63698530Sfenner if (curaddr->netmask) 63798530Sfenner free(curaddr->netmask); 63898530Sfenner if (curaddr->broadaddr) 63998530Sfenner free(curaddr->broadaddr); 64098530Sfenner if (curaddr->dstaddr) 64198530Sfenner free(curaddr->dstaddr); 64298530Sfenner free(curaddr); 64398530Sfenner } 64498530Sfenner 64598530Sfenner /* 64698530Sfenner * Free the name string. 64798530Sfenner */ 64898530Sfenner free(curdev->name); 64998530Sfenner 65098530Sfenner /* 65198530Sfenner * Free the description string, if any. 65298530Sfenner */ 65398530Sfenner if (curdev->description != NULL) 65498530Sfenner free(curdev->description); 65598530Sfenner 65698530Sfenner /* 65798530Sfenner * Free the interface. 65898530Sfenner */ 65998530Sfenner free(curdev); 66098530Sfenner } 66198530Sfenner} 66298530Sfenner 663146768Ssam#if !defined(WIN32) && !defined(MSDOS) 664127664Sbms 66598530Sfenner/* 66698530Sfenner * Return the name of a network interface attached to the system, or NULL 66798530Sfenner * if none can be found. The interface must be configured up; the 66898530Sfenner * lowest unit number is preferred; loopback is ignored. 66998530Sfenner */ 67098530Sfennerchar * 67198530Sfennerpcap_lookupdev(errbuf) 67298530Sfenner register char *errbuf; 67398530Sfenner{ 67498530Sfenner pcap_if_t *alldevs; 67598530Sfenner/* for old BSD systems, including bsdi3 */ 67698530Sfenner#ifndef IF_NAMESIZE 67798530Sfenner#define IF_NAMESIZE IFNAMSIZ 67898530Sfenner#endif 67998530Sfenner static char device[IF_NAMESIZE + 1]; 68098530Sfenner char *ret; 68198530Sfenner 68298530Sfenner if (pcap_findalldevs(&alldevs, errbuf) == -1) 68398530Sfenner return (NULL); 684127664Sbms 68598530Sfenner if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) { 68698530Sfenner /* 68798530Sfenner * There are no devices on the list, or the first device 68898530Sfenner * on the list is a loopback device, which means there 68998530Sfenner * are no non-loopback devices on the list. This means 69098530Sfenner * we can't return any device. 69198530Sfenner * 69298530Sfenner * XXX - why not return a loopback device? If we can't 69398530Sfenner * capture on it, it won't be on the list, and if it's 69498530Sfenner * on the list, there aren't any non-loopback devices, 69598530Sfenner * so why not just supply it as the default device? 69698530Sfenner */ 69775107Sfenner (void)strlcpy(errbuf, "no suitable device found", 69875107Sfenner PCAP_ERRBUF_SIZE); 69998530Sfenner ret = NULL; 70098530Sfenner } else { 70198530Sfenner /* 70298530Sfenner * Return the name of the first device on the list. 70398530Sfenner */ 70498530Sfenner (void)strlcpy(device, alldevs->name, sizeof(device)); 70598530Sfenner ret = device; 70617683Spst } 70717683Spst 70898530Sfenner pcap_freealldevs(alldevs); 70998530Sfenner return (ret); 71017683Spst} 71117683Spst 71217683Spstint 71317683Spstpcap_lookupnet(device, netp, maskp, errbuf) 714127664Sbms register const char *device; 71517683Spst register bpf_u_int32 *netp, *maskp; 71617683Spst register char *errbuf; 71717683Spst{ 71817683Spst register int fd; 719172677Smlaier register struct sockaddr_in *sin4; 72017683Spst struct ifreq ifr; 72117683Spst 722127664Sbms /* 72375107Sfenner * The pseudo-device "any" listens on all interfaces and therefore 72475107Sfenner * has the network address and -mask "0.0.0.0" therefore catching 72575107Sfenner * all traffic. Using NULL for the interface is the same as "any". 72675107Sfenner */ 727127664Sbms if (!device || strcmp(device, "any") == 0 728127664Sbms#ifdef HAVE_DAG_API 729127664Sbms || strstr(device, "dag") != NULL 730127664Sbms#endif 731147894Ssam#ifdef HAVE_SEPTEL_API 732147894Ssam || strstr(device, "septel") != NULL 733147894Ssam#endif 734190225Srpaulo#ifdef PCAP_SUPPORT_BT 735190225Srpaulo || strstr(device, "bluetooth") != NULL 736190225Srpaulo#endif 737190225Srpaulo#ifdef PCAP_SUPPORT_USB 738214518Srpaulo || strstr(device, "usbmon") != NULL 739190225Srpaulo#endif 740277722Sluigi#ifdef PCAP_SUPPORT_NETMAP 741277722Sluigi || !strncmp(device, "netmap:", 7) 742277722Sluigi || !strncmp(device, "vale", 4) 743277722Sluigi#endif 744214518Srpaulo#ifdef HAVE_SNF_API 745214518Srpaulo || strstr(device, "snf") != NULL 746214518Srpaulo#endif 747127664Sbms ) { 74875107Sfenner *netp = *maskp = 0; 74975107Sfenner return 0; 75075107Sfenner } 75175107Sfenner 75217683Spst fd = socket(AF_INET, SOCK_DGRAM, 0); 75317683Spst if (fd < 0) { 75475107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", 75575107Sfenner pcap_strerror(errno)); 75617683Spst return (-1); 75717683Spst } 75817683Spst memset(&ifr, 0, sizeof(ifr)); 75917683Spst#ifdef linux 76017683Spst /* XXX Work around Linux kernel bug */ 76117683Spst ifr.ifr_addr.sa_family = AF_INET; 76217683Spst#endif 76317683Spst (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 76417683Spst if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { 76556889Sfenner if (errno == EADDRNOTAVAIL) { 76675107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 76775107Sfenner "%s: no IPv4 address assigned", device); 76856889Sfenner } else { 76975107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 77075107Sfenner "SIOCGIFADDR: %s: %s", 77156889Sfenner device, pcap_strerror(errno)); 77256889Sfenner } 77317683Spst (void)close(fd); 77417683Spst return (-1); 77517683Spst } 776172677Smlaier sin4 = (struct sockaddr_in *)&ifr.ifr_addr; 777172677Smlaier *netp = sin4->sin_addr.s_addr; 778214518Srpaulo memset(&ifr, 0, sizeof(ifr)); 779214518Srpaulo#ifdef linux 780214518Srpaulo /* XXX Work around Linux kernel bug */ 781214518Srpaulo ifr.ifr_addr.sa_family = AF_INET; 782214518Srpaulo#endif 783214518Srpaulo (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 78417683Spst if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { 78575107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 78675107Sfenner "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno)); 78717683Spst (void)close(fd); 78817683Spst return (-1); 78917683Spst } 79017683Spst (void)close(fd); 791172677Smlaier *maskp = sin4->sin_addr.s_addr; 79217683Spst if (*maskp == 0) { 79317683Spst if (IN_CLASSA(*netp)) 79417683Spst *maskp = IN_CLASSA_NET; 79517683Spst else if (IN_CLASSB(*netp)) 79617683Spst *maskp = IN_CLASSB_NET; 79717683Spst else if (IN_CLASSC(*netp)) 79817683Spst *maskp = IN_CLASSC_NET; 79917683Spst else { 80075107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 80175107Sfenner "inet class for 0x%x unknown", *netp); 80217683Spst return (-1); 80317683Spst } 80417683Spst } 80517683Spst *netp &= *maskp; 80617683Spst return (0); 80717683Spst} 808127664Sbms 809146768Ssam#elif defined(WIN32) 810127664Sbms 811127664Sbms/* 812127664Sbms * Return the name of a network interface attached to the system, or NULL 813127664Sbms * if none can be found. The interface must be configured up; the 814127664Sbms * lowest unit number is preferred; loopback is ignored. 815127664Sbms */ 816127664Sbmschar * 817127664Sbmspcap_lookupdev(errbuf) 818127664Sbms register char *errbuf; 819127664Sbms{ 820127664Sbms DWORD dwVersion; 821127664Sbms DWORD dwWindowsMajorVersion; 822127664Sbms dwVersion = GetVersion(); /* get the OS version */ 823127664Sbms dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); 824127664Sbms 825127664Sbms if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) { 826127664Sbms /* 827127664Sbms * Windows 95, 98, ME. 828127664Sbms */ 829127664Sbms ULONG NameLength = 8192; 830127664Sbms static char AdaptersName[8192]; 831127664Sbms 832146768Ssam if (PacketGetAdapterNames(AdaptersName,&NameLength) ) 833146768Ssam return (AdaptersName); 834146768Ssam else 835146768Ssam return NULL; 836127664Sbms } else { 837127664Sbms /* 838127664Sbms * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility 839127664Sbms */ 840127664Sbms ULONG NameLength = 8192; 841127664Sbms static WCHAR AdaptersName[8192]; 842127664Sbms char *tAstr; 843127664Sbms WCHAR *tUstr; 844127664Sbms WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR)); 845127664Sbms int NAdapts = 0; 846127664Sbms 847127664Sbms if(TAdaptersName == NULL) 848127664Sbms { 849127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure"); 850127664Sbms return NULL; 851127664Sbms } 852127664Sbms 853146768Ssam if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) ) 854146768Ssam { 855146768Ssam (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 856146768Ssam "PacketGetAdapterNames: %s", 857146768Ssam pcap_win32strerror()); 858146768Ssam free(TAdaptersName); 859146768Ssam return NULL; 860146768Ssam } 861127664Sbms 862146768Ssam 863127664Sbms tAstr = (char*)TAdaptersName; 864127664Sbms tUstr = (WCHAR*)AdaptersName; 865127664Sbms 866127664Sbms /* 867127664Sbms * Convert and copy the device names 868127664Sbms */ 869127664Sbms while(sscanf(tAstr, "%S", tUstr) > 0) 870127664Sbms { 871127664Sbms tAstr += strlen(tAstr) + 1; 872127664Sbms tUstr += wcslen(tUstr) + 1; 873127664Sbms NAdapts ++; 874127664Sbms } 875127664Sbms 876127664Sbms tAstr++; 877127664Sbms *tUstr = 0; 878127664Sbms tUstr++; 879127664Sbms 880127664Sbms /* 881127664Sbms * Copy the descriptions 882127664Sbms */ 883127664Sbms while(NAdapts--) 884127664Sbms { 885235426Sdelphij char* tmp = (char*)tUstr; 886235426Sdelphij strcpy(tmp, tAstr); 887235426Sdelphij tmp += strlen(tAstr) + 1; 888235426Sdelphij tUstr = (WCHAR*)tmp; 889127664Sbms tAstr += strlen(tAstr) + 1; 890127664Sbms } 891127664Sbms 892146768Ssam free(TAdaptersName); 893127664Sbms return (char *)(AdaptersName); 894127664Sbms } 895127664Sbms} 896127664Sbms 897127664Sbms 898127664Sbmsint 899127664Sbmspcap_lookupnet(device, netp, maskp, errbuf) 900146768Ssam register const char *device; 901127664Sbms register bpf_u_int32 *netp, *maskp; 902127664Sbms register char *errbuf; 903127664Sbms{ 904127664Sbms /* 905127664Sbms * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo() 906127664Sbms * in order to skip non IPv4 (i.e. IPv6 addresses) 907127664Sbms */ 908127664Sbms npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; 909127664Sbms LONG if_addr_size = 1; 910127664Sbms struct sockaddr_in *t_addr; 911127664Sbms unsigned int i; 912127664Sbms 913127664Sbms if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) { 914127664Sbms *netp = *maskp = 0; 915127664Sbms return (0); 916127664Sbms } 917127664Sbms 918127664Sbms for(i=0; i<MAX_NETWORK_ADDRESSES; i++) 919127664Sbms { 920127664Sbms if(if_addrs[i].IPAddress.ss_family == AF_INET) 921127664Sbms { 922127664Sbms t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress); 923127664Sbms *netp = t_addr->sin_addr.S_un.S_addr; 924127664Sbms t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask); 925127664Sbms *maskp = t_addr->sin_addr.S_un.S_addr; 926127664Sbms 927127664Sbms *netp &= *maskp; 928127664Sbms return (0); 929127664Sbms } 930127664Sbms 931127664Sbms } 932127664Sbms 933127664Sbms *netp = *maskp = 0; 934127664Sbms return (0); 935127664Sbms} 936127664Sbms 937146768Ssam#endif /* !WIN32 && !MSDOS */ 938