nfswatch.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 736 行

C
736
字号
#ifndef lintstatic char *sccsid = "@(#)nfswatch.c	4.2	ULTRIX	1/25/91";/* Based on: */static char *RCSid = "$Header: nfswatch.c,v 3.1 91/01/23 16:56:19 mogul Exp $";#endif/* * nfswatch - NFS server packet monitoring program. * * David A. Curry				Jeffrey C. Mogul * SRI International				Digital Equipment Corporation * 333 Ravenswood Avenue			Western Research Laboratory * Menlo Park, CA 94025				100 Hamilton Avenue * davy@erg.sri.com				Palo Alto, CA 94301 *						mogul@decwrl.dec.com * * $Log:	nfswatch.c,v $ * Revision 3.1  91/01/23  16:56:19  mogul * Black magic *  * Revision 3.0  91/01/23  08:23:11  davy * NFSWATCH Version 3.0. *  * Revision 1.5  91/01/04  16:05:15  davy * Updated version number. *  * Revision 1.4  91/01/04  15:54:29  davy * New features from Jeff Mogul. *  * Revision 1.3  90/12/04  08:06:41  davy * Changed version number to 2.1. *  * Revision 1.2  90/08/17  15:47:29  davy * NFSWATCH Version 2.0. *  * Revision 1.1  88/11/29  11:20:40  davy * NFSWATCH Release 1.0 *  */#include <sys/param.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/time.h>#include <net/if.h>#include <signal.h>#include <errno.h>#include <stdio.h>#ifdef sun#include <net/nit_if.h>#include <net/nit_buf.h>#define USE_NITchar	*devices[] = {	"le0", "ie0", "le1", "ie1", "le2", "ie2",	"le3", "ie3", "le4", "ie4",	0};#endif /* sun */#ifdef ultrix#include <net/pfilt.h>#define USE_PFILTchar	*devices[] = {	"pf0", "pf1", "pf2", "pf3", "pf4", "pf5",	"pf6", "pf7", "pf8", "pf9",	0};#endif /* ultrix */#include "nfswatch.h"char		*pname;				/* program name		*/FILE		*logfp;				/* log file pointer	*/Counter		pkt_total = 0;			/* total packets seen	*/Counter		pkt_drops = 0;			/* total packets dropped*/Counter		int_pkt_total = 0;		/* packets this interval*/Counter		int_pkt_drops = 0;		/* dropped this interval*/Counter		dst_pkt_total = 0;		/* total pkts to host	*/Counter		int_dst_pkt_total = 0;		/* pkts to host this int*/int		if_fd[MAXINTERFACES];		/* nit device file desc	*/int		srcflag = 0;			/* "-src" specified	*/int		dstflag = 0;			/* "-dst" specified	*/int		allflag = 0;			/* "-all" specified	*/int		allintf = 0;			/* "-allif" specified	*/int		logging = 0;			/* 1 when logging on	*/int		learnfs = 0;			/* learn other servers	*/int		do_update = 0;			/* time to update screen*/int		showwhich = 0;			/* show filesys or files*/int		cycletime = CYCLETIME;		/* update cycle time	*/int		truncation = 200;		/* pkt trunc len - magic*/int		sortbyusage = 0;		/* sort by usage counts	*/int		nnfscounters = 0;		/* # of NFS counters	*/int		nfilecounters = 0;		/* # of file counters	*/int		nclientcounters = 0;		/* # of client counters */int		screen_inited = 0;		/* 1 when in curses	*/struct timeval	starttime;			/* time we started	*/int		ninterfaces;			/* number of interfaces	*/u_long		thisdst = 0;			/* cached IP dst of pkt	*/u_long		srcaddrs[MAXHOSTADDR];		/* src host net addrs	*/u_long		dstaddrs[MAXHOSTADDR];		/* dst host net addrs	*/char		myhost[MAXHOSTNAMELEN];		/* local host name	*/char		srchost[MAXHOSTNAMELEN];	/* source host name	*/char		dsthost[MAXHOSTNAMELEN];	/* destination host name*/char		*prompt = PROMPT;		/* prompt string	*/char		*filelist = NULL;		/* list of files	*/char		*logfile = LOGFILE;		/* log file name	*/char		*snapshotfile = SNAPSHOTFILE;	/* snapshot file name	*/NFSCounter	nfs_counters[MAXEXPORT];	/* NFS request counters	*/FileCounter	fil_counters[MAXEXPORT];	/* file request counters*/PacketCounter	pkt_counters[PKT_NCOUNTERS];	/* packet counters	*/ProcCounter	prc_counters[MAXNFSPROC+2];	/* procedure counters	*/				/* extra space simplifies sort_prc_counters */int		prc_countmap[MAXNFSPROC];	/* allows sorting	*/ClientCounter	clnt_counters[MAXCLIENTS];	/* per-client counters	*/#ifdef ultrixvoidfpe_warn(){	extern void finish();	fprintf(stderr, "nfswatch: mystery bug encountered.\n");	finish(-1);}#endif /* ultrix */main(argc, argv)int argc;char **argv;{	register int i;	struct sigvec sv;	char *device = NULL;	extern void finish(), nfswatch();	pname = *argv;	/*	 * Get our host name.  The default destination	 * host is the one we're running on.	 */	if (gethostname(myhost, sizeof(myhost)) < 0) {		error("gethostname");		finish(-1);	}	(void) strcpy(dsthost, myhost);	/*	 * Process arguments.	 */	while (--argc) {		if (**++argv != '-')			usage();		/*		 * Set destination host.		 */		if (!strcmp(*argv, "-dst")) {			if (--argc <= 0)				usage();			(void) strcpy(dsthost, *++argv);			dstflag++;			continue;		}		/*		 * Set source host.		 */		if (!strcmp(*argv, "-src")) {			if (--argc <= 0)				usage();			(void) strcpy(srchost, *++argv);			srcflag++;			continue;		}		/*		 * Device to use.		 */		if (!strcmp(*argv, "-dev")) {			if (--argc <= 0)				usage();			device = *++argv;			continue;		}		/*		 * Log file name.		 */		if (!strcmp(*argv, "-lf")) {			if (--argc <= 0)				usage();			logfile = *++argv;			continue;		}		/*		 * Snapshot file name.		 */		if (!strcmp(*argv, "-sf")) {			if (--argc <= 0)				usage();			snapshotfile = *++argv;			continue;		}		/*		 * List of files.		 */		if (!strcmp(*argv, "-f")) {			if (--argc <= 0)				usage();			if (showwhich == 0)				showwhich = SHOWINDVFILES;			filelist = *++argv;			continue;		}		/*		 * Change cycle time.		 */		if (!strcmp(*argv, "-t")) {			if (--argc <= 0)				usage();			cycletime = atoi(*++argv);			continue;		}		/*		 * Show file systems.		 */		if (!strcmp(*argv, "-fs")) {			showwhich = SHOWFILESYSTEM;			continue;		}		/*		 * Show individual files.		 */		if (!strcmp(*argv, "-if")) {			showwhich = SHOWINDVFILES;			continue;		}		/*		 * Show NFS procedures		 */		if (!strcmp(*argv, "-procs")) {			showwhich = SHOWNFSPROCS;			continue;		}		/*		 * Show NFS clients		 */		if (!strcmp(*argv, "-clients")) {			showwhich = SHOWCLIENTS;			continue;		}		/*		 * Turn on logging.		 */		if (!strcmp(*argv, "-l")) {			logging++;			continue;		}		/*		 * Watch all traffic.		 */		if (!strcmp(*argv, "-all")) {			allflag++;			continue;		}		/*		 * Use all interfaces.		 */		if (!strcmp(*argv, "-allif")) {			allintf++;			continue;		}		/*		 * Sort file systems by usage, not name.		 */		if (!strcmp(*argv, "-usage")) {			sortbyusage++;			continue;		}		usage();	}	/*	 * Check what we're showing.	 */	switch (showwhich) {	case 0:			/* default */		showwhich = SHOWFILESYSTEM;		break;	case SHOWINDVFILES:		if (filelist == NULL) {			(void) fprintf(stderr, "%s: must specify file list with -fi.\n", pname);			finish(-1);		}		break;	}	/*	 * Trap signals so we can clean up.	 */	sv.sv_handler = finish;	sv.sv_mask = sv.sv_flags = 0;	(void) sigvec(SIGINT, &sv, (struct sigvec *) 0);	(void) sigvec(SIGQUIT, &sv, (struct sigvec *) 0);#ifdef ultrix	sv.sv_handler = fpe_warn;	(void) sigvec(SIGFPE, &sv, (struct sigvec *) 0);#endif /* ultrix */#ifdef USE_NIT	/*	 * Set up the network interface tap right away,	 * since we probably need super-user permission.	 */	if (allintf) {		ninterfaces = 0;		for (i=0; devices[i] != NULL; i++) {			if_fd[ninterfaces] = setup_nit_dev(&devices[i]);			if (if_fd[ninterfaces] >= 0)				ninterfaces++;		}	}	else {		if_fd[0] = setup_nit_dev(&device);		if (if_fd[0] < 0) {			perror(device);			finish(-1);		}		ninterfaces = 1;	}#endif /* USE_NIT */#ifdef USE_PFILT	/*	 * Set up the packet filter interface now,	 * although we don't need super-user permission.	 */	if (allintf) {		ninterfaces = 0;		for (i=0; devices[i] != NULL; i++) {			if_fd[ninterfaces] = setup_pfilt_dev(&devices[i]);			if (if_fd[ninterfaces] >= 0)				ninterfaces++;		}	}	else {		if_fd[0] = setup_pfilt_dev(&device);		if (if_fd[0] < 0) {			perror(device);			finish(-1);		}		ninterfaces = 1;	}#endif /* USE_PFILT */	if (ninterfaces < 1) {		fprintf(stderr, "%s: no valid interfaces.\n", pname);		finish(-1);	}	/*	 * Now lose super-user permission, since we	 * don't need it for anything else.	 */	(void) setreuid(getuid(), getuid());	/*	 * Look up the network addresses of the source and	 * destination hosts.	 */	get_net_addrs();	/*	 * Tell the user what's going on.	 */	(void) printf("NFSWATCH Version %s\n", VERSION);	(void) printf("Watch packets from %s to %s on ",		(srcflag ? srchost : "all hosts"), dsthost);	if (allintf)		(void) printf("all interfaces;\n");	else		(void) printf("interface %s;\n", device);	(void) printf("log to \"%s\" (logging %s);\n", logfile,		(logging ? "on" : "off"));	(void) printf("snapshots to \"%s\";\n", snapshotfile);	(void) printf("cycle time %d seconds...", cycletime);	(void) fflush(stdout);	/*	 * Set up a pseudo RPC server.	 */	setup_rpcxdr();	/*	 * Set up the screen.	 */	setup_screen(device);	/*	 * Set up the packet counters.  This must be done after	 * setup_screen because they use the LINES variable.	 */	setup_pkt_counters();	setup_nfs_counters();	setup_proc_counters();	if (filelist)		setup_fil_counters();	/*	 * Now label the screen.	 */	label_screen();	/*	 * Open log file if logging is on.	 */	if (logging) {		if ((logfp = fopen(logfile, "a")) == NULL) {			error(logfile);			finish(-1);		}		(void) fprintf(logfp, "#\n# startlog\n#\n");		(void) fprintf(logfp, "# NFSwatch log file\n");		(void) fprintf(logfp, "#    Packets from: %s\n",			(srcflag ? srchost : "all hosts"));		(void) fprintf(logfp, "#    Packets to:   %s\n#\n",			dsthost);	}	/*	 * Go watch packets.  Never returns.	 */	nfswatch();}/* * nfswatch - main packet reading loop. */voidnfswatch(){	int i, cc;	char *buf;	char *malloc();	fd_set readfds;	struct sigvec sv;	struct timeval tv;	extern void wakeup();	struct itimerval itv;	register char *bp, *cp, *bufstop;#ifdef USE_NIT	int tdrops[MAXINTERFACES];	struct nit_bufhdr *hdrp;	struct nit_ifdrops *ndp;#endif /* USE_NIT */#ifdef USE_PFILT	struct enstamp stamp;	int datalen;#endif /* USE_PFILT */	/*	 * Allocate a buffer so it's properly aligned for	 * casting to structure types.	 */	if ((buf = malloc(NIT_CHUNKSIZE)) == NULL) {		(void) fprintf(stderr, "%s: out of memory.\n", pname);		finish(-1);	}	/*	 * Set up the alarm handler.	 */	sv.sv_handler = wakeup;	sv.sv_mask = sv.sv_flags = 0;	(void) sigvec(SIGALRM, &sv, (struct sigvec *) 0);	/*	 * Set up the alarm clock.	 */	(void) bzero((char *) &itv, sizeof(struct itimerval));	itv.it_interval.tv_sec = cycletime;	itv.it_interval.tv_usec = 0;	itv.it_value = itv.it_interval;	(void) setitimer(ITIMER_REAL, &itv, (struct itimerval *) 0);	/*	 * Set the start time.	 */	(void) gettimeofday(&starttime, (struct timezone *) 0);#ifdef USE_NIT	/*	 * Flush the read queue of any packets that accumulated	 * during setup time.	 */	for (i=0; i < ninterfaces; i++) {		flush_nit(if_fd[i]);		tdrops[i] = 0;	}	for (;;) {		FD_ZERO(&readfds);		for (i=0; i < ninterfaces; i++)			FD_SET(if_fd[i], &readfds);		/*		 * See which nets have packets to read.		 */		cc = select(NFDBITS, &readfds, (fd_set *) 0, (fd_set *) 0, 0);		if ((cc < 0) && (errno != EINTR)) {			error("select");			finish(-1);		}		if (cc == 0) {			continue;		}				/*		 * For each interface...		 */		for (i=0; i < ninterfaces; i++) {			/*			 * Nothing to read.			 */			if (!FD_ISSET(if_fd[i], &readfds))				continue;			/*			 * Now read packets from the nit device.			 */			if ((cc = read(if_fd[i], buf, NIT_CHUNKSIZE)) <= 0)				continue;			bufstop = buf + cc;			bp = buf;			/*			 * Loop through the chunk, extracting packets.			 */			while (bp < bufstop) {				cp = bp;				/*				 * Get the nit header.				 */				hdrp = (struct nit_bufhdr *) cp;				cp += sizeof(struct nit_bufhdr);				/*				 * Get the number of dropped packets.				 */				ndp = (struct nit_ifdrops *) cp;				cp += sizeof(struct nit_ifdrops);				int_pkt_drops += ndp->nh_drops - tdrops[i];				pkt_drops += ndp->nh_drops - tdrops[i];				tdrops[i] = ndp->nh_drops;				/*				 * Filter the packet.				 */				pkt_filter(cp, hdrp->nhb_msglen);				/*				 * Skip over this packet.				 */				bp += hdrp->nhb_totlen;			}		}#endif /* USE_NIT */#ifdef USE_PFILT	/*	 * Flush the read queue of any packets that accumulated	 * during setup time.	 */	for (i=0; i < ninterfaces; i++)		flush_pfilt(if_fd[i]);	for (;;) {		FD_ZERO(&readfds);		for (i=0; i < ninterfaces; i++)			FD_SET(if_fd[i], &readfds);		/*		 * See which interfaces have any packets to read.		 */		cc = select(NFDBITS, &readfds, (fd_set *) 0, (fd_set *) 0, 0);		if ((cc < 0) && (errno != EINTR)) {			error("select");			finish(-1);		}		if (cc == 0) {			continue;		}		/*		 * Now read packets from the packet filter device.		 */		for (i=0; i < ninterfaces; i++) {			if (!FD_ISSET(if_fd[i], &readfds))				continue;						if ((cc = read(if_fd[i], buf, NIT_CHUNKSIZE)) < 0) {				lseek(if_fd[i], 0L, 0);				/*				 * Might have read MAXINT bytes.  Try again.				 */				if ((cc = read(if_fd[i], buf, NIT_CHUNKSIZE)) < 0) {					error("pfilt read");					finish(-1);				}			}					bp = buf;			/*			 * Loop through buffer, extracting packets.			 */			while (cc > 0) {				/*				 * Avoid alignment issues.				 */				(void) bcopy(bp, &stamp, sizeof(stamp));				/*				 * Treat entire buffer as garbage.				 */				if (stamp.ens_stamplen != sizeof(stamp))					break;				/*				 * Get the number of dropped packets.				 */				int_pkt_drops += stamp.ens_dropped;				pkt_drops += stamp.ens_dropped;				/*				 * Filter the packet.				 */				datalen = stamp.ens_count;				if (datalen > truncation)					datalen = truncation;				pkt_filter(&(bp[sizeof(stamp)]), datalen);				/*				 * Skip over this packet.				 */				if (cc == (datalen + sizeof(stamp)))					break;				datalen = ENALIGN(datalen);				datalen += sizeof(stamp);				cc -= datalen;				bp += datalen;			}		}#endif /* USE_PFILT */		tv.tv_sec = 0;		tv.tv_usec = 0;		FD_ZERO(&readfds);		FD_SET(0, &readfds);		/*		 * See if a command has been typed.		 */		cc = select(NFDBITS, &readfds, (fd_set *) 0, (fd_set *) 0, &tv);		if ((cc > 0) && FD_ISSET(0, &readfds))			command();	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?