summaryrefslogtreecommitdiffstats
path: root/contrib/libpcap/inet.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libpcap/inet.c')
-rw-r--r--contrib/libpcap/inet.c132
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);
}
}
OpenPOWER on IntegriCloud