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