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