diff options
Diffstat (limited to 'contrib/libpcap/inet.c')
-rw-r--r-- | contrib/libpcap/inet.c | 132 |
1 files changed, 108 insertions, 24 deletions
diff --git a/contrib/libpcap/inet.c b/contrib/libpcap/inet.c index feeed42..0b5b696 100644 --- a/contrib/libpcap/inet.c +++ b/contrib/libpcap/inet.c @@ -33,7 +33,11 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.26 2000/01/14 23:55:31 mcr Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.36 2000/09/20 15:10:29 torsten Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" #endif #include <sys/param.h> @@ -45,11 +49,8 @@ static const char rcsid[] = #endif #include <sys/time.h> /* concession to AIX */ -#if __STDC__ struct mbuf; struct rtentry; -#endif - #include <net/if.h> #include <netinet/in.h> @@ -60,10 +61,12 @@ struct rtentry; #include <stdlib.h> #include <string.h> #include <unistd.h> +#ifdef HAVE_IFADDRS_H +#include <ifaddrs.h> +#endif #include "pcap-int.h" -#include "gnuc.h" #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif @@ -71,9 +74,12 @@ struct rtentry; /* Not all systems have IFF_LOOPBACK */ #ifdef IFF_LOOPBACK #define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK) +#define ISLOOPBACK_IFA(p) ((p)->ifa_flags & IFF_LOOPBACK) #else #define ISLOOPBACK(p) ((p)->ifr_name[0] == 'l' && (p)->ifr_name[1] == 'o' && \ (isdigit((p)->ifr_name[2]) || (p)->ifr_name[2] == '\0')) +#define ISLOOPBACK_IFA(p) ((p)->ifa_name[0] == 'l' && (p)->ifa_name[1] == 'o' && \ + (isdigit((p)->ifa_name[2]) || (p)->ifa_name[2] == '\0')) #endif /* @@ -85,6 +91,59 @@ char * pcap_lookupdev(errbuf) register char *errbuf; { +#ifdef HAVE_IFADDRS_H + struct ifaddrs *ifap, *ifa, *mp; + int n, minunit; + char *cp; + static char device[IF_NAMESIZE + 1]; + + if (getifaddrs(&ifap) != 0) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "getifaddrs: %s", pcap_strerror(errno)); + return NULL; + } + + mp = NULL; + minunit = 666; + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + const char *endcp; + + if ((ifa->ifa_flags & IFF_UP) == 0 || ISLOOPBACK_IFA(ifa)) + continue; + + endcp = ifa->ifa_name + strlen(ifa->ifa_name); + for (cp = ifa->ifa_name; cp < endcp && !isdigit(*cp); ++cp) + continue; + + if (isdigit (*cp)) { + n = atoi(cp); + } else { + n = 0; + } + if (n < minunit) { + minunit = n; + mp = ifa; + } + } + if (mp == NULL) { + (void)strlcpy(errbuf, "no suitable device found", + PCAP_ERRBUF_SIZE); +#ifdef HAVE_FREEIFADDRS + freeifaddrs(ifap); +#else + free(ifap); +#endif + return (NULL); + } + + (void)strlcpy(device, mp->ifa_name, sizeof(device)); +#ifdef HAVE_FREEIFADDRS + freeifaddrs(ifap); +#else + free(ifap); +#endif + return (device); +#else register int fd, minunit, n; register char *cp; register struct ifreq *ifrp, *ifend, *ifnext, *mp; @@ -96,7 +155,8 @@ pcap_lookupdev(errbuf) fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { - (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno)); + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "socket: %s", pcap_strerror(errno)); return (NULL); } @@ -106,17 +166,19 @@ pcap_lookupdev(errbuf) buf = malloc (buf_size); if (buf == NULL) { close (fd); - (void)sprintf(errbuf, "out of memory"); + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "out of memory"); return (NULL); } ifc.ifc_len = buf_size; ifc.ifc_buf = buf; memset (buf, 0, buf_size); - if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0) { + if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 + && errno != EINVAL) { free (buf); - (void)sprintf(errbuf, "SIOCGIFCONF: %s", - pcap_strerror(errno)); + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFCONF: %s", pcap_strerror(errno)); (void)close(fd); return (NULL); } @@ -132,6 +194,8 @@ pcap_lookupdev(errbuf) mp = NULL; minunit = 666; for (; ifrp < ifend; ifrp = ifnext) { + const char *endcp; + #ifdef HAVE_SOCKADDR_SA_LEN n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); if (n < sizeof(*ifrp)) @@ -153,7 +217,8 @@ pcap_lookupdev(errbuf) if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) { if (errno == ENXIO) continue; - (void)sprintf(errbuf, "SIOCGIFFLAGS: %.*s: %s", + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFFLAGS: %.*s: %s", (int)sizeof(ifr.ifr_name), ifr.ifr_name, pcap_strerror(errno)); (void)close(fd); @@ -165,9 +230,15 @@ pcap_lookupdev(errbuf) if ((ifr.ifr_flags & IFF_UP) == 0 || ISLOOPBACK(&ifr)) continue; - for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp) + endcp = ifrp->ifr_name + strlen(ifrp->ifr_name); + for (cp = ifrp->ifr_name; cp < endcp && !isdigit(*cp); ++cp) continue; - n = atoi(cp); + + if (isdigit (*cp)) { + n = atoi(cp); + } else { + n = 0; + } if (n < minunit) { minunit = n; mp = ifrp; @@ -175,15 +246,16 @@ pcap_lookupdev(errbuf) } (void)close(fd); if (mp == NULL) { - (void)strcpy(errbuf, "no suitable device found"); + (void)strlcpy(errbuf, "no suitable device found", + PCAP_ERRBUF_SIZE); free(buf); return (NULL); } - (void)strncpy(device, mp->ifr_name, sizeof(device) - 1); - device[sizeof(device) - 1] = '\0'; + (void)strlcpy(device, mp->ifr_name, sizeof(device)); free(buf); return (device); +#endif } int @@ -196,9 +268,20 @@ pcap_lookupnet(device, netp, maskp, errbuf) register struct sockaddr_in *sin; struct ifreq ifr; + /* + * The pseudo-device "any" listens on all interfaces and therefore + * has the network address and -mask "0.0.0.0" therefore catching + * all traffic. Using NULL for the interface is the same as "any". + */ + if (!device || strcmp(device, "any") == 0) { + *netp = *maskp = 0; + return 0; + } + fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { - (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno)); + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", + pcap_strerror(errno)); return (-1); } memset(&ifr, 0, sizeof(ifr)); @@ -209,10 +292,11 @@ pcap_lookupnet(device, netp, maskp, errbuf) (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { if (errno == EADDRNOTAVAIL) { - (void)sprintf(errbuf, "%s: no IPv4 address assigned", - device); + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "%s: no IPv4 address assigned", device); } else { - (void)sprintf(errbuf, "SIOCGIFADDR: %s: %s", + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFADDR: %s: %s", device, pcap_strerror(errno)); } (void)close(fd); @@ -221,8 +305,8 @@ pcap_lookupnet(device, netp, maskp, errbuf) sin = (struct sockaddr_in *)&ifr.ifr_addr; *netp = sin->sin_addr.s_addr; if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { - (void)sprintf(errbuf, "SIOCGIFNETMASK: %s: %s", - device, pcap_strerror(errno)); + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno)); (void)close(fd); return (-1); } @@ -236,8 +320,8 @@ pcap_lookupnet(device, netp, maskp, errbuf) else if (IN_CLASSC(*netp)) *maskp = IN_CLASSC_NET; else { - (void)sprintf(errbuf, "inet class for 0x%x unknown", - *netp); + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "inet class for 0x%x unknown", *netp); return (-1); } } |