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