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 * 842703Sbostic * %sccs.include.redist.c% 938460Smckusick */ 1038460Smckusick 1138460Smckusick #ifndef lint 1238460Smckusick char copyright[] = 1338460Smckusick "@(#) Copyright (c) 1989 Regents of the University of California.\n\ 1438460Smckusick All rights reserved.\n"; 1538460Smckusick #endif not lint 1638460Smckusick 1738460Smckusick #ifndef lint 18*44690Skarels static char sccsid[] = "@(#)mountd.c 5.11 (Berkeley) 06/29/90"; 1938460Smckusick #endif not lint 2038460Smckusick 2138460Smckusick #include <sys/param.h> 2238460Smckusick #include <sys/ioctl.h> 2338460Smckusick #include <sys/stat.h> 2439681Smckusick #include <sys/file.h> 2538460Smckusick #include <sys/mount.h> 2638460Smckusick #include <sys/socket.h> 2738460Smckusick #include <sys/errno.h> 2842038Sbostic #include <sys/signal.h> 2942038Sbostic #include <stdio.h> 3042038Sbostic #include <string.h> 3142038Sbostic #include <syslog.h> 3238460Smckusick #include <netdb.h> 3338460Smckusick #include <rpc/rpc.h> 3438460Smckusick #include <rpc/pmap_clnt.h> 3538460Smckusick #include <rpc/pmap_prot.h> 3638460Smckusick #include <nfs/rpcv2.h> 3738460Smckusick #include <nfs/nfsv2.h> 3839681Smckusick #include "pathnames.h" 3938460Smckusick 4038460Smckusick struct ufid { 4138460Smckusick u_short ufid_len; 4238460Smckusick ino_t ufid_ino; 4338460Smckusick long ufid_gen; 4438460Smckusick }; 4538460Smckusick /* 4638460Smckusick * Structures for keeping the mount list and export list 4738460Smckusick */ 4838460Smckusick struct mountlist { 4944015Smckusick struct mountlist *ml_next; 5038460Smckusick char ml_host[RPCMNT_NAMELEN+1]; 5138460Smckusick char ml_dirp[RPCMNT_PATHLEN+1]; 5238460Smckusick }; 5338460Smckusick 5438460Smckusick struct exportlist { 5538460Smckusick struct exportlist *ex_next; 5638460Smckusick struct exportlist *ex_prev; 5738460Smckusick struct grouplist *ex_groups; 5838460Smckusick int ex_rootuid; 5938460Smckusick int ex_exflags; 6044015Smckusick dev_t ex_dev; 6138460Smckusick char ex_dirp[RPCMNT_PATHLEN+1]; 6238460Smckusick }; 6338460Smckusick 6438460Smckusick struct grouplist { 6538460Smckusick struct grouplist *gr_next; 6639681Smckusick struct hostent *gr_hp; 6738460Smckusick }; 6838460Smckusick 6938460Smckusick /* Global defs */ 7038460Smckusick int xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist(); 7144015Smckusick int mntsrv(), get_exportlist(), send_umntall(), umntall_each(); 7244015Smckusick void get_mountlist(), add_mlist(), del_mlist(); 7338460Smckusick struct exportlist exphead; 7444015Smckusick struct mountlist *mlhead; 7538460Smckusick char exname[MAXPATHLEN]; 7638460Smckusick int def_rootuid = -2; 7744015Smckusick int root_only = 1; 7838460Smckusick extern int errno; 7938460Smckusick #ifdef DEBUG 8038460Smckusick int debug = 1; 8138460Smckusick #else 8238460Smckusick int debug = 0; 8338460Smckusick #endif 8438460Smckusick 8538460Smckusick /* 8638460Smckusick * Mountd server for NFS mount protocol as described in: 8739681Smckusick * NFS: Network File System Protocol Specification, RFC1094, Appendix A 8844015Smckusick * The optional arguments are the exports file name 8939681Smckusick * default: _PATH_EXPORTS 9044015Smckusick * and "-n" to allow nonroot mount. 9138460Smckusick */ 9238460Smckusick main(argc, argv) 9338460Smckusick int argc; 9444015Smckusick char **argv; 9538460Smckusick { 9638460Smckusick SVCXPRT *transp; 9744015Smckusick int c; 9844015Smckusick extern int optind; 9944015Smckusick extern char *optarg; 10038460Smckusick 10144015Smckusick while ((c = getopt(argc, argv, "n")) != EOF) 10244015Smckusick switch (c) { 10344015Smckusick case 'n': 10444015Smckusick root_only = 0; 10544015Smckusick break; 10644015Smckusick default: 10744015Smckusick fprintf(stderr, "Usage: mountd [-n] [export_file]\n"); 10844015Smckusick exit(1); 10944015Smckusick }; 11044015Smckusick argc -= optind; 11144015Smckusick argv += optind; 11244015Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 11344015Smckusick mlhead = (struct mountlist *)0; 11444015Smckusick if (argc == 1) { 11544015Smckusick strncpy(exname, *argv, MAXPATHLEN-1); 11644015Smckusick exname[MAXPATHLEN-1] = '\0'; 11744015Smckusick } else 11844015Smckusick strcpy(exname, _PATH_EXPORTS); 11944338Smckusick openlog("mountd:", LOG_PID, LOG_DAEMON); 12044015Smckusick get_exportlist(); 12144015Smckusick get_mountlist(); 12238460Smckusick if (debug == 0) { 123*44690Skarels daemon(0, 0); 12438460Smckusick signal(SIGINT, SIG_IGN); 12538460Smckusick signal(SIGQUIT, SIG_IGN); 12638460Smckusick } 12738460Smckusick signal(SIGHUP, get_exportlist); 12844015Smckusick signal(SIGTERM, send_umntall); 12940494Smckusick { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); 13040494Smckusick if (pidfile != NULL) { 13140494Smckusick fprintf(pidfile, "%d\n", getpid()); 13240494Smckusick fclose(pidfile); 13340494Smckusick } 13440494Smckusick } 13538460Smckusick if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL) { 13638460Smckusick syslog(LOG_ERR, "Can't create socket"); 13738460Smckusick exit(1); 13838460Smckusick } 13938460Smckusick pmap_unset(RPCPROG_MNT, RPCMNT_VER1); 14038460Smckusick if (!svc_register(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv, IPPROTO_UDP)) { 14138460Smckusick syslog(LOG_ERR, "Can't register mount"); 14238460Smckusick exit(1); 14338460Smckusick } 14438460Smckusick svc_run(); 14538460Smckusick syslog(LOG_ERR, "Mountd died"); 146*44690Skarels exit(1); 14738460Smckusick } 14838460Smckusick 14938460Smckusick /* 15038460Smckusick * The mount rpc service 15138460Smckusick */ 15238460Smckusick mntsrv(rqstp, transp) 15338460Smckusick register struct svc_req *rqstp; 15438460Smckusick register SVCXPRT *transp; 15538460Smckusick { 15639681Smckusick register struct grouplist *grp; 15739681Smckusick register u_long **addrp; 15838460Smckusick register struct exportlist *ep; 15938460Smckusick nfsv2fh_t nfh; 16038460Smckusick struct authunix_parms *ucr; 16138460Smckusick struct stat stb; 16238460Smckusick struct hostent *hp; 16339681Smckusick u_long saddr; 16438460Smckusick char dirpath[RPCMNT_PATHLEN+1]; 16538460Smckusick int bad = ENOENT; 16638460Smckusick int omask; 16739681Smckusick uid_t uid = -2; 16838460Smckusick 16938460Smckusick /* Get authorization */ 17038460Smckusick switch (rqstp->rq_cred.oa_flavor) { 17138460Smckusick case AUTH_UNIX: 17238460Smckusick ucr = (struct authunix_parms *)rqstp->rq_clntcred; 17339681Smckusick uid = ucr->aup_uid; 17439681Smckusick break; 17538460Smckusick case AUTH_NULL: 17638460Smckusick default: 17739681Smckusick break; 17838460Smckusick } 17938460Smckusick 18039681Smckusick saddr = transp->xp_raddr.sin_addr.s_addr; 18139681Smckusick hp = (struct hostent *)0; 18238460Smckusick switch (rqstp->rq_proc) { 18339681Smckusick case NULLPROC: 18439681Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 18539681Smckusick syslog(LOG_ERR, "Can't send reply"); 18639681Smckusick return; 18738460Smckusick case RPCMNT_MOUNT: 18844015Smckusick if (uid != 0 && root_only) { 18939681Smckusick svcerr_weakauth(transp); 19039681Smckusick return; 19139681Smckusick } 19238460Smckusick if (!svc_getargs(transp, xdr_dir, dirpath)) { 19338460Smckusick svcerr_decode(transp); 19438460Smckusick return; 19538460Smckusick } 19638460Smckusick 19738460Smckusick /* Check to see if it's a valid dirpath */ 19838460Smckusick if (stat(dirpath, &stb) < 0 || (stb.st_mode&S_IFMT) != 19938460Smckusick S_IFDIR) { 20038460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 20138460Smckusick syslog(LOG_ERR, "Can't send reply"); 20238460Smckusick return; 20338460Smckusick } 20438460Smckusick 20538460Smckusick /* Check in the exports list */ 20638460Smckusick omask = sigblock(sigmask(SIGHUP)); 20738460Smckusick ep = exphead.ex_next; 20838460Smckusick while (ep != NULL) { 20938460Smckusick if (!strcmp(ep->ex_dirp, dirpath)) { 21038460Smckusick grp = ep->ex_groups; 21138460Smckusick if (grp == NULL) 21238460Smckusick break; 21339681Smckusick 21439681Smckusick /* Check for a host match */ 21539681Smckusick addrp = (u_long **)grp->gr_hp->h_addr_list; 21639681Smckusick for (;;) { 21739681Smckusick if (**addrp == saddr) 21838460Smckusick break; 21939681Smckusick if (*++addrp == NULL) 22039681Smckusick if (grp = grp->gr_next) { 22139681Smckusick addrp = (u_long **) 22239681Smckusick grp->gr_hp->h_addr_list; 22339681Smckusick } else { 22439681Smckusick bad = EACCES; 22539681Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 22639681Smckusick syslog(LOG_ERR, "Can't send reply"); 22739681Smckusick sigsetmask(omask); 22839681Smckusick return; 22939681Smckusick } 23038460Smckusick } 23139681Smckusick hp = grp->gr_hp; 23239681Smckusick break; 23338460Smckusick } 23438460Smckusick ep = ep->ex_next; 23538460Smckusick } 23638460Smckusick sigsetmask(omask); 23738460Smckusick if (ep == NULL) { 23838460Smckusick bad = EACCES; 23938460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 24038460Smckusick syslog(LOG_ERR, "Can't send reply"); 24138460Smckusick return; 24238460Smckusick } 24338460Smckusick 24438460Smckusick /* Get the file handle */ 24538460Smckusick bzero((caddr_t)&nfh, sizeof(nfh)); 24638460Smckusick if (getfh(dirpath, (fhandle_t *)&nfh) < 0) { 24738460Smckusick bad = errno; 24838460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 24938460Smckusick syslog(LOG_ERR, "Can't send reply"); 25038460Smckusick return; 25138460Smckusick } 25238460Smckusick if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh)) 25338460Smckusick syslog(LOG_ERR, "Can't send reply"); 25439681Smckusick if (hp == NULL) 25539681Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 25644015Smckusick if (hp) 25744015Smckusick add_mlist(hp->h_name, dirpath); 25838460Smckusick return; 25938460Smckusick case RPCMNT_DUMP: 26038460Smckusick if (!svc_sendreply(transp, xdr_mlist, (caddr_t)0)) 26138460Smckusick syslog(LOG_ERR, "Can't send reply"); 26238460Smckusick return; 26338460Smckusick case RPCMNT_UMOUNT: 26444015Smckusick if (uid != 0 && root_only) { 26539681Smckusick svcerr_weakauth(transp); 26639681Smckusick return; 26739681Smckusick } 26838460Smckusick if (!svc_getargs(transp, xdr_dir, dirpath)) { 26938460Smckusick svcerr_decode(transp); 27038460Smckusick return; 27138460Smckusick } 27238460Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 27338460Smckusick syslog(LOG_ERR, "Can't send reply"); 27444015Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 27544015Smckusick if (hp) 27644015Smckusick del_mlist(hp->h_name, dirpath); 27738460Smckusick return; 27838460Smckusick case RPCMNT_UMNTALL: 27944015Smckusick if (uid != 0 && root_only) { 28039681Smckusick svcerr_weakauth(transp); 28139681Smckusick return; 28239681Smckusick } 28338460Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 28438460Smckusick syslog(LOG_ERR, "Can't send reply"); 28544015Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 28644015Smckusick if (hp) 28744015Smckusick del_mlist(hp->h_name, (char *)0); 28838460Smckusick return; 28938460Smckusick case RPCMNT_EXPORT: 29038460Smckusick if (!svc_sendreply(transp, xdr_explist, (caddr_t)0)) 29138460Smckusick syslog(LOG_ERR, "Can't send reply"); 29238460Smckusick return; 29338460Smckusick default: 29438460Smckusick svcerr_noproc(transp); 29538460Smckusick return; 29638460Smckusick } 29738460Smckusick } 29838460Smckusick 29938460Smckusick /* 30038460Smckusick * Xdr conversion for a dirpath string 30138460Smckusick */ 30238460Smckusick xdr_dir(xdrsp, dirp) 30338460Smckusick XDR *xdrsp; 30438460Smckusick char *dirp; 30538460Smckusick { 30638460Smckusick return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 30738460Smckusick } 30838460Smckusick 30938460Smckusick /* 31038460Smckusick * Xdr routine to generate fhstatus 31138460Smckusick */ 31238460Smckusick xdr_fhs(xdrsp, nfh) 31338460Smckusick XDR *xdrsp; 31438460Smckusick nfsv2fh_t *nfh; 31538460Smckusick { 31638460Smckusick int ok = 0; 31738460Smckusick 31838460Smckusick if (!xdr_long(xdrsp, &ok)) 31938460Smckusick return (0); 32038460Smckusick return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH)); 32138460Smckusick } 32238460Smckusick 32338460Smckusick xdr_mlist(xdrsp, cp) 32438460Smckusick XDR *xdrsp; 32538460Smckusick caddr_t cp; 32638460Smckusick { 32744015Smckusick register struct mountlist *mlp; 32838460Smckusick int true = 1; 32938460Smckusick int false = 0; 33038460Smckusick char *strp; 33138460Smckusick 33244015Smckusick mlp = mlhead; 33344015Smckusick while (mlp) { 33444015Smckusick if (!xdr_bool(xdrsp, &true)) 33544015Smckusick return (0); 33644015Smckusick strp = &mlp->ml_host[0]; 33744015Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 33844015Smckusick return (0); 33944015Smckusick strp = &mlp->ml_dirp[0]; 34044015Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 34144015Smckusick return (0); 34244015Smckusick mlp = mlp->ml_next; 34338460Smckusick } 34438460Smckusick if (!xdr_bool(xdrsp, &false)) 34538460Smckusick return (0); 34638460Smckusick return (1); 34738460Smckusick } 34838460Smckusick 34938460Smckusick /* 35038460Smckusick * Xdr conversion for export list 35138460Smckusick */ 35238460Smckusick xdr_explist(xdrsp, cp) 35338460Smckusick XDR *xdrsp; 35438460Smckusick caddr_t cp; 35538460Smckusick { 35638460Smckusick register struct exportlist *ep; 35738460Smckusick register struct grouplist *grp; 35838460Smckusick int true = 1; 35938460Smckusick int false = 0; 36038460Smckusick char *strp; 36138460Smckusick int omask; 36238460Smckusick 36338460Smckusick omask = sigblock(sigmask(SIGHUP)); 36438460Smckusick ep = exphead.ex_next; 36538460Smckusick while (ep != NULL) { 36638460Smckusick if (!xdr_bool(xdrsp, &true)) 36738460Smckusick goto errout; 36838460Smckusick strp = &ep->ex_dirp[0]; 36938460Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 37038460Smckusick goto errout; 37138460Smckusick grp = ep->ex_groups; 37238460Smckusick while (grp != NULL) { 37338460Smckusick if (!xdr_bool(xdrsp, &true)) 37438460Smckusick goto errout; 37539681Smckusick strp = grp->gr_hp->h_name; 37638460Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 37738460Smckusick goto errout; 37838460Smckusick grp = grp->gr_next; 37938460Smckusick } 38038460Smckusick if (!xdr_bool(xdrsp, &false)) 38138460Smckusick goto errout; 38238460Smckusick ep = ep->ex_next; 38338460Smckusick } 38438460Smckusick sigsetmask(omask); 38538460Smckusick if (!xdr_bool(xdrsp, &false)) 38638460Smckusick return (0); 38738460Smckusick return (1); 38838460Smckusick errout: 38938460Smckusick sigsetmask(omask); 39038460Smckusick return (0); 39138460Smckusick } 39238460Smckusick 39338460Smckusick #define LINESIZ 10240 39438460Smckusick char line[LINESIZ]; 39538460Smckusick 39638460Smckusick /* 39738460Smckusick * Get the export list 39838460Smckusick */ 39938460Smckusick get_exportlist() 40038460Smckusick { 40139681Smckusick register struct hostent *hp, *nhp; 40239681Smckusick register char **addrp, **naddrp; 40339681Smckusick register int i; 40444015Smckusick register struct grouplist *grp; 40538460Smckusick register struct exportlist *ep, *ep2; 40640368Smckusick struct ufs_args args; 40744015Smckusick struct stat sb; 40838460Smckusick FILE *inf; 40938460Smckusick char *cp, *endcp; 41039681Smckusick char savedc; 41144015Smckusick int len, dirplen; 41238460Smckusick int rootuid, exflags; 41344015Smckusick u_long saddr; 41444015Smckusick struct exportlist *fep; 41538460Smckusick 41638460Smckusick /* 41738460Smckusick * First, get rid of the old list 41838460Smckusick */ 41938460Smckusick ep = exphead.ex_next; 42038460Smckusick while (ep != NULL) { 42138460Smckusick ep2 = ep; 42238460Smckusick ep = ep->ex_next; 42344015Smckusick free_exp(ep2); 42438460Smckusick } 42538460Smckusick 42638460Smckusick /* 42738460Smckusick * Read in the exports file and build the list, calling 42838460Smckusick * exportfs() as we go along 42938460Smckusick */ 43038460Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 43138460Smckusick if ((inf = fopen(exname, "r")) == NULL) { 43238460Smckusick syslog(LOG_ERR, "Can't open %s", exname); 43338460Smckusick exit(2); 43438460Smckusick } 43538460Smckusick while (fgets(line, LINESIZ, inf)) { 43641404Smckusick exflags = MNT_EXPORTED; 43738460Smckusick rootuid = def_rootuid; 43838460Smckusick cp = line; 43938460Smckusick nextfield(&cp, &endcp); 44044015Smckusick 44144015Smckusick /* 44244015Smckusick * Get file system devno and see if an entry for this 44344015Smckusick * file system already exists. 44444015Smckusick */ 44544015Smckusick savedc = *endcp; 44644015Smckusick *endcp = '\0'; 44744015Smckusick if (stat(cp, &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFDIR) 44844015Smckusick goto err; 44944015Smckusick fep = (struct exportlist *)0; 45044015Smckusick ep = exphead.ex_next; 45144015Smckusick while (ep) { 45244015Smckusick if (ep->ex_dev == sb.st_dev) { 45344015Smckusick fep = ep; 45444015Smckusick break; 45544015Smckusick } 45644015Smckusick ep = ep->ex_next; 45744015Smckusick } 45844015Smckusick *endcp = savedc; 45944015Smckusick 46044015Smckusick /* 46144015Smckusick * Create new exports list entry 46244015Smckusick */ 46338460Smckusick len = endcp-cp; 46438460Smckusick if (len <= RPCMNT_PATHLEN && len > 0) { 46538460Smckusick ep = (struct exportlist *)malloc(sizeof(*ep)); 46638460Smckusick ep->ex_next = ep->ex_prev = (struct exportlist *)0; 46738460Smckusick ep->ex_groups = (struct grouplist *)0; 46838460Smckusick bcopy(cp, ep->ex_dirp, len); 46938460Smckusick ep->ex_dirp[len] = '\0'; 47044015Smckusick dirplen = len; 47138460Smckusick } else 47238460Smckusick goto err; 47338460Smckusick cp = endcp; 47438460Smckusick nextfield(&cp, &endcp); 47538460Smckusick len = endcp-cp; 47638460Smckusick while (len > 0) { 47739681Smckusick savedc = *endcp; 47839681Smckusick *endcp = '\0'; 47938460Smckusick if (len <= RPCMNT_NAMELEN) { 48038460Smckusick if (*cp == '-') { 48144015Smckusick do_opt(cp+1, fep, ep, &exflags, &rootuid); 48244015Smckusick } else { 48344015Smckusick if (isdigit(*cp)) { 48444015Smckusick saddr = inet_addr(cp); 48544015Smckusick if (saddr == -1 || 48644015Smckusick (hp = gethostbyaddr((caddr_t)&saddr, 48744015Smckusick sizeof(saddr), AF_INET)) == NULL) 48838460Smckusick goto err; 48944015Smckusick } else if ((hp = gethostbyname(cp)) == NULL) 49044015Smckusick goto err; 49144015Smckusick grp = (struct grouplist *) 49244015Smckusick malloc(sizeof(struct grouplist)); 49344015Smckusick if (grp == NULL) 49444015Smckusick goto err; 49544015Smckusick nhp = grp->gr_hp = (struct hostent *) 49644015Smckusick malloc(sizeof(struct hostent)); 49744015Smckusick if (nhp == NULL) 49844015Smckusick goto err; 49944015Smckusick bcopy((caddr_t)hp, (caddr_t)nhp, 50044015Smckusick sizeof(struct hostent)); 50144015Smckusick i = strlen(hp->h_name)+1; 50244015Smckusick nhp->h_name = (char *)malloc(i); 50344015Smckusick if (nhp->h_name == NULL) 50444015Smckusick goto err; 50544015Smckusick bcopy(hp->h_name, nhp->h_name, i); 50644015Smckusick addrp = hp->h_addr_list; 50744015Smckusick i = 1; 50844015Smckusick while (*addrp++) 50944015Smckusick i++; 51044015Smckusick naddrp = nhp->h_addr_list = (char **) 51144015Smckusick malloc(i*sizeof(char *)); 51244015Smckusick if (naddrp == NULL) 51344015Smckusick goto err; 51444015Smckusick addrp = hp->h_addr_list; 51544015Smckusick while (*addrp) { 51644015Smckusick *naddrp = (char *) 51744015Smckusick malloc(hp->h_length); 51844015Smckusick if (*naddrp == NULL) 51939681Smckusick goto err; 52044015Smckusick bcopy(*addrp, *naddrp, 52144015Smckusick hp->h_length); 52244015Smckusick addrp++; 52344015Smckusick naddrp++; 52444015Smckusick } 52544015Smckusick *naddrp = (char *)0; 52644015Smckusick grp->gr_next = ep->ex_groups; 52744015Smckusick ep->ex_groups = grp; 52838460Smckusick } 52938460Smckusick } 53038460Smckusick cp = endcp; 53139681Smckusick *cp = savedc; 53238460Smckusick nextfield(&cp, &endcp); 53338460Smckusick len = endcp-cp; 53438460Smckusick } 53544015Smckusick if (fep == NULL) { 53644015Smckusick args.fspec = 0; 53744015Smckusick args.exflags = exflags; 53844015Smckusick args.exroot = rootuid; 53944015Smckusick cp = (char *)0; 54044015Smckusick while (mount(MOUNT_UFS, ep->ex_dirp, MNT_UPDATE, &args) < 0) { 54144015Smckusick if (cp == NULL) 54244015Smckusick cp = ep->ex_dirp + dirplen - 1; 54344015Smckusick else 54444015Smckusick *cp = savedc; 54544015Smckusick /* back up over the last component */ 54644015Smckusick while (*cp == '/' && cp > ep->ex_dirp) 54744015Smckusick cp--; 54844015Smckusick while (*(cp - 1) != '/' && cp > ep->ex_dirp) 54944015Smckusick cp--; 55044015Smckusick if (cp == ep->ex_dirp) { 55144015Smckusick syslog(LOG_WARNING, 55244015Smckusick "Can't export %s", ep->ex_dirp); 55344015Smckusick free_exp(ep); 55444015Smckusick goto nextline; 55544015Smckusick } 55644015Smckusick savedc = *cp; 55744015Smckusick *cp = '\0'; 55844015Smckusick } 55944015Smckusick if (cp) 56044015Smckusick *cp = savedc; 56138460Smckusick ep->ex_rootuid = rootuid; 56238460Smckusick ep->ex_exflags = exflags; 56344015Smckusick } else { 56444015Smckusick ep->ex_rootuid = fep->ex_rootuid; 56544015Smckusick ep->ex_exflags = fep->ex_exflags; 56638460Smckusick } 56744015Smckusick ep->ex_dev = sb.st_dev; 56844015Smckusick ep->ex_next = exphead.ex_next; 56944015Smckusick ep->ex_prev = &exphead; 57044015Smckusick if (ep->ex_next != NULL) 57144015Smckusick ep->ex_next->ex_prev = ep; 57244015Smckusick exphead.ex_next = ep; 57344015Smckusick nextline: 57444015Smckusick ; 57538460Smckusick } 57638460Smckusick fclose(inf); 57738460Smckusick return; 57838460Smckusick err: 57939681Smckusick syslog(LOG_ERR, "Bad Exports File, mountd Failed"); 58038460Smckusick exit(2); 58138460Smckusick } 58238460Smckusick 58338460Smckusick /* 58438460Smckusick * Parse out the next white space separated field 58538460Smckusick */ 58638460Smckusick nextfield(cp, endcp) 58738460Smckusick char **cp; 58838460Smckusick char **endcp; 58938460Smckusick { 59038460Smckusick register char *p; 59138460Smckusick 59238460Smckusick p = *cp; 59338460Smckusick while (*p == ' ' || *p == '\t') 59438460Smckusick p++; 59538460Smckusick if (*p == '\n' || *p == '\0') { 59638460Smckusick *cp = *endcp = p; 59738460Smckusick return; 59838460Smckusick } 59938460Smckusick *cp = p++; 60038460Smckusick while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 60138460Smckusick p++; 60238460Smckusick *endcp = p; 60338460Smckusick } 60439681Smckusick 60539681Smckusick /* 60644015Smckusick * Parse the option string 60739681Smckusick */ 60844015Smckusick do_opt(cpopt, fep, ep, exflagsp, rootuidp) 60944015Smckusick register char *cpopt; 61044015Smckusick struct exportlist *fep, *ep; 61144015Smckusick int *exflagsp, *rootuidp; 61239681Smckusick { 61344015Smckusick register char *cpoptarg, *cpoptend; 61439681Smckusick 61544015Smckusick while (cpopt && *cpopt) { 61644015Smckusick if (cpoptend = index(cpopt, ',')) 61744015Smckusick *cpoptend++ = '\0'; 61844015Smckusick if (cpoptarg = index(cpopt, '=')) 61944015Smckusick *cpoptarg++ = '\0'; 62044015Smckusick if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 62144015Smckusick if (fep && (fep->ex_exflags & MNT_EXRDONLY) == 0) 62244015Smckusick syslog(LOG_WARNING, "ro failed for %s", 62344015Smckusick ep->ex_dirp); 62444015Smckusick else 62544015Smckusick *exflagsp |= MNT_EXRDONLY; 62644015Smckusick } else if (!strcmp(cpopt, "root") || !strcmp(cpopt, "r")) { 62744015Smckusick if (cpoptarg && isdigit(*cpoptarg)) { 62844015Smckusick *rootuidp = atoi(cpoptarg); 62944015Smckusick if (fep && fep->ex_rootuid != *rootuidp) 63044015Smckusick syslog(LOG_WARNING, 63144015Smckusick "uid failed for %s", 63244015Smckusick ep->ex_dirp); 63344015Smckusick } else 63444015Smckusick syslog(LOG_WARNING, 63544015Smckusick "uid failed for %s", 63644015Smckusick ep->ex_dirp); 63744015Smckusick } else 63844015Smckusick syslog(LOG_WARNING, "opt %s ignored for %s", cpopt, 63944015Smckusick ep->ex_dirp); 64044015Smckusick cpopt = cpoptend; 64144015Smckusick } 64244015Smckusick } 64344015Smckusick 64444015Smckusick #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 64544015Smckusick /* 64644015Smckusick * Routines that maintain the remote mounttab 64744015Smckusick */ 64844015Smckusick void get_mountlist() 64944015Smckusick { 65044015Smckusick register struct mountlist *mlp, **mlpp; 65144015Smckusick register char *eos, *dirp; 65244015Smckusick int len; 65344015Smckusick char str[STRSIZ]; 65444015Smckusick FILE *mlfile; 65544015Smckusick 65644338Smckusick if (((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) && 65744338Smckusick ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL)) { 65844015Smckusick syslog(LOG_WARNING, "Can't open %s", _PATH_RMOUNTLIST); 65944015Smckusick return; 66044015Smckusick } 66144015Smckusick mlpp = &mlhead; 66244015Smckusick while (fgets(str, STRSIZ, mlfile) != NULL) { 66344015Smckusick if ((dirp = index(str, '\t')) == NULL && 66444015Smckusick (dirp = index(str, ' ')) == NULL) 66544015Smckusick continue; 66644015Smckusick mlp = (struct mountlist *)malloc(sizeof (*mlp)); 66744015Smckusick len = dirp-str; 66844015Smckusick if (len > RPCMNT_NAMELEN) 66944015Smckusick len = RPCMNT_NAMELEN; 67044015Smckusick bcopy(str, mlp->ml_host, len); 67144015Smckusick mlp->ml_host[len] = '\0'; 67244015Smckusick while (*dirp == '\t' || *dirp == ' ') 67344015Smckusick dirp++; 67444015Smckusick if ((eos = index(dirp, '\t')) == NULL && 67544015Smckusick (eos = index(dirp, ' ')) == NULL && 67644015Smckusick (eos = index(dirp, '\n')) == NULL) 67744015Smckusick len = strlen(dirp); 67844015Smckusick else 67944015Smckusick len = eos-dirp; 68044015Smckusick if (len > RPCMNT_PATHLEN) 68144015Smckusick len = RPCMNT_PATHLEN; 68244015Smckusick bcopy(dirp, mlp->ml_dirp, len); 68344015Smckusick mlp->ml_dirp[len] = '\0'; 68444015Smckusick mlp->ml_next = (struct mountlist *)0; 68544015Smckusick *mlpp = mlp; 68644015Smckusick mlpp = &mlp->ml_next; 68744015Smckusick } 68844015Smckusick fclose(mlfile); 68944015Smckusick } 69044015Smckusick 69144015Smckusick void del_mlist(hostp, dirp) 69244015Smckusick register char *hostp, *dirp; 69344015Smckusick { 69444015Smckusick register struct mountlist *mlp, **mlpp; 69544015Smckusick FILE *mlfile; 69644015Smckusick int fnd = 0; 69744015Smckusick 69844015Smckusick mlpp = &mlhead; 69944015Smckusick mlp = mlhead; 70044015Smckusick while (mlp) { 70144015Smckusick if (!strcmp(mlp->ml_host, hostp) && 70244015Smckusick (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 70344015Smckusick fnd = 1; 70444015Smckusick *mlpp = mlp->ml_next; 70544015Smckusick free((caddr_t)mlp); 70639681Smckusick } 70744015Smckusick mlpp = &mlp->ml_next; 70844015Smckusick mlp = mlp->ml_next; 70939681Smckusick } 71044015Smckusick if (fnd) { 71144015Smckusick if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 71244015Smckusick syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST); 71344015Smckusick return; 71444015Smckusick } 71544015Smckusick mlp = mlhead; 71644015Smckusick while (mlp) { 71744015Smckusick fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 71844015Smckusick mlp = mlp->ml_next; 71944015Smckusick } 72044015Smckusick fclose(mlfile); 72144015Smckusick } 72239681Smckusick } 72344015Smckusick 72444015Smckusick void add_mlist(hostp, dirp) 72544015Smckusick register char *hostp, *dirp; 72644015Smckusick { 72744015Smckusick register struct mountlist *mlp, **mlpp; 72844015Smckusick FILE *mlfile; 72944015Smckusick 73044015Smckusick mlpp = &mlhead; 73144015Smckusick mlp = mlhead; 73244015Smckusick while (mlp) { 73344015Smckusick if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 73444015Smckusick return; 73544015Smckusick mlpp = &mlp->ml_next; 73644015Smckusick mlp = mlp->ml_next; 73744015Smckusick } 73844015Smckusick mlp = (struct mountlist *)malloc(sizeof (*mlp)); 73944015Smckusick strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 74044015Smckusick mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 74144015Smckusick strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 74244015Smckusick mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 74344015Smckusick mlp->ml_next = (struct mountlist *)0; 74444015Smckusick *mlpp = mlp; 74544015Smckusick if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 74644015Smckusick syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST); 74744015Smckusick return; 74844015Smckusick } 74944015Smckusick fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 75044015Smckusick fclose(mlfile); 75144015Smckusick } 75244015Smckusick 75344015Smckusick /* 75444015Smckusick * This function is called via. SIGTERM when the system is going down. 75544015Smckusick * It sends a broadcast RPCMNT_UMNTALL. 75644015Smckusick */ 75744015Smckusick send_umntall() 75844015Smckusick { 75944015Smckusick (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL, 76044015Smckusick xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each); 76144015Smckusick exit(); 76244015Smckusick } 76344015Smckusick 76444015Smckusick umntall_each(resultsp, raddr) 76544015Smckusick caddr_t resultsp; 76644015Smckusick struct sockaddr_in *raddr; 76744015Smckusick { 76844015Smckusick return (1); 76944015Smckusick } 77044015Smckusick 77144015Smckusick /* 77244015Smckusick * Free up an exports list component 77344015Smckusick */ 77444015Smckusick free_exp(ep) 77544015Smckusick register struct exportlist *ep; 77644015Smckusick { 77744015Smckusick register struct grouplist *grp; 77844015Smckusick register char **addrp; 77944015Smckusick struct grouplist *grp2; 78044015Smckusick 78144015Smckusick grp = ep->ex_groups; 78244015Smckusick while (grp != NULL) { 78344015Smckusick addrp = grp->gr_hp->h_addr_list; 78444015Smckusick while (*addrp) 78544015Smckusick free(*addrp++); 78644015Smckusick free((caddr_t)grp->gr_hp->h_addr_list); 78744015Smckusick free(grp->gr_hp->h_name); 78844015Smckusick free((caddr_t)grp->gr_hp); 78944015Smckusick grp2 = grp; 79044015Smckusick grp = grp->gr_next; 79144015Smckusick free((caddr_t)grp2); 79244015Smckusick } 79344015Smckusick free((caddr_t)ep); 79444015Smckusick } 795