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