not every value return in an nlist structure was being
[unix-history] / usr / src / usr.bin / netstat / main.c
CommitLineData
5ff67f98 1/*
b36fc510 2 * Copyright (c) 1983, 1988 Regents of the University of California.
ee3f90a5
MK
3 * All rights reserved.
4 *
87198c0c 5 * %sccs.include.redist.c%
5ff67f98
DF
6 */
7
8#ifndef lint
9char copyright[] =
b36fc510 10"@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
5ff67f98 11 All rights reserved.\n";
d2c7d54c 12#endif /* not lint */
5ff67f98 13
ed85a06f 14#ifndef lint
d1cfb820 15static char sccsid[] = "@(#)main.c 5.30 (Berkeley) %G%";
d2c7d54c 16#endif /* not lint */
ed85a06f
SL
17
18#include <sys/param.h>
27788811 19#include <sys/file.h>
6e549c8f 20#include <sys/protosw.h>
0be88646 21#include <sys/socket.h>
27788811
KS
22
23#include <netinet/in.h>
24
25#include <ctype.h>
ed85a06f 26#include <errno.h>
c4f5a622 27#include <kvm.h>
6e549c8f 28#include <limits.h>
27788811
KS
29#include <netdb.h>
30#include <nlist.h>
31#include <paths.h>
ed85a06f 32#include <stdio.h>
c4f5a622
KB
33#include <stdlib.h>
34#include <string.h>
27788811 35#include <unistd.h>
6e549c8f 36#include "netstat.h"
ed85a06f
SL
37
38struct nlist nl[] = {
39#define N_MBSTAT 0
40 { "_mbstat" },
41#define N_IPSTAT 1
42 { "_ipstat" },
43#define N_TCB 2
44 { "_tcb" },
45#define N_TCPSTAT 3
46 { "_tcpstat" },
47#define N_UDB 4
48 { "_udb" },
49#define N_UDPSTAT 5
50 { "_udpstat" },
c4f5a622 51#define N_IFNET 6
ed85a06f 52 { "_ifnet" },
c4f5a622 53#define N_IMP 7
0e710523 54 { "_imp_softc" },
b81b1333 55#define N_ICMPSTAT 8
7333c75b 56 { "_icmpstat" },
b81b1333 57#define N_RTSTAT 9
bbd2d21e 58 { "_rtstat" },
b81b1333 59#define N_UNIXSW 10
404a567d 60 { "_unixsw" },
b81b1333 61#define N_IDP 11
0be88646 62 { "_nspcb"},
b81b1333 63#define N_IDPSTAT 12
0be88646 64 { "_idpstat"},
b81b1333 65#define N_SPPSTAT 13
0be88646 66 { "_spp_istat"},
b81b1333 67#define N_NSERR 14
0be88646 68 { "_ns_errstat"},
b81b1333 69#define N_CLNPSTAT 15
5262655f 70 { "_clnp_stat"},
fb9a22c1 71#define IN_NOTUSED 16
5262655f 72 { "_tp_inpcb" },
b81b1333 73#define ISO_TP 17
fb9a22c1 74 { "_tp_refinfo" },
b81b1333 75#define N_TPSTAT 18
5262655f 76 { "_tp_stat" },
b81b1333 77#define N_ESISSTAT 19
5262655f 78 { "_esis_stat"},
b81b1333 79#define N_NIMP 20
0e710523 80 { "_nimp"},
b81b1333 81#define N_RTREE 21
4e64fa9b 82 { "_rt_tables"},
b81b1333 83#define N_CLTP 22
0fa5c909 84 { "_cltb"},
b81b1333 85#define N_CLTPSTAT 23
0fa5c909 86 { "_cltpstat"},
27788811
KS
87#define N_NFILE 24
88 { "_nfile" },
89#define N_FILE 25
90 { "_file" },
91#define N_IGMPSTAT 26
92 { "_igmpstat" },
93#define N_MRTPROTO 27
94 { "_ip_mrtproto" },
95#define N_MRTSTAT 28
96 { "_mrtstat" },
97#define N_MRTTABLE 29
98 { "_mrttable" },
99#define N_VIFTABLE 30
100 { "_viftable" },
0fa5c909 101
a5545777
MK
102 /* BBN Internet protocol implementation */
103#define N_TCP 23
104 { "_tcp" },
105#define N_UDP 24
106 { "_udp" },
107#define N_RDP 25
108 { "_rdp" },
109#define N_RDPSTAT 26
110 { "_rdpstat" },
111
7333c75b 112 "",
ed85a06f
SL
113};
114
115struct protox {
6df0a927
SL
116 u_char pr_index; /* index into nlist of cb head */
117 u_char pr_sindex; /* index into nlist of stat block */
118 u_char pr_wanted; /* 1 if wanted, 0 otherwise */
6e549c8f
KS
119 void (*pr_cblocks)(); /* control blocks printing routine */
120 void (*pr_stats)(); /* statistics printing routine */
6df0a927 121 char *pr_name; /* well-known name */
a5545777
MK
122};
123
124struct protox berkprotox[] = {
6df0a927
SL
125 { N_TCB, N_TCPSTAT, 1, protopr,
126 tcp_stats, "tcp" },
127 { N_UDB, N_UDPSTAT, 1, protopr,
128 udp_stats, "udp" },
129 { -1, N_IPSTAT, 1, 0,
130 ip_stats, "ip" },
7333c75b
SL
131 { -1, N_ICMPSTAT, 1, 0,
132 icmp_stats, "icmp" },
6df0a927
SL
133 { -1, -1, 0, 0,
134 0, 0 }
ed85a06f
SL
135};
136
a5545777
MK
137struct protox bbnprotox[] = {
138 { N_TCP, N_TCPSTAT, 1, bbnprotopr,
139 tcpstats, "tcp" },
140 { N_UDP, N_UDPSTAT, 1, bbnprotopr,
141 udpstats, "udp" },
142 { N_RDP, N_RDPSTAT, 1, bbnprotopr,
143 rdpstats, "rdp" },
144 { N_RAWCB, 0, 1, bbnprotopr,
145 0, "raw" },
146 { -1, N_IPSTAT, 1, 0,
147 ipstats, "ip" },
148 { -1, N_ICMPSTAT, 1, 0,
149 icmpstats, "icmp" },
150 { -1, -1, 0, 0,
151 0, 0 }
152};
153
0be88646
KS
154struct protox nsprotox[] = {
155 { N_IDP, N_IDPSTAT, 1, nsprotopr,
156 idp_stats, "idp" },
157 { N_IDP, N_SPPSTAT, 1, nsprotopr,
158 spp_stats, "spp" },
159 { -1, N_NSERR, 1, 0,
160 nserr_stats, "ns_err" },
161 { -1, -1, 0, 0,
162 0, 0 }
163};
164
5262655f
KS
165struct protox isoprotox[] = {
166 { ISO_TP, N_TPSTAT, 1, iso_protopr,
167 tp_stats, "tp" },
0fa5c909
KS
168 { N_CLTP, N_CLTPSTAT, 1, iso_protopr,
169 cltp_stats, "cltp" },
5262655f
KS
170 { -1, N_CLNPSTAT, 1, 0,
171 clnp_stats, "clnp"},
172 { -1, N_ESISSTAT, 1, 0,
173 esis_stats, "esis"},
174 { -1, -1, 0, 0,
175 0, 0 }
176};
177
c4f5a622 178struct protox *protoprotox[] = { protox, nsprotox, isoprotox, NULL };
ed85a06f 179
6e549c8f
KS
180static void printproto __P((struct protox *, char *));
181static void usage __P(());
182static struct protox *name2protox __P((char *));
183static struct protox *knownname __P((char *));
184
185kvm_t *kvmd;
2a893f10 186
6e549c8f 187int
ed85a06f
SL
188main(argc, argv)
189 int argc;
c4f5a622 190 char **argv;
ed85a06f 191{
d2c7d54c
KB
192 extern char *optarg;
193 extern int optind;
ed85a06f 194 register struct protoent *p;
6538ea31 195 register struct protox *tp; /* for printing cblocks & stats */
6e549c8f 196 register char *cp;
d2c7d54c 197 int ch;
6e549c8f
KS
198 char *nlistf = NULL, *memf = NULL;
199 char buf[_POSIX2_LINE_MAX];
200
201 if (cp = rindex(argv[0], '/'))
202 prog = cp + 1;
203 else
204 prog = argv[0];
205 af = AF_UNSPEC;
ed85a06f 206
27788811 207 while ((ch = getopt(argc, argv, "AaBdf:hI:iM:mN:np:rstuw")) != EOF)
d2c7d54c 208 switch((char)ch) {
ed85a06f 209 case 'A':
c4f5a622 210 Aflag = 1;
d2c7d54c 211 break;
ed85a06f 212 case 'a':
c4f5a622 213 aflag = 1;
ed85a06f 214 break;
27788811
KS
215 case 'B':
216 Bflag = 1;
217 break;
2ebaad6c 218 case 'd':
c4f5a622 219 dflag = 1;
2ebaad6c 220 break;
d2c7d54c
KB
221 case 'f':
222 if (strcmp(optarg, "ns") == 0)
223 af = AF_NS;
224 else if (strcmp(optarg, "inet") == 0)
225 af = AF_INET;
226 else if (strcmp(optarg, "unix") == 0)
227 af = AF_UNIX;
5262655f
KS
228 else if (strcmp(optarg, "iso") == 0)
229 af = AF_ISO;
d2c7d54c 230 else {
c4f5a622 231 (void)fprintf(stderr,
6e549c8f
KS
232 "%s: %s: unknown address family\n",
233 prog, optarg);
c4f5a622 234 exit(1);
d2c7d54c
KB
235 }
236 break;
ed85a06f 237 case 'h':
c4f5a622 238 hflag = 1;
ed85a06f 239 break;
c4f5a622
KB
240 case 'I': {
241 char *cp;
242
243 iflag = 1;
6e549c8f
KS
244 for (cp = interface = optarg; isalpha(*cp); cp++)
245 continue;
c4f5a622
KB
246 unit = atoi(cp);
247 *cp = '\0';
248 break;
249 }
ed85a06f 250 case 'i':
c4f5a622
KB
251 iflag = 1;
252 break;
253 case 'M':
3e18af20 254 memf = optarg;
ed85a06f 255 break;
ed85a06f 256 case 'm':
c4f5a622
KB
257 mflag = 1;
258 break;
259 case 'N':
3e18af20 260 nlistf = optarg;
ed85a06f 261 break;
ed85a06f 262 case 'n':
c4f5a622 263 nflag = 1;
ed85a06f 264 break;
d2c7d54c 265 case 'p':
c4f5a622
KB
266 if ((tp = name2protox(optarg)) == NULL) {
267 (void)fprintf(stderr,
6e549c8f
KS
268 "%s: %s: unknown or uninstrumented protocol\n",
269 prog, optarg);
c4f5a622 270 exit(1);
d2c7d54c 271 }
c4f5a622 272 pflag = 1;
d2c7d54c 273 break;
ed85a06f 274 case 'r':
c4f5a622 275 rflag = 1;
ed85a06f 276 break;
ed85a06f 277 case 's':
6e549c8f 278 ++sflag;
ed85a06f 279 break;
ed85a06f 280 case 't':
c4f5a622 281 tflag = 1;
ed85a06f 282 break;
404a567d 283 case 'u':
2a893f10 284 af = AF_UNIX;
404a567d 285 break;
c4f5a622
KB
286 case 'w':
287 interval = atoi(optarg);
288 break;
d2c7d54c
KB
289 case '?':
290 default:
291 usage();
292 }
293 argv += optind;
294 argc -= optind;
404a567d 295
c4f5a622
KB
296#define BACKWARD_COMPATIBILITY
297#ifdef BACKWARD_COMPATIBILITY
298 if (*argv) {
299 if (isdigit(**argv)) {
300 interval = atoi(*argv);
d2c7d54c
KB
301 if (interval <= 0)
302 usage();
c4f5a622
KB
303 ++argv;
304 iflag = 1;
d2c7d54c 305 }
c4f5a622 306 if (*argv) {
3e18af20 307 nlistf = *argv;
6e549c8f 308 if (*++argv)
3e18af20 309 memf = *argv;
ed85a06f 310 }
ed85a06f 311 }
c4f5a622 312#endif
6e549c8f 313
3e18af20
KB
314 /*
315 * Discard setgid privileges if not the running kernel so that bad
316 * guys can't print interesting stuff from kernel memory.
317 */
318 if (nlistf != NULL || memf != NULL)
319 setgid(getgid());
320
6e549c8f
KS
321 if ((kvmd = kvm_open(nlistf, memf, NULL, O_RDONLY, prog)) == NULL) {
322 fprintf(stderr, "%s: kvm_open: %s\n", prog, buf);
ed85a06f
SL
323 exit(1);
324 }
6e549c8f
KS
325 if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) {
326 if (nlistf)
327 fprintf(stderr, "%s: %s: no namelist\n", prog, nlistf);
328 else
329 fprintf(stderr, "%s: no namelist\n", prog);
ed85a06f
SL
330 exit(1);
331 }
ed85a06f 332 if (mflag) {
d1cfb820 333 mbpr(nl[N_MBSTAT].n_value);
6538ea31
MK
334 exit(0);
335 }
336 if (pflag) {
337 if (tp->pr_stats)
d2c7d54c 338 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
6538ea31
MK
339 tp->pr_name);
340 else
341 printf("%s: no stats routine\n", tp->pr_name);
ed85a06f
SL
342 exit(0);
343 }
0e710523
MK
344 if (hflag) {
345 hostpr(nl[N_IMP].n_value, nl[N_NIMP].n_value);
346 exit(0);
347 }
ed85a06f
SL
348 /*
349 * Keep file descriptors open to avoid overhead
350 * of open/close on each call to get* routines.
351 */
ed85a06f
SL
352 sethostent(1);
353 setnetent(1);
90cb8200
SL
354 if (iflag) {
355 intpr(interval, nl[N_IFNET].n_value);
356 exit(0);
357 }
ed85a06f 358 if (rflag) {
bbd2d21e 359 if (sflag)
d1cfb820 360 rt_stats(nl[N_RTSTAT].n_value);
bbd2d21e 361 else
d1cfb820 362 routepr(nl[N_RTREE].n_value);
ed85a06f
SL
363 exit(0);
364 }
27788811
KS
365 if (Bflag) {
366 if (sflag)
d1cfb820
KS
367 mrt_stats(nl[N_MRTPROTO].n_value,
368 nl[N_MRTSTAT].n_value);
27788811 369 else
d1cfb820
KS
370 mroutepr(nl[N_MRTPROTO].n_value,
371 nl[N_MRTTABLE].n_value,
372 nl[N_VIFTABLE].n_value);
27788811
KS
373 exit(0);
374 }
ed85a06f 375
a5545777
MK
376
377 if (sflag) {
378 if (tp->pr_stats)
379 (*tp->pr_stats)(nl[tp->pr_sindex].n_value, tp->pr_name);
380 } else if (tp->pr_cblocks)
381 (*tp->pr_cblocks)(nl[tp->pr_index].n_value, tp->pr_name);
ed85a06f 382 }
6e549c8f
KS
383 if (pr != NULL && (off || af != AF_UNSPEC))
384 (*pr)(off, name);
385}
386
387/*
388 * Read kernel memory, return 0 on success.
389 */
390int
391kread(addr, buf, size)
d1cfb820 392 u_long addr;
6e549c8f
KS
393 char *buf;
394 int size;
395{
396
397 if (kvm_read(kvmd, addr, buf, size) != size) {
398 /* XXX this duplicates kvm_read's error printout */
399 (void)fprintf(stderr, "%s: kvm_read %s\n", prog,
400 kvm_geterr(kvmd));
401 return (-1);
5262655f 402 }
6e549c8f 403 return (0);
ed85a06f
SL
404}
405
bbd2d21e
SL
406char *
407plural(n)
408 int n;
409{
bbd2d21e
SL
410 return (n != 1 ? "s" : "");
411}
6538ea31 412
27788811
KS
413char *
414plurales(n)
415 int n;
416{
417 return (n != 1 ? "es" : "");
418}
419
6538ea31
MK
420/*
421 * Find the protox for the given "well-known" name.
422 */
6e549c8f 423static struct protox *
6538ea31
MK
424knownname(name)
425 char *name;
426{
5262655f 427 struct protox **tpp, *tp;
d2c7d54c 428
5262655f 429 for (tpp = protoprotox; *tpp; tpp++)
6e549c8f
KS
430 for (tp = *tpp; tp->pr_name; tp++)
431 if (strcmp(tp->pr_name, name) == 0)
432 return (tp);
433 return (NULL);
6538ea31
MK
434}
435
436/*
437 * Find the protox corresponding to name.
438 */
6e549c8f 439static struct protox *
6538ea31
MK
440name2protox(name)
441 char *name;
442{
443 struct protox *tp;
444 char **alias; /* alias from p->aliases */
445 struct protoent *p;
d2c7d54c 446
6538ea31
MK
447 /*
448 * Try to find the name in the list of "well-known" names. If that
449 * fails, check if name is an alias for an Internet protocol.
450 */
451 if (tp = knownname(name))
6e549c8f 452 return (tp);
d2c7d54c 453
6538ea31
MK
454 setprotoent(1); /* make protocol lookup cheaper */
455 while (p = getprotoent()) {
456 /* assert: name not same as p->name */
457 for (alias = p->p_aliases; *alias; alias++)
458 if (strcmp(name, *alias) == 0) {
459 endprotoent();
6e549c8f 460 return (knownname(p->p_name));
6538ea31
MK
461 }
462 }
463 endprotoent();
6e549c8f 464 return (NULL);
6538ea31 465}
d2c7d54c 466
6e549c8f 467static void
d2c7d54c
KB
468usage()
469{
c4f5a622 470 (void)fprintf(stderr,
6e549c8f 471"usage: %s [-Aan] [-f address_family] [-M core] [-N system]\n", prog);
c4f5a622
KB
472 (void)fprintf(stderr,
473" [-himnrs] [-f address_family] [-M core] [-N system]\n");
474 (void)fprintf(stderr,
475" [-n] [-I interface] [-M core] [-N system] [-w wait]\n");
476 (void)fprintf(stderr,
477" [-M core] [-N system] [-p protocol]\n");
d2c7d54c
KB
478 exit(1);
479}