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, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 char copyright[] =
36 "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
37 All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 /* static char sccsid[] = "@(#)main.c 5.23 (Berkeley) 7/1/91"; */
42 static char sccsid[] = "$Id: main.c,v 1.2 93/03/15 19:27:39 bill Exp $";
43 #endif /* not lint */
44
45 #include <sys/param.h>
46 #include <sys/socket.h>
47 #include <sys/file.h>
48 #include <errno.h>
49 #include <netdb.h>
50 #include <nlist.h>
51 #include <kvm.h>
52 #include <stdio.h>
53 #include <ctype.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <paths.h>
57
58 struct nlist nl[] = {
59 #define N_MBSTAT 0
60 { "_mbstat" },
61 #define N_IPSTAT 1
62 { "_ipstat" },
63 #define N_TCB 2
64 { "_tcb" },
65 #define N_TCPSTAT 3
66 { "_tcpstat" },
67 #define N_UDB 4
68 { "_udb" },
69 #define N_UDPSTAT 5
70 { "_udpstat" },
71 #define N_IFNET 6
72 { "_ifnet" },
73 #define N_IMP 7
74 { "_imp_softc" },
75 #define N_RTHOST 8
76 { "_rthost" },
77 #define N_RTNET 9
78 { "_rtnet" },
79 #define N_ICMPSTAT 10
80 { "_icmpstat" },
81 #define N_RTSTAT 11
82 { "_rtstat" },
83 #define N_FILEHEAD 12
84 { "_filehead" },
85 #define N_UNIXSW 13
86 { "_unixsw" },
87 #define N_RTHASHSIZE 14
88 { "_rthashsize" },
89 #define N_IDP 15
90 { "_nspcb"},
91 #define N_IDPSTAT 16
92 { "_idpstat"},
93 #define N_SPPSTAT 17
94 { "_spp_istat"},
95 #define N_NSERR 18
96 { "_ns_errstat"},
97 #define N_CLNPSTAT 19
98 { "_clnp_stat"},
99 #define IN_TP 20
100 { "_tp_inpcb" },
101 #define ISO_TP 21
102 { "_tp_isopcb" },
103 #define N_TPSTAT 22
104 { "_tp_stat" },
105 #define N_ESISSTAT 23
106 { "_esis_stat"},
107 #define N_NIMP 24
108 { "_nimp"},
109 #define N_RTREE 25
110 { "_radix_node_head"},
111 #define N_CLTP 26
112 { "_cltb"},
113 #define N_CLTPSTAT 27
114 { "_cltpstat"},
115 "",
116 };
117
118 /* internet protocols */
119 extern int protopr();
120 extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats();
121 #ifdef notdef
122 /* ns protocols */
123 extern int nsprotopr();
124 extern int spp_stats(), idp_stats(), nserr_stats();
125 /* iso protocols */
126 extern int iso_protopr();
127 extern int tp_stats(), esis_stats(), clnp_stats(), cltp_stats();
128 #endif
129
130 struct protox {
131 u_char pr_index; /* index into nlist of cb head */
132 u_char pr_sindex; /* index into nlist of stat block */
133 u_char pr_wanted; /* 1 if wanted, 0 otherwise */
134 int (*pr_cblocks)(); /* control blocks printing routine */
135 int (*pr_stats)(); /* statistics printing routine */
136 char *pr_name; /* well-known name */
137 } protox[] = {
138 { N_TCB, N_TCPSTAT, 1, protopr,
139 tcp_stats, "tcp" },
140 { N_UDB, N_UDPSTAT, 1, protopr,
141 udp_stats, "udp" },
142 #ifdef notdef
143 { IN_TP, N_TPSTAT, 1, protopr,
144 tp_stats, "tpip" },
145 #endif
146 { -1, N_IPSTAT, 1, 0,
147 ip_stats, "ip" },
148 { -1, N_ICMPSTAT, 1, 0,
149 icmp_stats, "icmp" },
150 { -1, -1, 0, 0,
151 0, 0 }
152 };
153
154 #ifdef notdef
155 struct protox nsprotox[] = {
156 { N_IDP, N_IDPSTAT, 1, nsprotopr,
157 idp_stats, "idp" },
158 { N_IDP, N_SPPSTAT, 1, nsprotopr,
159 spp_stats, "spp" },
160 { -1, N_NSERR, 1, 0,
161 nserr_stats, "ns_err" },
162 { -1, -1, 0, 0,
163 0, 0 }
164 };
165
166 struct protox isoprotox[] = {
167 { ISO_TP, N_TPSTAT, 1, iso_protopr,
168 tp_stats, "tp" },
169 { N_CLTP, N_CLTPSTAT, 1, iso_protopr,
170 cltp_stats, "cltp" },
171 { -1, N_CLNPSTAT, 1, 0,
172 clnp_stats, "clnp"},
173 { -1, N_ESISSTAT, 1, 0,
174 esis_stats, "esis"},
175 { -1, -1, 0, 0,
176 0, 0 }
177 };
178
179 struct protox *protoprotox[] = { protox, nsprotox, isoprotox, NULL };
180 #else
181 struct protox *protoprotox[] = { protox, NULL };
182 #endif
183
184 char *vmunix = _PATH_UNIX;
185 char *kmemf;
186 int kmem;
187 int kflag;
188 int Aflag;
189 int aflag;
190 int hflag;
191 int iflag;
192 int mflag;
193 int nflag;
194 int pflag;
195 int rflag;
196 int sflag;
197 int tflag;
198 int dflag;
199 int interval;
200 char *interface;
201 int unit;
202
203 int af = AF_UNSPEC;
204
main(argc,argv)205 main(argc, argv)
206 int argc;
207 char **argv;
208 {
209 extern char *optarg;
210 extern int optind;
211 register struct protoent *p;
212 register struct protox *tp; /* for printing cblocks & stats */
213 struct protox *name2protox(); /* for -p */
214 int ch;
215 void usage();
216
217 while ((ch = getopt(argc, argv, "Aadf:hI:iM:mN:np:rstuw")) != EOF)
218 switch((char)ch) {
219 case 'A':
220 Aflag = 1;
221 break;
222 case 'a':
223 aflag = 1;
224 break;
225 case 'd':
226 dflag = 1;
227 break;
228 case 'f':
229 if (strcmp(optarg, "ns") == 0)
230 af = AF_NS;
231 else if (strcmp(optarg, "inet") == 0)
232 af = AF_INET;
233 else if (strcmp(optarg, "unix") == 0)
234 af = AF_UNIX;
235 else if (strcmp(optarg, "iso") == 0)
236 af = AF_ISO;
237 else {
238 (void)fprintf(stderr,
239 "%s: unknown address family\n", optarg);
240 exit(1);
241 }
242 break;
243 case 'h':
244 hflag = 1;
245 break;
246 case 'I': {
247 char *cp;
248
249 iflag = 1;
250 for (cp = interface = optarg; isalpha(*cp); cp++);
251 unit = atoi(cp);
252 *cp = '\0';
253 break;
254 }
255 case 'i':
256 iflag = 1;
257 break;
258 case 'M':
259 kmemf = optarg;
260 kflag = 1;
261 break;
262 case 'm':
263 mflag = 1;
264 break;
265 case 'N':
266 vmunix = optarg;
267 break;
268 case 'n':
269 nflag = 1;
270 break;
271 case 'p':
272 if ((tp = name2protox(optarg)) == NULL) {
273 (void)fprintf(stderr,
274 "%s: unknown or uninstrumented protocol\n",
275 optarg);
276 exit(1);
277 }
278 pflag = 1;
279 break;
280 case 'r':
281 rflag = 1;
282 break;
283 case 's':
284 sflag = 1;
285 break;
286 case 't':
287 tflag = 1;
288 break;
289 case 'u':
290 af = AF_UNIX;
291 break;
292 case 'w':
293 interval = atoi(optarg);
294 break;
295 case '?':
296 default:
297 usage();
298 }
299 argv += optind;
300 argc -= optind;
301
302 #define BACKWARD_COMPATIBILITY
303 #ifdef BACKWARD_COMPATIBILITY
304 if (*argv) {
305 if (isdigit(**argv)) {
306 interval = atoi(*argv);
307 if (interval <= 0)
308 usage();
309 ++argv;
310 iflag = 1;
311 }
312 if (*argv) {
313 vmunix = *argv;
314 if (*++argv) {
315 kmemf = *argv;
316 kflag = 1;
317 }
318 }
319 }
320 #endif
321 if (kvm_openfiles(vmunix, kmemf, NULL) == -1) {
322 fprintf(stderr, "netstat: kvm_openfiles: %s\n", kvm_geterr());
323 exit(1);
324 }
325 if (kvm_nlist(nl) < 0 || nl[0].n_type == 0) {
326 fprintf(stderr, "%s: no namelist\n", vmunix);
327 exit(1);
328 }
329 if (mflag) {
330 mbpr((off_t)nl[N_MBSTAT].n_value);
331 exit(0);
332 }
333 if (pflag) {
334 if (tp->pr_stats)
335 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
336 tp->pr_name);
337 else
338 printf("%s: no stats routine\n", tp->pr_name);
339 exit(0);
340 }
341 /*
342 * Keep file descriptors open to avoid overhead
343 * of open/close on each call to get* routines.
344 */
345 sethostent(1);
346 setnetent(1);
347 if (iflag) {
348 intpr(interval, nl[N_IFNET].n_value);
349 exit(0);
350 }
351 if (rflag) {
352 if (sflag)
353 rt_stats((off_t)nl[N_RTSTAT].n_value);
354 else
355 routepr((off_t)nl[N_RTHOST].n_value,
356 (off_t)nl[N_RTNET].n_value,
357 (off_t)nl[N_RTHASHSIZE].n_value,
358 (off_t)nl[N_RTREE].n_value);
359 exit(0);
360 }
361 if (af == AF_INET || af == AF_UNSPEC) {
362 setprotoent(1);
363 setservent(1);
364 while (p = getprotoent()) {
365
366 for (tp = protox; tp->pr_name; tp++)
367 if (strcmp(tp->pr_name, p->p_name) == 0)
368 break;
369 if (tp->pr_name == 0 || tp->pr_wanted == 0)
370 continue;
371 if (sflag) {
372 if (tp->pr_stats)
373 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
374 p->p_name);
375 } else
376 if (tp->pr_cblocks)
377 (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
378 p->p_name);
379 }
380 endprotoent();
381 }
382 #ifdef notdef
383 if (af == AF_NS || af == AF_UNSPEC) {
384 for (tp = nsprotox; tp->pr_name; tp++) {
385 if (sflag) {
386 if (tp->pr_stats)
387 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
388 tp->pr_name);
389 } else
390 if (tp->pr_cblocks)
391 (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
392 tp->pr_name);
393 }
394 }
395 if (af == AF_ISO || af == AF_UNSPEC) {
396 for (tp = isoprotox; tp->pr_name; tp++) {
397 if (sflag) {
398 if (tp->pr_stats)
399 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
400 tp->pr_name);
401 } else
402 if (tp->pr_cblocks)
403 (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
404 tp->pr_name);
405 }
406 }
407 #endif
408 if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
409 unixpr((off_t)nl[N_FILEHEAD].n_value,
410 (struct protosw *)nl[N_UNIXSW].n_value);
411 exit(0);
412 }
413
414 char *
plural(n)415 plural(n)
416 int n;
417 {
418 return (n != 1 ? "s" : "");
419 }
420
421 /*
422 * Find the protox for the given "well-known" name.
423 */
424 struct protox *
knownname(name)425 knownname(name)
426 char *name;
427 {
428 struct protox **tpp, *tp;
429
430 for (tpp = protoprotox; *tpp; tpp++)
431 for (tp = *tpp; tp->pr_name; tp++)
432 if (strcmp(tp->pr_name, name) == 0)
433 return(tp);
434 return(NULL);
435 }
436
437 /*
438 * Find the protox corresponding to name.
439 */
440 struct protox *
name2protox(name)441 name2protox(name)
442 char *name;
443 {
444 struct protox *tp;
445 char **alias; /* alias from p->aliases */
446 struct protoent *p;
447
448 /*
449 * Try to find the name in the list of "well-known" names. If that
450 * fails, check if name is an alias for an Internet protocol.
451 */
452 if (tp = knownname(name))
453 return(tp);
454
455 setprotoent(1); /* make protocol lookup cheaper */
456 while (p = getprotoent()) {
457 /* assert: name not same as p->name */
458 for (alias = p->p_aliases; *alias; alias++)
459 if (strcmp(name, *alias) == 0) {
460 endprotoent();
461 return(knownname(p->p_name));
462 }
463 }
464 endprotoent();
465 return(NULL);
466 }
467
468 void
usage()469 usage()
470 {
471 (void)fprintf(stderr,
472 "usage: netstat [-Aan] [-f address_family] [-M core] [-N system]\n");
473 (void)fprintf(stderr,
474 " [-himnrs] [-f address_family] [-M core] [-N system]\n");
475 (void)fprintf(stderr,
476 " [-n] [-I interface] [-M core] [-N system] [-w wait]\n");
477 (void)fprintf(stderr,
478 " [-M core] [-N system] [-p protocol]\n");
479 exit(1);
480 }
481