GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/systat/if.c Lines: 0 141 0.0 %
Date: 2017-11-07 Branches: 0 82 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: if.c,v 1.23 2015/01/16 00:03:37 deraadt Exp $ */
2
/*
3
 * Copyright (c) 2004 Markus Friedl <markus@openbsd.org>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <sys/param.h>	/* roundup */
19
#include <sys/signal.h>
20
#include <sys/socket.h>
21
#include <sys/sysctl.h>
22
#include <net/if.h>
23
#include <net/if_dl.h>
24
#include <net/route.h>
25
#include <sys/sockio.h>
26
#include <sys/ioctl.h>
27
28
#include <stdlib.h>
29
#include <string.h>
30
#include <unistd.h>
31
32
#include "systat.h"
33
34
static  enum state { BOOT, TIME, RUN } state = TIME;
35
36
struct ifstat {
37
	char		ifs_name[IFNAMSIZ];	/* interface name */
38
	char		ifs_description[IFDESCRSIZE];
39
	struct ifcount	ifs_cur;
40
	struct ifcount	ifs_old;
41
	struct ifcount	ifs_now;
42
	char		ifs_flag;
43
} *ifstats;
44
45
static	int nifs = 0;
46
static int num_ifs = 0;
47
static int show_bits = 0;
48
49
void print_if(void);
50
int read_if(void);
51
int select_if(void);
52
int if_keyboard_callback(int);
53
54
void fetchifstat(void);
55
static void showifstat(struct ifstat *);
56
static void showtotal(void);
57
static void rt_getaddrinfo(struct sockaddr *, int, struct sockaddr **);
58
59
60
/* Define fields */
61
field_def fields_if[] = {
62
	{"IFACE", 8, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
63
	{"STATE", 4, 6, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
64
	{"IPKTS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
65
	{"IBYTES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
66
	{"IERRS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
67
	{"OPKTS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
68
	{"OBYTES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
69
	{"OERRS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
70
	{"COLLS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
71
	{"DESC", 14, 64, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
72
};
73
74
75
#define FLD_IF_IFACE	FIELD_ADDR(fields_if,0)
76
#define FLD_IF_STATE	FIELD_ADDR(fields_if,1)
77
#define FLD_IF_IPKTS	FIELD_ADDR(fields_if,2)
78
#define FLD_IF_IBYTES	FIELD_ADDR(fields_if,3)
79
#define FLD_IF_IERRS	FIELD_ADDR(fields_if,4)
80
#define FLD_IF_OPKTS	FIELD_ADDR(fields_if,5)
81
#define FLD_IF_OBYTES	FIELD_ADDR(fields_if,6)
82
#define FLD_IF_OERRS	FIELD_ADDR(fields_if,7)
83
#define FLD_IF_COLLS	FIELD_ADDR(fields_if,8)
84
#define FLD_IF_DESC	FIELD_ADDR(fields_if,9)
85
86
87
/* Define views */
88
field_def *view_if_0[] = {
89
	FLD_IF_IFACE, FLD_IF_STATE, FLD_IF_DESC, FLD_IF_IPKTS,
90
	FLD_IF_IBYTES, FLD_IF_IERRS, FLD_IF_OPKTS, FLD_IF_OBYTES,
91
	FLD_IF_OERRS, FLD_IF_COLLS, NULL
92
};
93
94
/* Define view managers */
95
96
struct view_manager ifstat_mgr = {
97
	"Ifstat", select_if, read_if, NULL, print_header,
98
	print_if, if_keyboard_callback, NULL, NULL
99
};
100
101
field_view views_if[] = {
102
	{view_if_0, "ifstat", '1', &ifstat_mgr},
103
	{NULL, NULL, 0, NULL}
104
};
105
106
107
int
108
initifstat(void)
109
{
110
	field_view *v;
111
	read_if();
112
	for (v = views_if; v->name != NULL; v++)
113
		add_view(v);
114
115
	return(1);
116
}
117
118
#define UPDATE(x, y) do { \
119
		ifs->ifs_now.x = ifm.y; \
120
		ifs->ifs_cur.x = ifs->ifs_now.x - ifs->ifs_old.x; \
121
		if (state == TIME) {\
122
			ifs->ifs_old.x = ifs->ifs_now.x; \
123
			ifs->ifs_cur.x /= naptime; \
124
		} \
125
		sum.x += ifs->ifs_cur.x; \
126
	} while(0)
127
128
129
void
130
rt_getaddrinfo(struct sockaddr *sa, int addrs, struct sockaddr **info)
131
{
132
	int i;
133
134
	for (i = 0; i < RTAX_MAX; i++) {
135
		if (addrs & (1 << i)) {
136
			info[i] = sa;
137
			sa = (struct sockaddr *) ((char *)(sa) +
138
			    roundup(sa->sa_len, sizeof(long)));
139
		} else
140
			info[i] = NULL;
141
	}
142
}
143
144
145
146
int
147
select_if(void)
148
{
149
	num_disp = num_ifs + 1;
150
	return (0);
151
}
152
153
int
154
read_if(void)
155
{
156
	fetchifstat();
157
	num_disp = num_ifs + 1;
158
159
	return 0;
160
}
161
162
void
163
print_if(void)
164
{
165
	int n, i, count = 0;
166
167
	for (n = 0, i = 0; n < nifs; n++) {
168
		if (ifstats[n].ifs_name[0] == '\0')
169
			continue;
170
		if (i++ < dispstart)
171
			continue;
172
		if (i == num_disp)
173
			break;
174
		showifstat(ifstats + n);
175
		if (maxprint > 0 && ++count >= maxprint)
176
			return;
177
	}
178
	showtotal();
179
}
180
181
182
void
183
fetchifstat(void)
184
{
185
	struct ifstat *newstats, *ifs;
186
	struct if_msghdr ifm;
187
	struct sockaddr *info[RTAX_MAX];
188
	struct sockaddr_dl *sdl;
189
	char *buf, *next, *lim;
190
	int mib[6], i;
191
	size_t need;
192
193
	mib[0] = CTL_NET;
194
	mib[1] = PF_ROUTE;
195
	mib[2] = 0;
196
	mib[3] = 0;
197
	mib[4] = NET_RT_IFLIST;
198
	mib[5] = 0;
199
200
	if (sysctl(mib, 6, NULL, &need, NULL, 0) == -1)
201
		return;
202
	if ((buf = malloc(need)) == NULL)
203
		return;
204
	if (sysctl(mib, 6, buf, &need, NULL, 0) == -1) {
205
		free(buf);
206
		return;
207
	}
208
209
	bzero(&sum, sizeof(sum));
210
	num_ifs = 0;
211
212
	lim = buf + need;
213
	for (next = buf; next < lim; next += ifm.ifm_msglen) {
214
		bcopy(next, &ifm, sizeof ifm);
215
		if (ifm.ifm_version != RTM_VERSION ||
216
		    ifm.ifm_type != RTM_IFINFO ||
217
		    !(ifm.ifm_addrs & RTA_IFP))
218
			continue;
219
		if (ifm.ifm_index >= nifs) {
220
			if ((newstats = reallocarray(ifstats, ifm.ifm_index + 4,
221
			    sizeof(struct ifstat))) == NULL)
222
				continue;
223
			ifstats = newstats;
224
			for (; nifs < ifm.ifm_index + 4; nifs++)
225
				bzero(&ifstats[nifs], sizeof(*ifstats));
226
		}
227
		ifs = &ifstats[ifm.ifm_index];
228
		if (ifs->ifs_name[0] == '\0') {
229
			bzero(&info, sizeof(info));
230
			rt_getaddrinfo(
231
			    (struct sockaddr *)((struct if_msghdr *)next + 1),
232
			    ifm.ifm_addrs, info);
233
			sdl = (struct sockaddr_dl *)info[RTAX_IFP];
234
235
			if (sdl && sdl->sdl_family == AF_LINK &&
236
			    sdl->sdl_nlen > 0) {
237
				struct ifreq ifrdesc;
238
				char ifdescr[IFDESCRSIZE];
239
				int s;
240
241
				bcopy(sdl->sdl_data, ifs->ifs_name,
242
				      sdl->sdl_nlen);
243
				ifs->ifs_name[sdl->sdl_nlen] = '\0';
244
245
				/* Get the interface description */
246
				memset(&ifrdesc, 0, sizeof(ifrdesc));
247
				strlcpy(ifrdesc.ifr_name, ifs->ifs_name,
248
					sizeof(ifrdesc.ifr_name));
249
				ifrdesc.ifr_data = (caddr_t)&ifdescr;
250
251
				s = socket(AF_INET, SOCK_DGRAM, 0);
252
				if (s != -1) {
253
					if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0)
254
						strlcpy(ifs->ifs_description,
255
						    ifrdesc.ifr_data,
256
						    sizeof(ifs->ifs_description));
257
					close(s);
258
				}
259
			}
260
			if (ifs->ifs_name[0] == '\0')
261
				continue;
262
		}
263
		num_ifs++;
264
		UPDATE(ifc_ip, ifm_data.ifi_ipackets);
265
		UPDATE(ifc_ib, ifm_data.ifi_ibytes);
266
		UPDATE(ifc_ie, ifm_data.ifi_ierrors);
267
		UPDATE(ifc_op, ifm_data.ifi_opackets);
268
		UPDATE(ifc_ob, ifm_data.ifi_obytes);
269
		UPDATE(ifc_oe, ifm_data.ifi_oerrors);
270
		UPDATE(ifc_co, ifm_data.ifi_collisions);
271
		ifs->ifs_cur.ifc_flags = ifm.ifm_flags;
272
		ifs->ifs_cur.ifc_state = ifm.ifm_data.ifi_link_state;
273
		ifs->ifs_flag++;
274
	}
275
276
	/* remove unreferenced interfaces */
277
	for (i = 0; i < nifs; i++) {
278
		ifs = &ifstats[i];
279
		if (ifs->ifs_flag)
280
			ifs->ifs_flag = 0;
281
		else
282
			ifs->ifs_name[0] = '\0';
283
	}
284
285
	free(buf);
286
}
287
288
289
static void
290
showifstat(struct ifstat *ifs)
291
{
292
	int conv = show_bits ? 8 : 1;
293
	int div = show_bits ? 1000 : 1024;
294
295
	print_fld_str(FLD_IF_IFACE, ifs->ifs_name);
296
297
	tb_start();
298
	tbprintf("%s", ifs->ifs_cur.ifc_flags & IFF_UP ?
299
		 "up" : "dn");
300
301
	switch (ifs->ifs_cur.ifc_state) {
302
	case LINK_STATE_UP:
303
	case LINK_STATE_HALF_DUPLEX:
304
	case LINK_STATE_FULL_DUPLEX:
305
		tbprintf(":U");
306
		break;
307
	case LINK_STATE_DOWN:
308
		tbprintf (":D");
309
		break;
310
	}
311
312
	print_fld_tb(FLD_IF_STATE);
313
314
	print_fld_str(FLD_IF_DESC, ifs->ifs_description);
315
316
	print_fld_sdiv(FLD_IF_IBYTES, ifs->ifs_cur.ifc_ib * conv, div);
317
	print_fld_size(FLD_IF_IPKTS, ifs->ifs_cur.ifc_ip);
318
	print_fld_size(FLD_IF_IERRS, ifs->ifs_cur.ifc_ie);
319
320
	print_fld_sdiv(FLD_IF_OBYTES, ifs->ifs_cur.ifc_ob * conv, div);
321
	print_fld_size(FLD_IF_OPKTS, ifs->ifs_cur.ifc_op);
322
	print_fld_size(FLD_IF_OERRS, ifs->ifs_cur.ifc_oe);
323
324
	print_fld_size(FLD_IF_COLLS, ifs->ifs_cur.ifc_co);
325
326
	end_line();
327
}
328
329
static void
330
showtotal(void)
331
{
332
	int conv = show_bits ? 8 : 1;
333
	int div = show_bits ? 1000 : 1024;
334
335
	print_fld_str(FLD_IF_IFACE, "Totals");
336
337
	print_fld_sdiv(FLD_IF_IBYTES, sum.ifc_ib * conv, div);
338
	print_fld_size(FLD_IF_IPKTS, sum.ifc_ip);
339
	print_fld_size(FLD_IF_IERRS, sum.ifc_ie);
340
341
	print_fld_sdiv(FLD_IF_OBYTES, sum.ifc_ob * conv, div);
342
	print_fld_size(FLD_IF_OPKTS, sum.ifc_op);
343
	print_fld_size(FLD_IF_OERRS, sum.ifc_oe);
344
345
	print_fld_size(FLD_IF_COLLS, sum.ifc_co);
346
347
	end_line();
348
349
}
350
351
int
352
if_keyboard_callback(int ch)
353
{
354
	struct ifstat *ifs;
355
356
	switch (ch) {
357
	case 'r':
358
		for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
359
			ifs->ifs_old = ifs->ifs_now;
360
		state = RUN;
361
		gotsig_alarm = 1;
362
363
		break;
364
	case 'b':
365
		state = BOOT;
366
		for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
367
			bzero(&ifs->ifs_old, sizeof(ifs->ifs_old));
368
		gotsig_alarm = 1;
369
		break;
370
	case 'B':
371
		show_bits = !show_bits;
372
		if (show_bits) {
373
			FLD_IF_IBYTES->title = "IBITS";
374
			FLD_IF_OBYTES->title = "OBITS";
375
		} else {
376
			FLD_IF_IBYTES->title = "IBYTES";
377
			FLD_IF_OBYTES->title = "OBYTES";
378
		}
379
		gotsig_alarm = 1;
380
		break;
381
	case 't':
382
		state = TIME;
383
		gotsig_alarm = 1;
384
		break;
385
	default:
386
		return keyboard_callback(ch);
387
	};
388
389
	return 1;
390
}
391