diff --git a/sysdeps/kernel/glibtop_private.h b/sysdeps/kernel/glibtop_private.h index 02f6c264..0396d864 100644 --- a/sysdeps/kernel/glibtop_private.h +++ b/sysdeps/kernel/glibtop_private.h @@ -79,6 +79,11 @@ glibtop_get_proc_data_proc_maps_s (glibtop *server, pid_t pid, libgtop_proc_maps_t *result, size_t max_len); +int +glibtop_get_proc_data_netload_s (glibtop *server, + libgtop_netload_t *netload, + const char *device); + END_LIBGTOP_DECLS #endif __GLIBTOP_PRIVATE_H__ diff --git a/sysdeps/kernel/netload.c b/sysdeps/kernel/netload.c index beebedba..1ca15c0d 100644 --- a/sysdeps/kernel/netload.c +++ b/sysdeps/kernel/netload.c @@ -25,14 +25,52 @@ #include #include -static const unsigned long _glibtop_sysdeps_netload = 0; +#include + +#include +#include +#include + +#include +#include +#include + +#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 +/* GNU LibC */ +#include +#include +#include +#include +#include +#include +#include +#else /* Libc 5 */ +#include +#include +#include +#include +#include +#include +#endif + +static const unsigned long _glibtop_sysdeps_netload = +(1 << GLIBTOP_NETLOAD_BYTES_IN) + +(1 << GLIBTOP_NETLOAD_BYTES_OUT) + +(1 << GLIBTOP_NETLOAD_BYTES_TOTAL) + +(1 << GLIBTOP_NETLOAD_PACKETS_IN) + +(1 << GLIBTOP_NETLOAD_PACKETS_OUT) + +(1 << GLIBTOP_NETLOAD_PACKETS_TOTAL) + +(1 << GLIBTOP_NETLOAD_ERRORS_IN) + +(1 << GLIBTOP_NETLOAD_ERRORS_OUT) + +(1 << GLIBTOP_NETLOAD_ERRORS_TOTAL) + +(1 << GLIBTOP_NETLOAD_COLLISIONS); /* Init function. */ void glibtop_init_netload_s (glibtop *server) { - server->sysdeps.netload = _glibtop_sysdeps_netload; + server->sysdeps.netload = _glibtop_sysdeps_netload; } /* Provides network statistics. */ @@ -41,5 +79,97 @@ void glibtop_get_netload_s (glibtop *server, glibtop_netload *buf, const char *interface) { - memset (buf, 0, sizeof (glibtop_netload)); + libgtop_netload_t netload; + int skfd; + + memset (buf, 0, sizeof (glibtop_netload)); + + skfd = socket (AF_INET, SOCK_DGRAM, 0); + + if (skfd) { + struct ifreq ifr; + struct sockaddr_in addr; + char *address; + unsigned flags; + + strcpy (ifr.ifr_name, interface); + if (!ioctl (skfd, SIOCGIFFLAGS, &ifr)) { + buf->flags |= (1 << GLIBTOP_NETLOAD_IF_FLAGS); + flags = ifr.ifr_flags; + } else + flags = 0; + + if (flags & IFF_UP) + buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_UP); + + if (flags & IFF_BROADCAST) + buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_BROADCAST); + + if (flags & IFF_DEBUG) + buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_DEBUG); + + if (flags & IFF_LOOPBACK) + buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_LOOPBACK); + + if (flags & IFF_POINTOPOINT) + buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_POINTOPOINT); + + if (flags & IFF_RUNNING) + buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_RUNNING); + + if (flags & IFF_NOARP) + buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_NOARP); + + if (flags & IFF_PROMISC) + buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_PROMISC); + + if (flags & IFF_ALLMULTI) + buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_ALLMULTI); + + if (flags & IFF_MULTICAST) + buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_MULTICAST); + + strcpy (ifr.ifr_name, interface); + if (!ioctl (skfd, SIOCGIFADDR, &ifr)) { + struct sockaddr_in addr = + *(struct sockaddr_in *) &ifr.ifr_addr; + buf->address = addr.sin_addr.s_addr; + buf->flags |= (1 << GLIBTOP_NETLOAD_ADDRESS); + } + + strcpy (ifr.ifr_name, interface); + if (!ioctl (skfd, SIOCGIFNETMASK, &ifr)) { + struct sockaddr_in addr = + *(struct sockaddr_in *) &ifr.ifr_addr; + buf->subnet = addr.sin_addr.s_addr; + buf->flags |= (1 << GLIBTOP_NETLOAD_SUBNET); + } + + strcpy (ifr.ifr_name, interface); + if (!ioctl (skfd, SIOCGIFMTU, &ifr)) { + buf->mtu = ifr.ifr_mtu; + buf->flags |= (1 << GLIBTOP_NETLOAD_MTU); + } + + close (skfd); + } + + if (glibtop_get_proc_data_netload_s (server, &netload, interface)) + return; + + buf->bytes_in = netload.rx_bytes; + buf->bytes_out = netload.tx_bytes; + buf->bytes_total = buf->bytes_in + buf->bytes_out; + + buf->packets_in = netload.rx_packets; + buf->packets_out = netload.tx_packets; + buf->packets_total = buf->packets_in + buf->packets_out; + + buf->errors_in = netload.rx_errors; + buf->errors_out = netload.tx_errors; + buf->errors_total = buf->errors_in + buf->errors_out; + + buf->collisions = netload.collisions; + + buf->flags |= _glibtop_sysdeps_netload; } diff --git a/sysdeps/kernel/procdata.c b/sysdeps/kernel/procdata.c index 9431e1e3..d00dae3a 100644 --- a/sysdeps/kernel/procdata.c +++ b/sysdeps/kernel/procdata.c @@ -178,3 +178,19 @@ glibtop_get_proc_data_proc_maps_s (glibtop *server, pid_t pid, return size; } + +int +glibtop_get_proc_data_netload_s (glibtop *server, + libgtop_netload_t *netload, + const char *device) +{ + int name [2] = { CTL_LIBGTOP, LIBGTOP_NETLOAD }; + size_t size = sizeof (libgtop_netload_t); + + if (sysctl (name, 2, netload, &size, device, strlen (device)+1)) { + glibtop_warn_io_r (server, "sysctl (libgtop/netload)"); + return -1; + } + + return 0; +}