rpcfilter.c

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

C
644
字号
#ifndef lintstatic char *sccsid = "@(#)rpcfilter.c	4.2	(ULTRIX)	1/25/91";#endif/* Based on: * RCSid = "$Header: /sparky/a/davy/system/nfswatch/RCS/rpcfilter.c,v 3.0 91/01/23 08:23:20 davy Exp $"; *//* * rpcfilter.c - filter RPC packets. * * 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:	rpcfilter.c,v $ * Revision 3.0  91/01/23  08:23:20  davy * NFSWATCH Version 3.0. *  * Revision 1.5  91/01/17  10:13:02  davy * Bug fix from Jeff Mogul. *  * Revision 1.7  91/01/16  15:49:12  mogul * Print server or client address in a.b.c.d notation if name not known *  * Revision 1.6  91/01/07  15:35:51  mogul * Uses hash table instead of linear search on clients * One-element "hint" cache to avoid client hash lookup *  * Revision 1.5  91/01/04  14:12:35  mogul * Support for client counters * Disable screen update during database upheaval *  * Revision 1.4  91/01/03  17:35:00  mogul * Count per-procedure info *  * Revision 1.3  90/12/04  08:22:06  davy * Fix from Dan Trinkle (trinkle@cs.purdue.edu) to determine byte order in * file handle. *  * Revision 1.2  90/08/17  15:47:44  davy * NFSWATCH Version 2.0. *  * Revision 1.1  88/11/29  11:20:51  davy * NFSWATCH Release 1.0 *  */#include <sys/param.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/stat.h>#include <rpc/types.h>#include <rpc/xdr.h>#include <rpc/auth.h>#include <rpc/clnt.h>#include <rpc/rpc_msg.h>#include <rpc/pmap_clnt.h>#include <rpc/svc.h>#include <netdb.h>#include <errno.h>#include <stdio.h>#include <signal.h>#define NFSSERVER	1#ifdef sun#include <sys/vfs.h>#endif /* sun */#ifdef ultrix#include <sys/types.h>#include <sys/time.h>#endif /* ultrix */#include <nfs/nfs.h>#include "nfswatch.h"#include "externs.h"#include "rpcdefs.h"/* * NFS procedure types and XDR argument decoding routines. */static struct nfs_proc nfs_procs[] = {/* RFS_NULL (0)		*/	NFS_READ,	xdr_void,	0,/* RFS_GETATTR (1)	*/	NFS_READ,	xdr_fhandle,	sizeof(fhandle_t),/* RFS_SETATTR (2)	*/	NFS_WRITE,	xdr_saargs,	sizeof(struct nfssaargs),/* RFS_ROOT (3)		*/	NFS_READ,	xdr_void,	0,/* RFS_LOOKUP (4)	*/	NFS_READ,	xdr_diropargs,	sizeof(struct nfsdiropargs),/* RFS_READLINK (5)	*/	NFS_READ,	xdr_fhandle,	sizeof(fhandle_t),/* RFS_READ (6)		*/	NFS_READ,	xdr_readargs,	sizeof(struct nfsreadargs),/* RFS_WRITECACHE (7)	*/	NFS_WRITE,	xdr_void,	0,/* RFS_WRITE (8)	*/	NFS_WRITE,	xdr_writeargs,	sizeof(struct nfswriteargs),/* RFS_CREATE (9)	*/	NFS_WRITE,	xdr_creatargs,	sizeof(struct nfscreatargs),/* RFS_REMOVE (10)	*/	NFS_WRITE,	xdr_diropargs,	sizeof(struct nfsdiropargs),/* RFS_RENAME (11)	*/	NFS_WRITE,	xdr_rnmargs,	sizeof(struct nfsrnmargs),/* RFS_LINK (12)	*/	NFS_WRITE,	xdr_linkargs,	sizeof(struct nfslinkargs),/* RFS_SYMLINK (13)	*/	NFS_WRITE,	xdr_slargs,	sizeof(struct nfsslargs),/* RFS_MKDIR (14)	*/	NFS_WRITE,	xdr_creatargs,	sizeof(struct nfscreatargs),/* RFS_RMDIR (15)	*/	NFS_WRITE,	xdr_diropargs,	sizeof(struct nfsdiropargs),/* RFS_READDIR (16)	*/	NFS_READ,	xdr_rddirargs,	sizeof(struct nfsrddirargs),/* RFS_STATFS (17)	*/	NFS_READ,	xdr_fhandle,	sizeof(fhandle_t)};/* * rpc_filter - pass off RPC packets to other filters. */voidrpc_filter(data, length, src, dst)register u_long src, dst;register u_int length;register char *data;{	register struct rpc_msg *msg;	msg = (struct rpc_msg *) data;	/*	 * See which "direction" the packet is going.  We	 * can classify RPC CALLs, but we cannot classify	 * REPLYs, since they no longer have the RPC	 * program number in them (sigh).	 */	switch (ntohl(msg->rm_direction)) {	case CALL:			/* RPC call			*/		rpc_callfilter(data, length, src, dst);		break;	case REPLY:			/* RPC reply			*/		rpc_replyfilter(data, length, src, dst);		break;	default:			/* probably not an RPC packet	*/		break;	}}/* * rpc_callfilter - filter RPC call packets. */voidrpc_callfilter(data, length, src, dst)register u_long src, dst;register u_int length;register char *data;{	register struct rpc_msg *msg;	msg = (struct rpc_msg *) data;	/*	 * Decide what to do based on the program.	 */	switch (ntohl(msg->rm_call.cb_prog)) {	case RPC_NFSPROG:		nfs_filter(data, length, src, dst);		break;	case RPC_YPPROG:	case RPC_YPBINDPROG:	case RPC_YPPASSWDPROG:		pkt_counters[PKT_YELLOWPAGES].pc_interval++;		pkt_counters[PKT_YELLOWPAGES].pc_total++;		break;	case RPC_MOUNTPROG:		pkt_counters[PKT_NFSMOUNT].pc_interval++;		pkt_counters[PKT_NFSMOUNT].pc_total++;		break;#ifdef notdef	case RPC_PMAPPROG:	case RPC_RSTATPROG:	case RPC_RUSERSPROG:	case RPC_DBXPROG:	case RPC_WALLPROG:	case RPC_ETHERSTATPROG:	case RPC_RQUOTAPROG:	case RPC_SPRAYPROG:	case RPC_IBM3270PROG:	case RPC_IBMRJEPROG:	case RPC_SELNSVCPROG:	case RPC_RDATABASEPROG:	case RPC_REXECPROG:	case RPC_ALICEPROG:	case RPC_SCHEDPROG:	case RPC_LOCKPROG:	case RPC_NETLOCKPROG:	case RPC_X25PROG:	case RPC_STATMON1PROG:	case RPC_STATMON2PROG:	case RPC_SELNLIBPROG:	case RPC_BOOTPARAMPROG:	case RPC_MAZEPROG:	case RPC_YPUPDATEPROG:	case RPC_KEYSERVEPROG:	case RPC_SECURECMDPROG:	case RPC_NETFWDIPROG:	case RPC_NETFWDTPROG:	case RPC_SUNLINKMAP_PROG:	case RPC_NETMONPROG:	case RPC_DBASEPROG:	case RPC_PWDAUTHPROG:	case RPC_TFSPROG:	case RPC_NSEPROG:	case RPC_NSE_ACTIVATE_PROG:	case RPC_PCNFSDPROG:	case RPC_PYRAMIDLOCKINGPROG:	case RPC_PYRAMIDSYS5:	case RPC_CADDS_IMAGE:	case RPC_ADT_RFLOCKPROG:#endif /* notdef */	default:		pkt_counters[PKT_OTHERRPC].pc_interval++;		pkt_counters[PKT_OTHERRPC].pc_total++;		break;	}}/* * rpc_replyfilter - count RPC reply packets. */voidrpc_replyfilter(data, length, src, dst)register u_long src, dst;register u_int length;register char *data;{	register struct rpc_msg *msg;	msg = (struct rpc_msg *) data;	pkt_counters[PKT_RPCAUTH].pc_interval++;	pkt_counters[PKT_RPCAUTH].pc_total++;}/* * nfs_filter - filter NFS packets. */voidnfs_filter(data, length, src, dst)register u_long src, dst;register u_int length;register char *data;{	u_int proc;	caddr_t args;	SVCXPRT *xprt;	struct rpc_msg msg;	union nfs_rfsargs nfs_rfsargs;	char cred_area[2*MAX_AUTH_BYTES];	msg.rm_call.cb_cred.oa_base = cred_area;	msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);	/*	 * Act as if we received this packet through RPC.	 */	if (!udprpc_recv(data, length, &msg, &xprt))		return;	/*	 * Get the NFS procedure number.	 */	proc = msg.rm_call.cb_proc;	if (proc >= RFS_NPROC)		return;	/*	 * Now decode the arguments to the procedure from	 * XDR format.	 */	args = (caddr_t) &nfs_rfsargs;	(void) bzero(args, nfs_procs[proc].nfs_argsz);	if (!SVC_GETARGS(xprt, nfs_procs[proc].nfs_xdrargs, args))		return;	prc_counters[prc_countmap[proc]].pr_total++;	prc_counters[prc_countmap[proc]].pr_interval++;	CountSrc(src);	/*	 * Now count the packet in the appropriate file system's	 * counters.	 */	switch (proc) {	case RFS_NULL:		break;	case RFS_GETATTR:		nfs_count(&nfs_rfsargs.fhandle, proc);		break;	case RFS_SETATTR:		nfs_count(&nfs_rfsargs.nfssaargs.saa_fh, proc);		break;	case RFS_ROOT:		break;	case RFS_LOOKUP:		nfs_count(&nfs_rfsargs.nfsdiropargs.da_fhandle, proc);		break;	case RFS_READLINK:		nfs_count(&nfs_rfsargs.fhandle, proc);		break;	case RFS_READ:		nfs_count(&nfs_rfsargs.nfsreadargs.ra_fhandle, proc);		break;	case RFS_WRITECACHE:		break;	case RFS_WRITE:		nfs_count(&nfs_rfsargs.nfswriteargs.wa_fhandle, proc);		break;	case RFS_CREATE:		nfs_count(&nfs_rfsargs.nfscreatargs.ca_da.da_fhandle, proc);		break;	case RFS_REMOVE:		nfs_count(&nfs_rfsargs.nfsdiropargs.da_fhandle, proc);		break;	case RFS_RENAME:		nfs_count(&nfs_rfsargs.nfsrnmargs.rna_from.da_fhandle, proc);		break;	case RFS_LINK:		nfs_count(&nfs_rfsargs.nfslinkargs.la_from, proc);		break;	case RFS_SYMLINK:		nfs_count(&nfs_rfsargs.nfsslargs.sla_from.da_fhandle, proc);		break;	case RFS_MKDIR:		nfs_count(&nfs_rfsargs.nfscreatargs.ca_da.da_fhandle, proc);		break;	case RFS_RMDIR:		nfs_count(&nfs_rfsargs.nfsdiropargs.da_fhandle, proc);		break;	case RFS_READDIR:		nfs_count(&nfs_rfsargs.nfsrddirargs.rda_fh, proc);		break;	case RFS_STATFS:		nfs_count(&nfs_rfsargs.fhandle, proc);		break;	}	/*	 * Decide whether it's a read or write process.	 */	switch (nfs_procs[proc].nfs_proctype) {	case NFS_READ:		pkt_counters[PKT_NFSREAD].pc_interval++;		pkt_counters[PKT_NFSREAD].pc_total++;		break;	case NFS_WRITE:		pkt_counters[PKT_NFSWRITE].pc_interval++;		pkt_counters[PKT_NFSWRITE].pc_total++;		break;	}}/* * nfs_count - count an NFS reference to a specific file system. */voidnfs_count(fh, proc)register fhandle_t *fh;int proc;{	long fsid;	register int i, match1, match2;	/*	 * Run through the NFS counters looking for the matching	 * file system.	 */	match1 = 0;	for (i = 0; i < nnfscounters; i++) {		if (learnfs)			fsid = nfs_counters[i].nc_fsid;		else			fsid = (long) nfs_counters[i].nc_dev;		/*		 * Compare the device numbers.  Sun uses an		 * fsid_t for the device number, which is an		 * array of 2 longs.  The first long contains		 * the device number.		 */		match1 = !bcmp((char *) &(fh->fh_fsid), (char *) &fsid,			sizeof(long));		/*		 * Check server address.		 */		if (allflag && match1)			match1 = (thisdst == nfs_counters[i].nc_ipaddr);		if (match1) {			nfs_counters[i].nc_proc[proc]++;			nfs_counters[i].nc_interval++;			nfs_counters[i].nc_total++;			break;		}	}	/*	 * We don't know about this file system, but we can	 * learn.	 */	if (!match1 && learnfs && (nnfscounters < MAXEXPORT)) {		static char fsname[64], prefix[64];		long fsid;		int oldm;		oldm = sigblock(sigmask(SIGALRM));	    				/* no redisplay while unstable */		i = nnfscounters++;		bcopy((char *) &(fh->fh_fsid), (char *) &fsid, sizeof(long));		nfs_counters[i].nc_fsid = fsid;		nfs_counters[i].nc_proc[proc]++;		nfs_counters[i].nc_interval++;		nfs_counters[i].nc_total++;		/*		 * See if server uses opposite byte order.		 */		if ((fsid & 0xffff0000) && ((fsid & 0xffff) == 0))			fsid = ntohl(fsid);		/*		 * Some hosts use 32-bit values.		 */		if (fsid & 0xffff0000) {			/*			 * Try to intuit the byte order.			 */			if (fsid & 0xff00) {			  nfs_counters[i].nc_dev = makedev((fsid >> 8) & 0xff,							   (fsid >> 24) & 0xff);			}			else {			  nfs_counters[i].nc_dev = makedev((fsid >> 16) & 0xff,							   fsid & 0xff);			}		}		else {			nfs_counters[i].nc_dev = makedev(major(fsid),							 minor(fsid));		}		*prefix = 0;		if (allflag) {			struct hostent *hp;			nfs_counters[i].nc_ipaddr = thisdst;			hp = gethostbyaddr(&thisdst, sizeof(thisdst), AF_INET);			if (hp) {				char *index();				char *dotp;				sprintf(prefix, "%s", hp->h_name);				if ((dotp = index(prefix, '.')) != NULL)					*dotp = 0;			}			else {				struct in_addr ia;				ia.s_addr = thisdst;				sprintf(prefix, "%s", inet_ntoa(ia));			}		}		sprintf(fsname, "%.12s(%d,%d)", prefix,			major(nfs_counters[i].nc_dev),			minor(nfs_counters[i].nc_dev));		nfs_counters[i].nc_name = savestr(fsname);		sort_nfs_counters();		(void) sigsetmask(oldm);	/* permit redisplay */	}	if (filelist == NULL)		return;	/*	 * Run through the file counters looking for the matching	 * file.	 */	for (i = 0; i < nfilecounters; i++) {		fsid = (long) fil_counters[i].fc_dev;		/*		 * Compare device numbers and file numbers.  Sun		 * uses an fsid_t for the device, which is an		 * array of two longs.  They use an fid for the		 * inode.  The inode number is the first part		 * of this.		 */		match1 = !bcmp((char *) &(fh->fh_fsid), (char *) &fsid,			 sizeof(long));		if (!match1)			continue;#ifdef sun		/*		 * NOTE: this is dependent on the contents of the fh_data		 *       part of the file handle.  This is correct for		 *       SunOS 4.1 on SPARCs.		 */		match2 = !bcmp((char *) &(fh->fh_data[2]),			 (char *) &(fil_counters[i].fc_ino), sizeof(ino_t));#endif /* sun */#ifdef ultrix		match2 = !bcmp((char *) fh->fh_fno,			 (char *) &(fil_counters[i].fc_ino), sizeof(ino_t));#endif /* ultrix */		if (match2) {			fil_counters[i].fc_proc[proc]++;			fil_counters[i].fc_interval++;			fil_counters[i].fc_total++;			break;		}	}}/* * CountSrc uses a hash table to speed lookups.  Hash function *	uses high and low octect of IP address, so as to be *	fast and byte-order independent.  Table is organized *	as a array of linked lists. */#define	HASHSIZE	0x100#define	HASH(addr)	(((addr) & 0xFF) ^ (((addr) >> 24) & 0xFF))ClientCounter *Addr_hashtable[HASHSIZE];	/* initially all NULL ptrs */ClientCounter *cc_hint = clnt_counters;		/* one-element cache */CountSrc(src)register u_long src;{	register ClientCounter *ccp;	int hcode = HASH(src);		/* See if this is the same client as last time */	if (cc_hint->cl_ipaddr == src) {	    cc_hint->cl_total++;	    cc_hint->cl_interval++;	    return;	}	/* Search hash table */	ccp = Addr_hashtable[hcode];	while (ccp) {	    if (ccp->cl_ipaddr == src) {		ccp->cl_total++;		ccp->cl_interval++;		cc_hint = ccp;		return;	    }	    ccp = ccp->cl_next;	}		/* new client */	if (nclientcounters < MAXCLIENTS) {	    struct hostent *hp;	    static char clnt_name[64];	    int oldm;	    	    oldm = sigblock(sigmask(SIGALRM));	    				/* no redisplay while unstable */	    	    ccp = &(clnt_counters[nclientcounters]);	    nclientcounters++;	    	    /* Add to hash table */	    ccp->cl_next = Addr_hashtable[hcode];	    Addr_hashtable[hcode] = ccp;	    /* Fill in new ClientCounter */	    ccp->cl_ipaddr = src;	    hp = gethostbyaddr(&ccp->cl_ipaddr,					sizeof(ccp->cl_ipaddr), AF_INET);	    if (hp) {		char *index();		char *dotp;		sprintf(clnt_name, "%s", hp->h_name);		if ((dotp = index(clnt_name, '.')) != NULL)			*dotp = 0;	    }	    else {		struct in_addr ia;		ia.s_addr = ccp->cl_ipaddr;		sprintf(clnt_name, "%s", inet_ntoa(ia));	    }	    ccp->cl_name = savestr(clnt_name);	    ccp->cl_total = 1;	    ccp->cl_interval = 1;	    sort_clnt_counters();	    (void) sigsetmask(oldm);	/* permit redisplay */	}}/* * Must be called after sorting the clnt_counters[] table *	Should put busiest ones at front of list, but doesn't */ClientHashRebuild(){	register int i;	register ClientCounter *ccp;	int hcode;	bzero(Addr_hashtable, sizeof(Addr_hashtable));		for (i = 0, ccp = clnt_counters; i < nclientcounters; i++, ccp++) {	    hcode = HASH(ccp->cl_ipaddr);	    ccp->cl_next = Addr_hashtable[hcode];	    Addr_hashtable[hcode] = ccp;	}}

⌨️ 快捷键说明

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