|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)main.c 4.9 83/05/30";
3: #endif
4:
5: #include <sys/param.h>
6: #include <sys/vmmac.h>
7: #include <machine/pte.h>
8: #include <sys/socket.h>
9: #include <ctype.h>
10: #include <errno.h>
11: #include <netdb.h>
12: #include <nlist.h>
13: #include <stdio.h>
14: #include "nstat.h"
15:
16: extern int protopr(), arptab(), enperrors(), enpbuf();
17: extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats();
18: extern int acestat(), enpstat();
19:
20: struct protox {
21: u_char pr_wanted; /* 1 if wanted, 0 otherwise */
22: int (*pr_cblocks)(); /* control blocks printing routine */
23: int (*pr_stats)(); /* statistics printing routine */
24: char *pr_name; /* well-known name */
25: };
26: struct protox protox[] = {
27: { 1, protopr, tcp_stats, "tcp" },
28:
29: { 1, protopr, udp_stats, "udp" },
30:
31: { 1, 0, ip_stats, "ip" },
32:
33: { 1, 0, icmp_stats, "icmp" },
34:
35: { 0, 0, 0, 0 }
36: };
37:
38:
39: struct devx {
40: int (*d_stats)(); /* device statistics printing func */
41: char *d_name; /* well-known name */
42: };
43: struct devx devstat[] = {
44: { acestat, "ace"},
45: { enpstat, "enp"},
46: { 0 }
47: };
48:
49: struct pte *Sysmap;
50:
51: char *system = "/vmunix";
52: char *kmemf = "/dev/kmem";
53: int kmem; /* file descriptor of kmemf */
54:
55:
56: int interval; /* looping interval */
57: char *printproto; /* protocol flag */
58: char *devname; /* device name */
59:
60: #define DELIM() {printf("--------------------------------\n");}
61:
62: long flaggiven = 0x00000000;
63: int s; /* socket id */
64:
65: main(argc, argv)
66: int argc;
67: char *argv[];
68: {
69: int i;
70: char *cp, *name;
71: register struct protoent *p;
72: register struct protox *tp;
73:
74:
75: name = argv[0];
76: argc--, argv++;
77: while (argc > 0 && **argv == '-') {
78: for (cp = &argv[0][1]; *cp; cp++)
79: switch(*cp) {
80:
81: case 'A':
82: flaggiven |= AFLAG;
83: break;
84: case 'E':
85: s = socket(AF_INET, SOCK_DGRAM, 0);
86: if (s < 0) {
87: perror("main: socket");
88: exit(1);
89: }
90: flaggiven |= EFLAG;
91: break;
92: case 'e':
93: flaggiven |= eFLAG;
94: break;
95: case 'b':
96: argv++, argc--;
97: if (argc <= 0)
98: goto use;
99: devname = *argv;
100: flaggiven |= bFLAG;
101: break;
102: case 'a':
103: argv++, argc--;
104: if (argc <= 0)
105: goto use;
106: interval = atoi(argv[0]);
107: if (interval <= 0)
108: goto use;
109: break;
110:
111: case 'h':
112: flaggiven |= hFLAG;
113: break;
114:
115: case 'i':
116: flaggiven |= iFLAG;
117: break;
118:
119: case 'm':
120: flaggiven |= mFLAG;
121: break;
122:
123: case 'n':
124: flaggiven |= nFLAG;
125: break;
126:
127: case 'r':
128: flaggiven |= rFLAG;
129: break;
130:
131: case 's':
132: flaggiven |= sFLAG;
133: break;
134:
135: case 'c':
136: flaggiven |= cFLAG;
137: break;
138:
139: case 'p':
140: argv++, argc--;
141: if (argc <= 0)
142: goto use;
143: printproto = *argv;
144: flaggiven |= pFLAG;
145: break;
146:
147: case 'd':
148: argv++, argc--;
149: if (argc <= 0)
150: goto use;
151: devname = *argv;
152: flaggiven |= dFLAG;
153: break;
154: case 't':
155: flaggiven |= tFLAG;
156: break;
157:
158: case 'H':
159: default:
160: use:
161: help();
162: exit(1);
163: } /* end of switch */
164: argv++, argc--;
165: } /* end of while loop */
166: /* will print pcb when: */
167: if (!flaggiven || /* no option given at all */
168: Aflag || /* debug option */
169: (flaggiven == nFLAG) || /* only numeric flag given */
170: (flaggiven == pFLAG) || /* only protocol flag given */
171: (flaggiven == (nFLAG | pFLAG)) ) {
172: flaggiven |= cFLAG;
173: }
174:
175: if (argc > 0) {
176: system = *argv;
177: argv++, argc--;
178: }
179: if (argc > 0) {
180: kmemf = *argv;
181: flaggiven |= kFLAG;
182: }
183: kmem = open(kmemf, 0);
184: if (kmem < 0) {
185: fprintf(stderr, "nstat: cannot open ");
186: perror(kmemf);
187: exit(1);
188: }
189:
190: /*
191: * Keep file descriptors open to avoid overhead
192: * of open/close on each call to get* routines.
193: */
194: sethostent(1);
195: setnetent(1);
196:
197: for (;;) {
198: if (Eflag) {
199: DELIM();
200: arptab();
201: }
202: if (eflag) {
203: enperrors();
204: }
205: if (iflag || tflag) {
206: if (tflag && interval <= 0)
207: interval = 1;
208: DELIM();
209: intpr(interval);
210: }
211: if (kflag) {
212: rkmem();
213: }
214: if (mflag) {
215: DELIM();
216: mbpr();
217: }
218:
219: if (hflag) {
220: DELIM();
221: hostpr();
222: }
223: if (sflag) {
224: DELIM();
225: rt_stats();
226: }
227: if (rflag) {
228: DELIM();
229: routepr();
230: }
231: if (dflag || bflag) {
232: struct devx *p;
233: int i, unit;
234: char *c;
235:
236: c = devname;
237: while (*c && !isdigit(*c)) {
238: c++, i++;
239: }
240: if (*c)
241: unit = *c - '0';
242: else
243: unit = WILDCARD;
244:
245: for (p = devstat; p->d_name; p++) {
246: if (strncmp(p->d_name, devname, i) == 0)
247: break;
248: }
249: if (p->d_name == 0)
250: fprintf(stderr, "nstat: illegal device %s\n",devname);
251: else {
252: if (bflag) {
253: if (strncmp(p->d_name, "enp", 3) == 0)
254: enpbuf(unit);
255: else
256: fprintf(stderr,
257: "nstat: -b works for enp device only\n");
258: } else
259: if (dflag && p->d_stats)
260: (*p->d_stats)(unit, 0);
261: }
262: }
263: if (sflag) {
264: /* go through list of available protocols in system */
265: setprotoent(1);
266: setservent(1);
267: while (p = getprotoent()) {
268:
269: /* user gave any specific protocol? */
270: if (pflag &&
271: strcmp(p->p_name, printproto) != 0)
272: continue;
273:
274: /* go through list of protocols 'nstat' supports */
275: for (tp = protox; tp->pr_name; tp++)
276: if (strcmp(tp->pr_name, p->p_name) == 0)
277: break;
278: if (tp->pr_name == 0 || tp->pr_wanted == 0)
279: continue;
280:
281: /* found one protocol */
282: if (tp->pr_stats) {
283: DELIM();
284: (*tp->pr_stats)();
285: continue;
286: }
287: }
288: }
289:
290: if (cflag) {
291: setprotoent(1);
292: setservent(1);
293: while (p = getprotoent()) {
294:
295: if (pflag &&
296: strcmp(p->p_name, printproto) != 0)
297: continue;
298:
299: for (tp = protox; tp->pr_name; tp++)
300: if (strcmp(tp->pr_name, p->p_name) == 0)
301: break;
302: if (tp->pr_name == 0 || tp->pr_wanted == 0)
303: continue;
304: if (tp->pr_cblocks) {
305: DELIM();
306: (*tp->pr_cblocks)(tp->pr_name);
307: }
308: }
309: }
310: if (interval)
311: sleep(interval);
312: else {
313: DELIM();
314: close(kmem);
315: exit(0);
316: }
317: }
318: }
319:
320: /*
321: * Seek into the kernel for a value.
322: */
323: klseek(fd, base, off)
324: int fd, base, off;
325: {
326:
327: if (kflag) {
328: /* get kernel pte */
329: #if defined(vax) || defined(tahoe)
330: base &= 0x3FFFFFFF;
331: #endif
332: base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
333: }
334: lseek(fd, base, off);
335: }
336:
337: char *
338: plural(n)
339: int n;
340: {
341:
342: return (n != 1 ? "s" : "");
343: }
344:
345:
346:
347: help()
348: {
349:
350: printf("nstat [-HdchimnprstEAeb] [-p proto] [interval] [system] [core]\n");
351: printf("where:\n");
352: printf("-H HELP. print all available options.\n");
353: printf("-a interval\n");
354: printf(" specify nstat to continuously list the status, pausing");
355: printf(" for each interval between displays.\n");
356: printf("-d devicename\n");
357: printf(" show statistics associated with device.\n");
358: printf("-c show all connections.\n");
359: printf("-h show the state of the IMP host table.\n");
360: printf("-i show the state of auto-configured interfaces.\n");
361: printf("-m show mbuf statistics.\n");
362: printf("-n show network addresses as numbers.\n");
363: printf("-p protocol\n");
364: printf(" only print connections of 'protocol'.\n");
365: printf("-r show the routing tables\n");
366: printf("-s show protocol statistics\n");
367: printf("-t show data transmission through interfaces periodically.\n");
368: printf("-E show Ethernet/Internet addresses of currently-up hosts.\n");
369: printf("-A show addresses of PCBs; for debugging\n");
370: /* don't expose these 2 options to users */
371: #ifdef notdef
372: printf("-e show Driver-Level input-packet error types; for debugging\n");
373: printf("-b devicename (for enpX only); for debugging\n");
374: printf(" show ENP buffer rings' pointers.\n");
375: #endif
376: printf("The arguments 'system' and 'core' allow substitutes for the\n");
377: printf("defaults '/vmunix' and '/dev/kmem'.\n");
378: }
379:
380: struct nlist sysmapnl[] = {
381: #define N_SYSMAP 0
382: { "_Sysmap" },
383: #define N_SYSSIZE 1
384: { "_Syssize" },
385: {""},
386: };
387: rkmem()
388: {
389: static int getvm = 0;
390: off_t off;
391:
392: if (!getvm) {
393: nlist(system, sysmapnl);
394: getvm++;
395: }
396: sysmapnl[N_SYSSIZE].n_value *= 4;
397: Sysmap = (struct pte *)malloc(sysmapnl[N_SYSSIZE].n_value);
398: if (Sysmap == 0) {
399: perror("rsysmap");
400: exit(1);
401: }
402: #ifdef tahoe
403: off = sysmapnl[N_SYSMAP].n_value & 0x3FFFFFFF;
404: #endif
405: lseek(kmem, off, 0);
406: read(kmem, Sysmap, sysmapnl[N_SYSSIZE].n_value);
407: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.