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