miniupnpd 1.9 (20160113)
[tomato.git] / release / src / router / miniupnpd / mac / getifstats.c
blob9616e6bc507ced0c715a2cc957bfd5ab3febddb1
1 /* $Id: getifstats.c,v 1.7 2012/03/05 20:36:20 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 */
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>
22 #include "../getifstats.h"
23 #include "../config.h"
25 int 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
38 if (data == NULL || ifname == NULL || ifname[0] == '\0')
39 return -1; /* error */
41 data->baudrate = 4200000;
42 data->opackets = 0;
43 data->ipackets = 0;
44 data->obytes = 0;
45 data->ibytes = 0;
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;
57 #endif
59 if (sysctl(mib, mib_len, NULL, &needed, NULL, 0) == -1) {
60 syslog(LOG_ERR, "sysctl(): %m");
61 return -1;
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));
86 #endif
87 return 0; /* found, ok */
91 free(buf);
92 return -1; /* not found or error */