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*44338Smckusick static char sccsid[] = "@(#)mountd.c 5.10 (Berkeley) 06/27/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); 119*44338Smckusick openlog("mountd:", LOG_PID, LOG_DAEMON); 12044015Smckusick get_exportlist(); 12144015Smckusick get_mountlist(); 12238460Smckusick if (debug == 0) { 12338460Smckusick if (fork()) 12438460Smckusick exit(0); 12538460Smckusick { int s; 12638460Smckusick for (s = 0; s < 10; s++) 12738460Smckusick (void) close(s); 12838460Smckusick } 12938460Smckusick (void) open("/", O_RDONLY); 13038460Smckusick (void) dup2(0, 1); 13138460Smckusick (void) dup2(0, 2); 13238460Smckusick { int tt = open("/dev/tty", O_RDWR); 13338460Smckusick if (tt > 0) { 13438460Smckusick ioctl(tt, TIOCNOTTY, (char *)0); 13538460Smckusick close(tt); 13638460Smckusick } 13738460Smckusick } 13838460Smckusick (void) setpgrp(0, 0); 13938460Smckusick signal(SIGTSTP, SIG_IGN); 14038460Smckusick signal(SIGTTIN, SIG_IGN); 14138460Smckusick signal(SIGTTOU, SIG_IGN); 14238460Smckusick signal(SIGINT, SIG_IGN); 14338460Smckusick signal(SIGQUIT, SIG_IGN); 14438460Smckusick } 14538460Smckusick signal(SIGHUP, get_exportlist); 14644015Smckusick signal(SIGTERM, send_umntall); 14740494Smckusick { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); 14840494Smckusick if (pidfile != NULL) { 14940494Smckusick fprintf(pidfile, "%d\n", getpid()); 15040494Smckusick fclose(pidfile); 15140494Smckusick } 15240494Smckusick } 15338460Smckusick if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL) { 15438460Smckusick syslog(LOG_ERR, "Can't create socket"); 15538460Smckusick exit(1); 15638460Smckusick } 15738460Smckusick pmap_unset(RPCPROG_MNT, RPCMNT_VER1); 15838460Smckusick if (!svc_register(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv, IPPROTO_UDP)) { 15938460Smckusick syslog(LOG_ERR, "Can't register mount"); 16038460Smckusick exit(1); 16138460Smckusick } 16238460Smckusick svc_run(); 16338460Smckusick syslog(LOG_ERR, "Mountd died"); 16438460Smckusick } 16538460Smckusick 16638460Smckusick /* 16738460Smckusick * The mount rpc service 16838460Smckusick */ 16938460Smckusick mntsrv(rqstp, transp) 17038460Smckusick register struct svc_req *rqstp; 17138460Smckusick register SVCXPRT *transp; 17238460Smckusick { 17339681Smckusick register struct grouplist *grp; 17439681Smckusick register u_long **addrp; 17538460Smckusick register struct exportlist *ep; 17638460Smckusick nfsv2fh_t nfh; 17738460Smckusick struct authunix_parms *ucr; 17838460Smckusick struct stat stb; 17938460Smckusick struct hostent *hp; 18039681Smckusick u_long saddr; 18138460Smckusick char dirpath[RPCMNT_PATHLEN+1]; 18238460Smckusick int bad = ENOENT; 18338460Smckusick int omask; 18439681Smckusick uid_t uid = -2; 18538460Smckusick 18638460Smckusick /* Get authorization */ 18738460Smckusick switch (rqstp->rq_cred.oa_flavor) { 18838460Smckusick case AUTH_UNIX: 18938460Smckusick ucr = (struct authunix_parms *)rqstp->rq_clntcred; 19039681Smckusick uid = ucr->aup_uid; 19139681Smckusick break; 19238460Smckusick case AUTH_NULL: 19338460Smckusick default: 19439681Smckusick break; 19538460Smckusick } 19638460Smckusick 19739681Smckusick saddr = transp->xp_raddr.sin_addr.s_addr; 19839681Smckusick hp = (struct hostent *)0; 19938460Smckusick switch (rqstp->rq_proc) { 20039681Smckusick case NULLPROC: 20139681Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 20239681Smckusick syslog(LOG_ERR, "Can't send reply"); 20339681Smckusick return; 20438460Smckusick case RPCMNT_MOUNT: 20544015Smckusick if (uid != 0 && root_only) { 20639681Smckusick svcerr_weakauth(transp); 20739681Smckusick return; 20839681Smckusick } 20938460Smckusick if (!svc_getargs(transp, xdr_dir, dirpath)) { 21038460Smckusick svcerr_decode(transp); 21138460Smckusick return; 21238460Smckusick } 21338460Smckusick 21438460Smckusick /* Check to see if it's a valid dirpath */ 21538460Smckusick if (stat(dirpath, &stb) < 0 || (stb.st_mode&S_IFMT) != 21638460Smckusick S_IFDIR) { 21738460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 21838460Smckusick syslog(LOG_ERR, "Can't send reply"); 21938460Smckusick return; 22038460Smckusick } 22138460Smckusick 22238460Smckusick /* Check in the exports list */ 22338460Smckusick omask = sigblock(sigmask(SIGHUP)); 22438460Smckusick ep = exphead.ex_next; 22538460Smckusick while (ep != NULL) { 22638460Smckusick if (!strcmp(ep->ex_dirp, dirpath)) { 22738460Smckusick grp = ep->ex_groups; 22838460Smckusick if (grp == NULL) 22938460Smckusick break; 23039681Smckusick 23139681Smckusick /* Check for a host match */ 23239681Smckusick addrp = (u_long **)grp->gr_hp->h_addr_list; 23339681Smckusick for (;;) { 23439681Smckusick if (**addrp == saddr) 23538460Smckusick break; 23639681Smckusick if (*++addrp == NULL) 23739681Smckusick if (grp = grp->gr_next) { 23839681Smckusick addrp = (u_long **) 23939681Smckusick grp->gr_hp->h_addr_list; 24039681Smckusick } else { 24139681Smckusick bad = EACCES; 24239681Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 24339681Smckusick syslog(LOG_ERR, "Can't send reply"); 24439681Smckusick sigsetmask(omask); 24539681Smckusick return; 24639681Smckusick } 24738460Smckusick } 24839681Smckusick hp = grp->gr_hp; 24939681Smckusick break; 25038460Smckusick } 25138460Smckusick ep = ep->ex_next; 25238460Smckusick } 25338460Smckusick sigsetmask(omask); 25438460Smckusick if (ep == NULL) { 25538460Smckusick bad = EACCES; 25638460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 25738460Smckusick syslog(LOG_ERR, "Can't send reply"); 25838460Smckusick return; 25938460Smckusick } 26038460Smckusick 26138460Smckusick /* Get the file handle */ 26238460Smckusick bzero((caddr_t)&nfh, sizeof(nfh)); 26338460Smckusick if (getfh(dirpath, (fhandle_t *)&nfh) < 0) { 26438460Smckusick bad = errno; 26538460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 26638460Smckusick syslog(LOG_ERR, "Can't send reply"); 26738460Smckusick return; 26838460Smckusick } 26938460Smckusick if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh)) 27038460Smckusick syslog(LOG_ERR, "Can't send reply"); 27139681Smckusick if (hp == NULL) 27239681Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 27344015Smckusick if (hp) 27444015Smckusick add_mlist(hp->h_name, dirpath); 27538460Smckusick return; 27638460Smckusick case RPCMNT_DUMP: 27738460Smckusick if (!svc_sendreply(transp, xdr_mlist, (caddr_t)0)) 27838460Smckusick syslog(LOG_ERR, "Can't send reply"); 27938460Smckusick return; 28038460Smckusick case RPCMNT_UMOUNT: 28144015Smckusick if (uid != 0 && root_only) { 28239681Smckusick svcerr_weakauth(transp); 28339681Smckusick return; 28439681Smckusick } 28538460Smckusick if (!svc_getargs(transp, xdr_dir, dirpath)) { 28638460Smckusick svcerr_decode(transp); 28738460Smckusick return; 28838460Smckusick } 28938460Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 29038460Smckusick syslog(LOG_ERR, "Can't send reply"); 29144015Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 29244015Smckusick if (hp) 29344015Smckusick del_mlist(hp->h_name, dirpath); 29438460Smckusick return; 29538460Smckusick case RPCMNT_UMNTALL: 29644015Smckusick if (uid != 0 && root_only) { 29739681Smckusick svcerr_weakauth(transp); 29839681Smckusick return; 29939681Smckusick } 30038460Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 30138460Smckusick syslog(LOG_ERR, "Can't send reply"); 30244015Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 30344015Smckusick if (hp) 30444015Smckusick del_mlist(hp->h_name, (char *)0); 30538460Smckusick return; 30638460Smckusick case RPCMNT_EXPORT: 30738460Smckusick if (!svc_sendreply(transp, xdr_explist, (caddr_t)0)) 30838460Smckusick syslog(LOG_ERR, "Can't send reply"); 30938460Smckusick return; 31038460Smckusick default: 31138460Smckusick svcerr_noproc(transp); 31238460Smckusick return; 31338460Smckusick } 31438460Smckusick } 31538460Smckusick 31638460Smckusick /* 31738460Smckusick * Xdr conversion for a dirpath string 31838460Smckusick */ 31938460Smckusick xdr_dir(xdrsp, dirp) 32038460Smckusick XDR *xdrsp; 32138460Smckusick char *dirp; 32238460Smckusick { 32338460Smckusick return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 32438460Smckusick } 32538460Smckusick 32638460Smckusick /* 32738460Smckusick * Xdr routine to generate fhstatus 32838460Smckusick */ 32938460Smckusick xdr_fhs(xdrsp, nfh) 33038460Smckusick XDR *xdrsp; 33138460Smckusick nfsv2fh_t *nfh; 33238460Smckusick { 33338460Smckusick int ok = 0; 33438460Smckusick 33538460Smckusick if (!xdr_long(xdrsp, &ok)) 33638460Smckusick return (0); 33738460Smckusick return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH)); 33838460Smckusick } 33938460Smckusick 34038460Smckusick xdr_mlist(xdrsp, cp) 34138460Smckusick XDR *xdrsp; 34238460Smckusick caddr_t cp; 34338460Smckusick { 34444015Smckusick register struct mountlist *mlp; 34538460Smckusick int true = 1; 34638460Smckusick int false = 0; 34738460Smckusick char *strp; 34838460Smckusick 34944015Smckusick mlp = mlhead; 35044015Smckusick while (mlp) { 35144015Smckusick if (!xdr_bool(xdrsp, &true)) 35244015Smckusick return (0); 35344015Smckusick strp = &mlp->ml_host[0]; 35444015Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 35544015Smckusick return (0); 35644015Smckusick strp = &mlp->ml_dirp[0]; 35744015Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 35844015Smckusick return (0); 35944015Smckusick mlp = mlp->ml_next; 36038460Smckusick } 36138460Smckusick if (!xdr_bool(xdrsp, &false)) 36238460Smckusick return (0); 36338460Smckusick return (1); 36438460Smckusick } 36538460Smckusick 36638460Smckusick /* 36738460Smckusick * Xdr conversion for export list 36838460Smckusick */ 36938460Smckusick xdr_explist(xdrsp, cp) 37038460Smckusick XDR *xdrsp; 37138460Smckusick caddr_t cp; 37238460Smckusick { 37338460Smckusick register struct exportlist *ep; 37438460Smckusick register struct grouplist *grp; 37538460Smckusick int true = 1; 37638460Smckusick int false = 0; 37738460Smckusick char *strp; 37838460Smckusick int omask; 37938460Smckusick 38038460Smckusick omask = sigblock(sigmask(SIGHUP)); 38138460Smckusick ep = exphead.ex_next; 38238460Smckusick while (ep != NULL) { 38338460Smckusick if (!xdr_bool(xdrsp, &true)) 38438460Smckusick goto errout; 38538460Smckusick strp = &ep->ex_dirp[0]; 38638460Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 38738460Smckusick goto errout; 38838460Smckusick grp = ep->ex_groups; 38938460Smckusick while (grp != NULL) { 39038460Smckusick if (!xdr_bool(xdrsp, &true)) 39138460Smckusick goto errout; 39239681Smckusick strp = grp->gr_hp->h_name; 39338460Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 39438460Smckusick goto errout; 39538460Smckusick grp = grp->gr_next; 39638460Smckusick } 39738460Smckusick if (!xdr_bool(xdrsp, &false)) 39838460Smckusick goto errout; 39938460Smckusick ep = ep->ex_next; 40038460Smckusick } 40138460Smckusick sigsetmask(omask); 40238460Smckusick if (!xdr_bool(xdrsp, &false)) 40338460Smckusick return (0); 40438460Smckusick return (1); 40538460Smckusick errout: 40638460Smckusick sigsetmask(omask); 40738460Smckusick return (0); 40838460Smckusick } 40938460Smckusick 41038460Smckusick #define LINESIZ 10240 41138460Smckusick char line[LINESIZ]; 41238460Smckusick 41338460Smckusick /* 41438460Smckusick * Get the export list 41538460Smckusick */ 41638460Smckusick get_exportlist() 41738460Smckusick { 41839681Smckusick register struct hostent *hp, *nhp; 41939681Smckusick register char **addrp, **naddrp; 42039681Smckusick register int i; 42144015Smckusick register struct grouplist *grp; 42238460Smckusick register struct exportlist *ep, *ep2; 42340368Smckusick struct ufs_args args; 42444015Smckusick struct stat sb; 42538460Smckusick FILE *inf; 42638460Smckusick char *cp, *endcp; 42739681Smckusick char savedc; 42844015Smckusick int len, dirplen; 42938460Smckusick int rootuid, exflags; 43044015Smckusick u_long saddr; 43144015Smckusick struct exportlist *fep; 43238460Smckusick 43338460Smckusick /* 43438460Smckusick * First, get rid of the old list 43538460Smckusick */ 43638460Smckusick ep = exphead.ex_next; 43738460Smckusick while (ep != NULL) { 43838460Smckusick ep2 = ep; 43938460Smckusick ep = ep->ex_next; 44044015Smckusick free_exp(ep2); 44138460Smckusick } 44238460Smckusick 44338460Smckusick /* 44438460Smckusick * Read in the exports file and build the list, calling 44538460Smckusick * exportfs() as we go along 44638460Smckusick */ 44738460Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 44838460Smckusick if ((inf = fopen(exname, "r")) == NULL) { 44938460Smckusick syslog(LOG_ERR, "Can't open %s", exname); 45038460Smckusick exit(2); 45138460Smckusick } 45238460Smckusick while (fgets(line, LINESIZ, inf)) { 45341404Smckusick exflags = MNT_EXPORTED; 45438460Smckusick rootuid = def_rootuid; 45538460Smckusick cp = line; 45638460Smckusick nextfield(&cp, &endcp); 45744015Smckusick 45844015Smckusick /* 45944015Smckusick * Get file system devno and see if an entry for this 46044015Smckusick * file system already exists. 46144015Smckusick */ 46244015Smckusick savedc = *endcp; 46344015Smckusick *endcp = '\0'; 46444015Smckusick if (stat(cp, &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFDIR) 46544015Smckusick goto err; 46644015Smckusick fep = (struct exportlist *)0; 46744015Smckusick ep = exphead.ex_next; 46844015Smckusick while (ep) { 46944015Smckusick if (ep->ex_dev == sb.st_dev) { 47044015Smckusick fep = ep; 47144015Smckusick break; 47244015Smckusick } 47344015Smckusick ep = ep->ex_next; 47444015Smckusick } 47544015Smckusick *endcp = savedc; 47644015Smckusick 47744015Smckusick /* 47844015Smckusick * Create new exports list entry 47944015Smckusick */ 48038460Smckusick len = endcp-cp; 48138460Smckusick if (len <= RPCMNT_PATHLEN && len > 0) { 48238460Smckusick ep = (struct exportlist *)malloc(sizeof(*ep)); 48338460Smckusick ep->ex_next = ep->ex_prev = (struct exportlist *)0; 48438460Smckusick ep->ex_groups = (struct grouplist *)0; 48538460Smckusick bcopy(cp, ep->ex_dirp, len); 48638460Smckusick ep->ex_dirp[len] = '\0'; 48744015Smckusick dirplen = len; 48838460Smckusick } else 48938460Smckusick goto err; 49038460Smckusick cp = endcp; 49138460Smckusick nextfield(&cp, &endcp); 49238460Smckusick len = endcp-cp; 49338460Smckusick while (len > 0) { 49439681Smckusick savedc = *endcp; 49539681Smckusick *endcp = '\0'; 49638460Smckusick if (len <= RPCMNT_NAMELEN) { 49738460Smckusick if (*cp == '-') { 49844015Smckusick do_opt(cp+1, fep, ep, &exflags, &rootuid); 49944015Smckusick } else { 50044015Smckusick if (isdigit(*cp)) { 50144015Smckusick saddr = inet_addr(cp); 50244015Smckusick if (saddr == -1 || 50344015Smckusick (hp = gethostbyaddr((caddr_t)&saddr, 50444015Smckusick sizeof(saddr), AF_INET)) == NULL) 50538460Smckusick goto err; 50644015Smckusick } else if ((hp = gethostbyname(cp)) == NULL) 50744015Smckusick goto err; 50844015Smckusick grp = (struct grouplist *) 50944015Smckusick malloc(sizeof(struct grouplist)); 51044015Smckusick if (grp == NULL) 51144015Smckusick goto err; 51244015Smckusick nhp = grp->gr_hp = (struct hostent *) 51344015Smckusick malloc(sizeof(struct hostent)); 51444015Smckusick if (nhp == NULL) 51544015Smckusick goto err; 51644015Smckusick bcopy((caddr_t)hp, (caddr_t)nhp, 51744015Smckusick sizeof(struct hostent)); 51844015Smckusick i = strlen(hp->h_name)+1; 51944015Smckusick nhp->h_name = (char *)malloc(i); 52044015Smckusick if (nhp->h_name == NULL) 52144015Smckusick goto err; 52244015Smckusick bcopy(hp->h_name, nhp->h_name, i); 52344015Smckusick addrp = hp->h_addr_list; 52444015Smckusick i = 1; 52544015Smckusick while (*addrp++) 52644015Smckusick i++; 52744015Smckusick naddrp = nhp->h_addr_list = (char **) 52844015Smckusick malloc(i*sizeof(char *)); 52944015Smckusick if (naddrp == NULL) 53044015Smckusick goto err; 53144015Smckusick addrp = hp->h_addr_list; 53244015Smckusick while (*addrp) { 53344015Smckusick *naddrp = (char *) 53444015Smckusick malloc(hp->h_length); 53544015Smckusick if (*naddrp == NULL) 53639681Smckusick goto err; 53744015Smckusick bcopy(*addrp, *naddrp, 53844015Smckusick hp->h_length); 53944015Smckusick addrp++; 54044015Smckusick naddrp++; 54144015Smckusick } 54244015Smckusick *naddrp = (char *)0; 54344015Smckusick grp->gr_next = ep->ex_groups; 54444015Smckusick ep->ex_groups = grp; 54538460Smckusick } 54638460Smckusick } 54738460Smckusick cp = endcp; 54839681Smckusick *cp = savedc; 54938460Smckusick nextfield(&cp, &endcp); 55038460Smckusick len = endcp-cp; 55138460Smckusick } 55244015Smckusick if (fep == NULL) { 55344015Smckusick args.fspec = 0; 55444015Smckusick args.exflags = exflags; 55544015Smckusick args.exroot = rootuid; 55644015Smckusick cp = (char *)0; 55744015Smckusick while (mount(MOUNT_UFS, ep->ex_dirp, MNT_UPDATE, &args) < 0) { 55844015Smckusick if (cp == NULL) 55944015Smckusick cp = ep->ex_dirp + dirplen - 1; 56044015Smckusick else 56144015Smckusick *cp = savedc; 56244015Smckusick /* back up over the last component */ 56344015Smckusick while (*cp == '/' && cp > ep->ex_dirp) 56444015Smckusick cp--; 56544015Smckusick while (*(cp - 1) != '/' && cp > ep->ex_dirp) 56644015Smckusick cp--; 56744015Smckusick if (cp == ep->ex_dirp) { 56844015Smckusick syslog(LOG_WARNING, 56944015Smckusick "Can't export %s", ep->ex_dirp); 57044015Smckusick free_exp(ep); 57144015Smckusick goto nextline; 57244015Smckusick } 57344015Smckusick savedc = *cp; 57444015Smckusick *cp = '\0'; 57544015Smckusick } 57644015Smckusick if (cp) 57744015Smckusick *cp = savedc; 57838460Smckusick ep->ex_rootuid = rootuid; 57938460Smckusick ep->ex_exflags = exflags; 58044015Smckusick } else { 58144015Smckusick ep->ex_rootuid = fep->ex_rootuid; 58244015Smckusick ep->ex_exflags = fep->ex_exflags; 58338460Smckusick } 58444015Smckusick ep->ex_dev = sb.st_dev; 58544015Smckusick ep->ex_next = exphead.ex_next; 58644015Smckusick ep->ex_prev = &exphead; 58744015Smckusick if (ep->ex_next != NULL) 58844015Smckusick ep->ex_next->ex_prev = ep; 58944015Smckusick exphead.ex_next = ep; 59044015Smckusick nextline: 59144015Smckusick ; 59238460Smckusick } 59338460Smckusick fclose(inf); 59438460Smckusick return; 59538460Smckusick err: 59639681Smckusick syslog(LOG_ERR, "Bad Exports File, mountd Failed"); 59738460Smckusick exit(2); 59838460Smckusick } 59938460Smckusick 60038460Smckusick /* 60138460Smckusick * Parse out the next white space separated field 60238460Smckusick */ 60338460Smckusick nextfield(cp, endcp) 60438460Smckusick char **cp; 60538460Smckusick char **endcp; 60638460Smckusick { 60738460Smckusick register char *p; 60838460Smckusick 60938460Smckusick p = *cp; 61038460Smckusick while (*p == ' ' || *p == '\t') 61138460Smckusick p++; 61238460Smckusick if (*p == '\n' || *p == '\0') { 61338460Smckusick *cp = *endcp = p; 61438460Smckusick return; 61538460Smckusick } 61638460Smckusick *cp = p++; 61738460Smckusick while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 61838460Smckusick p++; 61938460Smckusick *endcp = p; 62038460Smckusick } 62139681Smckusick 62239681Smckusick /* 62344015Smckusick * Parse the option string 62439681Smckusick */ 62544015Smckusick do_opt(cpopt, fep, ep, exflagsp, rootuidp) 62644015Smckusick register char *cpopt; 62744015Smckusick struct exportlist *fep, *ep; 62844015Smckusick int *exflagsp, *rootuidp; 62939681Smckusick { 63044015Smckusick register char *cpoptarg, *cpoptend; 63139681Smckusick 63244015Smckusick while (cpopt && *cpopt) { 63344015Smckusick if (cpoptend = index(cpopt, ',')) 63444015Smckusick *cpoptend++ = '\0'; 63544015Smckusick if (cpoptarg = index(cpopt, '=')) 63644015Smckusick *cpoptarg++ = '\0'; 63744015Smckusick if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 63844015Smckusick if (fep && (fep->ex_exflags & MNT_EXRDONLY) == 0) 63944015Smckusick syslog(LOG_WARNING, "ro failed for %s", 64044015Smckusick ep->ex_dirp); 64144015Smckusick else 64244015Smckusick *exflagsp |= MNT_EXRDONLY; 64344015Smckusick } else if (!strcmp(cpopt, "root") || !strcmp(cpopt, "r")) { 64444015Smckusick if (cpoptarg && isdigit(*cpoptarg)) { 64544015Smckusick *rootuidp = atoi(cpoptarg); 64644015Smckusick if (fep && fep->ex_rootuid != *rootuidp) 64744015Smckusick syslog(LOG_WARNING, 64844015Smckusick "uid failed for %s", 64944015Smckusick ep->ex_dirp); 65044015Smckusick } else 65144015Smckusick syslog(LOG_WARNING, 65244015Smckusick "uid failed for %s", 65344015Smckusick ep->ex_dirp); 65444015Smckusick } else 65544015Smckusick syslog(LOG_WARNING, "opt %s ignored for %s", cpopt, 65644015Smckusick ep->ex_dirp); 65744015Smckusick cpopt = cpoptend; 65844015Smckusick } 65944015Smckusick } 66044015Smckusick 66144015Smckusick #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 66244015Smckusick /* 66344015Smckusick * Routines that maintain the remote mounttab 66444015Smckusick */ 66544015Smckusick void get_mountlist() 66644015Smckusick { 66744015Smckusick register struct mountlist *mlp, **mlpp; 66844015Smckusick register char *eos, *dirp; 66944015Smckusick int len; 67044015Smckusick char str[STRSIZ]; 67144015Smckusick FILE *mlfile; 67244015Smckusick 673*44338Smckusick if (((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) && 674*44338Smckusick ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL)) { 67544015Smckusick syslog(LOG_WARNING, "Can't open %s", _PATH_RMOUNTLIST); 67644015Smckusick return; 67744015Smckusick } 67844015Smckusick mlpp = &mlhead; 67944015Smckusick while (fgets(str, STRSIZ, mlfile) != NULL) { 68044015Smckusick if ((dirp = index(str, '\t')) == NULL && 68144015Smckusick (dirp = index(str, ' ')) == NULL) 68244015Smckusick continue; 68344015Smckusick mlp = (struct mountlist *)malloc(sizeof (*mlp)); 68444015Smckusick len = dirp-str; 68544015Smckusick if (len > RPCMNT_NAMELEN) 68644015Smckusick len = RPCMNT_NAMELEN; 68744015Smckusick bcopy(str, mlp->ml_host, len); 68844015Smckusick mlp->ml_host[len] = '\0'; 68944015Smckusick while (*dirp == '\t' || *dirp == ' ') 69044015Smckusick dirp++; 69144015Smckusick if ((eos = index(dirp, '\t')) == NULL && 69244015Smckusick (eos = index(dirp, ' ')) == NULL && 69344015Smckusick (eos = index(dirp, '\n')) == NULL) 69444015Smckusick len = strlen(dirp); 69544015Smckusick else 69644015Smckusick len = eos-dirp; 69744015Smckusick if (len > RPCMNT_PATHLEN) 69844015Smckusick len = RPCMNT_PATHLEN; 69944015Smckusick bcopy(dirp, mlp->ml_dirp, len); 70044015Smckusick mlp->ml_dirp[len] = '\0'; 70144015Smckusick mlp->ml_next = (struct mountlist *)0; 70244015Smckusick *mlpp = mlp; 70344015Smckusick mlpp = &mlp->ml_next; 70444015Smckusick } 70544015Smckusick fclose(mlfile); 70644015Smckusick } 70744015Smckusick 70844015Smckusick void del_mlist(hostp, dirp) 70944015Smckusick register char *hostp, *dirp; 71044015Smckusick { 71144015Smckusick register struct mountlist *mlp, **mlpp; 71244015Smckusick FILE *mlfile; 71344015Smckusick int fnd = 0; 71444015Smckusick 71544015Smckusick mlpp = &mlhead; 71644015Smckusick mlp = mlhead; 71744015Smckusick while (mlp) { 71844015Smckusick if (!strcmp(mlp->ml_host, hostp) && 71944015Smckusick (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 72044015Smckusick fnd = 1; 72144015Smckusick *mlpp = mlp->ml_next; 72244015Smckusick free((caddr_t)mlp); 72339681Smckusick } 72444015Smckusick mlpp = &mlp->ml_next; 72544015Smckusick mlp = mlp->ml_next; 72639681Smckusick } 72744015Smckusick if (fnd) { 72844015Smckusick if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 72944015Smckusick syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST); 73044015Smckusick return; 73144015Smckusick } 73244015Smckusick mlp = mlhead; 73344015Smckusick while (mlp) { 73444015Smckusick fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 73544015Smckusick mlp = mlp->ml_next; 73644015Smckusick } 73744015Smckusick fclose(mlfile); 73844015Smckusick } 73939681Smckusick } 74044015Smckusick 74144015Smckusick void add_mlist(hostp, dirp) 74244015Smckusick register char *hostp, *dirp; 74344015Smckusick { 74444015Smckusick register struct mountlist *mlp, **mlpp; 74544015Smckusick FILE *mlfile; 74644015Smckusick 74744015Smckusick mlpp = &mlhead; 74844015Smckusick mlp = mlhead; 74944015Smckusick while (mlp) { 75044015Smckusick if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 75144015Smckusick return; 75244015Smckusick mlpp = &mlp->ml_next; 75344015Smckusick mlp = mlp->ml_next; 75444015Smckusick } 75544015Smckusick mlp = (struct mountlist *)malloc(sizeof (*mlp)); 75644015Smckusick strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 75744015Smckusick mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 75844015Smckusick strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 75944015Smckusick mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 76044015Smckusick mlp->ml_next = (struct mountlist *)0; 76144015Smckusick *mlpp = mlp; 76244015Smckusick if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 76344015Smckusick syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST); 76444015Smckusick return; 76544015Smckusick } 76644015Smckusick fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 76744015Smckusick fclose(mlfile); 76844015Smckusick } 76944015Smckusick 77044015Smckusick /* 77144015Smckusick * This function is called via. SIGTERM when the system is going down. 77244015Smckusick * It sends a broadcast RPCMNT_UMNTALL. 77344015Smckusick */ 77444015Smckusick send_umntall() 77544015Smckusick { 77644015Smckusick (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL, 77744015Smckusick xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each); 77844015Smckusick exit(); 77944015Smckusick } 78044015Smckusick 78144015Smckusick umntall_each(resultsp, raddr) 78244015Smckusick caddr_t resultsp; 78344015Smckusick struct sockaddr_in *raddr; 78444015Smckusick { 78544015Smckusick return (1); 78644015Smckusick } 78744015Smckusick 78844015Smckusick /* 78944015Smckusick * Free up an exports list component 79044015Smckusick */ 79144015Smckusick free_exp(ep) 79244015Smckusick register struct exportlist *ep; 79344015Smckusick { 79444015Smckusick register struct grouplist *grp; 79544015Smckusick register char **addrp; 79644015Smckusick struct grouplist *grp2; 79744015Smckusick 79844015Smckusick grp = ep->ex_groups; 79944015Smckusick while (grp != NULL) { 80044015Smckusick addrp = grp->gr_hp->h_addr_list; 80144015Smckusick while (*addrp) 80244015Smckusick free(*addrp++); 80344015Smckusick free((caddr_t)grp->gr_hp->h_addr_list); 80444015Smckusick free(grp->gr_hp->h_name); 80544015Smckusick free((caddr_t)grp->gr_hp); 80644015Smckusick grp2 = grp; 80744015Smckusick grp = grp->gr_next; 80844015Smckusick free((caddr_t)grp2); 80944015Smckusick } 81044015Smckusick free((caddr_t)ep); 81144015Smckusick } 812