inet.c revision 219472
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) { 434219472Sdelphij#ifdef __FreeBSD__ 435219472Sdelphij /* 436219472Sdelphij * On FreeBSD, if the buffer isn't big enough for the 437219472Sdelphij * description, the ioctl succeeds, but the description 438219472Sdelphij * isn't copied, ifr_buffer.length is set to the description 439219472Sdelphij * length, and ifr_buffer.buffer is set to NULL. 440219472Sdelphij */ 441214518Srpaulo for (;;) { 442214518Srpaulo free(description); 443214518Srpaulo if ((description = malloc(descrlen)) != NULL) { 444214518Srpaulo ifrdesc.ifr_buffer.buffer = description; 445214518Srpaulo ifrdesc.ifr_buffer.length = descrlen; 446219472Sdelphij if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) { 447219472Sdelphij if (ifrdesc.ifr_buffer.buffer == 448219472Sdelphij description) 449219472Sdelphij break; 450219472Sdelphij else 451219472Sdelphij descrlen = ifrdesc.ifr_buffer.length; 452219472Sdelphij } else { 453219472Sdelphij /* 454219472Sdelphij * Failed to get interface description. 455219472Sdelphij */ 456219472Sdelphij free(description); 457219472Sdelphij description = NULL; 458214518Srpaulo break; 459219472Sdelphij } 460214518Srpaulo } else 461214518Srpaulo break; 462214518Srpaulo } 463219472Sdelphij#else /* __FreeBSD__ */ 464219472Sdelphij /* 465219472Sdelphij * The only other OS that currently supports 466219472Sdelphij * SIOCGIFDESCR is OpenBSD, and it has no way 467219472Sdelphij * to get the description length - it's clamped 468219472Sdelphij * to a maximum of IFDESCRSIZE. 469219472Sdelphij */ 470219472Sdelphij if ((description = malloc(descrlen)) != NULL) { 471219472Sdelphij ifrdesc.ifr_data = (caddr_t)description; 472219472Sdelphij if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) { 473219472Sdelphij /* 474219472Sdelphij * Failed to get interface description. 475219472Sdelphij */ 476219472Sdelphij free(description); 477219472Sdelphij description = NULL; 478219472Sdelphij } 479219472Sdelphij } else 480219472Sdelphij break; 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 740214518Srpaulo#ifdef HAVE_SNF_API 741214518Srpaulo || strstr(device, "snf") != NULL 742214518Srpaulo#endif 743127664Sbms ) { 74475107Sfenner *netp = *maskp = 0; 74575107Sfenner return 0; 74675107Sfenner } 74775107Sfenner 74817683Spst fd = socket(AF_INET, SOCK_DGRAM, 0); 74917683Spst if (fd < 0) { 75075107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", 75175107Sfenner pcap_strerror(errno)); 75217683Spst return (-1); 75317683Spst } 75417683Spst memset(&ifr, 0, sizeof(ifr)); 75517683Spst#ifdef linux 75617683Spst /* XXX Work around Linux kernel bug */ 75717683Spst ifr.ifr_addr.sa_family = AF_INET; 75817683Spst#endif 75917683Spst (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 76017683Spst if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { 76156889Sfenner if (errno == EADDRNOTAVAIL) { 76275107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 76375107Sfenner "%s: no IPv4 address assigned", device); 76456889Sfenner } else { 76575107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 76675107Sfenner "SIOCGIFADDR: %s: %s", 76756889Sfenner device, pcap_strerror(errno)); 76856889Sfenner } 76917683Spst (void)close(fd); 77017683Spst return (-1); 77117683Spst } 772172677Smlaier sin4 = (struct sockaddr_in *)&ifr.ifr_addr; 773172677Smlaier *netp = sin4->sin_addr.s_addr; 774214518Srpaulo memset(&ifr, 0, sizeof(ifr)); 775214518Srpaulo#ifdef linux 776214518Srpaulo /* XXX Work around Linux kernel bug */ 777214518Srpaulo ifr.ifr_addr.sa_family = AF_INET; 778214518Srpaulo#endif 779214518Srpaulo (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 78017683Spst if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { 78175107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 78275107Sfenner "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno)); 78317683Spst (void)close(fd); 78417683Spst return (-1); 78517683Spst } 78617683Spst (void)close(fd); 787172677Smlaier *maskp = sin4->sin_addr.s_addr; 78817683Spst if (*maskp == 0) { 78917683Spst if (IN_CLASSA(*netp)) 79017683Spst *maskp = IN_CLASSA_NET; 79117683Spst else if (IN_CLASSB(*netp)) 79217683Spst *maskp = IN_CLASSB_NET; 79317683Spst else if (IN_CLASSC(*netp)) 79417683Spst *maskp = IN_CLASSC_NET; 79517683Spst else { 79675107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 79775107Sfenner "inet class for 0x%x unknown", *netp); 79817683Spst return (-1); 79917683Spst } 80017683Spst } 80117683Spst *netp &= *maskp; 80217683Spst return (0); 80317683Spst} 804127664Sbms 805146768Ssam#elif defined(WIN32) 806127664Sbms 807127664Sbms/* 808127664Sbms * Return the name of a network interface attached to the system, or NULL 809127664Sbms * if none can be found. The interface must be configured up; the 810127664Sbms * lowest unit number is preferred; loopback is ignored. 811127664Sbms */ 812127664Sbmschar * 813127664Sbmspcap_lookupdev(errbuf) 814127664Sbms register char *errbuf; 815127664Sbms{ 816127664Sbms DWORD dwVersion; 817127664Sbms DWORD dwWindowsMajorVersion; 818127664Sbms dwVersion = GetVersion(); /* get the OS version */ 819127664Sbms dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); 820127664Sbms 821127664Sbms if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) { 822127664Sbms /* 823127664Sbms * Windows 95, 98, ME. 824127664Sbms */ 825127664Sbms ULONG NameLength = 8192; 826127664Sbms static char AdaptersName[8192]; 827127664Sbms 828146768Ssam if (PacketGetAdapterNames(AdaptersName,&NameLength) ) 829146768Ssam return (AdaptersName); 830146768Ssam else 831146768Ssam return NULL; 832127664Sbms } else { 833127664Sbms /* 834127664Sbms * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility 835127664Sbms */ 836127664Sbms ULONG NameLength = 8192; 837127664Sbms static WCHAR AdaptersName[8192]; 838127664Sbms char *tAstr; 839127664Sbms WCHAR *tUstr; 840127664Sbms WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR)); 841127664Sbms int NAdapts = 0; 842127664Sbms 843127664Sbms if(TAdaptersName == NULL) 844127664Sbms { 845127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure"); 846127664Sbms return NULL; 847127664Sbms } 848127664Sbms 849146768Ssam if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) ) 850146768Ssam { 851146768Ssam (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 852146768Ssam "PacketGetAdapterNames: %s", 853146768Ssam pcap_win32strerror()); 854146768Ssam free(TAdaptersName); 855146768Ssam return NULL; 856146768Ssam } 857127664Sbms 858146768Ssam 859127664Sbms tAstr = (char*)TAdaptersName; 860127664Sbms tUstr = (WCHAR*)AdaptersName; 861127664Sbms 862127664Sbms /* 863127664Sbms * Convert and copy the device names 864127664Sbms */ 865127664Sbms while(sscanf(tAstr, "%S", tUstr) > 0) 866127664Sbms { 867127664Sbms tAstr += strlen(tAstr) + 1; 868127664Sbms tUstr += wcslen(tUstr) + 1; 869127664Sbms NAdapts ++; 870127664Sbms } 871127664Sbms 872127664Sbms tAstr++; 873127664Sbms *tUstr = 0; 874127664Sbms tUstr++; 875127664Sbms 876127664Sbms /* 877127664Sbms * Copy the descriptions 878127664Sbms */ 879127664Sbms while(NAdapts--) 880127664Sbms { 881127664Sbms strcpy((char*)tUstr, tAstr); 882127664Sbms (char*)tUstr += strlen(tAstr) + 1;; 883127664Sbms tAstr += strlen(tAstr) + 1; 884127664Sbms } 885127664Sbms 886146768Ssam free(TAdaptersName); 887127664Sbms return (char *)(AdaptersName); 888127664Sbms } 889127664Sbms} 890127664Sbms 891127664Sbms 892127664Sbmsint 893127664Sbmspcap_lookupnet(device, netp, maskp, errbuf) 894146768Ssam register const char *device; 895127664Sbms register bpf_u_int32 *netp, *maskp; 896127664Sbms register char *errbuf; 897127664Sbms{ 898127664Sbms /* 899127664Sbms * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo() 900127664Sbms * in order to skip non IPv4 (i.e. IPv6 addresses) 901127664Sbms */ 902127664Sbms npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; 903127664Sbms LONG if_addr_size = 1; 904127664Sbms struct sockaddr_in *t_addr; 905127664Sbms unsigned int i; 906127664Sbms 907127664Sbms if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) { 908127664Sbms *netp = *maskp = 0; 909127664Sbms return (0); 910127664Sbms } 911127664Sbms 912127664Sbms for(i=0; i<MAX_NETWORK_ADDRESSES; i++) 913127664Sbms { 914127664Sbms if(if_addrs[i].IPAddress.ss_family == AF_INET) 915127664Sbms { 916127664Sbms t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress); 917127664Sbms *netp = t_addr->sin_addr.S_un.S_addr; 918127664Sbms t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask); 919127664Sbms *maskp = t_addr->sin_addr.S_un.S_addr; 920127664Sbms 921127664Sbms *netp &= *maskp; 922127664Sbms return (0); 923127664Sbms } 924127664Sbms 925127664Sbms } 926127664Sbms 927127664Sbms *netp = *maskp = 0; 928127664Sbms return (0); 929127664Sbms} 930127664Sbms 931146768Ssam#endif /* !WIN32 && !MSDOS */ 932