merged in Ultrix port, some clean up
[ppp.git] / pppstats / pppstats.c
1 /*
2  * print PPP statistics:
3  *      pppstats [-i interval] [-v] [interface] [system] [core] 
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.3 1994/04/21 03:11:03 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 #define VJC     1
49 #include <net/slcompress.h>
50 #include <net/if_ppp.h>
51
52 #ifdef STREAMS
53 #define PPP_STATS       1       /* should be defined iff it is in ppp_if.c */
54 #include <sys/stream.h>
55 #include <net/ppp_str.h>
56 #endif
57
58 #ifdef BSD4_4
59 #define KVMLIB
60 #endif
61
62 #ifndef KVMLIB
63
64 #include <machine/pte.h>
65 #ifdef ultrix
66 #include <machine/cpu.h>
67 #endif
68
69 struct  pte *Sysmap;
70 int     kmem;
71 char    *kmemf = "/dev/kmem";
72 extern  off_t lseek();
73
74 #else   /* KVMLIB */
75
76 char    *kmemf;
77
78 #ifdef sun
79 #include <kvm.h>
80 kvm_t   *kd;
81 #define KDARG   kd,
82
83 #else   /* sun */
84 #define KDARG
85 #endif  /* sun */
86
87 #endif  /* KVMLIB */
88
89 #ifdef STREAMS
90 struct nlist nl[] = {
91 #define N_SOFTC 0
92         { "_pii" },
93         "",
94 };
95 #else
96 struct nlist nl[] = {
97 #define N_SOFTC 0
98         { "_ppp_softc" },
99         "",
100 };
101 #endif
102
103 #ifndef BSD4_4
104 char    *system = "/vmunix";
105 #else
106 #include <paths.h>
107 char    *system = _PATH_UNIX;
108 #endif
109
110 int     kflag;
111 int     vflag;
112 unsigned interval = 5;
113 int     unit;
114
115 extern  char *malloc();
116
117 main(argc, argv)
118         int argc;
119         char *argv[];
120 {
121         --argc; ++argv;
122         while (argc > 0) {
123                 if (strcmp(argv[0], "-v") == 0) {
124                         ++vflag;
125                         ++argv, --argc;
126                         continue;
127                 }
128                 if (strcmp(argv[0], "-i") == 0 && argv[1] &&
129                     isdigit(argv[1][0])) {
130                         interval = atoi(argv[1]);
131                         if (interval <= 0)
132                                 usage();
133                         ++argv, --argc;
134                         ++argv, --argc;
135                         continue;
136                 }
137                 if (isdigit(argv[0][0])) {
138                         unit = atoi(argv[0]);
139                         if (unit < 0)
140                                 usage();
141                         ++argv, --argc;
142                         continue;
143                 }
144                 if (kflag)
145                         usage();
146
147                 system = *argv;
148                 ++argv, --argc;
149                 if (argc > 0) {
150                         kmemf = *argv++;
151                         --argc;
152                         kflag++;
153                 }
154         }
155 #ifndef KVMLIB
156         if (nlist(system, nl) < 0 || nl[0].n_type == 0) {
157                 fprintf(stderr, "%s: no namelist\n", system);
158                 exit(1);
159         }
160         kmem = open(kmemf, O_RDONLY);
161         if (kmem < 0) {
162                 perror(kmemf);
163                 exit(1);
164         }
165 #ifndef ultrix
166         if (kflag) {
167                 off_t off;
168
169                 Sysmap = (struct pte *)
170                    malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
171                 if (!Sysmap) {
172                         fputs("netstat: can't get memory for Sysmap.\n", stderr);
173                         exit(1);
174                 }
175                 off = nl[N_SYSMAP].n_value & ~KERNBASE;
176                 (void)lseek(kmem, off, L_SET);
177                 (void)read(kmem, (char *)Sysmap,
178                     (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
179         }
180 #endif
181 #else
182 #ifdef sun
183         /* SunOS */
184         if ((kd = kvm_open(system, kmemf, (char *)0, O_RDONLY, NULL)) == NULL) {
185             perror("kvm_open");
186             exit(1);
187         }
188 #else
189         /* BSD4.3+ */
190         if (kvm_openfiles(system, kmemf, (char *)0) == -1) {
191             fprintf(stderr, "kvm_openfiles: %s", kvm_geterr());
192             exit(1);
193         }
194 #endif
195
196         if (kvm_nlist(KDARG nl)) {
197             fprintf(stderr, "pppstats: can't find symbols in nlist\n");
198             exit(1);
199         }
200 #endif
201         intpr();
202         exit(0);
203 }
204
205 #ifndef KVMLIB
206 /*
207  * Seek into the kernel for a value.
208  */
209 off_t
210 klseek(fd, base, off)
211         int fd, off;
212         off_t base;
213 {
214         if (kflag) {
215 #ifdef ultrix
216                 base = K0_TO_PHYS(base);
217 #else
218                 /* get kernel pte */
219                 base &= ~KERNBASE;
220                 base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
221 #endif
222         }
223         return (lseek(fd, base, off));
224 }
225 #endif
226
227 usage()
228 {
229         fprintf(stderr,"usage: pppstats [-i interval] [-v] [unit] [system] [core]\n");
230         exit(1);
231 }
232
233 u_char  signalled;                      /* set if alarm goes off "early" */
234
235 #define V(offset) ((line % 20)? sc->offset - osc->offset : sc->offset)
236
237 #ifdef STREAMS
238 #define STRUCT  struct ppp_if_info
239 #define COMP    pii_sc_comp
240 #define STATS   pii_ifnet
241 #else
242 #define STRUCT  struct ppp_softc
243 #define COMP    sc_comp
244 #define STATS   sc_if
245 #endif
246
247 /*
248  * Print a running summary of interface statistics.
249  * Repeat display every interval seconds, showing statistics
250  * collected over that interval.  Assumes that interval is non-zero.
251  * First line printed at top of screen is always cumulative.
252  */
253 intpr()
254 {
255         register int line = 0;
256         int oldmask;
257 #ifdef __STDC__
258         void catchalarm(int);
259 #else
260         void catchalarm();
261 #endif
262
263         STRUCT *sc, *osc;
264
265         nl[N_SOFTC].n_value += unit * sizeof(STRUCT);
266         sc = (STRUCT *)malloc(sizeof(STRUCT));
267         osc = (STRUCT *)malloc(sizeof(STRUCT));
268
269         bzero((char *)osc, sizeof(STRUCT));
270
271         while (1) {
272 #ifndef KVMLIB
273             if (klseek(kmem, (off_t)nl[N_SOFTC].n_value, 0) == -1) {
274                 perror("kmem seek");
275                 exit(1);
276             }
277             if (read(kmem, (char *)sc, sizeof(STRUCT)) <= 0) {
278                 perror("kmem read");
279                 exit(1);
280             }
281 #else
282             if (kvm_read(KDARG nl[N_SOFTC].n_value, sc,
283                          sizeof(STRUCT)) != sizeof(STRUCT)) {
284                 perror("kvm_read");
285                 exit(1);
286             }
287 #endif
288
289             (void)signal(SIGALRM, catchalarm);
290             signalled = 0;
291             (void)alarm(interval);
292
293             if ((line % 20) == 0) {
294                 printf("%6.6s %6.6s %6.6s %6.6s %6.6s",
295                        "in", "pack", "comp", "uncomp", "err");
296                 if (vflag)
297                     printf(" %6.6s %6.6s", "toss", "ip");
298                 printf(" | %6.6s %6.6s %6.6s %6.6s %6.6s",
299                        "out", "pack", "comp", "uncomp", "ip");
300                 if (vflag)
301                     printf(" %6.6s %6.6s", "search", "miss");
302                 putchar('\n');
303             }
304
305             printf("%6d %6d %6d %6d %6d",
306 #ifdef BSD4_4
307                    V(STATS.if_ibytes),
308 #else
309 #ifndef STREAMS
310                    V(sc_bytesrcvd),
311 #else
312 #ifdef PPP_STATS
313                    V(pii_stats.ppp_ibytes),
314 #else
315                    0,
316 #endif
317 #endif
318 #endif
319                    V(STATS.if_ipackets),
320                    V(COMP.sls_compressedin),
321                    V(COMP.sls_uncompressedin),
322                    V(COMP.sls_errorin));
323             if (vflag)
324                 printf(" %6d %6d",
325                        V(COMP.sls_tossed),
326                        V(STATS.if_ipackets) - V(COMP.sls_compressedin) -
327                         V(COMP.sls_uncompressedin) - V(COMP.sls_errorin));
328             printf(" | %6d %6d %6d %6d %6d",
329 #ifdef BSD4_4
330                    V(STATS.if_obytes),
331 #else
332 #ifndef STREAMS
333                    V(sc_bytessent),
334 #else
335 #ifdef PPP_STATS
336                    V(pii_stats.ppp_obytes),
337 #else
338                    0,
339 #endif
340 #endif
341 #endif
342                    V(STATS.if_opackets),
343                    V(COMP.sls_compressed),
344                    V(COMP.sls_packets) - V(COMP.sls_compressed),
345                    V(STATS.if_opackets) - V(COMP.sls_packets));
346             if (vflag)
347                 printf(" %6d %6d",
348                        V(COMP.sls_searches),
349                        V(COMP.sls_misses));
350
351             putchar('\n');
352             fflush(stdout);
353             line++;
354
355             oldmask = sigblock(sigmask(SIGALRM));
356             if (! signalled) {
357                 sigpause(0);
358             }
359             sigsetmask(oldmask);
360             signalled = 0;
361             (void)alarm(interval);
362             bcopy((char *)sc, (char *)osc, sizeof(STRUCT));
363         }
364 }
365
366 /*
367  * Called if an interval expires before sidewaysintpr has completed a loop.
368  * Sets a flag to not wait for the alarm.
369  */
370 void catchalarm(arg)
371 int arg;
372 {
373         signalled = 1;
374 }