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