diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux/if_index.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/if_index.c | 44 |
1 files changed, 19 insertions, 25 deletions
diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c index 9d9bf0e0b2..de66b5cb21 100644 --- a/sysdeps/unix/sysv/linux/if_index.c +++ b/sysdeps/unix/sysv/linux/if_index.c @@ -117,52 +117,46 @@ if_nameindex (void) #else int fd = opensock (); struct ifconf ifc; - unsigned int rq_ifs = 4, nifs, i; + unsigned int nifs, i; int rq_len; struct if_nameindex *idx = NULL; -#ifdef SIOCGIFCOUNT - static int siocgifcount_works = 1; -#endif + static int new_siocgifconf = 1; +#define RQ_IFS 4 if (fd < 0) return NULL; -#ifdef SIOCGIFCOUNT - /* We may be able to find out how many interfaces really exist, rather - than guessing. This ioctl is not present in kernels before version - 2.1.50. */ - if (siocgifcount_works) - { - int serrno = errno; + ifc.ifc_buf = NULL; - if (ioctl (fd, SIOCGIFCOUNT, &nifs) < 0) + /* We may be able to get the needed buffer size directly, rather than + guessing. */ + if (new_siocgifconf) + { + ifc.ifc_buf = NULL; + ifc.ifc_len = 0; + if (ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0) { - if (errno == EINVAL) - { - siocgifcount_works = 0; - __set_errno (serrno); - } + new_siocgifconf = 0; + rq_len = RQ_IFS * sizeof (struct ifreq); } else - rq_ifs = nifs + 1; + rq_len = ifc.ifc_len; } -#endif - - ifc.ifc_buf = NULL; + else + rq_len = RQ_IFS * sizeof (struct ifreq); /* Read all the interfaces out of the kernel. */ do { - rq_len = ifc.ifc_len = rq_ifs * sizeof (struct ifreq); - ifc.ifc_buf = alloca (ifc.ifc_len); + ifc.ifc_buf = alloca (ifc.ifc_len = rq_len); if ((ifc.ifc_buf == NULL) || (ioctl (fd, SIOCGIFCONF, &ifc) < 0)) { close (fd); return NULL; } - rq_ifs *= 2; + rq_len *= 2; } - while (ifc.ifc_len == rq_len); + while (ifc.ifc_len == rq_len && new_siocgifconf == 0); nifs = ifc.ifc_len / sizeof (struct ifreq); |