diff --git a/sysdeps/linux/interfaces.c b/sysdeps/linux/interfaces.c index ea4aa0e8..e3887867 100644 --- a/sysdeps/linux/interfaces.c +++ b/sysdeps/linux/interfaces.c @@ -25,8 +25,15 @@ #include #include +#include #include +#include +#include +#include +#include +#include + static const unsigned long _glibtop_sysdeps_interface_names = (1L << GLIBTOP_INTERFACE_NAMES_NUMBER) + (1L << GLIBTOP_INTERFACE_NAMES_SIZE); @@ -44,13 +51,81 @@ glibtop_init_interface_names_s (glibtop *server) /* Provides network statistics. */ glibtop_interface * -glibtop_get_interface_names_s (glibtop *server, glibtop_interface_names *buf, +glibtop_get_interface_names_s (glibtop *server, glibtop_array *array, u_int64_t interface, u_int64_t number, u_int64_t instance, u_int64_t strategy) { + GPtrArray *parray; + u_int64_t strategy_flags; + glibtop_interface *retval = NULL; + int skfd, i, n, numreqs = 30; + struct ifconf ifc; + struct ifreq *ifr; + glibtop_init_s (&server, GLIBTOP_SYSDEPS_INTERFACE_NAMES, 0); - memset (buf, 0, sizeof (glibtop_interface_names)); + memset (array, 0, sizeof (glibtop_array)); - return NULL; + strategy_flags = strategy & GLIBTOP_STRATEGY_FLAGS_MASK; + strategy &= ~GLIBTOP_STRATEGY_FLAGS_MASK; + + parray = g_ptr_array_new (); + + skfd = socket (AF_INET, SOCK_DGRAM, 0); + if (!skfd) { + glibtop_error_io_r (server, "socket (AF_INET, SOCK_DGRAM, 0)"); + return NULL; + } + + ifc.ifc_buf = NULL; + for (;;) { + ifc.ifc_len = sizeof (struct ifreq) * numreqs; + ifc.ifc_buf = glibtop_realloc_r (server, ifc.ifc_buf, ifc.ifc_len); + + if (ioctl (skfd, SIOCGIFCONF, &ifc) < 0) { + glibtop_error_io_r (server, "SIOCGIFCONF"); + glibtop_free_r (server, ifc.ifc_buf); + return NULL; + } + if (ifc.ifc_len == sizeof (struct ifreq) * numreqs) { + /* assume it overflowed and try again */ + numreqs += 10; + continue; + } + break; + } + + ifr = ifc.ifc_req; + for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq), ifr++) { + glibtop_interface *interface_ptr; + + if (strchr (ifr->ifr_name, ':')) { + /* This is a logical interface */ + if (!(strategy_flags & GLIBTOP_INTERFACES_INCLUDE_LOGICAL)) + continue; + } + + interface_ptr = g_new0 (glibtop_interface, 1); + + strcpy (interface_ptr->name, ifr->ifr_name); + + g_ptr_array_add (parray, interface_ptr); + } + + glibtop_free_r (server, ifc.ifc_buf); + + close (skfd); + + retval = glibtop_calloc_r (server, parray->len, sizeof (glibtop_interface)); + + for (i = 0; i < parray->len; i++) + retval [i] = *(glibtop_interface *) parray->pdata [i]; + + array->number = parray->len; + array->size = sizeof (glibtop_interface); + array->total = array->number * array->size; + + g_ptr_array_free (parray, TRUE); + + return retval; }