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 */
7:
8: #include <syslog.h>
9: #include <sys/types.h>
10: #include <sys/socket.h>
11: #include <net/if.h>
12: #include <netinet/in.h>
13: #include <arpa/inet.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>
29:
30: #include "../getifstats.h"
31: #include "../config.h"
32:
33: static struct nlist list[] = {
34: {"_ifnet", 0, 0, 0, 0},
35: {NULL,0, 0, 0, 0}
36: };
37:
38: int
39: getifstats(const char * ifname, struct ifdata * data)
40: {
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;
75: }
76: }
77: #endif
78:
79: /*kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);*/
80: kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errstr);
81: if(!kd)
82: {
83: syslog (LOG_ERR, "getifstats() : kvm_open(): %s", errstr);
84: return -1;
85: }
86: if(kvm_nlist(kd, list) < 0)
87: {
88: syslog(LOG_ERR, "getifstats() : kvm_nlist(): FAILED");
89: goto error;
90: }
91: if(!list[0].n_value)
92: {
93: syslog(LOG_ERR, "getifstats() : n_value(): FAILED");
94: goto error;
95: }
96: n = kvm_read(kd, list[0].n_value, &ifh, sizeof(ifh));
97: if(n<0)
98: {
99: syslog(LOG_ERR, "getifstats() : kvm_read(head): %s", kvm_geterr(kd));
100: goto error;
101: }
102: for(ifp = TAILQ_FIRST(&ifh); ifp; ifp = TAILQ_NEXT(&ifc, if_list))
103: {
104: n = kvm_read(kd, (u_long)ifp, &ifc, sizeof(ifc));
105: if(n<0)
106: {
107: syslog(LOG_ERR, "getifstats() : kvm_read(element): %s", kvm_geterr(kd));
108: goto error;
109: }
110: if(strcmp(ifname, ifc.if_xname) == 0)
111: {
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);
119:
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));
124: }
125: #endif
126: return 0; /* ok */
127: }
128: }
129: error:
130: kvm_close(kd);
131: return -1; /* not found or error */
132: }
133:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>