1 /* 2 * Copyright (c) 1983, 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 char copyright[] = 36 "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ 37 All rights reserved.\n"; 38 #endif /* not lint */ 39 40 #ifndef lint 41 /*static char sccsid[] = "from: @(#)main.c 5.23 (Berkeley) 7/1/91";*/ 42 static char rcsid[] = "$Id: main.c,v 1.2 1993/08/01 18:10:50 mycroft Exp $"; 43 #endif /* not lint */ 44 45 #include <sys/param.h> 46 #include <sys/socket.h> 47 #include <sys/file.h> 48 #include <errno.h> 49 #include <netdb.h> 50 #include <nlist.h> 51 #include <kvm.h> 52 #include <stdio.h> 53 #include <ctype.h> 54 #include <stdlib.h> 55 #include <string.h> 56 #include <paths.h> 57 58 struct nlist nl[] = { 59 #define N_MBSTAT 0 60 { "_mbstat" }, 61 #define N_IPSTAT 1 62 { "_ipstat" }, 63 #define N_TCB 2 64 { "_tcb" }, 65 #define N_TCPSTAT 3 66 { "_tcpstat" }, 67 #define N_UDB 4 68 { "_udb" }, 69 #define N_UDPSTAT 5 70 { "_udpstat" }, 71 #define N_IFNET 6 72 { "_ifnet" }, 73 #define N_IMP 7 74 { "_imp_softc" }, 75 #define N_RTHOST 8 76 { "_rthost" }, 77 #define N_RTNET 9 78 { "_rtnet" }, 79 #define N_ICMPSTAT 10 80 { "_icmpstat" }, 81 #define N_RTSTAT 11 82 { "_rtstat" }, 83 #define N_FILEHEAD 12 84 { "_filehead" }, 85 #define N_FILES 13 86 { "_nfiles" }, 87 #define N_UNIXSW 14 88 { "_unixsw" }, 89 #define N_RTHASHSIZE 15 90 { "_rthashsize" }, 91 #define N_IDP 16 92 { "_nspcb"}, 93 #define N_IDPSTAT 17 94 { "_idpstat"}, 95 #define N_SPPSTAT 18 96 { "_spp_istat"}, 97 #define N_NSERR 19 98 { "_ns_errstat"}, 99 #define N_CLNPSTAT 20 100 { "_clnp_stat"}, 101 #define IN_TP 21 102 { "_tp_inpcb" }, 103 #define ISO_TP 22 104 { "_tp_isopcb" }, 105 #define N_TPSTAT 23 106 { "_tp_stat" }, 107 #define N_ESISSTAT 24 108 { "_esis_stat"}, 109 #define N_NIMP 25 110 { "_nimp"}, 111 #define N_RTREE 26 112 { "_radix_node_head"}, 113 #define N_CLTP 27 114 { "_cltb"}, 115 #define N_CLTPSTAT 28 116 { "_cltpstat"}, 117 "", 118 }; 119 120 /* internet protocols */ 121 extern int protopr(); 122 extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats(); 123 #ifdef NS 124 /* ns protocols */ 125 extern int nsprotopr(); 126 extern int spp_stats(), idp_stats(), nserr_stats(); 127 #endif 128 #ifdef ISO 129 /* iso protocols */ 130 extern int iso_protopr(); 131 extern int tp_stats(), esis_stats(), clnp_stats(), cltp_stats(); 132 #endif 133 134 struct protox { 135 u_char pr_index; /* index into nlist of cb head */ 136 u_char pr_sindex; /* index into nlist of stat block */ 137 u_char pr_wanted; /* 1 if wanted, 0 otherwise */ 138 int (*pr_cblocks)(); /* control blocks printing routine */ 139 int (*pr_stats)(); /* statistics printing routine */ 140 char *pr_name; /* well-known name */ 141 } protox[] = { 142 { N_TCB, N_TCPSTAT, 1, protopr, 143 tcp_stats, "tcp" }, 144 { N_UDB, N_UDPSTAT, 1, protopr, 145 udp_stats, "udp" }, 146 #ifdef ISO 147 { IN_TP, N_TPSTAT, 1, protopr, 148 tp_stats, "tpip" }, 149 #endif 150 { -1, N_IPSTAT, 1, 0, 151 ip_stats, "ip" }, 152 { -1, N_ICMPSTAT, 1, 0, 153 icmp_stats, "icmp" }, 154 { -1, -1, 0, 0, 155 0, 0 } 156 }; 157 158 #ifdef NS 159 struct protox nsprotox[] = { 160 { N_IDP, N_IDPSTAT, 1, nsprotopr, 161 idp_stats, "idp" }, 162 { N_IDP, N_SPPSTAT, 1, nsprotopr, 163 spp_stats, "spp" }, 164 { -1, N_NSERR, 1, 0, 165 nserr_stats, "ns_err" }, 166 { -1, -1, 0, 0, 167 0, 0 } 168 }; 169 #endif 170 171 #ifdef ISO 172 struct protox isoprotox[] = { 173 { ISO_TP, N_TPSTAT, 1, iso_protopr, 174 tp_stats, "tp" }, 175 { N_CLTP, N_CLTPSTAT, 1, iso_protopr, 176 cltp_stats, "cltp" }, 177 { -1, N_CLNPSTAT, 1, 0, 178 clnp_stats, "clnp"}, 179 { -1, N_ESISSTAT, 1, 0, 180 esis_stats, "esis"}, 181 { -1, -1, 0, 0, 182 0, 0 } 183 }; 184 #endif 185 186 struct protox *protoprotox[] = { protox, 187 188 #ifdef NS 189 nsprotox, 190 #endif 191 192 #ifdef ISO 193 isoprotox, 194 #endif 195 196 NULL }; 197 198 char *vmunix = _PATH_UNIX; 199 char *kmemf; 200 int kmem; 201 int kflag; 202 int Aflag; 203 int aflag; 204 int hflag; 205 int iflag; 206 int mflag; 207 int nflag; 208 int pflag; 209 int rflag; 210 int sflag; 211 int tflag; 212 int dflag; 213 int interval; 214 char *interface; 215 int unit; 216 217 int af = AF_UNSPEC; 218 219 main(argc, argv) 220 int argc; 221 char **argv; 222 { 223 extern char *optarg; 224 extern int optind; 225 register struct protoent *p; 226 register struct protox *tp; /* for printing cblocks & stats */ 227 struct protox *name2protox(); /* for -p */ 228 int ch; 229 void usage(); 230 231 while ((ch = getopt(argc, argv, "Aadf:hI:iM:mN:np:rstuw")) != EOF) 232 switch((char)ch) { 233 case 'A': 234 Aflag = 1; 235 break; 236 case 'a': 237 aflag = 1; 238 break; 239 case 'd': 240 dflag = 1; 241 break; 242 case 'f': 243 if (strcmp(optarg, "ns") == 0) 244 af = AF_NS; 245 else if (strcmp(optarg, "inet") == 0) 246 af = AF_INET; 247 else if (strcmp(optarg, "unix") == 0) 248 af = AF_UNIX; 249 else if (strcmp(optarg, "iso") == 0) 250 af = AF_ISO; 251 else { 252 (void)fprintf(stderr, 253 "%s: unknown address family\n", optarg); 254 exit(1); 255 } 256 break; 257 case 'h': 258 hflag = 1; 259 break; 260 case 'I': { 261 char *cp; 262 263 iflag = 1; 264 for (cp = interface = optarg; isalpha(*cp); cp++); 265 unit = atoi(cp); 266 *cp = '\0'; 267 break; 268 } 269 case 'i': 270 iflag = 1; 271 break; 272 case 'M': 273 kmemf = optarg; 274 kflag = 1; 275 break; 276 case 'm': 277 mflag = 1; 278 break; 279 case 'N': 280 vmunix = optarg; 281 break; 282 case 'n': 283 nflag = 1; 284 break; 285 case 'p': 286 if ((tp = name2protox(optarg)) == NULL) { 287 (void)fprintf(stderr, 288 "%s: unknown or uninstrumented protocol\n", 289 optarg); 290 exit(1); 291 } 292 pflag = 1; 293 break; 294 case 'r': 295 rflag = 1; 296 break; 297 case 's': 298 sflag = 1; 299 break; 300 case 't': 301 tflag = 1; 302 break; 303 case 'u': 304 af = AF_UNIX; 305 break; 306 case 'w': 307 interval = atoi(optarg); 308 break; 309 case '?': 310 default: 311 usage(); 312 } 313 argv += optind; 314 argc -= optind; 315 316 #define BACKWARD_COMPATIBILITY 317 #ifdef BACKWARD_COMPATIBILITY 318 if (*argv) { 319 if (isdigit(**argv)) { 320 interval = atoi(*argv); 321 if (interval <= 0) 322 usage(); 323 ++argv; 324 iflag = 1; 325 } 326 if (*argv) { 327 vmunix = *argv; 328 if (*++argv) { 329 kmemf = *argv; 330 kflag = 1; 331 } 332 } 333 } 334 #endif 335 if (kvm_openfiles(vmunix, kmemf, NULL) == -1) { 336 fprintf(stderr, "netstat: kvm_openfiles: %s\n", kvm_geterr()); 337 exit(1); 338 } 339 if (kvm_nlist(nl) < 0 || nl[0].n_type == 0) { 340 fprintf(stderr, "%s: no namelist\n", vmunix); 341 exit(1); 342 } 343 if (mflag) { 344 mbpr((off_t)nl[N_MBSTAT].n_value); 345 exit(0); 346 } 347 if (pflag) { 348 if (tp->pr_stats) 349 (*tp->pr_stats)(nl[tp->pr_sindex].n_value, 350 tp->pr_name); 351 else 352 printf("%s: no stats routine\n", tp->pr_name); 353 exit(0); 354 } 355 if (hflag) { 356 #ifdef IMP 357 hostpr(nl[N_IMP].n_value, nl[N_NIMP].n_value); 358 #else 359 (void)fprintf(stderr, "netstat: IMP code not compiled in\n"); 360 #endif 361 exit(0); 362 } 363 /* 364 * Keep file descriptors open to avoid overhead 365 * of open/close on each call to get* routines. 366 */ 367 sethostent(1); 368 setnetent(1); 369 if (iflag) { 370 intpr(interval, nl[N_IFNET].n_value); 371 exit(0); 372 } 373 if (rflag) { 374 if (sflag) 375 rt_stats((off_t)nl[N_RTSTAT].n_value); 376 else 377 routepr((off_t)nl[N_RTHOST].n_value, 378 (off_t)nl[N_RTNET].n_value, 379 (off_t)nl[N_RTHASHSIZE].n_value, 380 (off_t)nl[N_RTREE].n_value); 381 exit(0); 382 } 383 if (af == AF_INET || af == AF_UNSPEC) { 384 setprotoent(1); 385 setservent(1); 386 while (p = getprotoent()) { 387 388 for (tp = protox; tp->pr_name; tp++) 389 if (strcmp(tp->pr_name, p->p_name) == 0) 390 break; 391 if (tp->pr_name == 0 || tp->pr_wanted == 0) 392 continue; 393 if (sflag) { 394 if (tp->pr_stats) 395 (*tp->pr_stats)(nl[tp->pr_sindex].n_value, 396 p->p_name); 397 } else 398 if (tp->pr_cblocks) 399 (*tp->pr_cblocks)(nl[tp->pr_index].n_value, 400 p->p_name); 401 } 402 endprotoent(); 403 } 404 if (af == AF_NS || af == AF_UNSPEC) { 405 #ifdef NS 406 for (tp = nsprotox; tp->pr_name; tp++) { 407 if (sflag) { 408 if (tp->pr_stats) 409 (*tp->pr_stats)(nl[tp->pr_sindex].n_value, 410 tp->pr_name); 411 } else 412 if (tp->pr_cblocks) 413 (*tp->pr_cblocks)(nl[tp->pr_index].n_value, 414 tp->pr_name); 415 } 416 #endif 417 } 418 if (af == AF_ISO || af == AF_UNSPEC) { 419 #ifdef ISO 420 for (tp = isoprotox; tp->pr_name; tp++) { 421 if (sflag) { 422 if (tp->pr_stats) 423 (*tp->pr_stats)(nl[tp->pr_sindex].n_value, 424 tp->pr_name); 425 } else 426 if (tp->pr_cblocks) 427 (*tp->pr_cblocks)(nl[tp->pr_index].n_value, 428 tp->pr_name); 429 } 430 #endif 431 } 432 if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) 433 unixpr((off_t)nl[N_FILEHEAD].n_value, (off_t)nl[N_FILES].n_value, 434 (struct protosw *)nl[N_UNIXSW].n_value); 435 if (af == AF_UNSPEC && sflag) 436 #ifdef IMP 437 impstats(nl[N_IMP].n_value, nl[N_NIMP].n_value); 438 #endif 439 exit(0); 440 } 441 442 char * 443 plural(n) 444 int n; 445 { 446 return (n != 1 ? "s" : ""); 447 } 448 449 /* 450 * Find the protox for the given "well-known" name. 451 */ 452 struct protox * 453 knownname(name) 454 char *name; 455 { 456 struct protox **tpp, *tp; 457 458 for (tpp = protoprotox; *tpp; tpp++) 459 for (tp = *tpp; tp->pr_name; tp++) 460 if (strcmp(tp->pr_name, name) == 0) 461 return(tp); 462 return(NULL); 463 } 464 465 /* 466 * Find the protox corresponding to name. 467 */ 468 struct protox * 469 name2protox(name) 470 char *name; 471 { 472 struct protox *tp; 473 char **alias; /* alias from p->aliases */ 474 struct protoent *p; 475 476 /* 477 * Try to find the name in the list of "well-known" names. If that 478 * fails, check if name is an alias for an Internet protocol. 479 */ 480 if (tp = knownname(name)) 481 return(tp); 482 483 setprotoent(1); /* make protocol lookup cheaper */ 484 while (p = getprotoent()) { 485 /* assert: name not same as p->name */ 486 for (alias = p->p_aliases; *alias; alias++) 487 if (strcmp(name, *alias) == 0) { 488 endprotoent(); 489 return(knownname(p->p_name)); 490 } 491 } 492 endprotoent(); 493 return(NULL); 494 } 495 496 void 497 usage() 498 { 499 (void)fprintf(stderr, 500 "usage: netstat [-Aan] [-f address_family] [-M core] [-N system]\n"); 501 (void)fprintf(stderr, 502 " [-himnrs] [-f address_family] [-M core] [-N system]\n"); 503 (void)fprintf(stderr, 504 " [-n] [-I interface] [-M core] [-N system] [-w wait]\n"); 505 (void)fprintf(stderr, 506 " [-M core] [-N system] [-p protocol]\n"); 507 exit(1); 508 } 509