Tomato 1.28
[tomato.git] / release / src / router / miniupnpd / bsd / getifstats.c
blobf10b60ceebf9aabeaa461ab1a58db2d14c444d40
1 /* MiniUPnP project
2 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
3 * author: Ryan Wagoner and Thomas Bernard
4 * (c) 2006 Ryan Wagoner
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
8 #include <syslog.h>
9 #include <sys/types.h>
10 #include <sys/socket.h>
11 #include <net/if.h>
12 #include <arpa/inet.h>
13 #include <netinet/in.h>
14 #if defined(__FreeBSD__) || defined(__DragonFly__)
15 #include <net/if_var.h>
16 #endif
17 #if defined(__DragonFly__)
18 #include <net/pf/pfvar.h>
19 #else
20 #include <net/pfvar.h>
21 #endif
22 #include <kvm.h>
23 #include <fcntl.h>
24 #include <nlist.h>
25 #include <sys/queue.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <limits.h>
30 #include "../getifstats.h"
31 #include "../config.h"
33 struct nlist list[] = {
34 {"_ifnet"},
35 {NULL}
38 int
39 getifstats(const char * ifname, struct ifdata * data)
41 #if defined(__FreeBSD__) || defined(__DragonFly__)
42 struct ifnethead ifh;
43 #elif defined(__OpenBSD__) || defined(__NetBSD__)
44 struct ifnet_head ifh;
45 #else
46 #error "Dont know if I should use struct ifnethead or struct ifnet_head"
47 #endif
48 struct ifnet ifc;
49 struct ifnet *ifp;
50 kvm_t *kd;
51 ssize_t n;
52 char errstr[_POSIX2_LINE_MAX];
53 #ifdef ENABLE_GETIFSTATS_CACHING
54 static time_t cache_timestamp = 0;
55 static struct ifdata cache_data;
56 time_t current_time;
57 #endif
58 if(!data)
59 return -1;
60 data->baudrate = 4200000;
61 data->opackets = 0;
62 data->ipackets = 0;
63 data->obytes = 0;
64 data->ibytes = 0;
65 if(!ifname || ifname[0]=='\0')
66 return -1;
67 #ifdef ENABLE_GETIFSTATS_CACHING
68 current_time = time(NULL);
69 if(current_time == ((time_t)-1)) {
70 syslog(LOG_ERR, "getifstats() : time() error : %m");
71 } else {
72 if(current_time < cache_timestamp + GETIFSTATS_CACHING_DURATION) {
73 memcpy(data, &cache_data, sizeof(struct ifdata));
74 return 0;
77 #endif
79 /*kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);*/
80 kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errstr);
81 if(!kd)
83 syslog (LOG_ERR, "getifstats() : kvm_open(): %s", errstr);
84 return -1;
86 if(kvm_nlist(kd, list) < 0)
88 syslog(LOG_ERR, "getifstats() : kvm_nlist(): FAILED");
89 goto error;
91 if(!list[0].n_value)
93 syslog(LOG_ERR, "getifstats() : n_value(): FAILED");
94 goto error;
96 n = kvm_read(kd, list[0].n_value, &ifh, sizeof(ifh));
97 if(n<0)
99 syslog(LOG_ERR, "getifstats() : kvm_read(head): %s", kvm_geterr(kd));
100 goto error;
102 for(ifp = TAILQ_FIRST(&ifh); ifp; ifp = TAILQ_NEXT(&ifc, if_list))
104 n = kvm_read(kd, (u_long)ifp, &ifc, sizeof(ifc));
105 if(n<0)
107 syslog(LOG_ERR, "getifstats() : kvm_read(element): %s", kvm_geterr(kd));
108 goto error;
110 if(strcmp(ifname, ifc.if_xname) == 0)
112 /* found the right interface */
113 data->opackets = ifc.if_data.ifi_opackets;
114 data->ipackets = ifc.if_data.ifi_ipackets;
115 data->obytes = ifc.if_data.ifi_obytes;
116 data->ibytes = ifc.if_data.ifi_ibytes;
117 data->baudrate = ifc.if_data.ifi_baudrate;
118 kvm_close(kd);
120 #ifdef ENABLE_GETIFSTATS_CACHING
121 if(current_time!=((time_t)-1)) {
122 cache_timestamp = current_time;
123 memcpy(&cache_data, data, sizeof(struct ifdata));
125 #endif
126 return 0; /* ok */
129 error:
130 kvm_close(kd);
131 return -1; /* not found or error */