]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - contrib/libpcap/fad-gifc.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / contrib / libpcap / fad-gifc.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[] _U_ =
37     "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.11.2.1 2008-08-06 07:35:01 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/ioctl.h>
46 #include <sys/socket.h>
47 #ifdef HAVE_SYS_SOCKIO_H
48 #include <sys/sockio.h>
49 #endif
50 #include <sys/time.h>                           /* concession to AIX */
51
52 struct mbuf;            /* Squelch compiler warnings on some platforms for */
53 struct rtentry;         /* declarations in <net/if.h> */
54 #include <net/if.h>
55 #include <netinet/in.h>
56
57 #include <ctype.h>
58 #include <errno.h>
59 #include <memory.h>
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <unistd.h>
64
65 #include "pcap-int.h"
66
67 #ifdef HAVE_OS_PROTO_H
68 #include "os-proto.h"
69 #endif
70
71 /*
72  * This is fun.
73  *
74  * In older BSD systems, socket addresses were fixed-length, and
75  * "sizeof (struct sockaddr)" gave the size of the structure.
76  * All addresses fit within a "struct sockaddr".
77  *
78  * In newer BSD systems, the socket address is variable-length, and
79  * there's an "sa_len" field giving the length of the structure;
80  * this allows socket addresses to be longer than 2 bytes of family
81  * and 14 bytes of data.
82  *
83  * Some commercial UNIXes use the old BSD scheme, some use the RFC 2553
84  * variant of the old BSD scheme (with "struct sockaddr_storage" rather
85  * than "struct sockaddr"), and some use the new BSD scheme.
86  *
87  * Some versions of GNU libc use neither scheme, but has an "SA_LEN()"
88  * macro that determines the size based on the address family.  Other
89  * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553
90  * but not in the final version).
91  *
92  * We assume that a UNIX that doesn't have "getifaddrs()" and doesn't have
93  * SIOCGLIFCONF, but has SIOCGIFCONF, uses "struct sockaddr" for the
94  * address in an entry returned by SIOCGIFCONF.
95  */
96 #ifndef SA_LEN
97 #ifdef HAVE_SOCKADDR_SA_LEN
98 #define SA_LEN(addr)    ((addr)->sa_len)
99 #else /* HAVE_SOCKADDR_SA_LEN */
100 #define SA_LEN(addr)    (sizeof (struct sockaddr))
101 #endif /* HAVE_SOCKADDR_SA_LEN */
102 #endif /* SA_LEN */
103
104 /*
105  * This is also fun.
106  *
107  * There is no ioctl that returns the amount of space required for all
108  * the data that SIOCGIFCONF could return, and if a buffer is supplied
109  * that's not large enough for all the data SIOCGIFCONF could return,
110  * on at least some platforms it just returns the data that'd fit with
111  * no indication that there wasn't enough room for all the data, much
112  * less an indication of how much more room is required.
113  *
114  * The only way to ensure that we got all the data is to pass a buffer
115  * large enough that the amount of space in the buffer *not* filled in
116  * is greater than the largest possible entry.
117  *
118  * We assume that's "sizeof(ifreq.ifr_name)" plus 255, under the assumption
119  * that no address is more than 255 bytes (on systems where the "sa_len"
120  * field in a "struct sockaddr" is 1 byte, e.g. newer BSDs, that's the
121  * case, and addresses are unlikely to be bigger than that in any case).
122  */
123 #define MAX_SA_LEN      255
124
125 #ifdef HAVE_PROC_NET_DEV
126 /*
127  * Get from "/proc/net/dev" all interfaces listed there; if they're
128  * already in the list of interfaces we have, that won't add another
129  * instance, but if they're not, that'll add them.
130  *
131  * We don't bother getting any addresses for them; it appears you can't
132  * use SIOCGIFADDR on Linux to get IPv6 addresses for interfaces, and,
133  * although some other types of addresses can be fetched with SIOCGIFADDR,
134  * we don't bother with them for now.
135  *
136  * We also don't fail if we couldn't open "/proc/net/dev"; we just leave
137  * the list of interfaces as is.
138  */
139 static int
140 scan_proc_net_dev(pcap_if_t **devlistp, int fd, char *errbuf)
141 {
142         FILE *proc_net_f;
143         char linebuf[512];
144         int linenum;
145         unsigned char *p;
146         char name[512]; /* XXX - pick a size */
147         char *q, *saveq;
148         struct ifreq ifrflags;
149         int ret = 0;
150
151         proc_net_f = fopen("/proc/net/dev", "r");
152         if (proc_net_f == NULL)
153                 return (0);
154
155         for (linenum = 1;
156             fgets(linebuf, sizeof linebuf, proc_net_f) != NULL; linenum++) {
157                 /*
158                  * Skip the first two lines - they're headers.
159                  */
160                 if (linenum <= 2)
161                         continue;
162
163                 p = &linebuf[0];
164
165                 /*
166                  * Skip leading white space.
167                  */
168                 while (*p != '\0' && isspace(*p))
169                         p++;
170                 if (*p == '\0' || *p == '\n')
171                         continue;       /* blank line */
172
173                 /*
174                  * Get the interface name.
175                  */
176                 q = &name[0];
177                 while (*p != '\0' && !isspace(*p)) {
178                         if (*p == ':') {
179                                 /*
180                                  * This could be the separator between a
181                                  * name and an alias number, or it could be
182                                  * the separator between a name with no
183                                  * alias number and the next field.
184                                  *
185                                  * If there's a colon after digits, it
186                                  * separates the name and the alias number,
187                                  * otherwise it separates the name and the
188                                  * next field.
189                                  */
190                                 saveq = q;
191                                 while (isdigit(*p))
192                                         *q++ = *p++;
193                                 if (*p != ':') {
194                                         /*
195                                          * That was the next field,
196                                          * not the alias number.
197                                          */
198                                         q = saveq;
199                                 }
200                                 break;
201                         } else
202                                 *q++ = *p++;
203                 }
204                 *q = '\0';
205
206                 /*
207                  * Get the flags for this interface, and skip it if
208                  * it's not up.
209                  */
210                 strncpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name));
211                 if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
212                         if (errno == ENXIO)
213                                 continue;
214                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
215                             "SIOCGIFFLAGS: %.*s: %s",
216                             (int)sizeof(ifrflags.ifr_name),
217                             ifrflags.ifr_name,
218                             pcap_strerror(errno));
219                         ret = -1;
220                         break;
221                 }
222                 if (!(ifrflags.ifr_flags & IFF_UP))
223                         continue;
224
225                 /*
226                  * Add an entry for this interface, with no addresses.
227                  */
228                 if (pcap_add_if(devlistp, name, ifrflags.ifr_flags, NULL,
229                     errbuf) == -1) {
230                         /*
231                          * Failure.
232                          */
233                         ret = -1;
234                         break;
235                 }
236         }
237         if (ret != -1) {
238                 /*
239                  * Well, we didn't fail for any other reason; did we
240                  * fail due to an error reading the file?
241                  */
242                 if (ferror(proc_net_f)) {
243                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
244                             "Error reading /proc/net/dev: %s",
245                             pcap_strerror(errno));
246                         ret = -1;
247                 }
248         }
249
250         (void)fclose(proc_net_f);
251         return (ret);
252 }
253 #endif /* HAVE_PROC_NET_DEV */
254
255 /*
256  * Get a list of all interfaces that are up and that we can open.
257  * Returns -1 on error, 0 otherwise.
258  * The list, as returned through "alldevsp", may be null if no interfaces
259  * were up and could be opened.
260  *
261  * This is the implementation used on platforms that have SIOCGIFCONF but
262  * don't have any other mechanism for getting a list of interfaces.
263  *
264  * XXX - or platforms that have other, better mechanisms but for which
265  * we don't yet have code to use that mechanism; I think there's a better
266  * way on Linux, for example.
267  */
268 int
269 pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
270 {
271         pcap_if_t *devlist = NULL;
272         register int fd;
273         register struct ifreq *ifrp, *ifend, *ifnext;
274         int n;
275         struct ifconf ifc;
276         char *buf = NULL;
277         unsigned buf_size;
278 #if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER)
279         char *p, *q;
280 #endif
281         struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr;
282         struct sockaddr *netmask, *broadaddr, *dstaddr;
283         size_t netmask_size, broadaddr_size, dstaddr_size;
284         int ret = 0;
285
286         /*
287          * Create a socket from which to fetch the list of interfaces.
288          */
289         fd = socket(AF_INET, SOCK_DGRAM, 0);
290         if (fd < 0) {
291                 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
292                     "socket: %s", pcap_strerror(errno));
293                 return (-1);
294         }
295
296         /*
297          * Start with an 8K buffer, and keep growing the buffer until
298          * we have more than "sizeof(ifrp->ifr_name) + MAX_SA_LEN"
299          * bytes left over in the buffer or we fail to get the
300          * interface list for some reason other than EINVAL (which is
301          * presumed here to mean "buffer is too small").
302          */
303         buf_size = 8192;
304         for (;;) {
305                 buf = malloc(buf_size);
306                 if (buf == NULL) {
307                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
308                             "malloc: %s", pcap_strerror(errno));
309                         (void)close(fd);
310                         return (-1);
311                 }
312
313                 ifc.ifc_len = buf_size;
314                 ifc.ifc_buf = buf;
315                 memset(buf, 0, buf_size);
316                 if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0
317                     && errno != EINVAL) {
318                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
319                             "SIOCGIFCONF: %s", pcap_strerror(errno));
320                         (void)close(fd);
321                         free(buf);
322                         return (-1);
323                 }
324                 if (ifc.ifc_len < buf_size &&
325                     (buf_size - ifc.ifc_len) > sizeof(ifrp->ifr_name) + MAX_SA_LEN)
326                         break;
327                 free(buf);
328                 buf_size *= 2;
329         }
330
331         ifrp = (struct ifreq *)buf;
332         ifend = (struct ifreq *)(buf + ifc.ifc_len);
333
334         for (; ifrp < ifend; ifrp = ifnext) {
335                 /*
336                  * XXX - what if this isn't an IPv4 address?  Can
337                  * we still get the netmask, etc. with ioctls on
338                  * an IPv4 socket?
339                  *
340                  * The answer is probably platform-dependent, and
341                  * if the answer is "no" on more than one platform,
342                  * the way you work around it is probably platform-
343                  * dependent as well.
344                  */
345                 n = SA_LEN(&ifrp->ifr_addr) + sizeof(ifrp->ifr_name);
346                 if (n < sizeof(*ifrp))
347                         ifnext = ifrp + 1;
348                 else
349                         ifnext = (struct ifreq *)((char *)ifrp + n);
350
351                 /*
352                  * XXX - The 32-bit compatibility layer for Linux on IA-64
353                  * is slightly broken. It correctly converts the structures
354                  * to and from kernel land from 64 bit to 32 bit but 
355                  * doesn't update ifc.ifc_len, leaving it larger than the 
356                  * amount really used. This means we read off the end 
357                  * of the buffer and encounter an interface with an 
358                  * "empty" name. Since this is highly unlikely to ever 
359                  * occur in a valid case we can just finish looking for 
360                  * interfaces if we see an empty name.
361                  */
362                 if (!(*ifrp->ifr_name))
363                         break;
364
365                 /*
366                  * Skip entries that begin with "dummy".
367                  * XXX - what are these?  Is this Linux-specific?
368                  * Are there platforms on which we shouldn't do this?
369                  */
370                 if (strncmp(ifrp->ifr_name, "dummy", 5) == 0)
371                         continue;
372
373                 /*
374                  * Get the flags for this interface, and skip it if it's
375                  * not up.
376                  */
377                 strncpy(ifrflags.ifr_name, ifrp->ifr_name,
378                     sizeof(ifrflags.ifr_name));
379                 if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
380                         if (errno == ENXIO)
381                                 continue;
382                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
383                             "SIOCGIFFLAGS: %.*s: %s",
384                             (int)sizeof(ifrflags.ifr_name),
385                             ifrflags.ifr_name,
386                             pcap_strerror(errno));
387                         ret = -1;
388                         break;
389                 }
390                 if (!(ifrflags.ifr_flags & IFF_UP))
391                         continue;
392
393                 /*
394                  * Get the netmask for this address on this interface.
395                  */
396                 strncpy(ifrnetmask.ifr_name, ifrp->ifr_name,
397                     sizeof(ifrnetmask.ifr_name));
398                 memcpy(&ifrnetmask.ifr_addr, &ifrp->ifr_addr,
399                     sizeof(ifrnetmask.ifr_addr));
400                 if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifrnetmask) < 0) {
401                         if (errno == EADDRNOTAVAIL) {
402                                 /*
403                                  * Not available.
404                                  */
405                                 netmask = NULL;
406                                 netmask_size = 0;
407                         } else {
408                                 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
409                                     "SIOCGIFNETMASK: %.*s: %s",
410                                     (int)sizeof(ifrnetmask.ifr_name),
411                                     ifrnetmask.ifr_name,
412                                     pcap_strerror(errno));
413                                 ret = -1;
414                                 break;
415                         }
416                 } else {
417                         netmask = &ifrnetmask.ifr_addr;
418                         netmask_size = SA_LEN(netmask);
419                 }
420
421                 /*
422                  * Get the broadcast address for this address on this
423                  * interface (if any).
424                  */
425                 if (ifrflags.ifr_flags & IFF_BROADCAST) {
426                         strncpy(ifrbroadaddr.ifr_name, ifrp->ifr_name,
427                             sizeof(ifrbroadaddr.ifr_name));
428                         memcpy(&ifrbroadaddr.ifr_addr, &ifrp->ifr_addr,
429                             sizeof(ifrbroadaddr.ifr_addr));
430                         if (ioctl(fd, SIOCGIFBRDADDR,
431                             (char *)&ifrbroadaddr) < 0) {
432                                 if (errno == EADDRNOTAVAIL) {
433                                         /*
434                                          * Not available.
435                                          */
436                                         broadaddr = NULL;
437                                         broadaddr_size = 0;
438                                 } else {
439                                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
440                                             "SIOCGIFBRDADDR: %.*s: %s",
441                                             (int)sizeof(ifrbroadaddr.ifr_name),
442                                             ifrbroadaddr.ifr_name,
443                                             pcap_strerror(errno));
444                                         ret = -1;
445                                         break;
446                                 }
447                         } else {
448                                 broadaddr = &ifrbroadaddr.ifr_broadaddr;
449                                 broadaddr_size = SA_LEN(broadaddr);
450                         }
451                 } else {
452                         /*
453                          * Not a broadcast interface, so no broadcast
454                          * address.
455                          */
456                         broadaddr = NULL;
457                         broadaddr_size = 0;
458                 }
459
460                 /*
461                  * Get the destination address for this address on this
462                  * interface (if any).
463                  */
464                 if (ifrflags.ifr_flags & IFF_POINTOPOINT) {
465                         strncpy(ifrdstaddr.ifr_name, ifrp->ifr_name,
466                             sizeof(ifrdstaddr.ifr_name));
467                         memcpy(&ifrdstaddr.ifr_addr, &ifrp->ifr_addr,
468                             sizeof(ifrdstaddr.ifr_addr));
469                         if (ioctl(fd, SIOCGIFDSTADDR,
470                             (char *)&ifrdstaddr) < 0) {
471                                 if (errno == EADDRNOTAVAIL) {
472                                         /*
473                                          * Not available.
474                                          */
475                                         dstaddr = NULL;
476                                         dstaddr_size = 0;
477                                 } else {
478                                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
479                                             "SIOCGIFDSTADDR: %.*s: %s",
480                                             (int)sizeof(ifrdstaddr.ifr_name),
481                                             ifrdstaddr.ifr_name,
482                                             pcap_strerror(errno));
483                                         ret = -1;
484                                         break;
485                                 }
486                         } else {
487                                 dstaddr = &ifrdstaddr.ifr_dstaddr;
488                                 dstaddr_size = SA_LEN(dstaddr);
489                         }
490                 } else {
491                         /*
492                          * Not a point-to-point interface, so no destination
493                          * address.
494                          */
495                         dstaddr = NULL;
496                         dstaddr_size = 0;
497                 }
498
499 #if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER)
500                 /*
501                  * If this entry has a colon followed by a number at
502                  * the end, it's a logical interface.  Those are just
503                  * the way you assign multiple IP addresses to a real
504                  * interface, so an entry for a logical interface should
505                  * be treated like the entry for the real interface;
506                  * we do that by stripping off the ":" and the number.
507                  */
508                 p = strchr(ifrp->ifr_name, ':');
509                 if (p != NULL) {
510                         /*
511                          * We have a ":"; is it followed by a number?
512                          */
513                         q = p + 1;
514                         while (isdigit((unsigned char)*q))
515                                 q++;
516                         if (*q == '\0') {
517                                 /*
518                                  * All digits after the ":" until the end.
519                                  * Strip off the ":" and everything after
520                                  * it.
521                                  */
522                                 *p = '\0';
523                         }
524                 }
525 #endif
526
527                 /*
528                  * Add information for this address to the list.
529                  */
530                 if (add_addr_to_iflist(&devlist, ifrp->ifr_name,
531                     ifrflags.ifr_flags, &ifrp->ifr_addr,
532                     SA_LEN(&ifrp->ifr_addr), netmask, netmask_size,
533                     broadaddr, broadaddr_size, dstaddr, dstaddr_size,
534                     errbuf) < 0) {
535                         ret = -1;
536                         break;
537                 }
538         }
539         free(buf);
540
541 #ifdef HAVE_PROC_NET_DEV
542         if (ret != -1) {
543                 /*
544                  * We haven't had any errors yet; now read "/proc/net/dev",
545                  * and add to the list of interfaces all interfaces listed
546                  * there that we don't already have, because, on Linux,
547                  * SIOCGIFCONF reports only interfaces with IPv4 addresses,
548                  * so you need to read "/proc/net/dev" to get the names of
549                  * the rest of the interfaces.
550                  */
551                 ret = scan_proc_net_dev(&devlist, fd, errbuf);
552         }
553 #endif
554         (void)close(fd);
555
556         if (ret != -1) {
557                 /*
558                  * We haven't had any errors yet; do any platform-specific
559                  * operations to add devices.
560                  */
561                 if (pcap_platform_finddevs(&devlist, errbuf) < 0)
562                         ret = -1;
563         }
564
565         if (ret == -1) {
566                 /*
567                  * We had an error; free the list we've been constructing.
568                  */
569                 if (devlist != NULL) {
570                         pcap_freealldevs(devlist);
571                         devlist = NULL;
572                 }
573         }
574
575         *alldevsp = devlist;
576         return (ret);
577 }