1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * ifstat.c handy utility to read net interface statistics
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker *
9*de1e4e89SAndroid Build Coastguard Worker * Authors: Alexey Kuznetsov, <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker */
11*de1e4e89SAndroid Build Coastguard Worker
12*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
13*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <errno.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <time.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <sys/time.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <fnmatch.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <sys/file.h>
22*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <sys/un.h>
24*de1e4e89SAndroid Build Coastguard Worker #include <sys/poll.h>
25*de1e4e89SAndroid Build Coastguard Worker #include <sys/wait.h>
26*de1e4e89SAndroid Build Coastguard Worker #include <sys/stat.h>
27*de1e4e89SAndroid Build Coastguard Worker #include <signal.h>
28*de1e4e89SAndroid Build Coastguard Worker #include <math.h>
29*de1e4e89SAndroid Build Coastguard Worker #include <getopt.h>
30*de1e4e89SAndroid Build Coastguard Worker
31*de1e4e89SAndroid Build Coastguard Worker #include <linux/if.h>
32*de1e4e89SAndroid Build Coastguard Worker #include <linux/if_link.h>
33*de1e4e89SAndroid Build Coastguard Worker
34*de1e4e89SAndroid Build Coastguard Worker #include "libnetlink.h"
35*de1e4e89SAndroid Build Coastguard Worker #include "json_writer.h"
36*de1e4e89SAndroid Build Coastguard Worker #include "SNAPSHOT.h"
37*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
38*de1e4e89SAndroid Build Coastguard Worker
39*de1e4e89SAndroid Build Coastguard Worker int dump_zeros;
40*de1e4e89SAndroid Build Coastguard Worker int reset_history;
41*de1e4e89SAndroid Build Coastguard Worker int ignore_history;
42*de1e4e89SAndroid Build Coastguard Worker int no_output;
43*de1e4e89SAndroid Build Coastguard Worker int json_output;
44*de1e4e89SAndroid Build Coastguard Worker int no_update;
45*de1e4e89SAndroid Build Coastguard Worker int scan_interval;
46*de1e4e89SAndroid Build Coastguard Worker int time_constant;
47*de1e4e89SAndroid Build Coastguard Worker int show_errors;
48*de1e4e89SAndroid Build Coastguard Worker int pretty;
49*de1e4e89SAndroid Build Coastguard Worker double W;
50*de1e4e89SAndroid Build Coastguard Worker char **patterns;
51*de1e4e89SAndroid Build Coastguard Worker int npatterns;
52*de1e4e89SAndroid Build Coastguard Worker bool is_extended;
53*de1e4e89SAndroid Build Coastguard Worker int filter_type;
54*de1e4e89SAndroid Build Coastguard Worker int sub_type;
55*de1e4e89SAndroid Build Coastguard Worker
56*de1e4e89SAndroid Build Coastguard Worker char info_source[128];
57*de1e4e89SAndroid Build Coastguard Worker int source_mismatch;
58*de1e4e89SAndroid Build Coastguard Worker
59*de1e4e89SAndroid Build Coastguard Worker #define MAXS (sizeof(struct rtnl_link_stats)/sizeof(__u32))
60*de1e4e89SAndroid Build Coastguard Worker #define NO_SUB_TYPE 0xffff
61*de1e4e89SAndroid Build Coastguard Worker
62*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent {
63*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *next;
64*de1e4e89SAndroid Build Coastguard Worker char *name;
65*de1e4e89SAndroid Build Coastguard Worker int ifindex;
66*de1e4e89SAndroid Build Coastguard Worker __u64 val[MAXS];
67*de1e4e89SAndroid Build Coastguard Worker double rate[MAXS];
68*de1e4e89SAndroid Build Coastguard Worker __u32 ival[MAXS];
69*de1e4e89SAndroid Build Coastguard Worker };
70*de1e4e89SAndroid Build Coastguard Worker
71*de1e4e89SAndroid Build Coastguard Worker static const char *stats[MAXS] = {
72*de1e4e89SAndroid Build Coastguard Worker "rx_packets",
73*de1e4e89SAndroid Build Coastguard Worker "tx_packets",
74*de1e4e89SAndroid Build Coastguard Worker "rx_bytes",
75*de1e4e89SAndroid Build Coastguard Worker "tx_bytes",
76*de1e4e89SAndroid Build Coastguard Worker "rx_errors",
77*de1e4e89SAndroid Build Coastguard Worker "tx_errors",
78*de1e4e89SAndroid Build Coastguard Worker "rx_dropped",
79*de1e4e89SAndroid Build Coastguard Worker "tx_dropped",
80*de1e4e89SAndroid Build Coastguard Worker "multicast",
81*de1e4e89SAndroid Build Coastguard Worker "collisions",
82*de1e4e89SAndroid Build Coastguard Worker "rx_length_errors",
83*de1e4e89SAndroid Build Coastguard Worker "rx_over_errors",
84*de1e4e89SAndroid Build Coastguard Worker "rx_crc_errors",
85*de1e4e89SAndroid Build Coastguard Worker "rx_frame_errors",
86*de1e4e89SAndroid Build Coastguard Worker "rx_fifo_errors",
87*de1e4e89SAndroid Build Coastguard Worker "rx_missed_errors",
88*de1e4e89SAndroid Build Coastguard Worker "tx_aborted_errors",
89*de1e4e89SAndroid Build Coastguard Worker "tx_carrier_errors",
90*de1e4e89SAndroid Build Coastguard Worker "tx_fifo_errors",
91*de1e4e89SAndroid Build Coastguard Worker "tx_heartbeat_errors",
92*de1e4e89SAndroid Build Coastguard Worker "tx_window_errors",
93*de1e4e89SAndroid Build Coastguard Worker "rx_compressed",
94*de1e4e89SAndroid Build Coastguard Worker "tx_compressed"
95*de1e4e89SAndroid Build Coastguard Worker };
96*de1e4e89SAndroid Build Coastguard Worker
97*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *kern_db;
98*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *hist_db;
99*de1e4e89SAndroid Build Coastguard Worker
match(const char * id)100*de1e4e89SAndroid Build Coastguard Worker static int match(const char *id)
101*de1e4e89SAndroid Build Coastguard Worker {
102*de1e4e89SAndroid Build Coastguard Worker int i;
103*de1e4e89SAndroid Build Coastguard Worker
104*de1e4e89SAndroid Build Coastguard Worker if (npatterns == 0)
105*de1e4e89SAndroid Build Coastguard Worker return 1;
106*de1e4e89SAndroid Build Coastguard Worker
107*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < npatterns; i++) {
108*de1e4e89SAndroid Build Coastguard Worker if (!fnmatch(patterns[i], id, 0))
109*de1e4e89SAndroid Build Coastguard Worker return 1;
110*de1e4e89SAndroid Build Coastguard Worker }
111*de1e4e89SAndroid Build Coastguard Worker return 0;
112*de1e4e89SAndroid Build Coastguard Worker }
113*de1e4e89SAndroid Build Coastguard Worker
get_nlmsg_extended(const struct sockaddr_nl * who,struct nlmsghdr * m,void * arg)114*de1e4e89SAndroid Build Coastguard Worker static int get_nlmsg_extended(const struct sockaddr_nl *who,
115*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *m, void *arg)
116*de1e4e89SAndroid Build Coastguard Worker {
117*de1e4e89SAndroid Build Coastguard Worker struct if_stats_msg *ifsm = NLMSG_DATA(m);
118*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[IFLA_STATS_MAX+1];
119*de1e4e89SAndroid Build Coastguard Worker int len = m->nlmsg_len;
120*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *n;
121*de1e4e89SAndroid Build Coastguard Worker
122*de1e4e89SAndroid Build Coastguard Worker if (m->nlmsg_type != RTM_NEWSTATS)
123*de1e4e89SAndroid Build Coastguard Worker return 0;
124*de1e4e89SAndroid Build Coastguard Worker
125*de1e4e89SAndroid Build Coastguard Worker len -= NLMSG_LENGTH(sizeof(*ifsm));
126*de1e4e89SAndroid Build Coastguard Worker if (len < 0)
127*de1e4e89SAndroid Build Coastguard Worker return -1;
128*de1e4e89SAndroid Build Coastguard Worker
129*de1e4e89SAndroid Build Coastguard Worker parse_rtattr(tb, IFLA_STATS_MAX, IFLA_STATS_RTA(ifsm), len);
130*de1e4e89SAndroid Build Coastguard Worker if (tb[filter_type] == NULL)
131*de1e4e89SAndroid Build Coastguard Worker return 0;
132*de1e4e89SAndroid Build Coastguard Worker
133*de1e4e89SAndroid Build Coastguard Worker n = malloc(sizeof(*n));
134*de1e4e89SAndroid Build Coastguard Worker if (!n)
135*de1e4e89SAndroid Build Coastguard Worker abort();
136*de1e4e89SAndroid Build Coastguard Worker
137*de1e4e89SAndroid Build Coastguard Worker n->ifindex = ifsm->ifindex;
138*de1e4e89SAndroid Build Coastguard Worker n->name = strdup(ll_index_to_name(ifsm->ifindex));
139*de1e4e89SAndroid Build Coastguard Worker
140*de1e4e89SAndroid Build Coastguard Worker if (sub_type == NO_SUB_TYPE) {
141*de1e4e89SAndroid Build Coastguard Worker memcpy(&n->val, RTA_DATA(tb[filter_type]), sizeof(n->val));
142*de1e4e89SAndroid Build Coastguard Worker } else {
143*de1e4e89SAndroid Build Coastguard Worker struct rtattr *attr;
144*de1e4e89SAndroid Build Coastguard Worker
145*de1e4e89SAndroid Build Coastguard Worker attr = parse_rtattr_one_nested(sub_type, tb[filter_type]);
146*de1e4e89SAndroid Build Coastguard Worker if (attr == NULL) {
147*de1e4e89SAndroid Build Coastguard Worker free(n);
148*de1e4e89SAndroid Build Coastguard Worker return 0;
149*de1e4e89SAndroid Build Coastguard Worker }
150*de1e4e89SAndroid Build Coastguard Worker memcpy(&n->val, RTA_DATA(attr), sizeof(n->val));
151*de1e4e89SAndroid Build Coastguard Worker }
152*de1e4e89SAndroid Build Coastguard Worker memset(&n->rate, 0, sizeof(n->rate));
153*de1e4e89SAndroid Build Coastguard Worker n->next = kern_db;
154*de1e4e89SAndroid Build Coastguard Worker kern_db = n;
155*de1e4e89SAndroid Build Coastguard Worker return 0;
156*de1e4e89SAndroid Build Coastguard Worker }
157*de1e4e89SAndroid Build Coastguard Worker
get_nlmsg(const struct sockaddr_nl * who,struct nlmsghdr * m,void * arg)158*de1e4e89SAndroid Build Coastguard Worker static int get_nlmsg(const struct sockaddr_nl *who,
159*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *m, void *arg)
160*de1e4e89SAndroid Build Coastguard Worker {
161*de1e4e89SAndroid Build Coastguard Worker struct ifinfomsg *ifi = NLMSG_DATA(m);
162*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[IFLA_MAX+1];
163*de1e4e89SAndroid Build Coastguard Worker int len = m->nlmsg_len;
164*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *n;
165*de1e4e89SAndroid Build Coastguard Worker int i;
166*de1e4e89SAndroid Build Coastguard Worker
167*de1e4e89SAndroid Build Coastguard Worker if (m->nlmsg_type != RTM_NEWLINK)
168*de1e4e89SAndroid Build Coastguard Worker return 0;
169*de1e4e89SAndroid Build Coastguard Worker
170*de1e4e89SAndroid Build Coastguard Worker len -= NLMSG_LENGTH(sizeof(*ifi));
171*de1e4e89SAndroid Build Coastguard Worker if (len < 0)
172*de1e4e89SAndroid Build Coastguard Worker return -1;
173*de1e4e89SAndroid Build Coastguard Worker
174*de1e4e89SAndroid Build Coastguard Worker if (!(ifi->ifi_flags&IFF_UP))
175*de1e4e89SAndroid Build Coastguard Worker return 0;
176*de1e4e89SAndroid Build Coastguard Worker
177*de1e4e89SAndroid Build Coastguard Worker parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
178*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_IFNAME] == NULL || tb[IFLA_STATS] == NULL)
179*de1e4e89SAndroid Build Coastguard Worker return 0;
180*de1e4e89SAndroid Build Coastguard Worker
181*de1e4e89SAndroid Build Coastguard Worker n = malloc(sizeof(*n));
182*de1e4e89SAndroid Build Coastguard Worker if (!n)
183*de1e4e89SAndroid Build Coastguard Worker abort();
184*de1e4e89SAndroid Build Coastguard Worker n->ifindex = ifi->ifi_index;
185*de1e4e89SAndroid Build Coastguard Worker n->name = strdup(RTA_DATA(tb[IFLA_IFNAME]));
186*de1e4e89SAndroid Build Coastguard Worker memcpy(&n->ival, RTA_DATA(tb[IFLA_STATS]), sizeof(n->ival));
187*de1e4e89SAndroid Build Coastguard Worker memset(&n->rate, 0, sizeof(n->rate));
188*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < MAXS; i++)
189*de1e4e89SAndroid Build Coastguard Worker n->val[i] = n->ival[i];
190*de1e4e89SAndroid Build Coastguard Worker n->next = kern_db;
191*de1e4e89SAndroid Build Coastguard Worker kern_db = n;
192*de1e4e89SAndroid Build Coastguard Worker return 0;
193*de1e4e89SAndroid Build Coastguard Worker }
194*de1e4e89SAndroid Build Coastguard Worker
load_info(void)195*de1e4e89SAndroid Build Coastguard Worker static void load_info(void)
196*de1e4e89SAndroid Build Coastguard Worker {
197*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *db, *n;
198*de1e4e89SAndroid Build Coastguard Worker struct rtnl_handle rth;
199*de1e4e89SAndroid Build Coastguard Worker __u32 filter_mask;
200*de1e4e89SAndroid Build Coastguard Worker
201*de1e4e89SAndroid Build Coastguard Worker if (rtnl_open(&rth, 0) < 0)
202*de1e4e89SAndroid Build Coastguard Worker exit(1);
203*de1e4e89SAndroid Build Coastguard Worker
204*de1e4e89SAndroid Build Coastguard Worker if (is_extended) {
205*de1e4e89SAndroid Build Coastguard Worker ll_init_map(&rth);
206*de1e4e89SAndroid Build Coastguard Worker filter_mask = IFLA_STATS_FILTER_BIT(filter_type);
207*de1e4e89SAndroid Build Coastguard Worker if (rtnl_wilddump_stats_req_filter(&rth, AF_UNSPEC, RTM_GETSTATS,
208*de1e4e89SAndroid Build Coastguard Worker filter_mask) < 0) {
209*de1e4e89SAndroid Build Coastguard Worker perror("Cannot send dump request");
210*de1e4e89SAndroid Build Coastguard Worker exit(1);
211*de1e4e89SAndroid Build Coastguard Worker }
212*de1e4e89SAndroid Build Coastguard Worker
213*de1e4e89SAndroid Build Coastguard Worker if (rtnl_dump_filter(&rth, get_nlmsg_extended, NULL) < 0) {
214*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Dump terminated\n");
215*de1e4e89SAndroid Build Coastguard Worker exit(1);
216*de1e4e89SAndroid Build Coastguard Worker }
217*de1e4e89SAndroid Build Coastguard Worker } else {
218*de1e4e89SAndroid Build Coastguard Worker if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETLINK) < 0) {
219*de1e4e89SAndroid Build Coastguard Worker perror("Cannot send dump request");
220*de1e4e89SAndroid Build Coastguard Worker exit(1);
221*de1e4e89SAndroid Build Coastguard Worker }
222*de1e4e89SAndroid Build Coastguard Worker
223*de1e4e89SAndroid Build Coastguard Worker if (rtnl_dump_filter(&rth, get_nlmsg, NULL) < 0) {
224*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Dump terminated\n");
225*de1e4e89SAndroid Build Coastguard Worker exit(1);
226*de1e4e89SAndroid Build Coastguard Worker }
227*de1e4e89SAndroid Build Coastguard Worker }
228*de1e4e89SAndroid Build Coastguard Worker
229*de1e4e89SAndroid Build Coastguard Worker rtnl_close(&rth);
230*de1e4e89SAndroid Build Coastguard Worker
231*de1e4e89SAndroid Build Coastguard Worker db = kern_db;
232*de1e4e89SAndroid Build Coastguard Worker kern_db = NULL;
233*de1e4e89SAndroid Build Coastguard Worker
234*de1e4e89SAndroid Build Coastguard Worker while (db) {
235*de1e4e89SAndroid Build Coastguard Worker n = db;
236*de1e4e89SAndroid Build Coastguard Worker db = db->next;
237*de1e4e89SAndroid Build Coastguard Worker n->next = kern_db;
238*de1e4e89SAndroid Build Coastguard Worker kern_db = n;
239*de1e4e89SAndroid Build Coastguard Worker }
240*de1e4e89SAndroid Build Coastguard Worker }
241*de1e4e89SAndroid Build Coastguard Worker
load_raw_table(FILE * fp)242*de1e4e89SAndroid Build Coastguard Worker static void load_raw_table(FILE *fp)
243*de1e4e89SAndroid Build Coastguard Worker {
244*de1e4e89SAndroid Build Coastguard Worker char buf[4096];
245*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *db = NULL;
246*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *n;
247*de1e4e89SAndroid Build Coastguard Worker
248*de1e4e89SAndroid Build Coastguard Worker while (fgets(buf, sizeof(buf), fp) != NULL) {
249*de1e4e89SAndroid Build Coastguard Worker char *p;
250*de1e4e89SAndroid Build Coastguard Worker char *next;
251*de1e4e89SAndroid Build Coastguard Worker int i;
252*de1e4e89SAndroid Build Coastguard Worker
253*de1e4e89SAndroid Build Coastguard Worker if (buf[0] == '#') {
254*de1e4e89SAndroid Build Coastguard Worker buf[strlen(buf)-1] = 0;
255*de1e4e89SAndroid Build Coastguard Worker if (info_source[0] && strcmp(info_source, buf+1))
256*de1e4e89SAndroid Build Coastguard Worker source_mismatch = 1;
257*de1e4e89SAndroid Build Coastguard Worker strncpy(info_source, buf+1, sizeof(info_source)-1);
258*de1e4e89SAndroid Build Coastguard Worker continue;
259*de1e4e89SAndroid Build Coastguard Worker }
260*de1e4e89SAndroid Build Coastguard Worker if ((n = malloc(sizeof(*n))) == NULL)
261*de1e4e89SAndroid Build Coastguard Worker abort();
262*de1e4e89SAndroid Build Coastguard Worker
263*de1e4e89SAndroid Build Coastguard Worker if (!(p = strchr(buf, ' ')))
264*de1e4e89SAndroid Build Coastguard Worker abort();
265*de1e4e89SAndroid Build Coastguard Worker *p++ = 0;
266*de1e4e89SAndroid Build Coastguard Worker
267*de1e4e89SAndroid Build Coastguard Worker if (sscanf(buf, "%d", &n->ifindex) != 1)
268*de1e4e89SAndroid Build Coastguard Worker abort();
269*de1e4e89SAndroid Build Coastguard Worker if (!(next = strchr(p, ' ')))
270*de1e4e89SAndroid Build Coastguard Worker abort();
271*de1e4e89SAndroid Build Coastguard Worker *next++ = 0;
272*de1e4e89SAndroid Build Coastguard Worker
273*de1e4e89SAndroid Build Coastguard Worker n->name = strdup(p);
274*de1e4e89SAndroid Build Coastguard Worker p = next;
275*de1e4e89SAndroid Build Coastguard Worker
276*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < MAXS; i++) {
277*de1e4e89SAndroid Build Coastguard Worker unsigned int rate;
278*de1e4e89SAndroid Build Coastguard Worker
279*de1e4e89SAndroid Build Coastguard Worker if (!(next = strchr(p, ' ')))
280*de1e4e89SAndroid Build Coastguard Worker abort();
281*de1e4e89SAndroid Build Coastguard Worker *next++ = 0;
282*de1e4e89SAndroid Build Coastguard Worker if (sscanf(p, "%llu", n->val+i) != 1)
283*de1e4e89SAndroid Build Coastguard Worker abort();
284*de1e4e89SAndroid Build Coastguard Worker n->ival[i] = (__u32)n->val[i];
285*de1e4e89SAndroid Build Coastguard Worker p = next;
286*de1e4e89SAndroid Build Coastguard Worker if (!(next = strchr(p, ' ')))
287*de1e4e89SAndroid Build Coastguard Worker abort();
288*de1e4e89SAndroid Build Coastguard Worker *next++ = 0;
289*de1e4e89SAndroid Build Coastguard Worker if (sscanf(p, "%u", &rate) != 1)
290*de1e4e89SAndroid Build Coastguard Worker abort();
291*de1e4e89SAndroid Build Coastguard Worker n->rate[i] = rate;
292*de1e4e89SAndroid Build Coastguard Worker p = next;
293*de1e4e89SAndroid Build Coastguard Worker }
294*de1e4e89SAndroid Build Coastguard Worker n->next = db;
295*de1e4e89SAndroid Build Coastguard Worker db = n;
296*de1e4e89SAndroid Build Coastguard Worker }
297*de1e4e89SAndroid Build Coastguard Worker
298*de1e4e89SAndroid Build Coastguard Worker while (db) {
299*de1e4e89SAndroid Build Coastguard Worker n = db;
300*de1e4e89SAndroid Build Coastguard Worker db = db->next;
301*de1e4e89SAndroid Build Coastguard Worker n->next = kern_db;
302*de1e4e89SAndroid Build Coastguard Worker kern_db = n;
303*de1e4e89SAndroid Build Coastguard Worker }
304*de1e4e89SAndroid Build Coastguard Worker }
305*de1e4e89SAndroid Build Coastguard Worker
dump_raw_db(FILE * fp,int to_hist)306*de1e4e89SAndroid Build Coastguard Worker static void dump_raw_db(FILE *fp, int to_hist)
307*de1e4e89SAndroid Build Coastguard Worker {
308*de1e4e89SAndroid Build Coastguard Worker json_writer_t *jw = json_output ? jsonw_new(fp) : NULL;
309*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *n, *h;
310*de1e4e89SAndroid Build Coastguard Worker
311*de1e4e89SAndroid Build Coastguard Worker h = hist_db;
312*de1e4e89SAndroid Build Coastguard Worker if (jw) {
313*de1e4e89SAndroid Build Coastguard Worker jsonw_start_object(jw);
314*de1e4e89SAndroid Build Coastguard Worker jsonw_pretty(jw, pretty);
315*de1e4e89SAndroid Build Coastguard Worker jsonw_name(jw, info_source);
316*de1e4e89SAndroid Build Coastguard Worker jsonw_start_object(jw);
317*de1e4e89SAndroid Build Coastguard Worker } else
318*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "#%s\n", info_source);
319*de1e4e89SAndroid Build Coastguard Worker
320*de1e4e89SAndroid Build Coastguard Worker for (n = kern_db; n; n = n->next) {
321*de1e4e89SAndroid Build Coastguard Worker int i;
322*de1e4e89SAndroid Build Coastguard Worker unsigned long long *vals = n->val;
323*de1e4e89SAndroid Build Coastguard Worker double *rates = n->rate;
324*de1e4e89SAndroid Build Coastguard Worker
325*de1e4e89SAndroid Build Coastguard Worker if (!match(n->name)) {
326*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *h1;
327*de1e4e89SAndroid Build Coastguard Worker
328*de1e4e89SAndroid Build Coastguard Worker if (!to_hist)
329*de1e4e89SAndroid Build Coastguard Worker continue;
330*de1e4e89SAndroid Build Coastguard Worker for (h1 = h; h1; h1 = h1->next) {
331*de1e4e89SAndroid Build Coastguard Worker if (h1->ifindex == n->ifindex) {
332*de1e4e89SAndroid Build Coastguard Worker vals = h1->val;
333*de1e4e89SAndroid Build Coastguard Worker rates = h1->rate;
334*de1e4e89SAndroid Build Coastguard Worker h = h1->next;
335*de1e4e89SAndroid Build Coastguard Worker break;
336*de1e4e89SAndroid Build Coastguard Worker }
337*de1e4e89SAndroid Build Coastguard Worker }
338*de1e4e89SAndroid Build Coastguard Worker }
339*de1e4e89SAndroid Build Coastguard Worker
340*de1e4e89SAndroid Build Coastguard Worker if (jw) {
341*de1e4e89SAndroid Build Coastguard Worker jsonw_name(jw, n->name);
342*de1e4e89SAndroid Build Coastguard Worker jsonw_start_object(jw);
343*de1e4e89SAndroid Build Coastguard Worker
344*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < MAXS && stats[i]; i++)
345*de1e4e89SAndroid Build Coastguard Worker jsonw_uint_field(jw, stats[i], vals[i]);
346*de1e4e89SAndroid Build Coastguard Worker jsonw_end_object(jw);
347*de1e4e89SAndroid Build Coastguard Worker } else {
348*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%d %s ", n->ifindex, n->name);
349*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < MAXS; i++)
350*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%llu %u ", vals[i],
351*de1e4e89SAndroid Build Coastguard Worker (unsigned int)rates[i]);
352*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "\n");
353*de1e4e89SAndroid Build Coastguard Worker }
354*de1e4e89SAndroid Build Coastguard Worker }
355*de1e4e89SAndroid Build Coastguard Worker if (jw) {
356*de1e4e89SAndroid Build Coastguard Worker jsonw_end_object(jw);
357*de1e4e89SAndroid Build Coastguard Worker
358*de1e4e89SAndroid Build Coastguard Worker jsonw_end_object(jw);
359*de1e4e89SAndroid Build Coastguard Worker jsonw_destroy(&jw);
360*de1e4e89SAndroid Build Coastguard Worker }
361*de1e4e89SAndroid Build Coastguard Worker }
362*de1e4e89SAndroid Build Coastguard Worker
363*de1e4e89SAndroid Build Coastguard Worker /* use communication definitions of meg/kilo etc */
364*de1e4e89SAndroid Build Coastguard Worker static const unsigned long long giga = 1000000000ull;
365*de1e4e89SAndroid Build Coastguard Worker static const unsigned long long mega = 1000000;
366*de1e4e89SAndroid Build Coastguard Worker static const unsigned long long kilo = 1000;
367*de1e4e89SAndroid Build Coastguard Worker
format_rate(FILE * fp,const unsigned long long * vals,const double * rates,int i)368*de1e4e89SAndroid Build Coastguard Worker static void format_rate(FILE *fp, const unsigned long long *vals,
369*de1e4e89SAndroid Build Coastguard Worker const double *rates, int i)
370*de1e4e89SAndroid Build Coastguard Worker {
371*de1e4e89SAndroid Build Coastguard Worker char temp[64];
372*de1e4e89SAndroid Build Coastguard Worker
373*de1e4e89SAndroid Build Coastguard Worker if (vals[i] > giga)
374*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%7lluM ", vals[i]/mega);
375*de1e4e89SAndroid Build Coastguard Worker else if (vals[i] > mega)
376*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%7lluK ", vals[i]/kilo);
377*de1e4e89SAndroid Build Coastguard Worker else
378*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8llu ", vals[i]);
379*de1e4e89SAndroid Build Coastguard Worker
380*de1e4e89SAndroid Build Coastguard Worker if (rates[i] > mega) {
381*de1e4e89SAndroid Build Coastguard Worker sprintf(temp, "%uM", (unsigned int)(rates[i]/mega));
382*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-6s ", temp);
383*de1e4e89SAndroid Build Coastguard Worker } else if (rates[i] > kilo) {
384*de1e4e89SAndroid Build Coastguard Worker sprintf(temp, "%uK", (unsigned int)(rates[i]/kilo));
385*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-6s ", temp);
386*de1e4e89SAndroid Build Coastguard Worker } else
387*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-6u ", (unsigned int)rates[i]);
388*de1e4e89SAndroid Build Coastguard Worker }
389*de1e4e89SAndroid Build Coastguard Worker
format_pair(FILE * fp,const unsigned long long * vals,int i,int k)390*de1e4e89SAndroid Build Coastguard Worker static void format_pair(FILE *fp, const unsigned long long *vals, int i, int k)
391*de1e4e89SAndroid Build Coastguard Worker {
392*de1e4e89SAndroid Build Coastguard Worker char temp[64];
393*de1e4e89SAndroid Build Coastguard Worker
394*de1e4e89SAndroid Build Coastguard Worker if (vals[i] > giga)
395*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%7lluM ", vals[i]/mega);
396*de1e4e89SAndroid Build Coastguard Worker else if (vals[i] > mega)
397*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%7lluK ", vals[i]/kilo);
398*de1e4e89SAndroid Build Coastguard Worker else
399*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8llu ", vals[i]);
400*de1e4e89SAndroid Build Coastguard Worker
401*de1e4e89SAndroid Build Coastguard Worker if (vals[k] > giga) {
402*de1e4e89SAndroid Build Coastguard Worker sprintf(temp, "%uM", (unsigned int)(vals[k]/mega));
403*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-6s ", temp);
404*de1e4e89SAndroid Build Coastguard Worker } else if (vals[k] > mega) {
405*de1e4e89SAndroid Build Coastguard Worker sprintf(temp, "%uK", (unsigned int)(vals[k]/kilo));
406*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-6s ", temp);
407*de1e4e89SAndroid Build Coastguard Worker } else
408*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-6u ", (unsigned int)vals[k]);
409*de1e4e89SAndroid Build Coastguard Worker }
410*de1e4e89SAndroid Build Coastguard Worker
print_head(FILE * fp)411*de1e4e89SAndroid Build Coastguard Worker static void print_head(FILE *fp)
412*de1e4e89SAndroid Build Coastguard Worker {
413*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "#%s\n", info_source);
414*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-15s ", "Interface");
415*de1e4e89SAndroid Build Coastguard Worker
416*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "RX Pkts", "Rate");
417*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "TX Pkts", "Rate");
418*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "RX Data", "Rate");
419*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s\n", "TX Data", "Rate");
420*de1e4e89SAndroid Build Coastguard Worker
421*de1e4e89SAndroid Build Coastguard Worker if (!show_errors) {
422*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-15s ", "");
423*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "RX Errs", "Drop");
424*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "TX Errs", "Drop");
425*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "RX Over", "Rate");
426*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s\n", "TX Coll", "Rate");
427*de1e4e89SAndroid Build Coastguard Worker } else {
428*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-15s ", "");
429*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "RX Errs", "Rate");
430*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "RX Drop", "Rate");
431*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "RX Over", "Rate");
432*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s\n", "RX Leng", "Rate");
433*de1e4e89SAndroid Build Coastguard Worker
434*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-15s ", "");
435*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "RX Crc", "Rate");
436*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "RX Frm", "Rate");
437*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "RX Fifo", "Rate");
438*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s\n", "RX Miss", "Rate");
439*de1e4e89SAndroid Build Coastguard Worker
440*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-15s ", "");
441*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "TX Errs", "Rate");
442*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "TX Drop", "Rate");
443*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "TX Coll", "Rate");
444*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s\n", "TX Carr", "Rate");
445*de1e4e89SAndroid Build Coastguard Worker
446*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-15s ", "");
447*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "TX Abrt", "Rate");
448*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "TX Fifo", "Rate");
449*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s ", "TX Hear", "Rate");
450*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%8s/%-6s\n", "TX Wind", "Rate");
451*de1e4e89SAndroid Build Coastguard Worker }
452*de1e4e89SAndroid Build Coastguard Worker }
453*de1e4e89SAndroid Build Coastguard Worker
print_one_json(json_writer_t * jw,const struct ifstat_ent * n,const unsigned long long * vals)454*de1e4e89SAndroid Build Coastguard Worker static void print_one_json(json_writer_t *jw, const struct ifstat_ent *n,
455*de1e4e89SAndroid Build Coastguard Worker const unsigned long long *vals)
456*de1e4e89SAndroid Build Coastguard Worker {
457*de1e4e89SAndroid Build Coastguard Worker int i, m = show_errors ? 20 : 10;
458*de1e4e89SAndroid Build Coastguard Worker
459*de1e4e89SAndroid Build Coastguard Worker jsonw_name(jw, n->name);
460*de1e4e89SAndroid Build Coastguard Worker jsonw_start_object(jw);
461*de1e4e89SAndroid Build Coastguard Worker
462*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < m && stats[i]; i++)
463*de1e4e89SAndroid Build Coastguard Worker jsonw_uint_field(jw, stats[i], vals[i]);
464*de1e4e89SAndroid Build Coastguard Worker
465*de1e4e89SAndroid Build Coastguard Worker jsonw_end_object(jw);
466*de1e4e89SAndroid Build Coastguard Worker }
467*de1e4e89SAndroid Build Coastguard Worker
print_one_if(FILE * fp,const struct ifstat_ent * n,const unsigned long long * vals)468*de1e4e89SAndroid Build Coastguard Worker static void print_one_if(FILE *fp, const struct ifstat_ent *n,
469*de1e4e89SAndroid Build Coastguard Worker const unsigned long long *vals)
470*de1e4e89SAndroid Build Coastguard Worker {
471*de1e4e89SAndroid Build Coastguard Worker int i;
472*de1e4e89SAndroid Build Coastguard Worker
473*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-15s ", n->name);
474*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < 4; i++)
475*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, i);
476*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "\n");
477*de1e4e89SAndroid Build Coastguard Worker
478*de1e4e89SAndroid Build Coastguard Worker if (!show_errors) {
479*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-15s ", "");
480*de1e4e89SAndroid Build Coastguard Worker format_pair(fp, vals, 4, 6);
481*de1e4e89SAndroid Build Coastguard Worker format_pair(fp, vals, 5, 7);
482*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 11);
483*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 9);
484*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "\n");
485*de1e4e89SAndroid Build Coastguard Worker } else {
486*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-15s ", "");
487*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 4);
488*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 6);
489*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 11);
490*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 10);
491*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "\n");
492*de1e4e89SAndroid Build Coastguard Worker
493*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-15s ", "");
494*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 12);
495*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 13);
496*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 14);
497*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 15);
498*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "\n");
499*de1e4e89SAndroid Build Coastguard Worker
500*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-15s ", "");
501*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 5);
502*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 7);
503*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 9);
504*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 17);
505*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "\n");
506*de1e4e89SAndroid Build Coastguard Worker
507*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-15s ", "");
508*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 16);
509*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 18);
510*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 19);
511*de1e4e89SAndroid Build Coastguard Worker format_rate(fp, vals, n->rate, 20);
512*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "\n");
513*de1e4e89SAndroid Build Coastguard Worker }
514*de1e4e89SAndroid Build Coastguard Worker }
515*de1e4e89SAndroid Build Coastguard Worker
dump_kern_db(FILE * fp)516*de1e4e89SAndroid Build Coastguard Worker static void dump_kern_db(FILE *fp)
517*de1e4e89SAndroid Build Coastguard Worker {
518*de1e4e89SAndroid Build Coastguard Worker json_writer_t *jw = json_output ? jsonw_new(fp) : NULL;
519*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *n;
520*de1e4e89SAndroid Build Coastguard Worker
521*de1e4e89SAndroid Build Coastguard Worker if (jw) {
522*de1e4e89SAndroid Build Coastguard Worker jsonw_start_object(jw);
523*de1e4e89SAndroid Build Coastguard Worker jsonw_pretty(jw, pretty);
524*de1e4e89SAndroid Build Coastguard Worker jsonw_name(jw, info_source);
525*de1e4e89SAndroid Build Coastguard Worker jsonw_start_object(jw);
526*de1e4e89SAndroid Build Coastguard Worker } else
527*de1e4e89SAndroid Build Coastguard Worker print_head(fp);
528*de1e4e89SAndroid Build Coastguard Worker
529*de1e4e89SAndroid Build Coastguard Worker for (n = kern_db; n; n = n->next) {
530*de1e4e89SAndroid Build Coastguard Worker if (!match(n->name))
531*de1e4e89SAndroid Build Coastguard Worker continue;
532*de1e4e89SAndroid Build Coastguard Worker
533*de1e4e89SAndroid Build Coastguard Worker if (jw)
534*de1e4e89SAndroid Build Coastguard Worker print_one_json(jw, n, n->val);
535*de1e4e89SAndroid Build Coastguard Worker else
536*de1e4e89SAndroid Build Coastguard Worker print_one_if(fp, n, n->val);
537*de1e4e89SAndroid Build Coastguard Worker }
538*de1e4e89SAndroid Build Coastguard Worker if (jw) {
539*de1e4e89SAndroid Build Coastguard Worker jsonw_end_object(jw);
540*de1e4e89SAndroid Build Coastguard Worker
541*de1e4e89SAndroid Build Coastguard Worker jsonw_end_object(jw);
542*de1e4e89SAndroid Build Coastguard Worker jsonw_destroy(&jw);
543*de1e4e89SAndroid Build Coastguard Worker }
544*de1e4e89SAndroid Build Coastguard Worker }
545*de1e4e89SAndroid Build Coastguard Worker
dump_incr_db(FILE * fp)546*de1e4e89SAndroid Build Coastguard Worker static void dump_incr_db(FILE *fp)
547*de1e4e89SAndroid Build Coastguard Worker {
548*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *n, *h;
549*de1e4e89SAndroid Build Coastguard Worker json_writer_t *jw = json_output ? jsonw_new(fp) : NULL;
550*de1e4e89SAndroid Build Coastguard Worker
551*de1e4e89SAndroid Build Coastguard Worker h = hist_db;
552*de1e4e89SAndroid Build Coastguard Worker if (jw) {
553*de1e4e89SAndroid Build Coastguard Worker jsonw_start_object(jw);
554*de1e4e89SAndroid Build Coastguard Worker jsonw_pretty(jw, pretty);
555*de1e4e89SAndroid Build Coastguard Worker jsonw_name(jw, info_source);
556*de1e4e89SAndroid Build Coastguard Worker jsonw_start_object(jw);
557*de1e4e89SAndroid Build Coastguard Worker } else
558*de1e4e89SAndroid Build Coastguard Worker print_head(fp);
559*de1e4e89SAndroid Build Coastguard Worker
560*de1e4e89SAndroid Build Coastguard Worker for (n = kern_db; n; n = n->next) {
561*de1e4e89SAndroid Build Coastguard Worker int i;
562*de1e4e89SAndroid Build Coastguard Worker unsigned long long vals[MAXS];
563*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *h1;
564*de1e4e89SAndroid Build Coastguard Worker
565*de1e4e89SAndroid Build Coastguard Worker memcpy(vals, n->val, sizeof(vals));
566*de1e4e89SAndroid Build Coastguard Worker
567*de1e4e89SAndroid Build Coastguard Worker for (h1 = h; h1; h1 = h1->next) {
568*de1e4e89SAndroid Build Coastguard Worker if (h1->ifindex == n->ifindex) {
569*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < MAXS; i++)
570*de1e4e89SAndroid Build Coastguard Worker vals[i] -= h1->val[i];
571*de1e4e89SAndroid Build Coastguard Worker h = h1->next;
572*de1e4e89SAndroid Build Coastguard Worker break;
573*de1e4e89SAndroid Build Coastguard Worker }
574*de1e4e89SAndroid Build Coastguard Worker }
575*de1e4e89SAndroid Build Coastguard Worker if (!match(n->name))
576*de1e4e89SAndroid Build Coastguard Worker continue;
577*de1e4e89SAndroid Build Coastguard Worker
578*de1e4e89SAndroid Build Coastguard Worker if (jw)
579*de1e4e89SAndroid Build Coastguard Worker print_one_json(jw, n, n->val);
580*de1e4e89SAndroid Build Coastguard Worker else
581*de1e4e89SAndroid Build Coastguard Worker print_one_if(fp, n, vals);
582*de1e4e89SAndroid Build Coastguard Worker }
583*de1e4e89SAndroid Build Coastguard Worker
584*de1e4e89SAndroid Build Coastguard Worker if (jw) {
585*de1e4e89SAndroid Build Coastguard Worker jsonw_end_object(jw);
586*de1e4e89SAndroid Build Coastguard Worker
587*de1e4e89SAndroid Build Coastguard Worker jsonw_end_object(jw);
588*de1e4e89SAndroid Build Coastguard Worker jsonw_destroy(&jw);
589*de1e4e89SAndroid Build Coastguard Worker }
590*de1e4e89SAndroid Build Coastguard Worker }
591*de1e4e89SAndroid Build Coastguard Worker
592*de1e4e89SAndroid Build Coastguard Worker static int children;
593*de1e4e89SAndroid Build Coastguard Worker
sigchild(int signo)594*de1e4e89SAndroid Build Coastguard Worker static void sigchild(int signo)
595*de1e4e89SAndroid Build Coastguard Worker {
596*de1e4e89SAndroid Build Coastguard Worker }
597*de1e4e89SAndroid Build Coastguard Worker
update_db(int interval)598*de1e4e89SAndroid Build Coastguard Worker static void update_db(int interval)
599*de1e4e89SAndroid Build Coastguard Worker {
600*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *n, *h;
601*de1e4e89SAndroid Build Coastguard Worker
602*de1e4e89SAndroid Build Coastguard Worker n = kern_db;
603*de1e4e89SAndroid Build Coastguard Worker kern_db = NULL;
604*de1e4e89SAndroid Build Coastguard Worker
605*de1e4e89SAndroid Build Coastguard Worker load_info();
606*de1e4e89SAndroid Build Coastguard Worker
607*de1e4e89SAndroid Build Coastguard Worker h = kern_db;
608*de1e4e89SAndroid Build Coastguard Worker kern_db = n;
609*de1e4e89SAndroid Build Coastguard Worker
610*de1e4e89SAndroid Build Coastguard Worker for (n = kern_db; n; n = n->next) {
611*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *h1;
612*de1e4e89SAndroid Build Coastguard Worker
613*de1e4e89SAndroid Build Coastguard Worker for (h1 = h; h1; h1 = h1->next) {
614*de1e4e89SAndroid Build Coastguard Worker if (h1->ifindex == n->ifindex) {
615*de1e4e89SAndroid Build Coastguard Worker int i;
616*de1e4e89SAndroid Build Coastguard Worker
617*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < MAXS; i++) {
618*de1e4e89SAndroid Build Coastguard Worker if ((long)(h1->ival[i] - n->ival[i]) < 0) {
619*de1e4e89SAndroid Build Coastguard Worker memset(n->ival, 0, sizeof(n->ival));
620*de1e4e89SAndroid Build Coastguard Worker break;
621*de1e4e89SAndroid Build Coastguard Worker }
622*de1e4e89SAndroid Build Coastguard Worker }
623*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < MAXS; i++) {
624*de1e4e89SAndroid Build Coastguard Worker double sample;
625*de1e4e89SAndroid Build Coastguard Worker __u64 incr;
626*de1e4e89SAndroid Build Coastguard Worker
627*de1e4e89SAndroid Build Coastguard Worker if (is_extended) {
628*de1e4e89SAndroid Build Coastguard Worker incr = h1->val[i] - n->val[i];
629*de1e4e89SAndroid Build Coastguard Worker n->val[i] = h1->val[i];
630*de1e4e89SAndroid Build Coastguard Worker } else {
631*de1e4e89SAndroid Build Coastguard Worker incr = (__u32) (h1->ival[i] - n->ival[i]);
632*de1e4e89SAndroid Build Coastguard Worker n->val[i] += incr;
633*de1e4e89SAndroid Build Coastguard Worker n->ival[i] = h1->ival[i];
634*de1e4e89SAndroid Build Coastguard Worker }
635*de1e4e89SAndroid Build Coastguard Worker
636*de1e4e89SAndroid Build Coastguard Worker sample = (double)(incr*1000)/interval;
637*de1e4e89SAndroid Build Coastguard Worker if (interval >= scan_interval) {
638*de1e4e89SAndroid Build Coastguard Worker n->rate[i] += W*(sample-n->rate[i]);
639*de1e4e89SAndroid Build Coastguard Worker } else if (interval >= 1000) {
640*de1e4e89SAndroid Build Coastguard Worker if (interval >= time_constant) {
641*de1e4e89SAndroid Build Coastguard Worker n->rate[i] = sample;
642*de1e4e89SAndroid Build Coastguard Worker } else {
643*de1e4e89SAndroid Build Coastguard Worker double w = W*(double)interval/scan_interval;
644*de1e4e89SAndroid Build Coastguard Worker
645*de1e4e89SAndroid Build Coastguard Worker n->rate[i] += w*(sample-n->rate[i]);
646*de1e4e89SAndroid Build Coastguard Worker }
647*de1e4e89SAndroid Build Coastguard Worker }
648*de1e4e89SAndroid Build Coastguard Worker }
649*de1e4e89SAndroid Build Coastguard Worker
650*de1e4e89SAndroid Build Coastguard Worker while (h != h1) {
651*de1e4e89SAndroid Build Coastguard Worker struct ifstat_ent *tmp = h;
652*de1e4e89SAndroid Build Coastguard Worker
653*de1e4e89SAndroid Build Coastguard Worker h = h->next;
654*de1e4e89SAndroid Build Coastguard Worker free(tmp->name);
655*de1e4e89SAndroid Build Coastguard Worker free(tmp);
656*de1e4e89SAndroid Build Coastguard Worker };
657*de1e4e89SAndroid Build Coastguard Worker h = h1->next;
658*de1e4e89SAndroid Build Coastguard Worker free(h1->name);
659*de1e4e89SAndroid Build Coastguard Worker free(h1);
660*de1e4e89SAndroid Build Coastguard Worker break;
661*de1e4e89SAndroid Build Coastguard Worker }
662*de1e4e89SAndroid Build Coastguard Worker }
663*de1e4e89SAndroid Build Coastguard Worker }
664*de1e4e89SAndroid Build Coastguard Worker }
665*de1e4e89SAndroid Build Coastguard Worker
666*de1e4e89SAndroid Build Coastguard Worker #define T_DIFF(a, b) (((a).tv_sec-(b).tv_sec)*1000 + ((a).tv_usec-(b).tv_usec)/1000)
667*de1e4e89SAndroid Build Coastguard Worker
668*de1e4e89SAndroid Build Coastguard Worker
server_loop(int fd)669*de1e4e89SAndroid Build Coastguard Worker static void server_loop(int fd)
670*de1e4e89SAndroid Build Coastguard Worker {
671*de1e4e89SAndroid Build Coastguard Worker struct timeval snaptime = { 0 };
672*de1e4e89SAndroid Build Coastguard Worker struct pollfd p;
673*de1e4e89SAndroid Build Coastguard Worker
674*de1e4e89SAndroid Build Coastguard Worker p.fd = fd;
675*de1e4e89SAndroid Build Coastguard Worker p.events = p.revents = POLLIN;
676*de1e4e89SAndroid Build Coastguard Worker
677*de1e4e89SAndroid Build Coastguard Worker sprintf(info_source, "%d.%lu sampling_interval=%d time_const=%d",
678*de1e4e89SAndroid Build Coastguard Worker getpid(), (unsigned long)random(), scan_interval/1000, time_constant/1000);
679*de1e4e89SAndroid Build Coastguard Worker
680*de1e4e89SAndroid Build Coastguard Worker load_info();
681*de1e4e89SAndroid Build Coastguard Worker
682*de1e4e89SAndroid Build Coastguard Worker for (;;) {
683*de1e4e89SAndroid Build Coastguard Worker int status;
684*de1e4e89SAndroid Build Coastguard Worker time_t tdiff;
685*de1e4e89SAndroid Build Coastguard Worker struct timeval now;
686*de1e4e89SAndroid Build Coastguard Worker
687*de1e4e89SAndroid Build Coastguard Worker gettimeofday(&now, NULL);
688*de1e4e89SAndroid Build Coastguard Worker tdiff = T_DIFF(now, snaptime);
689*de1e4e89SAndroid Build Coastguard Worker if (tdiff >= scan_interval) {
690*de1e4e89SAndroid Build Coastguard Worker update_db(tdiff);
691*de1e4e89SAndroid Build Coastguard Worker snaptime = now;
692*de1e4e89SAndroid Build Coastguard Worker tdiff = 0;
693*de1e4e89SAndroid Build Coastguard Worker }
694*de1e4e89SAndroid Build Coastguard Worker
695*de1e4e89SAndroid Build Coastguard Worker if (poll(&p, 1, scan_interval - tdiff) > 0
696*de1e4e89SAndroid Build Coastguard Worker && (p.revents&POLLIN)) {
697*de1e4e89SAndroid Build Coastguard Worker int clnt = accept(fd, NULL, NULL);
698*de1e4e89SAndroid Build Coastguard Worker
699*de1e4e89SAndroid Build Coastguard Worker if (clnt >= 0) {
700*de1e4e89SAndroid Build Coastguard Worker pid_t pid;
701*de1e4e89SAndroid Build Coastguard Worker
702*de1e4e89SAndroid Build Coastguard Worker if (children >= 5) {
703*de1e4e89SAndroid Build Coastguard Worker close(clnt);
704*de1e4e89SAndroid Build Coastguard Worker } else if ((pid = fork()) != 0) {
705*de1e4e89SAndroid Build Coastguard Worker if (pid > 0)
706*de1e4e89SAndroid Build Coastguard Worker children++;
707*de1e4e89SAndroid Build Coastguard Worker close(clnt);
708*de1e4e89SAndroid Build Coastguard Worker } else {
709*de1e4e89SAndroid Build Coastguard Worker FILE *fp = fdopen(clnt, "w");
710*de1e4e89SAndroid Build Coastguard Worker
711*de1e4e89SAndroid Build Coastguard Worker if (fp)
712*de1e4e89SAndroid Build Coastguard Worker dump_raw_db(fp, 0);
713*de1e4e89SAndroid Build Coastguard Worker exit(0);
714*de1e4e89SAndroid Build Coastguard Worker }
715*de1e4e89SAndroid Build Coastguard Worker }
716*de1e4e89SAndroid Build Coastguard Worker }
717*de1e4e89SAndroid Build Coastguard Worker while (children && waitpid(-1, &status, WNOHANG) > 0)
718*de1e4e89SAndroid Build Coastguard Worker children--;
719*de1e4e89SAndroid Build Coastguard Worker }
720*de1e4e89SAndroid Build Coastguard Worker }
721*de1e4e89SAndroid Build Coastguard Worker
verify_forging(int fd)722*de1e4e89SAndroid Build Coastguard Worker static int verify_forging(int fd)
723*de1e4e89SAndroid Build Coastguard Worker {
724*de1e4e89SAndroid Build Coastguard Worker struct ucred cred;
725*de1e4e89SAndroid Build Coastguard Worker socklen_t olen = sizeof(cred);
726*de1e4e89SAndroid Build Coastguard Worker
727*de1e4e89SAndroid Build Coastguard Worker if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &olen) ||
728*de1e4e89SAndroid Build Coastguard Worker olen < sizeof(cred))
729*de1e4e89SAndroid Build Coastguard Worker return -1;
730*de1e4e89SAndroid Build Coastguard Worker if (cred.uid == getuid() || cred.uid == 0)
731*de1e4e89SAndroid Build Coastguard Worker return 0;
732*de1e4e89SAndroid Build Coastguard Worker return -1;
733*de1e4e89SAndroid Build Coastguard Worker }
734*de1e4e89SAndroid Build Coastguard Worker
xstat_usage(void)735*de1e4e89SAndroid Build Coastguard Worker static void xstat_usage(void)
736*de1e4e89SAndroid Build Coastguard Worker {
737*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
738*de1e4e89SAndroid Build Coastguard Worker "Usage: ifstat supported xstats:\n"
739*de1e4e89SAndroid Build Coastguard Worker " cpu_hits Counts only packets that went via the CPU.\n");
740*de1e4e89SAndroid Build Coastguard Worker }
741*de1e4e89SAndroid Build Coastguard Worker
742*de1e4e89SAndroid Build Coastguard Worker struct extended_stats_options_t {
743*de1e4e89SAndroid Build Coastguard Worker char *name;
744*de1e4e89SAndroid Build Coastguard Worker int id;
745*de1e4e89SAndroid Build Coastguard Worker int sub_type;
746*de1e4e89SAndroid Build Coastguard Worker };
747*de1e4e89SAndroid Build Coastguard Worker
748*de1e4e89SAndroid Build Coastguard Worker /* Note: if one xstat name is subset of another, it should be before it in this
749*de1e4e89SAndroid Build Coastguard Worker * list.
750*de1e4e89SAndroid Build Coastguard Worker * Name length must be under 64 chars.
751*de1e4e89SAndroid Build Coastguard Worker */
752*de1e4e89SAndroid Build Coastguard Worker static const struct extended_stats_options_t extended_stats_options[] = {
753*de1e4e89SAndroid Build Coastguard Worker {"cpu_hits", IFLA_STATS_LINK_OFFLOAD_XSTATS, IFLA_OFFLOAD_XSTATS_CPU_HIT},
754*de1e4e89SAndroid Build Coastguard Worker };
755*de1e4e89SAndroid Build Coastguard Worker
get_filter_type(const char * name)756*de1e4e89SAndroid Build Coastguard Worker static const char *get_filter_type(const char *name)
757*de1e4e89SAndroid Build Coastguard Worker {
758*de1e4e89SAndroid Build Coastguard Worker int name_len;
759*de1e4e89SAndroid Build Coastguard Worker int i;
760*de1e4e89SAndroid Build Coastguard Worker
761*de1e4e89SAndroid Build Coastguard Worker name_len = strlen(name);
762*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(extended_stats_options); i++) {
763*de1e4e89SAndroid Build Coastguard Worker const struct extended_stats_options_t *xstat;
764*de1e4e89SAndroid Build Coastguard Worker
765*de1e4e89SAndroid Build Coastguard Worker xstat = &extended_stats_options[i];
766*de1e4e89SAndroid Build Coastguard Worker if (strncmp(name, xstat->name, name_len) == 0) {
767*de1e4e89SAndroid Build Coastguard Worker filter_type = xstat->id;
768*de1e4e89SAndroid Build Coastguard Worker sub_type = xstat->sub_type;
769*de1e4e89SAndroid Build Coastguard Worker return xstat->name;
770*de1e4e89SAndroid Build Coastguard Worker }
771*de1e4e89SAndroid Build Coastguard Worker }
772*de1e4e89SAndroid Build Coastguard Worker
773*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "invalid ifstat extension %s\n", name);
774*de1e4e89SAndroid Build Coastguard Worker xstat_usage();
775*de1e4e89SAndroid Build Coastguard Worker return NULL;
776*de1e4e89SAndroid Build Coastguard Worker }
777*de1e4e89SAndroid Build Coastguard Worker
778*de1e4e89SAndroid Build Coastguard Worker static void usage(void) __attribute__((noreturn));
779*de1e4e89SAndroid Build Coastguard Worker
usage(void)780*de1e4e89SAndroid Build Coastguard Worker static void usage(void)
781*de1e4e89SAndroid Build Coastguard Worker {
782*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
783*de1e4e89SAndroid Build Coastguard Worker "Usage: ifstat [OPTION] [ PATTERN [ PATTERN ] ]\n"
784*de1e4e89SAndroid Build Coastguard Worker " -h, --help this message\n"
785*de1e4e89SAndroid Build Coastguard Worker " -a, --ignore ignore history\n"
786*de1e4e89SAndroid Build Coastguard Worker " -d, --scan=SECS sample every statistics every SECS\n"
787*de1e4e89SAndroid Build Coastguard Worker " -e, --errors show errors\n"
788*de1e4e89SAndroid Build Coastguard Worker " -j, --json format output in JSON\n"
789*de1e4e89SAndroid Build Coastguard Worker " -n, --nooutput do history only\n"
790*de1e4e89SAndroid Build Coastguard Worker " -p, --pretty pretty print\n"
791*de1e4e89SAndroid Build Coastguard Worker " -r, --reset reset history\n"
792*de1e4e89SAndroid Build Coastguard Worker " -s, --noupdate don't update history\n"
793*de1e4e89SAndroid Build Coastguard Worker " -t, --interval=SECS report average over the last SECS\n"
794*de1e4e89SAndroid Build Coastguard Worker " -V, --version output version information\n"
795*de1e4e89SAndroid Build Coastguard Worker " -z, --zeros show entries with zero activity\n"
796*de1e4e89SAndroid Build Coastguard Worker " -x, --extended=TYPE show extended stats of TYPE\n");
797*de1e4e89SAndroid Build Coastguard Worker
798*de1e4e89SAndroid Build Coastguard Worker exit(-1);
799*de1e4e89SAndroid Build Coastguard Worker }
800*de1e4e89SAndroid Build Coastguard Worker
801*de1e4e89SAndroid Build Coastguard Worker static const struct option longopts[] = {
802*de1e4e89SAndroid Build Coastguard Worker { "help", 0, 0, 'h' },
803*de1e4e89SAndroid Build Coastguard Worker { "ignore", 0, 0, 'a' },
804*de1e4e89SAndroid Build Coastguard Worker { "scan", 1, 0, 'd'},
805*de1e4e89SAndroid Build Coastguard Worker { "errors", 0, 0, 'e' },
806*de1e4e89SAndroid Build Coastguard Worker { "nooutput", 0, 0, 'n' },
807*de1e4e89SAndroid Build Coastguard Worker { "json", 0, 0, 'j' },
808*de1e4e89SAndroid Build Coastguard Worker { "reset", 0, 0, 'r' },
809*de1e4e89SAndroid Build Coastguard Worker { "pretty", 0, 0, 'p' },
810*de1e4e89SAndroid Build Coastguard Worker { "noupdate", 0, 0, 's' },
811*de1e4e89SAndroid Build Coastguard Worker { "interval", 1, 0, 't' },
812*de1e4e89SAndroid Build Coastguard Worker { "version", 0, 0, 'V' },
813*de1e4e89SAndroid Build Coastguard Worker { "zeros", 0, 0, 'z' },
814*de1e4e89SAndroid Build Coastguard Worker { "extended", 1, 0, 'x'},
815*de1e4e89SAndroid Build Coastguard Worker { 0 }
816*de1e4e89SAndroid Build Coastguard Worker };
817*de1e4e89SAndroid Build Coastguard Worker
main(int argc,char * argv[])818*de1e4e89SAndroid Build Coastguard Worker int main(int argc, char *argv[])
819*de1e4e89SAndroid Build Coastguard Worker {
820*de1e4e89SAndroid Build Coastguard Worker char hist_name[128];
821*de1e4e89SAndroid Build Coastguard Worker struct sockaddr_un sun;
822*de1e4e89SAndroid Build Coastguard Worker FILE *hist_fp = NULL;
823*de1e4e89SAndroid Build Coastguard Worker const char *stats_type = NULL;
824*de1e4e89SAndroid Build Coastguard Worker int ch;
825*de1e4e89SAndroid Build Coastguard Worker int fd;
826*de1e4e89SAndroid Build Coastguard Worker
827*de1e4e89SAndroid Build Coastguard Worker is_extended = false;
828*de1e4e89SAndroid Build Coastguard Worker while ((ch = getopt_long(argc, argv, "hjpvVzrnasd:t:ex:",
829*de1e4e89SAndroid Build Coastguard Worker longopts, NULL)) != EOF) {
830*de1e4e89SAndroid Build Coastguard Worker switch (ch) {
831*de1e4e89SAndroid Build Coastguard Worker case 'z':
832*de1e4e89SAndroid Build Coastguard Worker dump_zeros = 1;
833*de1e4e89SAndroid Build Coastguard Worker break;
834*de1e4e89SAndroid Build Coastguard Worker case 'r':
835*de1e4e89SAndroid Build Coastguard Worker reset_history = 1;
836*de1e4e89SAndroid Build Coastguard Worker break;
837*de1e4e89SAndroid Build Coastguard Worker case 'a':
838*de1e4e89SAndroid Build Coastguard Worker ignore_history = 1;
839*de1e4e89SAndroid Build Coastguard Worker break;
840*de1e4e89SAndroid Build Coastguard Worker case 's':
841*de1e4e89SAndroid Build Coastguard Worker no_update = 1;
842*de1e4e89SAndroid Build Coastguard Worker break;
843*de1e4e89SAndroid Build Coastguard Worker case 'n':
844*de1e4e89SAndroid Build Coastguard Worker no_output = 1;
845*de1e4e89SAndroid Build Coastguard Worker break;
846*de1e4e89SAndroid Build Coastguard Worker case 'e':
847*de1e4e89SAndroid Build Coastguard Worker show_errors = 1;
848*de1e4e89SAndroid Build Coastguard Worker break;
849*de1e4e89SAndroid Build Coastguard Worker case 'j':
850*de1e4e89SAndroid Build Coastguard Worker json_output = 1;
851*de1e4e89SAndroid Build Coastguard Worker break;
852*de1e4e89SAndroid Build Coastguard Worker case 'p':
853*de1e4e89SAndroid Build Coastguard Worker pretty = 1;
854*de1e4e89SAndroid Build Coastguard Worker break;
855*de1e4e89SAndroid Build Coastguard Worker case 'd':
856*de1e4e89SAndroid Build Coastguard Worker scan_interval = atoi(optarg) * 1000;
857*de1e4e89SAndroid Build Coastguard Worker if (scan_interval <= 0) {
858*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ifstat: invalid scan interval\n");
859*de1e4e89SAndroid Build Coastguard Worker exit(-1);
860*de1e4e89SAndroid Build Coastguard Worker }
861*de1e4e89SAndroid Build Coastguard Worker break;
862*de1e4e89SAndroid Build Coastguard Worker case 't':
863*de1e4e89SAndroid Build Coastguard Worker time_constant = atoi(optarg);
864*de1e4e89SAndroid Build Coastguard Worker if (time_constant <= 0) {
865*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ifstat: invalid time constant divisor\n");
866*de1e4e89SAndroid Build Coastguard Worker exit(-1);
867*de1e4e89SAndroid Build Coastguard Worker }
868*de1e4e89SAndroid Build Coastguard Worker break;
869*de1e4e89SAndroid Build Coastguard Worker case 'x':
870*de1e4e89SAndroid Build Coastguard Worker stats_type = optarg;
871*de1e4e89SAndroid Build Coastguard Worker is_extended = true;
872*de1e4e89SAndroid Build Coastguard Worker break;
873*de1e4e89SAndroid Build Coastguard Worker case 'v':
874*de1e4e89SAndroid Build Coastguard Worker case 'V':
875*de1e4e89SAndroid Build Coastguard Worker printf("ifstat utility, iproute2-ss%s\n", SNAPSHOT);
876*de1e4e89SAndroid Build Coastguard Worker exit(0);
877*de1e4e89SAndroid Build Coastguard Worker case 'h':
878*de1e4e89SAndroid Build Coastguard Worker case '?':
879*de1e4e89SAndroid Build Coastguard Worker default:
880*de1e4e89SAndroid Build Coastguard Worker usage();
881*de1e4e89SAndroid Build Coastguard Worker }
882*de1e4e89SAndroid Build Coastguard Worker }
883*de1e4e89SAndroid Build Coastguard Worker
884*de1e4e89SAndroid Build Coastguard Worker argc -= optind;
885*de1e4e89SAndroid Build Coastguard Worker argv += optind;
886*de1e4e89SAndroid Build Coastguard Worker
887*de1e4e89SAndroid Build Coastguard Worker if (stats_type) {
888*de1e4e89SAndroid Build Coastguard Worker stats_type = get_filter_type(stats_type);
889*de1e4e89SAndroid Build Coastguard Worker if (!stats_type)
890*de1e4e89SAndroid Build Coastguard Worker exit(-1);
891*de1e4e89SAndroid Build Coastguard Worker }
892*de1e4e89SAndroid Build Coastguard Worker
893*de1e4e89SAndroid Build Coastguard Worker sun.sun_family = AF_UNIX;
894*de1e4e89SAndroid Build Coastguard Worker sun.sun_path[0] = 0;
895*de1e4e89SAndroid Build Coastguard Worker sprintf(sun.sun_path+1, "ifstat%d", getuid());
896*de1e4e89SAndroid Build Coastguard Worker
897*de1e4e89SAndroid Build Coastguard Worker if (scan_interval > 0) {
898*de1e4e89SAndroid Build Coastguard Worker if (time_constant == 0)
899*de1e4e89SAndroid Build Coastguard Worker time_constant = 60;
900*de1e4e89SAndroid Build Coastguard Worker time_constant *= 1000;
901*de1e4e89SAndroid Build Coastguard Worker W = 1 - 1/exp(log(10)*(double)scan_interval/time_constant);
902*de1e4e89SAndroid Build Coastguard Worker if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
903*de1e4e89SAndroid Build Coastguard Worker perror("ifstat: socket");
904*de1e4e89SAndroid Build Coastguard Worker exit(-1);
905*de1e4e89SAndroid Build Coastguard Worker }
906*de1e4e89SAndroid Build Coastguard Worker if (bind(fd, (struct sockaddr *)&sun, 2+1+strlen(sun.sun_path+1)) < 0) {
907*de1e4e89SAndroid Build Coastguard Worker perror("ifstat: bind");
908*de1e4e89SAndroid Build Coastguard Worker exit(-1);
909*de1e4e89SAndroid Build Coastguard Worker }
910*de1e4e89SAndroid Build Coastguard Worker if (listen(fd, 5) < 0) {
911*de1e4e89SAndroid Build Coastguard Worker perror("ifstat: listen");
912*de1e4e89SAndroid Build Coastguard Worker exit(-1);
913*de1e4e89SAndroid Build Coastguard Worker }
914*de1e4e89SAndroid Build Coastguard Worker if (daemon(0, 0)) {
915*de1e4e89SAndroid Build Coastguard Worker perror("ifstat: daemon");
916*de1e4e89SAndroid Build Coastguard Worker exit(-1);
917*de1e4e89SAndroid Build Coastguard Worker }
918*de1e4e89SAndroid Build Coastguard Worker signal(SIGPIPE, SIG_IGN);
919*de1e4e89SAndroid Build Coastguard Worker signal(SIGCHLD, sigchild);
920*de1e4e89SAndroid Build Coastguard Worker server_loop(fd);
921*de1e4e89SAndroid Build Coastguard Worker exit(0);
922*de1e4e89SAndroid Build Coastguard Worker }
923*de1e4e89SAndroid Build Coastguard Worker
924*de1e4e89SAndroid Build Coastguard Worker patterns = argv;
925*de1e4e89SAndroid Build Coastguard Worker npatterns = argc;
926*de1e4e89SAndroid Build Coastguard Worker
927*de1e4e89SAndroid Build Coastguard Worker if (getenv("IFSTAT_HISTORY"))
928*de1e4e89SAndroid Build Coastguard Worker snprintf(hist_name, sizeof(hist_name),
929*de1e4e89SAndroid Build Coastguard Worker "%s", getenv("IFSTAT_HISTORY"));
930*de1e4e89SAndroid Build Coastguard Worker else
931*de1e4e89SAndroid Build Coastguard Worker if (!stats_type)
932*de1e4e89SAndroid Build Coastguard Worker snprintf(hist_name, sizeof(hist_name),
933*de1e4e89SAndroid Build Coastguard Worker "%s/.ifstat.u%d", P_tmpdir, getuid());
934*de1e4e89SAndroid Build Coastguard Worker else
935*de1e4e89SAndroid Build Coastguard Worker snprintf(hist_name, sizeof(hist_name),
936*de1e4e89SAndroid Build Coastguard Worker "%s/.%s_ifstat.u%d", P_tmpdir, stats_type,
937*de1e4e89SAndroid Build Coastguard Worker getuid());
938*de1e4e89SAndroid Build Coastguard Worker
939*de1e4e89SAndroid Build Coastguard Worker if (reset_history)
940*de1e4e89SAndroid Build Coastguard Worker unlink(hist_name);
941*de1e4e89SAndroid Build Coastguard Worker
942*de1e4e89SAndroid Build Coastguard Worker if (!ignore_history || !no_update) {
943*de1e4e89SAndroid Build Coastguard Worker struct stat stb;
944*de1e4e89SAndroid Build Coastguard Worker
945*de1e4e89SAndroid Build Coastguard Worker fd = open(hist_name, O_RDWR|O_CREAT|O_NOFOLLOW, 0600);
946*de1e4e89SAndroid Build Coastguard Worker if (fd < 0) {
947*de1e4e89SAndroid Build Coastguard Worker perror("ifstat: open history file");
948*de1e4e89SAndroid Build Coastguard Worker exit(-1);
949*de1e4e89SAndroid Build Coastguard Worker }
950*de1e4e89SAndroid Build Coastguard Worker if ((hist_fp = fdopen(fd, "r+")) == NULL) {
951*de1e4e89SAndroid Build Coastguard Worker perror("ifstat: fdopen history file");
952*de1e4e89SAndroid Build Coastguard Worker exit(-1);
953*de1e4e89SAndroid Build Coastguard Worker }
954*de1e4e89SAndroid Build Coastguard Worker if (flock(fileno(hist_fp), LOCK_EX)) {
955*de1e4e89SAndroid Build Coastguard Worker perror("ifstat: flock history file");
956*de1e4e89SAndroid Build Coastguard Worker exit(-1);
957*de1e4e89SAndroid Build Coastguard Worker }
958*de1e4e89SAndroid Build Coastguard Worker if (fstat(fileno(hist_fp), &stb) != 0) {
959*de1e4e89SAndroid Build Coastguard Worker perror("ifstat: fstat history file");
960*de1e4e89SAndroid Build Coastguard Worker exit(-1);
961*de1e4e89SAndroid Build Coastguard Worker }
962*de1e4e89SAndroid Build Coastguard Worker if (stb.st_nlink != 1 || stb.st_uid != getuid()) {
963*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ifstat: something is so wrong with history file, that I prefer not to proceed.\n");
964*de1e4e89SAndroid Build Coastguard Worker exit(-1);
965*de1e4e89SAndroid Build Coastguard Worker }
966*de1e4e89SAndroid Build Coastguard Worker if (!ignore_history) {
967*de1e4e89SAndroid Build Coastguard Worker FILE *tfp;
968*de1e4e89SAndroid Build Coastguard Worker long uptime = -1;
969*de1e4e89SAndroid Build Coastguard Worker
970*de1e4e89SAndroid Build Coastguard Worker if ((tfp = fopen("/proc/uptime", "r")) != NULL) {
971*de1e4e89SAndroid Build Coastguard Worker if (fscanf(tfp, "%ld", &uptime) != 1)
972*de1e4e89SAndroid Build Coastguard Worker uptime = -1;
973*de1e4e89SAndroid Build Coastguard Worker fclose(tfp);
974*de1e4e89SAndroid Build Coastguard Worker }
975*de1e4e89SAndroid Build Coastguard Worker if (uptime >= 0 && time(NULL) >= stb.st_mtime+uptime) {
976*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ifstat: history is aged out, resetting\n");
977*de1e4e89SAndroid Build Coastguard Worker if (ftruncate(fileno(hist_fp), 0))
978*de1e4e89SAndroid Build Coastguard Worker perror("ifstat: ftruncate");
979*de1e4e89SAndroid Build Coastguard Worker }
980*de1e4e89SAndroid Build Coastguard Worker }
981*de1e4e89SAndroid Build Coastguard Worker
982*de1e4e89SAndroid Build Coastguard Worker load_raw_table(hist_fp);
983*de1e4e89SAndroid Build Coastguard Worker
984*de1e4e89SAndroid Build Coastguard Worker hist_db = kern_db;
985*de1e4e89SAndroid Build Coastguard Worker kern_db = NULL;
986*de1e4e89SAndroid Build Coastguard Worker }
987*de1e4e89SAndroid Build Coastguard Worker
988*de1e4e89SAndroid Build Coastguard Worker if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0 &&
989*de1e4e89SAndroid Build Coastguard Worker (connect(fd, (struct sockaddr *)&sun, 2+1+strlen(sun.sun_path+1)) == 0
990*de1e4e89SAndroid Build Coastguard Worker || (strcpy(sun.sun_path+1, "ifstat0"),
991*de1e4e89SAndroid Build Coastguard Worker connect(fd, (struct sockaddr *)&sun, 2+1+strlen(sun.sun_path+1)) == 0))
992*de1e4e89SAndroid Build Coastguard Worker && verify_forging(fd) == 0) {
993*de1e4e89SAndroid Build Coastguard Worker FILE *sfp = fdopen(fd, "r");
994*de1e4e89SAndroid Build Coastguard Worker
995*de1e4e89SAndroid Build Coastguard Worker if (!sfp) {
996*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ifstat: fdopen failed: %s\n",
997*de1e4e89SAndroid Build Coastguard Worker strerror(errno));
998*de1e4e89SAndroid Build Coastguard Worker close(fd);
999*de1e4e89SAndroid Build Coastguard Worker } else {
1000*de1e4e89SAndroid Build Coastguard Worker load_raw_table(sfp);
1001*de1e4e89SAndroid Build Coastguard Worker if (hist_db && source_mismatch) {
1002*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ifstat: history is stale, ignoring it.\n");
1003*de1e4e89SAndroid Build Coastguard Worker hist_db = NULL;
1004*de1e4e89SAndroid Build Coastguard Worker }
1005*de1e4e89SAndroid Build Coastguard Worker fclose(sfp);
1006*de1e4e89SAndroid Build Coastguard Worker }
1007*de1e4e89SAndroid Build Coastguard Worker } else {
1008*de1e4e89SAndroid Build Coastguard Worker if (fd >= 0)
1009*de1e4e89SAndroid Build Coastguard Worker close(fd);
1010*de1e4e89SAndroid Build Coastguard Worker if (hist_db && info_source[0] && strcmp(info_source, "kernel")) {
1011*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ifstat: history is stale, ignoring it.\n");
1012*de1e4e89SAndroid Build Coastguard Worker hist_db = NULL;
1013*de1e4e89SAndroid Build Coastguard Worker info_source[0] = 0;
1014*de1e4e89SAndroid Build Coastguard Worker }
1015*de1e4e89SAndroid Build Coastguard Worker load_info();
1016*de1e4e89SAndroid Build Coastguard Worker if (info_source[0] == 0)
1017*de1e4e89SAndroid Build Coastguard Worker strcpy(info_source, "kernel");
1018*de1e4e89SAndroid Build Coastguard Worker }
1019*de1e4e89SAndroid Build Coastguard Worker
1020*de1e4e89SAndroid Build Coastguard Worker if (!no_output) {
1021*de1e4e89SAndroid Build Coastguard Worker if (ignore_history || hist_db == NULL)
1022*de1e4e89SAndroid Build Coastguard Worker dump_kern_db(stdout);
1023*de1e4e89SAndroid Build Coastguard Worker else
1024*de1e4e89SAndroid Build Coastguard Worker dump_incr_db(stdout);
1025*de1e4e89SAndroid Build Coastguard Worker }
1026*de1e4e89SAndroid Build Coastguard Worker
1027*de1e4e89SAndroid Build Coastguard Worker if (!no_update) {
1028*de1e4e89SAndroid Build Coastguard Worker if (ftruncate(fileno(hist_fp), 0))
1029*de1e4e89SAndroid Build Coastguard Worker perror("ifstat: ftruncate");
1030*de1e4e89SAndroid Build Coastguard Worker rewind(hist_fp);
1031*de1e4e89SAndroid Build Coastguard Worker
1032*de1e4e89SAndroid Build Coastguard Worker json_output = 0;
1033*de1e4e89SAndroid Build Coastguard Worker dump_raw_db(hist_fp, 1);
1034*de1e4e89SAndroid Build Coastguard Worker fclose(hist_fp);
1035*de1e4e89SAndroid Build Coastguard Worker }
1036*de1e4e89SAndroid Build Coastguard Worker exit(0);
1037*de1e4e89SAndroid Build Coastguard Worker }
1038