inet.c revision 147894
198530Sfenner/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
217683Spst/*
339291Sfenner * Copyright (c) 1994, 1995, 1996, 1997, 1998
417683Spst *	The Regents of the University of California.  All rights reserved.
517683Spst *
617683Spst * Redistribution and use in source and binary forms, with or without
717683Spst * modification, are permitted provided that the following conditions
817683Spst * are met:
917683Spst * 1. Redistributions of source code must retain the above copyright
1017683Spst *    notice, this list of conditions and the following disclaimer.
1117683Spst * 2. Redistributions in binary form must reproduce the above copyright
1217683Spst *    notice, this list of conditions and the following disclaimer in the
1317683Spst *    documentation and/or other materials provided with the distribution.
1417683Spst * 3. All advertising materials mentioning features or use of this software
1517683Spst *    must display the following acknowledgement:
1617683Spst *	This product includes software developed by the Computer Systems
1717683Spst *	Engineering Group at Lawrence Berkeley Laboratory.
1817683Spst * 4. Neither the name of the University nor of the Laboratory may be used
1917683Spst *    to endorse or promote products derived from this software without
2017683Spst *    specific prior written permission.
2117683Spst *
2217683Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2317683Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2417683Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2517683Spst * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2617683Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2717683Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2817683Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2917683Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3017683Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3117683Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3217683Spst * SUCH DAMAGE.
3317683Spst */
3417683Spst
3517683Spst#ifndef lint
36127664Sbmsstatic const char rcsid[] _U_ =
37147894Ssam    "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.66.2.1 2005/06/20 21:30:17 guy Exp $ (LBL)";
3817683Spst#endif
3917683Spst
4075107Sfenner#ifdef HAVE_CONFIG_H
4175107Sfenner#include "config.h"
4275107Sfenner#endif
4375107Sfenner
44127664Sbms#ifdef WIN32
45127664Sbms#include <pcap-stdinc.h>
46127664Sbms#else /* WIN32 */
47127664Sbms
4817683Spst#include <sys/param.h>
49146768Ssam#ifndef MSDOS
5017683Spst#include <sys/file.h>
51146768Ssam#endif
5217683Spst#include <sys/ioctl.h>
5317683Spst#include <sys/socket.h>
5417683Spst#ifdef HAVE_SYS_SOCKIO_H
5517683Spst#include <sys/sockio.h>
5617683Spst#endif
5717683Spst
58127664Sbmsstruct mbuf;		/* Squelch compiler warnings on some platforms for */
59127664Sbmsstruct rtentry;		/* declarations in <net/if.h> */
6017683Spst#include <net/if.h>
6117683Spst#include <netinet/in.h>
62127664Sbms#endif /* WIN32 */
6317683Spst
6417683Spst#include <ctype.h>
6517683Spst#include <errno.h>
6617683Spst#include <memory.h>
6717683Spst#include <stdio.h>
6817683Spst#include <stdlib.h>
6917683Spst#include <string.h>
70146768Ssam#if !defined(WIN32) && !defined(__BORLANDC__)
7117683Spst#include <unistd.h>
72146768Ssam#endif /* !WIN32 && !__BORLANDC__ */
7398530Sfenner#ifdef HAVE_LIMITS_H
7498530Sfenner#include <limits.h>
7598530Sfenner#else
7698530Sfenner#define INT_MAX		2147483647
7798530Sfenner#endif
7817683Spst
7917683Spst#include "pcap-int.h"
8017683Spst
8117683Spst#ifdef HAVE_OS_PROTO_H
8217683Spst#include "os-proto.h"
8317683Spst#endif
8417683Spst
8517683Spst/* Not all systems have IFF_LOOPBACK */
8617683Spst#ifdef IFF_LOOPBACK
8798530Sfenner#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
8817683Spst#else
8998530Sfenner#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
9098530Sfenner    (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
9117683Spst#endif
9217683Spst
93127664Sbmsstruct sockaddr *
94127664Sbmsdup_sockaddr(struct sockaddr *sa, size_t sa_length)
9517683Spst{
9698530Sfenner	struct sockaddr *newsa;
97127664Sbms
98127664Sbms	if ((newsa = malloc(sa_length)) == NULL)
9998530Sfenner		return (NULL);
100127664Sbms	return (memcpy(newsa, sa, sa_length));
10198530Sfenner}
10298530Sfenner
10398530Sfennerstatic int
104127664Sbmsget_instance(const char *name)
10598530Sfenner{
106127664Sbms	const char *cp, *endcp;
10798530Sfenner	int n;
10898530Sfenner
10998530Sfenner	if (strcmp(name, "any") == 0) {
11098530Sfenner		/*
11198530Sfenner		 * Give the "any" device an artificially high instance
11298530Sfenner		 * number, so it shows up after all other non-loopback
11398530Sfenner		 * interfaces.
11498530Sfenner		 */
11598530Sfenner		return INT_MAX;
11698530Sfenner	}
11798530Sfenner
11898530Sfenner	endcp = name + strlen(name);
11998530Sfenner	for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp)
12098530Sfenner		continue;
12198530Sfenner
12298530Sfenner	if (isdigit((unsigned char)*cp))
12398530Sfenner		n = atoi(cp);
12498530Sfenner	else
12598530Sfenner		n = 0;
12698530Sfenner	return (n);
12798530Sfenner}
12898530Sfenner
129127664Sbmsint
130127664Sbmsadd_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
13198530Sfenner    u_int flags, const char *description, char *errbuf)
13298530Sfenner{
133146768Ssam	pcap_t *p;
13498530Sfenner	pcap_if_t *curdev, *prevdev, *nextdev;
13598530Sfenner	int this_instance;
13698530Sfenner
13798530Sfenner	/*
138146768Ssam	 * Can we open this interface for live capture?
139146768Ssam	 *
140146768Ssam	 * We do this check so that interfaces that ae supplied
141146768Ssam	 * by the interface enumeration mechanism we're using
142146768Ssam	 * but that don't support packet capture aren't included
143146768Ssam	 * in the list.  An example of this is loopback interfaces
144146768Ssam	 * on Solaris; we don't just omit loopback interfaces
145146768Ssam	 * becaue you *can* capture on loopback interfaces on some
146146768Ssam	 * OSes.
147146768Ssam	 */
148146768Ssam	p = pcap_open_live(name, 68, 0, 0, errbuf);
149146768Ssam	if (p == NULL) {
150146768Ssam		/*
151146768Ssam		 * No.  Don't bother including it.
152146768Ssam		 * Don't treat this as an error, though.
153146768Ssam		 */
154146768Ssam		*curdev_ret = NULL;
155146768Ssam		return (0);
156146768Ssam	}
157146768Ssam	pcap_close(p);
158146768Ssam
159146768Ssam	/*
16098530Sfenner	 * Is there already an entry in the list for this interface?
16198530Sfenner	 */
16298530Sfenner	for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
16398530Sfenner		if (strcmp(name, curdev->name) == 0)
16498530Sfenner			break;	/* yes, we found it */
16598530Sfenner	}
16698530Sfenner	if (curdev == NULL) {
16798530Sfenner		/*
16898530Sfenner		 * No, we didn't find it.
16998530Sfenner		 * Allocate a new entry.
17098530Sfenner		 */
17198530Sfenner		curdev = malloc(sizeof(pcap_if_t));
17298530Sfenner		if (curdev == NULL) {
17398530Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
17498530Sfenner			    "malloc: %s", pcap_strerror(errno));
17598530Sfenner			return (-1);
17698530Sfenner		}
177127664Sbms
17898530Sfenner		/*
17998530Sfenner		 * Fill in the entry.
18098530Sfenner		 */
18198530Sfenner		curdev->next = NULL;
18298530Sfenner		curdev->name = malloc(strlen(name) + 1);
18398530Sfenner		strcpy(curdev->name, name);
18498530Sfenner		if (description != NULL) {
18598530Sfenner			/*
18698530Sfenner			 * We have a description for this interface.
18798530Sfenner			 */
18898530Sfenner			curdev->description = malloc(strlen(description) + 1);
18998530Sfenner			strcpy(curdev->description, description);
19098530Sfenner		} else {
19198530Sfenner			/*
19298530Sfenner			 * We don't.
19398530Sfenner			 */
19498530Sfenner			curdev->description = NULL;
19598530Sfenner		}
19698530Sfenner		curdev->addresses = NULL;	/* list starts out as empty */
19798530Sfenner		curdev->flags = 0;
19898530Sfenner		if (ISLOOPBACK(name, flags))
19998530Sfenner			curdev->flags |= PCAP_IF_LOOPBACK;
20098530Sfenner
20198530Sfenner		/*
20298530Sfenner		 * Add it to the list, in the appropriate location.
20398530Sfenner		 * First, get the instance number of this interface.
20498530Sfenner		 */
20598530Sfenner		this_instance = get_instance(name);
20698530Sfenner
20798530Sfenner		/*
20898530Sfenner		 * Now look for the last interface with an instance number
20998530Sfenner		 * less than or equal to the new interface's instance
21098530Sfenner		 * number - except that non-loopback interfaces are
21198530Sfenner		 * arbitrarily treated as having interface numbers less
21298530Sfenner		 * than those of loopback interfaces, so the loopback
21398530Sfenner		 * interfaces are put at the end of the list.
21498530Sfenner		 *
21598530Sfenner		 * We start with "prevdev" being NULL, meaning we're before
21698530Sfenner		 * the first element in the list.
21798530Sfenner		 */
21898530Sfenner		prevdev = NULL;
21998530Sfenner		for (;;) {
22098530Sfenner			/*
22198530Sfenner			 * Get the interface after this one.
22298530Sfenner			 */
22398530Sfenner			if (prevdev == NULL) {
22498530Sfenner				/*
22598530Sfenner				 * The next element is the first element.
22698530Sfenner				 */
22798530Sfenner				nextdev = *alldevs;
22898530Sfenner			} else
22998530Sfenner				nextdev = prevdev->next;
23098530Sfenner
23198530Sfenner			/*
23298530Sfenner			 * Are we at the end of the list?
23398530Sfenner			 */
23498530Sfenner			if (nextdev == NULL) {
23598530Sfenner				/*
23698530Sfenner				 * Yes - we have to put the new entry
23798530Sfenner				 * after "prevdev".
23898530Sfenner				 */
23998530Sfenner				break;
24098530Sfenner			}
24198530Sfenner
24298530Sfenner			/*
24398530Sfenner			 * Is the new interface a non-loopback interface
24498530Sfenner			 * and the next interface a loopback interface?
24598530Sfenner			 */
24698530Sfenner			if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
24798530Sfenner			    (nextdev->flags & PCAP_IF_LOOPBACK)) {
24898530Sfenner				/*
24998530Sfenner				 * Yes, we should put the new entry
25098530Sfenner				 * before "nextdev", i.e. after "prevdev".
25198530Sfenner				 */
25298530Sfenner				break;
25398530Sfenner			}
25498530Sfenner
25598530Sfenner			/*
25698530Sfenner			 * Is the new interface's instance number less
25798530Sfenner			 * than the next interface's instance number,
25898530Sfenner			 * and is it the case that the new interface is a
25998530Sfenner			 * non-loopback interface or the next interface is
26098530Sfenner			 * a loopback interface?
26198530Sfenner			 *
26298530Sfenner			 * (The goal of both loopback tests is to make
26398530Sfenner			 * sure that we never put a loopback interface
26498530Sfenner			 * before any non-loopback interface and that we
26598530Sfenner			 * always put a non-loopback interface before all
26698530Sfenner			 * loopback interfaces.)
26798530Sfenner			 */
26898530Sfenner			if (this_instance < get_instance(nextdev->name) &&
26998530Sfenner			    (!(curdev->flags & PCAP_IF_LOOPBACK) ||
27098530Sfenner			       (nextdev->flags & PCAP_IF_LOOPBACK))) {
27198530Sfenner				/*
27298530Sfenner				 * Yes - we should put the new entry
27398530Sfenner				 * before "nextdev", i.e. after "prevdev".
27498530Sfenner				 */
27598530Sfenner				break;
27698530Sfenner			}
27798530Sfenner
27898530Sfenner			prevdev = nextdev;
27998530Sfenner		}
28098530Sfenner
28198530Sfenner		/*
28298530Sfenner		 * Insert before "nextdev".
28398530Sfenner		 */
28498530Sfenner		curdev->next = nextdev;
28598530Sfenner
28698530Sfenner		/*
28798530Sfenner		 * Insert after "prevdev" - unless "prevdev" is null,
28898530Sfenner		 * in which case this is the first interface.
28998530Sfenner		 */
29098530Sfenner		if (prevdev == NULL) {
29198530Sfenner			/*
29298530Sfenner			 * This is the first interface.  Pass back a
29398530Sfenner			 * pointer to it, and put "curdev" before
29498530Sfenner			 * "nextdev".
29598530Sfenner			 */
29698530Sfenner			*alldevs = curdev;
29798530Sfenner		} else
29898530Sfenner			prevdev->next = curdev;
29998530Sfenner	}
300127664Sbms
30198530Sfenner	*curdev_ret = curdev;
30298530Sfenner	return (0);
30398530Sfenner}
30498530Sfenner
305127664Sbmsint
306146768Ssamadd_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
307127664Sbms    struct sockaddr *addr, size_t addr_size,
308127664Sbms    struct sockaddr *netmask, size_t netmask_size,
309127664Sbms    struct sockaddr *broadaddr, size_t broadaddr_size,
310127664Sbms    struct sockaddr *dstaddr, size_t dstaddr_size,
311127664Sbms    char *errbuf)
31298530Sfenner{
31398530Sfenner	pcap_if_t *curdev;
31498530Sfenner	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
31598530Sfenner
31698530Sfenner	if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
31798530Sfenner		/*
31898530Sfenner		 * Error - give up.
31998530Sfenner		 */
32098530Sfenner		return (-1);
32198530Sfenner	}
32298530Sfenner	if (curdev == NULL) {
32398530Sfenner		/*
32498530Sfenner		 * Device wasn't added because it can't be opened.
32598530Sfenner		 * Not a fatal error.
32698530Sfenner		 */
32798530Sfenner		return (0);
32898530Sfenner	}
32998530Sfenner
33098530Sfenner	/*
33198530Sfenner	 * "curdev" is an entry for this interface; add an entry for this
33298530Sfenner	 * address to its list of addresses.
33398530Sfenner	 *
33498530Sfenner	 * Allocate the new entry and fill it in.
33598530Sfenner	 */
33698530Sfenner	curaddr = malloc(sizeof(pcap_addr_t));
33798530Sfenner	if (curaddr == NULL) {
33898530Sfenner		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
33998530Sfenner		    "malloc: %s", pcap_strerror(errno));
34098530Sfenner		return (-1);
34198530Sfenner	}
34298530Sfenner
34398530Sfenner	curaddr->next = NULL;
34498530Sfenner	if (addr != NULL) {
345127664Sbms		curaddr->addr = dup_sockaddr(addr, addr_size);
34698530Sfenner		if (curaddr->addr == NULL) {
34798530Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
34898530Sfenner			    "malloc: %s", pcap_strerror(errno));
34998530Sfenner			free(curaddr);
35098530Sfenner			return (-1);
35198530Sfenner		}
35298530Sfenner	} else
35398530Sfenner		curaddr->addr = NULL;
35498530Sfenner
35598530Sfenner	if (netmask != NULL) {
356127664Sbms		curaddr->netmask = dup_sockaddr(netmask, netmask_size);
35798530Sfenner		if (curaddr->netmask == NULL) {
35898530Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
35998530Sfenner			    "malloc: %s", pcap_strerror(errno));
36098530Sfenner			free(curaddr);
36198530Sfenner			return (-1);
36298530Sfenner		}
36398530Sfenner	} else
36498530Sfenner		curaddr->netmask = NULL;
365127664Sbms
36698530Sfenner	if (broadaddr != NULL) {
367127664Sbms		curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
36898530Sfenner		if (curaddr->broadaddr == NULL) {
36998530Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
37098530Sfenner			    "malloc: %s", pcap_strerror(errno));
37198530Sfenner			free(curaddr);
37298530Sfenner			return (-1);
37398530Sfenner		}
37498530Sfenner	} else
37598530Sfenner		curaddr->broadaddr = NULL;
376127664Sbms
37798530Sfenner	if (dstaddr != NULL) {
378127664Sbms		curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
37998530Sfenner		if (curaddr->dstaddr == NULL) {
38098530Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
38198530Sfenner			    "malloc: %s", pcap_strerror(errno));
38298530Sfenner			free(curaddr);
38398530Sfenner			return (-1);
38498530Sfenner		}
38598530Sfenner	} else
38698530Sfenner		curaddr->dstaddr = NULL;
387127664Sbms
38898530Sfenner	/*
38998530Sfenner	 * Find the end of the list of addresses.
39098530Sfenner	 */
39198530Sfenner	for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
39298530Sfenner		nextaddr = prevaddr->next;
39398530Sfenner		if (nextaddr == NULL) {
39498530Sfenner			/*
39598530Sfenner			 * This is the end of the list.
39698530Sfenner			 */
39798530Sfenner			break;
39898530Sfenner		}
39998530Sfenner	}
40098530Sfenner
40198530Sfenner	if (prevaddr == NULL) {
40298530Sfenner		/*
40398530Sfenner		 * The list was empty; this is the first member.
40498530Sfenner		 */
40598530Sfenner		curdev->addresses = curaddr;
40698530Sfenner	} else {
40798530Sfenner		/*
40898530Sfenner		 * "prevaddr" is the last member of the list; append
40998530Sfenner		 * this member to it.
41098530Sfenner		 */
41198530Sfenner		prevaddr->next = curaddr;
41298530Sfenner	}
41398530Sfenner
41498530Sfenner	return (0);
41598530Sfenner}
41698530Sfenner
417127664Sbmsint
418146768Ssampcap_add_if(pcap_if_t **devlist, const char *name, u_int flags,
41998530Sfenner    const char *description, char *errbuf)
42098530Sfenner{
42198530Sfenner	pcap_if_t *curdev;
42298530Sfenner
42398530Sfenner	return (add_or_find_if(&curdev, devlist, name, flags, description,
42498530Sfenner	    errbuf));
42598530Sfenner}
42698530Sfenner
42775107Sfenner
42898530Sfenner/*
42998530Sfenner * Free a list of interfaces.
43098530Sfenner */
43198530Sfennervoid
43298530Sfennerpcap_freealldevs(pcap_if_t *alldevs)
43398530Sfenner{
43498530Sfenner	pcap_if_t *curdev, *nextdev;
43598530Sfenner	pcap_addr_t *curaddr, *nextaddr;
43698530Sfenner
43798530Sfenner	for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
43898530Sfenner		nextdev = curdev->next;
43998530Sfenner
44098530Sfenner		/*
44198530Sfenner		 * Free all addresses.
44298530Sfenner		 */
44398530Sfenner		for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
44498530Sfenner			nextaddr = curaddr->next;
44598530Sfenner			if (curaddr->addr)
44698530Sfenner				free(curaddr->addr);
44798530Sfenner			if (curaddr->netmask)
44898530Sfenner				free(curaddr->netmask);
44998530Sfenner			if (curaddr->broadaddr)
45098530Sfenner				free(curaddr->broadaddr);
45198530Sfenner			if (curaddr->dstaddr)
45298530Sfenner				free(curaddr->dstaddr);
45398530Sfenner			free(curaddr);
45498530Sfenner		}
45598530Sfenner
45698530Sfenner		/*
45798530Sfenner		 * Free the name string.
45898530Sfenner		 */
45998530Sfenner		free(curdev->name);
46098530Sfenner
46198530Sfenner		/*
46298530Sfenner		 * Free the description string, if any.
46398530Sfenner		 */
46498530Sfenner		if (curdev->description != NULL)
46598530Sfenner			free(curdev->description);
46698530Sfenner
46798530Sfenner		/*
46898530Sfenner		 * Free the interface.
46998530Sfenner		 */
47098530Sfenner		free(curdev);
47198530Sfenner	}
47298530Sfenner}
47398530Sfenner
474146768Ssam#if !defined(WIN32) && !defined(MSDOS)
475127664Sbms
47698530Sfenner/*
47798530Sfenner * Return the name of a network interface attached to the system, or NULL
47898530Sfenner * if none can be found.  The interface must be configured up; the
47998530Sfenner * lowest unit number is preferred; loopback is ignored.
48098530Sfenner */
48198530Sfennerchar *
48298530Sfennerpcap_lookupdev(errbuf)
48398530Sfenner	register char *errbuf;
48498530Sfenner{
48598530Sfenner	pcap_if_t *alldevs;
48698530Sfenner/* for old BSD systems, including bsdi3 */
48798530Sfenner#ifndef IF_NAMESIZE
48898530Sfenner#define IF_NAMESIZE IFNAMSIZ
48998530Sfenner#endif
49098530Sfenner	static char device[IF_NAMESIZE + 1];
49198530Sfenner	char *ret;
49298530Sfenner
49398530Sfenner	if (pcap_findalldevs(&alldevs, errbuf) == -1)
49498530Sfenner		return (NULL);
495127664Sbms
49698530Sfenner	if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
49798530Sfenner		/*
49898530Sfenner		 * There are no devices on the list, or the first device
49998530Sfenner		 * on the list is a loopback device, which means there
50098530Sfenner		 * are no non-loopback devices on the list.  This means
50198530Sfenner		 * we can't return any device.
50298530Sfenner		 *
50398530Sfenner		 * XXX - why not return a loopback device?  If we can't
50498530Sfenner		 * capture on it, it won't be on the list, and if it's
50598530Sfenner		 * on the list, there aren't any non-loopback devices,
50698530Sfenner		 * so why not just supply it as the default device?
50798530Sfenner		 */
50875107Sfenner		(void)strlcpy(errbuf, "no suitable device found",
50975107Sfenner		    PCAP_ERRBUF_SIZE);
51098530Sfenner		ret = NULL;
51198530Sfenner	} else {
51298530Sfenner		/*
51398530Sfenner		 * Return the name of the first device on the list.
51498530Sfenner		 */
51598530Sfenner		(void)strlcpy(device, alldevs->name, sizeof(device));
51698530Sfenner		ret = device;
51717683Spst	}
51817683Spst
51998530Sfenner	pcap_freealldevs(alldevs);
52098530Sfenner	return (ret);
52117683Spst}
52217683Spst
52317683Spstint
52417683Spstpcap_lookupnet(device, netp, maskp, errbuf)
525127664Sbms	register const char *device;
52617683Spst	register bpf_u_int32 *netp, *maskp;
52717683Spst	register char *errbuf;
52817683Spst{
52917683Spst	register int fd;
53017683Spst	register struct sockaddr_in *sin;
53117683Spst	struct ifreq ifr;
53217683Spst
533127664Sbms	/*
53475107Sfenner	 * The pseudo-device "any" listens on all interfaces and therefore
53575107Sfenner	 * has the network address and -mask "0.0.0.0" therefore catching
53675107Sfenner	 * all traffic. Using NULL for the interface is the same as "any".
53775107Sfenner	 */
538127664Sbms	if (!device || strcmp(device, "any") == 0
539127664Sbms#ifdef HAVE_DAG_API
540127664Sbms	    || strstr(device, "dag") != NULL
541127664Sbms#endif
542147894Ssam#ifdef HAVE_SEPTEL_API
543147894Ssam	    || strstr(device, "septel") != NULL
544147894Ssam#endif
545127664Sbms	    ) {
54675107Sfenner		*netp = *maskp = 0;
54775107Sfenner		return 0;
54875107Sfenner	}
54975107Sfenner
55017683Spst	fd = socket(AF_INET, SOCK_DGRAM, 0);
55117683Spst	if (fd < 0) {
55275107Sfenner		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
55375107Sfenner		    pcap_strerror(errno));
55417683Spst		return (-1);
55517683Spst	}
55617683Spst	memset(&ifr, 0, sizeof(ifr));
55717683Spst#ifdef linux
55817683Spst	/* XXX Work around Linux kernel bug */
55917683Spst	ifr.ifr_addr.sa_family = AF_INET;
56017683Spst#endif
56117683Spst	(void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
56217683Spst	if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
56356889Sfenner		if (errno == EADDRNOTAVAIL) {
56475107Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
56575107Sfenner			    "%s: no IPv4 address assigned", device);
56656889Sfenner		} else {
56775107Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
56875107Sfenner			    "SIOCGIFADDR: %s: %s",
56956889Sfenner			    device, pcap_strerror(errno));
57056889Sfenner		}
57117683Spst		(void)close(fd);
57217683Spst		return (-1);
57317683Spst	}
57417683Spst	sin = (struct sockaddr_in *)&ifr.ifr_addr;
57517683Spst	*netp = sin->sin_addr.s_addr;
57617683Spst	if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
57775107Sfenner		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
57875107Sfenner		    "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
57917683Spst		(void)close(fd);
58017683Spst		return (-1);
58117683Spst	}
58217683Spst	(void)close(fd);
58317683Spst	*maskp = sin->sin_addr.s_addr;
58417683Spst	if (*maskp == 0) {
58517683Spst		if (IN_CLASSA(*netp))
58617683Spst			*maskp = IN_CLASSA_NET;
58717683Spst		else if (IN_CLASSB(*netp))
58817683Spst			*maskp = IN_CLASSB_NET;
58917683Spst		else if (IN_CLASSC(*netp))
59017683Spst			*maskp = IN_CLASSC_NET;
59117683Spst		else {
59275107Sfenner			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
59375107Sfenner			    "inet class for 0x%x unknown", *netp);
59417683Spst			return (-1);
59517683Spst		}
59617683Spst	}
59717683Spst	*netp &= *maskp;
59817683Spst	return (0);
59917683Spst}
600127664Sbms
601146768Ssam#elif defined(WIN32)
602127664Sbms
603127664Sbms/*
604127664Sbms * Return the name of a network interface attached to the system, or NULL
605127664Sbms * if none can be found.  The interface must be configured up; the
606127664Sbms * lowest unit number is preferred; loopback is ignored.
607127664Sbms */
608127664Sbmschar *
609127664Sbmspcap_lookupdev(errbuf)
610127664Sbms	register char *errbuf;
611127664Sbms{
612127664Sbms	DWORD dwVersion;
613127664Sbms	DWORD dwWindowsMajorVersion;
614127664Sbms	dwVersion = GetVersion();	/* get the OS version */
615127664Sbms	dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
616127664Sbms
617127664Sbms	if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
618127664Sbms		/*
619127664Sbms		 * Windows 95, 98, ME.
620127664Sbms		 */
621127664Sbms		ULONG NameLength = 8192;
622127664Sbms		static char AdaptersName[8192];
623127664Sbms
624146768Ssam		if (PacketGetAdapterNames(AdaptersName,&NameLength) )
625146768Ssam			return (AdaptersName);
626146768Ssam		else
627146768Ssam			return NULL;
628127664Sbms	} else {
629127664Sbms		/*
630127664Sbms		 * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility
631127664Sbms		 */
632127664Sbms		ULONG NameLength = 8192;
633127664Sbms		static WCHAR AdaptersName[8192];
634127664Sbms		char *tAstr;
635127664Sbms		WCHAR *tUstr;
636127664Sbms		WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR));
637127664Sbms		int NAdapts = 0;
638127664Sbms
639127664Sbms		if(TAdaptersName == NULL)
640127664Sbms		{
641127664Sbms			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
642127664Sbms			return NULL;
643127664Sbms		}
644127664Sbms
645146768Ssam		if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
646146768Ssam		{
647146768Ssam			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
648146768Ssam				"PacketGetAdapterNames: %s",
649146768Ssam				pcap_win32strerror());
650146768Ssam			free(TAdaptersName);
651146768Ssam			return NULL;
652146768Ssam		}
653127664Sbms
654146768Ssam
655127664Sbms		tAstr = (char*)TAdaptersName;
656127664Sbms		tUstr = (WCHAR*)AdaptersName;
657127664Sbms
658127664Sbms		/*
659127664Sbms		 * Convert and copy the device names
660127664Sbms		 */
661127664Sbms		while(sscanf(tAstr, "%S", tUstr) > 0)
662127664Sbms		{
663127664Sbms			tAstr += strlen(tAstr) + 1;
664127664Sbms			tUstr += wcslen(tUstr) + 1;
665127664Sbms			NAdapts ++;
666127664Sbms		}
667127664Sbms
668127664Sbms		tAstr++;
669127664Sbms		*tUstr = 0;
670127664Sbms		tUstr++;
671127664Sbms
672127664Sbms		/*
673127664Sbms		 * Copy the descriptions
674127664Sbms		 */
675127664Sbms		while(NAdapts--)
676127664Sbms		{
677127664Sbms			strcpy((char*)tUstr, tAstr);
678127664Sbms			(char*)tUstr += strlen(tAstr) + 1;;
679127664Sbms			tAstr += strlen(tAstr) + 1;
680127664Sbms		}
681127664Sbms
682146768Ssam		free(TAdaptersName);
683127664Sbms		return (char *)(AdaptersName);
684127664Sbms	}
685127664Sbms}
686127664Sbms
687127664Sbms
688127664Sbmsint
689127664Sbmspcap_lookupnet(device, netp, maskp, errbuf)
690146768Ssam	register const char *device;
691127664Sbms	register bpf_u_int32 *netp, *maskp;
692127664Sbms	register char *errbuf;
693127664Sbms{
694127664Sbms	/*
695127664Sbms	 * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo()
696127664Sbms	 * in order to skip non IPv4 (i.e. IPv6 addresses)
697127664Sbms	 */
698127664Sbms	npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
699127664Sbms	LONG if_addr_size = 1;
700127664Sbms	struct sockaddr_in *t_addr;
701127664Sbms	unsigned int i;
702127664Sbms
703127664Sbms	if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
704127664Sbms		*netp = *maskp = 0;
705127664Sbms		return (0);
706127664Sbms	}
707127664Sbms
708127664Sbms	for(i=0; i<MAX_NETWORK_ADDRESSES; i++)
709127664Sbms	{
710127664Sbms		if(if_addrs[i].IPAddress.ss_family == AF_INET)
711127664Sbms		{
712127664Sbms			t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress);
713127664Sbms			*netp = t_addr->sin_addr.S_un.S_addr;
714127664Sbms			t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask);
715127664Sbms			*maskp = t_addr->sin_addr.S_un.S_addr;
716127664Sbms
717127664Sbms			*netp &= *maskp;
718127664Sbms			return (0);
719127664Sbms		}
720127664Sbms
721127664Sbms	}
722127664Sbms
723127664Sbms	*netp = *maskp = 0;
724127664Sbms	return (0);
725127664Sbms}
726127664Sbms
727146768Ssam#endif /* !WIN32 && !MSDOS */
728