xref: /original-bsd/usr.bin/netstat/main.c (revision 92d3de31)
1 #ifndef lint
2 static char sccsid[] = "@(#)main.c	4.8 83/05/01";
3 #endif
4 
5 #include <sys/param.h>
6 #include <sys/vmmac.h>
7 #include <machine/pte.h>
8 #include <ctype.h>
9 #include <errno.h>
10 #include <netdb.h>
11 #include <nlist.h>
12 #include <stdio.h>
13 
14 struct nlist nl[] = {
15 #define	N_MBSTAT	0
16 	{ "_mbstat" },
17 #define	N_IPSTAT	1
18 	{ "_ipstat" },
19 #define	N_TCB		2
20 	{ "_tcb" },
21 #define	N_TCPSTAT	3
22 	{ "_tcpstat" },
23 #define	N_UDB		4
24 	{ "_udb" },
25 #define	N_UDPSTAT	5
26 	{ "_udpstat" },
27 #define	N_RAWCB		6
28 	{ "_rawcb" },
29 #define	N_SYSMAP	7
30 	{ "_Sysmap" },
31 #define	N_SYSSIZE	8
32 	{ "_Syssize" },
33 #define	N_IFNET		9
34 	{ "_ifnet" },
35 #define	N_HOSTS		10
36 	{ "_hosts" },
37 #define	N_RTHOST	11
38 	{ "_rthost" },
39 #define	N_RTNET		12
40 	{ "_rtnet" },
41 #define	N_ICMPSTAT	13
42 	{ "_icmpstat" },
43 	"",
44 };
45 
46 extern	int protopr();
47 extern	int tcp_stats(), udp_stats(), ip_stats(), icmp_stats();
48 
49 struct protox {
50 	u_char	pr_index;		/* index into nlist of cb head */
51 	u_char	pr_sindex;		/* index into nlist of stat block */
52 	u_char	pr_wanted;		/* 1 if wanted, 0 otherwise */
53 	int	(*pr_cblocks)();	/* control blocks printing routine */
54 	int	(*pr_stats)();		/* statistics printing routine */
55 	char	*pr_name;		/* well-known name */
56 } protox[] = {
57 	{ N_TCB,	N_TCPSTAT,	1,	protopr,
58 	  tcp_stats,	"tcp" },
59 	{ N_UDB,	N_UDPSTAT,	1,	protopr,
60 	  udp_stats,	"udp" },
61 	{ -1,		N_IPSTAT,	1,	0,
62 	  ip_stats,	"ip" },
63 	{ -1,		N_ICMPSTAT,	1,	0,
64 	  icmp_stats,	"icmp" },
65 	{ -1,		-1,		0,	0,
66 	  0,		0 }
67 };
68 
69 struct	pte *Sysmap;
70 
71 char	*system = "/vmunix";
72 char	*kmemf = "/dev/kmem";
73 int	kmem;
74 int	kflag;
75 int	Aflag;
76 int	aflag;
77 int	hflag;
78 int	iflag;
79 int	mflag;
80 int	nflag;
81 int	rflag;
82 int	sflag;
83 int	tflag;
84 int	interval;
85 char	usage[] = "[ -Aaihmnrst ] [ interval ] [ system ] [ core ]";
86 
87 main(argc, argv)
88 	int argc;
89 	char *argv[];
90 {
91 	int i;
92 	char *cp, *name;
93 	register struct protoent *p;
94 
95 	name = argv[0];
96 	argc--, argv++;
97   	while (argc > 0 && **argv == '-') {
98 		for (cp = &argv[0][1]; *cp; cp++)
99 		switch(argv[0][1]) {
100 
101 		case 'A':
102 			Aflag++;
103 			break;
104 
105 		case 'a':
106 			aflag++;
107 			break;
108 
109 		case 'h':
110 			hflag++;
111 			break;
112 
113 		case 'i':
114 			iflag++;
115 			break;
116 
117 		case 'm':
118 			mflag++;
119 			break;
120 
121 		case 'n':
122 			nflag++;
123 			break;
124 
125 		case 'r':
126 			rflag++;
127 			break;
128 
129 		case 's':
130 			sflag++;
131 			break;
132 
133 		case 't':
134 			tflag++;
135 			break;
136 
137 		default:
138 use:
139 			printf("usage: %s %s\n", name, usage);
140 			exit(1);
141 		}
142 		argv++, argc--;
143 	}
144 	if (argc > 0 && isdigit(argv[0][0])) {
145 		interval = atoi(argv[0]);
146 		if (interval <= 0)
147 			goto use;
148 		argv++, argc--;
149 		iflag++;
150 	}
151 	if (argc > 0) {
152 		system = *argv;
153 		argv++, argc--;
154 	}
155 	nlist(system, nl);
156 	if (nl[0].n_type == 0) {
157 		fprintf(stderr, "%s: no namelist\n", system);
158 		exit(1);
159 	}
160 	if (argc > 0) {
161 		kmemf = *argv;
162 		kflag++;
163 	}
164 	kmem = open(kmemf, 0);
165 	if (kmem < 0) {
166 		fprintf(stderr, "cannot open ");
167 		perror(kmemf);
168 		exit(1);
169 	}
170 	if (kflag) {
171 		off_t off;
172 
173 		off = nl[N_SYSMAP].n_value & 0x7fffffff;
174 		lseek(kmem, off, 0);
175 		nl[N_SYSSIZE].n_value *= 4;
176 		Sysmap = (struct pte *)malloc(nl[N_SYSSIZE].n_value);
177 		if (Sysmap == 0) {
178 			perror("Sysmap");
179 			exit(1);
180 		}
181 		read(kmem, Sysmap, nl[N_SYSSIZE].n_value);
182 	}
183 	if (mflag) {
184 		mbpr(nl[N_MBSTAT].n_value);
185 		exit(0);
186 	}
187 	/*
188 	 * Keep file descriptors open to avoid overhead
189 	 * of open/close on each call to get* routines.
190 	 */
191 	sethostent(1);
192 	setnetent(1);
193 	if (iflag) {
194 		intpr(interval, nl[N_IFNET].n_value);
195 		exit(0);
196 	}
197 	if (hflag) {
198 		hostpr(nl[N_HOSTS].n_value);
199 		exit(0);
200 	}
201 	if (rflag) {
202 		routepr(nl[N_RTHOST].n_value, nl[N_RTNET].n_value);
203 		exit(0);
204 	}
205 	setprotoent(1);
206 	setservent(1);
207 	while (p = getprotoent()) {
208 		register struct protox *tp;
209 
210 		for (tp = protox; tp->pr_name; tp++)
211 			if (strcmp(tp->pr_name, p->p_name) == 0)
212 				break;
213 		if (tp->pr_name == 0 || tp->pr_wanted == 0)
214 			continue;
215 		if (sflag && tp->pr_stats) {
216 			(*tp->pr_stats)(nl[tp->pr_sindex].n_value, p->p_name);
217 			continue;
218 		}
219 		if (tp->pr_cblocks)
220 			(*tp->pr_cblocks)(nl[tp->pr_index].n_value, p->p_name);
221 	}
222 	endprotoent();
223 }
224 
225 /*
226  * Seek into the kernel for a value.
227  */
228 klseek(fd, base, off)
229 	int fd, base, off;
230 {
231 
232 	if (kflag) {
233 		/* get kernel pte */
234 #ifdef vax
235 		base &= 0x7fffffff;
236 #endif
237 		base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
238 	}
239 	lseek(fd, base, off);
240 }
241