xref: /csrg-svn/sbin/mountd/mountd.c (revision 39681)
138460Smckusick /*
238460Smckusick  * Copyright (c) 1989 The Regents of the University of California.
338460Smckusick  * All rights reserved.
438460Smckusick  *
538460Smckusick  * This code is derived from software contributed to Berkeley by
638460Smckusick  * Rick Macklem at The University of Guelph.
738460Smckusick  *
838460Smckusick  * Redistribution and use in source and binary forms are permitted
938460Smckusick  * provided that the above copyright notice and this paragraph are
1038460Smckusick  * duplicated in all such forms and that any documentation,
1138460Smckusick  * advertising materials, and other materials related to such
1238460Smckusick  * distribution and use acknowledge that the software was developed
1338460Smckusick  * by the University of California, Berkeley.  The name of the
1438460Smckusick  * University may not be used to endorse or promote products derived
1538460Smckusick  * from this software without specific prior written permission.
1638460Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1738460Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1838460Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1938460Smckusick  */
2038460Smckusick 
2138460Smckusick #ifndef lint
2238460Smckusick char copyright[] =
2338460Smckusick "@(#) Copyright (c) 1989 Regents of the University of California.\n\
2438460Smckusick  All rights reserved.\n";
2538460Smckusick #endif not lint
2638460Smckusick 
2738460Smckusick #ifndef lint
28*39681Smckusick static char sccsid[] = "@(#)mountd.c	5.2 (Berkeley) 11/30/89";
2938460Smckusick #endif not lint
3038460Smckusick 
3138460Smckusick #include <stdio.h>
3238460Smckusick #include <strings.h>
3338460Smckusick #include <syslog.h>
3438460Smckusick #include <signal.h>
3538460Smckusick #include <fcntl.h>
3638460Smckusick #include <sys/param.h>
3738460Smckusick #include <sys/types.h>
3838460Smckusick #include <sys/ioctl.h>
3938460Smckusick #include <sys/stat.h>
40*39681Smckusick #include <sys/file.h>
4138460Smckusick #include <sys/dir.h>
4238460Smckusick #include <sys/uio.h>
4338460Smckusick #include <sys/namei.h>
4438460Smckusick #include <sys/mount.h>
4538460Smckusick #include <sys/socket.h>
4638460Smckusick #include <sys/socketvar.h>
4738460Smckusick #include <sys/errno.h>
4838460Smckusick #include <netdb.h>
4938460Smckusick #include <rpc/rpc.h>
5038460Smckusick #include <rpc/pmap_clnt.h>
5138460Smckusick #include <rpc/pmap_prot.h>
5238460Smckusick #include <nfs/rpcv2.h>
5338460Smckusick #include <nfs/nfsv2.h>
54*39681Smckusick #include "pathnames.h"
5538460Smckusick 
5638460Smckusick struct ufid {
5738460Smckusick 	u_short	ufid_len;
5838460Smckusick 	ino_t	ufid_ino;
5938460Smckusick 	long	ufid_gen;
6038460Smckusick };
6138460Smckusick /*
6238460Smckusick  * Structures for keeping the mount list and export list
6338460Smckusick  */
6438460Smckusick struct mountlist {
6538460Smckusick 	char	ml_host[RPCMNT_NAMELEN+1];
6638460Smckusick 	char	ml_dirp[RPCMNT_PATHLEN+1];
6738460Smckusick };
6838460Smckusick 
6938460Smckusick struct exportlist {
7038460Smckusick 	struct exportlist *ex_next;
7138460Smckusick 	struct exportlist *ex_prev;
7238460Smckusick 	struct grouplist *ex_groups;
7338460Smckusick 	int	ex_rootuid;
7438460Smckusick 	int	ex_exflags;
7538460Smckusick 	char	ex_dirp[RPCMNT_PATHLEN+1];
7638460Smckusick };
7738460Smckusick 
7838460Smckusick struct grouplist {
7938460Smckusick 	struct grouplist *gr_next;
80*39681Smckusick 	struct hostent *gr_hp;
8138460Smckusick };
8238460Smckusick 
8338460Smckusick /* Global defs */
8438460Smckusick int xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist();
8538460Smckusick int mntsrv(), get_exportlist();
8638460Smckusick struct exportlist exphead;
87*39681Smckusick int mlfile;
8838460Smckusick char exname[MAXPATHLEN];
8938460Smckusick int def_rootuid = -2;
9038460Smckusick extern int errno;
9138460Smckusick #ifdef DEBUG
9238460Smckusick int debug = 1;
9338460Smckusick #else
9438460Smckusick int debug = 0;
9538460Smckusick #endif
9638460Smckusick 
9738460Smckusick /*
9838460Smckusick  * Mountd server for NFS mount protocol as described in:
99*39681Smckusick  * NFS: Network File System Protocol Specification, RFC1094, Appendix A
10038460Smckusick  * The optional argument is the exports file name
101*39681Smckusick  * default: _PATH_EXPORTS
10238460Smckusick  */
10338460Smckusick main(argc, argv)
10438460Smckusick 	int argc;
10538460Smckusick 	char *argv[];
10638460Smckusick {
10738460Smckusick 	SVCXPRT *transp;
10838460Smckusick 
10938460Smckusick 	if (debug == 0) {
11038460Smckusick 		if (fork())
11138460Smckusick 			exit(0);
11238460Smckusick 		{ int s;
11338460Smckusick 		for (s = 0; s < 10; s++)
11438460Smckusick 			(void) close(s);
11538460Smckusick 		}
11638460Smckusick 		(void) open("/", O_RDONLY);
11738460Smckusick 		(void) dup2(0, 1);
11838460Smckusick 		(void) dup2(0, 2);
11938460Smckusick 		{ int tt = open("/dev/tty", O_RDWR);
12038460Smckusick 		  if (tt > 0) {
12138460Smckusick 			ioctl(tt, TIOCNOTTY, (char *)0);
12238460Smckusick 			close(tt);
12338460Smckusick 		  }
12438460Smckusick 		}
12538460Smckusick 		(void) setpgrp(0, 0);
12638460Smckusick 		signal(SIGTSTP, SIG_IGN);
12738460Smckusick 		signal(SIGTTIN, SIG_IGN);
12838460Smckusick 		signal(SIGTTOU, SIG_IGN);
12938460Smckusick 		signal(SIGINT, SIG_IGN);
13038460Smckusick 		signal(SIGQUIT, SIG_IGN);
13138460Smckusick 		signal(SIGTERM, SIG_IGN);
13238460Smckusick 	}
13338460Smckusick 	openlog("mountd:", LOG_PID, LOG_DAEMON);
13438460Smckusick 	exphead.ex_next = exphead.ex_prev = (struct exportlist *)0;
13538460Smckusick 	if (argc == 2) {
13638460Smckusick 		strncpy(exname, argv[1], MAXPATHLEN-1);
13738460Smckusick 		exname[MAXPATHLEN-1] = '\0';
13838460Smckusick 	} else
139*39681Smckusick 		strcpy(exname, _PATH_EXPORTS);
14038460Smckusick 	get_exportlist();
14138460Smckusick 	signal(SIGHUP, get_exportlist);
142*39681Smckusick 	if ((mlfile = open(_PATH_RMOUNTLIST, (O_RDWR|O_CREAT), 0600)) < 0) {
143*39681Smckusick 		syslog(LOG_ERR, "Can't open mountlist file");
144*39681Smckusick 		exit(1);
145*39681Smckusick 	}
14638460Smckusick 	if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL) {
14738460Smckusick 		syslog(LOG_ERR, "Can't create socket");
14838460Smckusick 		exit(1);
14938460Smckusick 	}
15038460Smckusick 	pmap_unset(RPCPROG_MNT, RPCMNT_VER1);
15138460Smckusick 	if (!svc_register(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv, IPPROTO_UDP)) {
15238460Smckusick 		syslog(LOG_ERR, "Can't register mount");
15338460Smckusick 		exit(1);
15438460Smckusick 	}
15538460Smckusick 	svc_run();
15638460Smckusick 	syslog(LOG_ERR, "Mountd died");
15738460Smckusick }
15838460Smckusick 
15938460Smckusick /*
16038460Smckusick  * The mount rpc service
16138460Smckusick  */
16238460Smckusick mntsrv(rqstp, transp)
16338460Smckusick 	register struct svc_req *rqstp;
16438460Smckusick 	register SVCXPRT *transp;
16538460Smckusick {
166*39681Smckusick 	register struct grouplist *grp;
167*39681Smckusick 	register u_long **addrp;
16838460Smckusick 	register struct exportlist *ep;
169*39681Smckusick 	struct mountlist ml;
17038460Smckusick 	nfsv2fh_t nfh;
17138460Smckusick 	struct authunix_parms *ucr;
17238460Smckusick 	struct stat stb;
17338460Smckusick 	struct hostent *hp;
174*39681Smckusick 	u_long saddr;
17538460Smckusick 	char dirpath[RPCMNT_PATHLEN+1];
17638460Smckusick 	int ok = 0;
17738460Smckusick 	int bad = ENOENT;
17838460Smckusick 	int omask;
179*39681Smckusick 	uid_t uid = -2;
18038460Smckusick 
18138460Smckusick 	/* Get authorization */
18238460Smckusick 	switch (rqstp->rq_cred.oa_flavor) {
18338460Smckusick 	case AUTH_UNIX:
18438460Smckusick 		ucr = (struct authunix_parms *)rqstp->rq_clntcred;
185*39681Smckusick 		uid = ucr->aup_uid;
186*39681Smckusick 		break;
18738460Smckusick 	case AUTH_NULL:
18838460Smckusick 	default:
189*39681Smckusick 		break;
19038460Smckusick 	}
19138460Smckusick 
192*39681Smckusick 	saddr = transp->xp_raddr.sin_addr.s_addr;
193*39681Smckusick 	hp = (struct hostent *)0;
19438460Smckusick 	switch (rqstp->rq_proc) {
195*39681Smckusick 	case NULLPROC:
196*39681Smckusick 		if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
197*39681Smckusick 			syslog(LOG_ERR, "Can't send reply");
198*39681Smckusick 		return;
19938460Smckusick 	case RPCMNT_MOUNT:
200*39681Smckusick 		if (uid != 0) {
201*39681Smckusick 			svcerr_weakauth(transp);
202*39681Smckusick 			return;
203*39681Smckusick 		}
20438460Smckusick 		if (!svc_getargs(transp, xdr_dir, dirpath)) {
20538460Smckusick 			svcerr_decode(transp);
20638460Smckusick 			return;
20738460Smckusick 		}
20838460Smckusick 
20938460Smckusick 		/* Check to see if it's a valid dirpath */
21038460Smckusick 		if (stat(dirpath, &stb) < 0 || (stb.st_mode&S_IFMT) !=
21138460Smckusick 			S_IFDIR) {
21238460Smckusick 			if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
21338460Smckusick 				syslog(LOG_ERR, "Can't send reply");
21438460Smckusick 			return;
21538460Smckusick 		}
21638460Smckusick 
21738460Smckusick 		/* Check in the exports list */
21838460Smckusick 		omask = sigblock(sigmask(SIGHUP));
21938460Smckusick 		ep = exphead.ex_next;
22038460Smckusick 		while (ep != NULL) {
22138460Smckusick 			if (!strcmp(ep->ex_dirp, dirpath)) {
22238460Smckusick 				grp = ep->ex_groups;
22338460Smckusick 				if (grp == NULL)
22438460Smckusick 					break;
225*39681Smckusick 
226*39681Smckusick 				/* Check for a host match */
227*39681Smckusick 				addrp = (u_long **)grp->gr_hp->h_addr_list;
228*39681Smckusick 				for (;;) {
229*39681Smckusick 					if (**addrp == saddr)
23038460Smckusick 						break;
231*39681Smckusick 					if (*++addrp == NULL)
232*39681Smckusick 						if (grp = grp->gr_next) {
233*39681Smckusick 							addrp = (u_long **)
234*39681Smckusick 								grp->gr_hp->h_addr_list;
235*39681Smckusick 						} else {
236*39681Smckusick 							bad = EACCES;
237*39681Smckusick 							if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
238*39681Smckusick 								syslog(LOG_ERR, "Can't send reply");
239*39681Smckusick 							sigsetmask(omask);
240*39681Smckusick 							return;
241*39681Smckusick 						}
24238460Smckusick 				}
243*39681Smckusick 				hp = grp->gr_hp;
244*39681Smckusick 				break;
24538460Smckusick 			}
24638460Smckusick 			ep = ep->ex_next;
24738460Smckusick 		}
24838460Smckusick 		sigsetmask(omask);
24938460Smckusick 		if (ep == NULL) {
25038460Smckusick 			bad = EACCES;
25138460Smckusick 			if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
25238460Smckusick 				syslog(LOG_ERR, "Can't send reply");
25338460Smckusick 			return;
25438460Smckusick 		}
25538460Smckusick 
25638460Smckusick 		/* Get the file handle */
25738460Smckusick 		bzero((caddr_t)&nfh, sizeof(nfh));
25838460Smckusick 		if (getfh(dirpath, (fhandle_t *)&nfh) < 0) {
25938460Smckusick 			bad = errno;
26038460Smckusick 			if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
26138460Smckusick 				syslog(LOG_ERR, "Can't send reply");
26238460Smckusick 			return;
26338460Smckusick 		}
264*39681Smckusick #ifdef notnow
265*39681Smckusick nfh.fh_generic.fh_fid.fid_gen = htonl(nfh.fh_generic.fh_fid.fid_gen);
266*39681Smckusick #endif
26738460Smckusick 		if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh))
26838460Smckusick 			syslog(LOG_ERR, "Can't send reply");
269*39681Smckusick 		if (hp == NULL)
270*39681Smckusick 			hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
271*39681Smckusick 		if (hp) {
272*39681Smckusick 			if (!fnd_mnt(hp->h_name, dirpath)) {
273*39681Smckusick 				strcpy(ml.ml_host, hp->h_name);
274*39681Smckusick 				strcpy(ml.ml_dirp, dirpath);
275*39681Smckusick 				write(mlfile, (caddr_t)&ml, sizeof(ml));
276*39681Smckusick 			}
27738460Smckusick 		}
27838460Smckusick 		return;
27938460Smckusick 	case RPCMNT_DUMP:
28038460Smckusick 		if (!svc_sendreply(transp, xdr_mlist, (caddr_t)0))
28138460Smckusick 			syslog(LOG_ERR, "Can't send reply");
28238460Smckusick 		return;
28338460Smckusick 	case RPCMNT_UMOUNT:
284*39681Smckusick 		if (uid != 0) {
285*39681Smckusick 			svcerr_weakauth(transp);
286*39681Smckusick 			return;
287*39681Smckusick 		}
28838460Smckusick 		if (!svc_getargs(transp, xdr_dir, dirpath)) {
28938460Smckusick 			svcerr_decode(transp);
29038460Smckusick 			return;
29138460Smckusick 		}
292*39681Smckusick 		hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
293*39681Smckusick 		if (hp && fnd_mnt(hp->h_name, dirpath)) {
294*39681Smckusick 			ml.ml_host[0] = '\0';
295*39681Smckusick 			write(mlfile, (caddr_t)&ml, sizeof(ml));
29638460Smckusick 		}
29738460Smckusick 		if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
29838460Smckusick 			syslog(LOG_ERR, "Can't send reply");
29938460Smckusick 		return;
30038460Smckusick 	case RPCMNT_UMNTALL:
301*39681Smckusick 		if (uid != 0) {
302*39681Smckusick 			svcerr_weakauth(transp);
303*39681Smckusick 			return;
304*39681Smckusick 		}
305*39681Smckusick 		hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
306*39681Smckusick 		if (hp) {
307*39681Smckusick 			lseek(mlfile, (off_t)0, L_SET);
308*39681Smckusick 			while (read(mlfile, (caddr_t)&ml, sizeof(ml)) ==
309*39681Smckusick 				sizeof(ml)) {
310*39681Smckusick 				if (!strcmp(hp->h_name, ml.ml_host)) {
311*39681Smckusick 					lseek(mlfile, (off_t)-sizeof(ml),
312*39681Smckusick 						L_INCR);
313*39681Smckusick 					ml.ml_host[0] = '\0';
314*39681Smckusick 					write(mlfile, (caddr_t)&ml, sizeof(ml));
315*39681Smckusick 				}
31638460Smckusick 			}
31738460Smckusick 		}
31838460Smckusick 		if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
31938460Smckusick 			syslog(LOG_ERR, "Can't send reply");
32038460Smckusick 		return;
32138460Smckusick 	case RPCMNT_EXPORT:
32238460Smckusick 		if (!svc_sendreply(transp, xdr_explist, (caddr_t)0))
32338460Smckusick 			syslog(LOG_ERR, "Can't send reply");
32438460Smckusick 		return;
32538460Smckusick 	default:
32638460Smckusick 		svcerr_noproc(transp);
32738460Smckusick 		return;
32838460Smckusick 	}
32938460Smckusick }
33038460Smckusick 
33138460Smckusick /*
33238460Smckusick  * Xdr conversion for a dirpath string
33338460Smckusick  */
33438460Smckusick xdr_dir(xdrsp, dirp)
33538460Smckusick 	XDR *xdrsp;
33638460Smckusick 	char *dirp;
33738460Smckusick {
33838460Smckusick 	return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
33938460Smckusick }
34038460Smckusick 
34138460Smckusick /*
34238460Smckusick  * Xdr routine to generate fhstatus
34338460Smckusick  */
34438460Smckusick xdr_fhs(xdrsp, nfh)
34538460Smckusick 	XDR *xdrsp;
34638460Smckusick 	nfsv2fh_t *nfh;
34738460Smckusick {
34838460Smckusick 	int ok = 0;
34938460Smckusick 
35038460Smckusick 	if (!xdr_long(xdrsp, &ok))
35138460Smckusick 		return (0);
35238460Smckusick 	return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH));
35338460Smckusick }
35438460Smckusick 
35538460Smckusick xdr_mlist(xdrsp, cp)
35638460Smckusick 	XDR *xdrsp;
35738460Smckusick 	caddr_t cp;
35838460Smckusick {
359*39681Smckusick 	struct mountlist ml;
36038460Smckusick 	int true = 1;
36138460Smckusick 	int false = 0;
36238460Smckusick 	char *strp;
36338460Smckusick 
364*39681Smckusick 	lseek(mlfile, (off_t)0, L_SET);
365*39681Smckusick 	while (read(mlfile, (caddr_t)&ml, sizeof(ml)) == sizeof(ml)) {
366*39681Smckusick 		if (ml.ml_host[0] != '\0') {
367*39681Smckusick 			if (!xdr_bool(xdrsp, &true))
368*39681Smckusick 				return (0);
369*39681Smckusick 			strp = &ml.ml_host[0];
370*39681Smckusick 			if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
371*39681Smckusick 				return (0);
372*39681Smckusick 			strp = &ml.ml_dirp[0];
373*39681Smckusick 			if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
374*39681Smckusick 				return (0);
375*39681Smckusick 		}
37638460Smckusick 	}
37738460Smckusick 	if (!xdr_bool(xdrsp, &false))
37838460Smckusick 		return (0);
37938460Smckusick 	return (1);
38038460Smckusick }
38138460Smckusick 
38238460Smckusick /*
38338460Smckusick  * Xdr conversion for export list
38438460Smckusick  */
38538460Smckusick xdr_explist(xdrsp, cp)
38638460Smckusick 	XDR *xdrsp;
38738460Smckusick 	caddr_t cp;
38838460Smckusick {
38938460Smckusick 	register struct exportlist *ep;
39038460Smckusick 	register struct grouplist *grp;
39138460Smckusick 	int true = 1;
39238460Smckusick 	int false = 0;
39338460Smckusick 	char *strp;
39438460Smckusick 	int omask;
39538460Smckusick 
39638460Smckusick 	omask = sigblock(sigmask(SIGHUP));
39738460Smckusick 	ep = exphead.ex_next;
39838460Smckusick 	while (ep != NULL) {
39938460Smckusick 		if (!xdr_bool(xdrsp, &true))
40038460Smckusick 			goto errout;
40138460Smckusick 		strp = &ep->ex_dirp[0];
40238460Smckusick 		if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
40338460Smckusick 			goto errout;
40438460Smckusick 		grp = ep->ex_groups;
40538460Smckusick 		while (grp != NULL) {
40638460Smckusick 			if (!xdr_bool(xdrsp, &true))
40738460Smckusick 				goto errout;
408*39681Smckusick 			strp = grp->gr_hp->h_name;
40938460Smckusick 			if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
41038460Smckusick 				goto errout;
41138460Smckusick 			grp = grp->gr_next;
41238460Smckusick 		}
41338460Smckusick 		if (!xdr_bool(xdrsp, &false))
41438460Smckusick 			goto errout;
41538460Smckusick 		ep = ep->ex_next;
41638460Smckusick 	}
41738460Smckusick 	sigsetmask(omask);
41838460Smckusick 	if (!xdr_bool(xdrsp, &false))
41938460Smckusick 		return (0);
42038460Smckusick 	return (1);
42138460Smckusick errout:
42238460Smckusick 	sigsetmask(omask);
42338460Smckusick 	return (0);
42438460Smckusick }
42538460Smckusick 
42638460Smckusick #define LINESIZ	10240
42738460Smckusick char line[LINESIZ];
42838460Smckusick 
42938460Smckusick /*
43038460Smckusick  * Get the export list
43138460Smckusick  */
43238460Smckusick get_exportlist()
43338460Smckusick {
434*39681Smckusick 	register struct hostent *hp, *nhp;
435*39681Smckusick 	register char **addrp, **naddrp;
436*39681Smckusick 	register int i;
437*39681Smckusick 	register struct grouplist *grp, *grp2;
43838460Smckusick 	register struct exportlist *ep, *ep2;
43938460Smckusick 	FILE *inf;
44038460Smckusick 	char *cp, *endcp;
441*39681Smckusick 	char savedc;
44238460Smckusick 	int len;
44338460Smckusick 	int rootuid, exflags;
44438460Smckusick 
44538460Smckusick 	/*
44638460Smckusick 	 * First, get rid of the old list
44738460Smckusick 	 */
44838460Smckusick 	ep = exphead.ex_next;
44938460Smckusick 	while (ep != NULL) {
45038460Smckusick 		grp = ep->ex_groups;
45138460Smckusick 		while (grp != NULL) {
452*39681Smckusick 			addrp = grp->gr_hp->h_addr_list;
453*39681Smckusick 			while (*addrp)
454*39681Smckusick 				free(*addrp++);
455*39681Smckusick 			free((caddr_t)grp->gr_hp->h_addr_list);
456*39681Smckusick 			free(grp->gr_hp->h_name);
457*39681Smckusick 			free((caddr_t)grp->gr_hp);
45838460Smckusick 			grp2 = grp;
45938460Smckusick 			grp = grp->gr_next;
46038460Smckusick 			free((caddr_t)grp2);
46138460Smckusick 		}
46238460Smckusick 		ep2 = ep;
46338460Smckusick 		ep = ep->ex_next;
46438460Smckusick 		free((caddr_t)ep2);
46538460Smckusick 	}
46638460Smckusick 
46738460Smckusick 	/*
46838460Smckusick 	 * Read in the exports file and build the list, calling
46938460Smckusick 	 * exportfs() as we go along
47038460Smckusick 	 */
47138460Smckusick 	exphead.ex_next = exphead.ex_prev = (struct exportlist *)0;
47238460Smckusick 	if ((inf = fopen(exname, "r")) == NULL) {
47338460Smckusick 		syslog(LOG_ERR, "Can't open %s", exname);
47438460Smckusick 		exit(2);
47538460Smckusick 	}
47638460Smckusick 	while (fgets(line, LINESIZ, inf)) {
47738460Smckusick 		exflags = 0;
47838460Smckusick 		rootuid = def_rootuid;
47938460Smckusick 		cp = line;
48038460Smckusick 		nextfield(&cp, &endcp);
48138460Smckusick 		len = endcp-cp;
48238460Smckusick 		if (len <= RPCMNT_PATHLEN && len > 0) {
48338460Smckusick 			ep = (struct exportlist *)malloc(sizeof(*ep));
48438460Smckusick 			ep->ex_next = ep->ex_prev = (struct exportlist *)0;
48538460Smckusick 			ep->ex_groups = (struct grouplist *)0;
48638460Smckusick 			bcopy(cp, ep->ex_dirp, len);
48738460Smckusick 			ep->ex_dirp[len] = '\0';
48838460Smckusick 		} else
48938460Smckusick 			goto err;
49038460Smckusick 		cp = endcp;
49138460Smckusick 		nextfield(&cp, &endcp);
49238460Smckusick 		len = endcp-cp;
49338460Smckusick 		while (len > 0) {
494*39681Smckusick 			savedc = *endcp;
495*39681Smckusick 			*endcp = '\0';
49638460Smckusick 			if (len <= RPCMNT_NAMELEN) {
49738460Smckusick 				if (*cp == '-') {
49838460Smckusick 					cp++;
49938460Smckusick 					switch (*cp) {
50038460Smckusick 					case 'o':
50138460Smckusick 						exflags |= M_EXRDONLY;
50238460Smckusick 						break;
50338460Smckusick 					case 'r':
50438460Smckusick 						if (*++cp == '=')
50538460Smckusick 							rootuid = atoi(++cp);
50638460Smckusick 						break;
50738460Smckusick 					default:
50838460Smckusick 						syslog(LOG_WARNING,
50938460Smckusick 						  "Bad -%c option in %s",
51038460Smckusick 						  *cp, exname);
51138460Smckusick 						break;
51238460Smckusick 					};
513*39681Smckusick 				} else if (hp = gethostbyname(cp)) {
514*39681Smckusick 					grp = (struct grouplist *)
515*39681Smckusick 						malloc(sizeof(struct grouplist));
51638460Smckusick 					if (grp == NULL)
51738460Smckusick 						goto err;
518*39681Smckusick 					nhp = grp->gr_hp = (struct hostent *)
519*39681Smckusick 						malloc(sizeof(struct hostent));
520*39681Smckusick 					if (nhp == NULL)
521*39681Smckusick 						goto err;
522*39681Smckusick 					bcopy((caddr_t)hp, (caddr_t)nhp,
523*39681Smckusick 						sizeof(struct hostent));
524*39681Smckusick 					i = strlen(hp->h_name)+1;
525*39681Smckusick 					nhp->h_name = (char *)malloc(i);
526*39681Smckusick 					if (nhp->h_name == NULL)
527*39681Smckusick 						goto err;
528*39681Smckusick 					bcopy(hp->h_name, nhp->h_name, i);
529*39681Smckusick 					addrp = hp->h_addr_list;
530*39681Smckusick 					i = 1;
531*39681Smckusick 					while (*addrp++)
532*39681Smckusick 						i++;
533*39681Smckusick 					naddrp = nhp->h_addr_list = (char **)
534*39681Smckusick 						malloc(i*sizeof(char *));
535*39681Smckusick 					if (naddrp == NULL)
536*39681Smckusick 						goto err;
537*39681Smckusick 					addrp = hp->h_addr_list;
538*39681Smckusick 					while (*addrp) {
539*39681Smckusick 						*naddrp = (char *)
540*39681Smckusick 						    malloc(hp->h_length);
541*39681Smckusick 						bcopy(*addrp, *naddrp,
542*39681Smckusick 							hp->h_length);
543*39681Smckusick 						addrp++;
544*39681Smckusick 						naddrp++;
545*39681Smckusick 					}
546*39681Smckusick 					*naddrp = (char *)0;
54738460Smckusick 					grp->gr_next = ep->ex_groups;
54838460Smckusick 					ep->ex_groups = grp;
54938460Smckusick 				}
55038460Smckusick 			}
55138460Smckusick 			cp = endcp;
552*39681Smckusick 			*cp = savedc;
55338460Smckusick 			nextfield(&cp, &endcp);
55438460Smckusick 			len = endcp-cp;
55538460Smckusick 		}
55638460Smckusick 		if (exportfs(ep->ex_dirp, rootuid, exflags) < 0) {
55738460Smckusick 			syslog(LOG_WARNING, "Can't export %s", ep->ex_dirp);
55838460Smckusick 			free((caddr_t)ep);
55938460Smckusick 		} else {
56038460Smckusick 			ep->ex_rootuid = rootuid;
56138460Smckusick 			ep->ex_exflags = exflags;
56238460Smckusick 			ep->ex_next = exphead.ex_next;
56338460Smckusick 			ep->ex_prev = &exphead;
56438460Smckusick 			if (ep->ex_next != NULL)
56538460Smckusick 				ep->ex_next->ex_prev = ep;
56638460Smckusick 			exphead.ex_next = ep;
56738460Smckusick 		}
56838460Smckusick 	}
56938460Smckusick 	fclose(inf);
57038460Smckusick 	return;
57138460Smckusick err:
572*39681Smckusick 	syslog(LOG_ERR, "Bad Exports File, mountd Failed");
57338460Smckusick 	exit(2);
57438460Smckusick }
57538460Smckusick 
57638460Smckusick /*
57738460Smckusick  * Parse out the next white space separated field
57838460Smckusick  */
57938460Smckusick nextfield(cp, endcp)
58038460Smckusick 	char **cp;
58138460Smckusick 	char **endcp;
58238460Smckusick {
58338460Smckusick 	register char *p;
58438460Smckusick 
58538460Smckusick 	p = *cp;
58638460Smckusick 	while (*p == ' ' || *p == '\t')
58738460Smckusick 		p++;
58838460Smckusick 	if (*p == '\n' || *p == '\0') {
58938460Smckusick 		*cp = *endcp = p;
59038460Smckusick 		return;
59138460Smckusick 	}
59238460Smckusick 	*cp = p++;
59338460Smckusick 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
59438460Smckusick 		p++;
59538460Smckusick 	*endcp = p;
59638460Smckusick }
597*39681Smckusick 
598*39681Smckusick /*
599*39681Smckusick  * Search the remote mounts file for a match.
600*39681Smckusick  * Iff found
601*39681Smckusick  *	- set file offset to record and return TRUE
602*39681Smckusick  * else
603*39681Smckusick  *	- set file offset to an unused record if found or eof otherwise
604*39681Smckusick  *	  and return FALSE
605*39681Smckusick  */
606*39681Smckusick fnd_mnt(host, dirp)
607*39681Smckusick 	char *host;
608*39681Smckusick 	char *dirp;
609*39681Smckusick {
610*39681Smckusick 	struct mountlist ml;
611*39681Smckusick 	off_t off, pos;
612*39681Smckusick 
613*39681Smckusick 	off = -1;
614*39681Smckusick 	pos = 0;
615*39681Smckusick 	lseek(mlfile, (off_t)0, L_SET);
616*39681Smckusick 	while (read(mlfile, (caddr_t)&ml, sizeof(ml)) == sizeof(ml)) {
617*39681Smckusick 		if (!strcmp(host, ml.ml_host) && !strcmp(dirp, ml.ml_dirp)) {
618*39681Smckusick 			lseek(mlfile, (off_t)-sizeof(ml), L_INCR);
619*39681Smckusick 			return (TRUE);
620*39681Smckusick 		} else if (ml.ml_host[0] == '\0') {
621*39681Smckusick 			off = pos;
622*39681Smckusick 		}
623*39681Smckusick 		pos += sizeof(ml);
624*39681Smckusick 	}
625*39681Smckusick 	if (off != -1)
626*39681Smckusick 		lseek(mlfile, off, L_SET);
627*39681Smckusick 	else
628*39681Smckusick 		lseek(mlfile, (off_t)0, L_XTND);
629*39681Smckusick 	return (FALSE);
630*39681Smckusick }
631