libsodium: Needed for Dnscrypto-proxy Release 1.3.0
[tomato.git] / release / src / router / miniupnpd / linux / getifstats.c
blob2aa481d41c85adc40f3870f085b7ea50ee8921c7
1 /* $Id: getifstats.c,v 1.11 2012/04/06 15:26:45 nanard Exp $ */
2 /* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2012 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <syslog.h>
11 #include <string.h>
12 #include <time.h>
14 #include "../config.h"
15 #include "../getifstats.h"
17 int
18 getifstats(const char * ifname, struct ifdata * data)
20 FILE *f;
21 char line[512];
22 char * p;
23 int i;
24 int r = -1;
25 char fname[64];
26 #ifdef ENABLE_GETIFSTATS_CACHING
27 static time_t cache_timestamp = 0;
28 static struct ifdata cache_data;
29 time_t current_time;
30 #endif
31 if(!data)
32 return -1;
33 data->baudrate = 4200000; /* that is the answer */
34 data->opackets = 0;
35 data->ipackets = 0;
36 data->obytes = 0;
37 data->ibytes = 0;
38 if(!ifname || ifname[0]=='\0')
39 return -1;
40 #ifdef ENABLE_GETIFSTATS_CACHING
41 current_time = time(NULL);
42 if(current_time == ((time_t)-1)) {
43 syslog(LOG_ERR, "getifstats() : time() error : %m");
44 } else {
45 if(current_time < cache_timestamp + GETIFSTATS_CACHING_DURATION) {
46 /* return cached data */
47 memcpy(data, &cache_data, sizeof(struct ifdata));
48 return 0;
51 #endif
52 f = fopen("/proc/net/dev", "r");
53 if(!f) {
54 syslog(LOG_ERR, "getifstats() : cannot open /proc/net/dev : %m");
55 return -1;
57 /* discard the two header lines */
58 if(!fgets(line, sizeof(line), f) || !fgets(line, sizeof(line), f)) {
59 syslog(LOG_ERR, "getifstats() : error reading /proc/net/dev : %m");
61 while(fgets(line, sizeof(line), f)) {
62 p = line;
63 while(*p==' ') p++;
64 i = 0;
65 while(ifname[i] == *p) {
66 p++; i++;
68 /* TODO : how to handle aliases ? */
69 if(ifname[i] || *p != ':')
70 continue;
71 p++;
72 while(*p==' ') p++;
73 data->ibytes = strtoul(p, &p, 0);
74 while(*p==' ') p++;
75 data->ipackets = strtoul(p, &p, 0);
76 /* skip 6 columns */
77 for(i=6; i>0 && *p!='\0'; i--) {
78 while(*p==' ') p++;
79 while(*p!=' ' && *p) p++;
81 while(*p==' ') p++;
82 data->obytes = strtoul(p, &p, 0);
83 while(*p==' ') p++;
84 data->opackets = strtoul(p, &p, 0);
85 r = 0;
86 break;
88 fclose(f);
89 /* get interface speed */
90 snprintf(fname, sizeof(fname), "/sys/class/net/%s/speed", ifname);
91 f = fopen(fname, "r");
92 if(f) {
93 if(fgets(line, sizeof(line), f)) {
94 i = atoi(line); /* 65535 means unknown */
95 if(i > 0 && i < 65535)
96 data->baudrate = 1000000*i;
98 fclose(f);
99 } else {
100 syslog(LOG_INFO, "cannot read %s file : %m", fname);
102 #ifdef ENABLE_GETIFSTATS_CACHING
103 if(r==0 && current_time!=((time_t)-1)) {
104 /* cache the new data */
105 cache_timestamp = current_time;
106 memcpy(&cache_data, data, sizeof(struct ifdata));
108 #endif
109 return r;