1/* $Id: getifstats.c,v 1.6 2012/02/11 13:10:57 nanard Exp $ */ 2/* 3 * MiniUPnP project 4 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 5 * (c) 2009 Jardel Weyrich 6 * This software is subject to the conditions detailed 7 * in the LICENCE file provided within the distribution 8 */ 9 10#include <syslog.h> 11#include <sys/sysctl.h> 12#include <sys/types.h> 13#include <netinet/in.h> 14#include <net/if.h> 15#include <net/if_types.h> 16#include <net/route.h> 17#include <nlist.h> 18#include <stdio.h> 19#include <stdlib.h> 20#include <string.h> 21 22#include "../getifstats.h" 23#include "../config.h" 24 25int getifstats(const char * ifname, struct ifdata * data) { 26 int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_IFLIST, if_nametoindex(ifname) }; 27 const size_t mib_len = sizeof(mib) / sizeof(mib[0]); 28 size_t needed; 29 char *buf, *end, *p; 30 struct if_msghdr *ifm; 31 struct if_data ifdata; 32#ifdef ENABLE_GETIFSTATS_CACHING 33 static time_t cache_timestamp = 0; 34 static struct ifdata cache_data; 35 time_t current_time; 36#endif 37 38 if (data == NULL || ifname == NULL || ifname[0] == '\0') 39 return -1; /* error */ 40 41 data->baudrate = 4200000; 42 data->opackets = 0; 43 data->ipackets = 0; 44 data->obytes = 0; 45 data->ibytes = 0; 46 47#ifdef ENABLE_GETIFSTATS_CACHING 48 current_time = time(NULL); 49 if (current_time == ((time_t)-1)) { 50 syslog(LOG_ERR, "getifstats() : time() error : %m"); 51 } else { 52 if (current_time < cache_timestamp + GETIFSTATS_CACHING_DURATION) { 53 memcpy(data, &cache_data, sizeof(struct ifdata)); 54 return 0; 55 } 56 } 57#endif 58 59 if (sysctl(mib, mib_len, NULL, &needed, NULL, 0) == -1) { 60 syslog(LOG_ERR, "sysctl(): %m"); 61 return -1; 62 } 63 buf = (char *) malloc(needed); 64 if (buf == NULL) 65 return -1; /* error */ 66 if (sysctl(mib, mib_len, buf, &needed, NULL, 0) == -1) { 67 syslog(LOG_ERR, "sysctl(): %m"); 68 free(buf); 69 return -1; /* error */ 70 } else { 71 for (end = buf + needed, p = buf; p < end; p += ifm->ifm_msglen) { 72 ifm = (struct if_msghdr *) p; 73 if (ifm->ifm_type == RTM_IFINFO && ifm->ifm_data.ifi_type == IFT_ETHER) { 74 ifdata = ifm->ifm_data; 75 data->opackets = ifdata.ifi_opackets; 76 data->ipackets = ifdata.ifi_ipackets; 77 data->obytes = ifdata.ifi_obytes; 78 data->ibytes = ifdata.ifi_ibytes; 79 data->baudrate = ifdata.ifi_baudrate; 80 free(buf); 81#ifdef ENABLE_GETIFSTATS_CACHING 82 if (current_time!=((time_t)-1)) { 83 cache_timestamp = current_time; 84 memcpy(&cache_data, data, sizeof(struct ifdata)); 85 } 86#endif 87 return 0; /* found, ok */ 88 } 89 } 90 } 91 free(buf); 92 return -1; /* not found or error */ 93} 94 95