summaryrefslogtreecommitdiffstats
path: root/contrib/libpcap/fad-gifc.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libpcap/fad-gifc.c')
-rw-r--r--contrib/libpcap/fad-gifc.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/contrib/libpcap/fad-gifc.c b/contrib/libpcap/fad-gifc.c
index 4ed02f9..985d2c0 100644
--- a/contrib/libpcap/fad-gifc.c
+++ b/contrib/libpcap/fad-gifc.c
@@ -34,7 +34,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.8 2005/01/29 10:34:04 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.8.2.2 2005/06/29 06:43:31 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -102,6 +102,27 @@ struct rtentry; /* declarations in <net/if.h> */
#endif /* HAVE_SOCKADDR_SA_LEN */
#endif /* SA_LEN */
+/*
+ * This is also fun.
+ *
+ * There is no ioctl that returns the amount of space required for all
+ * the data that SIOCGIFCONF could return, and if a buffer is supplied
+ * that's not large enough for all the data SIOCGIFCONF could return,
+ * on at least some platforms it just returns the data that'd fit with
+ * no indication that there wasn't enough room for all the data, much
+ * less an indication of how much more room is required.
+ *
+ * The only way to ensure that we got all the data is to pass a buffer
+ * large enough that the amount of space in the buffer *not* filled in
+ * is greater than the largest possible entry.
+ *
+ * We assume that's "sizeof(ifreq.ifr_name)" plus 255, under the assumption
+ * that no address is more than 255 bytes (on systems where the "sa_len"
+ * field in a "struct sockaddr" is 1 byte, e.g. newer BSDs, that's the
+ * case, and addresses are unlikely to be bigger than that in any case).
+ */
+#define MAX_SA_LEN 255
+
#ifdef HAVE_PROC_NET_DEV
/*
* Get from "/proc/net/dev" all interfaces listed there; if they're
@@ -255,7 +276,7 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
struct ifconf ifc;
char *buf = NULL;
unsigned buf_size;
-#ifdef HAVE_SOLARIS
+#if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER)
char *p, *q;
#endif
struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr;
@@ -275,9 +296,10 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
/*
* Start with an 8K buffer, and keep growing the buffer until
- * we get the entire interface list or fail to get it for some
- * reason other than EINVAL (which is presumed here to mean
- * "buffer is too small").
+ * we have more than "sizeof(ifrp->ifr_name) + MAX_SA_LEN"
+ * bytes left over in the buffer or we fail to get the
+ * interface list for some reason other than EINVAL (which is
+ * presumed here to mean "buffer is too small").
*/
buf_size = 8192;
for (;;) {
@@ -300,7 +322,8 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
free(buf);
return (-1);
}
- if (ifc.ifc_len < buf_size)
+ if (ifc.ifc_len < buf_size &&
+ (buf_size - ifc.ifc_len) > sizeof(ifrp->ifr_name) + MAX_SA_LEN)
break;
free(buf);
buf_size *= 2;
@@ -474,7 +497,7 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
dstaddr_size = 0;
}
-#ifdef HAVE_SOLARIS
+#if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER)
/*
* If this entry has a colon followed by a number at
* the end, it's a logical interface. Those are just
OpenPOWER on IntegriCloud