1 /* 2 * print serial line IP statistics: 3 * slstat [-i interval] [-v] [interface] 4 * 5 * Copyright (c) 1989, 1990, 1991, 1992 Regents of the University of 6 * California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the University of California, Berkeley. The name of the 14 * University may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * Van Jacobson (van@ee.lbl.gov), Dec 31, 1989: 21 * - Initial distribution. 22 * 23 * $FreeBSD: src/usr.sbin/slstat/slstat.c,v 1.14 1999/08/28 01:20:00 peter Exp $ 24 */ 25 26 #define _KERNEL_STRUCTURES 27 #include <sys/param.h> 28 #include <sys/mbuf.h> 29 #include <sys/socket.h> 30 #include <sys/sysctl.h> 31 #include <sys/time.h> 32 33 #include <ctype.h> 34 #include <err.h> 35 #include <errno.h> 36 #include <signal.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 42 #include <net/if.h> 43 #include <net/if_var.h> 44 #include <net/if_mib.h> 45 #include <net/if_types.h> 46 #include <netinet/in.h> 47 #include <netinet/in_systm.h> 48 #include <netinet/ip.h> 49 #include <net/slcompress.h> 50 #include <net/sl/if_slvar.h> 51 52 static void usage(void); 53 static void intpr(void); 54 static void catchalarm(int); 55 56 #define INTERFACE_PREFIX "sl%d" 57 58 char interface[IFNAMSIZ]; 59 60 int rflag; 61 int vflag; 62 unsigned interval = 5; 63 int unit; 64 int name[6]; 65 66 int 67 main(int argc, char **argv) 68 { 69 int c, i; 70 size_t len; 71 int maxifno; 72 int indx; 73 struct ifmibdata ifmd; 74 75 while ((c = getopt(argc, argv, "vri:")) != -1) { 76 switch(c) { 77 case 'v': 78 ++vflag; 79 break; 80 case 'r': 81 ++rflag; 82 break; 83 case 'i': 84 interval = atoi(optarg); 85 if (interval <= 0) 86 usage(); 87 break; 88 default: 89 usage(); 90 } 91 } 92 if (optind >= argc) 93 sprintf(interface, INTERFACE_PREFIX, unit); 94 else if (isdigit(argv[optind][0])) { 95 unit = atoi(argv[optind]); 96 if (unit < 0) 97 usage(); 98 sprintf(interface, INTERFACE_PREFIX, unit); 99 } else if (strncmp(argv[optind], "sl", 2) == 0 100 && isdigit(argv[optind][2]) 101 && sscanf(argv[optind], "sl%d", &unit) == 1) { 102 strncpy(interface, argv[optind], IFNAMSIZ); 103 } else 104 usage(); 105 106 name[0] = CTL_NET; 107 name[1] = PF_LINK; 108 name[2] = NETLINK_GENERIC; 109 name[3] = IFMIB_SYSTEM; 110 name[4] = IFMIB_IFCOUNT; 111 len = sizeof maxifno; 112 if (sysctl(name, 5, &maxifno, &len, 0, 0) < 0) 113 err(1, "sysctl net.link.generic.system.ifcount"); 114 115 name[3] = IFMIB_IFDATA; 116 name[5] = IFDATA_GENERAL; 117 len = sizeof ifmd; 118 for (i = 1; ; i++) { 119 name[4] = i; 120 121 if (sysctl(name, 6, &ifmd, &len, 0, 0) < 0) 122 err(1, "sysctl"); 123 if (strncmp(interface, ifmd.ifmd_name, IFNAMSIZ) == 0 124 && ifmd.ifmd_data.ifi_type == IFT_SLIP) { 125 indx = i; 126 break; 127 } 128 if (i >= maxifno) 129 errx(1, "interface %s does not exist", interface); 130 } 131 132 name[4] = indx; 133 name[5] = IFDATA_LINKSPECIFIC; 134 intpr(); 135 exit(0); 136 } 137 138 #define V(offset) ((line % 20)? ((sc->offset - osc->offset) / \ 139 (rflag ? interval : 1)) : sc->offset) 140 #define AMT (sizeof(*sc) - 2 * sizeof(sc->sc_comp.tstate)) 141 142 static void 143 usage(void) 144 { 145 fprintf(stderr, "usage: slstat [-i interval] [-vr] [unit]\n"); 146 exit(1); 147 } 148 149 u_char signalled; /* set if alarm goes off "early" */ 150 151 /* 152 * Print a running summary of interface statistics. 153 * Repeat display every interval seconds, showing statistics 154 * collected over that interval. Assumes that interval is non-zero. 155 * First line printed at top of screen is always cumulative. 156 */ 157 static void 158 intpr(void) 159 { 160 int line = 0; 161 int oldmask; 162 struct sl_softc *sc, *osc; 163 size_t len; 164 165 sc = (struct sl_softc *)malloc(AMT); 166 osc = (struct sl_softc *)malloc(AMT); 167 bzero((char *)osc, AMT); 168 len = AMT; 169 170 while (1) { 171 if (sysctl(name, 6, sc, &len, 0, 0) < 0 && 172 (errno != ENOMEM || len != AMT)) 173 err(1, "sysctl linkspecific"); 174 175 signal(SIGALRM, catchalarm); 176 signalled = 0; 177 alarm(interval); 178 179 if ((line % 20) == 0) { 180 printf("%8.8s %6.6s %6.6s %6.6s %6.6s", 181 "in", "pack", "comp", "uncomp", "unknwn"); 182 if (vflag) 183 printf(" %6.6s %6.6s %6.6s", 184 "toss", "other", "err"); 185 printf(" | %8.8s %6.6s %6.6s %6.6s %6.6s", 186 "out", "pack", "comp", "uncomp", "other"); 187 if (vflag) 188 printf(" %6.6s %6.6s %6.6s %6.6s", 189 "search", "miss", "err", "coll"); 190 putchar('\n'); 191 } 192 printf("%8lu %6ld %6u %6u %6u", 193 V(sc_if.if_ibytes), 194 V(sc_if.if_ipackets), 195 V(sc_comp.sls_compressedin), 196 V(sc_comp.sls_uncompressedin), 197 V(sc_comp.sls_errorin)); 198 if (vflag) 199 printf(" %6u %6lu %6lu", 200 V(sc_comp.sls_tossed), 201 V(sc_if.if_ipackets) - 202 V(sc_comp.sls_compressedin) - 203 V(sc_comp.sls_uncompressedin) - 204 V(sc_comp.sls_errorin), 205 V(sc_if.if_ierrors)); 206 printf(" | %8lu %6ld %6u %6u %6lu", 207 V(sc_if.if_obytes) / (rflag ? interval : 1), 208 V(sc_if.if_opackets), 209 V(sc_comp.sls_compressed), 210 V(sc_comp.sls_packets) - V(sc_comp.sls_compressed), 211 V(sc_if.if_opackets) - V(sc_comp.sls_packets)); 212 if (vflag) 213 printf(" %6u %6u %6lu %6lu", 214 V(sc_comp.sls_searches), 215 V(sc_comp.sls_misses), 216 V(sc_if.if_oerrors), 217 V(sc_if.if_collisions)); 218 putchar('\n'); 219 fflush(stdout); 220 line++; 221 oldmask = sigblock(sigmask(SIGALRM)); 222 if (! signalled) { 223 sigpause(0); 224 } 225 sigsetmask(oldmask); 226 signalled = 0; 227 alarm(interval); 228 bcopy((char *)sc, (char *)osc, AMT); 229 } 230 } 231 232 /* 233 * Called if an interval expires before sidewaysintpr has completed a loop. 234 * Sets a flag to not wait for the alarm. 235 */ 236 static void 237 catchalarm(int sig) 238 { 239 signalled = 1; 240 } 241