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*46709Sbostic static char sccsid[] = "@(#)mountd.c 5.14 (Berkeley) 02/26/91"; 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 */ 70*46709Sbostic int mntsrv(), umntall_each(), xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist(); 71*46709Sbostic void add_mlist(), del_mlist(), get_exportlist(), get_mountlist(); 72*46709Sbostic void send_umntall(); 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 */ 399*46709Sbostic void 40038460Smckusick get_exportlist() 40138460Smckusick { 40239681Smckusick register struct hostent *hp, *nhp; 40339681Smckusick register char **addrp, **naddrp; 40439681Smckusick register int i; 40544015Smckusick register struct grouplist *grp; 40638460Smckusick register struct exportlist *ep, *ep2; 40745168Smckusick struct statfs stfsbuf; 40840368Smckusick struct ufs_args args; 40944015Smckusick struct stat sb; 41038460Smckusick FILE *inf; 41138460Smckusick char *cp, *endcp; 41239681Smckusick char savedc; 41344015Smckusick int len, dirplen; 41438460Smckusick int rootuid, exflags; 41544015Smckusick u_long saddr; 41644015Smckusick struct exportlist *fep; 41738460Smckusick 41838460Smckusick /* 41938460Smckusick * First, get rid of the old list 42038460Smckusick */ 42138460Smckusick ep = exphead.ex_next; 42238460Smckusick while (ep != NULL) { 42338460Smckusick ep2 = ep; 42438460Smckusick ep = ep->ex_next; 42544015Smckusick free_exp(ep2); 42638460Smckusick } 42738460Smckusick 42838460Smckusick /* 42938460Smckusick * Read in the exports file and build the list, calling 43038460Smckusick * exportfs() as we go along 43138460Smckusick */ 43238460Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 43338460Smckusick if ((inf = fopen(exname, "r")) == NULL) { 43438460Smckusick syslog(LOG_ERR, "Can't open %s", exname); 43538460Smckusick exit(2); 43638460Smckusick } 43738460Smckusick while (fgets(line, LINESIZ, inf)) { 43841404Smckusick exflags = MNT_EXPORTED; 43938460Smckusick rootuid = def_rootuid; 44038460Smckusick cp = line; 44138460Smckusick nextfield(&cp, &endcp); 44244015Smckusick 44344015Smckusick /* 44444015Smckusick * Get file system devno and see if an entry for this 44544015Smckusick * file system already exists. 44644015Smckusick */ 44744015Smckusick savedc = *endcp; 44844015Smckusick *endcp = '\0'; 44945271Smckusick if (stat(cp, &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFDIR) { 45045271Smckusick syslog(LOG_ERR, 45145271Smckusick "Bad Exports File, %s: %s, mountd Failed", 45245271Smckusick cp, "Not a directory"); 45345271Smckusick exit(2); 45445271Smckusick } 45544015Smckusick fep = (struct exportlist *)0; 45644015Smckusick ep = exphead.ex_next; 45744015Smckusick while (ep) { 45844015Smckusick if (ep->ex_dev == sb.st_dev) { 45944015Smckusick fep = ep; 46044015Smckusick break; 46144015Smckusick } 46244015Smckusick ep = ep->ex_next; 46344015Smckusick } 46444015Smckusick *endcp = savedc; 46544015Smckusick 46644015Smckusick /* 46744015Smckusick * Create new exports list entry 46844015Smckusick */ 46938460Smckusick len = endcp-cp; 47038460Smckusick if (len <= RPCMNT_PATHLEN && len > 0) { 47138460Smckusick ep = (struct exportlist *)malloc(sizeof(*ep)); 47245271Smckusick if (ep == NULL) 47345271Smckusick goto err; 47438460Smckusick ep->ex_next = ep->ex_prev = (struct exportlist *)0; 47538460Smckusick ep->ex_groups = (struct grouplist *)0; 47638460Smckusick bcopy(cp, ep->ex_dirp, len); 47738460Smckusick ep->ex_dirp[len] = '\0'; 47844015Smckusick dirplen = len; 47945271Smckusick } else { 48045271Smckusick syslog(LOG_ERR, "Bad Exports File, mountd Failed"); 48145271Smckusick exit(2); 48245271Smckusick } 48338460Smckusick cp = endcp; 48438460Smckusick nextfield(&cp, &endcp); 48538460Smckusick len = endcp-cp; 48638460Smckusick while (len > 0) { 48739681Smckusick savedc = *endcp; 48839681Smckusick *endcp = '\0'; 48945271Smckusick if (len > RPCMNT_NAMELEN) 49045271Smckusick goto more; 49145271Smckusick if (*cp == '-') { 49245271Smckusick do_opt(cp + 1, fep, ep, &exflags, &rootuid); 49345271Smckusick goto more; 49445271Smckusick } 49545271Smckusick if (isdigit(*cp)) { 49645271Smckusick saddr = inet_addr(cp); 49745271Smckusick if (saddr == -1 || 49845271Smckusick (hp = gethostbyaddr((caddr_t)&saddr, 49945271Smckusick sizeof(saddr), AF_INET)) == NULL) { 50045271Smckusick syslog(LOG_ERR, 50145271Smckusick "Bad Exports File, %s: %s", cp, 50245271Smckusick "Gethostbyaddr failed, ignored"); 50345271Smckusick goto more; 50438460Smckusick } 50545271Smckusick } else if ((hp = gethostbyname(cp)) == NULL) { 50645271Smckusick syslog(LOG_ERR, "Bad Exports File, %s: %s", 50745271Smckusick cp, "Gethostbyname failed, ignored"); 50845271Smckusick goto more; 50938460Smckusick } 51045271Smckusick grp = (struct grouplist *) 51145271Smckusick malloc(sizeof(struct grouplist)); 51245271Smckusick if (grp == NULL) 51345271Smckusick goto err; 51445271Smckusick nhp = grp->gr_hp = (struct hostent *) 51545271Smckusick malloc(sizeof(struct hostent)); 51645271Smckusick if (nhp == NULL) 51745271Smckusick goto err; 51845271Smckusick bcopy((caddr_t)hp, (caddr_t)nhp, 51945271Smckusick sizeof(struct hostent)); 52045271Smckusick i = strlen(hp->h_name)+1; 52145271Smckusick nhp->h_name = (char *)malloc(i); 52245271Smckusick if (nhp->h_name == NULL) 52345271Smckusick goto err; 52445271Smckusick bcopy(hp->h_name, nhp->h_name, i); 52545271Smckusick addrp = hp->h_addr_list; 52645271Smckusick i = 1; 52745271Smckusick while (*addrp++) 52845271Smckusick i++; 52945271Smckusick naddrp = nhp->h_addr_list = (char **) 53045271Smckusick malloc(i*sizeof(char *)); 53145271Smckusick if (naddrp == NULL) 53245271Smckusick goto err; 53345271Smckusick addrp = hp->h_addr_list; 53445271Smckusick while (*addrp) { 53545271Smckusick *naddrp = (char *) 53645271Smckusick malloc(hp->h_length); 53745271Smckusick if (*naddrp == NULL) 53845271Smckusick goto err; 53945271Smckusick bcopy(*addrp, *naddrp, 54045271Smckusick hp->h_length); 54145271Smckusick addrp++; 54245271Smckusick naddrp++; 54345271Smckusick } 54445271Smckusick *naddrp = (char *)0; 54545271Smckusick grp->gr_next = ep->ex_groups; 54645271Smckusick ep->ex_groups = grp; 54745271Smckusick more: 54838460Smckusick cp = endcp; 54939681Smckusick *cp = savedc; 55038460Smckusick nextfield(&cp, &endcp); 55145271Smckusick len = endcp - cp; 55238460Smckusick } 55344015Smckusick if (fep == NULL) { 55444015Smckusick args.fspec = 0; 55544015Smckusick args.exflags = exflags; 55644015Smckusick args.exroot = rootuid; 55744015Smckusick cp = (char *)0; 55845168Smckusick while (statfs(ep->ex_dirp, &stfsbuf) < 0 || 55945168Smckusick mount(MOUNT_UFS, ep->ex_dirp, 56045168Smckusick stfsbuf.f_flags|MNT_UPDATE, &args) < 0) { 56144015Smckusick if (cp == NULL) 56244015Smckusick cp = ep->ex_dirp + dirplen - 1; 56344015Smckusick else 56444015Smckusick *cp = savedc; 56544015Smckusick /* back up over the last component */ 56644015Smckusick while (*cp == '/' && cp > ep->ex_dirp) 56744015Smckusick cp--; 56844015Smckusick while (*(cp - 1) != '/' && cp > ep->ex_dirp) 56944015Smckusick cp--; 57044015Smckusick if (cp == ep->ex_dirp) { 57144015Smckusick syslog(LOG_WARNING, 57244015Smckusick "Can't export %s", ep->ex_dirp); 57344015Smckusick free_exp(ep); 57444015Smckusick goto nextline; 57544015Smckusick } 57644015Smckusick savedc = *cp; 57744015Smckusick *cp = '\0'; 57844015Smckusick } 57944015Smckusick if (cp) 58044015Smckusick *cp = savedc; 58138460Smckusick ep->ex_rootuid = rootuid; 58238460Smckusick ep->ex_exflags = exflags; 58344015Smckusick } else { 58444015Smckusick ep->ex_rootuid = fep->ex_rootuid; 58544015Smckusick ep->ex_exflags = fep->ex_exflags; 58638460Smckusick } 58744015Smckusick ep->ex_dev = sb.st_dev; 58844015Smckusick ep->ex_next = exphead.ex_next; 58944015Smckusick ep->ex_prev = &exphead; 59044015Smckusick if (ep->ex_next != NULL) 59144015Smckusick ep->ex_next->ex_prev = ep; 59244015Smckusick exphead.ex_next = ep; 59344015Smckusick nextline: 59444015Smckusick ; 59538460Smckusick } 59638460Smckusick fclose(inf); 59738460Smckusick return; 59838460Smckusick err: 59945271Smckusick syslog(LOG_ERR, "No more memory: mountd Failed"); 60038460Smckusick exit(2); 60138460Smckusick } 60238460Smckusick 60338460Smckusick /* 60438460Smckusick * Parse out the next white space separated field 60538460Smckusick */ 60638460Smckusick nextfield(cp, endcp) 60738460Smckusick char **cp; 60838460Smckusick char **endcp; 60938460Smckusick { 61038460Smckusick register char *p; 61138460Smckusick 61238460Smckusick p = *cp; 61338460Smckusick while (*p == ' ' || *p == '\t') 61438460Smckusick p++; 61538460Smckusick if (*p == '\n' || *p == '\0') { 61638460Smckusick *cp = *endcp = p; 61738460Smckusick return; 61838460Smckusick } 61938460Smckusick *cp = p++; 62038460Smckusick while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 62138460Smckusick p++; 62238460Smckusick *endcp = p; 62338460Smckusick } 62439681Smckusick 62539681Smckusick /* 62644015Smckusick * Parse the option string 62739681Smckusick */ 62844015Smckusick do_opt(cpopt, fep, ep, exflagsp, rootuidp) 62944015Smckusick register char *cpopt; 63044015Smckusick struct exportlist *fep, *ep; 63144015Smckusick int *exflagsp, *rootuidp; 63239681Smckusick { 63344015Smckusick register char *cpoptarg, *cpoptend; 63439681Smckusick 63544015Smckusick while (cpopt && *cpopt) { 63644015Smckusick if (cpoptend = index(cpopt, ',')) 63744015Smckusick *cpoptend++ = '\0'; 63844015Smckusick if (cpoptarg = index(cpopt, '=')) 63944015Smckusick *cpoptarg++ = '\0'; 64044015Smckusick if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 64144015Smckusick if (fep && (fep->ex_exflags & MNT_EXRDONLY) == 0) 64244015Smckusick syslog(LOG_WARNING, "ro failed for %s", 64344015Smckusick ep->ex_dirp); 64444015Smckusick else 64544015Smckusick *exflagsp |= MNT_EXRDONLY; 64644015Smckusick } else if (!strcmp(cpopt, "root") || !strcmp(cpopt, "r")) { 64744015Smckusick if (cpoptarg && isdigit(*cpoptarg)) { 64844015Smckusick *rootuidp = atoi(cpoptarg); 64944015Smckusick if (fep && fep->ex_rootuid != *rootuidp) 65044015Smckusick syslog(LOG_WARNING, 65144015Smckusick "uid failed for %s", 65244015Smckusick ep->ex_dirp); 65344015Smckusick } else 65444015Smckusick syslog(LOG_WARNING, 65544015Smckusick "uid failed for %s", 65644015Smckusick ep->ex_dirp); 65744015Smckusick } else 65844015Smckusick syslog(LOG_WARNING, "opt %s ignored for %s", cpopt, 65944015Smckusick ep->ex_dirp); 66044015Smckusick cpopt = cpoptend; 66144015Smckusick } 66244015Smckusick } 66344015Smckusick 66444015Smckusick #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 66544015Smckusick /* 66644015Smckusick * Routines that maintain the remote mounttab 66744015Smckusick */ 66844015Smckusick void get_mountlist() 66944015Smckusick { 67044015Smckusick register struct mountlist *mlp, **mlpp; 67144015Smckusick register char *eos, *dirp; 67244015Smckusick int len; 67344015Smckusick char str[STRSIZ]; 67444015Smckusick FILE *mlfile; 67544015Smckusick 67644338Smckusick if (((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) && 67744338Smckusick ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL)) { 67844015Smckusick syslog(LOG_WARNING, "Can't open %s", _PATH_RMOUNTLIST); 67944015Smckusick return; 68044015Smckusick } 68144015Smckusick mlpp = &mlhead; 68244015Smckusick while (fgets(str, STRSIZ, mlfile) != NULL) { 68344015Smckusick if ((dirp = index(str, '\t')) == NULL && 68444015Smckusick (dirp = index(str, ' ')) == NULL) 68544015Smckusick continue; 68644015Smckusick mlp = (struct mountlist *)malloc(sizeof (*mlp)); 68744015Smckusick len = dirp-str; 68844015Smckusick if (len > RPCMNT_NAMELEN) 68944015Smckusick len = RPCMNT_NAMELEN; 69044015Smckusick bcopy(str, mlp->ml_host, len); 69144015Smckusick mlp->ml_host[len] = '\0'; 69244015Smckusick while (*dirp == '\t' || *dirp == ' ') 69344015Smckusick dirp++; 69444015Smckusick if ((eos = index(dirp, '\t')) == NULL && 69544015Smckusick (eos = index(dirp, ' ')) == NULL && 69644015Smckusick (eos = index(dirp, '\n')) == NULL) 69744015Smckusick len = strlen(dirp); 69844015Smckusick else 69944015Smckusick len = eos-dirp; 70044015Smckusick if (len > RPCMNT_PATHLEN) 70144015Smckusick len = RPCMNT_PATHLEN; 70244015Smckusick bcopy(dirp, mlp->ml_dirp, len); 70344015Smckusick mlp->ml_dirp[len] = '\0'; 70444015Smckusick mlp->ml_next = (struct mountlist *)0; 70544015Smckusick *mlpp = mlp; 70644015Smckusick mlpp = &mlp->ml_next; 70744015Smckusick } 70844015Smckusick fclose(mlfile); 70944015Smckusick } 71044015Smckusick 71144015Smckusick void del_mlist(hostp, dirp) 71244015Smckusick register char *hostp, *dirp; 71344015Smckusick { 71444015Smckusick register struct mountlist *mlp, **mlpp; 71544015Smckusick FILE *mlfile; 71644015Smckusick int fnd = 0; 71744015Smckusick 71844015Smckusick mlpp = &mlhead; 71944015Smckusick mlp = mlhead; 72044015Smckusick while (mlp) { 72144015Smckusick if (!strcmp(mlp->ml_host, hostp) && 72244015Smckusick (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 72344015Smckusick fnd = 1; 72444015Smckusick *mlpp = mlp->ml_next; 72544015Smckusick free((caddr_t)mlp); 72639681Smckusick } 72744015Smckusick mlpp = &mlp->ml_next; 72844015Smckusick mlp = mlp->ml_next; 72939681Smckusick } 73044015Smckusick if (fnd) { 73144015Smckusick if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 73244015Smckusick syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST); 73344015Smckusick return; 73444015Smckusick } 73544015Smckusick mlp = mlhead; 73644015Smckusick while (mlp) { 73744015Smckusick fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 73844015Smckusick mlp = mlp->ml_next; 73944015Smckusick } 74044015Smckusick fclose(mlfile); 74144015Smckusick } 74239681Smckusick } 74344015Smckusick 74444015Smckusick void add_mlist(hostp, dirp) 74544015Smckusick register char *hostp, *dirp; 74644015Smckusick { 74744015Smckusick register struct mountlist *mlp, **mlpp; 74844015Smckusick FILE *mlfile; 74944015Smckusick 75044015Smckusick mlpp = &mlhead; 75144015Smckusick mlp = mlhead; 75244015Smckusick while (mlp) { 75344015Smckusick if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 75444015Smckusick return; 75544015Smckusick mlpp = &mlp->ml_next; 75644015Smckusick mlp = mlp->ml_next; 75744015Smckusick } 75844015Smckusick mlp = (struct mountlist *)malloc(sizeof (*mlp)); 75944015Smckusick strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 76044015Smckusick mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 76144015Smckusick strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 76244015Smckusick mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 76344015Smckusick mlp->ml_next = (struct mountlist *)0; 76444015Smckusick *mlpp = mlp; 76544015Smckusick if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 76644015Smckusick syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST); 76744015Smckusick return; 76844015Smckusick } 76944015Smckusick fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 77044015Smckusick fclose(mlfile); 77144015Smckusick } 77244015Smckusick 77344015Smckusick /* 77444015Smckusick * This function is called via. SIGTERM when the system is going down. 77544015Smckusick * It sends a broadcast RPCMNT_UMNTALL. 77644015Smckusick */ 777*46709Sbostic void 77844015Smckusick send_umntall() 77944015Smckusick { 78044015Smckusick (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL, 78144015Smckusick xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each); 78244015Smckusick exit(); 78344015Smckusick } 78444015Smckusick 78544015Smckusick umntall_each(resultsp, raddr) 78644015Smckusick caddr_t resultsp; 78744015Smckusick struct sockaddr_in *raddr; 78844015Smckusick { 78944015Smckusick return (1); 79044015Smckusick } 79144015Smckusick 79244015Smckusick /* 79344015Smckusick * Free up an exports list component 79444015Smckusick */ 79544015Smckusick free_exp(ep) 79644015Smckusick register struct exportlist *ep; 79744015Smckusick { 79844015Smckusick register struct grouplist *grp; 79944015Smckusick register char **addrp; 80044015Smckusick struct grouplist *grp2; 80144015Smckusick 80244015Smckusick grp = ep->ex_groups; 80344015Smckusick while (grp != NULL) { 80444015Smckusick addrp = grp->gr_hp->h_addr_list; 80544015Smckusick while (*addrp) 80644015Smckusick free(*addrp++); 80744015Smckusick free((caddr_t)grp->gr_hp->h_addr_list); 80844015Smckusick free(grp->gr_hp->h_name); 80944015Smckusick free((caddr_t)grp->gr_hp); 81044015Smckusick grp2 = grp; 81144015Smckusick grp = grp->gr_next; 81244015Smckusick free((caddr_t)grp2); 81344015Smckusick } 81444015Smckusick free((caddr_t)ep); 81544015Smckusick } 816