⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mountd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1989, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Herb Hasler and Rick Macklem at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char copyright[] ="@(#) Copyright (c) 1989, 1993\n\	The Regents of the University of California.  All rights reserved.\n";#endif not lint#ifndef lintstatic char sccsid[] = "@(#)mountd.c	8.8 (Berkeley) 2/20/94";#endif not lint#include <sys/param.h>#include <sys/file.h>#include <sys/ioctl.h>#include <sys/mount.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/syslog.h>#include <sys/ucred.h>#include <rpc/rpc.h>#include <rpc/pmap_clnt.h>#include <rpc/pmap_prot.h>#ifdef ISO#include <netiso/iso.h>#endif#include <nfs/rpcv2.h>#include <nfs/nfsv2.h>#include <arpa/inet.h>#include <ctype.h>#include <errno.h>#include <grp.h>#include <netdb.h>#include <pwd.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include "pathnames.h"#ifdef DEBUG#include <stdarg.h>#endif/* * Structures for keeping the mount list and export list */struct mountlist {	struct mountlist *ml_next;	char	ml_host[RPCMNT_NAMELEN+1];	char	ml_dirp[RPCMNT_PATHLEN+1];};struct dirlist {	struct dirlist	*dp_left;	struct dirlist	*dp_right;	int		dp_flag;	struct hostlist	*dp_hosts;	/* List of hosts this dir exported to */	char		dp_dirp[1];	/* Actually malloc'd to size of dir */};/* dp_flag bits */#define	DP_DEFSET	0x1struct exportlist {	struct exportlist *ex_next;	struct dirlist	*ex_dirl;	struct dirlist	*ex_defdir;	int		ex_flag;	fsid_t		ex_fs;	char		*ex_fsdir;};/* ex_flag bits */#define	EX_LINKED	0x1struct netmsk {	u_long	nt_net;	u_long	nt_mask;	char *nt_name;};union grouptypes {	struct hostent *gt_hostent;	struct netmsk	gt_net;#ifdef ISO	struct sockaddr_iso *gt_isoaddr;#endif};struct grouplist {	int gr_type;	union grouptypes gr_ptr;	struct grouplist *gr_next;};/* Group types */#define	GT_NULL		0x0#define	GT_HOST		0x1#define	GT_NET		0x2#define	GT_ISO		0x4struct hostlist {	struct grouplist *ht_grp;	struct hostlist	 *ht_next;};/* Global defs */char	*add_expdir __P((struct dirlist **, char *, int));void	add_dlist __P((struct dirlist **, struct dirlist *,				struct grouplist *));void	add_mlist __P((char *, char *));int	check_dirpath __P((char *));int	check_options __P((struct dirlist *));int	chk_host __P((struct dirlist *, u_long, int *));void	del_mlist __P((char *, char *));struct dirlist *dirp_search __P((struct dirlist *, char *));int	do_mount __P((struct exportlist *, struct grouplist *, int,				struct ucred *, char *, int, struct statfs *));int	do_opt __P((char **, char **, struct exportlist *, struct grouplist *,				int *, int *, struct ucred *));struct	exportlist *ex_search __P((fsid_t *));struct	exportlist *get_exp __P((void));void	free_dir __P((struct dirlist *));void	free_exp __P((struct exportlist *));void	free_grp __P((struct grouplist *));void	free_host __P((struct hostlist *));void	get_exportlist __P((void));int	get_host __P((char *, struct grouplist *));struct hostlist *get_ht __P((void));int	get_line __P((void));void	get_mountlist __P((void));int	get_net __P((char *, struct netmsk *, int));void	getexp_err __P((struct exportlist *, struct grouplist *));struct grouplist *get_grp __P((void));void	hang_dirp __P((struct dirlist *, struct grouplist *,				struct exportlist *, int));void	mntsrv __P((struct svc_req *, SVCXPRT *));void	nextfield __P((char **, char **));void	out_of_mem __P((void));void	parsecred __P((char *, struct ucred *));int	put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *));int	scan_tree __P((struct dirlist *, u_long));void	send_umntall __P((void));int	umntall_each __P((caddr_t, struct sockaddr_in *));int	xdr_dir __P((XDR *, char *));int	xdr_explist __P((XDR *, caddr_t));int	xdr_fhs __P((XDR *, nfsv2fh_t *));int	xdr_mlist __P((XDR *, caddr_t));/* C library */int	getnetgrent();void	endnetgrent();void	setnetgrent();#ifdef ISOstruct iso_addr *iso_addr();#endifstruct exportlist *exphead;struct mountlist *mlhead;struct grouplist *grphead;char exname[MAXPATHLEN];struct ucred def_anon = {	1,	(uid_t) -2,	1,	{ (gid_t) -2 }};int root_only = 1;int opt_flags;/* Bits for above */#define	OP_MAPROOT	0x01#define	OP_MAPALL	0x02#define	OP_KERB		0x04#define	OP_MASK		0x08#define	OP_NET		0x10#define	OP_ISO		0x20#define	OP_ALLDIRS	0x40#ifdef DEBUGint debug = 1;void	SYSLOG __P((int, const char *, ...));#define syslog SYSLOG#elseint debug = 0;#endif/* * Mountd server for NFS mount protocol as described in: * NFS: Network File System Protocol Specification, RFC1094, Appendix A * The optional arguments are the exports file name * default: _PATH_EXPORTS * and "-n" to allow nonroot mount. */intmain(argc, argv)	int argc;	char **argv;{	SVCXPRT *transp;	int c;	while ((c = getopt(argc, argv, "n")) != EOF)		switch (c) {		case 'n':			root_only = 0;			break;		default:			fprintf(stderr, "Usage: mountd [-n] [export_file]\n");			exit(1);		};	argc -= optind;	argv += optind;	grphead = (struct grouplist *)NULL;	exphead = (struct exportlist *)NULL;	mlhead = (struct mountlist *)NULL;	if (argc == 1) {		strncpy(exname, *argv, MAXPATHLEN-1);		exname[MAXPATHLEN-1] = '\0';	} else		strcpy(exname, _PATH_EXPORTS);	openlog("mountd", LOG_PID, LOG_DAEMON);	if (debug)		fprintf(stderr,"Getting export list.\n");	get_exportlist();	if (debug)		fprintf(stderr,"Getting mount list.\n");	get_mountlist();	if (debug)		fprintf(stderr,"Here we go.\n");	if (debug == 0) {		daemon(0, 0);		signal(SIGINT, SIG_IGN);		signal(SIGQUIT, SIG_IGN);	}	signal(SIGHUP, (void (*) __P((int))) get_exportlist);	signal(SIGTERM, (void (*) __P((int))) send_umntall);	{ FILE *pidfile = fopen(_PATH_MOUNTDPID, "w");	  if (pidfile != NULL) {		fprintf(pidfile, "%d\n", getpid());		fclose(pidfile);	  }	}	if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL) {		syslog(LOG_ERR, "Can't create socket");		exit(1);	}	pmap_unset(RPCPROG_MNT, RPCMNT_VER1);	if (!svc_register(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv,	    IPPROTO_UDP)) {		syslog(LOG_ERR, "Can't register mount");		exit(1);	}	svc_run();	syslog(LOG_ERR, "Mountd died");	exit(1);}/* * The mount rpc service */voidmntsrv(rqstp, transp)	struct svc_req *rqstp;	SVCXPRT *transp;{	struct exportlist *ep;	struct dirlist *dp;	nfsv2fh_t nfh;	struct authunix_parms *ucr;	struct stat stb;	struct statfs fsb;	struct hostent *hp;	u_long saddr;	char rpcpath[RPCMNT_PATHLEN+1], dirpath[MAXPATHLEN];	int bad = ENOENT, omask, defset;	uid_t uid = -2;	/* Get authorization */	switch (rqstp->rq_cred.oa_flavor) {	case AUTH_UNIX:		ucr = (struct authunix_parms *)rqstp->rq_clntcred;		uid = ucr->aup_uid;		break;	case AUTH_NULL:	default:		break;	}	saddr = transp->xp_raddr.sin_addr.s_addr;	hp = (struct hostent *)NULL;	switch (rqstp->rq_proc) {	case NULLPROC:		if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL))			syslog(LOG_ERR, "Can't send reply");		return;	case RPCMNT_MOUNT:		if ((uid != 0 && root_only) || uid == -2) {			svcerr_weakauth(transp);			return;		}		if (!svc_getargs(transp, xdr_dir, rpcpath)) {			svcerr_decode(transp);			return;		}		/*		 * Get the real pathname and make sure it is a directory		 * that exists.		 */		if (realpath(rpcpath, dirpath) == 0 ||		    stat(dirpath, &stb) < 0 ||		    (stb.st_mode & S_IFMT) != S_IFDIR ||		    statfs(dirpath, &fsb) < 0) {			chdir("/");	/* Just in case realpath doesn't */			if (debug)				fprintf(stderr, "stat failed on %s\n", dirpath);			if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))				syslog(LOG_ERR, "Can't send reply");			return;		}		/* Check in the exports list */		omask = sigblock(sigmask(SIGHUP));		ep = ex_search(&fsb.f_fsid);		defset = 0;		if (ep && (chk_host(ep->ex_defdir, saddr, &defset) ||		    ((dp = dirp_search(ep->ex_dirl, dirpath)) &&		     chk_host(dp, saddr, &defset)) ||		     (defset && scan_tree(ep->ex_defdir, saddr) == 0 &&		      scan_tree(ep->ex_dirl, saddr) == 0))) {			/* Get the file handle */			bzero((caddr_t)&nfh, sizeof(nfh));			if (getfh(dirpath, (fhandle_t *)&nfh) < 0) {				bad = errno;				syslog(LOG_ERR, "Can't get fh for %s", dirpath);				if (!svc_sendreply(transp, xdr_long,				    (caddr_t)&bad))					syslog(LOG_ERR, "Can't send reply");				sigsetmask(omask);				return;			}			if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh))				syslog(LOG_ERR, "Can't send reply");			if (hp == NULL)				hp = gethostbyaddr((caddr_t)&saddr,				    sizeof(saddr), AF_INET);			if (hp)				add_mlist(hp->h_name, dirpath);			else				add_mlist(inet_ntoa(transp->xp_raddr.sin_addr),					dirpath);			if (debug)				fprintf(stderr,"Mount successfull.\n");		} else {			bad = EACCES;			if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))				syslog(LOG_ERR, "Can't send reply");		}		sigsetmask(omask);		return;	case RPCMNT_DUMP:		if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL))			syslog(LOG_ERR, "Can't send reply");		return;	case RPCMNT_UMOUNT:		if ((uid != 0 && root_only) || uid == -2) {			svcerr_weakauth(transp);			return;		}		if (!svc_getargs(transp, xdr_dir, dirpath)) {			svcerr_decode(transp);			return;		}		if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL))			syslog(LOG_ERR, "Can't send reply");		hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);		if (hp)			del_mlist(hp->h_name, dirpath);		del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath);		return;	case RPCMNT_UMNTALL:		if ((uid != 0 && root_only) || uid == -2) {			svcerr_weakauth(transp);			return;		}		if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL))			syslog(LOG_ERR, "Can't send reply");		hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);		if (hp)			del_mlist(hp->h_name, (char *)NULL);		del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), (char *)NULL);		return;	case RPCMNT_EXPORT:		if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL))			syslog(LOG_ERR, "Can't send reply");		return;	default:		svcerr_noproc(transp);		return;	}}/* * Xdr conversion for a dirpath string */intxdr_dir(xdrsp, dirp)	XDR *xdrsp;	char *dirp;{	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));}/* * Xdr routine to generate fhstatus */intxdr_fhs(xdrsp, nfh)	XDR *xdrsp;	nfsv2fh_t *nfh;{	int ok = 0;	if (!xdr_long(xdrsp, &ok))		return (0);	return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH));}intxdr_mlist(xdrsp, cp)	XDR *xdrsp;	caddr_t cp;{	struct mountlist *mlp;	int true = 1;	int false = 0;	char *strp;	mlp = mlhead;	while (mlp) {		if (!xdr_bool(xdrsp, &true))			return (0);		strp = &mlp->ml_host[0];		if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))			return (0);		strp = &mlp->ml_dirp[0];		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))			return (0);		mlp = mlp->ml_next;	}	if (!xdr_bool(xdrsp, &false))		return (0);	return (1);}/* * Xdr conversion for export list */intxdr_explist(xdrsp, cp)	XDR *xdrsp;	caddr_t cp;{	struct exportlist *ep;	int false = 0;	int omask, putdef;	omask = sigblock(sigmask(SIGHUP));	ep = exphead;	while (ep) {		putdef = 0;		if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, &putdef))			goto errout;		if (ep->ex_defdir && putdef == 0 &&			put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL,			&putdef))			goto errout;		ep = ep->ex_next;	}	sigsetmask(omask);	if (!xdr_bool(xdrsp, &false))		return (0);	return (1);errout:	sigsetmask(omask);	return (0);}/* * Called from xdr_explist() to traverse the tree and export the * directory paths. */intput_exlist(dp, xdrsp, adp, putdefp)	struct dirlist *dp;	XDR *xdrsp;	struct dirlist *adp;	int *putdefp;{	struct grouplist *grp;	struct hostlist *hp;	int true = 1;	int false = 0;	int gotalldir = 0;	char *strp;	if (dp) {		if (put_exlist(dp->dp_left, xdrsp, adp, putdefp))			return (1);		if (!xdr_bool(xdrsp, &true))			return (1);		strp = dp->dp_dirp;		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))			return (1);		if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) {			gotalldir = 1;			*putdefp = 1;		}		if ((dp->dp_flag & DP_DEFSET) == 0 &&		    (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) {			hp = dp->dp_hosts;			while (hp) {				grp = hp->ht_grp;				if (grp->gr_type == GT_HOST) {					if (!xdr_bool(xdrsp, &true))						return (1);					strp = grp->gr_ptr.gt_hostent->h_name;					if (!xdr_string(xdrsp, &strp, 					    RPCMNT_NAMELEN))						return (1);				} else if (grp->gr_type == GT_NET) {					if (!xdr_bool(xdrsp, &true))						return (1);					strp = grp->gr_ptr.gt_net.nt_name;					if (!xdr_string(xdrsp, &strp, 					    RPCMNT_NAMELEN))						return (1);				}				hp = hp->ht_next;				if (gotalldir && hp == (struct hostlist *)NULL) {					hp = adp->dp_hosts;					gotalldir = 0;				}			}		}		if (!xdr_bool(xdrsp, &false))			return (1);		if (put_exlist(dp->dp_right, xdrsp, adp, putdefp))			return (1);	}	return (0);}#define LINESIZ	10240char line[LINESIZ];FILE *exp_file;/* * Get the export list */voidget_exportlist(){	struct exportlist *ep, *ep2;	struct grouplist *grp, *tgrp;	struct exportlist **epp;	struct dirlist *dirhead;	struct statfs fsb, *fsp;	struct hostent *hpe;	struct ucred anon;	char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc;	int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp;	/*	 * First, get rid of the old list	 */	ep = exphead;	while (ep) {		ep2 = ep;		ep = ep->ex_next;		free_exp(ep2);	}	exphead = (struct exportlist *)NULL;	grp = grphead;	while (grp) {		tgrp = grp;		grp = grp->gr_next;		free_grp(tgrp);	}	grphead = (struct grouplist *)NULL;	/*	 * And delete exports that are in the kernel for all local	 * file systems.	 * XXX: Should know how to handle all local exportable file systems	 *      instead of just MOUNT_UFS.	 */	num = getmntinfo(&fsp, MNT_NOWAIT);	for (i = 0; i < num; i++) {		union {			struct ufs_args ua;			struct iso_args ia;			struct mfs_args ma;		} targs;		switch (fsp->f_type) {		case MOUNT_MFS:		case MOUNT_UFS:		case MOUNT_CD9660:			targs.ua.fspec = NULL;			targs.ua.export.ex_flags = MNT_DELEXPORT;			if (mount(fsp->f_type, fsp->f_mntonname,				  fsp->f_flags | MNT_UPDATE,				  (caddr_t)&targs) < 0)				syslog(LOG_ERR, "Can't delete exports for %s",				       fsp->f_mntonname);		}		fsp++;	}	/*	 * Read in the exports file and build the list, calling	 * mount() as we go along to push the export rules into the kernel.	 */	if ((exp_file = fopen(exname, "r")) == NULL) {		syslog(LOG_ERR, "Can't open %s", exname);		exit(2);	}	dirhead = (struct dirlist *)NULL;	while (get_line()) {		if (debug)

⌨️ 快捷键说明

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