miniupnpd 1.9 (20160113)
[tomato.git] / release / src / router / miniupnpd / linux / getifstats.c
blobfc35ba654e0204cd1bd00e0f1df04c289beae633
1 /* $Id: getifstats.c,v 1.13 2015/06/09 15:33:24 nanard Exp $ */
2 /* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2013 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 #ifdef GET_WIRELESS_STATS
18 #include <unistd.h>
19 #include <sys/ioctl.h>
20 #include <arpa/inet.h>
21 #include <linux/wireless.h>
22 #endif /* GET_WIRELESS_STATS */
24 /* that is the answer */
25 #define BAUDRATE_DEFAULT 4200000
27 int
28 getifstats(const char * ifname, struct ifdata * data)
30 FILE *f;
31 char line[512];
32 char * p;
33 int i;
34 int r = -1;
35 char fname[64];
36 #ifdef ENABLE_GETIFSTATS_CACHING
37 static time_t cache_timestamp = 0;
38 static struct ifdata cache_data;
39 time_t current_time;
40 #endif /* ENABLE_GETIFSTATS_CACHING */
41 if(!data)
42 return -1;
43 data->baudrate = BAUDRATE_DEFAULT;
44 data->opackets = 0;
45 data->ipackets = 0;
46 data->obytes = 0;
47 data->ibytes = 0;
48 if(!ifname || ifname[0]=='\0')
49 return -1;
50 #ifdef ENABLE_GETIFSTATS_CACHING
51 current_time = time(NULL);
52 if(current_time == ((time_t)-1)) {
53 syslog(LOG_ERR, "getifstats() : time() error : %m");
54 } else {
55 if(current_time < cache_timestamp + GETIFSTATS_CACHING_DURATION) {
56 /* return cached data */
57 memcpy(data, &cache_data, sizeof(struct ifdata));
58 return 0;
61 #endif /* ENABLE_GETIFSTATS_CACHING */
62 f = fopen("/proc/net/dev", "r");
63 if(!f) {
64 syslog(LOG_ERR, "getifstats() : cannot open /proc/net/dev : %m");
65 return -1;
67 /* discard the two header lines */
68 if(!fgets(line, sizeof(line), f) || !fgets(line, sizeof(line), f)) {
69 syslog(LOG_ERR, "getifstats() : error reading /proc/net/dev : %m");
71 while(fgets(line, sizeof(line), f)) {
72 p = line;
73 while(*p==' ') p++;
74 i = 0;
75 while(ifname[i] == *p) {
76 p++; i++;
78 /* TODO : how to handle aliases ? */
79 if(ifname[i] || *p != ':')
80 continue;
81 p++;
82 while(*p==' ') p++;
83 data->ibytes = strtoul(p, &p, 0);
84 while(*p==' ') p++;
85 data->ipackets = strtoul(p, &p, 0);
86 /* skip 6 columns */
87 for(i=6; i>0 && *p!='\0'; i--) {
88 while(*p==' ') p++;
89 while(*p!=' ' && *p) p++;
91 while(*p==' ') p++;
92 data->obytes = strtoul(p, &p, 0);
93 while(*p==' ') p++;
94 data->opackets = strtoul(p, &p, 0);
95 r = 0;
96 break;
98 fclose(f);
99 /* get interface speed */
100 snprintf(fname, sizeof(fname), "/sys/class/net/%s/speed", ifname);
101 f = fopen(fname, "r");
102 if(f) {
103 if(fgets(line, sizeof(line), f)) {
104 i = atoi(line); /* 65535 means unknown */
105 if(i > 0 && i < 65535)
106 data->baudrate = 1000000*i;
108 fclose(f);
109 } else {
110 syslog(LOG_INFO, "cannot read %s file : %m", fname);
112 #ifdef GET_WIRELESS_STATS
113 if(data->baudrate == BAUDRATE_DEFAULT) {
114 struct iwreq iwr;
115 int s;
116 s = socket(AF_INET, SOCK_DGRAM, 0);
117 if(s >= 0) {
118 strncpy(iwr.ifr_name, ifname, IFNAMSIZ);
119 if(ioctl(s, SIOCGIWRATE, &iwr) >= 0) {
120 data->baudrate = iwr.u.bitrate.value;
122 close(s);
125 #endif /* GET_WIRELESS_STATS */
126 #ifdef ENABLE_GETIFSTATS_CACHING
127 if(r==0 && current_time!=((time_t)-1)) {
128 /* cache the new data */
129 cache_timestamp = current_time;
130 memcpy(&cache_data, data, sizeof(struct ifdata));
132 #endif /* ENABLE_GETIFSTATS_CACHING */
133 return r;