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*45271Smckusick static char sccsid[] = "@(#)mountd.c 5.13 (Berkeley) 09/30/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) { 12344690Skarels 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"); 14644690Skarels 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; 40645168Smckusick struct statfs stfsbuf; 40740368Smckusick struct ufs_args args; 40844015Smckusick struct stat sb; 40938460Smckusick FILE *inf; 41038460Smckusick char *cp, *endcp; 41139681Smckusick char savedc; 41244015Smckusick int len, dirplen; 41338460Smckusick int rootuid, exflags; 41444015Smckusick u_long saddr; 41544015Smckusick struct exportlist *fep; 41638460Smckusick 41738460Smckusick /* 41838460Smckusick * First, get rid of the old list 41938460Smckusick */ 42038460Smckusick ep = exphead.ex_next; 42138460Smckusick while (ep != NULL) { 42238460Smckusick ep2 = ep; 42338460Smckusick ep = ep->ex_next; 42444015Smckusick free_exp(ep2); 42538460Smckusick } 42638460Smckusick 42738460Smckusick /* 42838460Smckusick * Read in the exports file and build the list, calling 42938460Smckusick * exportfs() as we go along 43038460Smckusick */ 43138460Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 43238460Smckusick if ((inf = fopen(exname, "r")) == NULL) { 43338460Smckusick syslog(LOG_ERR, "Can't open %s", exname); 43438460Smckusick exit(2); 43538460Smckusick } 43638460Smckusick while (fgets(line, LINESIZ, inf)) { 43741404Smckusick exflags = MNT_EXPORTED; 43838460Smckusick rootuid = def_rootuid; 43938460Smckusick cp = line; 44038460Smckusick nextfield(&cp, &endcp); 44144015Smckusick 44244015Smckusick /* 44344015Smckusick * Get file system devno and see if an entry for this 44444015Smckusick * file system already exists. 44544015Smckusick */ 44644015Smckusick savedc = *endcp; 44744015Smckusick *endcp = '\0'; 448*45271Smckusick if (stat(cp, &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFDIR) { 449*45271Smckusick syslog(LOG_ERR, 450*45271Smckusick "Bad Exports File, %s: %s, mountd Failed", 451*45271Smckusick cp, "Not a directory"); 452*45271Smckusick exit(2); 453*45271Smckusick } 45444015Smckusick fep = (struct exportlist *)0; 45544015Smckusick ep = exphead.ex_next; 45644015Smckusick while (ep) { 45744015Smckusick if (ep->ex_dev == sb.st_dev) { 45844015Smckusick fep = ep; 45944015Smckusick break; 46044015Smckusick } 46144015Smckusick ep = ep->ex_next; 46244015Smckusick } 46344015Smckusick *endcp = savedc; 46444015Smckusick 46544015Smckusick /* 46644015Smckusick * Create new exports list entry 46744015Smckusick */ 46838460Smckusick len = endcp-cp; 46938460Smckusick if (len <= RPCMNT_PATHLEN && len > 0) { 47038460Smckusick ep = (struct exportlist *)malloc(sizeof(*ep)); 471*45271Smckusick if (ep == NULL) 472*45271Smckusick goto err; 47338460Smckusick ep->ex_next = ep->ex_prev = (struct exportlist *)0; 47438460Smckusick ep->ex_groups = (struct grouplist *)0; 47538460Smckusick bcopy(cp, ep->ex_dirp, len); 47638460Smckusick ep->ex_dirp[len] = '\0'; 47744015Smckusick dirplen = len; 478*45271Smckusick } else { 479*45271Smckusick syslog(LOG_ERR, "Bad Exports File, mountd Failed"); 480*45271Smckusick exit(2); 481*45271Smckusick } 48238460Smckusick cp = endcp; 48338460Smckusick nextfield(&cp, &endcp); 48438460Smckusick len = endcp-cp; 48538460Smckusick while (len > 0) { 48639681Smckusick savedc = *endcp; 48739681Smckusick *endcp = '\0'; 488*45271Smckusick if (len > RPCMNT_NAMELEN) 489*45271Smckusick goto more; 490*45271Smckusick if (*cp == '-') { 491*45271Smckusick do_opt(cp + 1, fep, ep, &exflags, &rootuid); 492*45271Smckusick goto more; 493*45271Smckusick } 494*45271Smckusick if (isdigit(*cp)) { 495*45271Smckusick saddr = inet_addr(cp); 496*45271Smckusick if (saddr == -1 || 497*45271Smckusick (hp = gethostbyaddr((caddr_t)&saddr, 498*45271Smckusick sizeof(saddr), AF_INET)) == NULL) { 499*45271Smckusick syslog(LOG_ERR, 500*45271Smckusick "Bad Exports File, %s: %s", cp, 501*45271Smckusick "Gethostbyaddr failed, ignored"); 502*45271Smckusick goto more; 50338460Smckusick } 504*45271Smckusick } else if ((hp = gethostbyname(cp)) == NULL) { 505*45271Smckusick syslog(LOG_ERR, "Bad Exports File, %s: %s", 506*45271Smckusick cp, "Gethostbyname failed, ignored"); 507*45271Smckusick goto more; 50838460Smckusick } 509*45271Smckusick grp = (struct grouplist *) 510*45271Smckusick malloc(sizeof(struct grouplist)); 511*45271Smckusick if (grp == NULL) 512*45271Smckusick goto err; 513*45271Smckusick nhp = grp->gr_hp = (struct hostent *) 514*45271Smckusick malloc(sizeof(struct hostent)); 515*45271Smckusick if (nhp == NULL) 516*45271Smckusick goto err; 517*45271Smckusick bcopy((caddr_t)hp, (caddr_t)nhp, 518*45271Smckusick sizeof(struct hostent)); 519*45271Smckusick i = strlen(hp->h_name)+1; 520*45271Smckusick nhp->h_name = (char *)malloc(i); 521*45271Smckusick if (nhp->h_name == NULL) 522*45271Smckusick goto err; 523*45271Smckusick bcopy(hp->h_name, nhp->h_name, i); 524*45271Smckusick addrp = hp->h_addr_list; 525*45271Smckusick i = 1; 526*45271Smckusick while (*addrp++) 527*45271Smckusick i++; 528*45271Smckusick naddrp = nhp->h_addr_list = (char **) 529*45271Smckusick malloc(i*sizeof(char *)); 530*45271Smckusick if (naddrp == NULL) 531*45271Smckusick goto err; 532*45271Smckusick addrp = hp->h_addr_list; 533*45271Smckusick while (*addrp) { 534*45271Smckusick *naddrp = (char *) 535*45271Smckusick malloc(hp->h_length); 536*45271Smckusick if (*naddrp == NULL) 537*45271Smckusick goto err; 538*45271Smckusick bcopy(*addrp, *naddrp, 539*45271Smckusick hp->h_length); 540*45271Smckusick addrp++; 541*45271Smckusick naddrp++; 542*45271Smckusick } 543*45271Smckusick *naddrp = (char *)0; 544*45271Smckusick grp->gr_next = ep->ex_groups; 545*45271Smckusick ep->ex_groups = grp; 546*45271Smckusick more: 54738460Smckusick cp = endcp; 54839681Smckusick *cp = savedc; 54938460Smckusick nextfield(&cp, &endcp); 550*45271Smckusick len = endcp - cp; 55138460Smckusick } 55244015Smckusick if (fep == NULL) { 55344015Smckusick args.fspec = 0; 55444015Smckusick args.exflags = exflags; 55544015Smckusick args.exroot = rootuid; 55644015Smckusick cp = (char *)0; 55745168Smckusick while (statfs(ep->ex_dirp, &stfsbuf) < 0 || 55845168Smckusick mount(MOUNT_UFS, ep->ex_dirp, 55945168Smckusick stfsbuf.f_flags|MNT_UPDATE, &args) < 0) { 56044015Smckusick if (cp == NULL) 56144015Smckusick cp = ep->ex_dirp + dirplen - 1; 56244015Smckusick else 56344015Smckusick *cp = savedc; 56444015Smckusick /* back up over the last component */ 56544015Smckusick while (*cp == '/' && cp > ep->ex_dirp) 56644015Smckusick cp--; 56744015Smckusick while (*(cp - 1) != '/' && cp > ep->ex_dirp) 56844015Smckusick cp--; 56944015Smckusick if (cp == ep->ex_dirp) { 57044015Smckusick syslog(LOG_WARNING, 57144015Smckusick "Can't export %s", ep->ex_dirp); 57244015Smckusick free_exp(ep); 57344015Smckusick goto nextline; 57444015Smckusick } 57544015Smckusick savedc = *cp; 57644015Smckusick *cp = '\0'; 57744015Smckusick } 57844015Smckusick if (cp) 57944015Smckusick *cp = savedc; 58038460Smckusick ep->ex_rootuid = rootuid; 58138460Smckusick ep->ex_exflags = exflags; 58244015Smckusick } else { 58344015Smckusick ep->ex_rootuid = fep->ex_rootuid; 58444015Smckusick ep->ex_exflags = fep->ex_exflags; 58538460Smckusick } 58644015Smckusick ep->ex_dev = sb.st_dev; 58744015Smckusick ep->ex_next = exphead.ex_next; 58844015Smckusick ep->ex_prev = &exphead; 58944015Smckusick if (ep->ex_next != NULL) 59044015Smckusick ep->ex_next->ex_prev = ep; 59144015Smckusick exphead.ex_next = ep; 59244015Smckusick nextline: 59344015Smckusick ; 59438460Smckusick } 59538460Smckusick fclose(inf); 59638460Smckusick return; 59738460Smckusick err: 598*45271Smckusick syslog(LOG_ERR, "No more memory: mountd Failed"); 59938460Smckusick exit(2); 60038460Smckusick } 60138460Smckusick 60238460Smckusick /* 60338460Smckusick * Parse out the next white space separated field 60438460Smckusick */ 60538460Smckusick nextfield(cp, endcp) 60638460Smckusick char **cp; 60738460Smckusick char **endcp; 60838460Smckusick { 60938460Smckusick register char *p; 61038460Smckusick 61138460Smckusick p = *cp; 61238460Smckusick while (*p == ' ' || *p == '\t') 61338460Smckusick p++; 61438460Smckusick if (*p == '\n' || *p == '\0') { 61538460Smckusick *cp = *endcp = p; 61638460Smckusick return; 61738460Smckusick } 61838460Smckusick *cp = p++; 61938460Smckusick while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 62038460Smckusick p++; 62138460Smckusick *endcp = p; 62238460Smckusick } 62339681Smckusick 62439681Smckusick /* 62544015Smckusick * Parse the option string 62639681Smckusick */ 62744015Smckusick do_opt(cpopt, fep, ep, exflagsp, rootuidp) 62844015Smckusick register char *cpopt; 62944015Smckusick struct exportlist *fep, *ep; 63044015Smckusick int *exflagsp, *rootuidp; 63139681Smckusick { 63244015Smckusick register char *cpoptarg, *cpoptend; 63339681Smckusick 63444015Smckusick while (cpopt && *cpopt) { 63544015Smckusick if (cpoptend = index(cpopt, ',')) 63644015Smckusick *cpoptend++ = '\0'; 63744015Smckusick if (cpoptarg = index(cpopt, '=')) 63844015Smckusick *cpoptarg++ = '\0'; 63944015Smckusick if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 64044015Smckusick if (fep && (fep->ex_exflags & MNT_EXRDONLY) == 0) 64144015Smckusick syslog(LOG_WARNING, "ro failed for %s", 64244015Smckusick ep->ex_dirp); 64344015Smckusick else 64444015Smckusick *exflagsp |= MNT_EXRDONLY; 64544015Smckusick } else if (!strcmp(cpopt, "root") || !strcmp(cpopt, "r")) { 64644015Smckusick if (cpoptarg && isdigit(*cpoptarg)) { 64744015Smckusick *rootuidp = atoi(cpoptarg); 64844015Smckusick if (fep && fep->ex_rootuid != *rootuidp) 64944015Smckusick syslog(LOG_WARNING, 65044015Smckusick "uid failed for %s", 65144015Smckusick ep->ex_dirp); 65244015Smckusick } else 65344015Smckusick syslog(LOG_WARNING, 65444015Smckusick "uid failed for %s", 65544015Smckusick ep->ex_dirp); 65644015Smckusick } else 65744015Smckusick syslog(LOG_WARNING, "opt %s ignored for %s", cpopt, 65844015Smckusick ep->ex_dirp); 65944015Smckusick cpopt = cpoptend; 66044015Smckusick } 66144015Smckusick } 66244015Smckusick 66344015Smckusick #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 66444015Smckusick /* 66544015Smckusick * Routines that maintain the remote mounttab 66644015Smckusick */ 66744015Smckusick void get_mountlist() 66844015Smckusick { 66944015Smckusick register struct mountlist *mlp, **mlpp; 67044015Smckusick register char *eos, *dirp; 67144015Smckusick int len; 67244015Smckusick char str[STRSIZ]; 67344015Smckusick FILE *mlfile; 67444015Smckusick 67544338Smckusick if (((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) && 67644338Smckusick ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL)) { 67744015Smckusick syslog(LOG_WARNING, "Can't open %s", _PATH_RMOUNTLIST); 67844015Smckusick return; 67944015Smckusick } 68044015Smckusick mlpp = &mlhead; 68144015Smckusick while (fgets(str, STRSIZ, mlfile) != NULL) { 68244015Smckusick if ((dirp = index(str, '\t')) == NULL && 68344015Smckusick (dirp = index(str, ' ')) == NULL) 68444015Smckusick continue; 68544015Smckusick mlp = (struct mountlist *)malloc(sizeof (*mlp)); 68644015Smckusick len = dirp-str; 68744015Smckusick if (len > RPCMNT_NAMELEN) 68844015Smckusick len = RPCMNT_NAMELEN; 68944015Smckusick bcopy(str, mlp->ml_host, len); 69044015Smckusick mlp->ml_host[len] = '\0'; 69144015Smckusick while (*dirp == '\t' || *dirp == ' ') 69244015Smckusick dirp++; 69344015Smckusick if ((eos = index(dirp, '\t')) == NULL && 69444015Smckusick (eos = index(dirp, ' ')) == NULL && 69544015Smckusick (eos = index(dirp, '\n')) == NULL) 69644015Smckusick len = strlen(dirp); 69744015Smckusick else 69844015Smckusick len = eos-dirp; 69944015Smckusick if (len > RPCMNT_PATHLEN) 70044015Smckusick len = RPCMNT_PATHLEN; 70144015Smckusick bcopy(dirp, mlp->ml_dirp, len); 70244015Smckusick mlp->ml_dirp[len] = '\0'; 70344015Smckusick mlp->ml_next = (struct mountlist *)0; 70444015Smckusick *mlpp = mlp; 70544015Smckusick mlpp = &mlp->ml_next; 70644015Smckusick } 70744015Smckusick fclose(mlfile); 70844015Smckusick } 70944015Smckusick 71044015Smckusick void del_mlist(hostp, dirp) 71144015Smckusick register char *hostp, *dirp; 71244015Smckusick { 71344015Smckusick register struct mountlist *mlp, **mlpp; 71444015Smckusick FILE *mlfile; 71544015Smckusick int fnd = 0; 71644015Smckusick 71744015Smckusick mlpp = &mlhead; 71844015Smckusick mlp = mlhead; 71944015Smckusick while (mlp) { 72044015Smckusick if (!strcmp(mlp->ml_host, hostp) && 72144015Smckusick (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 72244015Smckusick fnd = 1; 72344015Smckusick *mlpp = mlp->ml_next; 72444015Smckusick free((caddr_t)mlp); 72539681Smckusick } 72644015Smckusick mlpp = &mlp->ml_next; 72744015Smckusick mlp = mlp->ml_next; 72839681Smckusick } 72944015Smckusick if (fnd) { 73044015Smckusick if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 73144015Smckusick syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST); 73244015Smckusick return; 73344015Smckusick } 73444015Smckusick mlp = mlhead; 73544015Smckusick while (mlp) { 73644015Smckusick fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 73744015Smckusick mlp = mlp->ml_next; 73844015Smckusick } 73944015Smckusick fclose(mlfile); 74044015Smckusick } 74139681Smckusick } 74244015Smckusick 74344015Smckusick void add_mlist(hostp, dirp) 74444015Smckusick register char *hostp, *dirp; 74544015Smckusick { 74644015Smckusick register struct mountlist *mlp, **mlpp; 74744015Smckusick FILE *mlfile; 74844015Smckusick 74944015Smckusick mlpp = &mlhead; 75044015Smckusick mlp = mlhead; 75144015Smckusick while (mlp) { 75244015Smckusick if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 75344015Smckusick return; 75444015Smckusick mlpp = &mlp->ml_next; 75544015Smckusick mlp = mlp->ml_next; 75644015Smckusick } 75744015Smckusick mlp = (struct mountlist *)malloc(sizeof (*mlp)); 75844015Smckusick strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 75944015Smckusick mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 76044015Smckusick strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 76144015Smckusick mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 76244015Smckusick mlp->ml_next = (struct mountlist *)0; 76344015Smckusick *mlpp = mlp; 76444015Smckusick if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 76544015Smckusick syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST); 76644015Smckusick return; 76744015Smckusick } 76844015Smckusick fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 76944015Smckusick fclose(mlfile); 77044015Smckusick } 77144015Smckusick 77244015Smckusick /* 77344015Smckusick * This function is called via. SIGTERM when the system is going down. 77444015Smckusick * It sends a broadcast RPCMNT_UMNTALL. 77544015Smckusick */ 77644015Smckusick send_umntall() 77744015Smckusick { 77844015Smckusick (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL, 77944015Smckusick xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each); 78044015Smckusick exit(); 78144015Smckusick } 78244015Smckusick 78344015Smckusick umntall_each(resultsp, raddr) 78444015Smckusick caddr_t resultsp; 78544015Smckusick struct sockaddr_in *raddr; 78644015Smckusick { 78744015Smckusick return (1); 78844015Smckusick } 78944015Smckusick 79044015Smckusick /* 79144015Smckusick * Free up an exports list component 79244015Smckusick */ 79344015Smckusick free_exp(ep) 79444015Smckusick register struct exportlist *ep; 79544015Smckusick { 79644015Smckusick register struct grouplist *grp; 79744015Smckusick register char **addrp; 79844015Smckusick struct grouplist *grp2; 79944015Smckusick 80044015Smckusick grp = ep->ex_groups; 80144015Smckusick while (grp != NULL) { 80244015Smckusick addrp = grp->gr_hp->h_addr_list; 80344015Smckusick while (*addrp) 80444015Smckusick free(*addrp++); 80544015Smckusick free((caddr_t)grp->gr_hp->h_addr_list); 80644015Smckusick free(grp->gr_hp->h_name); 80744015Smckusick free((caddr_t)grp->gr_hp); 80844015Smckusick grp2 = grp; 80944015Smckusick grp = grp->gr_next; 81044015Smckusick free((caddr_t)grp2); 81144015Smckusick } 81244015Smckusick free((caddr_t)ep); 81344015Smckusick } 814