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