diff options
author | Sam Leffler <sam@FreeBSD.org> | 2005-07-11 03:24:53 +0000 |
---|---|---|
committer | Sam Leffler <sam@FreeBSD.org> | 2005-07-11 03:24:53 +0000 |
commit | ee2dd488bf795a49670e92d0c5a838cc80522088 (patch) | |
tree | d384a6daf986752ae619933314dd5195879612ca /contrib/libpcap/fad-gifc.c | |
parent | 04fb274578a5def82f89c3a522b3f28c8916aa1f (diff) | |
download | src-ee2dd488bf795a49670e92d0c5a838cc80522088.tar.gz src-ee2dd488bf795a49670e92d0c5a838cc80522088.zip |
Notes
Diffstat (limited to 'contrib/libpcap/fad-gifc.c')
-rw-r--r-- | contrib/libpcap/fad-gifc.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/contrib/libpcap/fad-gifc.c b/contrib/libpcap/fad-gifc.c index 4ed02f9a0e53..985d2c0ba341 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 |