use SIOCGPPPSTATS ioctl on a socket instead of poking around
[ppp.git] / pppstats / pppstats.c
1 /*
2  * print PPP statistics:
3  *      pppstats [-i interval] [-v] [interface]
4  *
5  *      Brad Parker (brad@cayman.com) 6/92
6  *
7  * from the original "slstats" by Van Jaconson
8  *
9  * Copyright (c) 1989 Regents of the University of California.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms are permitted
13  * provided that the above copyright notice and this paragraph are
14  * duplicated in all such forms and that any documentation,
15  * advertising materials, and other materials related to such
16  * distribution and use acknowledge that the software was developed
17  * by the University of California, Berkeley.  The name of the
18  * University may not be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
22  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23  *
24  *      Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
25  *      - Initial distribution.
26  */
27
28 #ifndef lint
29 static char rcsid[] = "$Id: pppstats.c,v 1.5 1994/09/19 04:14:37 paulus Exp $";
30 #endif
31
32 #include <ctype.h>
33 #include <errno.h>
34 #include <nlist.h>
35 #include <stdio.h>
36 #include <signal.h>
37 #include <sys/param.h>
38 #include <sys/mbuf.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <sys/file.h>
42 #include <net/if.h>
43 #include <netinet/in.h>
44 #include <netinet/in_systm.h>
45 #include <netinet/ip.h>
46 #include <netinet/ip_var.h>
47
48 #include <net/ppp_defs.h>
49
50 #ifndef STREAMS
51 #include <net/if_ppp.h>
52 #endif
53
54 #ifdef STREAMS
55 #define PPP_STATS       1       /* should be defined iff it is in ppp_if.c */
56 #include <sys/stream.h>
57 #include <net/ppp_str.h>
58 #endif
59
60 int     vflag;
61 unsigned interval = 5;
62 int     unit;
63 int     s;                      /* socket file descriptor */
64 int     signalled;              /* set if alarm goes off "early" */
65
66 extern  char *malloc();
67 void catchalarm __P((int));
68
69 main(argc, argv)
70     int argc;
71     char *argv[];
72 {
73     --argc; ++argv;
74     while (argc > 0) {
75         if (strcmp(argv[0], "-v") == 0) {
76             ++vflag;
77             ++argv, --argc;
78             continue;
79         }
80         if (strcmp(argv[0], "-i") == 0 && argv[1] &&
81             isdigit(argv[1][0])) {
82             interval = atoi(argv[1]);
83             if (interval <= 0)
84                 usage();
85             ++argv, --argc;
86             ++argv, --argc;
87             continue;
88         }
89         if (isdigit(argv[0][0])) {
90             unit = atoi(argv[0]);
91             if (unit < 0)
92                 usage();
93             ++argv, --argc;
94             continue;
95         }
96         usage();
97     }
98     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
99         perror("couldn't create IP socket");
100         exit(1);
101     }
102     intpr();
103     exit(0);
104 }
105
106 usage()
107 {
108     fprintf(stderr, "Usage: pppstats [-v] [-i interval] [unit]\n");
109     exit(1);
110 }
111
112 #define V(offset) (line % 20? req.stats.offset - osc.offset: req.stats.offset)
113
114 /*
115  * Print a running summary of interface statistics.
116  * Repeat display every interval seconds, showing statistics
117  * collected over that interval.  Assumes that interval is non-zero.
118  * First line printed at top of screen is always cumulative.
119  */
120 intpr()
121 {
122     register int line = 0;
123     int oldmask;
124     struct ifpppstatsreq req;
125     struct ppp_stats osc;
126
127     bzero(&osc, sizeof(osc));
128
129     sprintf(req.ifr_name, "ppp%d", unit);
130     while (1) {
131         if (ioctl(s, SIOCGPPPSTATS, &req) < 0) {
132             if (errno == ENOTTY)
133                 fprintf(stderr, "pppstats: kernel support missing\n");
134             else
135                 perror("ioctl(SIOCGPPPSTATS)");
136             exit(1);
137         }
138         (void)signal(SIGALRM, catchalarm);
139         signalled = 0;
140         (void)alarm(interval);
141
142         if ((line % 20) == 0) {
143             printf("%6.6s %6.6s %6.6s %6.6s %6.6s",
144                    "in", "pack", "comp", "uncomp", "err");
145             if (vflag)
146                 printf(" %6.6s %6.6s", "toss", "ip");
147             printf(" | %6.6s %6.6s %6.6s %6.6s %6.6s",
148                    "out", "pack", "comp", "uncomp", "ip");
149             if (vflag)
150                 printf(" %6.6s %6.6s", "search", "miss");
151             putchar('\n');
152         }
153
154         printf("%6d %6d %6d %6d %6d", V(p.ppp_ibytes),
155                V(p.ppp_ipackets), V(vj.vjs_compressedin),
156                V(vj.vjs_uncompressedin), V(vj.vjs_errorin));
157         if (vflag)
158             printf(" %6d %6d", V(vj.vjs_tossed),
159                    V(p.ppp_ipackets) - V(vj.vjs_compressedin) -
160                      V(vj.vjs_uncompressedin) - V(vj.vjs_errorin));
161         printf(" | %6d %6d %6d %6d %6d", V(p.ppp_obytes),
162                V(p.ppp_opackets), V(vj.vjs_compressed),
163                V(vj.vjs_packets) - V(vj.vjs_compressed),
164                V(p.ppp_opackets) - V(vj.vjs_packets));
165         if (vflag)
166             printf(" %6d %6d", V(vj.vjs_searches), V(vj.vjs_misses));
167
168         putchar('\n');
169         fflush(stdout);
170         line++;
171
172         oldmask = sigblock(sigmask(SIGALRM));
173         if (! signalled) {
174             sigpause(0);
175         }
176         sigsetmask(oldmask);
177         signalled = 0;
178         (void)alarm(interval);
179         osc = req.stats;
180     }
181 }
182
183 /*
184  * Called if an interval expires before sidewaysintpr has completed a loop.
185  * Sets a flag to not wait for the alarm.
186  */
187 void catchalarm(arg)
188     int arg;
189 {
190     signalled = 1;
191 }