|
|
1.1 root 1: /*
2: * Copyright (c) 1983, 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: */
17:
18: #ifndef lint
19: char copyright[] =
20: "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
21: All rights reserved.\n";
22: #endif /* not lint */
23:
24: #ifndef lint
25: static char sccsid[] = "@(#)main.c 5.14 (Berkeley) 6/29/88";
26: #endif /* not lint */
27:
28: #include <sys/param.h>
29: #include <sys/vmmac.h>
30: #include <sys/socket.h>
31: #include <sys/file.h>
32: #include <machine/pte.h>
33: #include <ctype.h>
34: #include <errno.h>
35: #include <netdb.h>
36: #include <nlist.h>
37: #include <stdio.h>
38:
39: struct nlist nl[] = {
40: #define N_MBSTAT 0
41: { "_mbstat" },
42: #define N_IPSTAT 1
43: { "_ipstat" },
44: #define N_TCB 2
45: { "_tcb" },
46: #define N_TCPSTAT 3
47: { "_tcpstat" },
48: #define N_UDB 4
49: { "_udb" },
50: #define N_UDPSTAT 5
51: { "_udpstat" },
52: #define N_RAWCB 6
53: { "_rawcb" },
54: #define N_SYSMAP 7
55: { "_Sysmap" },
56: #define N_SYSSIZE 8
57: { "_Syssize" },
58: #define N_IFNET 9
59: { "_ifnet" },
60: #define N_IMP 10
61: { "_imp_softc" },
62: #define N_RTHOST 11
63: { "_rthost" },
64: #define N_RTNET 12
65: { "_rtnet" },
66: #define N_ICMPSTAT 13
67: { "_icmpstat" },
68: #define N_RTSTAT 14
69: { "_rtstat" },
70: #define N_NFILE 15
71: { "_nfile" },
72: #define N_FILE 16
73: { "_file" },
74: #define N_UNIXSW 17
75: { "_unixsw" },
76: #define N_RTHASHSIZE 18
77: { "_rthashsize" },
78: #define N_IDP 19
79: { "_nspcb"},
80: #define N_IDPSTAT 20
81: { "_idpstat"},
82: #define N_SPPSTAT 21
83: { "_spp_istat"},
84: #define N_NSERR 22
85: { "_ns_errstat"},
86: #define N_NIMP 23
87: { "_nimp"},
88: "",
89: };
90:
91: /* internet protocols */
92: extern int protopr();
93: extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats();
94: /* ns protocols */
95: extern int nsprotopr();
96: extern int spp_stats(), idp_stats(), nserr_stats();
97:
98: #define NULLPROTOX ((struct protox *) 0)
99: struct protox {
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 */
106: } protox[] = {
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" },
113: { -1, N_ICMPSTAT, 1, 0,
114: icmp_stats, "icmp" },
115: { -1, -1, 0, 0,
116: 0, 0 }
117: };
118:
119: struct protox nsprotox[] = {
120: { N_IDP, N_IDPSTAT, 1, nsprotopr,
121: idp_stats, "idp" },
122: { N_IDP, N_SPPSTAT, 1, nsprotopr,
123: spp_stats, "spp" },
124: { -1, N_NSERR, 1, 0,
125: nserr_stats, "ns_err" },
126: { -1, -1, 0, 0,
127: 0, 0 }
128: };
129:
130: struct pte *Sysmap;
131:
132: char *system = "/vmunix";
133: char *kmemf = "/dev/kmem";
134: int kmem;
135: int kflag;
136: int Aflag;
137: int aflag;
138: int hflag;
139: int iflag;
140: int mflag;
141: int nflag;
142: int pflag;
143: int rflag;
144: int sflag;
145: int tflag;
146: int dflag;
147: int interval;
148: char *interface;
149: int unit;
150:
151: int af = AF_UNSPEC;
152:
153: extern char *malloc();
154: extern off_t lseek();
155:
156: main(argc, argv)
157: int argc;
158: char *argv[];
159: {
160: extern char *optarg;
161: extern int optind;
162: register struct protoent *p;
163: register struct protox *tp; /* for printing cblocks & stats */
164: struct protox *name2protox(); /* for -p */
165: int ch;
166:
167: while ((ch = getopt(argc, argv, "AI:af:himnp:drstu")) != EOF)
168: switch((char)ch) {
169: case 'A':
170: Aflag++;
171: break;
172: case 'I': {
173: char *cp;
174:
175: iflag++;
176: for (cp = interface = optarg; isalpha(*cp); cp++);
177: unit = atoi(cp);
178: *cp = '\0';
179: break;
180: }
181: case 'a':
182: aflag++;
183: break;
184: case 'd':
185: dflag++;
186: break;
187: case 'f':
188: if (strcmp(optarg, "ns") == 0)
189: af = AF_NS;
190: else if (strcmp(optarg, "inet") == 0)
191: af = AF_INET;
192: else if (strcmp(optarg, "unix") == 0)
193: af = AF_UNIX;
194: else {
195: fprintf(stderr, "%s: unknown address family\n", optarg);
196: exit(10);
197: }
198: break;
199: case 'h':
200: hflag++;
201: break;
202: case 'i':
203: iflag++;
204: break;
205: case 'm':
206: mflag++;
207: break;
208: case 'n':
209: nflag++;
210: break;
211: case 'p':
212: if ((tp = name2protox(optarg)) == NULLPROTOX) {
213: fprintf(stderr, "%s: unknown or uninstrumented protocol\n", optarg);
214: exit(10);
215: }
216: pflag++;
217: break;
218: case 'r':
219: rflag++;
220: break;
221: case 's':
222: sflag++;
223: break;
224: case 't':
225: tflag++;
226: break;
227: case 'u':
228: af = AF_UNIX;
229: break;
230: case '?':
231: default:
232: usage();
233: }
234: argv += optind;
235: argc -= optind;
236:
237: if (argc > 0) {
238: if (isdigit(argv[0][0])) {
239: interval = atoi(argv[0]);
240: if (interval <= 0)
241: usage();
242: argv++, argc--;
243: iflag++;
244: }
245: if (argc > 0) {
246: system = *argv;
247: argv++, argc--;
248: if (argc > 0) {
249: kmemf = *argv;
250: kflag++;
251: }
252: }
253: }
254: if (nlist(system, nl) < 0 || nl[0].n_type == 0) {
255: fprintf(stderr, "%s: no namelist\n", system);
256: exit(1);
257: }
258: kmem = open(kmemf, O_RDONLY);
259: if (kmem < 0) {
260: perror(kmemf);
261: exit(1);
262: }
263: if (kflag) {
264: off_t off;
265:
266: Sysmap = (struct pte *)
267: malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
268: if (!Sysmap) {
269: fputs("netstat: can't get memory for Sysmap.\n", stderr);
270: exit(1);
271: }
272: off = nl[N_SYSMAP].n_value & ~KERNBASE;
273: (void)lseek(kmem, off, L_SET);
274: (void)read(kmem, (char *)Sysmap,
275: (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
276: }
277: if (mflag) {
278: mbpr((off_t)nl[N_MBSTAT].n_value);
279: exit(0);
280: }
281: if (pflag) {
282: if (tp->pr_stats)
283: (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
284: tp->pr_name);
285: else
286: printf("%s: no stats routine\n", tp->pr_name);
287: exit(0);
288: }
289: if (hflag) {
290: hostpr(nl[N_IMP].n_value, nl[N_NIMP].n_value);
291: exit(0);
292: }
293: /*
294: * Keep file descriptors open to avoid overhead
295: * of open/close on each call to get* routines.
296: */
297: sethostent(1);
298: setnetent(1);
299: if (iflag) {
300: intpr(interval, nl[N_IFNET].n_value);
301: exit(0);
302: }
303: if (rflag) {
304: if (sflag)
305: rt_stats((off_t)nl[N_RTSTAT].n_value);
306: else
307: routepr((off_t)nl[N_RTHOST].n_value,
308: (off_t)nl[N_RTNET].n_value,
309: (off_t)nl[N_RTHASHSIZE].n_value);
310: exit(0);
311: }
312: if (af == AF_INET || af == AF_UNSPEC) {
313: setprotoent(1);
314: setservent(1);
315: while (p = getprotoent()) {
316:
317: for (tp = protox; tp->pr_name; tp++)
318: if (strcmp(tp->pr_name, p->p_name) == 0)
319: break;
320: if (tp->pr_name == 0 || tp->pr_wanted == 0)
321: continue;
322: if (sflag) {
323: if (tp->pr_stats)
324: (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
325: p->p_name);
326: } else
327: if (tp->pr_cblocks)
328: (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
329: p->p_name);
330: }
331: endprotoent();
332: }
333: if (af == AF_NS || af == AF_UNSPEC) {
334: for (tp = nsprotox; tp->pr_name; tp++) {
335: if (sflag) {
336: if (tp->pr_stats)
337: (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
338: tp->pr_name);
339: } else
340: if (tp->pr_cblocks)
341: (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
342: tp->pr_name);
343: }
344: }
345: if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
346: unixpr((off_t)nl[N_NFILE].n_value, (off_t)nl[N_FILE].n_value,
347: (struct protosw *)nl[N_UNIXSW].n_value);
348: if (af == AF_UNSPEC && sflag)
349: impstats(nl[N_IMP].n_value, nl[N_NIMP].n_value);
350: exit(0);
351: }
352:
353: /*
354: * Seek into the kernel for a value.
355: */
356: off_t
357: klseek(fd, base, off)
358: int fd, off;
359: off_t base;
360: {
361: if (kflag) {
362: /* get kernel pte */
363: base &= ~KERNBASE;
364: base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
365: }
366: return (lseek(fd, base, off));
367: }
368:
369: char *
370: plural(n)
371: int n;
372: {
373:
374: return (n != 1 ? "s" : "");
375: }
376:
377: /*
378: * Find the protox for the given "well-known" name.
379: */
380: struct protox *
381: knownname(name)
382: char *name;
383: {
384: struct protox *tp;
385:
386: for (tp = protox; tp->pr_name; tp++)
387: if (strcmp(tp->pr_name, name) == 0)
388: return(tp);
389: for (tp = nsprotox; tp->pr_name; tp++)
390: if (strcmp(tp->pr_name, name) == 0)
391: return(tp);
392: return(NULLPROTOX);
393: }
394:
395: /*
396: * Find the protox corresponding to name.
397: */
398: struct protox *
399: name2protox(name)
400: char *name;
401: {
402: struct protox *tp;
403: char **alias; /* alias from p->aliases */
404: struct protoent *p;
405:
406: /*
407: * Try to find the name in the list of "well-known" names. If that
408: * fails, check if name is an alias for an Internet protocol.
409: */
410: if (tp = knownname(name))
411: return(tp);
412:
413: setprotoent(1); /* make protocol lookup cheaper */
414: while (p = getprotoent()) {
415: /* assert: name not same as p->name */
416: for (alias = p->p_aliases; *alias; alias++)
417: if (strcmp(name, *alias) == 0) {
418: endprotoent();
419: return(knownname(p->p_name));
420: }
421: }
422: endprotoent();
423: return(NULLPROTOX);
424: }
425:
426: usage()
427: {
428: 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);
429: exit(1);
430: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.