Use BSD libc API to fetch data about interface statistics instead
of nosing in kernel memory. This API should work on all versions of FreeBSD/NetBSD/OpenBSD/Dragonfly. This fixes compilation on FreeBSD 11, where kernel structures have changed and protects against future breakages. It also make the file much simplier. Tested by: Daniel Engberg <daniel.engberg.lists pyret.net>
This commit is contained in:
parent
0436d03757
commit
7f6cf3680e
miniupnpd/bsd
|
@ -1,61 +1,30 @@
|
||||||
/* MiniUPnP project
|
/* MiniUPnP project
|
||||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||||
* author: Ryan Wagoner and Thomas Bernard
|
* author: Gleb Smirnoff <glebius@FreeBSD.org>
|
||||||
* (c) 2006 Ryan Wagoner
|
* (c) 2006 Ryan Wagoner
|
||||||
|
* (c) 2014 Gleb Smirnoff
|
||||||
* This software is subject to the conditions detailed
|
* This software is subject to the conditions detailed
|
||||||
* in the LICENCE file provided within the distribution */
|
* in the LICENCE file provided within the distribution */
|
||||||
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <errno.h>
|
||||||
#include <arpa/inet.h>
|
#include <ifaddrs.h>
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
||||||
#ifdef __DragonFly__
|
|
||||||
#define _KERNEL_STRUCTURES
|
|
||||||
#endif
|
|
||||||
#include <net/if_var.h>
|
|
||||||
#endif
|
|
||||||
#if defined(__DragonFly__)
|
|
||||||
#include <net/pf/pfvar.h>
|
|
||||||
#else
|
|
||||||
#include <net/pfvar.h>
|
|
||||||
#endif
|
|
||||||
#include <kvm.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <nlist.h>
|
|
||||||
#include <sys/queue.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <syslog.h>
|
||||||
|
|
||||||
|
#ifdef ENABLE_GETIFSTATS_CACHING
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../getifstats.h"
|
#include "../getifstats.h"
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
|
|
||||||
static struct nlist list[] = {
|
|
||||||
{"_ifnet", 0, 0, 0, 0},
|
|
||||||
{NULL,0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
int
|
||||||
getifstats(const char * ifname, struct ifdata * data)
|
getifstats(const char *ifname, struct ifdata *data)
|
||||||
{
|
{
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
static struct ifaddrs *ifap, *ifa;
|
||||||
struct ifnethead ifh;
|
|
||||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
|
||||||
struct ifnet_head ifh;
|
|
||||||
#else
|
|
||||||
#error "Dont know if I should use struct ifnethead or struct ifnet_head"
|
|
||||||
#endif
|
|
||||||
struct ifnet ifc;
|
|
||||||
struct ifnet *ifp;
|
|
||||||
kvm_t *kd;
|
|
||||||
ssize_t n;
|
|
||||||
char errstr[_POSIX2_LINE_MAX];
|
|
||||||
#ifdef ENABLE_GETIFSTATS_CACHING
|
#ifdef ENABLE_GETIFSTATS_CACHING
|
||||||
static time_t cache_timestamp = 0;
|
static time_t cache_timestamp;
|
||||||
static struct ifdata cache_data;
|
|
||||||
time_t current_time;
|
time_t current_time;
|
||||||
#endif
|
#endif
|
||||||
if(!data)
|
if(!data)
|
||||||
|
@ -67,70 +36,40 @@ getifstats(const char * ifname, struct ifdata * data)
|
||||||
data->ibytes = 0;
|
data->ibytes = 0;
|
||||||
if(!ifname || ifname[0]=='\0')
|
if(!ifname || ifname[0]=='\0')
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#ifdef ENABLE_GETIFSTATS_CACHING
|
#ifdef ENABLE_GETIFSTATS_CACHING
|
||||||
current_time = time(NULL);
|
current_time = time(NULL);
|
||||||
if(current_time == ((time_t)-1)) {
|
if (ifap != NULL &&
|
||||||
syslog(LOG_ERR, "getifstats() : time() error : %m");
|
current_time < cache_timestamp + GETIFSTATS_CACHING_DURATION)
|
||||||
} else {
|
goto copy;
|
||||||
if(current_time < cache_timestamp + GETIFSTATS_CACHING_DURATION) {
|
|
||||||
memcpy(data, &cache_data, sizeof(struct ifdata));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);*/
|
if (ifap != NULL) {
|
||||||
kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errstr);
|
freeifaddrs(ifap);
|
||||||
if(!kd)
|
ifap = NULL;
|
||||||
{
|
|
||||||
syslog (LOG_ERR, "getifstats() : kvm_open(): %s", errstr);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
if(kvm_nlist(kd, list) < 0)
|
|
||||||
{
|
|
||||||
syslog(LOG_ERR, "getifstats() : kvm_nlist(): FAILED");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if(!list[0].n_value)
|
|
||||||
{
|
|
||||||
syslog(LOG_ERR, "getifstats() : n_value(): FAILED");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
n = kvm_read(kd, list[0].n_value, &ifh, sizeof(ifh));
|
|
||||||
if(n<0)
|
|
||||||
{
|
|
||||||
syslog(LOG_ERR, "getifstats() : kvm_read(head): %s", kvm_geterr(kd));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
for(ifp = TAILQ_FIRST(&ifh); ifp; ifp = TAILQ_NEXT(&ifc, if_list))
|
|
||||||
{
|
|
||||||
n = kvm_read(kd, (u_long)ifp, &ifc, sizeof(ifc));
|
|
||||||
if(n<0)
|
|
||||||
{
|
|
||||||
syslog(LOG_ERR, "getifstats() : kvm_read(element): %s", kvm_geterr(kd));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if(strcmp(ifname, ifc.if_xname) == 0)
|
|
||||||
{
|
|
||||||
/* found the right interface */
|
|
||||||
data->opackets = ifc.if_data.ifi_opackets;
|
|
||||||
data->ipackets = ifc.if_data.ifi_ipackets;
|
|
||||||
data->obytes = ifc.if_data.ifi_obytes;
|
|
||||||
data->ibytes = ifc.if_data.ifi_ibytes;
|
|
||||||
data->baudrate = ifc.if_data.ifi_baudrate;
|
|
||||||
kvm_close(kd);
|
|
||||||
|
|
||||||
|
if (getifaddrs(&ifap) != 0) {
|
||||||
|
syslog (LOG_ERR, "getifstats() : getifaddrs(): %s",
|
||||||
|
strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ifa = ifap; ifa; ifa = ifa->ifa_next)
|
||||||
|
if (ifa->ifa_addr->sa_family == AF_LINK &&
|
||||||
|
strcmp(ifa->ifa_name, ifname) == 0) {
|
||||||
#ifdef ENABLE_GETIFSTATS_CACHING
|
#ifdef ENABLE_GETIFSTATS_CACHING
|
||||||
if(current_time!=((time_t)-1)) {
|
cache_timestamp = current_time;
|
||||||
cache_timestamp = current_time;
|
copy:
|
||||||
memcpy(&cache_data, data, sizeof(struct ifdata));
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return 0; /* ok */
|
#define IFA_STAT(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s)
|
||||||
|
data->opackets = IFA_STAT(opackets);
|
||||||
|
data->ipackets = IFA_STAT(ipackets);
|
||||||
|
data->obytes = IFA_STAT(obytes);
|
||||||
|
data->ibytes = IFA_STAT(ibytes);
|
||||||
|
data->baudrate = IFA_STAT(baudrate);
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
error:
|
|
||||||
kvm_close(kd);
|
|
||||||
return -1; /* not found or error */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue