inet.c revision 190225
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_ =
37190225Srpaulo    "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.75.2.4 2008-04-20 18:19:24 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 *
369190225Srpaulo * Do NetBSD, DragonflyBSD, or OpenBSD support this as well?  OpenBSD
370190225Srpaulo * lets you get a description, but it's not generated by the OS, it's
371190225Srpaulo * set with another ioctl that ifconfig supports; we use that to get
372190225Srpaulo * the description in OpenBSD.
373190225Srpaulo *
374190225Srpaulo * In OS X, the System Configuration framework can apparently return
375190225Srpaulo * names in 10.4 and later; it also appears that freedesktop.org's HAL
376190225Srpaulo * offers an "info.product" string, but the HAL specification says
377190225Srpaulo * it "should not be used in any UI" and "subsystem/capability
378190225Srpaulo * specific properties" should be used instead.  Using that would
379190225Srpaulo * require that libpcap applications be linked with the frameworks/
380190225Srpaulo * libraries in question, which would be a bit of a pain unless we
381190225Srpaulo * offer, for example, a pkg-config:
382190225Srpaulo *
383190225Srpaulo *	http://pkg-config.freedesktop.org/wiki/
384190225Srpaulo *
385190225Srpaulo * script, so applications can just use that script to find out what
386190225Srpaulo * libraries you need to link with when linking with libpcap.
387190225Srpaulo * pkg-config is GPLed; I don't know whether that would prevent its
388190225Srpaulo * use with a BSD-licensed library such as libpcap.
389190225Srpaulo *
390190225Srpaulo * Do any other UN*Xes, or desktop environments support getting a
391190225Srpaulo * description?
392190225Srpaulo */
393127664Sbmsint
394146768Ssamadd_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
395127664Sbms    struct sockaddr *addr, size_t addr_size,
396127664Sbms    struct sockaddr *netmask, size_t netmask_size,
397127664Sbms    struct sockaddr *broadaddr, size_t broadaddr_size,
398127664Sbms    struct sockaddr *dstaddr, size_t dstaddr_size,
399127664Sbms    char *errbuf)
40098530Sfenner{
40198530Sfenner	pcap_if_t *curdev;
402190225Srpaulo	char *description = NULL;
40398530Sfenner	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
404190225Srpaulo#ifdef SIOCGIFDESCR
405190225Srpaulo	struct ifreq ifrdesc;
406190225Srpaulo	char ifdescr[IFDESCRSIZE];
407190225Srpaulo	int s;
408190225Srpaulo#endif
40998530Sfenner
410190225Srpaulo#ifdef SIOCGIFDESCR
411190225Srpaulo	/*
412190225Srpaulo	 * Get the description for the interface.
413190225Srpaulo	 */
414190225Srpaulo	memset(&ifrdesc, 0, sizeof ifrdesc);
415190225Srpaulo	strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
416190225Srpaulo	ifrdesc.ifr_data = (caddr_t)&ifdescr;
417190225Srpaulo	s = socket(AF_INET, SOCK_DGRAM, 0);
418190225Srpaulo	if (s >= 0) {
419190225Srpaulo		if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0 &&
420190225Srpaulo		    strlen(ifrdesc.ifr_data) != 0)
421190225Srpaulo			description = ifrdesc.ifr_data;
422190225Srpaulo		close(s);
423190225Srpaulo	}
424190225Srpaulo#endif
425190225Srpaulo
426190225Srpaulo	if (add_or_find_if(&curdev, alldevs, name, flags, description,
427190225Srpaulo	    errbuf) == -1) {
42898530Sfenner		/*
42998530Sfenner		 * Error - give up.
43098530Sfenner		 */
43198530Sfenner		return (-1);
43298530Sfenner	}
43398530Sfenner	if (curdev == NULL) {
43498530Sfenner		/*
43598530Sfenner		 * Device wasn't added because it can't be opened.
43698530Sfenner		 * Not a fatal error.
43798530Sfenner		 */
43898530Sfenner		return (0);
43998530Sfenner	}
44098530Sfenner
44198530Sfenner	/*
44298530Sfenner	 * "curdev" is an entry for this interface; add an entry for this
44398530Sfenner	 * address to its list of addresses.
44498530Sfenner	 *
44598530Sfenner	 * Allocate the new entry and fill it in.
44698530Sfenner	 */
44798530Sfenner	curaddr = malloc(sizeof(pcap_addr_t));
44898530Sfenner	if (curaddr == NULL) {
44998530Sfenner		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
45098530Sfenner		    "malloc: %s", pcap_strerror(errno));
45198530Sfenner		return (-1);
45298530Sfenner	}
45398530Sfenner
45498530Sfenner	curaddr->next = NULL;
45598530Sfenner	if (addr != NULL) {
456127664Sbms		curaddr->addr = dup_sockaddr(addr, addr_size);
45798530Sfenner		if (curaddr->addr == NULL) {
45898530Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
45998530Sfenner			    "malloc: %s", pcap_strerror(errno));
46098530Sfenner			free(curaddr);
46198530Sfenner			return (-1);
46298530Sfenner		}
46398530Sfenner	} else
46498530Sfenner		curaddr->addr = NULL;
46598530Sfenner
46698530Sfenner	if (netmask != NULL) {
467127664Sbms		curaddr->netmask = dup_sockaddr(netmask, netmask_size);
46898530Sfenner		if (curaddr->netmask == NULL) {
46998530Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
47098530Sfenner			    "malloc: %s", pcap_strerror(errno));
471172677Smlaier			if (curaddr->addr != NULL)
472172677Smlaier				free(curaddr->addr);
47398530Sfenner			free(curaddr);
47498530Sfenner			return (-1);
47598530Sfenner		}
47698530Sfenner	} else
47798530Sfenner		curaddr->netmask = NULL;
478127664Sbms
47998530Sfenner	if (broadaddr != NULL) {
480127664Sbms		curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
48198530Sfenner		if (curaddr->broadaddr == NULL) {
48298530Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
48398530Sfenner			    "malloc: %s", pcap_strerror(errno));
484172677Smlaier			if (curaddr->netmask != NULL)
485172677Smlaier				free(curaddr->netmask);
486172677Smlaier			if (curaddr->addr != NULL)
487172677Smlaier				free(curaddr->addr);
48898530Sfenner			free(curaddr);
48998530Sfenner			return (-1);
49098530Sfenner		}
49198530Sfenner	} else
49298530Sfenner		curaddr->broadaddr = NULL;
493127664Sbms
49498530Sfenner	if (dstaddr != NULL) {
495127664Sbms		curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
49698530Sfenner		if (curaddr->dstaddr == NULL) {
49798530Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
49898530Sfenner			    "malloc: %s", pcap_strerror(errno));
499172677Smlaier			if (curaddr->broadaddr != NULL)
500172677Smlaier				free(curaddr->broadaddr);
501172677Smlaier			if (curaddr->netmask != NULL)
502172677Smlaier				free(curaddr->netmask);
503172677Smlaier			if (curaddr->addr != NULL)
504172677Smlaier				free(curaddr->addr);
50598530Sfenner			free(curaddr);
50698530Sfenner			return (-1);
50798530Sfenner		}
50898530Sfenner	} else
50998530Sfenner		curaddr->dstaddr = NULL;
510127664Sbms
51198530Sfenner	/*
51298530Sfenner	 * Find the end of the list of addresses.
51398530Sfenner	 */
51498530Sfenner	for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
51598530Sfenner		nextaddr = prevaddr->next;
51698530Sfenner		if (nextaddr == NULL) {
51798530Sfenner			/*
51898530Sfenner			 * This is the end of the list.
51998530Sfenner			 */
52098530Sfenner			break;
52198530Sfenner		}
52298530Sfenner	}
52398530Sfenner
52498530Sfenner	if (prevaddr == NULL) {
52598530Sfenner		/*
52698530Sfenner		 * The list was empty; this is the first member.
52798530Sfenner		 */
52898530Sfenner		curdev->addresses = curaddr;
52998530Sfenner	} else {
53098530Sfenner		/*
53198530Sfenner		 * "prevaddr" is the last member of the list; append
53298530Sfenner		 * this member to it.
53398530Sfenner		 */
53498530Sfenner		prevaddr->next = curaddr;
53598530Sfenner	}
53698530Sfenner
53798530Sfenner	return (0);
53898530Sfenner}
53998530Sfenner
540127664Sbmsint
541146768Ssampcap_add_if(pcap_if_t **devlist, const char *name, u_int flags,
54298530Sfenner    const char *description, char *errbuf)
54398530Sfenner{
54498530Sfenner	pcap_if_t *curdev;
54598530Sfenner
54698530Sfenner	return (add_or_find_if(&curdev, devlist, name, flags, description,
54798530Sfenner	    errbuf));
54898530Sfenner}
54998530Sfenner
55075107Sfenner
55198530Sfenner/*
55298530Sfenner * Free a list of interfaces.
55398530Sfenner */
55498530Sfennervoid
55598530Sfennerpcap_freealldevs(pcap_if_t *alldevs)
55698530Sfenner{
55798530Sfenner	pcap_if_t *curdev, *nextdev;
55898530Sfenner	pcap_addr_t *curaddr, *nextaddr;
55998530Sfenner
56098530Sfenner	for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
56198530Sfenner		nextdev = curdev->next;
56298530Sfenner
56398530Sfenner		/*
56498530Sfenner		 * Free all addresses.
56598530Sfenner		 */
56698530Sfenner		for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
56798530Sfenner			nextaddr = curaddr->next;
56898530Sfenner			if (curaddr->addr)
56998530Sfenner				free(curaddr->addr);
57098530Sfenner			if (curaddr->netmask)
57198530Sfenner				free(curaddr->netmask);
57298530Sfenner			if (curaddr->broadaddr)
57398530Sfenner				free(curaddr->broadaddr);
57498530Sfenner			if (curaddr->dstaddr)
57598530Sfenner				free(curaddr->dstaddr);
57698530Sfenner			free(curaddr);
57798530Sfenner		}
57898530Sfenner
57998530Sfenner		/*
58098530Sfenner		 * Free the name string.
58198530Sfenner		 */
58298530Sfenner		free(curdev->name);
58398530Sfenner
58498530Sfenner		/*
58598530Sfenner		 * Free the description string, if any.
58698530Sfenner		 */
58798530Sfenner		if (curdev->description != NULL)
58898530Sfenner			free(curdev->description);
58998530Sfenner
59098530Sfenner		/*
59198530Sfenner		 * Free the interface.
59298530Sfenner		 */
59398530Sfenner		free(curdev);
59498530Sfenner	}
59598530Sfenner}
59698530Sfenner
597146768Ssam#if !defined(WIN32) && !defined(MSDOS)
598127664Sbms
59998530Sfenner/*
60098530Sfenner * Return the name of a network interface attached to the system, or NULL
60198530Sfenner * if none can be found.  The interface must be configured up; the
60298530Sfenner * lowest unit number is preferred; loopback is ignored.
60398530Sfenner */
60498530Sfennerchar *
60598530Sfennerpcap_lookupdev(errbuf)
60698530Sfenner	register char *errbuf;
60798530Sfenner{
60898530Sfenner	pcap_if_t *alldevs;
60998530Sfenner/* for old BSD systems, including bsdi3 */
61098530Sfenner#ifndef IF_NAMESIZE
61198530Sfenner#define IF_NAMESIZE IFNAMSIZ
61298530Sfenner#endif
61398530Sfenner	static char device[IF_NAMESIZE + 1];
61498530Sfenner	char *ret;
61598530Sfenner
61698530Sfenner	if (pcap_findalldevs(&alldevs, errbuf) == -1)
61798530Sfenner		return (NULL);
618127664Sbms
61998530Sfenner	if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
62098530Sfenner		/*
62198530Sfenner		 * There are no devices on the list, or the first device
62298530Sfenner		 * on the list is a loopback device, which means there
62398530Sfenner		 * are no non-loopback devices on the list.  This means
62498530Sfenner		 * we can't return any device.
62598530Sfenner		 *
62698530Sfenner		 * XXX - why not return a loopback device?  If we can't
62798530Sfenner		 * capture on it, it won't be on the list, and if it's
62898530Sfenner		 * on the list, there aren't any non-loopback devices,
62998530Sfenner		 * so why not just supply it as the default device?
63098530Sfenner		 */
63175107Sfenner		(void)strlcpy(errbuf, "no suitable device found",
63275107Sfenner		    PCAP_ERRBUF_SIZE);
63398530Sfenner		ret = NULL;
63498530Sfenner	} else {
63598530Sfenner		/*
63698530Sfenner		 * Return the name of the first device on the list.
63798530Sfenner		 */
63898530Sfenner		(void)strlcpy(device, alldevs->name, sizeof(device));
63998530Sfenner		ret = device;
64017683Spst	}
64117683Spst
64298530Sfenner	pcap_freealldevs(alldevs);
64398530Sfenner	return (ret);
64417683Spst}
64517683Spst
64617683Spstint
64717683Spstpcap_lookupnet(device, netp, maskp, errbuf)
648127664Sbms	register const char *device;
64917683Spst	register bpf_u_int32 *netp, *maskp;
65017683Spst	register char *errbuf;
65117683Spst{
65217683Spst	register int fd;
653172677Smlaier	register struct sockaddr_in *sin4;
65417683Spst	struct ifreq ifr;
65517683Spst
656127664Sbms	/*
65775107Sfenner	 * The pseudo-device "any" listens on all interfaces and therefore
65875107Sfenner	 * has the network address and -mask "0.0.0.0" therefore catching
65975107Sfenner	 * all traffic. Using NULL for the interface is the same as "any".
66075107Sfenner	 */
661127664Sbms	if (!device || strcmp(device, "any") == 0
662127664Sbms#ifdef HAVE_DAG_API
663127664Sbms	    || strstr(device, "dag") != NULL
664127664Sbms#endif
665147894Ssam#ifdef HAVE_SEPTEL_API
666147894Ssam	    || strstr(device, "septel") != NULL
667147894Ssam#endif
668190225Srpaulo#ifdef PCAP_SUPPORT_BT
669190225Srpaulo	    || strstr(device, "bluetooth") != NULL
670190225Srpaulo#endif
671190225Srpaulo#ifdef PCAP_SUPPORT_USB
672190225Srpaulo	    || strstr(device, "usb") != NULL
673190225Srpaulo#endif
674127664Sbms	    ) {
67575107Sfenner		*netp = *maskp = 0;
67675107Sfenner		return 0;
67775107Sfenner	}
67875107Sfenner
67917683Spst	fd = socket(AF_INET, SOCK_DGRAM, 0);
68017683Spst	if (fd < 0) {
68175107Sfenner		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
68275107Sfenner		    pcap_strerror(errno));
68317683Spst		return (-1);
68417683Spst	}
68517683Spst	memset(&ifr, 0, sizeof(ifr));
68617683Spst#ifdef linux
68717683Spst	/* XXX Work around Linux kernel bug */
68817683Spst	ifr.ifr_addr.sa_family = AF_INET;
68917683Spst#endif
69017683Spst	(void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
69117683Spst	if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
69256889Sfenner		if (errno == EADDRNOTAVAIL) {
69375107Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
69475107Sfenner			    "%s: no IPv4 address assigned", device);
69556889Sfenner		} else {
69675107Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
69775107Sfenner			    "SIOCGIFADDR: %s: %s",
69856889Sfenner			    device, pcap_strerror(errno));
69956889Sfenner		}
70017683Spst		(void)close(fd);
70117683Spst		return (-1);
70217683Spst	}
703172677Smlaier	sin4 = (struct sockaddr_in *)&ifr.ifr_addr;
704172677Smlaier	*netp = sin4->sin_addr.s_addr;
70517683Spst	if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
70675107Sfenner		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
70775107Sfenner		    "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
70817683Spst		(void)close(fd);
70917683Spst		return (-1);
71017683Spst	}
71117683Spst	(void)close(fd);
712172677Smlaier	*maskp = sin4->sin_addr.s_addr;
71317683Spst	if (*maskp == 0) {
71417683Spst		if (IN_CLASSA(*netp))
71517683Spst			*maskp = IN_CLASSA_NET;
71617683Spst		else if (IN_CLASSB(*netp))
71717683Spst			*maskp = IN_CLASSB_NET;
71817683Spst		else if (IN_CLASSC(*netp))
71917683Spst			*maskp = IN_CLASSC_NET;
72017683Spst		else {
72175107Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
72275107Sfenner			    "inet class for 0x%x unknown", *netp);
72317683Spst			return (-1);
72417683Spst		}
72517683Spst	}
72617683Spst	*netp &= *maskp;
72717683Spst	return (0);
72817683Spst}
729127664Sbms
730146768Ssam#elif defined(WIN32)
731127664Sbms
732127664Sbms/*
733127664Sbms * Return the name of a network interface attached to the system, or NULL
734127664Sbms * if none can be found.  The interface must be configured up; the
735127664Sbms * lowest unit number is preferred; loopback is ignored.
736127664Sbms */
737127664Sbmschar *
738127664Sbmspcap_lookupdev(errbuf)
739127664Sbms	register char *errbuf;
740127664Sbms{
741127664Sbms	DWORD dwVersion;
742127664Sbms	DWORD dwWindowsMajorVersion;
743127664Sbms	dwVersion = GetVersion();	/* get the OS version */
744127664Sbms	dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
745127664Sbms
746127664Sbms	if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
747127664Sbms		/*
748127664Sbms		 * Windows 95, 98, ME.
749127664Sbms		 */
750127664Sbms		ULONG NameLength = 8192;
751127664Sbms		static char AdaptersName[8192];
752127664Sbms
753146768Ssam		if (PacketGetAdapterNames(AdaptersName,&NameLength) )
754146768Ssam			return (AdaptersName);
755146768Ssam		else
756146768Ssam			return NULL;
757127664Sbms	} else {
758127664Sbms		/*
759127664Sbms		 * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility
760127664Sbms		 */
761127664Sbms		ULONG NameLength = 8192;
762127664Sbms		static WCHAR AdaptersName[8192];
763127664Sbms		char *tAstr;
764127664Sbms		WCHAR *tUstr;
765127664Sbms		WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR));
766127664Sbms		int NAdapts = 0;
767127664Sbms
768127664Sbms		if(TAdaptersName == NULL)
769127664Sbms		{
770127664Sbms			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
771127664Sbms			return NULL;
772127664Sbms		}
773127664Sbms
774146768Ssam		if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
775146768Ssam		{
776146768Ssam			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
777146768Ssam				"PacketGetAdapterNames: %s",
778146768Ssam				pcap_win32strerror());
779146768Ssam			free(TAdaptersName);
780146768Ssam			return NULL;
781146768Ssam		}
782127664Sbms
783146768Ssam
784127664Sbms		tAstr = (char*)TAdaptersName;
785127664Sbms		tUstr = (WCHAR*)AdaptersName;
786127664Sbms
787127664Sbms		/*
788127664Sbms		 * Convert and copy the device names
789127664Sbms		 */
790127664Sbms		while(sscanf(tAstr, "%S", tUstr) > 0)
791127664Sbms		{
792127664Sbms			tAstr += strlen(tAstr) + 1;
793127664Sbms			tUstr += wcslen(tUstr) + 1;
794127664Sbms			NAdapts ++;
795127664Sbms		}
796127664Sbms
797127664Sbms		tAstr++;
798127664Sbms		*tUstr = 0;
799127664Sbms		tUstr++;
800127664Sbms
801127664Sbms		/*
802127664Sbms		 * Copy the descriptions
803127664Sbms		 */
804127664Sbms		while(NAdapts--)
805127664Sbms		{
806127664Sbms			strcpy((char*)tUstr, tAstr);
807127664Sbms			(char*)tUstr += strlen(tAstr) + 1;;
808127664Sbms			tAstr += strlen(tAstr) + 1;
809127664Sbms		}
810127664Sbms
811146768Ssam		free(TAdaptersName);
812127664Sbms		return (char *)(AdaptersName);
813127664Sbms	}
814127664Sbms}
815127664Sbms
816127664Sbms
817127664Sbmsint
818127664Sbmspcap_lookupnet(device, netp, maskp, errbuf)
819146768Ssam	register const char *device;
820127664Sbms	register bpf_u_int32 *netp, *maskp;
821127664Sbms	register char *errbuf;
822127664Sbms{
823127664Sbms	/*
824127664Sbms	 * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo()
825127664Sbms	 * in order to skip non IPv4 (i.e. IPv6 addresses)
826127664Sbms	 */
827127664Sbms	npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
828127664Sbms	LONG if_addr_size = 1;
829127664Sbms	struct sockaddr_in *t_addr;
830127664Sbms	unsigned int i;
831127664Sbms
832127664Sbms	if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
833127664Sbms		*netp = *maskp = 0;
834127664Sbms		return (0);
835127664Sbms	}
836127664Sbms
837127664Sbms	for(i=0; i<MAX_NETWORK_ADDRESSES; i++)
838127664Sbms	{
839127664Sbms		if(if_addrs[i].IPAddress.ss_family == AF_INET)
840127664Sbms		{
841127664Sbms			t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress);
842127664Sbms			*netp = t_addr->sin_addr.S_un.S_addr;
843127664Sbms			t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask);
844127664Sbms			*maskp = t_addr->sin_addr.S_un.S_addr;
845127664Sbms
846127664Sbms			*netp &= *maskp;
847127664Sbms			return (0);
848127664Sbms		}
849127664Sbms
850127664Sbms	}
851127664Sbms
852127664Sbms	*netp = *maskp = 0;
853127664Sbms	return (0);
854127664Sbms}
855127664Sbms
856146768Ssam#endif /* !WIN32 && !MSDOS */
857