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