/*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved. The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * Copyright (c) 1983, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
*/
#ifndef lint
char copyright[] =
-"@(#) Copyright (c) 1983 Regents of the University of California.\n\
+"@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
All rights reserved.\n";
-#endif not lint
+#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)main.c 5.2 (Berkeley) %G%";
-#endif not lint
+static char sccsid[] = "@(#)main.c 5.30 (Berkeley) %G%";
+#endif /* not lint */
#include <sys/param.h>
-#include <sys/vmmac.h>
-#include <machine/pte.h>
+#include <sys/file.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
#include <ctype.h>
#include <errno.h>
+#include <kvm.h>
+#include <limits.h>
#include <netdb.h>
#include <nlist.h>
+#include <paths.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
struct nlist nl[] = {
#define N_MBSTAT 0
{ "_udb" },
#define N_UDPSTAT 5
{ "_udpstat" },
-#define N_RAWCB 6
- { "_rawcb" },
-#define N_SYSMAP 7
- { "_Sysmap" },
-#define N_SYSSIZE 8
- { "_Syssize" },
-#define N_IFNET 9
+#define N_IFNET 6
{ "_ifnet" },
-#define N_HOSTS 10
- { "_hosts" },
-#define N_RTHOST 11
- { "_rthost" },
-#define N_RTNET 12
- { "_rtnet" },
-#define N_ICMPSTAT 13
+#define N_IMP 7
+ { "_imp_softc" },
+#define N_ICMPSTAT 8
{ "_icmpstat" },
-#define N_RTSTAT 14
+#define N_RTSTAT 9
{ "_rtstat" },
-#define N_NFILE 15
+#define N_UNIXSW 10
+ { "_unixsw" },
+#define N_IDP 11
+ { "_nspcb"},
+#define N_IDPSTAT 12
+ { "_idpstat"},
+#define N_SPPSTAT 13
+ { "_spp_istat"},
+#define N_NSERR 14
+ { "_ns_errstat"},
+#define N_CLNPSTAT 15
+ { "_clnp_stat"},
+#define IN_NOTUSED 16
+ { "_tp_inpcb" },
+#define ISO_TP 17
+ { "_tp_refinfo" },
+#define N_TPSTAT 18
+ { "_tp_stat" },
+#define N_ESISSTAT 19
+ { "_esis_stat"},
+#define N_NIMP 20
+ { "_nimp"},
+#define N_RTREE 21
+ { "_rt_tables"},
+#define N_CLTP 22
+ { "_cltb"},
+#define N_CLTPSTAT 23
+ { "_cltpstat"},
+#define N_NFILE 24
{ "_nfile" },
-#define N_FILE 16
+#define N_FILE 25
{ "_file" },
-#define N_UNIXSW 17
- { "_unixsw" },
-#define N_RTHASHSIZE 18
- { "_rthashsize" },
+#define N_IGMPSTAT 26
+ { "_igmpstat" },
+#define N_MRTPROTO 27
+ { "_ip_mrtproto" },
+#define N_MRTSTAT 28
+ { "_mrtstat" },
+#define N_MRTTABLE 29
+ { "_mrttable" },
+#define N_VIFTABLE 30
+ { "_viftable" },
+
+ /* BBN Internet protocol implementation */
+#define N_TCP 23
+ { "_tcp" },
+#define N_UDP 24
+ { "_udp" },
+#define N_RDP 25
+ { "_rdp" },
+#define N_RDPSTAT 26
+ { "_rdpstat" },
+
"",
};
-/* internet protocols */
-extern int protopr();
-extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats();
-
struct protox {
u_char pr_index; /* index into nlist of cb head */
u_char pr_sindex; /* index into nlist of stat block */
u_char pr_wanted; /* 1 if wanted, 0 otherwise */
- int (*pr_cblocks)(); /* control blocks printing routine */
- int (*pr_stats)(); /* statistics printing routine */
+ void (*pr_cblocks)(); /* control blocks printing routine */
+ void (*pr_stats)(); /* statistics printing routine */
char *pr_name; /* well-known name */
-} protox[] = {
+};
+
+struct protox berkprotox[] = {
{ N_TCB, N_TCPSTAT, 1, protopr,
tcp_stats, "tcp" },
{ N_UDB, N_UDPSTAT, 1, protopr,
0, 0 }
};
-struct pte *Sysmap;
-
-char *system = "/vmunix";
-char *kmemf = "/dev/kmem";
-int kmem;
-int kflag;
-int Aflag;
-int aflag;
-int hflag;
-int iflag;
-int mflag;
-int nflag;
-int rflag;
-int sflag;
-int tflag;
-int uflag;
-int interval;
-char *interface;
-int unit;
-char usage[] = "[ -Aaihmnrstu ] [-I interface] [ interval ] [ system ] [ core ]";
+struct protox bbnprotox[] = {
+ { N_TCP, N_TCPSTAT, 1, bbnprotopr,
+ tcpstats, "tcp" },
+ { N_UDP, N_UDPSTAT, 1, bbnprotopr,
+ udpstats, "udp" },
+ { N_RDP, N_RDPSTAT, 1, bbnprotopr,
+ rdpstats, "rdp" },
+ { N_RAWCB, 0, 1, bbnprotopr,
+ 0, "raw" },
+ { -1, N_IPSTAT, 1, 0,
+ ipstats, "ip" },
+ { -1, N_ICMPSTAT, 1, 0,
+ icmpstats, "icmp" },
+ { -1, -1, 0, 0,
+ 0, 0 }
+};
+struct protox nsprotox[] = {
+ { N_IDP, N_IDPSTAT, 1, nsprotopr,
+ idp_stats, "idp" },
+ { N_IDP, N_SPPSTAT, 1, nsprotopr,
+ spp_stats, "spp" },
+ { -1, N_NSERR, 1, 0,
+ nserr_stats, "ns_err" },
+ { -1, -1, 0, 0,
+ 0, 0 }
+};
+
+struct protox isoprotox[] = {
+ { ISO_TP, N_TPSTAT, 1, iso_protopr,
+ tp_stats, "tp" },
+ { N_CLTP, N_CLTPSTAT, 1, iso_protopr,
+ cltp_stats, "cltp" },
+ { -1, N_CLNPSTAT, 1, 0,
+ clnp_stats, "clnp"},
+ { -1, N_ESISSTAT, 1, 0,
+ esis_stats, "esis"},
+ { -1, -1, 0, 0,
+ 0, 0 }
+};
+
+struct protox *protoprotox[] = { protox, nsprotox, isoprotox, NULL };
+
+static void printproto __P((struct protox *, char *));
+static void usage __P(());
+static struct protox *name2protox __P((char *));
+static struct protox *knownname __P((char *));
+
+kvm_t *kvmd;
+
+int
main(argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
- int i;
- char *cp, *name;
+ extern char *optarg;
+ extern int optind;
register struct protoent *p;
+ register struct protox *tp; /* for printing cblocks & stats */
+ register char *cp;
+ int ch;
+ char *nlistf = NULL, *memf = NULL;
+ char buf[_POSIX2_LINE_MAX];
- name = argv[0];
- argc--, argv++;
- while (argc > 0 && **argv == '-') {
- for (cp = &argv[0][1]; *cp; cp++)
- switch(*cp) {
+ if (cp = rindex(argv[0], '/'))
+ prog = cp + 1;
+ else
+ prog = argv[0];
+ af = AF_UNSPEC;
+ while ((ch = getopt(argc, argv, "AaBdf:hI:iM:mN:np:rstuw")) != EOF)
+ switch((char)ch) {
case 'A':
- Aflag++;
+ Aflag = 1;
break;
-
case 'a':
- aflag++;
+ aflag = 1;
+ break;
+ case 'B':
+ Bflag = 1;
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'f':
+ if (strcmp(optarg, "ns") == 0)
+ af = AF_NS;
+ else if (strcmp(optarg, "inet") == 0)
+ af = AF_INET;
+ else if (strcmp(optarg, "unix") == 0)
+ af = AF_UNIX;
+ else if (strcmp(optarg, "iso") == 0)
+ af = AF_ISO;
+ else {
+ (void)fprintf(stderr,
+ "%s: %s: unknown address family\n",
+ prog, optarg);
+ exit(1);
+ }
break;
-
case 'h':
- hflag++;
+ hflag = 1;
break;
+ case 'I': {
+ char *cp;
+ iflag = 1;
+ for (cp = interface = optarg; isalpha(*cp); cp++)
+ continue;
+ unit = atoi(cp);
+ *cp = '\0';
+ break;
+ }
case 'i':
- iflag++;
+ iflag = 1;
+ break;
+ case 'M':
+ memf = optarg;
break;
-
case 'm':
- mflag++;
+ mflag = 1;
+ break;
+ case 'N':
+ nlistf = optarg;
break;
-
case 'n':
- nflag++;
+ nflag = 1;
+ break;
+ case 'p':
+ if ((tp = name2protox(optarg)) == NULL) {
+ (void)fprintf(stderr,
+ "%s: %s: unknown or uninstrumented protocol\n",
+ prog, optarg);
+ exit(1);
+ }
+ pflag = 1;
break;
-
case 'r':
- rflag++;
+ rflag = 1;
break;
-
case 's':
- sflag++;
+ ++sflag;
break;
-
case 't':
- tflag++;
+ tflag = 1;
break;
-
case 'u':
- uflag++;
+ af = AF_UNIX;
break;
-
- case 'I':
- iflag++;
- if (*(interface = cp + 1) == 0) {
- if ((interface = argv[1]) == 0)
- break;
- argv++;
- argc--;
- }
- for (cp = interface; isalpha(*cp); cp++)
- ;
- unit = atoi(cp);
- *cp-- = 0;
+ case 'w':
+ interval = atoi(optarg);
break;
-
+ case '?':
default:
-use:
- printf("usage: %s %s\n", name, usage);
- exit(1);
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+
+#define BACKWARD_COMPATIBILITY
+#ifdef BACKWARD_COMPATIBILITY
+ if (*argv) {
+ if (isdigit(**argv)) {
+ interval = atoi(*argv);
+ if (interval <= 0)
+ usage();
+ ++argv;
+ iflag = 1;
+ }
+ if (*argv) {
+ nlistf = *argv;
+ if (*++argv)
+ memf = *argv;
}
- argv++, argc--;
- }
- if (argc > 0 && isdigit(argv[0][0])) {
- interval = atoi(argv[0]);
- if (interval <= 0)
- goto use;
- argv++, argc--;
- iflag++;
- }
- if (argc > 0) {
- system = *argv;
- argv++, argc--;
}
- nlist(system, nl);
- if (nl[0].n_type == 0) {
- fprintf(stderr, "%s: no namelist\n", system);
+#endif
+
+ /*
+ * Discard setgid privileges if not the running kernel so that bad
+ * guys can't print interesting stuff from kernel memory.
+ */
+ if (nlistf != NULL || memf != NULL)
+ setgid(getgid());
+
+ if ((kvmd = kvm_open(nlistf, memf, NULL, O_RDONLY, prog)) == NULL) {
+ fprintf(stderr, "%s: kvm_open: %s\n", prog, buf);
exit(1);
}
- if (argc > 0) {
- kmemf = *argv;
- kflag++;
- }
- kmem = open(kmemf, 0);
- if (kmem < 0) {
- fprintf(stderr, "cannot open ");
- perror(kmemf);
+ if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) {
+ if (nlistf)
+ fprintf(stderr, "%s: %s: no namelist\n", prog, nlistf);
+ else
+ fprintf(stderr, "%s: no namelist\n", prog);
exit(1);
}
- if (kflag) {
- off_t off;
-
- off = nl[N_SYSMAP].n_value & 0x7fffffff;
- lseek(kmem, off, 0);
- nl[N_SYSSIZE].n_value *= 4;
- Sysmap = (struct pte *)malloc(nl[N_SYSSIZE].n_value);
- if (Sysmap == 0) {
- perror("Sysmap");
- exit(1);
- }
- read(kmem, Sysmap, nl[N_SYSSIZE].n_value);
- }
if (mflag) {
mbpr(nl[N_MBSTAT].n_value);
exit(0);
}
- if (uflag) {
- unixpr(nl[N_NFILE].n_value, nl[N_FILE].n_value,
- nl[N_UNIXSW].n_value);
+ if (pflag) {
+ if (tp->pr_stats)
+ (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
+ tp->pr_name);
+ else
+ printf("%s: no stats routine\n", tp->pr_name);
+ exit(0);
+ }
+ if (hflag) {
+ hostpr(nl[N_IMP].n_value, nl[N_NIMP].n_value);
exit(0);
}
/*
intpr(interval, nl[N_IFNET].n_value);
exit(0);
}
- if (hflag) {
- hostpr(nl[N_HOSTS].n_value);
- exit(0);
- }
if (rflag) {
if (sflag)
rt_stats(nl[N_RTSTAT].n_value);
else
- routepr(nl[N_RTHOST].n_value, nl[N_RTNET].n_value,
- nl[N_RTHASHSIZE].n_value);
+ routepr(nl[N_RTREE].n_value);
exit(0);
}
- setprotoent(1);
- setservent(1);
- while (p = getprotoent()) {
- register struct protox *tp;
-
- for (tp = protox; tp->pr_name; tp++)
- if (strcmp(tp->pr_name, p->p_name) == 0)
- break;
- if (tp->pr_name == 0 || tp->pr_wanted == 0)
- continue;
- if (sflag && tp->pr_stats) {
- (*tp->pr_stats)(nl[tp->pr_sindex].n_value, p->p_name);
- continue;
- }
- if (tp->pr_cblocks)
- (*tp->pr_cblocks)(nl[tp->pr_index].n_value, p->p_name);
+ if (Bflag) {
+ if (sflag)
+ mrt_stats(nl[N_MRTPROTO].n_value,
+ nl[N_MRTSTAT].n_value);
+ else
+ mroutepr(nl[N_MRTPROTO].n_value,
+ nl[N_MRTTABLE].n_value,
+ nl[N_VIFTABLE].n_value);
+ exit(0);
}
- endprotoent();
+
+
+ if (sflag) {
+ if (tp->pr_stats)
+ (*tp->pr_stats)(nl[tp->pr_sindex].n_value, tp->pr_name);
+ } else if (tp->pr_cblocks)
+ (*tp->pr_cblocks)(nl[tp->pr_index].n_value, tp->pr_name);
+ }
+ if (pr != NULL && (off || af != AF_UNSPEC))
+ (*pr)(off, name);
}
/*
- * Seek into the kernel for a value.
+ * Read kernel memory, return 0 on success.
*/
-klseek(fd, base, off)
- int fd, base, off;
+int
+kread(addr, buf, size)
+ u_long addr;
+ char *buf;
+ int size;
{
- if (kflag) {
- /* get kernel pte */
-#ifdef vax
- base &= 0x7fffffff;
-#endif
- base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
+ if (kvm_read(kvmd, addr, buf, size) != size) {
+ /* XXX this duplicates kvm_read's error printout */
+ (void)fprintf(stderr, "%s: kvm_read %s\n", prog,
+ kvm_geterr(kvmd));
+ return (-1);
}
- lseek(fd, base, off);
+ return (0);
}
char *
plural(n)
int n;
{
-
return (n != 1 ? "s" : "");
}
+
+char *
+plurales(n)
+ int n;
+{
+ return (n != 1 ? "es" : "");
+}
+
+/*
+ * Find the protox for the given "well-known" name.
+ */
+static struct protox *
+knownname(name)
+ char *name;
+{
+ struct protox **tpp, *tp;
+
+ for (tpp = protoprotox; *tpp; tpp++)
+ for (tp = *tpp; tp->pr_name; tp++)
+ if (strcmp(tp->pr_name, name) == 0)
+ return (tp);
+ return (NULL);
+}
+
+/*
+ * Find the protox corresponding to name.
+ */
+static struct protox *
+name2protox(name)
+ char *name;
+{
+ struct protox *tp;
+ char **alias; /* alias from p->aliases */
+ struct protoent *p;
+
+ /*
+ * Try to find the name in the list of "well-known" names. If that
+ * fails, check if name is an alias for an Internet protocol.
+ */
+ if (tp = knownname(name))
+ return (tp);
+
+ setprotoent(1); /* make protocol lookup cheaper */
+ while (p = getprotoent()) {
+ /* assert: name not same as p->name */
+ for (alias = p->p_aliases; *alias; alias++)
+ if (strcmp(name, *alias) == 0) {
+ endprotoent();
+ return (knownname(p->p_name));
+ }
+ }
+ endprotoent();
+ return (NULL);
+}
+
+static void
+usage()
+{
+ (void)fprintf(stderr,
+"usage: %s [-Aan] [-f address_family] [-M core] [-N system]\n", prog);
+ (void)fprintf(stderr,
+" [-himnrs] [-f address_family] [-M core] [-N system]\n");
+ (void)fprintf(stderr,
+" [-n] [-I interface] [-M core] [-N system] [-w wait]\n");
+ (void)fprintf(stderr,
+" [-M core] [-N system] [-p protocol]\n");
+ exit(1);
+}