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