1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * nstat.c handy utility to read counters /proc/net/netstat and snmp
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 <json_writer.h>
32*de1e4e89SAndroid Build Coastguard Worker #include <SNAPSHOT.h>
33*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
34*de1e4e89SAndroid Build Coastguard Worker
35*de1e4e89SAndroid Build Coastguard Worker int dump_zeros;
36*de1e4e89SAndroid Build Coastguard Worker int reset_history;
37*de1e4e89SAndroid Build Coastguard Worker int ignore_history;
38*de1e4e89SAndroid Build Coastguard Worker int no_output;
39*de1e4e89SAndroid Build Coastguard Worker int json_output;
40*de1e4e89SAndroid Build Coastguard Worker int pretty;
41*de1e4e89SAndroid Build Coastguard Worker int no_update;
42*de1e4e89SAndroid Build Coastguard Worker int scan_interval;
43*de1e4e89SAndroid Build Coastguard Worker int time_constant;
44*de1e4e89SAndroid Build Coastguard Worker double W;
45*de1e4e89SAndroid Build Coastguard Worker char **patterns;
46*de1e4e89SAndroid Build Coastguard Worker int npatterns;
47*de1e4e89SAndroid Build Coastguard Worker
48*de1e4e89SAndroid Build Coastguard Worker char info_source[128];
49*de1e4e89SAndroid Build Coastguard Worker int source_mismatch;
50*de1e4e89SAndroid Build Coastguard Worker
generic_proc_open(const char * env,char * name)51*de1e4e89SAndroid Build Coastguard Worker static int generic_proc_open(const char *env, char *name)
52*de1e4e89SAndroid Build Coastguard Worker {
53*de1e4e89SAndroid Build Coastguard Worker char store[128];
54*de1e4e89SAndroid Build Coastguard Worker char *p = getenv(env);
55*de1e4e89SAndroid Build Coastguard Worker
56*de1e4e89SAndroid Build Coastguard Worker if (!p) {
57*de1e4e89SAndroid Build Coastguard Worker p = getenv("PROC_ROOT") ? : "/proc";
58*de1e4e89SAndroid Build Coastguard Worker snprintf(store, sizeof(store)-1, "%s/%s", p, name);
59*de1e4e89SAndroid Build Coastguard Worker p = store;
60*de1e4e89SAndroid Build Coastguard Worker }
61*de1e4e89SAndroid Build Coastguard Worker return open(p, O_RDONLY);
62*de1e4e89SAndroid Build Coastguard Worker }
63*de1e4e89SAndroid Build Coastguard Worker
net_netstat_open(void)64*de1e4e89SAndroid Build Coastguard Worker static int net_netstat_open(void)
65*de1e4e89SAndroid Build Coastguard Worker {
66*de1e4e89SAndroid Build Coastguard Worker return generic_proc_open("PROC_NET_NETSTAT", "net/netstat");
67*de1e4e89SAndroid Build Coastguard Worker }
68*de1e4e89SAndroid Build Coastguard Worker
net_snmp_open(void)69*de1e4e89SAndroid Build Coastguard Worker static int net_snmp_open(void)
70*de1e4e89SAndroid Build Coastguard Worker {
71*de1e4e89SAndroid Build Coastguard Worker return generic_proc_open("PROC_NET_SNMP", "net/snmp");
72*de1e4e89SAndroid Build Coastguard Worker }
73*de1e4e89SAndroid Build Coastguard Worker
net_snmp6_open(void)74*de1e4e89SAndroid Build Coastguard Worker static int net_snmp6_open(void)
75*de1e4e89SAndroid Build Coastguard Worker {
76*de1e4e89SAndroid Build Coastguard Worker return generic_proc_open("PROC_NET_SNMP6", "net/snmp6");
77*de1e4e89SAndroid Build Coastguard Worker }
78*de1e4e89SAndroid Build Coastguard Worker
net_sctp_snmp_open(void)79*de1e4e89SAndroid Build Coastguard Worker static int net_sctp_snmp_open(void)
80*de1e4e89SAndroid Build Coastguard Worker {
81*de1e4e89SAndroid Build Coastguard Worker return generic_proc_open("PROC_NET_SCTP_SNMP", "net/sctp/snmp");
82*de1e4e89SAndroid Build Coastguard Worker }
83*de1e4e89SAndroid Build Coastguard Worker
84*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent {
85*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *next;
86*de1e4e89SAndroid Build Coastguard Worker char *id;
87*de1e4e89SAndroid Build Coastguard Worker unsigned long long val;
88*de1e4e89SAndroid Build Coastguard Worker double rate;
89*de1e4e89SAndroid Build Coastguard Worker };
90*de1e4e89SAndroid Build Coastguard Worker
91*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *kern_db;
92*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *hist_db;
93*de1e4e89SAndroid Build Coastguard Worker
94*de1e4e89SAndroid Build Coastguard Worker static const char *useless_numbers[] = {
95*de1e4e89SAndroid Build Coastguard Worker "IpForwarding", "IpDefaultTTL",
96*de1e4e89SAndroid Build Coastguard Worker "TcpRtoAlgorithm", "TcpRtoMin", "TcpRtoMax",
97*de1e4e89SAndroid Build Coastguard Worker "TcpMaxConn", "TcpCurrEstab"
98*de1e4e89SAndroid Build Coastguard Worker };
99*de1e4e89SAndroid Build Coastguard Worker
useless_number(const char * id)100*de1e4e89SAndroid Build Coastguard Worker static int useless_number(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 for (i = 0; i < ARRAY_SIZE(useless_numbers); i++)
105*de1e4e89SAndroid Build Coastguard Worker if (strcmp(id, useless_numbers[i]) == 0)
106*de1e4e89SAndroid Build Coastguard Worker return 1;
107*de1e4e89SAndroid Build Coastguard Worker return 0;
108*de1e4e89SAndroid Build Coastguard Worker }
109*de1e4e89SAndroid Build Coastguard Worker
match(const char * id)110*de1e4e89SAndroid Build Coastguard Worker static int match(const char *id)
111*de1e4e89SAndroid Build Coastguard Worker {
112*de1e4e89SAndroid Build Coastguard Worker int i;
113*de1e4e89SAndroid Build Coastguard Worker
114*de1e4e89SAndroid Build Coastguard Worker if (npatterns == 0)
115*de1e4e89SAndroid Build Coastguard Worker return 1;
116*de1e4e89SAndroid Build Coastguard Worker
117*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < npatterns; i++) {
118*de1e4e89SAndroid Build Coastguard Worker if (!fnmatch(patterns[i], id, 0))
119*de1e4e89SAndroid Build Coastguard Worker return 1;
120*de1e4e89SAndroid Build Coastguard Worker }
121*de1e4e89SAndroid Build Coastguard Worker return 0;
122*de1e4e89SAndroid Build Coastguard Worker }
123*de1e4e89SAndroid Build Coastguard Worker
load_good_table(FILE * fp)124*de1e4e89SAndroid Build Coastguard Worker static void load_good_table(FILE *fp)
125*de1e4e89SAndroid Build Coastguard Worker {
126*de1e4e89SAndroid Build Coastguard Worker char buf[4096];
127*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *db = NULL;
128*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *n;
129*de1e4e89SAndroid Build Coastguard Worker
130*de1e4e89SAndroid Build Coastguard Worker while (fgets(buf, sizeof(buf), fp) != NULL) {
131*de1e4e89SAndroid Build Coastguard Worker int nr;
132*de1e4e89SAndroid Build Coastguard Worker unsigned long long val;
133*de1e4e89SAndroid Build Coastguard Worker double rate;
134*de1e4e89SAndroid Build Coastguard Worker char idbuf[sizeof(buf)];
135*de1e4e89SAndroid Build Coastguard Worker
136*de1e4e89SAndroid Build Coastguard Worker if (buf[0] == '#') {
137*de1e4e89SAndroid Build Coastguard Worker buf[strlen(buf)-1] = 0;
138*de1e4e89SAndroid Build Coastguard Worker if (info_source[0] && strcmp(info_source, buf+1))
139*de1e4e89SAndroid Build Coastguard Worker source_mismatch = 1;
140*de1e4e89SAndroid Build Coastguard Worker info_source[0] = 0;
141*de1e4e89SAndroid Build Coastguard Worker strncat(info_source, buf+1, sizeof(info_source)-1);
142*de1e4e89SAndroid Build Coastguard Worker continue;
143*de1e4e89SAndroid Build Coastguard Worker }
144*de1e4e89SAndroid Build Coastguard Worker /* idbuf is as big as buf, so this is safe */
145*de1e4e89SAndroid Build Coastguard Worker nr = sscanf(buf, "%s%llu%lg", idbuf, &val, &rate);
146*de1e4e89SAndroid Build Coastguard Worker if (nr < 2)
147*de1e4e89SAndroid Build Coastguard Worker abort();
148*de1e4e89SAndroid Build Coastguard Worker if (nr < 3)
149*de1e4e89SAndroid Build Coastguard Worker rate = 0;
150*de1e4e89SAndroid Build Coastguard Worker if (useless_number(idbuf))
151*de1e4e89SAndroid Build Coastguard Worker continue;
152*de1e4e89SAndroid Build Coastguard Worker if ((n = malloc(sizeof(*n))) == NULL)
153*de1e4e89SAndroid Build Coastguard Worker abort();
154*de1e4e89SAndroid Build Coastguard Worker n->id = strdup(idbuf);
155*de1e4e89SAndroid Build Coastguard Worker n->val = val;
156*de1e4e89SAndroid Build Coastguard Worker n->rate = rate;
157*de1e4e89SAndroid Build Coastguard Worker n->next = db;
158*de1e4e89SAndroid Build Coastguard Worker db = n;
159*de1e4e89SAndroid Build Coastguard Worker }
160*de1e4e89SAndroid Build Coastguard Worker
161*de1e4e89SAndroid Build Coastguard Worker while (db) {
162*de1e4e89SAndroid Build Coastguard Worker n = db;
163*de1e4e89SAndroid Build Coastguard Worker db = db->next;
164*de1e4e89SAndroid Build Coastguard Worker n->next = kern_db;
165*de1e4e89SAndroid Build Coastguard Worker kern_db = n;
166*de1e4e89SAndroid Build Coastguard Worker }
167*de1e4e89SAndroid Build Coastguard Worker }
168*de1e4e89SAndroid Build Coastguard Worker
count_spaces(const char * line)169*de1e4e89SAndroid Build Coastguard Worker static int count_spaces(const char *line)
170*de1e4e89SAndroid Build Coastguard Worker {
171*de1e4e89SAndroid Build Coastguard Worker int count = 0;
172*de1e4e89SAndroid Build Coastguard Worker char c;
173*de1e4e89SAndroid Build Coastguard Worker
174*de1e4e89SAndroid Build Coastguard Worker while ((c = *line++) != 0)
175*de1e4e89SAndroid Build Coastguard Worker count += c == ' ' || c == '\n';
176*de1e4e89SAndroid Build Coastguard Worker return count;
177*de1e4e89SAndroid Build Coastguard Worker }
178*de1e4e89SAndroid Build Coastguard Worker
load_ugly_table(FILE * fp)179*de1e4e89SAndroid Build Coastguard Worker static void load_ugly_table(FILE *fp)
180*de1e4e89SAndroid Build Coastguard Worker {
181*de1e4e89SAndroid Build Coastguard Worker char buf[4096];
182*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *db = NULL;
183*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *n;
184*de1e4e89SAndroid Build Coastguard Worker
185*de1e4e89SAndroid Build Coastguard Worker while (fgets(buf, sizeof(buf), fp) != NULL) {
186*de1e4e89SAndroid Build Coastguard Worker char idbuf[sizeof(buf)];
187*de1e4e89SAndroid Build Coastguard Worker int off;
188*de1e4e89SAndroid Build Coastguard Worker char *p;
189*de1e4e89SAndroid Build Coastguard Worker int count1, count2, skip = 0;
190*de1e4e89SAndroid Build Coastguard Worker
191*de1e4e89SAndroid Build Coastguard Worker p = strchr(buf, ':');
192*de1e4e89SAndroid Build Coastguard Worker if (!p)
193*de1e4e89SAndroid Build Coastguard Worker abort();
194*de1e4e89SAndroid Build Coastguard Worker count1 = count_spaces(buf);
195*de1e4e89SAndroid Build Coastguard Worker *p = 0;
196*de1e4e89SAndroid Build Coastguard Worker idbuf[0] = 0;
197*de1e4e89SAndroid Build Coastguard Worker strncat(idbuf, buf, sizeof(idbuf) - 1);
198*de1e4e89SAndroid Build Coastguard Worker off = p - buf;
199*de1e4e89SAndroid Build Coastguard Worker p += 2;
200*de1e4e89SAndroid Build Coastguard Worker
201*de1e4e89SAndroid Build Coastguard Worker while (*p) {
202*de1e4e89SAndroid Build Coastguard Worker char *next;
203*de1e4e89SAndroid Build Coastguard Worker
204*de1e4e89SAndroid Build Coastguard Worker if ((next = strchr(p, ' ')) != NULL)
205*de1e4e89SAndroid Build Coastguard Worker *next++ = 0;
206*de1e4e89SAndroid Build Coastguard Worker else if ((next = strchr(p, '\n')) != NULL)
207*de1e4e89SAndroid Build Coastguard Worker *next++ = 0;
208*de1e4e89SAndroid Build Coastguard Worker if (off < sizeof(idbuf)) {
209*de1e4e89SAndroid Build Coastguard Worker idbuf[off] = 0;
210*de1e4e89SAndroid Build Coastguard Worker strncat(idbuf, p, sizeof(idbuf) - off - 1);
211*de1e4e89SAndroid Build Coastguard Worker }
212*de1e4e89SAndroid Build Coastguard Worker n = malloc(sizeof(*n));
213*de1e4e89SAndroid Build Coastguard Worker if (!n)
214*de1e4e89SAndroid Build Coastguard Worker abort();
215*de1e4e89SAndroid Build Coastguard Worker n->id = strdup(idbuf);
216*de1e4e89SAndroid Build Coastguard Worker n->rate = 0;
217*de1e4e89SAndroid Build Coastguard Worker n->next = db;
218*de1e4e89SAndroid Build Coastguard Worker db = n;
219*de1e4e89SAndroid Build Coastguard Worker p = next;
220*de1e4e89SAndroid Build Coastguard Worker }
221*de1e4e89SAndroid Build Coastguard Worker n = db;
222*de1e4e89SAndroid Build Coastguard Worker if (fgets(buf, sizeof(buf), fp) == NULL)
223*de1e4e89SAndroid Build Coastguard Worker abort();
224*de1e4e89SAndroid Build Coastguard Worker count2 = count_spaces(buf);
225*de1e4e89SAndroid Build Coastguard Worker if (count2 > count1)
226*de1e4e89SAndroid Build Coastguard Worker skip = count2 - count1;
227*de1e4e89SAndroid Build Coastguard Worker do {
228*de1e4e89SAndroid Build Coastguard Worker p = strrchr(buf, ' ');
229*de1e4e89SAndroid Build Coastguard Worker if (!p)
230*de1e4e89SAndroid Build Coastguard Worker abort();
231*de1e4e89SAndroid Build Coastguard Worker *p = 0;
232*de1e4e89SAndroid Build Coastguard Worker if (sscanf(p+1, "%llu", &n->val) != 1)
233*de1e4e89SAndroid Build Coastguard Worker abort();
234*de1e4e89SAndroid Build Coastguard Worker /* Trick to skip "dummy" trailing ICMP MIB in 2.4 */
235*de1e4e89SAndroid Build Coastguard Worker if (skip)
236*de1e4e89SAndroid Build Coastguard Worker skip--;
237*de1e4e89SAndroid Build Coastguard Worker else
238*de1e4e89SAndroid Build Coastguard Worker n = n->next;
239*de1e4e89SAndroid Build Coastguard Worker } while (p > buf + off + 2);
240*de1e4e89SAndroid Build Coastguard Worker }
241*de1e4e89SAndroid Build Coastguard Worker
242*de1e4e89SAndroid Build Coastguard Worker while (db) {
243*de1e4e89SAndroid Build Coastguard Worker n = db;
244*de1e4e89SAndroid Build Coastguard Worker db = db->next;
245*de1e4e89SAndroid Build Coastguard Worker if (useless_number(n->id)) {
246*de1e4e89SAndroid Build Coastguard Worker free(n->id);
247*de1e4e89SAndroid Build Coastguard Worker free(n);
248*de1e4e89SAndroid Build Coastguard Worker } else {
249*de1e4e89SAndroid Build Coastguard Worker n->next = kern_db;
250*de1e4e89SAndroid Build Coastguard Worker kern_db = n;
251*de1e4e89SAndroid Build Coastguard Worker }
252*de1e4e89SAndroid Build Coastguard Worker }
253*de1e4e89SAndroid Build Coastguard Worker }
254*de1e4e89SAndroid Build Coastguard Worker
load_sctp_snmp(void)255*de1e4e89SAndroid Build Coastguard Worker static void load_sctp_snmp(void)
256*de1e4e89SAndroid Build Coastguard Worker {
257*de1e4e89SAndroid Build Coastguard Worker FILE *fp = fdopen(net_sctp_snmp_open(), "r");
258*de1e4e89SAndroid Build Coastguard Worker
259*de1e4e89SAndroid Build Coastguard Worker if (fp) {
260*de1e4e89SAndroid Build Coastguard Worker load_good_table(fp);
261*de1e4e89SAndroid Build Coastguard Worker fclose(fp);
262*de1e4e89SAndroid Build Coastguard Worker }
263*de1e4e89SAndroid Build Coastguard Worker }
264*de1e4e89SAndroid Build Coastguard Worker
load_snmp(void)265*de1e4e89SAndroid Build Coastguard Worker static void load_snmp(void)
266*de1e4e89SAndroid Build Coastguard Worker {
267*de1e4e89SAndroid Build Coastguard Worker FILE *fp = fdopen(net_snmp_open(), "r");
268*de1e4e89SAndroid Build Coastguard Worker
269*de1e4e89SAndroid Build Coastguard Worker if (fp) {
270*de1e4e89SAndroid Build Coastguard Worker load_ugly_table(fp);
271*de1e4e89SAndroid Build Coastguard Worker fclose(fp);
272*de1e4e89SAndroid Build Coastguard Worker }
273*de1e4e89SAndroid Build Coastguard Worker }
274*de1e4e89SAndroid Build Coastguard Worker
load_snmp6(void)275*de1e4e89SAndroid Build Coastguard Worker static void load_snmp6(void)
276*de1e4e89SAndroid Build Coastguard Worker {
277*de1e4e89SAndroid Build Coastguard Worker FILE *fp = fdopen(net_snmp6_open(), "r");
278*de1e4e89SAndroid Build Coastguard Worker
279*de1e4e89SAndroid Build Coastguard Worker if (fp) {
280*de1e4e89SAndroid Build Coastguard Worker load_good_table(fp);
281*de1e4e89SAndroid Build Coastguard Worker fclose(fp);
282*de1e4e89SAndroid Build Coastguard Worker }
283*de1e4e89SAndroid Build Coastguard Worker }
284*de1e4e89SAndroid Build Coastguard Worker
load_netstat(void)285*de1e4e89SAndroid Build Coastguard Worker static void load_netstat(void)
286*de1e4e89SAndroid Build Coastguard Worker {
287*de1e4e89SAndroid Build Coastguard Worker FILE *fp = fdopen(net_netstat_open(), "r");
288*de1e4e89SAndroid Build Coastguard Worker
289*de1e4e89SAndroid Build Coastguard Worker if (fp) {
290*de1e4e89SAndroid Build Coastguard Worker load_ugly_table(fp);
291*de1e4e89SAndroid Build Coastguard Worker fclose(fp);
292*de1e4e89SAndroid Build Coastguard Worker }
293*de1e4e89SAndroid Build Coastguard Worker }
294*de1e4e89SAndroid Build Coastguard Worker
295*de1e4e89SAndroid Build Coastguard Worker
dump_kern_db(FILE * fp,int to_hist)296*de1e4e89SAndroid Build Coastguard Worker static void dump_kern_db(FILE *fp, int to_hist)
297*de1e4e89SAndroid Build Coastguard Worker {
298*de1e4e89SAndroid Build Coastguard Worker json_writer_t *jw = json_output ? jsonw_new(fp) : NULL;
299*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *n, *h;
300*de1e4e89SAndroid Build Coastguard Worker
301*de1e4e89SAndroid Build Coastguard Worker h = hist_db;
302*de1e4e89SAndroid Build Coastguard Worker if (jw) {
303*de1e4e89SAndroid Build Coastguard Worker jsonw_start_object(jw);
304*de1e4e89SAndroid Build Coastguard Worker jsonw_pretty(jw, pretty);
305*de1e4e89SAndroid Build Coastguard Worker jsonw_name(jw, info_source);
306*de1e4e89SAndroid Build Coastguard Worker jsonw_start_object(jw);
307*de1e4e89SAndroid Build Coastguard Worker } else
308*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "#%s\n", info_source);
309*de1e4e89SAndroid Build Coastguard Worker
310*de1e4e89SAndroid Build Coastguard Worker for (n = kern_db; n; n = n->next) {
311*de1e4e89SAndroid Build Coastguard Worker unsigned long long val = n->val;
312*de1e4e89SAndroid Build Coastguard Worker
313*de1e4e89SAndroid Build Coastguard Worker if (!dump_zeros && !val && !n->rate)
314*de1e4e89SAndroid Build Coastguard Worker continue;
315*de1e4e89SAndroid Build Coastguard Worker if (!match(n->id)) {
316*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *h1;
317*de1e4e89SAndroid Build Coastguard Worker
318*de1e4e89SAndroid Build Coastguard Worker if (!to_hist)
319*de1e4e89SAndroid Build Coastguard Worker continue;
320*de1e4e89SAndroid Build Coastguard Worker for (h1 = h; h1; h1 = h1->next) {
321*de1e4e89SAndroid Build Coastguard Worker if (strcmp(h1->id, n->id) == 0) {
322*de1e4e89SAndroid Build Coastguard Worker val = h1->val;
323*de1e4e89SAndroid Build Coastguard Worker h = h1->next;
324*de1e4e89SAndroid Build Coastguard Worker break;
325*de1e4e89SAndroid Build Coastguard Worker }
326*de1e4e89SAndroid Build Coastguard Worker }
327*de1e4e89SAndroid Build Coastguard Worker }
328*de1e4e89SAndroid Build Coastguard Worker
329*de1e4e89SAndroid Build Coastguard Worker if (jw)
330*de1e4e89SAndroid Build Coastguard Worker jsonw_uint_field(jw, n->id, val);
331*de1e4e89SAndroid Build Coastguard Worker else
332*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-32s%-16llu%6.1f\n", n->id, val, n->rate);
333*de1e4e89SAndroid Build Coastguard Worker }
334*de1e4e89SAndroid Build Coastguard Worker
335*de1e4e89SAndroid Build Coastguard Worker if (jw) {
336*de1e4e89SAndroid Build Coastguard Worker jsonw_end_object(jw);
337*de1e4e89SAndroid Build Coastguard Worker
338*de1e4e89SAndroid Build Coastguard Worker jsonw_end_object(jw);
339*de1e4e89SAndroid Build Coastguard Worker jsonw_destroy(&jw);
340*de1e4e89SAndroid Build Coastguard Worker }
341*de1e4e89SAndroid Build Coastguard Worker }
342*de1e4e89SAndroid Build Coastguard Worker
dump_incr_db(FILE * fp)343*de1e4e89SAndroid Build Coastguard Worker static void dump_incr_db(FILE *fp)
344*de1e4e89SAndroid Build Coastguard Worker {
345*de1e4e89SAndroid Build Coastguard Worker json_writer_t *jw = json_output ? jsonw_new(fp) : NULL;
346*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *n, *h;
347*de1e4e89SAndroid Build Coastguard Worker
348*de1e4e89SAndroid Build Coastguard Worker h = hist_db;
349*de1e4e89SAndroid Build Coastguard Worker if (jw) {
350*de1e4e89SAndroid Build Coastguard Worker jsonw_start_object(jw);
351*de1e4e89SAndroid Build Coastguard Worker jsonw_pretty(jw, pretty);
352*de1e4e89SAndroid Build Coastguard Worker jsonw_name(jw, info_source);
353*de1e4e89SAndroid Build Coastguard Worker jsonw_start_object(jw);
354*de1e4e89SAndroid Build Coastguard Worker } else
355*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "#%s\n", info_source);
356*de1e4e89SAndroid Build Coastguard Worker
357*de1e4e89SAndroid Build Coastguard Worker for (n = kern_db; n; n = n->next) {
358*de1e4e89SAndroid Build Coastguard Worker int ovfl = 0;
359*de1e4e89SAndroid Build Coastguard Worker unsigned long long val = n->val;
360*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *h1;
361*de1e4e89SAndroid Build Coastguard Worker
362*de1e4e89SAndroid Build Coastguard Worker for (h1 = h; h1; h1 = h1->next) {
363*de1e4e89SAndroid Build Coastguard Worker if (strcmp(h1->id, n->id) == 0) {
364*de1e4e89SAndroid Build Coastguard Worker if (val < h1->val) {
365*de1e4e89SAndroid Build Coastguard Worker ovfl = 1;
366*de1e4e89SAndroid Build Coastguard Worker val = h1->val;
367*de1e4e89SAndroid Build Coastguard Worker }
368*de1e4e89SAndroid Build Coastguard Worker val -= h1->val;
369*de1e4e89SAndroid Build Coastguard Worker h = h1->next;
370*de1e4e89SAndroid Build Coastguard Worker break;
371*de1e4e89SAndroid Build Coastguard Worker }
372*de1e4e89SAndroid Build Coastguard Worker }
373*de1e4e89SAndroid Build Coastguard Worker if (!dump_zeros && !val && !n->rate)
374*de1e4e89SAndroid Build Coastguard Worker continue;
375*de1e4e89SAndroid Build Coastguard Worker if (!match(n->id))
376*de1e4e89SAndroid Build Coastguard Worker continue;
377*de1e4e89SAndroid Build Coastguard Worker
378*de1e4e89SAndroid Build Coastguard Worker if (jw)
379*de1e4e89SAndroid Build Coastguard Worker jsonw_uint_field(jw, n->id, val);
380*de1e4e89SAndroid Build Coastguard Worker else
381*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-32s%-16llu%6.1f%s\n", n->id, val,
382*de1e4e89SAndroid Build Coastguard Worker n->rate, ovfl?" (overflow)":"");
383*de1e4e89SAndroid Build Coastguard Worker }
384*de1e4e89SAndroid Build Coastguard Worker
385*de1e4e89SAndroid Build Coastguard Worker if (jw) {
386*de1e4e89SAndroid Build Coastguard Worker jsonw_end_object(jw);
387*de1e4e89SAndroid Build Coastguard Worker
388*de1e4e89SAndroid Build Coastguard Worker jsonw_end_object(jw);
389*de1e4e89SAndroid Build Coastguard Worker jsonw_destroy(&jw);
390*de1e4e89SAndroid Build Coastguard Worker }
391*de1e4e89SAndroid Build Coastguard Worker }
392*de1e4e89SAndroid Build Coastguard Worker
393*de1e4e89SAndroid Build Coastguard Worker static int children;
394*de1e4e89SAndroid Build Coastguard Worker
sigchild(int signo)395*de1e4e89SAndroid Build Coastguard Worker static void sigchild(int signo)
396*de1e4e89SAndroid Build Coastguard Worker {
397*de1e4e89SAndroid Build Coastguard Worker }
398*de1e4e89SAndroid Build Coastguard Worker
update_db(int interval)399*de1e4e89SAndroid Build Coastguard Worker static void update_db(int interval)
400*de1e4e89SAndroid Build Coastguard Worker {
401*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *n, *h;
402*de1e4e89SAndroid Build Coastguard Worker
403*de1e4e89SAndroid Build Coastguard Worker n = kern_db;
404*de1e4e89SAndroid Build Coastguard Worker kern_db = NULL;
405*de1e4e89SAndroid Build Coastguard Worker
406*de1e4e89SAndroid Build Coastguard Worker load_netstat();
407*de1e4e89SAndroid Build Coastguard Worker load_snmp6();
408*de1e4e89SAndroid Build Coastguard Worker load_snmp();
409*de1e4e89SAndroid Build Coastguard Worker load_sctp_snmp();
410*de1e4e89SAndroid Build Coastguard Worker
411*de1e4e89SAndroid Build Coastguard Worker h = kern_db;
412*de1e4e89SAndroid Build Coastguard Worker kern_db = n;
413*de1e4e89SAndroid Build Coastguard Worker
414*de1e4e89SAndroid Build Coastguard Worker for (n = kern_db; n; n = n->next) {
415*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *h1;
416*de1e4e89SAndroid Build Coastguard Worker
417*de1e4e89SAndroid Build Coastguard Worker for (h1 = h; h1; h1 = h1->next) {
418*de1e4e89SAndroid Build Coastguard Worker if (strcmp(h1->id, n->id) == 0) {
419*de1e4e89SAndroid Build Coastguard Worker double sample;
420*de1e4e89SAndroid Build Coastguard Worker unsigned long long incr = h1->val - n->val;
421*de1e4e89SAndroid Build Coastguard Worker
422*de1e4e89SAndroid Build Coastguard Worker n->val = h1->val;
423*de1e4e89SAndroid Build Coastguard Worker sample = (double)incr * 1000.0 / interval;
424*de1e4e89SAndroid Build Coastguard Worker if (interval >= scan_interval) {
425*de1e4e89SAndroid Build Coastguard Worker n->rate += W*(sample-n->rate);
426*de1e4e89SAndroid Build Coastguard Worker } else if (interval >= 1000) {
427*de1e4e89SAndroid Build Coastguard Worker if (interval >= time_constant) {
428*de1e4e89SAndroid Build Coastguard Worker n->rate = sample;
429*de1e4e89SAndroid Build Coastguard Worker } else {
430*de1e4e89SAndroid Build Coastguard Worker double w = W*(double)interval/scan_interval;
431*de1e4e89SAndroid Build Coastguard Worker
432*de1e4e89SAndroid Build Coastguard Worker n->rate += w*(sample-n->rate);
433*de1e4e89SAndroid Build Coastguard Worker }
434*de1e4e89SAndroid Build Coastguard Worker }
435*de1e4e89SAndroid Build Coastguard Worker
436*de1e4e89SAndroid Build Coastguard Worker while (h != h1) {
437*de1e4e89SAndroid Build Coastguard Worker struct nstat_ent *tmp = h;
438*de1e4e89SAndroid Build Coastguard Worker
439*de1e4e89SAndroid Build Coastguard Worker h = h->next;
440*de1e4e89SAndroid Build Coastguard Worker free(tmp->id);
441*de1e4e89SAndroid Build Coastguard Worker free(tmp);
442*de1e4e89SAndroid Build Coastguard Worker };
443*de1e4e89SAndroid Build Coastguard Worker h = h1->next;
444*de1e4e89SAndroid Build Coastguard Worker free(h1->id);
445*de1e4e89SAndroid Build Coastguard Worker free(h1);
446*de1e4e89SAndroid Build Coastguard Worker break;
447*de1e4e89SAndroid Build Coastguard Worker }
448*de1e4e89SAndroid Build Coastguard Worker }
449*de1e4e89SAndroid Build Coastguard Worker }
450*de1e4e89SAndroid Build Coastguard Worker }
451*de1e4e89SAndroid Build Coastguard Worker
452*de1e4e89SAndroid Build Coastguard Worker #define T_DIFF(a, b) (((a).tv_sec-(b).tv_sec)*1000 + ((a).tv_usec-(b).tv_usec)/1000)
453*de1e4e89SAndroid Build Coastguard Worker
454*de1e4e89SAndroid Build Coastguard Worker
server_loop(int fd)455*de1e4e89SAndroid Build Coastguard Worker static void server_loop(int fd)
456*de1e4e89SAndroid Build Coastguard Worker {
457*de1e4e89SAndroid Build Coastguard Worker struct timeval snaptime = { 0 };
458*de1e4e89SAndroid Build Coastguard Worker struct pollfd p;
459*de1e4e89SAndroid Build Coastguard Worker
460*de1e4e89SAndroid Build Coastguard Worker p.fd = fd;
461*de1e4e89SAndroid Build Coastguard Worker p.events = p.revents = POLLIN;
462*de1e4e89SAndroid Build Coastguard Worker
463*de1e4e89SAndroid Build Coastguard Worker sprintf(info_source, "%d.%lu sampling_interval=%d time_const=%d",
464*de1e4e89SAndroid Build Coastguard Worker getpid(), (unsigned long)random(), scan_interval/1000, time_constant/1000);
465*de1e4e89SAndroid Build Coastguard Worker
466*de1e4e89SAndroid Build Coastguard Worker load_netstat();
467*de1e4e89SAndroid Build Coastguard Worker load_snmp6();
468*de1e4e89SAndroid Build Coastguard Worker load_snmp();
469*de1e4e89SAndroid Build Coastguard Worker load_sctp_snmp();
470*de1e4e89SAndroid Build Coastguard Worker
471*de1e4e89SAndroid Build Coastguard Worker for (;;) {
472*de1e4e89SAndroid Build Coastguard Worker int status;
473*de1e4e89SAndroid Build Coastguard Worker time_t tdiff;
474*de1e4e89SAndroid Build Coastguard Worker struct timeval now;
475*de1e4e89SAndroid Build Coastguard Worker
476*de1e4e89SAndroid Build Coastguard Worker gettimeofday(&now, NULL);
477*de1e4e89SAndroid Build Coastguard Worker tdiff = T_DIFF(now, snaptime);
478*de1e4e89SAndroid Build Coastguard Worker if (tdiff >= scan_interval) {
479*de1e4e89SAndroid Build Coastguard Worker update_db(tdiff);
480*de1e4e89SAndroid Build Coastguard Worker snaptime = now;
481*de1e4e89SAndroid Build Coastguard Worker tdiff = 0;
482*de1e4e89SAndroid Build Coastguard Worker }
483*de1e4e89SAndroid Build Coastguard Worker if (poll(&p, 1, scan_interval - tdiff) > 0
484*de1e4e89SAndroid Build Coastguard Worker && (p.revents&POLLIN)) {
485*de1e4e89SAndroid Build Coastguard Worker int clnt = accept(fd, NULL, NULL);
486*de1e4e89SAndroid Build Coastguard Worker
487*de1e4e89SAndroid Build Coastguard Worker if (clnt >= 0) {
488*de1e4e89SAndroid Build Coastguard Worker pid_t pid;
489*de1e4e89SAndroid Build Coastguard Worker
490*de1e4e89SAndroid Build Coastguard Worker if (children >= 5) {
491*de1e4e89SAndroid Build Coastguard Worker close(clnt);
492*de1e4e89SAndroid Build Coastguard Worker } else if ((pid = fork()) != 0) {
493*de1e4e89SAndroid Build Coastguard Worker if (pid > 0)
494*de1e4e89SAndroid Build Coastguard Worker children++;
495*de1e4e89SAndroid Build Coastguard Worker close(clnt);
496*de1e4e89SAndroid Build Coastguard Worker } else {
497*de1e4e89SAndroid Build Coastguard Worker FILE *fp = fdopen(clnt, "w");
498*de1e4e89SAndroid Build Coastguard Worker
499*de1e4e89SAndroid Build Coastguard Worker if (fp)
500*de1e4e89SAndroid Build Coastguard Worker dump_kern_db(fp, 0);
501*de1e4e89SAndroid Build Coastguard Worker exit(0);
502*de1e4e89SAndroid Build Coastguard Worker }
503*de1e4e89SAndroid Build Coastguard Worker }
504*de1e4e89SAndroid Build Coastguard Worker }
505*de1e4e89SAndroid Build Coastguard Worker while (children && waitpid(-1, &status, WNOHANG) > 0)
506*de1e4e89SAndroid Build Coastguard Worker children--;
507*de1e4e89SAndroid Build Coastguard Worker }
508*de1e4e89SAndroid Build Coastguard Worker }
509*de1e4e89SAndroid Build Coastguard Worker
verify_forging(int fd)510*de1e4e89SAndroid Build Coastguard Worker static int verify_forging(int fd)
511*de1e4e89SAndroid Build Coastguard Worker {
512*de1e4e89SAndroid Build Coastguard Worker struct ucred cred;
513*de1e4e89SAndroid Build Coastguard Worker socklen_t olen = sizeof(cred);
514*de1e4e89SAndroid Build Coastguard Worker
515*de1e4e89SAndroid Build Coastguard Worker if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &olen) ||
516*de1e4e89SAndroid Build Coastguard Worker olen < sizeof(cred))
517*de1e4e89SAndroid Build Coastguard Worker return -1;
518*de1e4e89SAndroid Build Coastguard Worker if (cred.uid == getuid() || cred.uid == 0)
519*de1e4e89SAndroid Build Coastguard Worker return 0;
520*de1e4e89SAndroid Build Coastguard Worker return -1;
521*de1e4e89SAndroid Build Coastguard Worker }
522*de1e4e89SAndroid Build Coastguard Worker
523*de1e4e89SAndroid Build Coastguard Worker static void usage(void) __attribute__((noreturn));
524*de1e4e89SAndroid Build Coastguard Worker
usage(void)525*de1e4e89SAndroid Build Coastguard Worker static void usage(void)
526*de1e4e89SAndroid Build Coastguard Worker {
527*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
528*de1e4e89SAndroid Build Coastguard Worker "Usage: nstat [OPTION] [ PATTERN [ PATTERN ] ]\n"
529*de1e4e89SAndroid Build Coastguard Worker " -h, --help this message\n"
530*de1e4e89SAndroid Build Coastguard Worker " -a, --ignore ignore history\n"
531*de1e4e89SAndroid Build Coastguard Worker " -d, --scan=SECS sample every statistics every SECS\n"
532*de1e4e89SAndroid Build Coastguard Worker " -j, --json format output in JSON\n"
533*de1e4e89SAndroid Build Coastguard Worker " -n, --nooutput do history only\n"
534*de1e4e89SAndroid Build Coastguard Worker " -p, --pretty pretty print\n"
535*de1e4e89SAndroid Build Coastguard Worker " -r, --reset reset history\n"
536*de1e4e89SAndroid Build Coastguard Worker " -s, --noupdate don't update history\n"
537*de1e4e89SAndroid Build Coastguard Worker " -t, --interval=SECS report average over the last SECS\n"
538*de1e4e89SAndroid Build Coastguard Worker " -V, --version output version information\n"
539*de1e4e89SAndroid Build Coastguard Worker " -z, --zeros show entries with zero activity\n");
540*de1e4e89SAndroid Build Coastguard Worker exit(-1);
541*de1e4e89SAndroid Build Coastguard Worker }
542*de1e4e89SAndroid Build Coastguard Worker
543*de1e4e89SAndroid Build Coastguard Worker static const struct option longopts[] = {
544*de1e4e89SAndroid Build Coastguard Worker { "help", 0, 0, 'h' },
545*de1e4e89SAndroid Build Coastguard Worker { "ignore", 0, 0, 'a' },
546*de1e4e89SAndroid Build Coastguard Worker { "scan", 1, 0, 'd'},
547*de1e4e89SAndroid Build Coastguard Worker { "nooutput", 0, 0, 'n' },
548*de1e4e89SAndroid Build Coastguard Worker { "json", 0, 0, 'j' },
549*de1e4e89SAndroid Build Coastguard Worker { "reset", 0, 0, 'r' },
550*de1e4e89SAndroid Build Coastguard Worker { "noupdate", 0, 0, 's' },
551*de1e4e89SAndroid Build Coastguard Worker { "pretty", 0, 0, 'p' },
552*de1e4e89SAndroid Build Coastguard Worker { "interval", 1, 0, 't' },
553*de1e4e89SAndroid Build Coastguard Worker { "version", 0, 0, 'V' },
554*de1e4e89SAndroid Build Coastguard Worker { "zeros", 0, 0, 'z' },
555*de1e4e89SAndroid Build Coastguard Worker { 0 }
556*de1e4e89SAndroid Build Coastguard Worker };
557*de1e4e89SAndroid Build Coastguard Worker
main(int argc,char * argv[])558*de1e4e89SAndroid Build Coastguard Worker int main(int argc, char *argv[])
559*de1e4e89SAndroid Build Coastguard Worker {
560*de1e4e89SAndroid Build Coastguard Worker char *hist_name;
561*de1e4e89SAndroid Build Coastguard Worker struct sockaddr_un sun;
562*de1e4e89SAndroid Build Coastguard Worker FILE *hist_fp = NULL;
563*de1e4e89SAndroid Build Coastguard Worker int ch;
564*de1e4e89SAndroid Build Coastguard Worker int fd;
565*de1e4e89SAndroid Build Coastguard Worker
566*de1e4e89SAndroid Build Coastguard Worker while ((ch = getopt_long(argc, argv, "h?vVzrnasd:t:jp",
567*de1e4e89SAndroid Build Coastguard Worker longopts, NULL)) != EOF) {
568*de1e4e89SAndroid Build Coastguard Worker switch (ch) {
569*de1e4e89SAndroid Build Coastguard Worker case 'z':
570*de1e4e89SAndroid Build Coastguard Worker dump_zeros = 1;
571*de1e4e89SAndroid Build Coastguard Worker break;
572*de1e4e89SAndroid Build Coastguard Worker case 'r':
573*de1e4e89SAndroid Build Coastguard Worker reset_history = 1;
574*de1e4e89SAndroid Build Coastguard Worker break;
575*de1e4e89SAndroid Build Coastguard Worker case 'a':
576*de1e4e89SAndroid Build Coastguard Worker ignore_history = 1;
577*de1e4e89SAndroid Build Coastguard Worker break;
578*de1e4e89SAndroid Build Coastguard Worker case 's':
579*de1e4e89SAndroid Build Coastguard Worker no_update = 1;
580*de1e4e89SAndroid Build Coastguard Worker break;
581*de1e4e89SAndroid Build Coastguard Worker case 'n':
582*de1e4e89SAndroid Build Coastguard Worker no_output = 1;
583*de1e4e89SAndroid Build Coastguard Worker break;
584*de1e4e89SAndroid Build Coastguard Worker case 'd':
585*de1e4e89SAndroid Build Coastguard Worker scan_interval = 1000*atoi(optarg);
586*de1e4e89SAndroid Build Coastguard Worker break;
587*de1e4e89SAndroid Build Coastguard Worker case 't':
588*de1e4e89SAndroid Build Coastguard Worker if (sscanf(optarg, "%d", &time_constant) != 1 ||
589*de1e4e89SAndroid Build Coastguard Worker time_constant <= 0) {
590*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "nstat: invalid time constant divisor\n");
591*de1e4e89SAndroid Build Coastguard Worker exit(-1);
592*de1e4e89SAndroid Build Coastguard Worker }
593*de1e4e89SAndroid Build Coastguard Worker break;
594*de1e4e89SAndroid Build Coastguard Worker case 'j':
595*de1e4e89SAndroid Build Coastguard Worker json_output = 1;
596*de1e4e89SAndroid Build Coastguard Worker break;
597*de1e4e89SAndroid Build Coastguard Worker case 'p':
598*de1e4e89SAndroid Build Coastguard Worker pretty = 1;
599*de1e4e89SAndroid Build Coastguard Worker break;
600*de1e4e89SAndroid Build Coastguard Worker case 'v':
601*de1e4e89SAndroid Build Coastguard Worker case 'V':
602*de1e4e89SAndroid Build Coastguard Worker printf("nstat utility, iproute2-ss%s\n", SNAPSHOT);
603*de1e4e89SAndroid Build Coastguard Worker exit(0);
604*de1e4e89SAndroid Build Coastguard Worker case 'h':
605*de1e4e89SAndroid Build Coastguard Worker case '?':
606*de1e4e89SAndroid Build Coastguard Worker default:
607*de1e4e89SAndroid Build Coastguard Worker usage();
608*de1e4e89SAndroid Build Coastguard Worker }
609*de1e4e89SAndroid Build Coastguard Worker }
610*de1e4e89SAndroid Build Coastguard Worker
611*de1e4e89SAndroid Build Coastguard Worker argc -= optind;
612*de1e4e89SAndroid Build Coastguard Worker argv += optind;
613*de1e4e89SAndroid Build Coastguard Worker
614*de1e4e89SAndroid Build Coastguard Worker sun.sun_family = AF_UNIX;
615*de1e4e89SAndroid Build Coastguard Worker sun.sun_path[0] = 0;
616*de1e4e89SAndroid Build Coastguard Worker sprintf(sun.sun_path+1, "nstat%d", getuid());
617*de1e4e89SAndroid Build Coastguard Worker
618*de1e4e89SAndroid Build Coastguard Worker if (scan_interval > 0) {
619*de1e4e89SAndroid Build Coastguard Worker if (time_constant == 0)
620*de1e4e89SAndroid Build Coastguard Worker time_constant = 60;
621*de1e4e89SAndroid Build Coastguard Worker time_constant *= 1000;
622*de1e4e89SAndroid Build Coastguard Worker W = 1 - 1/exp(log(10)*(double)scan_interval/time_constant);
623*de1e4e89SAndroid Build Coastguard Worker if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
624*de1e4e89SAndroid Build Coastguard Worker perror("nstat: socket");
625*de1e4e89SAndroid Build Coastguard Worker exit(-1);
626*de1e4e89SAndroid Build Coastguard Worker }
627*de1e4e89SAndroid Build Coastguard Worker if (bind(fd, (struct sockaddr *)&sun, 2+1+strlen(sun.sun_path+1)) < 0) {
628*de1e4e89SAndroid Build Coastguard Worker perror("nstat: bind");
629*de1e4e89SAndroid Build Coastguard Worker exit(-1);
630*de1e4e89SAndroid Build Coastguard Worker }
631*de1e4e89SAndroid Build Coastguard Worker if (listen(fd, 5) < 0) {
632*de1e4e89SAndroid Build Coastguard Worker perror("nstat: listen");
633*de1e4e89SAndroid Build Coastguard Worker exit(-1);
634*de1e4e89SAndroid Build Coastguard Worker }
635*de1e4e89SAndroid Build Coastguard Worker if (daemon(0, 0)) {
636*de1e4e89SAndroid Build Coastguard Worker perror("nstat: daemon");
637*de1e4e89SAndroid Build Coastguard Worker exit(-1);
638*de1e4e89SAndroid Build Coastguard Worker }
639*de1e4e89SAndroid Build Coastguard Worker signal(SIGPIPE, SIG_IGN);
640*de1e4e89SAndroid Build Coastguard Worker signal(SIGCHLD, sigchild);
641*de1e4e89SAndroid Build Coastguard Worker server_loop(fd);
642*de1e4e89SAndroid Build Coastguard Worker exit(0);
643*de1e4e89SAndroid Build Coastguard Worker }
644*de1e4e89SAndroid Build Coastguard Worker
645*de1e4e89SAndroid Build Coastguard Worker patterns = argv;
646*de1e4e89SAndroid Build Coastguard Worker npatterns = argc;
647*de1e4e89SAndroid Build Coastguard Worker
648*de1e4e89SAndroid Build Coastguard Worker if ((hist_name = getenv("NSTAT_HISTORY")) == NULL) {
649*de1e4e89SAndroid Build Coastguard Worker hist_name = malloc(128);
650*de1e4e89SAndroid Build Coastguard Worker sprintf(hist_name, "/tmp/.nstat.u%d", getuid());
651*de1e4e89SAndroid Build Coastguard Worker }
652*de1e4e89SAndroid Build Coastguard Worker
653*de1e4e89SAndroid Build Coastguard Worker if (reset_history)
654*de1e4e89SAndroid Build Coastguard Worker unlink(hist_name);
655*de1e4e89SAndroid Build Coastguard Worker
656*de1e4e89SAndroid Build Coastguard Worker if (!ignore_history || !no_update) {
657*de1e4e89SAndroid Build Coastguard Worker struct stat stb;
658*de1e4e89SAndroid Build Coastguard Worker
659*de1e4e89SAndroid Build Coastguard Worker fd = open(hist_name, O_RDWR|O_CREAT|O_NOFOLLOW, 0600);
660*de1e4e89SAndroid Build Coastguard Worker if (fd < 0) {
661*de1e4e89SAndroid Build Coastguard Worker perror("nstat: open history file");
662*de1e4e89SAndroid Build Coastguard Worker exit(-1);
663*de1e4e89SAndroid Build Coastguard Worker }
664*de1e4e89SAndroid Build Coastguard Worker if ((hist_fp = fdopen(fd, "r+")) == NULL) {
665*de1e4e89SAndroid Build Coastguard Worker perror("nstat: fdopen history file");
666*de1e4e89SAndroid Build Coastguard Worker exit(-1);
667*de1e4e89SAndroid Build Coastguard Worker }
668*de1e4e89SAndroid Build Coastguard Worker if (flock(fileno(hist_fp), LOCK_EX)) {
669*de1e4e89SAndroid Build Coastguard Worker perror("nstat: flock history file");
670*de1e4e89SAndroid Build Coastguard Worker exit(-1);
671*de1e4e89SAndroid Build Coastguard Worker }
672*de1e4e89SAndroid Build Coastguard Worker if (fstat(fileno(hist_fp), &stb) != 0) {
673*de1e4e89SAndroid Build Coastguard Worker perror("nstat: fstat history file");
674*de1e4e89SAndroid Build Coastguard Worker exit(-1);
675*de1e4e89SAndroid Build Coastguard Worker }
676*de1e4e89SAndroid Build Coastguard Worker if (stb.st_nlink != 1 || stb.st_uid != getuid()) {
677*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "nstat: something is so wrong with history file, that I prefer not to proceed.\n");
678*de1e4e89SAndroid Build Coastguard Worker exit(-1);
679*de1e4e89SAndroid Build Coastguard Worker }
680*de1e4e89SAndroid Build Coastguard Worker if (!ignore_history) {
681*de1e4e89SAndroid Build Coastguard Worker FILE *tfp;
682*de1e4e89SAndroid Build Coastguard Worker long uptime = -1;
683*de1e4e89SAndroid Build Coastguard Worker
684*de1e4e89SAndroid Build Coastguard Worker if ((tfp = fopen("/proc/uptime", "r")) != NULL) {
685*de1e4e89SAndroid Build Coastguard Worker if (fscanf(tfp, "%ld", &uptime) != 1)
686*de1e4e89SAndroid Build Coastguard Worker uptime = -1;
687*de1e4e89SAndroid Build Coastguard Worker fclose(tfp);
688*de1e4e89SAndroid Build Coastguard Worker }
689*de1e4e89SAndroid Build Coastguard Worker if (uptime >= 0 && time(NULL) >= stb.st_mtime+uptime) {
690*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "nstat: history is aged out, resetting\n");
691*de1e4e89SAndroid Build Coastguard Worker if (ftruncate(fileno(hist_fp), 0) < 0)
692*de1e4e89SAndroid Build Coastguard Worker perror("nstat: ftruncate");
693*de1e4e89SAndroid Build Coastguard Worker }
694*de1e4e89SAndroid Build Coastguard Worker }
695*de1e4e89SAndroid Build Coastguard Worker
696*de1e4e89SAndroid Build Coastguard Worker load_good_table(hist_fp);
697*de1e4e89SAndroid Build Coastguard Worker
698*de1e4e89SAndroid Build Coastguard Worker hist_db = kern_db;
699*de1e4e89SAndroid Build Coastguard Worker kern_db = NULL;
700*de1e4e89SAndroid Build Coastguard Worker }
701*de1e4e89SAndroid Build Coastguard Worker
702*de1e4e89SAndroid Build Coastguard Worker if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0 &&
703*de1e4e89SAndroid Build Coastguard Worker (connect(fd, (struct sockaddr *)&sun, 2+1+strlen(sun.sun_path+1)) == 0
704*de1e4e89SAndroid Build Coastguard Worker || (strcpy(sun.sun_path+1, "nstat0"),
705*de1e4e89SAndroid Build Coastguard Worker connect(fd, (struct sockaddr *)&sun, 2+1+strlen(sun.sun_path+1)) == 0))
706*de1e4e89SAndroid Build Coastguard Worker && verify_forging(fd) == 0) {
707*de1e4e89SAndroid Build Coastguard Worker FILE *sfp = fdopen(fd, "r");
708*de1e4e89SAndroid Build Coastguard Worker
709*de1e4e89SAndroid Build Coastguard Worker if (!sfp) {
710*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "nstat: fdopen failed: %s\n",
711*de1e4e89SAndroid Build Coastguard Worker strerror(errno));
712*de1e4e89SAndroid Build Coastguard Worker close(fd);
713*de1e4e89SAndroid Build Coastguard Worker } else {
714*de1e4e89SAndroid Build Coastguard Worker load_good_table(sfp);
715*de1e4e89SAndroid Build Coastguard Worker if (hist_db && source_mismatch) {
716*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "nstat: history is stale, ignoring it.\n");
717*de1e4e89SAndroid Build Coastguard Worker hist_db = NULL;
718*de1e4e89SAndroid Build Coastguard Worker }
719*de1e4e89SAndroid Build Coastguard Worker fclose(sfp);
720*de1e4e89SAndroid Build Coastguard Worker }
721*de1e4e89SAndroid Build Coastguard Worker } else {
722*de1e4e89SAndroid Build Coastguard Worker if (fd >= 0)
723*de1e4e89SAndroid Build Coastguard Worker close(fd);
724*de1e4e89SAndroid Build Coastguard Worker if (hist_db && info_source[0] && strcmp(info_source, "kernel")) {
725*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "nstat: history is stale, ignoring it.\n");
726*de1e4e89SAndroid Build Coastguard Worker hist_db = NULL;
727*de1e4e89SAndroid Build Coastguard Worker info_source[0] = 0;
728*de1e4e89SAndroid Build Coastguard Worker }
729*de1e4e89SAndroid Build Coastguard Worker load_netstat();
730*de1e4e89SAndroid Build Coastguard Worker load_snmp6();
731*de1e4e89SAndroid Build Coastguard Worker load_snmp();
732*de1e4e89SAndroid Build Coastguard Worker load_sctp_snmp();
733*de1e4e89SAndroid Build Coastguard Worker if (info_source[0] == 0)
734*de1e4e89SAndroid Build Coastguard Worker strcpy(info_source, "kernel");
735*de1e4e89SAndroid Build Coastguard Worker }
736*de1e4e89SAndroid Build Coastguard Worker
737*de1e4e89SAndroid Build Coastguard Worker if (!no_output) {
738*de1e4e89SAndroid Build Coastguard Worker if (ignore_history || hist_db == NULL)
739*de1e4e89SAndroid Build Coastguard Worker dump_kern_db(stdout, 0);
740*de1e4e89SAndroid Build Coastguard Worker else
741*de1e4e89SAndroid Build Coastguard Worker dump_incr_db(stdout);
742*de1e4e89SAndroid Build Coastguard Worker }
743*de1e4e89SAndroid Build Coastguard Worker if (!no_update) {
744*de1e4e89SAndroid Build Coastguard Worker if (ftruncate(fileno(hist_fp), 0) < 0)
745*de1e4e89SAndroid Build Coastguard Worker perror("nstat: ftruncate");
746*de1e4e89SAndroid Build Coastguard Worker rewind(hist_fp);
747*de1e4e89SAndroid Build Coastguard Worker
748*de1e4e89SAndroid Build Coastguard Worker json_output = 0;
749*de1e4e89SAndroid Build Coastguard Worker dump_kern_db(hist_fp, 1);
750*de1e4e89SAndroid Build Coastguard Worker fclose(hist_fp);
751*de1e4e89SAndroid Build Coastguard Worker }
752*de1e4e89SAndroid Build Coastguard Worker exit(0);
753*de1e4e89SAndroid Build Coastguard Worker }
754