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