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