• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
36 static 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 
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 struct sockaddr *
dup_sockaddr(struct sockaddr * sa,size_t sa_length)94 dup_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 
103 static int
get_instance(const char * name)104 get_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 
129 int
add_or_find_if(pcap_if_t ** curdev_ret,pcap_if_t ** alldevs,const char * name,u_int flags,const char * description,char * errbuf)130 add_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  */
406 int
add_addr_to_iflist(pcap_if_t ** alldevs,const char * name,u_int flags,struct sockaddr * addr,size_t addr_size,struct sockaddr * netmask,size_t netmask_size,struct sockaddr * broadaddr,size_t broadaddr_size,struct sockaddr * dstaddr,size_t dstaddr_size,char * errbuf)407 add_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 
606 int
pcap_add_if(pcap_if_t ** devlist,const char * name,u_int flags,const char * description,char * errbuf)607 pcap_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  */
620 void
pcap_freealldevs(pcap_if_t * alldevs)621 pcap_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  */
670 char *
pcap_lookupdev(errbuf)671 pcap_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 
712 int
pcap_lookupnet(device,netp,maskp,errbuf)713 pcap_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  */
812 char *
pcap_lookupdev(errbuf)813 pcap_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 
894 int
pcap_lookupnet(device,netp,maskp,errbuf)895 pcap_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