dect
/
libpcap
Archived
13
0
Fork 0

Checking whether the amount of data returned by SIOCGIFCONF is less than

the size of the buffer we handed to it is insufficient to determine
whether we have the entire list of interfaces or not - if the amount of
space left in the buffer after adding an entry is non-zero but less
than the amount of space required by the next entry, the ioctl will stop
before adding the next entry, and not necessarily return an error.

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).
This commit is contained in:
guy 2005-06-29 06:41:39 +00:00
parent 959719860d
commit 819e96c769
1 changed files with 28 additions and 5 deletions

View File

@ -34,7 +34,7 @@
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.10 2005-04-08 02:15:49 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.11 2005-06-29 06:41:39 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
@ -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;