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