first draft
[unix-history] / usr / src / usr.bin / netstat / main.c
CommitLineData
5ff67f98
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
9"@(#) Copyright (c) 1983 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
ed85a06f 13#ifndef lint
38d9ef3b 14static char sccsid[] = "@(#)main.c 5.8 (Berkeley) %G%";
5ff67f98 15#endif not lint
ed85a06f
SL
16
17#include <sys/param.h>
d96df0d1 18#include <sys/vmmac.h>
0be88646 19#include <sys/socket.h>
7cd60ad6 20#include <machine/pte.h>
ed85a06f
SL
21#include <ctype.h>
22#include <errno.h>
23#include <netdb.h>
24#include <nlist.h>
25#include <stdio.h>
26
27struct nlist nl[] = {
28#define N_MBSTAT 0
29 { "_mbstat" },
30#define N_IPSTAT 1
31 { "_ipstat" },
32#define N_TCB 2
33 { "_tcb" },
34#define N_TCPSTAT 3
35 { "_tcpstat" },
36#define N_UDB 4
37 { "_udb" },
38#define N_UDPSTAT 5
39 { "_udpstat" },
40#define N_RAWCB 6
41 { "_rawcb" },
42#define N_SYSMAP 7
43 { "_Sysmap" },
44#define N_SYSSIZE 8
45 { "_Syssize" },
46#define N_IFNET 9
47 { "_ifnet" },
48#define N_HOSTS 10
49 { "_hosts" },
50#define N_RTHOST 11
51 { "_rthost" },
52#define N_RTNET 12
53 { "_rtnet" },
7333c75b
SL
54#define N_ICMPSTAT 13
55 { "_icmpstat" },
bbd2d21e
SL
56#define N_RTSTAT 14
57 { "_rtstat" },
404a567d
SL
58#define N_NFILE 15
59 { "_nfile" },
60#define N_FILE 16
61 { "_file" },
62#define N_UNIXSW 17
63 { "_unixsw" },
f508555e
MK
64#define N_RTHASHSIZE 18
65 { "_rthashsize" },
0be88646
KS
66#define N_IDP 19
67 { "_nspcb"},
68#define N_IDPSTAT 20
69 { "_idpstat"},
70#define N_SPPSTAT 21
71 { "_spp_istat"},
72#define N_NSERR 22
73 { "_ns_errstat"},
a5545777
MK
74
75 /* BBN Internet protocol implementation */
76#define N_TCP 23
77 { "_tcp" },
78#define N_UDP 24
79 { "_udp" },
80#define N_RDP 25
81 { "_rdp" },
82#define N_RDPSTAT 26
83 { "_rdpstat" },
84
7333c75b 85 "",
ed85a06f
SL
86};
87
404a567d 88/* internet protocols */
a5545777 89extern int protopr(), bbnprotopr();
7333c75b 90extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats();
a5545777 91extern int tcpstats(), udpstats(), ipstats(), icmpstats(), rdpstats();
0be88646
KS
92extern int nsprotopr();
93extern int spp_stats(), idp_stats(), nserr_stats();
6df0a927 94
ed85a06f 95struct protox {
6df0a927
SL
96 u_char pr_index; /* index into nlist of cb head */
97 u_char pr_sindex; /* index into nlist of stat block */
98 u_char pr_wanted; /* 1 if wanted, 0 otherwise */
99 int (*pr_cblocks)(); /* control blocks printing routine */
100 int (*pr_stats)(); /* statistics printing routine */
101 char *pr_name; /* well-known name */
a5545777
MK
102};
103
104struct protox berkprotox[] = {
6df0a927
SL
105 { N_TCB, N_TCPSTAT, 1, protopr,
106 tcp_stats, "tcp" },
107 { N_UDB, N_UDPSTAT, 1, protopr,
108 udp_stats, "udp" },
109 { -1, N_IPSTAT, 1, 0,
110 ip_stats, "ip" },
7333c75b
SL
111 { -1, N_ICMPSTAT, 1, 0,
112 icmp_stats, "icmp" },
6df0a927
SL
113 { -1, -1, 0, 0,
114 0, 0 }
ed85a06f
SL
115};
116
a5545777
MK
117struct protox bbnprotox[] = {
118 { N_TCP, N_TCPSTAT, 1, bbnprotopr,
119 tcpstats, "tcp" },
120 { N_UDP, N_UDPSTAT, 1, bbnprotopr,
121 udpstats, "udp" },
122 { N_RDP, N_RDPSTAT, 1, bbnprotopr,
123 rdpstats, "rdp" },
124 { N_RAWCB, 0, 1, bbnprotopr,
125 0, "raw" },
126 { -1, N_IPSTAT, 1, 0,
127 ipstats, "ip" },
128 { -1, N_ICMPSTAT, 1, 0,
129 icmpstats, "icmp" },
130 { -1, -1, 0, 0,
131 0, 0 }
132};
133
0be88646
KS
134struct protox nsprotox[] = {
135 { N_IDP, N_IDPSTAT, 1, nsprotopr,
136 idp_stats, "idp" },
137 { N_IDP, N_SPPSTAT, 1, nsprotopr,
138 spp_stats, "spp" },
139 { -1, N_NSERR, 1, 0,
140 nserr_stats, "ns_err" },
141 { -1, -1, 0, 0,
142 0, 0 }
143};
144
ed85a06f
SL
145struct pte *Sysmap;
146
147char *system = "/vmunix";
148char *kmemf = "/dev/kmem";
149int kmem;
150int kflag;
151int Aflag;
152int aflag;
153int hflag;
154int iflag;
155int mflag;
156int nflag;
157int rflag;
158int sflag;
159int tflag;
0be88646 160int fflag;
ed85a06f 161int interval;
79ddba48
EW
162char *interface;
163int unit;
2a893f10 164char usage[] = "[ -Aaihmnrst ] [-f address_family] [-I interface] [ interval ] [ system ] [ core ]";
ed85a06f 165
0be88646 166int af = AF_UNSPEC;
2a893f10 167
ed85a06f
SL
168main(argc, argv)
169 int argc;
170 char *argv[];
171{
172 int i;
173 char *cp, *name;
174 register struct protoent *p;
0be88646 175 register struct protox *tp;
ed85a06f
SL
176
177 name = argv[0];
178 argc--, argv++;
179 while (argc > 0 && **argv == '-') {
180 for (cp = &argv[0][1]; *cp; cp++)
18f196b0 181 switch(*cp) {
ed85a06f
SL
182
183 case 'A':
184 Aflag++;
185 break;
186
187 case 'a':
188 aflag++;
189 break;
190
191 case 'h':
192 hflag++;
193 break;
194
195 case 'i':
196 iflag++;
197 break;
198
199 case 'm':
200 mflag++;
201 break;
202
203 case 'n':
204 nflag++;
205 break;
206
207 case 'r':
208 rflag++;
209 break;
210
211 case 's':
212 sflag++;
213 break;
214
215 case 't':
216 tflag++;
217 break;
218
404a567d 219 case 'u':
2a893f10 220 af = AF_UNIX;
404a567d
SL
221 break;
222
0be88646
KS
223 case 'f':
224 argv++;
225 argc--;
2a893f10 226 if (strcmp(*argv, "ns") == 0)
0be88646 227 af = AF_NS;
2a893f10 228 else if (strcmp(*argv, "inet") == 0)
0be88646 229 af = AF_INET;
2a893f10
MK
230 else if (strcmp(*argv, "unix") == 0)
231 af = AF_UNIX;
232 else {
233 fprintf(stderr, "%s: unknown address family\n",
234 *argv);
235 exit(10);
0be88646
KS
236 }
237 break;
238
79ddba48
EW
239 case 'I':
240 iflag++;
241 if (*(interface = cp + 1) == 0) {
242 if ((interface = argv[1]) == 0)
243 break;
244 argv++;
245 argc--;
246 }
247 for (cp = interface; isalpha(*cp); cp++)
248 ;
249 unit = atoi(cp);
250 *cp-- = 0;
251 break;
252
ed85a06f
SL
253 default:
254use:
255 printf("usage: %s %s\n", name, usage);
256 exit(1);
257 }
258 argv++, argc--;
259 }
260 if (argc > 0 && isdigit(argv[0][0])) {
261 interval = atoi(argv[0]);
262 if (interval <= 0)
263 goto use;
264 argv++, argc--;
90cb8200 265 iflag++;
ed85a06f
SL
266 }
267 if (argc > 0) {
268 system = *argv;
269 argv++, argc--;
270 }
271 nlist(system, nl);
272 if (nl[0].n_type == 0) {
273 fprintf(stderr, "%s: no namelist\n", system);
274 exit(1);
275 }
276 if (argc > 0) {
277 kmemf = *argv;
278 kflag++;
279 }
280 kmem = open(kmemf, 0);
281 if (kmem < 0) {
282 fprintf(stderr, "cannot open ");
283 perror(kmemf);
284 exit(1);
285 }
286 if (kflag) {
287 off_t off;
288
289 off = nl[N_SYSMAP].n_value & 0x7fffffff;
290 lseek(kmem, off, 0);
291 nl[N_SYSSIZE].n_value *= 4;
292 Sysmap = (struct pte *)malloc(nl[N_SYSSIZE].n_value);
293 if (Sysmap == 0) {
294 perror("Sysmap");
295 exit(1);
296 }
297 read(kmem, Sysmap, nl[N_SYSSIZE].n_value);
298 }
299 if (mflag) {
300 mbpr(nl[N_MBSTAT].n_value);
301 exit(0);
302 }
ed85a06f
SL
303 /*
304 * Keep file descriptors open to avoid overhead
305 * of open/close on each call to get* routines.
306 */
ed85a06f
SL
307 sethostent(1);
308 setnetent(1);
90cb8200
SL
309 if (iflag) {
310 intpr(interval, nl[N_IFNET].n_value);
311 exit(0);
312 }
ed85a06f
SL
313 if (hflag) {
314 hostpr(nl[N_HOSTS].n_value);
315 exit(0);
316 }
317 if (rflag) {
bbd2d21e
SL
318 if (sflag)
319 rt_stats(nl[N_RTSTAT].n_value);
320 else
f508555e
MK
321 routepr(nl[N_RTHOST].n_value, nl[N_RTNET].n_value,
322 nl[N_RTHASHSIZE].n_value);
ed85a06f
SL
323 exit(0);
324 }
0be88646 325 if (af == AF_INET || af == AF_UNSPEC) {
a5545777
MK
326 struct protox *head;
327
328 head = (nl[N_TCB].n_type == 0) ? bbnprotox : berkprotox;
90cb8200
SL
329 setprotoent(1);
330 setservent(1);
ed85a06f 331
a5545777
MK
332 for (tp = head; tp->pr_name; tp++) {
333 if (tp->pr_wanted == 0)
ed85a06f 334 continue;
a5545777
MK
335
336 if (sflag) {
337 if (tp->pr_stats)
338 (*tp->pr_stats)(nl[tp->pr_sindex].n_value, tp->pr_name);
339 } else if (tp->pr_cblocks)
340 (*tp->pr_cblocks)(nl[tp->pr_index].n_value, tp->pr_name);
ed85a06f
SL
341 }
342 endprotoent();
0be88646
KS
343 }
344 if (af == AF_NS || af == AF_UNSPEC) {
345 for (tp = nsprotox; tp->pr_name; tp++) {
54c165a5
MK
346 if (sflag) {
347 if (tp->pr_stats)
348 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
349 tp->pr_name);
350 } else
351 if (tp->pr_cblocks)
352 (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
353 tp->pr_name);
0be88646
KS
354 }
355 }
54c165a5 356 if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
2a893f10
MK
357 unixpr(nl[N_NFILE].n_value, nl[N_FILE].n_value,
358 nl[N_UNIXSW].n_value);
085b521c 359 exit(0);
ed85a06f
SL
360}
361
362/*
363 * Seek into the kernel for a value.
364 */
365klseek(fd, base, off)
366 int fd, base, off;
367{
368
369 if (kflag) {
370 /* get kernel pte */
4659bf8e 371#ifdef vax
ed85a06f 372 base &= 0x7fffffff;
4659bf8e 373#endif
d96df0d1 374 base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
ed85a06f
SL
375 }
376 lseek(fd, base, off);
377}
bbd2d21e
SL
378
379char *
380plural(n)
381 int n;
382{
383
384 return (n != 1 ? "s" : "");
385}