rm unused/broken x25 hooks
[unix-history] / usr / src / usr.bin / netstat / main.c
... / ...
CommitLineData
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
9char 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
15static char sccsid[] = "@(#)main.c 5.23 (Berkeley) %G%";
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
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" },
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 /* 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
101 "",
102};
103
104/* internet protocols */
105extern int protopr(), bbnprotopr();
106extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats();
107/* ns protocols */
108extern int tcpstats(), udpstats(), ipstats(), icmpstats(), rdpstats();
109extern int nsprotopr();
110extern int spp_stats(), idp_stats(), nserr_stats();
111/* iso protocols */
112extern int iso_protopr();
113extern int tp_stats(), esis_stats(), clnp_stats(), cltp_stats();
114
115struct protox {
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 */
122};
123
124struct protox berkprotox[] = {
125 { N_TCB, N_TCPSTAT, 1, protopr,
126 tcp_stats, "tcp" },
127 { N_UDB, N_UDPSTAT, 1, protopr,
128 udp_stats, "udp" },
129 { IN_TP, N_TPSTAT, 1, protopr,
130 tp_stats, "tpip" },
131 { -1, N_IPSTAT, 1, 0,
132 ip_stats, "ip" },
133 { -1, N_ICMPSTAT, 1, 0,
134 icmp_stats, "icmp" },
135 { -1, -1, 0, 0,
136 0, 0 }
137};
138
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
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
167struct protox isoprotox[] = {
168 { ISO_TP, N_TPSTAT, 1, iso_protopr,
169 tp_stats, "tp" },
170 { N_CLTP, N_CLTPSTAT, 1, iso_protopr,
171 cltp_stats, "cltp" },
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
180struct protox *protoprotox[] = { protox, nsprotox, isoprotox, NULL };
181
182char *vmunix = _PATH_UNIX;
183char *kmemf;
184int kmem;
185int kflag;
186int Aflag;
187int aflag;
188int hflag;
189int iflag;
190int mflag;
191int nflag;
192int pflag;
193int rflag;
194int sflag;
195int tflag;
196int dflag;
197int interval;
198char *interface;
199int unit;
200
201int af = AF_UNSPEC;
202
203main(argc, argv)
204 int argc;
205 char **argv;
206{
207 extern char *optarg;
208 extern int optind;
209 register struct protoent *p;
210 register struct protox *tp; /* for printing cblocks & stats */
211 struct protox *name2protox(); /* for -p */
212 int ch;
213 void usage();
214
215 while ((ch = getopt(argc, argv, "Aadf:hI:iM:mN:np:rstuw")) != EOF)
216 switch((char)ch) {
217 case 'A':
218 Aflag = 1;
219 break;
220 case 'a':
221 aflag = 1;
222 break;
223 case 'd':
224 dflag = 1;
225 break;
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;
233 else if (strcmp(optarg, "iso") == 0)
234 af = AF_ISO;
235 else {
236 (void)fprintf(stderr,
237 "%s: unknown address family\n", optarg);
238 exit(1);
239 }
240 break;
241 case 'h':
242 hflag = 1;
243 break;
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 }
253 case 'i':
254 iflag = 1;
255 break;
256 case 'M':
257 kmemf = optarg;
258 kflag = 1;
259 break;
260 case 'm':
261 mflag = 1;
262 break;
263 case 'N':
264 vmunix = optarg;
265 break;
266 case 'n':
267 nflag = 1;
268 break;
269 case 'p':
270 if ((tp = name2protox(optarg)) == NULL) {
271 (void)fprintf(stderr,
272 "%s: unknown or uninstrumented protocol\n",
273 optarg);
274 exit(1);
275 }
276 pflag = 1;
277 break;
278 case 'r':
279 rflag = 1;
280 break;
281 case 's':
282 sflag = 1;
283 break;
284 case 't':
285 tflag = 1;
286 break;
287 case 'u':
288 af = AF_UNIX;
289 break;
290 case 'w':
291 interval = atoi(optarg);
292 break;
293 case '?':
294 default:
295 usage();
296 }
297 argv += optind;
298 argc -= optind;
299
300#define BACKWARD_COMPATIBILITY
301#ifdef BACKWARD_COMPATIBILITY
302 if (*argv) {
303 if (isdigit(**argv)) {
304 interval = atoi(*argv);
305 if (interval <= 0)
306 usage();
307 ++argv;
308 iflag = 1;
309 }
310 if (*argv) {
311 vmunix = *argv;
312 if (*++argv) {
313 kmemf = *argv;
314 kflag = 1;
315 }
316 }
317 }
318#endif
319 if (kvm_openfiles(vmunix, kmemf, NULL) == -1) {
320 fprintf(stderr, "netstat: kvm_openfiles: %s\n", kvm_geterr());
321 exit(1);
322 }
323 if (kvm_nlist(nl) < 0 || nl[0].n_type == 0) {
324 fprintf(stderr, "%s: no namelist\n", vmunix);
325 exit(1);
326 }
327 if (mflag) {
328 mbpr((off_t)nl[N_MBSTAT].n_value);
329 exit(0);
330 }
331 if (pflag) {
332 if (tp->pr_stats)
333 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
334 tp->pr_name);
335 else
336 printf("%s: no stats routine\n", tp->pr_name);
337 exit(0);
338 }
339 if (hflag) {
340 hostpr(nl[N_IMP].n_value, nl[N_NIMP].n_value);
341 exit(0);
342 }
343 /*
344 * Keep file descriptors open to avoid overhead
345 * of open/close on each call to get* routines.
346 */
347 sethostent(1);
348 setnetent(1);
349 if (iflag) {
350 intpr(interval, nl[N_IFNET].n_value);
351 exit(0);
352 }
353 if (rflag) {
354 if (sflag)
355 rt_stats((off_t)nl[N_RTSTAT].n_value);
356 else
357 routepr((off_t)nl[N_RTHOST].n_value,
358 (off_t)nl[N_RTNET].n_value,
359 (off_t)nl[N_RTHASHSIZE].n_value,
360 (off_t)nl[N_RTREE].n_value);
361 exit(0);
362 }
363 if (af == AF_INET || af == AF_UNSPEC) {
364 struct protox *head;
365
366 head = (nl[N_TCB].n_type == 0) ? bbnprotox : berkprotox;
367 setprotoent(1);
368 setservent(1);
369
370 for (tp = head; tp->pr_name; tp++) {
371 if (tp->pr_wanted == 0)
372 continue;
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);
379 }
380 endprotoent();
381 }
382 if (af == AF_NS || af == AF_UNSPEC) {
383 for (tp = nsprotox; tp->pr_name; tp++) {
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);
392 }
393 }
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 }
406 if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
407 unixpr((off_t)nl[N_NFILE].n_value, (off_t)nl[N_FILE].n_value,
408 (struct protosw *)nl[N_UNIXSW].n_value);
409 if (af == AF_UNSPEC && sflag)
410 impstats(nl[N_IMP].n_value, nl[N_NIMP].n_value);
411 exit(0);
412}
413
414char *
415plural(n)
416 int n;
417{
418 return (n != 1 ? "s" : "");
419}
420
421/*
422 * Find the protox for the given "well-known" name.
423 */
424struct protox *
425knownname(name)
426 char *name;
427{
428 struct protox **tpp, *tp;
429
430 for (tpp = protoprotox; *tpp; tpp++)
431 for (tp = *tpp; tp->pr_name; tp++)
432 if (strcmp(tp->pr_name, name) == 0)
433 return(tp);
434 return(NULL);
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;
447
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);
454
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();
465 return(NULL);
466}
467
468void
469usage()
470{
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");
479 exit(1);
480}