net/wmnetload has a memory leak [patch] wmnetload (6.4 release) repeatedly calls getifaddrs(3) without freeifaddrs.
The patch here fixes and would replace net/wmnetload/patches/patch-src_ifstat_openbsd_c not apply over it. Also fixes a compile warning from strcmp() w/o <string.h> -Ed Hynan # patch: --- src/ifstat_openbsd.c.orig Tue Jan 29 03:09:18 2002 +++ src/ifstat_openbsd.c Tue Dec 18 13:38:23 2018 @@ -24,22 +24,18 @@ #pragma ident "@(#)ifstat_netbsd.c 1.2 02/01/29 meem" #include <config.h> +#include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <net/if.h> -#include <fcntl.h> -#include <kvm.h> -#include <limits.h> -#include <nlist.h> +#include <ifaddrs.h> #include <stdlib.h> -#include <string.h> #include "ifstat.h" #include "utils.h" struct ifstatstate { - void *ifnet_head; - kvm_t *kd; + struct ifaddrs *ifap; }; /* @@ -51,8 +47,6 @@ if_statinit(void) { ifstatstate_t *statep; - struct nlist ifnet[] = { { "_ifnet" }, { NULL }}; - char errbuf[_POSIX2_LINE_MAX]; statep = malloc(sizeof (ifstatstate_t)); if (statep == NULL) { @@ -60,37 +54,7 @@ return (NULL); } - /* - * Just for the duration of kmem_openfiles(), get privileges - * needed to access kmem. - */ - chpriv(PRIV_GAIN); - statep->kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); - chpriv(PRIV_DROP); - if (statep->kd == NULL) { - warn("cannot access raw kernel memory: %s\n", errbuf); - free(statep); - return (NULL); - } - - if (kvm_nlist(statep->kd, ifnet) == -1) { - warn("cannot populate kernel namelist: %s\n", - kvm_geterr(statep->kd)); - goto fail; - } - - if (kvm_read(statep->kd, ifnet->n_value, &statep->ifnet_head, - sizeof (ifnet->n_value)) != sizeof (ifnet->n_value)) { - warn("cannot find ifnet list head: %s\n", - kvm_geterr(statep->kd)); - goto fail; - } - return (statep); -fail: - (void) kvm_close(statep->kd); - free(statep); - return (NULL); } /* @@ -100,22 +64,39 @@ int if_stats(const char *ifname, ifstatstate_t *statep, ifstats_t *ifstatsp) { - void *ifnet_addr = statep->ifnet_head; - struct ifnet ifnet; + struct ifaddrs *ifa; - for (; ifnet_addr != NULL; ifnet_addr = TAILQ_NEXT(&ifnet, if_list)) { + if (statep->ifap != NULL) { + freeifaddrs(statep->ifap); + } - if (kvm_read(statep->kd, (unsigned long)ifnet_addr, &ifnet, - sizeof (struct ifnet)) != sizeof (struct ifnet)) - return (0); + if (getifaddrs(&statep->ifap) != 0) { + warn("failed to get interface addresses"); + statep->ifap = NULL; + return (0); + } - if (strcmp(ifnet.if_xname, ifname) == 0) { - ifstatsp->rxbytes = ifnet.if_ibytes; - ifstatsp->txbytes = ifnet.if_obytes; - return (1); + for (ifa = statep->ifap; ifa != NULL; ifa = ifa->ifa_next) { + if (strcmp(ifname, ifa->ifa_name)) { + continue; } + + if (ifa->ifa_addr->sa_family == AF_LINK) { + struct sockaddr_dl *dl = (struct sockaddr_dl *)ifa->ifa_addr; + struct if_data *ifd = NULL; + + ifd = ifa->ifa_data; + + if (ifd != NULL) { + ifstatsp->rxbytes = ifd->ifi_ibytes; + ifstatsp->txbytes = ifd->ifi_obytes; + return 1; + } + } } + freeifaddrs(statep->ifap); + statep->ifap = NULL; return (0); } @@ -125,6 +106,7 @@ void if_statfini(ifstatstate_t *statep) { - (void) kvm_close(statep->kd); + if (statep->ifap != NULL) + freeifaddrs(statep->ifap); free(statep); }