File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / usr / src / etc / nstat / main.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:24:30 2019 UTC (7 years ago) by root
Branches: bsd, MAIN
CVS tags: v121, HEAD
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);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.