Giuseppe Scrivano <gscriv...@gnu.org> writes: > It seems that SIOCGIFCONF, used by ifconfig, doesn't return all > interfaces as we expect.
What do you think about this patch? Any comment? Cheers, Giuseppe >From 1f4f0273c5dbb14706055639e932554dce8d0353 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano <gscriv...@gnu.org> Date: Sun, 1 Aug 2010 14:52:28 +0200 Subject: [PATCH] Now ifconfig -a includes interfaces without an address * NEWS: Mention the change. * ifconfig/if_index.c (if_nameindex): Remove local variables `ifc', `i', `rq_len', `last_len', `ifr', `end', `cur'. Add local variables `content', `it', `length', `index'. Remove code that uses the SIOCGIFCONF ioctl to get the interfaces list. Parse the PATH_PROCNET_DEV file to fetch the list of interfaces. * bootstrap.conf (gnulib_modules): Add `read-file' module. --- ChangeLog | 14 +++++ NEWS | 8 +++ bootstrap.conf | 1 + ifconfig/if_index.c | 138 +++++++++++++++++++++------------------------------ 4 files changed, 79 insertions(+), 82 deletions(-) diff --git a/ChangeLog b/ChangeLog index 052daee..c5fcddd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,18 @@ +2010-08-01 Giuseppe Scrivano <gscriv...@gnu.org> + + * NEWS: Mention the change. + + * ifconfig/if_index.c (if_nameindex): Remove local variables + `ifc', `i', `rq_len', `last_len', `ifr', `end', `cur'. + Add local variables `content', `it', `length', `index'. + Remove code that uses the SIOCGIFCONF ioctl to get the interfaces + list. Parse the PATH_PROCNET_DEV file to fetch the list of + interfaces. + + * bootstrap.conf (gnulib_modules): Add `read-file' module. + 2010-07-30 Giuseppe Scrivano <gscriv...@gnu.org> + Suggested by Chris Webb <ch...@arachsys.com> * ifconfig/if_index.c (if_nameindex): Remove local variable `len'. Remove code that compute the sizeof of the struct `ifreq'. diff --git a/NEWS b/NEWS index 4583586..2dba114 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,14 @@ See the end of this file for for license conditions. Please send inetutils bug reports to <bug-inetutils@gnu.org>. +XXX YY, ZZ +Version A.B: + +* ifconfig + +ifconfig -a includes interfaces without an address. + + May 15, 2010 Version 1.8: diff --git a/bootstrap.conf b/bootstrap.conf index bbb5c2e..facab0a 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -53,6 +53,7 @@ minmax obstack poll progname +read-file readline readutmp realloc diff --git a/ifconfig/if_index.c b/ifconfig/if_index.c index 3062bf7..3eafb3a 100644 --- a/ifconfig/if_index.c +++ b/ifconfig/if_index.c @@ -29,6 +29,8 @@ #include <sys/types.h> #include <sys/socket.h> +#include <read-file.h> + /* Solaris at least earlier 2.6 and before does not include the ioctl definitions if BSD_COMP is not set. */ #if defined(__svr4__) @@ -97,104 +99,76 @@ if_freenameindex (struct if_nameindex *ifn) struct if_nameindex * if_nameindex (void) { -#if defined(SIOCGIFCONF) - int fd = socket (AF_INET, SOCK_DGRAM, 0); - struct ifconf ifc; - unsigned int i = 0; - int rq_len, last_len; + char *content, *it; + size_t length, index; struct if_nameindex *idx = NULL; - struct ifreq *ifr, *end, *cur; + int fd; + fd = socket (AF_INET, SOCK_DGRAM, 0); if (fd < 0) return NULL; - /* A first estimate. */ - rq_len = 4 * sizeof (struct ifreq); - - ifc.ifc_buf = NULL; - ifc.ifc_len = 0; - /* Read all the interfaces out of the kernel. */ - do - { - last_len = 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_len *= 2; - } - while (ifc.ifc_len != last_len); - - i = 0; - ifr = (struct ifreq *) ifc.ifc_req; - end = (struct ifreq *) ((caddr_t) ifr + ifc.ifc_len); - while (ifr < end) - { - cur = ifr; - - ++ifr; + content = read_file (PATH_PROCNET_DEV, &length); + if (content == NULL) + return NULL; - /* We ignore the other families .. OK ? */ - if (cur->ifr_addr.sa_family != AF_INET) - continue; + /* Count how many interfaces we have. */ + { + size_t n = 0; + it = content; + do + { + it = memchr (it + 1, ':', length - (it - content)); + n++; + } + while (it); - /* Make Room safely. */ + idx = malloc (n * sizeof (*idx)); + if (idx == NULL) { - struct if_nameindex *tidx = NULL; - tidx = realloc (idx, (i + 1) * sizeof (*idx)); - if (tidx == NULL) - { - if_freenameindex (idx); - close (fd); - errno = ENOBUFS; - return NULL; - } - idx = tidx; + int saved_errno = errno; + close (fd); + free (content); + errno = saved_errno; + return NULL; } + } - /* FIXME: We did not deal with duplicates or interface aliases. */ + for (it = memchr (content, ':', length), index = 0; it; + it = memchr (it, ':', it - content), index++) + { + char *start = it - 1; + *it = '\0'; + + while (*start != ' ' && *start != '\n') + start--; - idx[i].if_name = strdup (cur->ifr_name); - if (idx[i].if_name == NULL) - { - if_freenameindex (idx); - close (fd); - errno = ENOBUFS; - return NULL; - } + idx[index].if_name = strdup (start + 1); + idx[index].if_index = index + 1; # if defined(SIOCGIFINDEX) - if (ioctl (fd, SIOCGIFINDEX, cur) >= 0) - idx[i].if_index = cur->ifr_index; - else + { + struct ifreq cur; + strcpy (cur.ifr_name, idx[index].if_name); + cur.ifr_index = -1; + if (ioctl (fd, SIOCGIFINDEX, &cur) >= 0) + idx[index].if_index = cur.ifr_index; + } # endif - idx[i].if_index = i + 1; - i++; + + if (idx[index].if_name == NULL) + { + int saved_errno = errno; + close (fd); + free (content); + errno = saved_errno; + return NULL; + } } - /* Terminate the array with an empty solt. */ - { - struct if_nameindex *tidx = NULL; - tidx = realloc (idx, (i + 1) * sizeof (*idx)); - if (tidx == NULL) - { - if_freenameindex (idx); - close (fd); - errno = ENOBUFS; - return NULL; - } - idx = tidx; - } - idx[i].if_index = 0; - idx[i].if_name = NULL; + idx[index].if_index = 0; + idx[index].if_name = NULL; - close (fd); + free (content); return idx; - -#else - errno = ENOSYS; - return NULL; -#endif } -- 1.7.1