|
|
Power 6/32 Unix version 1.21
#ifndef lint
static char sccsid[] = "@(#)main.c 4.9 83/05/30";
#endif
#include <sys/param.h>
#include <sys/vmmac.h>
#include <machine/pte.h>
#include <sys/socket.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <nlist.h>
#include <stdio.h>
#include "nstat.h"
extern int protopr(), arptab(), enperrors(), enpbuf();
extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats();
extern int acestat(), enpstat();
struct protox {
u_char pr_wanted; /* 1 if wanted, 0 otherwise */
int (*pr_cblocks)(); /* control blocks printing routine */
int (*pr_stats)(); /* statistics printing routine */
char *pr_name; /* well-known name */
};
struct protox protox[] = {
{ 1, protopr, tcp_stats, "tcp" },
{ 1, protopr, udp_stats, "udp" },
{ 1, 0, ip_stats, "ip" },
{ 1, 0, icmp_stats, "icmp" },
{ 0, 0, 0, 0 }
};
struct devx {
int (*d_stats)(); /* device statistics printing func */
char *d_name; /* well-known name */
};
struct devx devstat[] = {
{ acestat, "ace"},
{ enpstat, "enp"},
{ 0 }
};
struct pte *Sysmap;
char *system = "/vmunix";
char *kmemf = "/dev/kmem";
int kmem; /* file descriptor of kmemf */
int interval; /* looping interval */
char *printproto; /* protocol flag */
char *devname; /* device name */
#define DELIM() {printf("--------------------------------\n");}
long flaggiven = 0x00000000;
int s; /* socket id */
main(argc, argv)
int argc;
char *argv[];
{
int i;
char *cp, *name;
register struct protoent *p;
register struct protox *tp;
name = argv[0];
argc--, argv++;
while (argc > 0 && **argv == '-') {
for (cp = &argv[0][1]; *cp; cp++)
switch(*cp) {
case 'A':
flaggiven |= AFLAG;
break;
case 'E':
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
perror("main: socket");
exit(1);
}
flaggiven |= EFLAG;
break;
case 'e':
flaggiven |= eFLAG;
break;
case 'b':
argv++, argc--;
if (argc <= 0)
goto use;
devname = *argv;
flaggiven |= bFLAG;
break;
case 'a':
argv++, argc--;
if (argc <= 0)
goto use;
interval = atoi(argv[0]);
if (interval <= 0)
goto use;
break;
case 'h':
flaggiven |= hFLAG;
break;
case 'i':
flaggiven |= iFLAG;
break;
case 'm':
flaggiven |= mFLAG;
break;
case 'n':
flaggiven |= nFLAG;
break;
case 'r':
flaggiven |= rFLAG;
break;
case 's':
flaggiven |= sFLAG;
break;
case 'c':
flaggiven |= cFLAG;
break;
case 'p':
argv++, argc--;
if (argc <= 0)
goto use;
printproto = *argv;
flaggiven |= pFLAG;
break;
case 'd':
argv++, argc--;
if (argc <= 0)
goto use;
devname = *argv;
flaggiven |= dFLAG;
break;
case 't':
flaggiven |= tFLAG;
break;
case 'H':
default:
use:
help();
exit(1);
} /* end of switch */
argv++, argc--;
} /* end of while loop */
/* will print pcb when: */
if (!flaggiven || /* no option given at all */
Aflag || /* debug option */
(flaggiven == nFLAG) || /* only numeric flag given */
(flaggiven == pFLAG) || /* only protocol flag given */
(flaggiven == (nFLAG | pFLAG)) ) {
flaggiven |= cFLAG;
}
if (argc > 0) {
system = *argv;
argv++, argc--;
}
if (argc > 0) {
kmemf = *argv;
flaggiven |= kFLAG;
}
kmem = open(kmemf, 0);
if (kmem < 0) {
fprintf(stderr, "nstat: cannot open ");
perror(kmemf);
exit(1);
}
/*
* Keep file descriptors open to avoid overhead
* of open/close on each call to get* routines.
*/
sethostent(1);
setnetent(1);
for (;;) {
if (Eflag) {
DELIM();
arptab();
}
if (eflag) {
enperrors();
}
if (iflag || tflag) {
if (tflag && interval <= 0)
interval = 1;
DELIM();
intpr(interval);
}
if (kflag) {
rkmem();
}
if (mflag) {
DELIM();
mbpr();
}
if (hflag) {
DELIM();
hostpr();
}
if (sflag) {
DELIM();
rt_stats();
}
if (rflag) {
DELIM();
routepr();
}
if (dflag || bflag) {
struct devx *p;
int i, unit;
char *c;
c = devname;
while (*c && !isdigit(*c)) {
c++, i++;
}
if (*c)
unit = *c - '0';
else
unit = WILDCARD;
for (p = devstat; p->d_name; p++) {
if (strncmp(p->d_name, devname, i) == 0)
break;
}
if (p->d_name == 0)
fprintf(stderr, "nstat: illegal device %s\n",devname);
else {
if (bflag) {
if (strncmp(p->d_name, "enp", 3) == 0)
enpbuf(unit);
else
fprintf(stderr,
"nstat: -b works for enp device only\n");
} else
if (dflag && p->d_stats)
(*p->d_stats)(unit, 0);
}
}
if (sflag) {
/* go through list of available protocols in system */
setprotoent(1);
setservent(1);
while (p = getprotoent()) {
/* user gave any specific protocol? */
if (pflag &&
strcmp(p->p_name, printproto) != 0)
continue;
/* go through list of protocols 'nstat' supports */
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;
/* found one protocol */
if (tp->pr_stats) {
DELIM();
(*tp->pr_stats)();
continue;
}
}
}
if (cflag) {
setprotoent(1);
setservent(1);
while (p = getprotoent()) {
if (pflag &&
strcmp(p->p_name, printproto) != 0)
continue;
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 (tp->pr_cblocks) {
DELIM();
(*tp->pr_cblocks)(tp->pr_name);
}
}
}
if (interval)
sleep(interval);
else {
DELIM();
close(kmem);
exit(0);
}
}
}
/*
* Seek into the kernel for a value.
*/
klseek(fd, base, off)
int fd, base, off;
{
if (kflag) {
/* get kernel pte */
#if defined(vax) || defined(tahoe)
base &= 0x3FFFFFFF;
#endif
base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
}
lseek(fd, base, off);
}
char *
plural(n)
int n;
{
return (n != 1 ? "s" : "");
}
help()
{
printf("nstat [-HdchimnprstEAeb] [-p proto] [interval] [system] [core]\n");
printf("where:\n");
printf("-H HELP. print all available options.\n");
printf("-a interval\n");
printf(" specify nstat to continuously list the status, pausing");
printf(" for each interval between displays.\n");
printf("-d devicename\n");
printf(" show statistics associated with device.\n");
printf("-c show all connections.\n");
printf("-h show the state of the IMP host table.\n");
printf("-i show the state of auto-configured interfaces.\n");
printf("-m show mbuf statistics.\n");
printf("-n show network addresses as numbers.\n");
printf("-p protocol\n");
printf(" only print connections of 'protocol'.\n");
printf("-r show the routing tables\n");
printf("-s show protocol statistics\n");
printf("-t show data transmission through interfaces periodically.\n");
printf("-E show Ethernet/Internet addresses of currently-up hosts.\n");
printf("-A show addresses of PCBs; for debugging\n");
/* don't expose these 2 options to users */
#ifdef notdef
printf("-e show Driver-Level input-packet error types; for debugging\n");
printf("-b devicename (for enpX only); for debugging\n");
printf(" show ENP buffer rings' pointers.\n");
#endif
printf("The arguments 'system' and 'core' allow substitutes for the\n");
printf("defaults '/vmunix' and '/dev/kmem'.\n");
}
struct nlist sysmapnl[] = {
#define N_SYSMAP 0
{ "_Sysmap" },
#define N_SYSSIZE 1
{ "_Syssize" },
{""},
};
rkmem()
{
static int getvm = 0;
off_t off;
if (!getvm) {
nlist(system, sysmapnl);
getvm++;
}
sysmapnl[N_SYSSIZE].n_value *= 4;
Sysmap = (struct pte *)malloc(sysmapnl[N_SYSSIZE].n_value);
if (Sysmap == 0) {
perror("rsysmap");
exit(1);
}
#ifdef tahoe
off = sysmapnl[N_SYSMAP].n_value & 0x3FFFFFFF;
#endif
lseek(kmem, off, 0);
read(kmem, Sysmap, sysmapnl[N_SYSSIZE].n_value);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.