branch for FTP release (#ifdef for sun)
[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
33e1c186 14static char sccsid[] = "@(#)main.c 5.9 (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();
6538ea31 91/* ns protocols */
a5545777 92extern int tcpstats(), udpstats(), ipstats(), icmpstats(), rdpstats();
0be88646
KS
93extern int nsprotopr();
94extern int spp_stats(), idp_stats(), nserr_stats();
6df0a927 95
6538ea31 96#define NULLPROTOX ((struct protox *) 0)
ed85a06f 97struct protox {
6df0a927
SL
98 u_char pr_index; /* index into nlist of cb head */
99 u_char pr_sindex; /* index into nlist of stat block */
100 u_char pr_wanted; /* 1 if wanted, 0 otherwise */
101 int (*pr_cblocks)(); /* control blocks printing routine */
102 int (*pr_stats)(); /* statistics printing routine */
103 char *pr_name; /* well-known name */
a5545777
MK
104};
105
106struct protox berkprotox[] = {
6df0a927
SL
107 { N_TCB, N_TCPSTAT, 1, protopr,
108 tcp_stats, "tcp" },
109 { N_UDB, N_UDPSTAT, 1, protopr,
110 udp_stats, "udp" },
111 { -1, N_IPSTAT, 1, 0,
112 ip_stats, "ip" },
7333c75b
SL
113 { -1, N_ICMPSTAT, 1, 0,
114 icmp_stats, "icmp" },
6df0a927
SL
115 { -1, -1, 0, 0,
116 0, 0 }
ed85a06f
SL
117};
118
a5545777
MK
119struct protox bbnprotox[] = {
120 { N_TCP, N_TCPSTAT, 1, bbnprotopr,
121 tcpstats, "tcp" },
122 { N_UDP, N_UDPSTAT, 1, bbnprotopr,
123 udpstats, "udp" },
124 { N_RDP, N_RDPSTAT, 1, bbnprotopr,
125 rdpstats, "rdp" },
126 { N_RAWCB, 0, 1, bbnprotopr,
127 0, "raw" },
128 { -1, N_IPSTAT, 1, 0,
129 ipstats, "ip" },
130 { -1, N_ICMPSTAT, 1, 0,
131 icmpstats, "icmp" },
132 { -1, -1, 0, 0,
133 0, 0 }
134};
135
0be88646
KS
136struct protox nsprotox[] = {
137 { N_IDP, N_IDPSTAT, 1, nsprotopr,
138 idp_stats, "idp" },
139 { N_IDP, N_SPPSTAT, 1, nsprotopr,
140 spp_stats, "spp" },
141 { -1, N_NSERR, 1, 0,
142 nserr_stats, "ns_err" },
143 { -1, -1, 0, 0,
144 0, 0 }
145};
146
ed85a06f
SL
147struct pte *Sysmap;
148
149char *system = "/vmunix";
150char *kmemf = "/dev/kmem";
151int kmem;
152int kflag;
153int Aflag;
154int aflag;
155int hflag;
156int iflag;
157int mflag;
158int nflag;
6538ea31 159int pflag;
ed85a06f
SL
160int rflag;
161int sflag;
162int tflag;
163int interval;
79ddba48
EW
164char *interface;
165int unit;
6538ea31 166char usage[] = "[ -Aaihmnrst ] [-f family] [-p proto] [-I interface] [ interval ] [ system ] [ core ]";
ed85a06f 167
0be88646 168int af = AF_UNSPEC;
2a893f10 169
6538ea31
MK
170extern char *malloc();
171extern off_t lseek();
172
ed85a06f
SL
173main(argc, argv)
174 int argc;
175 char *argv[];
176{
ed85a06f
SL
177 char *cp, *name;
178 register struct protoent *p;
6538ea31
MK
179 register struct protox *tp; /* for printing cblocks & stats */
180 struct protox *name2protox(); /* for -p */
181
ed85a06f
SL
182 name = argv[0];
183 argc--, argv++;
184 while (argc > 0 && **argv == '-') {
185 for (cp = &argv[0][1]; *cp; cp++)
18f196b0 186 switch(*cp) {
ed85a06f
SL
187
188 case 'A':
189 Aflag++;
190 break;
191
192 case 'a':
193 aflag++;
194 break;
195
196 case 'h':
197 hflag++;
198 break;
199
200 case 'i':
201 iflag++;
202 break;
203
204 case 'm':
205 mflag++;
206 break;
207
208 case 'n':
209 nflag++;
210 break;
211
212 case 'r':
213 rflag++;
214 break;
215
216 case 's':
217 sflag++;
218 break;
219
220 case 't':
221 tflag++;
222 break;
223
404a567d 224 case 'u':
2a893f10 225 af = AF_UNIX;
404a567d
SL
226 break;
227
6538ea31
MK
228 case 'p':
229 argv++;
230 argc--;
231 if (argc == 0)
232 goto use;
233 if ((tp = name2protox(*argv)) == NULLPROTOX) {
234 fprintf(stderr, "%s: unknown or uninstrumented protocol\n",
235 *argv);
236 exit(10);
237 }
238 pflag++;
239 break;
240
0be88646
KS
241 case 'f':
242 argv++;
243 argc--;
2a893f10 244 if (strcmp(*argv, "ns") == 0)
0be88646 245 af = AF_NS;
2a893f10 246 else if (strcmp(*argv, "inet") == 0)
0be88646 247 af = AF_INET;
2a893f10
MK
248 else if (strcmp(*argv, "unix") == 0)
249 af = AF_UNIX;
250 else {
251 fprintf(stderr, "%s: unknown address family\n",
252 *argv);
253 exit(10);
0be88646
KS
254 }
255 break;
256
79ddba48
EW
257 case 'I':
258 iflag++;
259 if (*(interface = cp + 1) == 0) {
260 if ((interface = argv[1]) == 0)
261 break;
262 argv++;
263 argc--;
264 }
265 for (cp = interface; isalpha(*cp); cp++)
266 ;
267 unit = atoi(cp);
268 *cp-- = 0;
269 break;
270
ed85a06f
SL
271 default:
272use:
273 printf("usage: %s %s\n", name, usage);
274 exit(1);
275 }
276 argv++, argc--;
277 }
278 if (argc > 0 && isdigit(argv[0][0])) {
279 interval = atoi(argv[0]);
280 if (interval <= 0)
281 goto use;
282 argv++, argc--;
90cb8200 283 iflag++;
ed85a06f
SL
284 }
285 if (argc > 0) {
286 system = *argv;
287 argv++, argc--;
288 }
289 nlist(system, nl);
290 if (nl[0].n_type == 0) {
291 fprintf(stderr, "%s: no namelist\n", system);
292 exit(1);
293 }
294 if (argc > 0) {
295 kmemf = *argv;
296 kflag++;
297 }
298 kmem = open(kmemf, 0);
299 if (kmem < 0) {
300 fprintf(stderr, "cannot open ");
301 perror(kmemf);
302 exit(1);
303 }
304 if (kflag) {
305 off_t off;
306
307 off = nl[N_SYSMAP].n_value & 0x7fffffff;
308 lseek(kmem, off, 0);
309 nl[N_SYSSIZE].n_value *= 4;
6538ea31 310 Sysmap = (struct pte *)malloc((u_int)nl[N_SYSSIZE].n_value);
ed85a06f
SL
311 if (Sysmap == 0) {
312 perror("Sysmap");
313 exit(1);
314 }
6538ea31 315 read(kmem, (char *)Sysmap, (int)nl[N_SYSSIZE].n_value);
ed85a06f
SL
316 }
317 if (mflag) {
6538ea31
MK
318 mbpr((off_t)nl[N_MBSTAT].n_value);
319 exit(0);
320 }
321 if (pflag) {
322 if (tp->pr_stats)
323 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
324 tp->pr_name);
325 else
326 printf("%s: no stats routine\n", tp->pr_name);
ed85a06f
SL
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
SL
339 if (hflag) {
340 hostpr(nl[N_HOSTS].n_value);
341 exit(0);
342 }
343 if (rflag) {
bbd2d21e 344 if (sflag)
6538ea31 345 rt_stats((off_t)nl[N_RTSTAT].n_value);
bbd2d21e 346 else
6538ea31
MK
347 routepr((off_t)nl[N_RTHOST].n_value,
348 (off_t)nl[N_RTNET].n_value,
349 (off_t)nl[N_RTHASHSIZE].n_value);
ed85a06f
SL
350 exit(0);
351 }
0be88646 352 if (af == AF_INET || af == AF_UNSPEC) {
a5545777
MK
353 struct protox *head;
354
355 head = (nl[N_TCB].n_type == 0) ? bbnprotox : berkprotox;
90cb8200
SL
356 setprotoent(1);
357 setservent(1);
ed85a06f 358
a5545777
MK
359 for (tp = head; tp->pr_name; tp++) {
360 if (tp->pr_wanted == 0)
ed85a06f 361 continue;
a5545777
MK
362
363 if (sflag) {
364 if (tp->pr_stats)
365 (*tp->pr_stats)(nl[tp->pr_sindex].n_value, tp->pr_name);
366 } else if (tp->pr_cblocks)
367 (*tp->pr_cblocks)(nl[tp->pr_index].n_value, tp->pr_name);
ed85a06f
SL
368 }
369 endprotoent();
0be88646
KS
370 }
371 if (af == AF_NS || af == AF_UNSPEC) {
372 for (tp = nsprotox; tp->pr_name; tp++) {
54c165a5
MK
373 if (sflag) {
374 if (tp->pr_stats)
375 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
376 tp->pr_name);
377 } else
378 if (tp->pr_cblocks)
379 (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
380 tp->pr_name);
0be88646
KS
381 }
382 }
54c165a5 383 if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
6538ea31
MK
384 unixpr((off_t)nl[N_NFILE].n_value, (off_t)nl[N_FILE].n_value,
385 (struct protosw *)nl[N_UNIXSW].n_value);
085b521c 386 exit(0);
ed85a06f
SL
387}
388
389/*
390 * Seek into the kernel for a value.
391 */
6538ea31 392off_t
ed85a06f 393klseek(fd, base, off)
6538ea31
MK
394 int fd, off;
395 off_t base;
ed85a06f 396{
ed85a06f
SL
397 if (kflag) {
398 /* get kernel pte */
33e1c186 399 base &= ~KERNBASE;
d96df0d1 400 base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
ed85a06f 401 }
6538ea31 402 return (lseek(fd, base, off));
ed85a06f 403}
bbd2d21e
SL
404
405char *
406plural(n)
407 int n;
408{
409
410 return (n != 1 ? "s" : "");
411}
6538ea31
MK
412
413/*
414 * Find the protox for the given "well-known" name.
415 */
416struct protox *
417knownname(name)
418 char *name;
419{
420 struct protox *tp;
421
422 for (tp = protox; tp->pr_name; tp++)
423 if (strcmp(tp->pr_name, name) == 0)
424 return(tp);
425 for (tp = nsprotox; tp->pr_name; tp++)
426 if (strcmp(tp->pr_name, name) == 0)
427 return(tp);
428 return(NULLPROTOX);
429}
430
431/*
432 * Find the protox corresponding to name.
433 */
434struct protox *
435name2protox(name)
436 char *name;
437{
438 struct protox *tp;
439 char **alias; /* alias from p->aliases */
440 struct protoent *p;
441
442 /*
443 * Try to find the name in the list of "well-known" names. If that
444 * fails, check if name is an alias for an Internet protocol.
445 */
446 if (tp = knownname(name))
447 return(tp);
448
449 setprotoent(1); /* make protocol lookup cheaper */
450 while (p = getprotoent()) {
451 /* assert: name not same as p->name */
452 for (alias = p->p_aliases; *alias; alias++)
453 if (strcmp(name, *alias) == 0) {
454 endprotoent();
455 return(knownname(p->p_name));
456 }
457 }
458 endprotoent();
459 return(NULLPROTOX);
460}