1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/*
2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * ifstat.c	handy utility to read net interface statistics
3dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
4dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		This program is free software; you can redistribute it and/or
5dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		modify it under the terms of the GNU General Public License
6dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		as published by the Free Software Foundation; either version
7dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		2 of the License, or (at your option) any later version.
8dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
9dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */
11dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
12dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdio.h>
13dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdlib.h>
14dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <unistd.h>
15dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <fcntl.h>
16dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <string.h>
17dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <errno.h>
18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <time.h>
19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/time.h>
20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <fnmatch.h>
21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/file.h>
22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/socket.h>
23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/un.h>
24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/poll.h>
25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/wait.h>
26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/stat.h>
27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <signal.h>
28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <math.h>
29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <getopt.h>
30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <libnetlink.h>
32dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/netdevice.h>
33dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
34dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <SNAPSHOT.h>
35dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
36dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint dump_zeros = 0;
37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint reset_history = 0;
38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint ignore_history = 0;
39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint no_output = 0;
40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint no_update = 0;
41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint scan_interval = 0;
42dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint time_constant = 0;
43dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint show_errors = 0;
44dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatdouble W;
45dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar **patterns;
46dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint npatterns;
47dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
48dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar info_source[128];
49dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint source_mismatch;
50dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
51dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#define MAXS (sizeof(struct net_device_stats)/sizeof(unsigned long))
52dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
53dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct ifstat_ent
54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ifstat_ent	*next;
56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char			*name;
57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int			ifindex;
58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	unsigned long long	val[MAXS];
59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	double			rate[MAXS];
60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	unsigned long		ival[MAXS];
61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat};
62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct ifstat_ent *kern_db;
64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct ifstat_ent *hist_db;
65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int match(const char *id)
67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int i;
69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (npatterns == 0)
71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return 1;
72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (i=0; i<npatterns; i++) {
74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!fnmatch(patterns[i], id, 0))
75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return 1;
76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int get_nlmsg(const struct sockaddr_nl *who,
81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		     struct nlmsghdr *m, void *arg)
82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ifinfomsg *ifi = NLMSG_DATA(m);
84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct rtattr * tb[IFLA_MAX+1];
85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int len = m->nlmsg_len;
86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ifstat_ent *n;
87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int i;
88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (m->nlmsg_type != RTM_NEWLINK)
90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return 0;
91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	len -= NLMSG_LENGTH(sizeof(*ifi));
93dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (len < 0)
94dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
95dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
96dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!(ifi->ifi_flags&IFF_UP))
97dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return 0;
98dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
99dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
100dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[IFLA_IFNAME] == NULL || tb[IFLA_STATS] == NULL)
101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return 0;
102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	n = malloc(sizeof(*n));
104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!n)
105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		abort();
106dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	n->ifindex = ifi->ifi_index;
107dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	n->name = strdup(RTA_DATA(tb[IFLA_IFNAME]));
108dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	memcpy(&n->ival, RTA_DATA(tb[IFLA_STATS]), sizeof(n->ival));
109dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	memset(&n->rate, 0, sizeof(n->rate));
110dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (i=0; i<MAXS; i++)
111dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		n->val[i] = n->ival[i];
112dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	n->next = kern_db;
113dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	kern_db = n;
114dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
115dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
116dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
117dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid load_info(void)
118dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ifstat_ent *db, *n;
120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct rtnl_handle rth;
121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (rtnl_open(&rth, 0) < 0)
123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		exit(1);
124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETLINK) < 0) {
126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		perror("Cannot send dump request");
127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		exit(1);
128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (rtnl_dump_filter(&rth, get_nlmsg, NULL, NULL, NULL) < 0) {
131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(stderr, "Dump terminated\n");
132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		exit(1);
133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	rtnl_close(&rth);
136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	db = kern_db;
138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	kern_db = NULL;
139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	while (db) {
141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		n = db;
142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		db = db->next;
143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		n->next = kern_db;
144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		kern_db = n;
145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid load_raw_table(FILE *fp)
149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char buf[4096];
151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ifstat_ent *db = NULL;
152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ifstat_ent *n;
153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	while (fgets(buf, sizeof(buf), fp) != NULL) {
155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		char *p;
156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		char *next;
157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int i;
158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (buf[0] == '#') {
160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			buf[strlen(buf)-1] = 0;
161dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (info_source[0] && strcmp(info_source, buf+1))
162dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				source_mismatch = 1;
163dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			strncpy(info_source, buf+1, sizeof(info_source)-1);
164dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			continue;
165dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
166dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if ((n = malloc(sizeof(*n))) == NULL)
167dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			abort();
168dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
169dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!(p = strchr(buf, ' ')))
170dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			abort();
171dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		*p++ = 0;
172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
173dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (sscanf(buf, "%d", &n->ifindex) != 1)
174dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			abort();
175dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!(next = strchr(p, ' ')))
176dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			abort();
177dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		*next++ = 0;
178dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
179dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		n->name = strdup(p);
180dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		p = next;
181dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
182dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		for (i=0; i<MAXS; i++) {
183dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			unsigned rate;
184dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (!(next = strchr(p, ' ')))
185dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				abort();
186dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			*next++ = 0;
187dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (sscanf(p, "%llu", n->val+i) != 1)
188dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				abort();
189dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			n->ival[i] = (unsigned long)n->val[i];
190dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			p = next;
191dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (!(next = strchr(p, ' ')))
192dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				abort();
193dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			*next++ = 0;
194dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (sscanf(p, "%u", &rate) != 1)
195dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				abort();
196dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			n->rate[i] = rate;
197dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			p = next;
198dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
199dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		n->next = db;
200dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		db = n;
201dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
202dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
203dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	while (db) {
204dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		n = db;
205dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		db = db->next;
206dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		n->next = kern_db;
207dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		kern_db = n;
208dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
209dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
210dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
211dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid dump_raw_db(FILE *fp, int to_hist)
212dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
213dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ifstat_ent *n, *h;
214dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	h = hist_db;
215dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(fp, "#%s\n", info_source);
216dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
217dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (n=kern_db; n; n=n->next) {
218dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int i;
219dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		unsigned long long *vals = n->val;
220dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		double *rates = n->rate;
221dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!match(n->name)) {
222dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			struct ifstat_ent *h1;
223dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (!to_hist)
224dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				continue;
225dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			for (h1 = h; h1; h1 = h1->next) {
226dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				if (h1->ifindex == n->ifindex) {
227dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					vals = h1->val;
228dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					rates = h1->rate;
229dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					h = h1->next;
230dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					break;
231dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				}
232dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
233dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
234dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%d %s ", n->ifindex, n->name);
235dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		for (i=0; i<MAXS; i++)
236dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(fp, "%llu %u ", vals[i], (unsigned)rates[i]);
237dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "\n");
238dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
239dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
240dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
241dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/* use communication definitions of meg/kilo etc */
242dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic const unsigned long long giga = 1000000000ull;
243dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic const unsigned long long mega = 1000000;
244dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic const unsigned long long kilo = 1000;
245dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
246dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid format_rate(FILE *fp, unsigned long long *vals, double *rates, int i)
247dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
248dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char temp[64];
249dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (vals[i] > giga)
250dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%7lluM ", vals[i]/mega);
251dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (vals[i] > mega)
252dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%7lluK ", vals[i]/kilo);
253dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else
254dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8llu ", vals[i]);
255dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
256dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (rates[i] > mega) {
257dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		sprintf(temp, "%uM", (unsigned)(rates[i]/mega));
258dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-6s ", temp);
259dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else if (rates[i] > kilo) {
260dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		sprintf(temp, "%uK", (unsigned)(rates[i]/kilo));
261dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-6s ", temp);
262dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else
263dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-6u ", (unsigned)rates[i]);
264dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
265dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
266dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid format_pair(FILE *fp, unsigned long long *vals, int i, int k)
267dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
268dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char temp[64];
269dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (vals[i] > giga)
270dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%7lluM ", vals[i]/mega);
271dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (vals[i] > mega)
272dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%7lluK ", vals[i]/kilo);
273dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else
274dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8llu ", vals[i]);
275dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
276dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (vals[k] > giga) {
277dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		sprintf(temp, "%uM", (unsigned)(vals[k]/mega));
278dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-6s ", temp);
279dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else if (vals[k] > mega) {
280dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		sprintf(temp, "%uK", (unsigned)(vals[k]/kilo));
281dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-6s ", temp);
282dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else
283dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-6u ", (unsigned)vals[k]);
284dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
285dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
286dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid print_head(FILE *fp)
287dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
288dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(fp, "#%s\n", info_source);
289dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(fp, "%-15s ", "Interface");
290dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
291dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(fp, "%8s/%-6s ", "RX Pkts", "Rate");
292dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(fp, "%8s/%-6s ", "TX Pkts", "Rate");
293dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(fp, "%8s/%-6s ", "RX Data", "Rate");
294dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(fp, "%8s/%-6s\n","TX Data", "Rate");
295dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
296dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!show_errors) {
297dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-15s ", "");
298dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "RX Errs", "Drop");
299dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "TX Errs", "Drop");
300dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "RX Over", "Rate");
301dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s\n","TX Coll", "Rate");
302dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else {
303dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-15s ", "");
304dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "RX Errs", "Rate");
305dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "RX Drop", "Rate");
306dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "RX Over", "Rate");
307dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s\n","RX Leng", "Rate");
308dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
309dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-15s ", "");
310dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "RX Crc", "Rate");
311dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "RX Frm", "Rate");
312dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "RX Fifo", "Rate");
313dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s\n","RX Miss", "Rate");
314dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
315dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-15s ", "");
316dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "TX Errs", "Rate");
317dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "TX Drop", "Rate");
318dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "TX Coll", "Rate");
319dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s\n","TX Carr", "Rate");
320dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
321dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-15s ", "");
322dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "TX Abrt", "Rate");
323dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "TX Fifo", "Rate");
324dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s ", "TX Hear", "Rate");
325dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%8s/%-6s\n","TX Wind", "Rate");
326dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
327dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
328dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
329dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid print_one_if(FILE *fp, struct ifstat_ent *n, unsigned long long *vals)
330dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
331dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int i;
332dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(fp, "%-15s ", n->name);
333dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (i=0; i<4; i++)
334dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, i);
335dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(fp, "\n");
336dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
337dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!show_errors) {
338dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-15s ", "");
339dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_pair(fp, vals, 4, 6);
340dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_pair(fp, vals, 5, 7);
341dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 11);
342dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 9);
343dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "\n");
344dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else {
345dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-15s ", "");
346dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 4);
347dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 6);
348dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 11);
349dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 10);
350dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "\n");
351dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
352dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-15s ", "");
353dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 12);
354dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 13);
355dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 14);
356dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 15);
357dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "\n");
358dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
359dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-15s ", "");
360dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 5);
361dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 7);
362dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 9);
363dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 17);
364dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "\n");
365dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
366dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%-15s ", "");
367dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 16);
368dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 18);
369dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 19);
370dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		format_rate(fp, vals, n->rate, 20);
371dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "\n");
372dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
373dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
374dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
375dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
376dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid dump_kern_db(FILE *fp)
377dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
378dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ifstat_ent *n, *h;
379dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	h = hist_db;
380dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
381dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	print_head(fp);
382dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
383dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (n=kern_db; n; n=n->next) {
384dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!match(n->name))
385dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			continue;
386dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		print_one_if(fp, n, n->val);
387dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
388dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
389dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
390dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
391dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid dump_incr_db(FILE *fp)
392dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
393dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ifstat_ent *n, *h;
394dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	h = hist_db;
395dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
396dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	print_head(fp);
397dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
398dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (n=kern_db; n; n=n->next) {
399dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int i;
400dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		unsigned long long vals[MAXS];
401dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct ifstat_ent *h1;
402dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
403dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		memcpy(vals, n->val, sizeof(vals));
404dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
405dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		for (h1 = h; h1; h1 = h1->next) {
406dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (h1->ifindex == n->ifindex) {
407dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				for (i = 0; i < MAXS; i++)
408dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					vals[i] -= h1->val[i];
409dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				h = h1->next;
410dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				break;
411dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
412dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
413dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!match(n->name))
414dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			continue;
415dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		print_one_if(fp, n, vals);
416dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
417dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
418dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
419dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
420dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int children;
421dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
422dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid sigchild(int signo)
423dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
424dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
425dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
426dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid update_db(int interval)
427dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
428dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ifstat_ent *n, *h;
429dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
430dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	n = kern_db;
431dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	kern_db = NULL;
432dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
433dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	load_info();
434dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
435dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	h = kern_db;
436dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	kern_db = n;
437dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
438dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (n = kern_db; n; n = n->next) {
439dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct ifstat_ent *h1;
440dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		for (h1 = h; h1; h1 = h1->next) {
441dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (h1->ifindex == n->ifindex) {
442dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				int i;
443dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				for (i = 0; i < MAXS; i++) {
444dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					if ((long)(h1->ival[i] - n->ival[i]) < 0) {
445dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat						memset(n->ival, 0, sizeof(n->ival));
446dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat						break;
447dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					}
448dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				}
449dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				for (i = 0; i < MAXS; i++) {
450dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					double sample;
451dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					unsigned long incr = h1->ival[i] - n->ival[i];
452dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					n->val[i] += incr;
453dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					n->ival[i] = h1->ival[i];
454dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					sample = (double)(incr*1000)/interval;
455dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					if (interval >= scan_interval) {
456dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat						n->rate[i] += W*(sample-n->rate[i]);
457dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					} else if (interval >= 1000) {
458dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat						if (interval >= time_constant) {
459dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat							n->rate[i] = sample;
460dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat						} else {
461dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat							double w = W*(double)interval/scan_interval;
462dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat							n->rate[i] += w*(sample-n->rate[i]);
463dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat						}
464dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					}
465dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				}
466dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
467dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				while (h != h1) {
468dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					struct ifstat_ent *tmp = h;
469dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					h = h->next;
470dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					free(tmp->name);
471dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					free(tmp);
472dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				};
473dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				h = h1->next;
474dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				free(h1->name);
475dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				free(h1);
476dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				break;
477dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
478dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
479dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
480dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
481dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
482dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#define T_DIFF(a,b) (((a).tv_sec-(b).tv_sec)*1000 + ((a).tv_usec-(b).tv_usec)/1000)
483dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
484dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
485dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid server_loop(int fd)
486dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
487dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct timeval snaptime = { 0 };
488dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct pollfd p;
489dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	p.fd = fd;
490dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	p.events = p.revents = POLLIN;
491dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
492dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	sprintf(info_source, "%d.%lu sampling_interval=%d time_const=%d",
493dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		getpid(), (unsigned long)random(), scan_interval/1000, time_constant/1000);
494dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
495dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	load_info();
496dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
497dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (;;) {
498dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int status;
499dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int tdiff;
500dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct timeval now;
501dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
502dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		gettimeofday(&now, NULL);
503dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		tdiff = T_DIFF(now, snaptime);
504dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (tdiff >= scan_interval) {
505dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			update_db(tdiff);
506dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			snaptime = now;
507dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			tdiff = 0;
508dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
509dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
510dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (poll(&p, 1, tdiff + scan_interval) > 0
511dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		    && (p.revents&POLLIN)) {
512dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			int clnt = accept(fd, NULL, NULL);
513dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (clnt >= 0) {
514dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				pid_t pid;
515dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				if (children >= 5) {
516dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					close(clnt);
517dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				} else if ((pid = fork()) != 0) {
518dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					if (pid>0)
519dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat						children++;
520dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					close(clnt);
521dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				} else {
522dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					FILE *fp = fdopen(clnt, "w");
523dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					if (fp) {
524dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat						if (tdiff > 0)
525dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat							update_db(tdiff);
526dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat						dump_raw_db(fp, 0);
527dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					}
528dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					exit(0);
529dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				}
530dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
531dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
532dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		while (children && waitpid(-1, &status, WNOHANG) > 0)
533dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			children--;
534dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
535dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
536dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
537dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint verify_forging(int fd)
538dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
539dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ucred cred;
540dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	socklen_t olen = sizeof(cred);
541dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
542dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, (void*)&cred, &olen) ||
543dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	    olen < sizeof(cred))
544dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
545dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (cred.uid == getuid() || cred.uid == 0)
546dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return 0;
547dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return -1;
548dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
549dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
550dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void usage(void) __attribute__((noreturn));
551dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
552dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void usage(void)
553dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
554dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stderr,
555dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"Usage: ifstat [OPTION] [ PATTERN [ PATTERN ] ]\n"
556dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"   -h, --help		this message\n"
557dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"   -a, --ignore	ignore history\n"
558dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"   -d, --scan=SECS	sample every statistics every SECS\n"
559dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"   -e, --errors	show errors\n"
560dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"   -n, --nooutput	do history only\n"
561dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"   -r, --reset		reset history\n"
562dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"   -s, --noupdate	don;t update history\n"
563dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"   -t, --interval=SECS	report average over the last SECS\n"
564dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"   -V, --version	output version information\n"
565dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"   -z, --zeros		show entries with zero activity\n"
566dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"   -e, --errors	show errors\n"
567dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat"   -z, --zeros		show entries with zero activity\n");
568dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
569dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	exit(-1);
570dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
571dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
572dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic const struct option longopts[] = {
573dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "help", 0, 0, 'h' },
574dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "ignore",  0,  0, 'a' },
575dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "scan", 1, 0, 'd'},
576dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "errors", 0, 0, 'e' },
577dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "nooutput", 0, 0, 'n' },
578dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "reset", 0, 0, 'r' },
579dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "noupdate", 0, 0, 's' },
580dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "interval", 1, 0, 't' },
581dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "version", 0, 0, 'V' },
582dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "zeros", 0, 0, 'z' },
583dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "errors", 0, 0, 'e' },
584dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "zeros", 0, 0, 'z' },
585dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ 0 }
586dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat};
587dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
588dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint main(int argc, char *argv[])
589dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
590dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char hist_name[128];
591dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct sockaddr_un sun;
592dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	FILE *hist_fp = NULL;
593dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int ch;
594dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int fd;
595dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
596dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	while ((ch = getopt_long(argc, argv, "hvVzrnasd:t:eK",
597dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			longopts, NULL)) != EOF) {
598dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		switch(ch) {
599dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case 'z':
600dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			dump_zeros = 1;
601dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
602dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case 'r':
603dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			reset_history = 1;
604dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
605dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case 'a':
606dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			ignore_history = 1;
607dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
608dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case 's':
609dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			no_update = 1;
610dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
611dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case 'n':
612dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			no_output = 1;
613dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
614dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case 'e':
615dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			show_errors = 1;
616dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
617dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case 'd':
618dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			scan_interval = atoi(optarg) * 1000;
619dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (scan_interval <= 0) {
620dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(stderr, "ifstat: invalid scan interval\n");
621dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				exit(-1);
622dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
623dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
624dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case 't':
625dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			time_constant = atoi(optarg);
626dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (time_constant <= 0) {
627dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(stderr, "ifstat: invalid time constant divisor\n");
628dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				exit(-1);
629dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
630dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
631dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case 'v':
632dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case 'V':
633dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			printf("ifstat utility, iproute2-ss%s\n", SNAPSHOT);
634dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			exit(0);
635dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case 'h':
636dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case '?':
637dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		default:
638dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			usage();
639dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
640dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
641dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
642dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	argc -= optind;
643dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	argv += optind;
644dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
645dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	sun.sun_family = AF_UNIX;
646dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	sun.sun_path[0] = 0;
647dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	sprintf(sun.sun_path+1, "ifstat%d", getuid());
648dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
649dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (scan_interval > 0) {
650dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (time_constant == 0)
651dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			time_constant = 60;
652dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		time_constant *= 1000;
653dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		W = 1 - 1/exp(log(10)*(double)scan_interval/time_constant);
654dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
655dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			perror("ifstat: socket");
656dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			exit(-1);
657dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
658dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (bind(fd, (struct sockaddr*)&sun, 2+1+strlen(sun.sun_path+1)) < 0) {
659dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			perror("ifstat: bind");
660dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			exit(-1);
661dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
662dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (listen(fd, 5) < 0) {
663dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			perror("ifstat: listen");
664dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			exit(-1);
665dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
666dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (daemon(0, 0)) {
667dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			perror("ifstat: daemon");
668dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			exit(-1);
669dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
670dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		signal(SIGPIPE, SIG_IGN);
671dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		signal(SIGCHLD, sigchild);
672dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		server_loop(fd);
673dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		exit(0);
674dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
675dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
676dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	patterns = argv;
677dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	npatterns = argc;
678dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
679dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (getenv("IFSTAT_HISTORY"))
680dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(hist_name, sizeof(hist_name), getenv("IFSTAT_HISTORY"));
681dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else
682dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		sprintf(hist_name, "%s/.ifstat.u%d", P_tmpdir, getuid());
683dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
684dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (reset_history)
685dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		unlink(hist_name);
686dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
687dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!ignore_history || !no_update) {
688dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct stat stb;
689dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
690dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fd = open(hist_name, O_RDWR|O_CREAT|O_NOFOLLOW, 0600);
691dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (fd < 0) {
692dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			perror("ifstat: open history file");
693dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			exit(-1);
694dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
695dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if ((hist_fp = fdopen(fd, "r+")) == NULL) {
696dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			perror("ifstat: fdopen history file");
697dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			exit(-1);
698dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
699dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (flock(fileno(hist_fp), LOCK_EX)) {
700dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			perror("ifstat: flock history file");
701dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			exit(-1);
702dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
703dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (fstat(fileno(hist_fp), &stb) != 0) {
704dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			perror("ifstat: fstat history file");
705dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			exit(-1);
706dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
707dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (stb.st_nlink != 1 || stb.st_uid != getuid()) {
708dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr, "ifstat: something is so wrong with history file, that I prefer not to proceed.\n");
709dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			exit(-1);
710dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
711dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!ignore_history) {
712dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			FILE *tfp;
713dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			long uptime;
714dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if ((tfp = fopen("/proc/uptime", "r")) != NULL) {
715dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				if (fscanf(tfp, "%ld", &uptime) != 1)
716dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					uptime = -1;
717dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fclose(tfp);
718dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
719dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (uptime >= 0 && time(NULL) >= stb.st_mtime+uptime) {
720dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(stderr, "ifstat: history is aged out, resetting\n");
721dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				ftruncate(fileno(hist_fp), 0);
722dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
723dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
724dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
725dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		load_raw_table(hist_fp);
726dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
727dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		hist_db = kern_db;
728dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		kern_db = NULL;
729dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
730dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
731dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0 &&
732dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	    (connect(fd, (struct sockaddr*)&sun, 2+1+strlen(sun.sun_path+1)) == 0
733dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	     || (strcpy(sun.sun_path+1, "ifstat0"),
734dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		 connect(fd, (struct sockaddr*)&sun, 2+1+strlen(sun.sun_path+1)) == 0))
735dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	    && verify_forging(fd) == 0) {
736dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		FILE *sfp = fdopen(fd, "r");
737dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		load_raw_table(sfp);
738dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (hist_db && source_mismatch) {
739dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr, "ifstat: history is stale, ignoring it.\n");
740dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			hist_db = NULL;
741dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
742dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fclose(sfp);
743dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else {
744dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (fd >= 0)
745dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			close(fd);
746dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (hist_db && info_source[0] && strcmp(info_source, "kernel")) {
747dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr, "ifstat: history is stale, ignoring it.\n");
748dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			hist_db = NULL;
749dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			info_source[0] = 0;
750dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
751dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		load_info();
752dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (info_source[0] == 0)
753dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			strcpy(info_source, "kernel");
754dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
755dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
756dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!no_output) {
757dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (ignore_history || hist_db == NULL)
758dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			dump_kern_db(stdout);
759dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else
760dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			dump_incr_db(stdout);
761dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
762dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!no_update) {
763dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		ftruncate(fileno(hist_fp), 0);
764dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		rewind(hist_fp);
765dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		dump_raw_db(hist_fp, 1);
766dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fflush(hist_fp);
767dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
768dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	exit(0);
769dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
770