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