1/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
2/*
3 * Copyright (c) 1994, 1995, 1996, 1997, 1998
4 *	The Regents of the University of California.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *	This product includes software developed by the Computer Systems
17 *	Engineering Group at Lawrence Berkeley Laboratory.
18 * 4. Neither the name of the University nor of the Laboratory may be used
19 *    to endorse or promote products derived from this software without
20 *    specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#ifndef lint
36static const char rcsid[] _U_ =
37    "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.79 2008-04-20 18:19:02 guy Exp $ (LBL)";
38#endif
39
40#ifdef HAVE_CONFIG_H
41#include "config.h"
42#endif
43
44#ifdef WIN32
45#include <pcap-stdinc.h>
46#else /* WIN32 */
47
48#include <sys/param.h>
49#ifndef MSDOS
50#include <sys/file.h>
51#endif
52#include <sys/ioctl.h>
53#include <sys/socket.h>
54#ifdef HAVE_SYS_SOCKIO_H
55#include <sys/sockio.h>
56#endif
57
58struct mbuf;		/* Squelch compiler warnings on some platforms for */
59struct rtentry;		/* declarations in <net/if.h> */
60#include <net/if.h>
61#include <netinet/in.h>
62#endif /* WIN32 */
63
64#include <ctype.h>
65#include <errno.h>
66#include <memory.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70#if !defined(WIN32) && !defined(__BORLANDC__)
71#include <unistd.h>
72#endif /* !WIN32 && !__BORLANDC__ */
73#ifdef HAVE_LIMITS_H
74#include <limits.h>
75#else
76#define INT_MAX		2147483647
77#endif
78
79#include "pcap-int.h"
80
81#ifdef HAVE_OS_PROTO_H
82#include "os-proto.h"
83#endif
84
85/* Not all systems have IFF_LOOPBACK */
86#ifdef IFF_LOOPBACK
87#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
88#else
89#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
90    (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
91#endif
92
93struct sockaddr *
94dup_sockaddr(struct sockaddr *sa, size_t sa_length)
95{
96	struct sockaddr *newsa;
97
98	if ((newsa = malloc(sa_length)) == NULL)
99		return (NULL);
100	return (memcpy(newsa, sa, sa_length));
101}
102
103static int
104get_instance(const char *name)
105{
106	const char *cp, *endcp;
107	int n;
108
109	if (strcmp(name, "any") == 0) {
110		/*
111		 * Give the "any" device an artificially high instance
112		 * number, so it shows up after all other non-loopback
113		 * interfaces.
114		 */
115		return INT_MAX;
116	}
117
118	endcp = name + strlen(name);
119	for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp)
120		continue;
121
122	if (isdigit((unsigned char)*cp))
123		n = atoi(cp);
124	else
125		n = 0;
126	return (n);
127}
128
129int
130add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
131    u_int flags, const char *description, char *errbuf)
132{
133	pcap_t *p;
134	pcap_if_t *curdev, *prevdev, *nextdev;
135	int this_instance;
136	char open_errbuf[PCAP_ERRBUF_SIZE];
137
138	/*
139	 * Is there already an entry in the list for this interface?
140	 */
141	for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
142		if (strcmp(name, curdev->name) == 0)
143			break;	/* yes, we found it */
144	}
145
146	if (curdev == NULL) {
147		/*
148		 * No, we didn't find it.
149		 *
150		 * Can we open this interface for live capture?
151		 *
152		 * We do this check so that interfaces that are
153		 * supplied by the interface enumeration mechanism
154		 * we're using but that don't support packet capture
155		 * aren't included in the list.  Loopback interfaces
156		 * on Solaris are an example of this; we don't just
157		 * omit loopback interfaces on all platforms because
158		 * you *can* capture on loopback interfaces on some
159		 * OSes.
160		 *
161		 * On OS X, we don't do this check if the device
162		 * name begins with "wlt"; at least some versions
163		 * of OS X offer monitor mode capturing by having
164		 * a separate "monitor mode" device for each wireless
165		 * adapter, rather than by implementing the ioctls
166		 * that {Free,Net,Open,DragonFly}BSD provide.
167		 * Opening that device puts the adapter into monitor
168		 * mode, which, at least for some adapters, causes
169		 * them to deassociate from the network with which
170		 * they're associated.
171		 *
172		 * Instead, we try to open the corresponding "en"
173		 * device (so that we don't end up with, for users
174		 * without sufficient privilege to open capture
175		 * devices, a list of adapters that only includes
176		 * the wlt devices).
177		 */
178#ifdef __APPLE__
179		if (strncmp(name, "wlt", 3) == 0) {
180			char *en_name;
181			size_t en_name_len;
182
183			/*
184			 * Try to allocate a buffer for the "en"
185			 * device's name.
186			 */
187			en_name_len = strlen(name) - 1;
188			en_name = malloc(en_name_len + 1);
189			if (en_name == NULL) {
190				(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
191				    "malloc: %s", pcap_strerror(errno));
192				return (-1);
193			}
194			strcpy(en_name, "en");
195			strcat(en_name, name + 3);
196			p = pcap_open_live(en_name, 68, 0, 0, open_errbuf);
197			free(en_name);
198		} else
199#endif /* __APPLE */
200		p = pcap_open_live(name, 68, 0, 0, open_errbuf);
201		if (p == NULL) {
202			/*
203			 * No.  Don't bother including it.
204			 * Don't treat this as an error, though.
205			 */
206			*curdev_ret = NULL;
207			return (0);
208		}
209		pcap_close(p);
210
211		/*
212		 * Yes, we can open it.
213		 * Allocate a new entry.
214		 */
215		curdev = malloc(sizeof(pcap_if_t));
216		if (curdev == NULL) {
217			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
218			    "malloc: %s", pcap_strerror(errno));
219			return (-1);
220		}
221
222		/*
223		 * Fill in the entry.
224		 */
225		curdev->next = NULL;
226		curdev->name = strdup(name);
227		if (curdev->name == NULL) {
228			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
229			    "malloc: %s", pcap_strerror(errno));
230			free(curdev);
231			return (-1);
232		}
233		if (description != NULL) {
234			/*
235			 * We have a description for this interface.
236			 */
237			curdev->description = strdup(description);
238			if (curdev->description == NULL) {
239				(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
240				    "malloc: %s", pcap_strerror(errno));
241				free(curdev->name);
242				free(curdev);
243				return (-1);
244			}
245		} else {
246			/*
247			 * We don't.
248			 */
249			curdev->description = NULL;
250		}
251		curdev->addresses = NULL;	/* list starts out as empty */
252		curdev->flags = 0;
253		if (ISLOOPBACK(name, flags))
254			curdev->flags |= PCAP_IF_LOOPBACK;
255
256		/*
257		 * Add it to the list, in the appropriate location.
258		 * First, get the instance number of this interface.
259		 */
260		this_instance = get_instance(name);
261
262		/*
263		 * Now look for the last interface with an instance number
264		 * less than or equal to the new interface's instance
265		 * number - except that non-loopback interfaces are
266		 * arbitrarily treated as having interface numbers less
267		 * than those of loopback interfaces, so the loopback
268		 * interfaces are put at the end of the list.
269		 *
270		 * We start with "prevdev" being NULL, meaning we're before
271		 * the first element in the list.
272		 */
273		prevdev = NULL;
274		for (;;) {
275			/*
276			 * Get the interface after this one.
277			 */
278			if (prevdev == NULL) {
279				/*
280				 * The next element is the first element.
281				 */
282				nextdev = *alldevs;
283			} else
284				nextdev = prevdev->next;
285
286			/*
287			 * Are we at the end of the list?
288			 */
289			if (nextdev == NULL) {
290				/*
291				 * Yes - we have to put the new entry
292				 * after "prevdev".
293				 */
294				break;
295			}
296
297			/*
298			 * Is the new interface a non-loopback interface
299			 * and the next interface a loopback interface?
300			 */
301			if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
302			    (nextdev->flags & PCAP_IF_LOOPBACK)) {
303				/*
304				 * Yes, we should put the new entry
305				 * before "nextdev", i.e. after "prevdev".
306				 */
307				break;
308			}
309
310			/*
311			 * Is the new interface's instance number less
312			 * than the next interface's instance number,
313			 * and is it the case that the new interface is a
314			 * non-loopback interface or the next interface is
315			 * a loopback interface?
316			 *
317			 * (The goal of both loopback tests is to make
318			 * sure that we never put a loopback interface
319			 * before any non-loopback interface and that we
320			 * always put a non-loopback interface before all
321			 * loopback interfaces.)
322			 */
323			if (this_instance < get_instance(nextdev->name) &&
324			    (!(curdev->flags & PCAP_IF_LOOPBACK) ||
325			       (nextdev->flags & PCAP_IF_LOOPBACK))) {
326				/*
327				 * Yes - we should put the new entry
328				 * before "nextdev", i.e. after "prevdev".
329				 */
330				break;
331			}
332
333			prevdev = nextdev;
334		}
335
336		/*
337		 * Insert before "nextdev".
338		 */
339		curdev->next = nextdev;
340
341		/*
342		 * Insert after "prevdev" - unless "prevdev" is null,
343		 * in which case this is the first interface.
344		 */
345		if (prevdev == NULL) {
346			/*
347			 * This is the first interface.  Pass back a
348			 * pointer to it, and put "curdev" before
349			 * "nextdev".
350			 */
351			*alldevs = curdev;
352		} else
353			prevdev->next = curdev;
354	}
355
356	*curdev_ret = curdev;
357	return (0);
358}
359
360/*
361 * XXX - on FreeBSDs that support it, should it get the sysctl named
362 * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
363 * of the adapter?  Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
364 * with my Cisco 350 card, so the name isn't entirely descriptive.  The
365 * "dev.an.0.%pnpinfo" has a better description, although one might argue
366 * that the problem is really a driver bug - if it can find out that it's
367 * a Cisco 340 or 350, rather than an old Aironet card, it should use
368 * that in the description.
369 *
370 * Do NetBSD, DragonflyBSD, or OpenBSD support this as well?  FreeBSD
371 * and OpenBSD let you get a description, but it's not generated by the OS,
372 * it's set with another ioctl that ifconfig supports; we use that to get
373 * a description in FreeBSD and OpenBSD, but if there is no such
374 * description available, it still might be nice to get some description
375 * string based on the device type or something such as that.
376 *
377 * In OS X, the System Configuration framework can apparently return
378 * names in 10.4 and later.
379 *
380 * It also appears that freedesktop.org's HAL offers an "info.product"
381 * string, but the HAL specification says it "should not be used in any
382 * UI" and "subsystem/capability specific properties" should be used
383 * instead and, in any case, I think HAL is being deprecated in
384 * favor of other stuff such as DeviceKit.  DeviceKit doesn't appear
385 * to have any obvious product information for devices, but maybe
386 * I haven't looked hard enough.
387 *
388 * Using the System Configuration framework, or HAL, or DeviceKit, or
389 * whatever, would require that libpcap applications be linked with
390 * the frameworks/libraries in question.  That shouldn't be a problem
391 * for programs linking with the shared version of libpcap (unless
392 * you're running on AIX - which I think is the only UN*X that doesn't
393 * support linking a shared library with other libraries on which it
394 * depends, and having an executable linked only with the first shared
395 * library automatically pick up the other libraries when started -
396 * and using HAL or whatever).  Programs linked with the static
397 * version of libpcap would have to use pcap-config with the --static
398 * flag in order to get the right linker flags in order to pick up
399 * the additional libraries/frameworks; those programs need that anyway
400 * for libpcap 1.1 and beyond on Linux, as, by default, it requires
401 * -lnl.
402 *
403 * Do any other UN*Xes, or desktop environments support getting a
404 * description?
405 */
406int
407add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
408    struct sockaddr *addr, size_t addr_size,
409    struct sockaddr *netmask, size_t netmask_size,
410    struct sockaddr *broadaddr, size_t broadaddr_size,
411    struct sockaddr *dstaddr, size_t dstaddr_size,
412    char *errbuf)
413{
414	pcap_if_t *curdev;
415	char *description = NULL;
416	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
417#ifdef SIOCGIFDESCR
418	int s;
419	struct ifreq ifrdesc;
420#ifndef IFDESCRSIZE
421	size_t descrlen = 64;
422#else
423	size_t descrlen = IFDESCRSIZE;
424#endif /* IFDESCRSIZE */
425#endif /* SIOCGIFDESCR */
426
427#ifdef SIOCGIFDESCR
428	/*
429	 * Get the description for the interface.
430	 */
431	memset(&ifrdesc, 0, sizeof ifrdesc);
432	strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
433	s = socket(AF_INET, SOCK_DGRAM, 0);
434	if (s >= 0) {
435#ifdef __FreeBSD__
436		/*
437		 * On FreeBSD, if the buffer isn't big enough for the
438		 * description, the ioctl succeeds, but the description
439		 * isn't copied, ifr_buffer.length is set to the description
440		 * length, and ifr_buffer.buffer is set to NULL.
441		 */
442		for (;;) {
443			free(description);
444			if ((description = malloc(descrlen)) != NULL) {
445				ifrdesc.ifr_buffer.buffer = description;
446				ifrdesc.ifr_buffer.length = descrlen;
447				if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
448					if (ifrdesc.ifr_buffer.buffer ==
449					    description)
450						break;
451					else
452						descrlen = ifrdesc.ifr_buffer.length;
453				} else {
454					/*
455					 * Failed to get interface description.
456					 */
457					free(description);
458					description = NULL;
459					break;
460				}
461			} else
462				break;
463		}
464#else /* __FreeBSD__ */
465		/*
466		 * The only other OS that currently supports
467		 * SIOCGIFDESCR is OpenBSD, and it has no way
468		 * to get the description length - it's clamped
469		 * to a maximum of IFDESCRSIZE.
470		 */
471		if ((description = malloc(descrlen)) != NULL) {
472			ifrdesc.ifr_data = (caddr_t)description;
473			if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
474				/*
475				 * Failed to get interface description.
476				 */
477				free(description);
478				description = NULL;
479			}
480		}
481#endif /* __FreeBSD__ */
482		close(s);
483		if (description != NULL && strlen(description) == 0) {
484			free(description);
485			description = NULL;
486		}
487	}
488#endif /* SIOCGIFDESCR */
489
490	if (add_or_find_if(&curdev, alldevs, name, flags, description,
491	    errbuf) == -1) {
492		free(description);
493		/*
494		 * Error - give up.
495		 */
496		return (-1);
497	}
498	free(description);
499	if (curdev == NULL) {
500		/*
501		 * Device wasn't added because it can't be opened.
502		 * Not a fatal error.
503		 */
504		return (0);
505	}
506
507	/*
508	 * "curdev" is an entry for this interface; add an entry for this
509	 * address to its list of addresses.
510	 *
511	 * Allocate the new entry and fill it in.
512	 */
513	curaddr = malloc(sizeof(pcap_addr_t));
514	if (curaddr == NULL) {
515		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
516		    "malloc: %s", pcap_strerror(errno));
517		return (-1);
518	}
519
520	curaddr->next = NULL;
521	if (addr != NULL) {
522		curaddr->addr = dup_sockaddr(addr, addr_size);
523		if (curaddr->addr == NULL) {
524			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
525			    "malloc: %s", pcap_strerror(errno));
526			free(curaddr);
527			return (-1);
528		}
529	} else
530		curaddr->addr = NULL;
531
532	if (netmask != NULL) {
533		curaddr->netmask = dup_sockaddr(netmask, netmask_size);
534		if (curaddr->netmask == NULL) {
535			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
536			    "malloc: %s", pcap_strerror(errno));
537			if (curaddr->addr != NULL)
538				free(curaddr->addr);
539			free(curaddr);
540			return (-1);
541		}
542	} else
543		curaddr->netmask = NULL;
544
545	if (broadaddr != NULL) {
546		curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
547		if (curaddr->broadaddr == NULL) {
548			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
549			    "malloc: %s", pcap_strerror(errno));
550			if (curaddr->netmask != NULL)
551				free(curaddr->netmask);
552			if (curaddr->addr != NULL)
553				free(curaddr->addr);
554			free(curaddr);
555			return (-1);
556		}
557	} else
558		curaddr->broadaddr = NULL;
559
560	if (dstaddr != NULL) {
561		curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
562		if (curaddr->dstaddr == NULL) {
563			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
564			    "malloc: %s", pcap_strerror(errno));
565			if (curaddr->broadaddr != NULL)
566				free(curaddr->broadaddr);
567			if (curaddr->netmask != NULL)
568				free(curaddr->netmask);
569			if (curaddr->addr != NULL)
570				free(curaddr->addr);
571			free(curaddr);
572			return (-1);
573		}
574	} else
575		curaddr->dstaddr = NULL;
576
577	/*
578	 * Find the end of the list of addresses.
579	 */
580	for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
581		nextaddr = prevaddr->next;
582		if (nextaddr == NULL) {
583			/*
584			 * This is the end of the list.
585			 */
586			break;
587		}
588	}
589
590	if (prevaddr == NULL) {
591		/*
592		 * The list was empty; this is the first member.
593		 */
594		curdev->addresses = curaddr;
595	} else {
596		/*
597		 * "prevaddr" is the last member of the list; append
598		 * this member to it.
599		 */
600		prevaddr->next = curaddr;
601	}
602
603	return (0);
604}
605
606int
607pcap_add_if(pcap_if_t **devlist, const char *name, u_int flags,
608    const char *description, char *errbuf)
609{
610	pcap_if_t *curdev;
611
612	return (add_or_find_if(&curdev, devlist, name, flags, description,
613	    errbuf));
614}
615
616
617/*
618 * Free a list of interfaces.
619 */
620void
621pcap_freealldevs(pcap_if_t *alldevs)
622{
623	pcap_if_t *curdev, *nextdev;
624	pcap_addr_t *curaddr, *nextaddr;
625
626	for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
627		nextdev = curdev->next;
628
629		/*
630		 * Free all addresses.
631		 */
632		for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
633			nextaddr = curaddr->next;
634			if (curaddr->addr)
635				free(curaddr->addr);
636			if (curaddr->netmask)
637				free(curaddr->netmask);
638			if (curaddr->broadaddr)
639				free(curaddr->broadaddr);
640			if (curaddr->dstaddr)
641				free(curaddr->dstaddr);
642			free(curaddr);
643		}
644
645		/*
646		 * Free the name string.
647		 */
648		free(curdev->name);
649
650		/*
651		 * Free the description string, if any.
652		 */
653		if (curdev->description != NULL)
654			free(curdev->description);
655
656		/*
657		 * Free the interface.
658		 */
659		free(curdev);
660	}
661}
662
663#if !defined(WIN32) && !defined(MSDOS)
664
665/*
666 * Return the name of a network interface attached to the system, or NULL
667 * if none can be found.  The interface must be configured up; the
668 * lowest unit number is preferred; loopback is ignored.
669 */
670char *
671pcap_lookupdev(errbuf)
672	register char *errbuf;
673{
674	pcap_if_t *alldevs;
675/* for old BSD systems, including bsdi3 */
676#ifndef IF_NAMESIZE
677#define IF_NAMESIZE IFNAMSIZ
678#endif
679	static char device[IF_NAMESIZE + 1];
680	char *ret;
681
682	if (pcap_findalldevs(&alldevs, errbuf) == -1)
683		return (NULL);
684
685	if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
686		/*
687		 * There are no devices on the list, or the first device
688		 * on the list is a loopback device, which means there
689		 * are no non-loopback devices on the list.  This means
690		 * we can't return any device.
691		 *
692		 * XXX - why not return a loopback device?  If we can't
693		 * capture on it, it won't be on the list, and if it's
694		 * on the list, there aren't any non-loopback devices,
695		 * so why not just supply it as the default device?
696		 */
697		(void)strlcpy(errbuf, "no suitable device found",
698		    PCAP_ERRBUF_SIZE);
699		ret = NULL;
700	} else {
701		/*
702		 * Return the name of the first device on the list.
703		 */
704		(void)strlcpy(device, alldevs->name, sizeof(device));
705		ret = device;
706	}
707
708	pcap_freealldevs(alldevs);
709	return (ret);
710}
711
712int
713pcap_lookupnet(device, netp, maskp, errbuf)
714	register const char *device;
715	register bpf_u_int32 *netp, *maskp;
716	register char *errbuf;
717{
718	register int fd;
719	register struct sockaddr_in *sin4;
720	struct ifreq ifr;
721
722	/*
723	 * The pseudo-device "any" listens on all interfaces and therefore
724	 * has the network address and -mask "0.0.0.0" therefore catching
725	 * all traffic. Using NULL for the interface is the same as "any".
726	 */
727	if (!device || strcmp(device, "any") == 0
728#ifdef HAVE_DAG_API
729	    || strstr(device, "dag") != NULL
730#endif
731#ifdef HAVE_SEPTEL_API
732	    || strstr(device, "septel") != NULL
733#endif
734#ifdef PCAP_SUPPORT_BT
735	    || strstr(device, "bluetooth") != NULL
736#endif
737#ifdef PCAP_SUPPORT_USB
738	    || strstr(device, "usbmon") != NULL
739#endif
740#ifdef HAVE_SNF_API
741	    || strstr(device, "snf") != NULL
742#endif
743	    ) {
744		*netp = *maskp = 0;
745		return 0;
746	}
747
748	fd = socket(AF_INET, SOCK_DGRAM, 0);
749	if (fd < 0) {
750		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
751		    pcap_strerror(errno));
752		return (-1);
753	}
754	memset(&ifr, 0, sizeof(ifr));
755#ifdef linux
756	/* XXX Work around Linux kernel bug */
757	ifr.ifr_addr.sa_family = AF_INET;
758#endif
759	(void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
760	if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
761		if (errno == EADDRNOTAVAIL) {
762			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
763			    "%s: no IPv4 address assigned", device);
764		} else {
765			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
766			    "SIOCGIFADDR: %s: %s",
767			    device, pcap_strerror(errno));
768		}
769		(void)close(fd);
770		return (-1);
771	}
772	sin4 = (struct sockaddr_in *)&ifr.ifr_addr;
773	*netp = sin4->sin_addr.s_addr;
774	memset(&ifr, 0, sizeof(ifr));
775#ifdef linux
776	/* XXX Work around Linux kernel bug */
777	ifr.ifr_addr.sa_family = AF_INET;
778#endif
779	(void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
780	if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
781		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
782		    "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
783		(void)close(fd);
784		return (-1);
785	}
786	(void)close(fd);
787	*maskp = sin4->sin_addr.s_addr;
788	if (*maskp == 0) {
789		if (IN_CLASSA(*netp))
790			*maskp = IN_CLASSA_NET;
791		else if (IN_CLASSB(*netp))
792			*maskp = IN_CLASSB_NET;
793		else if (IN_CLASSC(*netp))
794			*maskp = IN_CLASSC_NET;
795		else {
796			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
797			    "inet class for 0x%x unknown", *netp);
798			return (-1);
799		}
800	}
801	*netp &= *maskp;
802	return (0);
803}
804
805#elif defined(WIN32)
806
807/*
808 * Return the name of a network interface attached to the system, or NULL
809 * if none can be found.  The interface must be configured up; the
810 * lowest unit number is preferred; loopback is ignored.
811 */
812char *
813pcap_lookupdev(errbuf)
814	register char *errbuf;
815{
816	DWORD dwVersion;
817	DWORD dwWindowsMajorVersion;
818	dwVersion = GetVersion();	/* get the OS version */
819	dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
820
821	if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
822		/*
823		 * Windows 95, 98, ME.
824		 */
825		ULONG NameLength = 8192;
826		static char AdaptersName[8192];
827
828		if (PacketGetAdapterNames(AdaptersName,&NameLength) )
829			return (AdaptersName);
830		else
831			return NULL;
832	} else {
833		/*
834		 * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility
835		 */
836		ULONG NameLength = 8192;
837		static WCHAR AdaptersName[8192];
838		char *tAstr;
839		WCHAR *tUstr;
840		WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR));
841		int NAdapts = 0;
842
843		if(TAdaptersName == NULL)
844		{
845			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
846			return NULL;
847		}
848
849		if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
850		{
851			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
852				"PacketGetAdapterNames: %s",
853				pcap_win32strerror());
854			free(TAdaptersName);
855			return NULL;
856		}
857
858
859		tAstr = (char*)TAdaptersName;
860		tUstr = (WCHAR*)AdaptersName;
861
862		/*
863		 * Convert and copy the device names
864		 */
865		while(sscanf(tAstr, "%S", tUstr) > 0)
866		{
867			tAstr += strlen(tAstr) + 1;
868			tUstr += wcslen(tUstr) + 1;
869			NAdapts ++;
870		}
871
872		tAstr++;
873		*tUstr = 0;
874		tUstr++;
875
876		/*
877		 * Copy the descriptions
878		 */
879		while(NAdapts--)
880		{
881			char* tmp = (char*)tUstr;
882			strcpy(tmp, tAstr);
883			tmp += strlen(tAstr) + 1;
884			tUstr = (WCHAR*)tmp;
885			tAstr += strlen(tAstr) + 1;
886		}
887
888		free(TAdaptersName);
889		return (char *)(AdaptersName);
890	}
891}
892
893
894int
895pcap_lookupnet(device, netp, maskp, errbuf)
896	register const char *device;
897	register bpf_u_int32 *netp, *maskp;
898	register char *errbuf;
899{
900	/*
901	 * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo()
902	 * in order to skip non IPv4 (i.e. IPv6 addresses)
903	 */
904	npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
905	LONG if_addr_size = 1;
906	struct sockaddr_in *t_addr;
907	unsigned int i;
908
909	if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
910		*netp = *maskp = 0;
911		return (0);
912	}
913
914	for(i=0; i<MAX_NETWORK_ADDRESSES; i++)
915	{
916		if(if_addrs[i].IPAddress.ss_family == AF_INET)
917		{
918			t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress);
919			*netp = t_addr->sin_addr.S_un.S_addr;
920			t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask);
921			*maskp = t_addr->sin_addr.S_un.S_addr;
922
923			*netp &= *maskp;
924			return (0);
925		}
926
927	}
928
929	*netp = *maskp = 0;
930	return (0);
931}
932
933#endif /* !WIN32 && !MSDOS */
934