inet.c revision 147894
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_ = 37147894Ssam "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.66.2.1 2005/06/20 21:30:17 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 /* 138146768Ssam * Can we open this interface for live capture? 139146768Ssam * 140146768Ssam * We do this check so that interfaces that ae supplied 141146768Ssam * by the interface enumeration mechanism we're using 142146768Ssam * but that don't support packet capture aren't included 143146768Ssam * in the list. An example of this is loopback interfaces 144146768Ssam * on Solaris; we don't just omit loopback interfaces 145146768Ssam * becaue you *can* capture on loopback interfaces on some 146146768Ssam * OSes. 147146768Ssam */ 148146768Ssam p = pcap_open_live(name, 68, 0, 0, errbuf); 149146768Ssam if (p == NULL) { 150146768Ssam /* 151146768Ssam * No. Don't bother including it. 152146768Ssam * Don't treat this as an error, though. 153146768Ssam */ 154146768Ssam *curdev_ret = NULL; 155146768Ssam return (0); 156146768Ssam } 157146768Ssam pcap_close(p); 158146768Ssam 159146768Ssam /* 16098530Sfenner * Is there already an entry in the list for this interface? 16198530Sfenner */ 16298530Sfenner for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) { 16398530Sfenner if (strcmp(name, curdev->name) == 0) 16498530Sfenner break; /* yes, we found it */ 16598530Sfenner } 16698530Sfenner if (curdev == NULL) { 16798530Sfenner /* 16898530Sfenner * No, we didn't find it. 16998530Sfenner * Allocate a new entry. 17098530Sfenner */ 17198530Sfenner curdev = malloc(sizeof(pcap_if_t)); 17298530Sfenner if (curdev == NULL) { 17398530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 17498530Sfenner "malloc: %s", pcap_strerror(errno)); 17598530Sfenner return (-1); 17698530Sfenner } 177127664Sbms 17898530Sfenner /* 17998530Sfenner * Fill in the entry. 18098530Sfenner */ 18198530Sfenner curdev->next = NULL; 18298530Sfenner curdev->name = malloc(strlen(name) + 1); 18398530Sfenner strcpy(curdev->name, name); 18498530Sfenner if (description != NULL) { 18598530Sfenner /* 18698530Sfenner * We have a description for this interface. 18798530Sfenner */ 18898530Sfenner curdev->description = malloc(strlen(description) + 1); 18998530Sfenner strcpy(curdev->description, description); 19098530Sfenner } else { 19198530Sfenner /* 19298530Sfenner * We don't. 19398530Sfenner */ 19498530Sfenner curdev->description = NULL; 19598530Sfenner } 19698530Sfenner curdev->addresses = NULL; /* list starts out as empty */ 19798530Sfenner curdev->flags = 0; 19898530Sfenner if (ISLOOPBACK(name, flags)) 19998530Sfenner curdev->flags |= PCAP_IF_LOOPBACK; 20098530Sfenner 20198530Sfenner /* 20298530Sfenner * Add it to the list, in the appropriate location. 20398530Sfenner * First, get the instance number of this interface. 20498530Sfenner */ 20598530Sfenner this_instance = get_instance(name); 20698530Sfenner 20798530Sfenner /* 20898530Sfenner * Now look for the last interface with an instance number 20998530Sfenner * less than or equal to the new interface's instance 21098530Sfenner * number - except that non-loopback interfaces are 21198530Sfenner * arbitrarily treated as having interface numbers less 21298530Sfenner * than those of loopback interfaces, so the loopback 21398530Sfenner * interfaces are put at the end of the list. 21498530Sfenner * 21598530Sfenner * We start with "prevdev" being NULL, meaning we're before 21698530Sfenner * the first element in the list. 21798530Sfenner */ 21898530Sfenner prevdev = NULL; 21998530Sfenner for (;;) { 22098530Sfenner /* 22198530Sfenner * Get the interface after this one. 22298530Sfenner */ 22398530Sfenner if (prevdev == NULL) { 22498530Sfenner /* 22598530Sfenner * The next element is the first element. 22698530Sfenner */ 22798530Sfenner nextdev = *alldevs; 22898530Sfenner } else 22998530Sfenner nextdev = prevdev->next; 23098530Sfenner 23198530Sfenner /* 23298530Sfenner * Are we at the end of the list? 23398530Sfenner */ 23498530Sfenner if (nextdev == NULL) { 23598530Sfenner /* 23698530Sfenner * Yes - we have to put the new entry 23798530Sfenner * after "prevdev". 23898530Sfenner */ 23998530Sfenner break; 24098530Sfenner } 24198530Sfenner 24298530Sfenner /* 24398530Sfenner * Is the new interface a non-loopback interface 24498530Sfenner * and the next interface a loopback interface? 24598530Sfenner */ 24698530Sfenner if (!(curdev->flags & PCAP_IF_LOOPBACK) && 24798530Sfenner (nextdev->flags & PCAP_IF_LOOPBACK)) { 24898530Sfenner /* 24998530Sfenner * Yes, we should put the new entry 25098530Sfenner * before "nextdev", i.e. after "prevdev". 25198530Sfenner */ 25298530Sfenner break; 25398530Sfenner } 25498530Sfenner 25598530Sfenner /* 25698530Sfenner * Is the new interface's instance number less 25798530Sfenner * than the next interface's instance number, 25898530Sfenner * and is it the case that the new interface is a 25998530Sfenner * non-loopback interface or the next interface is 26098530Sfenner * a loopback interface? 26198530Sfenner * 26298530Sfenner * (The goal of both loopback tests is to make 26398530Sfenner * sure that we never put a loopback interface 26498530Sfenner * before any non-loopback interface and that we 26598530Sfenner * always put a non-loopback interface before all 26698530Sfenner * loopback interfaces.) 26798530Sfenner */ 26898530Sfenner if (this_instance < get_instance(nextdev->name) && 26998530Sfenner (!(curdev->flags & PCAP_IF_LOOPBACK) || 27098530Sfenner (nextdev->flags & PCAP_IF_LOOPBACK))) { 27198530Sfenner /* 27298530Sfenner * Yes - we should put the new entry 27398530Sfenner * before "nextdev", i.e. after "prevdev". 27498530Sfenner */ 27598530Sfenner break; 27698530Sfenner } 27798530Sfenner 27898530Sfenner prevdev = nextdev; 27998530Sfenner } 28098530Sfenner 28198530Sfenner /* 28298530Sfenner * Insert before "nextdev". 28398530Sfenner */ 28498530Sfenner curdev->next = nextdev; 28598530Sfenner 28698530Sfenner /* 28798530Sfenner * Insert after "prevdev" - unless "prevdev" is null, 28898530Sfenner * in which case this is the first interface. 28998530Sfenner */ 29098530Sfenner if (prevdev == NULL) { 29198530Sfenner /* 29298530Sfenner * This is the first interface. Pass back a 29398530Sfenner * pointer to it, and put "curdev" before 29498530Sfenner * "nextdev". 29598530Sfenner */ 29698530Sfenner *alldevs = curdev; 29798530Sfenner } else 29898530Sfenner prevdev->next = curdev; 29998530Sfenner } 300127664Sbms 30198530Sfenner *curdev_ret = curdev; 30298530Sfenner return (0); 30398530Sfenner} 30498530Sfenner 305127664Sbmsint 306146768Ssamadd_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags, 307127664Sbms struct sockaddr *addr, size_t addr_size, 308127664Sbms struct sockaddr *netmask, size_t netmask_size, 309127664Sbms struct sockaddr *broadaddr, size_t broadaddr_size, 310127664Sbms struct sockaddr *dstaddr, size_t dstaddr_size, 311127664Sbms char *errbuf) 31298530Sfenner{ 31398530Sfenner pcap_if_t *curdev; 31498530Sfenner pcap_addr_t *curaddr, *prevaddr, *nextaddr; 31598530Sfenner 31698530Sfenner if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) { 31798530Sfenner /* 31898530Sfenner * Error - give up. 31998530Sfenner */ 32098530Sfenner return (-1); 32198530Sfenner } 32298530Sfenner if (curdev == NULL) { 32398530Sfenner /* 32498530Sfenner * Device wasn't added because it can't be opened. 32598530Sfenner * Not a fatal error. 32698530Sfenner */ 32798530Sfenner return (0); 32898530Sfenner } 32998530Sfenner 33098530Sfenner /* 33198530Sfenner * "curdev" is an entry for this interface; add an entry for this 33298530Sfenner * address to its list of addresses. 33398530Sfenner * 33498530Sfenner * Allocate the new entry and fill it in. 33598530Sfenner */ 33698530Sfenner curaddr = malloc(sizeof(pcap_addr_t)); 33798530Sfenner if (curaddr == NULL) { 33898530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 33998530Sfenner "malloc: %s", pcap_strerror(errno)); 34098530Sfenner return (-1); 34198530Sfenner } 34298530Sfenner 34398530Sfenner curaddr->next = NULL; 34498530Sfenner if (addr != NULL) { 345127664Sbms curaddr->addr = dup_sockaddr(addr, addr_size); 34698530Sfenner if (curaddr->addr == NULL) { 34798530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 34898530Sfenner "malloc: %s", pcap_strerror(errno)); 34998530Sfenner free(curaddr); 35098530Sfenner return (-1); 35198530Sfenner } 35298530Sfenner } else 35398530Sfenner curaddr->addr = NULL; 35498530Sfenner 35598530Sfenner if (netmask != NULL) { 356127664Sbms curaddr->netmask = dup_sockaddr(netmask, netmask_size); 35798530Sfenner if (curaddr->netmask == NULL) { 35898530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 35998530Sfenner "malloc: %s", pcap_strerror(errno)); 36098530Sfenner free(curaddr); 36198530Sfenner return (-1); 36298530Sfenner } 36398530Sfenner } else 36498530Sfenner curaddr->netmask = NULL; 365127664Sbms 36698530Sfenner if (broadaddr != NULL) { 367127664Sbms curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size); 36898530Sfenner if (curaddr->broadaddr == NULL) { 36998530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 37098530Sfenner "malloc: %s", pcap_strerror(errno)); 37198530Sfenner free(curaddr); 37298530Sfenner return (-1); 37398530Sfenner } 37498530Sfenner } else 37598530Sfenner curaddr->broadaddr = NULL; 376127664Sbms 37798530Sfenner if (dstaddr != NULL) { 378127664Sbms curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size); 37998530Sfenner if (curaddr->dstaddr == NULL) { 38098530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 38198530Sfenner "malloc: %s", pcap_strerror(errno)); 38298530Sfenner free(curaddr); 38398530Sfenner return (-1); 38498530Sfenner } 38598530Sfenner } else 38698530Sfenner curaddr->dstaddr = NULL; 387127664Sbms 38898530Sfenner /* 38998530Sfenner * Find the end of the list of addresses. 39098530Sfenner */ 39198530Sfenner for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) { 39298530Sfenner nextaddr = prevaddr->next; 39398530Sfenner if (nextaddr == NULL) { 39498530Sfenner /* 39598530Sfenner * This is the end of the list. 39698530Sfenner */ 39798530Sfenner break; 39898530Sfenner } 39998530Sfenner } 40098530Sfenner 40198530Sfenner if (prevaddr == NULL) { 40298530Sfenner /* 40398530Sfenner * The list was empty; this is the first member. 40498530Sfenner */ 40598530Sfenner curdev->addresses = curaddr; 40698530Sfenner } else { 40798530Sfenner /* 40898530Sfenner * "prevaddr" is the last member of the list; append 40998530Sfenner * this member to it. 41098530Sfenner */ 41198530Sfenner prevaddr->next = curaddr; 41298530Sfenner } 41398530Sfenner 41498530Sfenner return (0); 41598530Sfenner} 41698530Sfenner 417127664Sbmsint 418146768Ssampcap_add_if(pcap_if_t **devlist, const char *name, u_int flags, 41998530Sfenner const char *description, char *errbuf) 42098530Sfenner{ 42198530Sfenner pcap_if_t *curdev; 42298530Sfenner 42398530Sfenner return (add_or_find_if(&curdev, devlist, name, flags, description, 42498530Sfenner errbuf)); 42598530Sfenner} 42698530Sfenner 42775107Sfenner 42898530Sfenner/* 42998530Sfenner * Free a list of interfaces. 43098530Sfenner */ 43198530Sfennervoid 43298530Sfennerpcap_freealldevs(pcap_if_t *alldevs) 43398530Sfenner{ 43498530Sfenner pcap_if_t *curdev, *nextdev; 43598530Sfenner pcap_addr_t *curaddr, *nextaddr; 43698530Sfenner 43798530Sfenner for (curdev = alldevs; curdev != NULL; curdev = nextdev) { 43898530Sfenner nextdev = curdev->next; 43998530Sfenner 44098530Sfenner /* 44198530Sfenner * Free all addresses. 44298530Sfenner */ 44398530Sfenner for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) { 44498530Sfenner nextaddr = curaddr->next; 44598530Sfenner if (curaddr->addr) 44698530Sfenner free(curaddr->addr); 44798530Sfenner if (curaddr->netmask) 44898530Sfenner free(curaddr->netmask); 44998530Sfenner if (curaddr->broadaddr) 45098530Sfenner free(curaddr->broadaddr); 45198530Sfenner if (curaddr->dstaddr) 45298530Sfenner free(curaddr->dstaddr); 45398530Sfenner free(curaddr); 45498530Sfenner } 45598530Sfenner 45698530Sfenner /* 45798530Sfenner * Free the name string. 45898530Sfenner */ 45998530Sfenner free(curdev->name); 46098530Sfenner 46198530Sfenner /* 46298530Sfenner * Free the description string, if any. 46398530Sfenner */ 46498530Sfenner if (curdev->description != NULL) 46598530Sfenner free(curdev->description); 46698530Sfenner 46798530Sfenner /* 46898530Sfenner * Free the interface. 46998530Sfenner */ 47098530Sfenner free(curdev); 47198530Sfenner } 47298530Sfenner} 47398530Sfenner 474146768Ssam#if !defined(WIN32) && !defined(MSDOS) 475127664Sbms 47698530Sfenner/* 47798530Sfenner * Return the name of a network interface attached to the system, or NULL 47898530Sfenner * if none can be found. The interface must be configured up; the 47998530Sfenner * lowest unit number is preferred; loopback is ignored. 48098530Sfenner */ 48198530Sfennerchar * 48298530Sfennerpcap_lookupdev(errbuf) 48398530Sfenner register char *errbuf; 48498530Sfenner{ 48598530Sfenner pcap_if_t *alldevs; 48698530Sfenner/* for old BSD systems, including bsdi3 */ 48798530Sfenner#ifndef IF_NAMESIZE 48898530Sfenner#define IF_NAMESIZE IFNAMSIZ 48998530Sfenner#endif 49098530Sfenner static char device[IF_NAMESIZE + 1]; 49198530Sfenner char *ret; 49298530Sfenner 49398530Sfenner if (pcap_findalldevs(&alldevs, errbuf) == -1) 49498530Sfenner return (NULL); 495127664Sbms 49698530Sfenner if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) { 49798530Sfenner /* 49898530Sfenner * There are no devices on the list, or the first device 49998530Sfenner * on the list is a loopback device, which means there 50098530Sfenner * are no non-loopback devices on the list. This means 50198530Sfenner * we can't return any device. 50298530Sfenner * 50398530Sfenner * XXX - why not return a loopback device? If we can't 50498530Sfenner * capture on it, it won't be on the list, and if it's 50598530Sfenner * on the list, there aren't any non-loopback devices, 50698530Sfenner * so why not just supply it as the default device? 50798530Sfenner */ 50875107Sfenner (void)strlcpy(errbuf, "no suitable device found", 50975107Sfenner PCAP_ERRBUF_SIZE); 51098530Sfenner ret = NULL; 51198530Sfenner } else { 51298530Sfenner /* 51398530Sfenner * Return the name of the first device on the list. 51498530Sfenner */ 51598530Sfenner (void)strlcpy(device, alldevs->name, sizeof(device)); 51698530Sfenner ret = device; 51717683Spst } 51817683Spst 51998530Sfenner pcap_freealldevs(alldevs); 52098530Sfenner return (ret); 52117683Spst} 52217683Spst 52317683Spstint 52417683Spstpcap_lookupnet(device, netp, maskp, errbuf) 525127664Sbms register const char *device; 52617683Spst register bpf_u_int32 *netp, *maskp; 52717683Spst register char *errbuf; 52817683Spst{ 52917683Spst register int fd; 53017683Spst register struct sockaddr_in *sin; 53117683Spst struct ifreq ifr; 53217683Spst 533127664Sbms /* 53475107Sfenner * The pseudo-device "any" listens on all interfaces and therefore 53575107Sfenner * has the network address and -mask "0.0.0.0" therefore catching 53675107Sfenner * all traffic. Using NULL for the interface is the same as "any". 53775107Sfenner */ 538127664Sbms if (!device || strcmp(device, "any") == 0 539127664Sbms#ifdef HAVE_DAG_API 540127664Sbms || strstr(device, "dag") != NULL 541127664Sbms#endif 542147894Ssam#ifdef HAVE_SEPTEL_API 543147894Ssam || strstr(device, "septel") != NULL 544147894Ssam#endif 545127664Sbms ) { 54675107Sfenner *netp = *maskp = 0; 54775107Sfenner return 0; 54875107Sfenner } 54975107Sfenner 55017683Spst fd = socket(AF_INET, SOCK_DGRAM, 0); 55117683Spst if (fd < 0) { 55275107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", 55375107Sfenner pcap_strerror(errno)); 55417683Spst return (-1); 55517683Spst } 55617683Spst memset(&ifr, 0, sizeof(ifr)); 55717683Spst#ifdef linux 55817683Spst /* XXX Work around Linux kernel bug */ 55917683Spst ifr.ifr_addr.sa_family = AF_INET; 56017683Spst#endif 56117683Spst (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 56217683Spst if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { 56356889Sfenner if (errno == EADDRNOTAVAIL) { 56475107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 56575107Sfenner "%s: no IPv4 address assigned", device); 56656889Sfenner } else { 56775107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 56875107Sfenner "SIOCGIFADDR: %s: %s", 56956889Sfenner device, pcap_strerror(errno)); 57056889Sfenner } 57117683Spst (void)close(fd); 57217683Spst return (-1); 57317683Spst } 57417683Spst sin = (struct sockaddr_in *)&ifr.ifr_addr; 57517683Spst *netp = sin->sin_addr.s_addr; 57617683Spst if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { 57775107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 57875107Sfenner "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno)); 57917683Spst (void)close(fd); 58017683Spst return (-1); 58117683Spst } 58217683Spst (void)close(fd); 58317683Spst *maskp = sin->sin_addr.s_addr; 58417683Spst if (*maskp == 0) { 58517683Spst if (IN_CLASSA(*netp)) 58617683Spst *maskp = IN_CLASSA_NET; 58717683Spst else if (IN_CLASSB(*netp)) 58817683Spst *maskp = IN_CLASSB_NET; 58917683Spst else if (IN_CLASSC(*netp)) 59017683Spst *maskp = IN_CLASSC_NET; 59117683Spst else { 59275107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 59375107Sfenner "inet class for 0x%x unknown", *netp); 59417683Spst return (-1); 59517683Spst } 59617683Spst } 59717683Spst *netp &= *maskp; 59817683Spst return (0); 59917683Spst} 600127664Sbms 601146768Ssam#elif defined(WIN32) 602127664Sbms 603127664Sbms/* 604127664Sbms * Return the name of a network interface attached to the system, or NULL 605127664Sbms * if none can be found. The interface must be configured up; the 606127664Sbms * lowest unit number is preferred; loopback is ignored. 607127664Sbms */ 608127664Sbmschar * 609127664Sbmspcap_lookupdev(errbuf) 610127664Sbms register char *errbuf; 611127664Sbms{ 612127664Sbms DWORD dwVersion; 613127664Sbms DWORD dwWindowsMajorVersion; 614127664Sbms dwVersion = GetVersion(); /* get the OS version */ 615127664Sbms dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); 616127664Sbms 617127664Sbms if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) { 618127664Sbms /* 619127664Sbms * Windows 95, 98, ME. 620127664Sbms */ 621127664Sbms ULONG NameLength = 8192; 622127664Sbms static char AdaptersName[8192]; 623127664Sbms 624146768Ssam if (PacketGetAdapterNames(AdaptersName,&NameLength) ) 625146768Ssam return (AdaptersName); 626146768Ssam else 627146768Ssam return NULL; 628127664Sbms } else { 629127664Sbms /* 630127664Sbms * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility 631127664Sbms */ 632127664Sbms ULONG NameLength = 8192; 633127664Sbms static WCHAR AdaptersName[8192]; 634127664Sbms char *tAstr; 635127664Sbms WCHAR *tUstr; 636127664Sbms WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR)); 637127664Sbms int NAdapts = 0; 638127664Sbms 639127664Sbms if(TAdaptersName == NULL) 640127664Sbms { 641127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure"); 642127664Sbms return NULL; 643127664Sbms } 644127664Sbms 645146768Ssam if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) ) 646146768Ssam { 647146768Ssam (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 648146768Ssam "PacketGetAdapterNames: %s", 649146768Ssam pcap_win32strerror()); 650146768Ssam free(TAdaptersName); 651146768Ssam return NULL; 652146768Ssam } 653127664Sbms 654146768Ssam 655127664Sbms tAstr = (char*)TAdaptersName; 656127664Sbms tUstr = (WCHAR*)AdaptersName; 657127664Sbms 658127664Sbms /* 659127664Sbms * Convert and copy the device names 660127664Sbms */ 661127664Sbms while(sscanf(tAstr, "%S", tUstr) > 0) 662127664Sbms { 663127664Sbms tAstr += strlen(tAstr) + 1; 664127664Sbms tUstr += wcslen(tUstr) + 1; 665127664Sbms NAdapts ++; 666127664Sbms } 667127664Sbms 668127664Sbms tAstr++; 669127664Sbms *tUstr = 0; 670127664Sbms tUstr++; 671127664Sbms 672127664Sbms /* 673127664Sbms * Copy the descriptions 674127664Sbms */ 675127664Sbms while(NAdapts--) 676127664Sbms { 677127664Sbms strcpy((char*)tUstr, tAstr); 678127664Sbms (char*)tUstr += strlen(tAstr) + 1;; 679127664Sbms tAstr += strlen(tAstr) + 1; 680127664Sbms } 681127664Sbms 682146768Ssam free(TAdaptersName); 683127664Sbms return (char *)(AdaptersName); 684127664Sbms } 685127664Sbms} 686127664Sbms 687127664Sbms 688127664Sbmsint 689127664Sbmspcap_lookupnet(device, netp, maskp, errbuf) 690146768Ssam register const char *device; 691127664Sbms register bpf_u_int32 *netp, *maskp; 692127664Sbms register char *errbuf; 693127664Sbms{ 694127664Sbms /* 695127664Sbms * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo() 696127664Sbms * in order to skip non IPv4 (i.e. IPv6 addresses) 697127664Sbms */ 698127664Sbms npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; 699127664Sbms LONG if_addr_size = 1; 700127664Sbms struct sockaddr_in *t_addr; 701127664Sbms unsigned int i; 702127664Sbms 703127664Sbms if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) { 704127664Sbms *netp = *maskp = 0; 705127664Sbms return (0); 706127664Sbms } 707127664Sbms 708127664Sbms for(i=0; i<MAX_NETWORK_ADDRESSES; i++) 709127664Sbms { 710127664Sbms if(if_addrs[i].IPAddress.ss_family == AF_INET) 711127664Sbms { 712127664Sbms t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress); 713127664Sbms *netp = t_addr->sin_addr.S_un.S_addr; 714127664Sbms t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask); 715127664Sbms *maskp = t_addr->sin_addr.S_un.S_addr; 716127664Sbms 717127664Sbms *netp &= *maskp; 718127664Sbms return (0); 719127664Sbms } 720127664Sbms 721127664Sbms } 722127664Sbms 723127664Sbms *netp = *maskp = 0; 724127664Sbms return (0); 725127664Sbms} 726127664Sbms 727146768Ssam#endif /* !WIN32 && !MSDOS */ 728