1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 char copyright[] = 9 "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 10 All rights reserved.\n"; 11 #endif not lint 12 13 #ifndef lint 14 static char sccsid[] = "@(#)main.c 5.9 (Berkeley) 07/27/87"; 15 #endif not lint 16 17 #include <sys/param.h> 18 #include <sys/vmmac.h> 19 #include <sys/socket.h> 20 #include <machine/pte.h> 21 #include <ctype.h> 22 #include <errno.h> 23 #include <netdb.h> 24 #include <nlist.h> 25 #include <stdio.h> 26 27 struct nlist nl[] = { 28 #define N_MBSTAT 0 29 { "_mbstat" }, 30 #define N_IPSTAT 1 31 { "_ipstat" }, 32 #define N_TCB 2 33 { "_tcb" }, 34 #define N_TCPSTAT 3 35 { "_tcpstat" }, 36 #define N_UDB 4 37 { "_udb" }, 38 #define N_UDPSTAT 5 39 { "_udpstat" }, 40 #define N_RAWCB 6 41 { "_rawcb" }, 42 #define N_SYSMAP 7 43 { "_Sysmap" }, 44 #define N_SYSSIZE 8 45 { "_Syssize" }, 46 #define N_IFNET 9 47 { "_ifnet" }, 48 #define N_HOSTS 10 49 { "_hosts" }, 50 #define N_RTHOST 11 51 { "_rthost" }, 52 #define N_RTNET 12 53 { "_rtnet" }, 54 #define N_ICMPSTAT 13 55 { "_icmpstat" }, 56 #define N_RTSTAT 14 57 { "_rtstat" }, 58 #define N_NFILE 15 59 { "_nfile" }, 60 #define N_FILE 16 61 { "_file" }, 62 #define N_UNIXSW 17 63 { "_unixsw" }, 64 #define N_RTHASHSIZE 18 65 { "_rthashsize" }, 66 #define N_IDP 19 67 { "_nspcb"}, 68 #define N_IDPSTAT 20 69 { "_idpstat"}, 70 #define N_SPPSTAT 21 71 { "_spp_istat"}, 72 #define N_NSERR 22 73 { "_ns_errstat"}, 74 "", 75 }; 76 77 /* internet protocols */ 78 extern int protopr(); 79 extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats(); 80 /* ns protocols */ 81 extern int nsprotopr(); 82 extern int spp_stats(), idp_stats(), nserr_stats(); 83 84 #define NULLPROTOX ((struct protox *) 0) 85 struct protox { 86 u_char pr_index; /* index into nlist of cb head */ 87 u_char pr_sindex; /* index into nlist of stat block */ 88 u_char pr_wanted; /* 1 if wanted, 0 otherwise */ 89 int (*pr_cblocks)(); /* control blocks printing routine */ 90 int (*pr_stats)(); /* statistics printing routine */ 91 char *pr_name; /* well-known name */ 92 } protox[] = { 93 { N_TCB, N_TCPSTAT, 1, protopr, 94 tcp_stats, "tcp" }, 95 { N_UDB, N_UDPSTAT, 1, protopr, 96 udp_stats, "udp" }, 97 { -1, N_IPSTAT, 1, 0, 98 ip_stats, "ip" }, 99 { -1, N_ICMPSTAT, 1, 0, 100 icmp_stats, "icmp" }, 101 { -1, -1, 0, 0, 102 0, 0 } 103 }; 104 105 struct protox nsprotox[] = { 106 { N_IDP, N_IDPSTAT, 1, nsprotopr, 107 idp_stats, "idp" }, 108 { N_IDP, N_SPPSTAT, 1, nsprotopr, 109 spp_stats, "spp" }, 110 { -1, N_NSERR, 1, 0, 111 nserr_stats, "ns_err" }, 112 { -1, -1, 0, 0, 113 0, 0 } 114 }; 115 116 struct pte *Sysmap; 117 118 char *system = "/vmunix"; 119 char *kmemf = "/dev/kmem"; 120 int kmem; 121 int kflag; 122 int Aflag; 123 int aflag; 124 int hflag; 125 int iflag; 126 int mflag; 127 int nflag; 128 int pflag; 129 int rflag; 130 int sflag; 131 int tflag; 132 int interval; 133 char *interface; 134 int unit; 135 char usage[] = "[ -Aaihmnrst ] [-f family] [-p proto] [-I interface] [ interval ] [ system ] [ core ]"; 136 137 int af = AF_UNSPEC; 138 139 extern char *malloc(); 140 extern off_t lseek(); 141 142 main(argc, argv) 143 int argc; 144 char *argv[]; 145 { 146 char *cp, *name; 147 register struct protoent *p; 148 register struct protox *tp; /* for printing cblocks & stats */ 149 struct protox *name2protox(); /* for -p */ 150 151 name = argv[0]; 152 argc--, argv++; 153 while (argc > 0 && **argv == '-') { 154 for (cp = &argv[0][1]; *cp; cp++) 155 switch(*cp) { 156 157 case 'A': 158 Aflag++; 159 break; 160 161 case 'a': 162 aflag++; 163 break; 164 165 case 'h': 166 hflag++; 167 break; 168 169 case 'i': 170 iflag++; 171 break; 172 173 case 'm': 174 mflag++; 175 break; 176 177 case 'n': 178 nflag++; 179 break; 180 181 case 'r': 182 rflag++; 183 break; 184 185 case 's': 186 sflag++; 187 break; 188 189 case 't': 190 tflag++; 191 break; 192 193 case 'u': 194 af = AF_UNIX; 195 break; 196 197 case 'p': 198 argv++; 199 argc--; 200 if (argc == 0) 201 goto use; 202 if ((tp = name2protox(*argv)) == NULLPROTOX) { 203 fprintf(stderr, "%s: unknown or uninstrumented protocol\n", 204 *argv); 205 exit(10); 206 } 207 pflag++; 208 break; 209 210 case 'f': 211 argv++; 212 argc--; 213 if (strcmp(*argv, "ns") == 0) 214 af = AF_NS; 215 else if (strcmp(*argv, "inet") == 0) 216 af = AF_INET; 217 else if (strcmp(*argv, "unix") == 0) 218 af = AF_UNIX; 219 else { 220 fprintf(stderr, "%s: unknown address family\n", 221 *argv); 222 exit(10); 223 } 224 break; 225 226 case 'I': 227 iflag++; 228 if (*(interface = cp + 1) == 0) { 229 if ((interface = argv[1]) == 0) 230 break; 231 argv++; 232 argc--; 233 } 234 for (cp = interface; isalpha(*cp); cp++) 235 ; 236 unit = atoi(cp); 237 *cp-- = 0; 238 break; 239 240 default: 241 use: 242 printf("usage: %s %s\n", name, usage); 243 exit(1); 244 } 245 argv++, argc--; 246 } 247 if (argc > 0 && isdigit(argv[0][0])) { 248 interval = atoi(argv[0]); 249 if (interval <= 0) 250 goto use; 251 argv++, argc--; 252 iflag++; 253 } 254 if (argc > 0) { 255 system = *argv; 256 argv++, argc--; 257 } 258 nlist(system, nl); 259 if (nl[0].n_type == 0) { 260 fprintf(stderr, "%s: no namelist\n", system); 261 exit(1); 262 } 263 if (argc > 0) { 264 kmemf = *argv; 265 kflag++; 266 } 267 kmem = open(kmemf, 0); 268 if (kmem < 0) { 269 fprintf(stderr, "cannot open "); 270 perror(kmemf); 271 exit(1); 272 } 273 if (kflag) { 274 off_t off; 275 276 off = nl[N_SYSMAP].n_value & 0x7fffffff; 277 lseek(kmem, off, 0); 278 nl[N_SYSSIZE].n_value *= 4; 279 Sysmap = (struct pte *)malloc((u_int)nl[N_SYSSIZE].n_value); 280 if (Sysmap == 0) { 281 perror("Sysmap"); 282 exit(1); 283 } 284 read(kmem, (char *)Sysmap, (int)nl[N_SYSSIZE].n_value); 285 } 286 if (mflag) { 287 mbpr((off_t)nl[N_MBSTAT].n_value); 288 exit(0); 289 } 290 if (pflag) { 291 if (tp->pr_stats) 292 (*tp->pr_stats)(nl[tp->pr_sindex].n_value, 293 tp->pr_name); 294 else 295 printf("%s: no stats routine\n", tp->pr_name); 296 exit(0); 297 } 298 /* 299 * Keep file descriptors open to avoid overhead 300 * of open/close on each call to get* routines. 301 */ 302 sethostent(1); 303 setnetent(1); 304 if (iflag) { 305 intpr(interval, nl[N_IFNET].n_value); 306 exit(0); 307 } 308 if (hflag) { 309 hostpr(nl[N_HOSTS].n_value); 310 exit(0); 311 } 312 if (rflag) { 313 if (sflag) 314 rt_stats((off_t)nl[N_RTSTAT].n_value); 315 else 316 routepr((off_t)nl[N_RTHOST].n_value, 317 (off_t)nl[N_RTNET].n_value, 318 (off_t)nl[N_RTHASHSIZE].n_value); 319 exit(0); 320 } 321 if (af == AF_INET || af == AF_UNSPEC) { 322 setprotoent(1); 323 setservent(1); 324 while (p = getprotoent()) { 325 326 for (tp = protox; tp->pr_name; tp++) 327 if (strcmp(tp->pr_name, p->p_name) == 0) 328 break; 329 if (tp->pr_name == 0 || tp->pr_wanted == 0) 330 continue; 331 if (sflag) { 332 if (tp->pr_stats) 333 (*tp->pr_stats)(nl[tp->pr_sindex].n_value, 334 p->p_name); 335 } else 336 if (tp->pr_cblocks) 337 (*tp->pr_cblocks)(nl[tp->pr_index].n_value, 338 p->p_name); 339 } 340 endprotoent(); 341 } 342 if (af == AF_NS || af == AF_UNSPEC) { 343 for (tp = nsprotox; tp->pr_name; tp++) { 344 if (sflag) { 345 if (tp->pr_stats) 346 (*tp->pr_stats)(nl[tp->pr_sindex].n_value, 347 tp->pr_name); 348 } else 349 if (tp->pr_cblocks) 350 (*tp->pr_cblocks)(nl[tp->pr_index].n_value, 351 tp->pr_name); 352 } 353 } 354 if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) 355 unixpr((off_t)nl[N_NFILE].n_value, (off_t)nl[N_FILE].n_value, 356 (struct protosw *)nl[N_UNIXSW].n_value); 357 exit(0); 358 } 359 360 /* 361 * Seek into the kernel for a value. 362 */ 363 off_t 364 klseek(fd, base, off) 365 int fd, off; 366 off_t base; 367 { 368 if (kflag) { 369 /* get kernel pte */ 370 base &= ~KERNBASE; 371 base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET); 372 } 373 return (lseek(fd, base, off)); 374 } 375 376 char * 377 plural(n) 378 int n; 379 { 380 381 return (n != 1 ? "s" : ""); 382 } 383 384 /* 385 * Find the protox for the given "well-known" name. 386 */ 387 struct protox * 388 knownname(name) 389 char *name; 390 { 391 struct protox *tp; 392 393 for (tp = protox; tp->pr_name; tp++) 394 if (strcmp(tp->pr_name, name) == 0) 395 return(tp); 396 for (tp = nsprotox; tp->pr_name; tp++) 397 if (strcmp(tp->pr_name, name) == 0) 398 return(tp); 399 return(NULLPROTOX); 400 } 401 402 /* 403 * Find the protox corresponding to name. 404 */ 405 struct protox * 406 name2protox(name) 407 char *name; 408 { 409 struct protox *tp; 410 char **alias; /* alias from p->aliases */ 411 struct protoent *p; 412 413 /* 414 * Try to find the name in the list of "well-known" names. If that 415 * fails, check if name is an alias for an Internet protocol. 416 */ 417 if (tp = knownname(name)) 418 return(tp); 419 420 setprotoent(1); /* make protocol lookup cheaper */ 421 while (p = getprotoent()) { 422 /* assert: name not same as p->name */ 423 for (alias = p->p_aliases; *alias; alias++) 424 if (strcmp(name, *alias) == 0) { 425 endprotoent(); 426 return(knownname(p->p_name)); 427 } 428 } 429 endprotoent(); 430 return(NULLPROTOX); 431 } 432