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