GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/pppd/pppstats/pppstats.c Lines: 0 174 0.0 %
Date: 2017-11-13 Branches: 0 196 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: pppstats.c,v 1.12 2015/02/09 23:00:14 deraadt Exp $	*/
2
3
/*
4
 * print PPP statistics:
5
 * 	pppstats [-a|-d] [-v|-r|-z] [-c count] [-w wait] [interface]
6
 *
7
 *   -a Show absolute values rather than deltas
8
 *   -d Show data rate (KB/s) rather than bytes
9
 *   -v Show more stats for VJ TCP header compression
10
 *   -r Show compression ratio
11
 *   -z Show compression statistics instead of default display
12
 *
13
 * History:
14
 *      perkins@cps.msu.edu: Added compression statistics and alternate
15
 *                display. 11/94
16
 *      Brad Parker (brad@cayman.com) 6/92
17
 *
18
 * from the original "slstats" by Van Jacobson:
19
 *
20
 * Contributed by Van Jacobson (van@ee.lbl.gov), Dec 31, 1989.
21
 *
22
 * Copyright (c) 1989, 1990, 1991, 1992 Regents of the University of
23
 * California. All rights reserved.
24
 *
25
 * Redistribution and use in source and binary forms, with or without
26
 * modification, are permitted provided that the following conditions
27
 * are met:
28
 * 1. Redistributions of source code must retain the above copyright
29
 *    notice, this list of conditions and the following disclaimer.
30
 * 2. Redistributions in binary form must reproduce the above copyright
31
 *    notice, this list of conditions and the following disclaimer in the
32
 *    documentation and/or other materials provided with the distribution.
33
 * 3. Neither the name of the University nor the names of its contributors
34
 *    may be used to endorse or promote products derived from this software
35
 *    without specific prior written permission.
36
 *
37
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
38
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
41
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47
 * SUCH DAMAGE.
48
 */
49
50
#include <sys/types.h>
51
#include <sys/ioctl.h>
52
#include <sys/socket.h>
53
#include <net/ppp_defs.h>
54
#include <net/if.h>
55
#include <net/if_ppp.h>
56
#include <stdio.h>
57
#include <stddef.h>
58
#include <stdlib.h>
59
#include <string.h>
60
#include <ctype.h>
61
#include <errno.h>
62
#include <signal.h>
63
#include <fcntl.h>
64
#include <err.h>
65
#include <unistd.h>
66
67
int	vflag, rflag, zflag;	/* select type of display */
68
int	aflag;			/* print absolute values, not deltas */
69
int	dflag;			/* print data rates, not bytes */
70
int	interval, count;
71
int	infinite;
72
int	unit;
73
int	s;			/* socket file descriptor */
74
int	signalled;		/* set if alarm goes off "early" */
75
char	interface[IFNAMSIZ];
76
77
void usage(void);
78
void catchalarm(int);
79
void get_ppp_stats(struct ppp_stats *);
80
void get_ppp_cstats(struct ppp_comp_stats *);
81
void intpr(void);
82
int main(int, char *argv[]);
83
84
void
85
usage()
86
{
87
	extern char *__progname;
88
89
	fprintf(stderr,
90
	    "usage: %s [-adrvz] [-c count] [-w wait] [interface]\n",
91
	    __progname);
92
	exit(1);
93
}
94
95
/*
96
 * Called if an interval expires before intpr has completed a loop.
97
 * Sets a flag to not wait for the alarm.
98
 */
99
void
100
catchalarm(arg)
101
	int arg;
102
{
103
	signalled = 1;
104
}
105
106
void
107
get_ppp_stats(curp)
108
	struct ppp_stats *curp;
109
{
110
	struct ifpppstatsreq req;
111
112
	memset(&req, 0, sizeof(req));
113
	(void)strlcpy(req.ifr_name, interface, sizeof(req.ifr_name));
114
115
	if (ioctl(s, SIOCGPPPSTATS, &req) < 0) {
116
		if (errno == ENOTTY)
117
			errx(1, "kernel support missing");
118
		else
119
			err(1, "couldn't get PPP statistics");
120
	}
121
	*curp = req.stats;
122
}
123
124
void
125
get_ppp_cstats(csp)
126
	struct ppp_comp_stats *csp;
127
{
128
	struct ifpppcstatsreq creq;
129
130
	memset(&creq, 0, sizeof(creq));
131
	(void)strlcpy(creq.ifr_name, interface, sizeof(creq.ifr_name));
132
133
	if (ioctl(s, SIOCGPPPCSTATS, &creq) < 0) {
134
		if (errno == ENOTTY) {
135
			warnx("no kernel compression support");
136
			if (zflag)
137
				exit(1);
138
			rflag = 0;
139
		} else
140
			err(1, "couldn't get PPP compression stats");
141
	}
142
	*csp = creq.stats;
143
}
144
145
#define MAX0(a)		((int)(a) > 0? (a): 0)
146
#define V(offset)	MAX0(cur.offset - old.offset)
147
#define W(offset)	MAX0(ccs.offset - ocs.offset)
148
149
#define RATIO(c, i, u)	((c) == 0? 1.0: (u) / ((double)(c) + (i)))
150
#define CRATE(x)	RATIO(W(x.comp_bytes), W(x.inc_bytes), W(x.unc_bytes))
151
152
#define KBPS(n)		((n) / (interval * 1000.0))
153
154
/*
155
 * Print a running summary of interface statistics.
156
 * Repeat display every interval seconds, showing statistics
157
 * collected over that interval.  Assumes that interval is non-zero.
158
 * First line printed is cumulative.
159
 */
160
void
161
intpr()
162
{
163
	register int line = 0;
164
	sigset_t oldmask, mask;
165
	char *bunit;
166
	int ratef = 0;
167
	struct ppp_stats cur, old;
168
	struct ppp_comp_stats ccs, ocs;
169
170
	memset(&old, 0, sizeof(old));
171
	memset(&ocs, 0, sizeof(ocs));
172
173
	for (;;) {
174
		get_ppp_stats(&cur);
175
		if (zflag || rflag)
176
			get_ppp_cstats(&ccs);
177
178
		(void)signal(SIGALRM, catchalarm);
179
		signalled = 0;
180
		(void)alarm(interval);
181
182
		if ((line % 20) == 0) {
183
			if (zflag) {
184
				printf("IN:  COMPRESSED  INCOMPRESSIBLE   COMP | ");
185
				printf("OUT: COMPRESSED  INCOMPRESSIBLE   COMP\n");
186
				bunit = dflag? "KB/S": "BYTE";
187
				printf("    %s   PACK     %s   PACK  RATIO | ",
188
				    bunit, bunit);
189
				printf("    %s   PACK     %s   PACK  RATIO",
190
				    bunit, bunit);
191
			} else {
192
				printf("%8.8s %6.6s %6.6s",
193
					"IN", "PACK", "VJCOMP");
194
195
				if (!rflag)
196
					printf(" %6.6s %6.6s", "VJUNC", "VJERR");
197
				if (vflag)
198
					printf(" %6.6s %6.6s", "VJTOSS", "NON-VJ");
199
				if (rflag)
200
					printf(" %6.6s %6.6s", "RATIO", "UBYTE");
201
				printf("  | %8.8s %6.6s %6.6s",
202
					"OUT", "PACK", "VJCOMP");
203
204
				if (!rflag)
205
					printf(" %6.6s %6.6s", "VJUNC", "NON-VJ");
206
				if (vflag)
207
					printf(" %6.6s %6.6s", "VJSRCH", "VJMISS");
208
				if (rflag)
209
					printf(" %6.6s %6.6s", "RATIO", "UBYTE");
210
			}
211
			putchar('\n');
212
		}
213
214
		if (zflag) {
215
			if (ratef) {
216
				printf("%8.3f %6u %8.3f %6u %6.2f",
217
				    KBPS(W(d.comp_bytes)), W(d.comp_packets),
218
				    KBPS(W(d.inc_bytes)), W(d.inc_packets),
219
				    ccs.d.ratio * 256.0);
220
221
				printf(" | %8.3f %6u %8.3f %6u %6.2f",
222
				    KBPS(W(c.comp_bytes)), W(c.comp_packets),
223
				    KBPS(W(c.inc_bytes)), W(c.inc_packets),
224
				    ccs.c.ratio * 256.0);
225
			} else {
226
				printf("%8u %6u %8u %6u %6.2f",
227
				   W(d.comp_bytes), W(d.comp_packets),
228
				   W(d.inc_bytes), W(d.inc_packets),
229
				   ccs.d.ratio * 256.0);
230
231
				printf(" | %8u %6u %8u %6u %6.2f",
232
				   W(c.comp_bytes), W(c.comp_packets),
233
				   W(c.inc_bytes), W(c.inc_packets),
234
				   ccs.c.ratio * 256.0);
235
			}
236
		} else {
237
			if (ratef)
238
				printf("%8.3f", KBPS(V(p.ppp_ibytes)));
239
			else
240
				printf("%8u", V(p.ppp_ibytes));
241
			printf(" %6u %6u", V(p.ppp_ipackets),
242
			    V(vj.vjs_compressedin));
243
			if (!rflag)
244
				printf(" %6u %6u", V(vj.vjs_uncompressedin),
245
				   V(vj.vjs_errorin));
246
			if (vflag)
247
				printf(" %6u %6u", V(vj.vjs_tossed),
248
				   V(p.ppp_ipackets) -
249
				   V(vj.vjs_compressedin) -
250
				   V(vj.vjs_uncompressedin) -
251
				   V(vj.vjs_errorin));
252
			if (rflag) {
253
				printf(" %6.2f ", CRATE(d));
254
				if (ratef)
255
					printf("%6.2f", KBPS(W(d.unc_bytes)));
256
				else
257
					printf("%6u", W(d.unc_bytes));
258
			}
259
			if (ratef)
260
				printf("  | %8.3f", KBPS(V(p.ppp_obytes)));
261
			else
262
				printf("  | %8u", V(p.ppp_obytes));
263
264
			printf(" %6u %6u", V(p.ppp_opackets),
265
			    V(vj.vjs_compressed));
266
			if (!rflag)
267
				printf(" %6u %6u",
268
				   V(vj.vjs_packets) - V(vj.vjs_compressed),
269
				   V(p.ppp_opackets) - V(vj.vjs_packets));
270
			if (vflag)
271
				printf(" %6u %6u", V(vj.vjs_searches),
272
				   V(vj.vjs_misses));
273
			if (rflag) {
274
				printf(" %6.2f ", CRATE(c));
275
				if (ratef)
276
					printf("%6.2f", KBPS(W(c.unc_bytes)));
277
				else
278
					printf("%6u", W(c.unc_bytes));
279
			}
280
		}
281
282
		putchar('\n');
283
		fflush(stdout);
284
		line++;
285
286
		count--;
287
		if (!infinite && !count)
288
			break;
289
290
		sigemptyset(&mask);
291
		sigaddset(&mask, SIGALRM);
292
		sigprocmask(SIG_BLOCK, &mask, &oldmask);
293
		if (signalled == 0) {
294
			sigemptyset(&mask);
295
			sigsuspend(&mask);
296
		}
297
		sigprocmask(SIG_SETMASK, &oldmask, NULL);
298
		signalled = 0;
299
		(void)alarm(interval);
300
		if (!aflag) {
301
			old = cur;
302
			ocs = ccs;
303
			ratef = dflag;
304
		}
305
	}
306
}
307
308
int
309
main(argc, argv)
310
	int argc;
311
	char *argv[];
312
{
313
	int c;
314
	struct ifreq ifr;
315
316
	(void)strlcpy(interface, "ppp0", sizeof(interface));
317
318
	while ((c = getopt(argc, argv, "advrzc:w:")) != -1) {
319
		switch (c) {
320
		case 'a':
321
			aflag = 1;
322
			break;
323
		case 'd':
324
			dflag = 1;
325
			break;
326
		case 'v':
327
			vflag = 1;
328
			break;
329
		case 'r':
330
			rflag = 1;
331
			break;
332
		case 'z':
333
			zflag = 1;
334
			break;
335
		case 'c':
336
			count = atoi(optarg);
337
			if (count <= 0)
338
				usage();
339
			break;
340
		case 'w':
341
			interval = atoi(optarg);
342
			if (interval <= 0)
343
				usage();
344
			break;
345
		default:
346
			usage();
347
		}
348
	}
349
	argc -= optind;
350
	argv += optind;
351
352
	if (!interval && count)
353
		interval = 5;
354
	if (interval && !count)
355
		infinite = 1;
356
	if (!interval && !count)
357
		count = 1;
358
	if (aflag)
359
		dflag = 0;
360
361
	if (argc > 1)
362
		usage();
363
	if (argc > 0)
364
		(void)strlcpy(interface, argv[0], sizeof(interface));
365
366
	if (sscanf(interface, "ppp%d", &unit) != 1 || unit < 0)
367
		errx(1, "invalid interface '%s' specified", interface);
368
369
	s = socket(AF_INET, SOCK_DGRAM, 0);
370
	if (s < 0)
371
		err(1, "couldn't create IP socket");
372
	(void)strlcpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
373
	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0)
374
		errx(1, "nonexistent interface '%s' specified", interface);
375
376
	intpr();
377
	exit(0);
378
}