diff --git a/config.h.in b/config.h.in index da91ee0..3af8ff7 100644 --- a/config.h.in +++ b/config.h.in @@ -66,6 +66,9 @@ /* if if_packet.h has tpacket_stats defined */ #undef HAVE_TPACKET_STATS +/* define if you have a /proc/net/dev */ +#undef HAVE_PROC_NET_DEV + /* define on AIX to get certain functions */ #undef _SUN diff --git a/configure b/configure index 0ef5929..ae9020c 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh -# From configure.in Revision: 1.90 +# From configure.in Revision: 1.91 @@ -1750,6 +1750,21 @@ null) esac +echo $ac_n "checking whether we have /proc/net/dev""... $ac_c" 1>&6 +echo "configure:1755: checking whether we have /proc/net/dev" >&5 +if test -r /proc/net/dev ; then + ac_cv_lbl_proc_net_dev=yes +else + ac_cv_lbl_proc_net_dev=no +fi +if test $ac_cv_lbl_proc_net_dev = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_PROC_NET_DEV 1 +EOF + +fi +echo "$ac_t""$ac_cv_lbl_proc_net_dev" 1>&6 + # Check whether --with-flex or --without-flex was given. if test "${with_flex+set}" = set; then withval="$with_flex" @@ -1770,7 +1785,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1774: checking for $ac_word" >&5 +echo "configure:1789: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_V_LEX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1804,7 +1819,7 @@ test -n "$V_LEX" || V_LEX="lex" if test "$V_LEX" = flex ; then # The -V flag was added in 2.4 echo $ac_n "checking for flex 2.4 or higher""... $ac_c" 1>&6 -echo "configure:1808: checking for flex 2.4 or higher" >&5 +echo "configure:1823: checking for flex 2.4 or higher" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_flex_v24'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1830,7 +1845,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1834: checking for $ac_word" >&5 +echo "configure:1849: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_V_YACC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1877,7 +1892,7 @@ if test "$V_LEX" = lex ; then # Some versions of lex can't handle the definitions section of scanner.l . # Try lexing it and complain if it can't deal. echo $ac_n "checking for capable lex""... $ac_c" 1>&6 -echo "configure:1881: checking for capable lex" >&5 +echo "configure:1896: checking for capable lex" >&5 if eval "test \"`echo '$''{'tcpdump_cv_capable_lex'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1928,19 +1943,19 @@ EOF sinix*) echo $ac_n "checking if SINIX compiler defines sinix""... $ac_c" 1>&6 -echo "configure:1932: checking if SINIX compiler defines sinix" >&5 +echo "configure:1947: checking if SINIX compiler defines sinix" >&5 if eval "test \"`echo '$''{'ac_cv_cc_sinix_defined'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1959: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_cc_sinix_defined=yes else @@ -1972,7 +1987,7 @@ esac # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1976: checking for $ac_word" >&5 +echo "configure:1991: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2040,12 +2055,12 @@ EOF fi echo $ac_n "checking if sockaddr struct has sa_len member""... $ac_c" 1>&6 -echo "configure:2044: checking if sockaddr struct has sa_len member" >&5 +echo "configure:2059: checking if sockaddr struct has sa_len member" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_sockaddr_has_sa_len'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -2054,7 +2069,7 @@ int main() { u_int i = sizeof(((struct sockaddr *)0)->sa_len) ; return 0; } EOF -if { (eval echo configure:2058: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2073: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_sockaddr_has_sa_len=yes else @@ -2075,12 +2090,12 @@ EOF fi echo $ac_n "checking if dl_hp_ppa_info_t struct has dl_module_id_1 member""... $ac_c" 1>&6 -echo "configure:2079: checking if dl_hp_ppa_info_t struct has dl_module_id_1 member" >&5 +echo "configure:2094: checking if dl_hp_ppa_info_t struct has dl_module_id_1 member" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -2090,7 +2105,7 @@ int main() { u_int i = sizeof(((dl_hp_ppa_info_t *)0)->dl_module_id_1) ; return 0; } EOF -if { (eval echo configure:2094: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2109: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1=yes else @@ -2111,7 +2126,7 @@ EOF fi echo $ac_n "checking if unaligned accesses fail""... $ac_c" 1>&6 -echo "configure:2115: checking if unaligned accesses fail" >&5 +echo "configure:2130: checking if unaligned accesses fail" >&5 if eval "test \"`echo '$''{'ac_cv_lbl_unaligned_fail'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2196,7 +2211,7 @@ ln -s ${srcdir}/bpf/net net # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:2200: checking for a BSD compatible install" >&5 +echo "configure:2215: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 diff --git a/configure.in b/configure.in index 6da36c6..2821a88 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.90 2001-10-09 03:53:38 guy Exp $ (LBL) +dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.91 2001-10-09 05:43:20 guy Exp $ (LBL) dnl dnl Copyright (c) 1994, 1995, 1996, 1997 dnl The Regents of the University of California. All rights reserved. @@ -6,7 +6,7 @@ dnl dnl Process this file with autoconf to produce a configure script. dnl -AC_REVISION($Revision: 1.90 $) +AC_REVISION($Revision: 1.91 $) AC_INIT(pcap.c) AC_CANONICAL_SYSTEM @@ -142,6 +142,17 @@ null) esac +AC_MSG_CHECKING(whether we have /proc/net/dev) +if test -r /proc/net/dev ; then + ac_cv_lbl_proc_net_dev=yes +else + ac_cv_lbl_proc_net_dev=no +fi +if test $ac_cv_lbl_proc_net_dev = yes; then + AC_DEFINE(HAVE_PROC_NET_DEV, 1, [define if you have a /proc/net/dev]) +fi +AC_MSG_RESULT($ac_cv_lbl_proc_net_dev) + AC_LBL_LEX_AND_YACC(V_LEX, V_YACC, pcap_) if test "$V_LEX" = lex ; then # Some versions of lex can't handle the definitions section of scanner.l . diff --git a/inet.c b/inet.c index 9b4a7e0..86f6d72 100644 --- a/inet.c +++ b/inet.c @@ -34,7 +34,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.40 2001-10-09 03:53:38 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.41 2001-10-09 05:43:20 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -412,11 +412,11 @@ add_addr_to_iflist(pcap_if_t **alldevs, char *name, u_int flags, } static int -pcap_addanydev(pcap_if_t **devlist, char *errbuf) +pcap_add_if(pcap_if_t **devlist, char *name, u_int flags, char *errbuf) { pcap_if_t *curdev; - return (add_or_find_if(&curdev, devlist, "any", 0, errbuf)); + return (add_or_find_if(&curdev, devlist, name, flags, errbuf)); } /* @@ -438,6 +438,17 @@ pcap_findalldevs(alldevsp, errbuf) /* * Get the list of interface addresses. + * + * Note: this won't return information about interfaces + * with no addresses; are there any such interfaces + * that would be capable of receiving packets? + * (Interfaces incapable of receiving packets aren't + * very interesting from libpcap's point of view.) + * + * LAN interfaces will probably have link-layer + * addresses; I don't know whether all implementations + * of "getifaddrs()" now, or in the future, will return + * those. */ if (getifaddrs(&ifap) != 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, @@ -477,14 +488,6 @@ pcap_findalldevs(alldevsp, errbuf) if (add_addr_to_iflist(&devlist, ifa->ifa_name, ifa->ifa_flags, ifa->ifa_addr, ifa->ifa_netmask, broadaddr, dstaddr, errbuf) < 0) { - /* - * Oops, we had a fatal error. - * Free the list we've been constructing, and fail. - */ - if (devlist != NULL) { - pcap_freealldevs(devlist); - devlist = NULL; - } ret = -1; break; } @@ -497,16 +500,17 @@ pcap_findalldevs(alldevsp, errbuf) * We haven't had any errors yet; add the "any" device, * if we can open it. */ - if (pcap_addanydev(&devlist, errbuf) < 0) { - /* - * Oops, we had a fatal error. - * Free the list we've been constructing, and fail. - */ - if (devlist != NULL) { - pcap_freealldevs(devlist); - devlist = NULL; - } - return (-1); + if (pcap_add_if(&devlist, "any", 0, errbuf) < 0) + ret = -1; + } + + if (ret == -1) { + /* + * We had an error; free the list we've been constructing. + */ + if (devlist != NULL) { + pcap_freealldevs(devlist); + devlist = NULL; } } @@ -528,6 +532,14 @@ pcap_findalldevs(alldevsp, errbuf) unsigned buf_size; struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr; struct sockaddr *netmask, *broadaddr, *dstaddr; +#ifdef HAVE_PROC_NET_DEV + FILE *proc_net_f; + char linebuf[512]; + int i; + unsigned char *p; + char name[512]; /* XXX - pick a size */ + char *q, *saveq; +#endif int ret = 0; /* @@ -556,6 +568,7 @@ pcap_findalldevs(alldevsp, errbuf) if (buf == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); + (void)close(fd); return (-1); } @@ -566,7 +579,7 @@ pcap_findalldevs(alldevsp, errbuf) && errno != EINVAL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFCONF: %s", pcap_strerror(errno)); - close(fd); + (void)close(fd); free(buf); return (-1); } @@ -600,10 +613,6 @@ pcap_findalldevs(alldevsp, errbuf) (int)sizeof(ifrflags.ifr_name), ifrflags.ifr_name, pcap_strerror(errno)); - if (devlist != NULL) { - pcap_freealldevs(devlist); - devlist = NULL; - } ret = -1; break; } @@ -629,10 +638,6 @@ pcap_findalldevs(alldevsp, errbuf) (int)sizeof(ifrnetmask.ifr_name), ifrnetmask.ifr_name, pcap_strerror(errno)); - if (devlist != NULL) { - pcap_freealldevs(devlist); - devlist = NULL; - } ret = -1; break; } @@ -661,10 +666,6 @@ pcap_findalldevs(alldevsp, errbuf) (int)sizeof(ifrbroadaddr.ifr_name), ifrbroadaddr.ifr_name, pcap_strerror(errno)); - if (devlist != NULL) { - pcap_freealldevs(devlist); - devlist = NULL; - } ret = -1; break; } @@ -700,10 +701,6 @@ pcap_findalldevs(alldevsp, errbuf) (int)sizeof(ifrdstaddr.ifr_name), ifrdstaddr.ifr_name, pcap_strerror(errno)); - if (devlist != NULL) { - pcap_freealldevs(devlist); - devlist = NULL; - } ret = -1; break; } @@ -718,37 +715,155 @@ pcap_findalldevs(alldevsp, errbuf) if (add_addr_to_iflist(&devlist, ifrp->ifr_name, ifrflags.ifr_flags, &ifrp->ifr_addr, netmask, broadaddr, dstaddr, errbuf) < 0) { - /* - * Oops, we had a fatal error. - * Free the list we've been constructing, and fail. - */ - if (devlist != NULL) { - pcap_freealldevs(devlist); - devlist = NULL; - } ret = -1; break; } } + free(buf); + +#ifdef HAVE_PROC_NET_DEV + /* + * OK, now read "/proc/net/dev", and add to the list of + * interfaces all interfaces listed there that we don't + * already have. + * + * We don't bother getting any addresses for them; + * it appears you can't use SIOCGIFADDR to get + * IPv6 addresses for interfaces, and, although some + * other types of addresses can be fetched with + * SIOCGIFADDR, we don't bother with them for now. + * + * We also don't fail if we couldn't open "/proc/net/dev"; + * we just return the interfaces we've already found. + */ + proc_net_f = fopen("/proc/net/dev", "r"); + if (proc_net_f != NULL) { + /* + * Skip the first two lines - they're headers. + */ + for (i = 0; i < 2; i++) { + if (fgets(linebuf, sizeof linebuf, proc_net_f) == NULL) { + if (ferror(proc_net_f)) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "Error reading /proc/net/dev: %s", + pcap_strerror(errno)); + } else { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "EOF reading header line %d of /proc/net/dev: %s", + i + 1, pcap_strerror(errno)); + } + ret = -1; + break; + } + } + + /* + * Now read the rest of the lines. + */ + while (ret != -1 && + fgets(linebuf, sizeof linebuf, proc_net_f) != NULL) { + p = &linebuf[0]; + + /* + * Skip leading white space. + */ + while (*p != '\0' && isspace(*p)) + p++; + if (*p == '\0' || *p == '\n') + continue; /* blank line */ + + /* + * Get the interface name. + */ + q = &name[0]; + while (*p != '\0' && !isspace(*p)) { + if (*p == ':') { + /* + * This could be the separator + * between a name and an alias + * number, or it could be the + * separator between a name with + * no alias number and the next + * field. + * If there's a colon after digits, + * it separates the name and the alias + * number, otherwise it separates the + * name and the next field. + */ + saveq = q; + while (isdigit(*p)) + *q++ = *p++; + if (*p != ':') { + /* + * That was the next field, + * not the alias number. + */ + q = saveq; + } + break; + } else + *q++ = *p++; + } + *q = '\0'; + + /* + * Get the flags for this interface, and skip it if + * it's not up. + */ + strncpy(ifrflags.ifr_name, name, + sizeof(ifrflags.ifr_name)); + if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) { + if (errno == ENXIO) + continue; + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFFLAGS: %.*s: %s", + (int)sizeof(ifrflags.ifr_name), + ifrflags.ifr_name, + pcap_strerror(errno)); + ret = -1; + break; + } + if (!(ifrflags.ifr_flags & IFF_UP)) + continue; + + /* + * Add an entry for this interface, with no addresses. + */ + if (pcap_add_if(&devlist, name, ifrflags.ifr_flags, + errbuf) == -1) { + /* + * Failure. + */ + ret = -1; + break; + } + } + (void)fclose(proc_net_f); + } +#endif (void)close(fd); - free(buf); if (ret != -1) { /* * We haven't had any errors yet; add the "any" device, * if we can open it. */ - if (pcap_addanydev(&devlist, errbuf) < 0) { + if (pcap_add_if(&devlist, "any", 0, errbuf) < 0) { /* * Oops, we had a fatal error. - * Free the list we've been constructing, and fail. */ - if (devlist != NULL) { - pcap_freealldevs(devlist); - devlist = NULL; - } - return (-1); + ret = -1; + } + } + + if (ret == -1) { + /* + * We had an error; free the list we've been constructing. + */ + if (devlist != NULL) { + pcap_freealldevs(devlist); + devlist = NULL; } }