]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libpcap/inet.c
This commit was generated by cvs2svn to compensate for changes in r100490,
[FreeBSD/FreeBSD.git] / contrib / 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 #ifndef lint
36 static const char rcsid[] =
37     "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.45 2001/10/28 20:40:43 guy Exp $ (LBL)";
38 #endif
39
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43
44 #include <sys/param.h>
45 #include <sys/file.h>
46 #include <sys/ioctl.h>
47 #include <sys/socket.h>
48 #ifdef HAVE_SYS_SOCKIO_H
49 #include <sys/sockio.h>
50 #endif
51 #include <sys/time.h>                           /* concession to AIX */
52
53 struct mbuf;
54 struct rtentry;
55 #include <net/if.h>
56 #include <netinet/in.h>
57
58 #include <ctype.h>
59 #include <errno.h>
60 #include <memory.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <unistd.h>
65 #ifdef HAVE_LIMITS_H
66 #include <limits.h>
67 #else
68 #define INT_MAX         2147483647
69 #endif
70 #ifdef HAVE_IFADDRS_H
71 #include <ifaddrs.h>
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 /*
89  * This is fun.
90  *
91  * In older BSD systems, socket addresses were fixed-length, and
92  * "sizeof (struct sockaddr)" gave the size of the structure.
93  * All addresses fit within a "struct sockaddr".
94  *
95  * In newer BSD systems, the socket address is variable-length, and
96  * there's an "sa_len" field giving the length of the structure;
97  * this allows socket addresses to be longer than 2 bytes of family
98  * and 14 bytes of data.
99  *
100  * Some commercial UNIXes use the old BSD scheme, and some might use
101  * the new BSD scheme.
102  *
103  * GNU libc uses neither scheme, but has an "SA_LEN()" macro that
104  * determines the size based on the address family.
105  */
106 #ifndef SA_LEN
107 #ifdef HAVE_SOCKADDR_SA_LEN
108 #define SA_LEN(addr)    ((addr)->sa_len)
109 #else /* HAVE_SOCKADDR_SA_LEN */
110 #define SA_LEN(addr)    (sizeof (struct sockaddr))
111 #endif /* HAVE_SOCKADDR_SA_LEN */
112 #endif /* SA_LEN */
113
114 /*
115  * Description string for the "any" device.
116  */
117 static const char any_descr[] = "Pseudo-device that captures on all interfaces";
118
119 static struct sockaddr *
120 dup_sockaddr(struct sockaddr *sa)
121 {
122         struct sockaddr *newsa;
123         unsigned int size;
124         
125         size = SA_LEN(sa);
126         if ((newsa = malloc(size)) == NULL)
127                 return (NULL);
128         return (memcpy(newsa, sa, size));
129 }
130
131 static int
132 get_instance(char *name)
133 {
134         char *cp, *endcp;
135         int n;
136
137         if (strcmp(name, "any") == 0) {
138                 /*
139                  * Give the "any" device an artificially high instance
140                  * number, so it shows up after all other non-loopback
141                  * interfaces.
142                  */
143                 return INT_MAX;
144         }
145
146         endcp = name + strlen(name);
147         for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp)
148                 continue;
149
150         if (isdigit((unsigned char)*cp))
151                 n = atoi(cp);
152         else
153                 n = 0;
154         return (n);
155 }
156
157 static int
158 add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, char *name,
159     u_int flags, const char *description, char *errbuf)
160 {
161         pcap_t *p;
162         pcap_if_t *curdev, *prevdev, *nextdev;
163         int this_instance;
164
165         /*
166          * Can we open this interface for live capture?
167          */
168         p = pcap_open_live(name, 68, 0, 0, errbuf);
169         if (p == NULL) {
170                 /*
171                  * No.  Don't bother including it.
172                  * Don't treat this as an error, though.
173                  */
174                 *curdev_ret = NULL;
175                 return (0);
176         }
177         pcap_close(p);
178
179         /*
180          * Is there already an entry in the list for this interface?
181          */
182         for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
183                 if (strcmp(name, curdev->name) == 0)
184                         break;  /* yes, we found it */
185         }
186         if (curdev == NULL) {
187                 /*
188                  * No, we didn't find it.
189                  * Allocate a new entry.
190                  */
191                 curdev = malloc(sizeof(pcap_if_t));
192                 if (curdev == NULL) {
193                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
194                             "malloc: %s", pcap_strerror(errno));
195                         return (-1);
196                 }
197                 
198                 /*
199                  * Fill in the entry.
200                  */
201                 curdev->next = NULL;
202                 curdev->name = malloc(strlen(name) + 1);
203                 strcpy(curdev->name, name);
204                 if (description != NULL) {
205                         /*
206                          * We have a description for this interface.
207                          */
208                         curdev->description = malloc(strlen(description) + 1);
209                         strcpy(curdev->description, description);
210                 } else {
211                         /*
212                          * We don't.
213                          */
214                         curdev->description = NULL;
215                 }
216                 curdev->addresses = NULL;       /* list starts out as empty */
217                 curdev->flags = 0;
218                 if (ISLOOPBACK(name, flags))
219                         curdev->flags |= PCAP_IF_LOOPBACK;
220
221                 /*
222                  * Add it to the list, in the appropriate location.
223                  * First, get the instance number of this interface.
224                  */
225                 this_instance = get_instance(name);
226
227                 /*
228                  * Now look for the last interface with an instance number
229                  * less than or equal to the new interface's instance
230                  * number - except that non-loopback interfaces are
231                  * arbitrarily treated as having interface numbers less
232                  * than those of loopback interfaces, so the loopback
233                  * interfaces are put at the end of the list.
234                  *
235                  * We start with "prevdev" being NULL, meaning we're before
236                  * the first element in the list.
237                  */
238                 prevdev = NULL;
239                 for (;;) {
240                         /*
241                          * Get the interface after this one.
242                          */
243                         if (prevdev == NULL) {
244                                 /*
245                                  * The next element is the first element.
246                                  */
247                                 nextdev = *alldevs;
248                         } else
249                                 nextdev = prevdev->next;
250
251                         /*
252                          * Are we at the end of the list?
253                          */
254                         if (nextdev == NULL) {
255                                 /*
256                                  * Yes - we have to put the new entry
257                                  * after "prevdev".
258                                  */
259                                 break;
260                         }
261
262                         /*
263                          * Is the new interface a non-loopback interface
264                          * and the next interface a loopback interface?
265                          */
266                         if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
267                             (nextdev->flags & PCAP_IF_LOOPBACK)) {
268                                 /*
269                                  * Yes, we should put the new entry
270                                  * before "nextdev", i.e. after "prevdev".
271                                  */
272                                 break;
273                         }
274
275                         /*
276                          * Is the new interface's instance number less
277                          * than the next interface's instance number,
278                          * and is it the case that the new interface is a
279                          * non-loopback interface or the next interface is
280                          * a loopback interface?
281                          *
282                          * (The goal of both loopback tests is to make
283                          * sure that we never put a loopback interface
284                          * before any non-loopback interface and that we
285                          * always put a non-loopback interface before all
286                          * loopback interfaces.)
287                          */
288                         if (this_instance < get_instance(nextdev->name) &&
289                             (!(curdev->flags & PCAP_IF_LOOPBACK) ||
290                                (nextdev->flags & PCAP_IF_LOOPBACK))) {
291                                 /*
292                                  * Yes - we should put the new entry
293                                  * before "nextdev", i.e. after "prevdev".
294                                  */
295                                 break;
296                         }
297
298                         prevdev = nextdev;
299                 }
300
301                 /*
302                  * Insert before "nextdev".
303                  */
304                 curdev->next = nextdev;
305
306                 /*
307                  * Insert after "prevdev" - unless "prevdev" is null,
308                  * in which case this is the first interface.
309                  */
310                 if (prevdev == NULL) {
311                         /*
312                          * This is the first interface.  Pass back a
313                          * pointer to it, and put "curdev" before
314                          * "nextdev".
315                          */
316                         *alldevs = curdev;
317                 } else
318                         prevdev->next = curdev;
319         }
320         
321         *curdev_ret = curdev;
322         return (0);
323 }
324
325 static int
326 add_addr_to_iflist(pcap_if_t **alldevs, char *name, u_int flags,
327     struct sockaddr *addr, struct sockaddr *netmask,
328     struct sockaddr *broadaddr, struct sockaddr *dstaddr, char *errbuf)
329 {
330         pcap_if_t *curdev;
331         pcap_addr_t *curaddr, *prevaddr, *nextaddr;
332
333         if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
334                 /*
335                  * Error - give up.
336                  */
337                 return (-1);
338         }
339         if (curdev == NULL) {
340                 /*
341                  * Device wasn't added because it can't be opened.
342                  * Not a fatal error.
343                  */
344                 return (0);
345         }
346
347         /*
348          * "curdev" is an entry for this interface; add an entry for this
349          * address to its list of addresses.
350          *
351          * Allocate the new entry and fill it in.
352          */
353         curaddr = malloc(sizeof(pcap_addr_t));
354         if (curaddr == NULL) {
355                 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
356                     "malloc: %s", pcap_strerror(errno));
357                 return (-1);
358         }
359
360         curaddr->next = NULL;
361         if (addr != NULL) {
362                 curaddr->addr = dup_sockaddr(addr);
363                 if (curaddr->addr == NULL) {
364                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
365                             "malloc: %s", pcap_strerror(errno));
366                         free(curaddr);
367                         return (-1);
368                 }
369         } else
370                 curaddr->addr = NULL;
371
372         if (netmask != NULL) {
373                 curaddr->netmask = dup_sockaddr(netmask);
374                 if (curaddr->netmask == NULL) {
375                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
376                             "malloc: %s", pcap_strerror(errno));
377                         free(curaddr);
378                         return (-1);
379                 }
380         } else
381                 curaddr->netmask = NULL;
382                 
383         if (broadaddr != NULL) {
384                 curaddr->broadaddr = dup_sockaddr(broadaddr);
385                 if (curaddr->broadaddr == NULL) {
386                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
387                             "malloc: %s", pcap_strerror(errno));
388                         free(curaddr);
389                         return (-1);
390                 }
391         } else
392                 curaddr->broadaddr = NULL;
393                 
394         if (dstaddr != NULL) {
395                 curaddr->dstaddr = dup_sockaddr(dstaddr);
396                 if (curaddr->dstaddr == NULL) {
397                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
398                             "malloc: %s", pcap_strerror(errno));
399                         free(curaddr);
400                         return (-1);
401                 }
402         } else
403                 curaddr->dstaddr = NULL;
404                 
405         /*
406          * Find the end of the list of addresses.
407          */
408         for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
409                 nextaddr = prevaddr->next;
410                 if (nextaddr == NULL) {
411                         /*
412                          * This is the end of the list.
413                          */
414                         break;
415                 }
416         }
417
418         if (prevaddr == NULL) {
419                 /*
420                  * The list was empty; this is the first member.
421                  */
422                 curdev->addresses = curaddr;
423         } else {
424                 /*
425                  * "prevaddr" is the last member of the list; append
426                  * this member to it.
427                  */
428                 prevaddr->next = curaddr;
429         }
430
431         return (0);
432 }
433
434 static int
435 pcap_add_if(pcap_if_t **devlist, char *name, u_int flags,
436     const char *description, char *errbuf)
437 {
438         pcap_if_t *curdev;
439
440         return (add_or_find_if(&curdev, devlist, name, flags, description,
441             errbuf));
442 }
443
444 /*
445  * Get a list of all interfaces that are up and that we can open.
446  * Returns -1 on error, 0 otherwise.
447  * The list, as returned through "alldevsp", may be null if no interfaces
448  * were up and could be opened.
449  */
450 #ifdef HAVE_IFADDRS_H
451 int
452 pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
453 {
454         pcap_if_t *devlist = NULL;
455         struct ifaddrs *ifap, *ifa;
456         struct sockaddr *broadaddr, *dstaddr;
457         int ret = 0;
458
459         /*
460          * Get the list of interface addresses.
461          *
462          * Note: this won't return information about interfaces
463          * with no addresses; are there any such interfaces
464          * that would be capable of receiving packets?
465          * (Interfaces incapable of receiving packets aren't
466          * very interesting from libpcap's point of view.)
467          *
468          * LAN interfaces will probably have link-layer
469          * addresses; I don't know whether all implementations
470          * of "getifaddrs()" now, or in the future, will return
471          * those.
472          */
473         if (getifaddrs(&ifap) != 0) {
474                 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
475                     "getifaddrs: %s", pcap_strerror(errno));
476                 return (-1);
477         }
478         for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
479                 /*
480                  * Is this interface up?
481                  */
482                 if (!(ifa->ifa_flags & IFF_UP)) {
483                         /*
484                          * No, so don't add it to the list.
485                          */
486                         continue;
487                 }
488
489                 /*
490                  * "ifa_broadaddr" may be non-null even on
491                  * non-broadcast interfaces; "ifa_dstaddr"
492                  * was, on at least one FreeBSD 4.1 system,
493                  * non-null on a non-point-to-point
494                  * interface.
495                  */
496                 if (ifa->ifa_flags & IFF_BROADCAST)
497                         broadaddr = ifa->ifa_broadaddr;
498                 else
499                         broadaddr = NULL;
500                 if (ifa->ifa_flags & IFF_POINTOPOINT)
501                         dstaddr = ifa->ifa_dstaddr;
502                 else
503                         dstaddr = NULL;
504
505                 /*
506                  * Add information for this address to the list.
507                  */
508                 if (add_addr_to_iflist(&devlist, ifa->ifa_name,
509                     ifa->ifa_flags, ifa->ifa_addr, ifa->ifa_netmask,
510                     broadaddr, dstaddr, errbuf) < 0) {
511                         ret = -1;
512                         break;
513                 }
514         }
515
516         freeifaddrs(ifap);
517
518         if (ret != -1) {
519                 /*
520                  * We haven't had any errors yet; add the "any" device,
521                  * if we can open it.
522                  */
523                 if (pcap_add_if(&devlist, "any", 0, any_descr, errbuf) < 0)
524                         ret = -1;
525         }
526
527         if (ret == -1) {
528                 /*
529                  * We had an error; free the list we've been constructing.
530                  */
531                 if (devlist != NULL) {
532                         pcap_freealldevs(devlist);
533                         devlist = NULL;
534                 }
535         }
536
537         *alldevsp = devlist;
538         return (ret);
539 }
540 #else /* HAVE_IFADDRS_H */
541 #ifdef HAVE_PROC_NET_DEV
542 /*
543  * Get from "/proc/net/dev" all interfaces listed there; if they're
544  * already in the list of interfaces we have, that won't add another
545  * instance, but if they're not, that'll add them.
546  *
547  * We don't bother getting any addresses for them; it appears you can't
548  * use SIOCGIFADDR on Linux to get IPv6 addresses for interfaces, and,
549  * although some other types of addresses can be fetched with SIOCGIFADDR,
550  * we don't bother with them for now.
551  *
552  * We also don't fail if we couldn't open "/proc/net/dev"; we just leave
553  * the list of interfaces as is.
554  */
555 static int
556 scan_proc_net_dev(pcap_if_t **devlistp, int fd, char *errbuf)
557 {
558         FILE *proc_net_f;
559         char linebuf[512];
560         int linenum;
561         unsigned char *p;
562         char name[512]; /* XXX - pick a size */
563         char *q, *saveq;
564         struct ifreq ifrflags;
565         int ret = 0;
566
567         proc_net_f = fopen("/proc/net/dev", "r");
568         if (proc_net_f == NULL)
569                 return (0);
570
571         for (linenum = 1;
572             fgets(linebuf, sizeof linebuf, proc_net_f) != NULL; linenum++) {
573                 /*
574                  * Skip the first two lines - they're headers.
575                  */
576                 if (linenum <= 2)
577                         continue;
578
579                 p = &linebuf[0];
580
581                 /*
582                  * Skip leading white space.
583                  */
584                 while (*p != '\0' && isspace(*p))
585                         p++;
586                 if (*p == '\0' || *p == '\n')
587                         continue;       /* blank line */
588
589                 /*
590                  * Get the interface name.
591                  */
592                 q = &name[0];
593                 while (*p != '\0' && !isspace(*p)) {
594                         if (*p == ':') {
595                                 /*
596                                  * This could be the separator between a
597                                  * name and an alias number, or it could be
598                                  * the separator between a name with no 
599                                  * alias number and the next field.
600                                  *
601                                  * If there's a colon after digits, it
602                                  * separates the name and the alias number,
603                                  * otherwise it separates the name and the
604                                  * next field.
605                                  */
606                                 saveq = q;
607                                 while (isdigit(*p))
608                                         *q++ = *p++;
609                                 if (*p != ':') {
610                                         /*
611                                          * That was the next field,
612                                          * not the alias number.
613                                          */
614                                         q = saveq;
615                                 }
616                                 break;
617                         } else
618                                 *q++ = *p++;
619                 }
620                 *q = '\0';
621
622                 /*
623                  * Get the flags for this interface, and skip it if
624                  * it's not up.
625                  */
626                 strncpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name));
627                 if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
628                         if (errno == ENXIO)
629                                 continue;
630                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
631                             "SIOCGIFFLAGS: %.*s: %s",
632                             (int)sizeof(ifrflags.ifr_name),
633                             ifrflags.ifr_name,
634                             pcap_strerror(errno));
635                         ret = -1;
636                         break;
637                 }
638                 if (!(ifrflags.ifr_flags & IFF_UP))
639                         continue;
640
641                 /*
642                  * Add an entry for this interface, with no addresses.
643                  */
644                 if (pcap_add_if(devlistp, name, ifrflags.ifr_flags, NULL,
645                     errbuf) == -1) {
646                         /*
647                          * Failure.
648                          */
649                         ret = -1;
650                         break;
651                 }
652         }
653         if (ret != -1) {
654                 /*
655                  * Well, we didn't fail for any other reason; did we
656                  * fail due to an error reading the file?
657                  */
658                 if (ferror(proc_net_f)) {
659                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
660                             "Error reading /proc/net/dev: %s",
661                             pcap_strerror(errno));
662                         ret = -1;
663                 }
664         }
665
666         (void)fclose(proc_net_f);
667         return (ret);
668 }
669 #endif /* HAVE_PROC_NET_DEV */
670
671 int
672 pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
673 {
674         pcap_if_t *devlist = NULL;
675         register int fd;
676         register struct ifreq *ifrp, *ifend, *ifnext;
677         int n;
678         struct ifconf ifc;
679         char *buf = NULL;
680         unsigned buf_size;
681         struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr;
682         struct sockaddr *netmask, *broadaddr, *dstaddr;
683         int ret = 0;
684
685         /*
686          * Create a socket from which to fetch the list of interfaces.
687          */
688         fd = socket(AF_INET, SOCK_DGRAM, 0);
689         if (fd < 0) {
690                 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
691                     "socket: %s", pcap_strerror(errno));
692                 return (-1);
693         }
694
695         /*
696          * Start with an 8K buffer, and keep growing the buffer until
697          * we get the entire interface list or fail to get it for some
698          * reason other than EINVAL (which is presumed here to mean
699          * "buffer is too small").
700          */
701         buf_size = 8192;
702         for (;;) {
703                 buf = malloc(buf_size);
704                 if (buf == NULL) {
705                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
706                             "malloc: %s", pcap_strerror(errno));
707                         (void)close(fd);
708                         return (-1);
709                 }
710
711                 ifc.ifc_len = buf_size;
712                 ifc.ifc_buf = buf;
713                 memset(buf, 0, buf_size);
714                 if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0
715                     && errno != EINVAL) {
716                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
717                             "SIOCGIFCONF: %s", pcap_strerror(errno));
718                         (void)close(fd);
719                         free(buf);
720                         return (-1);
721                 }
722                 if (ifc.ifc_len < buf_size)
723                         break;
724                 free(buf);
725                 buf_size *= 2;
726         }
727
728         ifrp = (struct ifreq *)buf;
729         ifend = (struct ifreq *)(buf + ifc.ifc_len);
730
731         for (; ifrp < ifend; ifrp = ifnext) {
732                 n = SA_LEN(&ifrp->ifr_addr) + sizeof(ifrp->ifr_name);
733                 if (n < sizeof(*ifrp))
734                         ifnext = ifrp + 1;
735                 else
736                         ifnext = (struct ifreq *)((char *)ifrp + n);
737
738                 /*
739                  * Get the flags for this interface, and skip it if it's
740                  * not up.
741                  */
742                 strncpy(ifrflags.ifr_name, ifrp->ifr_name,
743                     sizeof(ifrflags.ifr_name));
744                 if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
745                         if (errno == ENXIO)
746                                 continue;
747                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
748                             "SIOCGIFFLAGS: %.*s: %s",
749                             (int)sizeof(ifrflags.ifr_name),
750                             ifrflags.ifr_name,
751                             pcap_strerror(errno));
752                         ret = -1;
753                         break;
754                 }
755                 if (!(ifrflags.ifr_flags & IFF_UP))
756                         continue;
757
758                 /*
759                  * Get the netmask for this address on this interface.
760                  */
761                 strncpy(ifrnetmask.ifr_name, ifrp->ifr_name,
762                     sizeof(ifrnetmask.ifr_name));
763                 memcpy(&ifrnetmask.ifr_addr, &ifrp->ifr_addr,
764                     sizeof(ifrnetmask.ifr_addr));
765                 if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifrnetmask) < 0) {
766                         if (errno == EADDRNOTAVAIL) {
767                                 /*
768                                  * Not available.
769                                  */
770                                 netmask = NULL;
771                         } else {
772                                 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
773                                     "SIOCGIFNETMASK: %.*s: %s",
774                                     (int)sizeof(ifrnetmask.ifr_name),
775                                     ifrnetmask.ifr_name,
776                                     pcap_strerror(errno));
777                                 ret = -1;
778                                 break;
779                         }
780                 } else
781                         netmask = &ifrnetmask.ifr_addr;
782
783                 /*
784                  * Get the broadcast address for this address on this
785                  * interface (if any).
786                  */
787                 if (ifrflags.ifr_flags & IFF_BROADCAST) {
788                         strncpy(ifrbroadaddr.ifr_name, ifrp->ifr_name,
789                             sizeof(ifrbroadaddr.ifr_name));
790                         memcpy(&ifrbroadaddr.ifr_addr, &ifrp->ifr_addr,
791                             sizeof(ifrbroadaddr.ifr_addr));
792                         if (ioctl(fd, SIOCGIFBRDADDR,
793                             (char *)&ifrbroadaddr) < 0) {
794                                 if (errno == EADDRNOTAVAIL) {
795                                         /*
796                                          * Not available.
797                                          */
798                                         broadaddr = NULL;
799                                 } else {
800                                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
801                                             "SIOCGIFBRDADDR: %.*s: %s",
802                                             (int)sizeof(ifrbroadaddr.ifr_name),
803                                             ifrbroadaddr.ifr_name,
804                                             pcap_strerror(errno));
805                                         ret = -1;
806                                         break;
807                                 }
808                         } else
809                                 broadaddr = &ifrbroadaddr.ifr_broadaddr;
810                 } else {
811                         /*
812                          * Not a broadcast interface, so no broadcast
813                          * address.
814                          */
815                         broadaddr = NULL;
816                 }
817
818                 /*
819                  * Get the destination address for this address on this
820                  * interface (if any).
821                  */
822                 if (ifrflags.ifr_flags & IFF_POINTOPOINT) {
823                         strncpy(ifrdstaddr.ifr_name, ifrp->ifr_name,
824                             sizeof(ifrdstaddr.ifr_name));
825                         memcpy(&ifrdstaddr.ifr_addr, &ifrp->ifr_addr,
826                             sizeof(ifrdstaddr.ifr_addr));
827                         if (ioctl(fd, SIOCGIFDSTADDR,
828                             (char *)&ifrdstaddr) < 0) {
829                                 if (errno == EADDRNOTAVAIL) {
830                                         /*
831                                          * Not available.
832                                          */
833                                         dstaddr = NULL;
834                                 } else {
835                                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
836                                             "SIOCGIFDSTADDR: %.*s: %s",
837                                             (int)sizeof(ifrdstaddr.ifr_name),
838                                             ifrdstaddr.ifr_name,
839                                             pcap_strerror(errno));
840                                         ret = -1;
841                                         break;
842                                 }
843                         } else
844                                 dstaddr = &ifrdstaddr.ifr_dstaddr;
845                 } else
846                         dstaddr = NULL;
847
848                 /*
849                  * Add information for this address to the list.
850                  */
851                 if (add_addr_to_iflist(&devlist, ifrp->ifr_name,
852                     ifrflags.ifr_flags, &ifrp->ifr_addr,
853                     netmask, broadaddr, dstaddr, errbuf) < 0) {
854                         ret = -1;
855                         break;
856                 }
857         }
858         free(buf);
859
860 #ifdef HAVE_PROC_NET_DEV
861         if (ret != -1) {
862                 /*
863                  * We haven't had any errors yet; now read "/proc/net/dev",
864                  * and add to the list of interfaces all interfaces listed
865                  * there that we don't already have, because, on Linux,
866                  * SIOCGIFCONF reports only interfaces with IPv4 addresses,
867                  * so you need to read "/proc/net/dev" to get the names of
868                  * the rest of the interfaces.
869                  */
870                 ret = scan_proc_net_dev(&devlist, fd, errbuf);
871         }
872 #endif
873         (void)close(fd);
874
875         if (ret != -1) {
876                 /*
877                  * We haven't had any errors yet; add the "any" device,
878                  * if we can open it.
879                  */
880                 if (pcap_add_if(&devlist, "any", 0, any_descr, errbuf) < 0) {
881                         /*
882                          * Oops, we had a fatal error.
883                          */
884                         ret = -1;
885                 }
886         }
887
888         if (ret == -1) {
889                 /*
890                  * We had an error; free the list we've been constructing.
891                  */
892                 if (devlist != NULL) {
893                         pcap_freealldevs(devlist);
894                         devlist = NULL;
895                 }
896         }
897
898         *alldevsp = devlist;
899         return (ret);
900 }
901 #endif /* HAVE_IFADDRS_H */
902
903 /*
904  * Free a list of interfaces.
905  */
906 void
907 pcap_freealldevs(pcap_if_t *alldevs)
908 {
909         pcap_if_t *curdev, *nextdev;
910         pcap_addr_t *curaddr, *nextaddr;
911
912         for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
913                 nextdev = curdev->next;
914
915                 /*
916                  * Free all addresses.
917                  */
918                 for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
919                         nextaddr = curaddr->next;
920                         if (curaddr->addr)
921                                 free(curaddr->addr);
922                         if (curaddr->netmask)
923                                 free(curaddr->netmask);
924                         if (curaddr->broadaddr)
925                                 free(curaddr->broadaddr);
926                         if (curaddr->dstaddr)
927                                 free(curaddr->dstaddr);
928                         free(curaddr);
929                 }
930
931                 /*
932                  * Free the name string.
933                  */
934                 free(curdev->name);
935
936                 /*
937                  * Free the description string, if any.
938                  */
939                 if (curdev->description != NULL)
940                         free(curdev->description);
941
942                 /*
943                  * Free the interface.
944                  */
945                 free(curdev);
946         }
947 }
948
949 /*
950  * Return the name of a network interface attached to the system, or NULL
951  * if none can be found.  The interface must be configured up; the
952  * lowest unit number is preferred; loopback is ignored.
953  */
954 char *
955 pcap_lookupdev(errbuf)
956         register char *errbuf;
957 {
958         pcap_if_t *alldevs;
959 /* for old BSD systems, including bsdi3 */
960 #ifndef IF_NAMESIZE
961 #define IF_NAMESIZE IFNAMSIZ
962 #endif
963         static char device[IF_NAMESIZE + 1];
964         char *ret;
965
966         if (pcap_findalldevs(&alldevs, errbuf) == -1)
967                 return (NULL);
968         
969         if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
970                 /*
971                  * There are no devices on the list, or the first device
972                  * on the list is a loopback device, which means there
973                  * are no non-loopback devices on the list.  This means
974                  * we can't return any device.
975                  *
976                  * XXX - why not return a loopback device?  If we can't
977                  * capture on it, it won't be on the list, and if it's
978                  * on the list, there aren't any non-loopback devices,
979                  * so why not just supply it as the default device?
980                  */
981                 (void)strlcpy(errbuf, "no suitable device found",
982                     PCAP_ERRBUF_SIZE);
983                 ret = NULL;
984         } else {
985                 /*
986                  * Return the name of the first device on the list.
987                  */
988                 (void)strlcpy(device, alldevs->name, sizeof(device));
989                 ret = device;
990         }
991
992         pcap_freealldevs(alldevs);
993         return (ret);
994 }
995
996 int
997 pcap_lookupnet(device, netp, maskp, errbuf)
998         register char *device;
999         register bpf_u_int32 *netp, *maskp;
1000         register char *errbuf;
1001 {
1002         register int fd;
1003         register struct sockaddr_in *sin;
1004         struct ifreq ifr;
1005
1006         /* 
1007          * The pseudo-device "any" listens on all interfaces and therefore
1008          * has the network address and -mask "0.0.0.0" therefore catching
1009          * all traffic. Using NULL for the interface is the same as "any".
1010          */
1011         if (!device || strcmp(device, "any") == 0) {
1012                 *netp = *maskp = 0;
1013                 return 0;
1014         }
1015
1016         fd = socket(AF_INET, SOCK_DGRAM, 0);
1017         if (fd < 0) {
1018                 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
1019                     pcap_strerror(errno));
1020                 return (-1);
1021         }
1022         memset(&ifr, 0, sizeof(ifr));
1023 #ifdef linux
1024         /* XXX Work around Linux kernel bug */
1025         ifr.ifr_addr.sa_family = AF_INET;
1026 #endif
1027         (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
1028         if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
1029                 if (errno == EADDRNOTAVAIL) {
1030                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
1031                             "%s: no IPv4 address assigned", device);
1032                 } else {
1033                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
1034                             "SIOCGIFADDR: %s: %s",
1035                             device, pcap_strerror(errno));
1036                 }
1037                 (void)close(fd);
1038                 return (-1);
1039         }
1040         sin = (struct sockaddr_in *)&ifr.ifr_addr;
1041         *netp = sin->sin_addr.s_addr;
1042         if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
1043                 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
1044                     "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
1045                 (void)close(fd);
1046                 return (-1);
1047         }
1048         (void)close(fd);
1049         *maskp = sin->sin_addr.s_addr;
1050         if (*maskp == 0) {
1051                 if (IN_CLASSA(*netp))
1052                         *maskp = IN_CLASSA_NET;
1053                 else if (IN_CLASSB(*netp))
1054                         *maskp = IN_CLASSB_NET;
1055                 else if (IN_CLASSC(*netp))
1056                         *maskp = IN_CLASSC_NET;
1057                 else {
1058                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
1059                             "inet class for 0x%x unknown", *netp);
1060                         return (-1);
1061                 }
1062         }
1063         *netp &= *maskp;
1064         return (0);
1065 }