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