inet.c revision 127664
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_ = 37127664Sbms "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.58.2.1 2003/11/15 23:26:41 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> 4917683Spst#include <sys/file.h> 5017683Spst#include <sys/ioctl.h> 5117683Spst#include <sys/socket.h> 5217683Spst#ifdef HAVE_SYS_SOCKIO_H 5317683Spst#include <sys/sockio.h> 5417683Spst#endif 5517683Spst#include <sys/time.h> /* concession to AIX */ 5617683Spst 57127664Sbmsstruct mbuf; /* Squelch compiler warnings on some platforms for */ 58127664Sbmsstruct rtentry; /* declarations in <net/if.h> */ 5917683Spst#include <net/if.h> 6017683Spst#include <netinet/in.h> 61127664Sbms#endif /* WIN32 */ 6217683Spst 6317683Spst#include <ctype.h> 6417683Spst#include <errno.h> 6517683Spst#include <memory.h> 6617683Spst#include <stdio.h> 6717683Spst#include <stdlib.h> 6817683Spst#include <string.h> 69127664Sbms#ifndef WIN32 7017683Spst#include <unistd.h> 71127664Sbms#endif /* WIN32 */ 7298530Sfenner#ifdef HAVE_LIMITS_H 7398530Sfenner#include <limits.h> 7498530Sfenner#else 7598530Sfenner#define INT_MAX 2147483647 7698530Sfenner#endif 7775107Sfenner#ifdef HAVE_IFADDRS_H 7875107Sfenner#include <ifaddrs.h> 7975107Sfenner#endif 8017683Spst 8117683Spst#include "pcap-int.h" 8217683Spst 8317683Spst#ifdef HAVE_OS_PROTO_H 8417683Spst#include "os-proto.h" 8517683Spst#endif 8617683Spst 8717683Spst/* Not all systems have IFF_LOOPBACK */ 8817683Spst#ifdef IFF_LOOPBACK 8998530Sfenner#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK) 9017683Spst#else 9198530Sfenner#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \ 9298530Sfenner (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0')) 9317683Spst#endif 9417683Spst 95127664Sbmsstruct sockaddr * 96127664Sbmsdup_sockaddr(struct sockaddr *sa, size_t sa_length) 9717683Spst{ 9898530Sfenner struct sockaddr *newsa; 99127664Sbms 100127664Sbms if ((newsa = malloc(sa_length)) == NULL) 10198530Sfenner return (NULL); 102127664Sbms return (memcpy(newsa, sa, sa_length)); 10398530Sfenner} 10498530Sfenner 10598530Sfennerstatic int 106127664Sbmsget_instance(const char *name) 10798530Sfenner{ 108127664Sbms const char *cp, *endcp; 10998530Sfenner int n; 11098530Sfenner 11198530Sfenner if (strcmp(name, "any") == 0) { 11298530Sfenner /* 11398530Sfenner * Give the "any" device an artificially high instance 11498530Sfenner * number, so it shows up after all other non-loopback 11598530Sfenner * interfaces. 11698530Sfenner */ 11798530Sfenner return INT_MAX; 11898530Sfenner } 11998530Sfenner 12098530Sfenner endcp = name + strlen(name); 12198530Sfenner for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp) 12298530Sfenner continue; 12398530Sfenner 12498530Sfenner if (isdigit((unsigned char)*cp)) 12598530Sfenner n = atoi(cp); 12698530Sfenner else 12798530Sfenner n = 0; 12898530Sfenner return (n); 12998530Sfenner} 13098530Sfenner 131127664Sbmsint 132127664Sbmsadd_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name, 13398530Sfenner u_int flags, const char *description, char *errbuf) 13498530Sfenner{ 13598530Sfenner pcap_if_t *curdev, *prevdev, *nextdev; 13698530Sfenner int this_instance; 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 } 14598530Sfenner if (curdev == NULL) { 14698530Sfenner /* 14798530Sfenner * No, we didn't find it. 14898530Sfenner * Allocate a new entry. 14998530Sfenner */ 15098530Sfenner curdev = malloc(sizeof(pcap_if_t)); 15198530Sfenner if (curdev == NULL) { 15298530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 15398530Sfenner "malloc: %s", pcap_strerror(errno)); 15498530Sfenner return (-1); 15598530Sfenner } 156127664Sbms 15798530Sfenner /* 15898530Sfenner * Fill in the entry. 15998530Sfenner */ 16098530Sfenner curdev->next = NULL; 16198530Sfenner curdev->name = malloc(strlen(name) + 1); 16298530Sfenner strcpy(curdev->name, name); 16398530Sfenner if (description != NULL) { 16498530Sfenner /* 16598530Sfenner * We have a description for this interface. 16698530Sfenner */ 16798530Sfenner curdev->description = malloc(strlen(description) + 1); 16898530Sfenner strcpy(curdev->description, description); 16998530Sfenner } else { 17098530Sfenner /* 17198530Sfenner * We don't. 17298530Sfenner */ 17398530Sfenner curdev->description = NULL; 17498530Sfenner } 17598530Sfenner curdev->addresses = NULL; /* list starts out as empty */ 17698530Sfenner curdev->flags = 0; 17798530Sfenner if (ISLOOPBACK(name, flags)) 17898530Sfenner curdev->flags |= PCAP_IF_LOOPBACK; 17998530Sfenner 18098530Sfenner /* 18198530Sfenner * Add it to the list, in the appropriate location. 18298530Sfenner * First, get the instance number of this interface. 18398530Sfenner */ 18498530Sfenner this_instance = get_instance(name); 18598530Sfenner 18698530Sfenner /* 18798530Sfenner * Now look for the last interface with an instance number 18898530Sfenner * less than or equal to the new interface's instance 18998530Sfenner * number - except that non-loopback interfaces are 19098530Sfenner * arbitrarily treated as having interface numbers less 19198530Sfenner * than those of loopback interfaces, so the loopback 19298530Sfenner * interfaces are put at the end of the list. 19398530Sfenner * 19498530Sfenner * We start with "prevdev" being NULL, meaning we're before 19598530Sfenner * the first element in the list. 19698530Sfenner */ 19798530Sfenner prevdev = NULL; 19898530Sfenner for (;;) { 19998530Sfenner /* 20098530Sfenner * Get the interface after this one. 20198530Sfenner */ 20298530Sfenner if (prevdev == NULL) { 20398530Sfenner /* 20498530Sfenner * The next element is the first element. 20598530Sfenner */ 20698530Sfenner nextdev = *alldevs; 20798530Sfenner } else 20898530Sfenner nextdev = prevdev->next; 20998530Sfenner 21098530Sfenner /* 21198530Sfenner * Are we at the end of the list? 21298530Sfenner */ 21398530Sfenner if (nextdev == NULL) { 21498530Sfenner /* 21598530Sfenner * Yes - we have to put the new entry 21698530Sfenner * after "prevdev". 21798530Sfenner */ 21898530Sfenner break; 21998530Sfenner } 22098530Sfenner 22198530Sfenner /* 22298530Sfenner * Is the new interface a non-loopback interface 22398530Sfenner * and the next interface a loopback interface? 22498530Sfenner */ 22598530Sfenner if (!(curdev->flags & PCAP_IF_LOOPBACK) && 22698530Sfenner (nextdev->flags & PCAP_IF_LOOPBACK)) { 22798530Sfenner /* 22898530Sfenner * Yes, we should put the new entry 22998530Sfenner * before "nextdev", i.e. after "prevdev". 23098530Sfenner */ 23198530Sfenner break; 23298530Sfenner } 23398530Sfenner 23498530Sfenner /* 23598530Sfenner * Is the new interface's instance number less 23698530Sfenner * than the next interface's instance number, 23798530Sfenner * and is it the case that the new interface is a 23898530Sfenner * non-loopback interface or the next interface is 23998530Sfenner * a loopback interface? 24098530Sfenner * 24198530Sfenner * (The goal of both loopback tests is to make 24298530Sfenner * sure that we never put a loopback interface 24398530Sfenner * before any non-loopback interface and that we 24498530Sfenner * always put a non-loopback interface before all 24598530Sfenner * loopback interfaces.) 24698530Sfenner */ 24798530Sfenner if (this_instance < get_instance(nextdev->name) && 24898530Sfenner (!(curdev->flags & PCAP_IF_LOOPBACK) || 24998530Sfenner (nextdev->flags & PCAP_IF_LOOPBACK))) { 25098530Sfenner /* 25198530Sfenner * Yes - we should put the new entry 25298530Sfenner * before "nextdev", i.e. after "prevdev". 25398530Sfenner */ 25498530Sfenner break; 25598530Sfenner } 25698530Sfenner 25798530Sfenner prevdev = nextdev; 25898530Sfenner } 25998530Sfenner 26098530Sfenner /* 26198530Sfenner * Insert before "nextdev". 26298530Sfenner */ 26398530Sfenner curdev->next = nextdev; 26498530Sfenner 26598530Sfenner /* 26698530Sfenner * Insert after "prevdev" - unless "prevdev" is null, 26798530Sfenner * in which case this is the first interface. 26898530Sfenner */ 26998530Sfenner if (prevdev == NULL) { 27098530Sfenner /* 27198530Sfenner * This is the first interface. Pass back a 27298530Sfenner * pointer to it, and put "curdev" before 27398530Sfenner * "nextdev". 27498530Sfenner */ 27598530Sfenner *alldevs = curdev; 27698530Sfenner } else 27798530Sfenner prevdev->next = curdev; 27898530Sfenner } 279127664Sbms 28098530Sfenner *curdev_ret = curdev; 28198530Sfenner return (0); 28298530Sfenner} 28398530Sfenner 284127664Sbmsint 28598530Sfenneradd_addr_to_iflist(pcap_if_t **alldevs, char *name, u_int flags, 286127664Sbms struct sockaddr *addr, size_t addr_size, 287127664Sbms struct sockaddr *netmask, size_t netmask_size, 288127664Sbms struct sockaddr *broadaddr, size_t broadaddr_size, 289127664Sbms struct sockaddr *dstaddr, size_t dstaddr_size, 290127664Sbms char *errbuf) 29198530Sfenner{ 29298530Sfenner pcap_if_t *curdev; 29398530Sfenner pcap_addr_t *curaddr, *prevaddr, *nextaddr; 29498530Sfenner 29598530Sfenner if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) { 29698530Sfenner /* 29798530Sfenner * Error - give up. 29898530Sfenner */ 29998530Sfenner return (-1); 30098530Sfenner } 30198530Sfenner if (curdev == NULL) { 30298530Sfenner /* 30398530Sfenner * Device wasn't added because it can't be opened. 30498530Sfenner * Not a fatal error. 30598530Sfenner */ 30698530Sfenner return (0); 30798530Sfenner } 30898530Sfenner 30998530Sfenner /* 31098530Sfenner * "curdev" is an entry for this interface; add an entry for this 31198530Sfenner * address to its list of addresses. 31298530Sfenner * 31398530Sfenner * Allocate the new entry and fill it in. 31498530Sfenner */ 31598530Sfenner curaddr = malloc(sizeof(pcap_addr_t)); 31698530Sfenner if (curaddr == NULL) { 31798530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 31898530Sfenner "malloc: %s", pcap_strerror(errno)); 31998530Sfenner return (-1); 32098530Sfenner } 32198530Sfenner 32298530Sfenner curaddr->next = NULL; 32398530Sfenner if (addr != NULL) { 324127664Sbms curaddr->addr = dup_sockaddr(addr, addr_size); 32598530Sfenner if (curaddr->addr == NULL) { 32698530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 32798530Sfenner "malloc: %s", pcap_strerror(errno)); 32898530Sfenner free(curaddr); 32998530Sfenner return (-1); 33098530Sfenner } 33198530Sfenner } else 33298530Sfenner curaddr->addr = NULL; 33398530Sfenner 33498530Sfenner if (netmask != NULL) { 335127664Sbms curaddr->netmask = dup_sockaddr(netmask, netmask_size); 33698530Sfenner if (curaddr->netmask == NULL) { 33798530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 33898530Sfenner "malloc: %s", pcap_strerror(errno)); 33998530Sfenner free(curaddr); 34098530Sfenner return (-1); 34198530Sfenner } 34298530Sfenner } else 34398530Sfenner curaddr->netmask = NULL; 344127664Sbms 34598530Sfenner if (broadaddr != NULL) { 346127664Sbms curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size); 34798530Sfenner if (curaddr->broadaddr == NULL) { 34898530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 34998530Sfenner "malloc: %s", pcap_strerror(errno)); 35098530Sfenner free(curaddr); 35198530Sfenner return (-1); 35298530Sfenner } 35398530Sfenner } else 35498530Sfenner curaddr->broadaddr = NULL; 355127664Sbms 35698530Sfenner if (dstaddr != NULL) { 357127664Sbms curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size); 35898530Sfenner if (curaddr->dstaddr == NULL) { 35998530Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 36098530Sfenner "malloc: %s", pcap_strerror(errno)); 36198530Sfenner free(curaddr); 36298530Sfenner return (-1); 36398530Sfenner } 36498530Sfenner } else 36598530Sfenner curaddr->dstaddr = NULL; 366127664Sbms 36798530Sfenner /* 36898530Sfenner * Find the end of the list of addresses. 36998530Sfenner */ 37098530Sfenner for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) { 37198530Sfenner nextaddr = prevaddr->next; 37298530Sfenner if (nextaddr == NULL) { 37398530Sfenner /* 37498530Sfenner * This is the end of the list. 37598530Sfenner */ 37698530Sfenner break; 37798530Sfenner } 37898530Sfenner } 37998530Sfenner 38098530Sfenner if (prevaddr == NULL) { 38198530Sfenner /* 38298530Sfenner * The list was empty; this is the first member. 38398530Sfenner */ 38498530Sfenner curdev->addresses = curaddr; 38598530Sfenner } else { 38698530Sfenner /* 38798530Sfenner * "prevaddr" is the last member of the list; append 38898530Sfenner * this member to it. 38998530Sfenner */ 39098530Sfenner prevaddr->next = curaddr; 39198530Sfenner } 39298530Sfenner 39398530Sfenner return (0); 39498530Sfenner} 39598530Sfenner 396127664Sbmsint 39798530Sfennerpcap_add_if(pcap_if_t **devlist, char *name, u_int flags, 39898530Sfenner const char *description, char *errbuf) 39998530Sfenner{ 40098530Sfenner pcap_if_t *curdev; 40198530Sfenner 40298530Sfenner return (add_or_find_if(&curdev, devlist, name, flags, description, 40398530Sfenner errbuf)); 40498530Sfenner} 40598530Sfenner 40675107Sfenner 40798530Sfenner/* 40898530Sfenner * Free a list of interfaces. 40998530Sfenner */ 41098530Sfennervoid 41198530Sfennerpcap_freealldevs(pcap_if_t *alldevs) 41298530Sfenner{ 41398530Sfenner pcap_if_t *curdev, *nextdev; 41498530Sfenner pcap_addr_t *curaddr, *nextaddr; 41598530Sfenner 41698530Sfenner for (curdev = alldevs; curdev != NULL; curdev = nextdev) { 41798530Sfenner nextdev = curdev->next; 41898530Sfenner 41998530Sfenner /* 42098530Sfenner * Free all addresses. 42198530Sfenner */ 42298530Sfenner for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) { 42398530Sfenner nextaddr = curaddr->next; 42498530Sfenner if (curaddr->addr) 42598530Sfenner free(curaddr->addr); 42698530Sfenner if (curaddr->netmask) 42798530Sfenner free(curaddr->netmask); 42898530Sfenner if (curaddr->broadaddr) 42998530Sfenner free(curaddr->broadaddr); 43098530Sfenner if (curaddr->dstaddr) 43198530Sfenner free(curaddr->dstaddr); 43298530Sfenner free(curaddr); 43398530Sfenner } 43498530Sfenner 43598530Sfenner /* 43698530Sfenner * Free the name string. 43798530Sfenner */ 43898530Sfenner free(curdev->name); 43998530Sfenner 44098530Sfenner /* 44198530Sfenner * Free the description string, if any. 44298530Sfenner */ 44398530Sfenner if (curdev->description != NULL) 44498530Sfenner free(curdev->description); 44598530Sfenner 44698530Sfenner /* 44798530Sfenner * Free the interface. 44898530Sfenner */ 44998530Sfenner free(curdev); 45098530Sfenner } 45198530Sfenner} 45298530Sfenner 453127664Sbms#ifndef WIN32 454127664Sbms 45598530Sfenner/* 45698530Sfenner * Return the name of a network interface attached to the system, or NULL 45798530Sfenner * if none can be found. The interface must be configured up; the 45898530Sfenner * lowest unit number is preferred; loopback is ignored. 45998530Sfenner */ 46098530Sfennerchar * 46198530Sfennerpcap_lookupdev(errbuf) 46298530Sfenner register char *errbuf; 46398530Sfenner{ 46498530Sfenner pcap_if_t *alldevs; 46598530Sfenner/* for old BSD systems, including bsdi3 */ 46698530Sfenner#ifndef IF_NAMESIZE 46798530Sfenner#define IF_NAMESIZE IFNAMSIZ 46898530Sfenner#endif 46998530Sfenner static char device[IF_NAMESIZE + 1]; 47098530Sfenner char *ret; 47198530Sfenner 47298530Sfenner if (pcap_findalldevs(&alldevs, errbuf) == -1) 47398530Sfenner return (NULL); 474127664Sbms 47598530Sfenner if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) { 47698530Sfenner /* 47798530Sfenner * There are no devices on the list, or the first device 47898530Sfenner * on the list is a loopback device, which means there 47998530Sfenner * are no non-loopback devices on the list. This means 48098530Sfenner * we can't return any device. 48198530Sfenner * 48298530Sfenner * XXX - why not return a loopback device? If we can't 48398530Sfenner * capture on it, it won't be on the list, and if it's 48498530Sfenner * on the list, there aren't any non-loopback devices, 48598530Sfenner * so why not just supply it as the default device? 48698530Sfenner */ 48775107Sfenner (void)strlcpy(errbuf, "no suitable device found", 48875107Sfenner PCAP_ERRBUF_SIZE); 48998530Sfenner ret = NULL; 49098530Sfenner } else { 49198530Sfenner /* 49298530Sfenner * Return the name of the first device on the list. 49398530Sfenner */ 49498530Sfenner (void)strlcpy(device, alldevs->name, sizeof(device)); 49598530Sfenner ret = device; 49617683Spst } 49717683Spst 49898530Sfenner pcap_freealldevs(alldevs); 49998530Sfenner return (ret); 50017683Spst} 50117683Spst 50217683Spstint 50317683Spstpcap_lookupnet(device, netp, maskp, errbuf) 504127664Sbms register const char *device; 50517683Spst register bpf_u_int32 *netp, *maskp; 50617683Spst register char *errbuf; 50717683Spst{ 50817683Spst register int fd; 50917683Spst register struct sockaddr_in *sin; 51017683Spst struct ifreq ifr; 51117683Spst 512127664Sbms /* 51375107Sfenner * The pseudo-device "any" listens on all interfaces and therefore 51475107Sfenner * has the network address and -mask "0.0.0.0" therefore catching 51575107Sfenner * all traffic. Using NULL for the interface is the same as "any". 51675107Sfenner */ 517127664Sbms if (!device || strcmp(device, "any") == 0 518127664Sbms#ifdef HAVE_DAG_API 519127664Sbms || strstr(device, "dag") != NULL 520127664Sbms#endif 521127664Sbms ) { 52275107Sfenner *netp = *maskp = 0; 52375107Sfenner return 0; 52475107Sfenner } 52575107Sfenner 52617683Spst fd = socket(AF_INET, SOCK_DGRAM, 0); 52717683Spst if (fd < 0) { 52875107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", 52975107Sfenner pcap_strerror(errno)); 53017683Spst return (-1); 53117683Spst } 53217683Spst memset(&ifr, 0, sizeof(ifr)); 53317683Spst#ifdef linux 53417683Spst /* XXX Work around Linux kernel bug */ 53517683Spst ifr.ifr_addr.sa_family = AF_INET; 53617683Spst#endif 53717683Spst (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 53817683Spst if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { 53956889Sfenner if (errno == EADDRNOTAVAIL) { 54075107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 54175107Sfenner "%s: no IPv4 address assigned", device); 54256889Sfenner } else { 54375107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 54475107Sfenner "SIOCGIFADDR: %s: %s", 54556889Sfenner device, pcap_strerror(errno)); 54656889Sfenner } 54717683Spst (void)close(fd); 54817683Spst return (-1); 54917683Spst } 55017683Spst sin = (struct sockaddr_in *)&ifr.ifr_addr; 55117683Spst *netp = sin->sin_addr.s_addr; 55217683Spst if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { 55375107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 55475107Sfenner "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno)); 55517683Spst (void)close(fd); 55617683Spst return (-1); 55717683Spst } 55817683Spst (void)close(fd); 55917683Spst *maskp = sin->sin_addr.s_addr; 56017683Spst if (*maskp == 0) { 56117683Spst if (IN_CLASSA(*netp)) 56217683Spst *maskp = IN_CLASSA_NET; 56317683Spst else if (IN_CLASSB(*netp)) 56417683Spst *maskp = IN_CLASSB_NET; 56517683Spst else if (IN_CLASSC(*netp)) 56617683Spst *maskp = IN_CLASSC_NET; 56717683Spst else { 56875107Sfenner (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 56975107Sfenner "inet class for 0x%x unknown", *netp); 57017683Spst return (-1); 57117683Spst } 57217683Spst } 57317683Spst *netp &= *maskp; 57417683Spst return (0); 57517683Spst} 576127664Sbms 577127664Sbms#else /* WIN32 */ 578127664Sbms 579127664Sbms/* 580127664Sbms * Return the name of a network interface attached to the system, or NULL 581127664Sbms * if none can be found. The interface must be configured up; the 582127664Sbms * lowest unit number is preferred; loopback is ignored. 583127664Sbms */ 584127664Sbmschar * 585127664Sbmspcap_lookupdev(errbuf) 586127664Sbms register char *errbuf; 587127664Sbms{ 588127664Sbms DWORD dwVersion; 589127664Sbms DWORD dwWindowsMajorVersion; 590127664Sbms dwVersion = GetVersion(); /* get the OS version */ 591127664Sbms dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); 592127664Sbms 593127664Sbms if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) { 594127664Sbms /* 595127664Sbms * Windows 95, 98, ME. 596127664Sbms */ 597127664Sbms ULONG NameLength = 8192; 598127664Sbms static char AdaptersName[8192]; 599127664Sbms 600127664Sbms PacketGetAdapterNames(AdaptersName,&NameLength); 601127664Sbms 602127664Sbms return (AdaptersName); 603127664Sbms } else { 604127664Sbms /* 605127664Sbms * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility 606127664Sbms */ 607127664Sbms ULONG NameLength = 8192; 608127664Sbms static WCHAR AdaptersName[8192]; 609127664Sbms char *tAstr; 610127664Sbms WCHAR *tUstr; 611127664Sbms WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR)); 612127664Sbms int NAdapts = 0; 613127664Sbms 614127664Sbms if(TAdaptersName == NULL) 615127664Sbms { 616127664Sbms (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure"); 617127664Sbms return NULL; 618127664Sbms } 619127664Sbms 620127664Sbms PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength); 621127664Sbms 622127664Sbms tAstr = (char*)TAdaptersName; 623127664Sbms tUstr = (WCHAR*)AdaptersName; 624127664Sbms 625127664Sbms /* 626127664Sbms * Convert and copy the device names 627127664Sbms */ 628127664Sbms while(sscanf(tAstr, "%S", tUstr) > 0) 629127664Sbms { 630127664Sbms tAstr += strlen(tAstr) + 1; 631127664Sbms tUstr += wcslen(tUstr) + 1; 632127664Sbms NAdapts ++; 633127664Sbms } 634127664Sbms 635127664Sbms tAstr++; 636127664Sbms *tUstr = 0; 637127664Sbms tUstr++; 638127664Sbms 639127664Sbms /* 640127664Sbms * Copy the descriptions 641127664Sbms */ 642127664Sbms while(NAdapts--) 643127664Sbms { 644127664Sbms strcpy((char*)tUstr, tAstr); 645127664Sbms (char*)tUstr += strlen(tAstr) + 1;; 646127664Sbms tAstr += strlen(tAstr) + 1; 647127664Sbms } 648127664Sbms 649127664Sbms return (char *)(AdaptersName); 650127664Sbms } 651127664Sbms} 652127664Sbms 653127664Sbms 654127664Sbmsint 655127664Sbmspcap_lookupnet(device, netp, maskp, errbuf) 656127664Sbms const register char *device; 657127664Sbms register bpf_u_int32 *netp, *maskp; 658127664Sbms register char *errbuf; 659127664Sbms{ 660127664Sbms /* 661127664Sbms * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo() 662127664Sbms * in order to skip non IPv4 (i.e. IPv6 addresses) 663127664Sbms */ 664127664Sbms npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES]; 665127664Sbms LONG if_addr_size = 1; 666127664Sbms struct sockaddr_in *t_addr; 667127664Sbms unsigned int i; 668127664Sbms 669127664Sbms if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) { 670127664Sbms *netp = *maskp = 0; 671127664Sbms return (0); 672127664Sbms } 673127664Sbms 674127664Sbms for(i=0; i<MAX_NETWORK_ADDRESSES; i++) 675127664Sbms { 676127664Sbms if(if_addrs[i].IPAddress.ss_family == AF_INET) 677127664Sbms { 678127664Sbms t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress); 679127664Sbms *netp = t_addr->sin_addr.S_un.S_addr; 680127664Sbms t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask); 681127664Sbms *maskp = t_addr->sin_addr.S_un.S_addr; 682127664Sbms 683127664Sbms *netp &= *maskp; 684127664Sbms return (0); 685127664Sbms } 686127664Sbms 687127664Sbms } 688127664Sbms 689127664Sbms *netp = *maskp = 0; 690127664Sbms return (0); 691127664Sbms} 692127664Sbms 693127664Sbms#endif /* WIN32 */ 694