install man page
[ppp.git] / pppstats / pppstats.c
1 /*
2  * print PPP statistics:
3  *      pppstats [-i interval] [-v] [-r] [-c] [interface]
4  *
5  *   -i <update interval in seconds>
6  *   -v Verbose mode for default display
7  *   -r Show compression ratio in default display
8  *   -c Show Compression statistics instead of default display
9  *
10  *
11  * History:
12  *      perkins@cps.msu.edu: Added compression statistics and alternate 
13  *                display. 11/94
14
15  *      Brad Parker (brad@cayman.com) 6/92
16  *
17  * from the original "slstats" by Van Jaconson
18  *
19  * Copyright (c) 1989 Regents of the University of California.
20  * All rights reserved.
21  *
22  * Redistribution and use in source and binary forms are permitted
23  * provided that the above copyright notice and this paragraph are
24  * duplicated in all such forms and that any documentation,
25  * advertising materials, and other materials related to such
26  * distribution and use acknowledge that the software was developed
27  * by the University of California, Berkeley.  The name of the
28  * University may not be used to endorse or promote products derived
29  * from this software without specific prior written permission.
30  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
31  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
32  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
33  *
34  *      Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
35  *      - Initial distribution.
36  */
37
38 #ifndef lint
39 static char rcsid[] = "$Id: pppstats.c,v 1.8 1995/05/02 05:51:22 paulus Exp $";
40 #endif
41
42 #include <ctype.h>
43 #include <errno.h>
44 #include <nlist.h>
45 #include <stdio.h>
46 #include <signal.h>
47 #include <sys/param.h>
48 #include <sys/mbuf.h>
49 #include <sys/types.h>
50 #include <sys/ioctl.h>
51 #include <sys/socket.h>
52 #include <sys/file.h>
53 #include <net/if.h>
54 #include <netinet/in.h>
55 #include <netinet/in_systm.h>
56 #include <netinet/ip.h>
57 #include <netinet/ip_var.h>
58
59 #include <net/ppp_defs.h>
60
61 #ifndef STREAMS
62 #include <net/if_ppp.h>
63 #endif
64
65 #ifdef STREAMS
66 #define PPP_STATS       1       /* should be defined iff it is in ppp_if.c */
67 #include <sys/stream.h>
68 #include <net/ppp_str.h>
69 #endif
70
71 int     vflag, rflag, cflag;
72 unsigned interval = 5;
73 int     unit;
74 int     s;                      /* socket file descriptor */
75 int     signalled;              /* set if alarm goes off "early" */
76
77 extern  char *malloc();
78 void catchalarm __P((int));
79
80 main(argc, argv)
81     int argc;
82     char *argv[];
83 {
84     --argc; ++argv;
85     while (argc > 0) {
86         if (strcmp(argv[0], "-v") == 0) {
87             ++vflag;
88             ++argv, --argc;
89             continue;
90         }
91         if (strcmp(argv[0], "-r") == 0) {
92           ++rflag;
93           ++argv, --argc;
94           continue;
95         }
96         if (strcmp(argv[0], "-c") == 0) {
97           ++cflag;
98           ++argv, --argc;
99           continue;
100         }
101         if (strcmp(argv[0], "-i") == 0 && argv[1] &&
102             isdigit(argv[1][0])) {
103             interval = atoi(argv[1]);
104             if (interval < 0)
105                 usage();
106             ++argv, --argc;
107             ++argv, --argc;
108             continue;
109         }
110         if (isdigit(argv[0][0])) {
111             unit = atoi(argv[0]);
112             if (unit < 0)
113                 usage();
114             ++argv, --argc;
115             continue;
116         }
117         usage();
118     }
119
120     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
121         perror("couldn't create IP socket");
122         exit(1);
123     }
124     intpr();
125     exit(0);
126 }
127
128 usage()
129 {
130     fprintf(stderr, "Usage: pppstats [-v] [-r] [-c] [-i interval] [unit]\n");
131     exit(1);
132 }
133
134 #define V(offset) (line % 20? req.stats.offset - osc.offset: req.stats.offset)
135 #define W(offset) (line % 20? creq.stats.offset - csc.offset: creq.stats.offset)
136
137 #define CRATE(comp, inc, unc)   ((unc) == 0? 0.0: \
138                                  1.0 - (double)((comp) + (inc)) / (unc))
139
140 /*
141  * Print a running summary of interface statistics.
142  * Repeat display every interval seconds, showing statistics
143  * collected over that interval.  Assumes that interval is non-zero.
144  * First line printed at top of screen is always cumulative.
145  */
146 intpr()
147 {
148     register int line = 0;
149     int oldmask;
150     struct ifpppstatsreq req;
151     struct ifpppcstatsreq creq;
152     struct ppp_stats osc;
153     struct ppp_comp_stats csc;
154
155     bzero(&osc, sizeof(osc));
156     bzero(&csc, sizeof(csc));
157
158     sprintf(req.ifr_name, "ppp%d", unit);
159     sprintf(creq.ifr_name, "ppp%d", unit);
160     while (1) {
161         if (ioctl(s, SIOCGPPPSTATS, &req) < 0) {
162             if (errno == ENOTTY)
163                 fprintf(stderr, "pppstats: kernel support missing\n");
164             else
165                 perror("ioctl(SIOCGPPPSTATS)");
166             exit(1);
167         }
168         if ((cflag || rflag) && ioctl(s, SIOCGPPPCSTATS, &creq) < 0) {
169             if (errno == ENOTTY) {
170                 fprintf(stderr, "pppstats: no kernel compression support\n");
171                 if (cflag)
172                     exit(1);
173                 rflag = 0;
174             } else {
175                 perror("ioctl(SIOCGPPPCSTATS)");
176                 exit(1);
177             }
178         }
179         (void)signal(SIGALRM, catchalarm);
180         signalled = 0;
181         (void)alarm(interval);
182     
183         if ((line % 20) == 0) {
184             if (line > 0)
185                 putchar('\n');
186             if (cflag) {
187             
188                 printf("%6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s",
189                        "ubyte", "upack", "cbyte", "cpack", "ibyte", "ipack", "ratio");
190                 printf(" | %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s",
191                        "ubyte", "upack", "cbyte", "cpack", "ibyte", "ipack", "ratio");
192                 putchar('\n');
193             } else {
194
195                 printf("%6.6s %6.6s %6.6s %6.6s %6.6s",
196                        "in", "pack", "comp", "uncomp", "err");
197                 if (vflag)
198                     printf(" %6.6s %6.6s", "toss", "ip");
199                 if (rflag)
200                     printf("   %6.6s %6.6s", "ratio", "ubyte");
201                 printf("  | %6.6s %6.6s %6.6s %6.6s %6.6s",
202                        "out", "pack", "comp", "uncomp", "ip");
203                 if (vflag)
204                     printf(" %6.6s %6.6s", "search", "miss");
205                 if(rflag)
206                     printf("   %6.6s %6.6s", "ratio", "ubyte");
207                 putchar('\n');
208             }
209             bzero(&osc, sizeof(osc));
210             bzero(&csc, sizeof(csc));
211         }
212         
213         if (cflag) {
214             printf("%6d %6d %6d %6d %6d %6d %6.2f",
215                    W(d.unc_bytes),
216                    W(d.unc_packets),
217                    W(d.comp_bytes),
218                    W(d.comp_packets),
219                    W(d.inc_bytes),
220                    W(d.inc_packets),
221                    W(d.ratio) == 0? 0.0: 1 - 1.0 / W(d.ratio) * 256.0);
222
223             printf(" | %6d %6d %6d %6d %6d %6d %6.2f",
224                    W(c.unc_bytes),
225                    W(c.unc_packets),
226                    W(c.comp_bytes),
227                    W(c.comp_packets),
228                    W(c.inc_bytes),
229                    W(c.inc_packets),
230                    W(d.ratio) == 0? 0.0: 1 - 1.0 / W(d.ratio) * 256.0);
231         
232             putchar('\n');
233         } else {
234
235             printf("%6d %6d %6d %6d %6d",
236                    V(p.ppp_ibytes),
237                    V(p.ppp_ipackets), V(vj.vjs_compressedin),
238                    V(vj.vjs_uncompressedin), V(vj.vjs_errorin));
239             if (vflag)
240                 printf(" %6d %6d", V(vj.vjs_tossed),
241                        V(p.ppp_ipackets) - V(vj.vjs_compressedin) -
242                        V(vj.vjs_uncompressedin) - V(vj.vjs_errorin));
243             if (rflag)
244                 printf("   %6.2f %6d",
245                        CRATE(W(d.comp_bytes), W(d.unc_bytes), W(d.unc_bytes)),
246                        W(d.unc_bytes));
247             printf("  | %6d %6d %6d %6d %6d", V(p.ppp_obytes),
248                    V(p.ppp_opackets), V(vj.vjs_compressed),
249                    V(vj.vjs_packets) - V(vj.vjs_compressed),
250                    V(p.ppp_opackets) - V(vj.vjs_packets));
251             if (vflag)
252                 printf(" %6d %6d", V(vj.vjs_searches), V(vj.vjs_misses));
253
254             if (rflag)
255                 printf("   %6.2f %6d",
256                        CRATE(W(d.comp_bytes), W(d.unc_bytes), W(d.unc_bytes)),
257                        W(c.unc_bytes));
258             
259             putchar('\n');
260         }
261
262         fflush(stdout);
263         line++;
264         if (interval == 0)
265             exit(0);
266     
267         oldmask = sigblock(sigmask(SIGALRM));
268         if (! signalled) {
269             sigpause(0);
270         }
271         sigsetmask(oldmask);
272         signalled = 0;
273         (void)alarm(interval);
274         osc = req.stats;
275         csc = creq.stats;
276     }
277 }
278
279 /*
280  * Called if an interval expires before sidewaysintpr has completed a loop.
281  * Sets a flag to not wait for the alarm.
282  */
283 void catchalarm(arg)
284     int arg;
285 {
286     signalled = 1;
287 }