BSD 4_3_Reno release
[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 *
1c15e888
C
5 * Redistribution and use in source and binary forms are permitted provided
6 * that: (1) source distributions retain this entire copyright notice and
7 * comment, and (2) distributions including binaries display the following
8 * acknowledgement: ``This product includes software developed by the
9 * University of California, Berkeley and its contributors'' in the
10 * documentation or other materials provided with the distribution and in
11 * all advertising materials mentioning features or use of this software.
12 * Neither the name of the University nor the names of its contributors may
13 * be used to endorse or promote products derived from this software without
14 * specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
5ff67f98
DF
18 */
19
20#ifndef lint
21char copyright[] =
b36fc510 22"@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
5ff67f98 23 All rights reserved.\n";
d2c7d54c 24#endif /* not lint */
5ff67f98 25
ed85a06f 26#ifndef lint
1c15e888 27static char sccsid[] = "@(#)main.c 5.19 (Berkeley) 6/18/90";
d2c7d54c 28#endif /* not lint */
ed85a06f
SL
29
30#include <sys/param.h>
d96df0d1 31#include <sys/vmmac.h>
0be88646 32#include <sys/socket.h>
d2c7d54c 33#include <sys/file.h>
7cd60ad6 34#include <machine/pte.h>
ed85a06f
SL
35#include <ctype.h>
36#include <errno.h>
37#include <netdb.h>
38#include <nlist.h>
39#include <stdio.h>
4390c68f 40#include <paths.h>
ed85a06f 41
c34ecf77 42#define nl netstatnl
ed85a06f
SL
43struct nlist nl[] = {
44#define N_MBSTAT 0
45 { "_mbstat" },
46#define N_IPSTAT 1
47 { "_ipstat" },
48#define N_TCB 2
49 { "_tcb" },
50#define N_TCPSTAT 3
51 { "_tcpstat" },
52#define N_UDB 4
53 { "_udb" },
54#define N_UDPSTAT 5
55 { "_udpstat" },
56#define N_RAWCB 6
57 { "_rawcb" },
58#define N_SYSMAP 7
59 { "_Sysmap" },
60#define N_SYSSIZE 8
61 { "_Syssize" },
62#define N_IFNET 9
63 { "_ifnet" },
0e710523
MK
64#define N_IMP 10
65 { "_imp_softc" },
ed85a06f
SL
66#define N_RTHOST 11
67 { "_rthost" },
68#define N_RTNET 12
69 { "_rtnet" },
7333c75b
SL
70#define N_ICMPSTAT 13
71 { "_icmpstat" },
bbd2d21e
SL
72#define N_RTSTAT 14
73 { "_rtstat" },
404a567d
SL
74#define N_NFILE 15
75 { "_nfile" },
76#define N_FILE 16
77 { "_file" },
78#define N_UNIXSW 17
79 { "_unixsw" },
f508555e
MK
80#define N_RTHASHSIZE 18
81 { "_rthashsize" },
0be88646
KS
82#define N_IDP 19
83 { "_nspcb"},
84#define N_IDPSTAT 20
85 { "_idpstat"},
86#define N_SPPSTAT 21
87 { "_spp_istat"},
88#define N_NSERR 22
89 { "_ns_errstat"},
5262655f
KS
90#define N_CLNPSTAT 23
91 { "_clnp_stat"},
92#define IN_TP 24
93 { "_tp_inpcb" },
94#define ISO_TP 25
95 { "_tp_isopcb" },
96#define ISO_X25 26
0fa5c909 97 { /*"_x25_isopcb"*/ "_file"}, /* fast gross hack to speed up */
5262655f
KS
98#define N_TPSTAT 27
99 { "_tp_stat" },
100#define N_X25STAT 28
0fa5c909 101 { /*"_x25_stat"*/ "_file"},
5262655f
KS
102#define N_ESISSTAT 29
103 { "_esis_stat"},
104#define N_NIMP 30
0e710523 105 { "_nimp"},
5262655f 106#define N_RTREE 31
4390c68f 107 { "_radix_node_head"},
0fa5c909
KS
108#define N_CLTP 32
109 { "_cltb"},
110#define N_CLTPSTAT 33
111 { "_cltpstat"},
112
7333c75b 113 "",
ed85a06f
SL
114};
115
404a567d 116/* internet protocols */
6df0a927 117extern int protopr();
7333c75b 118extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats();
6538ea31 119/* ns protocols */
0be88646
KS
120extern int nsprotopr();
121extern int spp_stats(), idp_stats(), nserr_stats();
5262655f
KS
122/* iso protocols */
123extern int iso_protopr();
0fa5c909 124extern int tp_stats(), esis_stats(), clnp_stats(), cltp_stats();
6df0a927 125
6538ea31 126#define NULLPROTOX ((struct protox *) 0)
ed85a06f 127struct protox {
6df0a927
SL
128 u_char pr_index; /* index into nlist of cb head */
129 u_char pr_sindex; /* index into nlist of stat block */
130 u_char pr_wanted; /* 1 if wanted, 0 otherwise */
131 int (*pr_cblocks)(); /* control blocks printing routine */
132 int (*pr_stats)(); /* statistics printing routine */
133 char *pr_name; /* well-known name */
ed85a06f 134} protox[] = {
6df0a927
SL
135 { N_TCB, N_TCPSTAT, 1, protopr,
136 tcp_stats, "tcp" },
137 { N_UDB, N_UDPSTAT, 1, protopr,
138 udp_stats, "udp" },
5262655f
KS
139 { IN_TP, N_TPSTAT, 1, protopr,
140 tp_stats, "tpip" },
6df0a927
SL
141 { -1, N_IPSTAT, 1, 0,
142 ip_stats, "ip" },
7333c75b
SL
143 { -1, N_ICMPSTAT, 1, 0,
144 icmp_stats, "icmp" },
6df0a927
SL
145 { -1, -1, 0, 0,
146 0, 0 }
ed85a06f
SL
147};
148
0be88646
KS
149struct protox nsprotox[] = {
150 { N_IDP, N_IDPSTAT, 1, nsprotopr,
151 idp_stats, "idp" },
152 { N_IDP, N_SPPSTAT, 1, nsprotopr,
153 spp_stats, "spp" },
154 { -1, N_NSERR, 1, 0,
155 nserr_stats, "ns_err" },
156 { -1, -1, 0, 0,
157 0, 0 }
158};
159
5262655f
KS
160struct protox isoprotox[] = {
161 { ISO_TP, N_TPSTAT, 1, iso_protopr,
162 tp_stats, "tp" },
0fa5c909
KS
163 { N_CLTP, N_CLTPSTAT, 1, iso_protopr,
164 cltp_stats, "cltp" },
5262655f
KS
165#ifdef notdef
166 { ISO_X25, N_X25STAT, 1, x25_protopr,
167 x25_stats, "x25" },
168#endif
169 { -1, N_CLNPSTAT, 1, 0,
170 clnp_stats, "clnp"},
171 { -1, N_ESISSTAT, 1, 0,
172 esis_stats, "esis"},
173 { -1, -1, 0, 0,
174 0, 0 }
175};
176
177struct protox *protoprotox[] = { protox, nsprotox, isoprotox, NULLPROTOX };
178
ed85a06f
SL
179struct pte *Sysmap;
180
4390c68f 181char *system = _PATH_UNIX;
c34ecf77 182char *kmemf;
ed85a06f
SL
183int kmem;
184int kflag;
185int Aflag;
186int aflag;
187int hflag;
188int iflag;
189int mflag;
190int nflag;
6538ea31 191int pflag;
ed85a06f
SL
192int rflag;
193int sflag;
194int tflag;
2ebaad6c 195int dflag;
ed85a06f 196int interval;
79ddba48
EW
197char *interface;
198int unit;
ed85a06f 199
0be88646 200int af = AF_UNSPEC;
2a893f10 201
6538ea31
MK
202extern char *malloc();
203extern off_t lseek();
204
ed85a06f
SL
205main(argc, argv)
206 int argc;
207 char *argv[];
208{
d2c7d54c
KB
209 extern char *optarg;
210 extern int optind;
ed85a06f 211 register struct protoent *p;
6538ea31
MK
212 register struct protox *tp; /* for printing cblocks & stats */
213 struct protox *name2protox(); /* for -p */
d2c7d54c 214 int ch;
ed85a06f 215
2ebaad6c 216 while ((ch = getopt(argc, argv, "AI:af:himnp:drstu")) != EOF)
d2c7d54c 217 switch((char)ch) {
ed85a06f
SL
218 case 'A':
219 Aflag++;
220 break;
d2c7d54c
KB
221 case 'I': {
222 char *cp;
ed85a06f 223
d2c7d54c
KB
224 iflag++;
225 for (cp = interface = optarg; isalpha(*cp); cp++);
226 unit = atoi(cp);
227 *cp = '\0';
228 break;
229 }
ed85a06f
SL
230 case 'a':
231 aflag++;
232 break;
2ebaad6c
MK
233 case 'd':
234 dflag++;
235 break;
d2c7d54c
KB
236 case 'f':
237 if (strcmp(optarg, "ns") == 0)
238 af = AF_NS;
239 else if (strcmp(optarg, "inet") == 0)
240 af = AF_INET;
241 else if (strcmp(optarg, "unix") == 0)
242 af = AF_UNIX;
5262655f
KS
243 else if (strcmp(optarg, "iso") == 0)
244 af = AF_ISO;
d2c7d54c
KB
245 else {
246 fprintf(stderr, "%s: unknown address family\n", optarg);
247 exit(10);
248 }
249 break;
ed85a06f
SL
250 case 'h':
251 hflag++;
252 break;
ed85a06f
SL
253 case 'i':
254 iflag++;
255 break;
ed85a06f
SL
256 case 'm':
257 mflag++;
258 break;
ed85a06f
SL
259 case 'n':
260 nflag++;
261 break;
d2c7d54c
KB
262 case 'p':
263 if ((tp = name2protox(optarg)) == NULLPROTOX) {
264 fprintf(stderr, "%s: unknown or uninstrumented protocol\n", optarg);
265 exit(10);
266 }
267 pflag++;
268 break;
ed85a06f
SL
269 case 'r':
270 rflag++;
271 break;
ed85a06f
SL
272 case 's':
273 sflag++;
274 break;
ed85a06f
SL
275 case 't':
276 tflag++;
277 break;
404a567d 278 case 'u':
2a893f10 279 af = AF_UNIX;
404a567d 280 break;
d2c7d54c
KB
281 case '?':
282 default:
283 usage();
284 }
285 argv += optind;
286 argc -= optind;
404a567d 287
d2c7d54c
KB
288 if (argc > 0) {
289 if (isdigit(argv[0][0])) {
290 interval = atoi(argv[0]);
291 if (interval <= 0)
292 usage();
293 argv++, argc--;
79ddba48 294 iflag++;
d2c7d54c
KB
295 }
296 if (argc > 0) {
297 system = *argv;
298 argv++, argc--;
299 if (argc > 0) {
300 kmemf = *argv;
301 kflag++;
79ddba48 302 }
ed85a06f 303 }
ed85a06f 304 }
c34ecf77
KS
305 if (kvm_openfiles(system, kmemf, (char *)0) == -1) {
306 fprintf("netstat(kvm_openfiles): %s\n", kvm_geterr());
ed85a06f
SL
307 exit(1);
308 }
c34ecf77
KS
309 if (kvm_nlist(nl) < 0 || nl[0].n_type == 0) {
310 fprintf(stderr, "%s: no namelist\n", system);
ed85a06f
SL
311 exit(1);
312 }
ed85a06f 313 if (mflag) {
6538ea31
MK
314 mbpr((off_t)nl[N_MBSTAT].n_value);
315 exit(0);
316 }
317 if (pflag) {
318 if (tp->pr_stats)
d2c7d54c 319 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
6538ea31
MK
320 tp->pr_name);
321 else
322 printf("%s: no stats routine\n", tp->pr_name);
ed85a06f
SL
323 exit(0);
324 }
0e710523
MK
325 if (hflag) {
326 hostpr(nl[N_IMP].n_value, nl[N_NIMP].n_value);
327 exit(0);
328 }
ed85a06f
SL
329 /*
330 * Keep file descriptors open to avoid overhead
331 * of open/close on each call to get* routines.
332 */
ed85a06f
SL
333 sethostent(1);
334 setnetent(1);
90cb8200
SL
335 if (iflag) {
336 intpr(interval, nl[N_IFNET].n_value);
337 exit(0);
338 }
ed85a06f 339 if (rflag) {
bbd2d21e 340 if (sflag)
6538ea31 341 rt_stats((off_t)nl[N_RTSTAT].n_value);
bbd2d21e 342 else
6538ea31
MK
343 routepr((off_t)nl[N_RTHOST].n_value,
344 (off_t)nl[N_RTNET].n_value,
4390c68f
KS
345 (off_t)nl[N_RTHASHSIZE].n_value,
346 (off_t)nl[N_RTREE].n_value);
ed85a06f
SL
347 exit(0);
348 }
0be88646 349 if (af == AF_INET || af == AF_UNSPEC) {
90cb8200
SL
350 setprotoent(1);
351 setservent(1);
ed85a06f 352 while (p = getprotoent()) {
ed85a06f 353
6df0a927 354 for (tp = protox; tp->pr_name; tp++)
ed85a06f
SL
355 if (strcmp(tp->pr_name, p->p_name) == 0)
356 break;
6df0a927 357 if (tp->pr_name == 0 || tp->pr_wanted == 0)
ed85a06f 358 continue;
a5545777
MK
359 if (sflag) {
360 if (tp->pr_stats)
95f51977
C
361 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
362 p->p_name);
363 } else
364 if (tp->pr_cblocks)
365 (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
366 p->p_name);
ed85a06f
SL
367 }
368 endprotoent();
0be88646
KS
369 }
370 if (af == AF_NS || af == AF_UNSPEC) {
371 for (tp = nsprotox; tp->pr_name; tp++) {
54c165a5
MK
372 if (sflag) {
373 if (tp->pr_stats)
374 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
375 tp->pr_name);
376 } else
377 if (tp->pr_cblocks)
378 (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
379 tp->pr_name);
0be88646
KS
380 }
381 }
5262655f
KS
382 if (af == AF_ISO || af == AF_UNSPEC) {
383 for (tp = isoprotox; 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 }
54c165a5 394 if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
6538ea31
MK
395 unixpr((off_t)nl[N_NFILE].n_value, (off_t)nl[N_FILE].n_value,
396 (struct protosw *)nl[N_UNIXSW].n_value);
0e710523
MK
397 if (af == AF_UNSPEC && sflag)
398 impstats(nl[N_IMP].n_value, nl[N_NIMP].n_value);
085b521c 399 exit(0);
ed85a06f
SL
400}
401
bbd2d21e
SL
402
403char *
404plural(n)
405 int n;
406{
407
408 return (n != 1 ? "s" : "");
409}
6538ea31
MK
410
411/*
412 * Find the protox for the given "well-known" name.
413 */
414struct protox *
415knownname(name)
416 char *name;
417{
5262655f 418 struct protox **tpp, *tp;
d2c7d54c 419
5262655f
KS
420 for (tpp = protoprotox; *tpp; tpp++)
421 for (tp = *tpp; tp->pr_name; tp++)
6538ea31
MK
422 if (strcmp(tp->pr_name, name) == 0)
423 return(tp);
424 return(NULLPROTOX);
425}
426
427/*
428 * Find the protox corresponding to name.
429 */
430struct protox *
431name2protox(name)
432 char *name;
433{
434 struct protox *tp;
435 char **alias; /* alias from p->aliases */
436 struct protoent *p;
d2c7d54c 437
6538ea31
MK
438 /*
439 * Try to find the name in the list of "well-known" names. If that
440 * fails, check if name is an alias for an Internet protocol.
441 */
442 if (tp = knownname(name))
443 return(tp);
d2c7d54c 444
6538ea31
MK
445 setprotoent(1); /* make protocol lookup cheaper */
446 while (p = getprotoent()) {
447 /* assert: name not same as p->name */
448 for (alias = p->p_aliases; *alias; alias++)
449 if (strcmp(name, *alias) == 0) {
450 endprotoent();
451 return(knownname(p->p_name));
452 }
453 }
454 endprotoent();
455 return(NULLPROTOX);
456}
d2c7d54c
KB
457
458usage()
459{
460 fputs("usage: netstat [-Aan] [-f address_family] [system] [core]\n [-himnrs] [-f address_family] [system] [core]\n [-n] [-I interface] interval [system] [core]\n", stderr);
461 exit(1);
462}