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 651667Smckusick * Herb Hasler and 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*51712Smckusick static char sccsid[] = "@(#)mountd.c 5.17 (Berkeley) 11/14/91"; 1938460Smckusick #endif not lint 2038460Smckusick 2151667Smckusick #include <pwd.h> 2251667Smckusick #include <grp.h> 2351667Smckusick #include <unistd.h> 2451667Smckusick #include <stdlib.h> 2551667Smckusick #include <fcntl.h> 2638460Smckusick #include <sys/param.h> 2738460Smckusick #include <sys/ioctl.h> 2838460Smckusick #include <sys/stat.h> 2939681Smckusick #include <sys/file.h> 3051667Smckusick #include <sys/ucred.h> 3138460Smckusick #include <sys/mount.h> 3238460Smckusick #include <sys/socket.h> 3338460Smckusick #include <sys/errno.h> 3442038Sbostic #include <sys/signal.h> 3542038Sbostic #include <stdio.h> 3642038Sbostic #include <string.h> 3742038Sbostic #include <syslog.h> 3838460Smckusick #include <netdb.h> 3938460Smckusick #include <rpc/rpc.h> 4038460Smckusick #include <rpc/pmap_clnt.h> 4138460Smckusick #include <rpc/pmap_prot.h> 4251667Smckusick #ifdef ISO 4351667Smckusick #include <netiso/iso.h> 4451667Smckusick #endif 4538460Smckusick #include <nfs/rpcv2.h> 4638460Smckusick #include <nfs/nfsv2.h> 4739681Smckusick #include "pathnames.h" 4838460Smckusick 4951667Smckusick #define MNT_HOST 0 5051667Smckusick #define MNT_GROUP 1 5151667Smckusick #define MNT_ISO 2 5251667Smckusick 5351667Smckusick struct namelist { 5451667Smckusick char name[RPCMNT_NAMELEN+1]; 5551667Smckusick struct namelist *next; 5638460Smckusick }; 5751667Smckusick struct namegrp { 5851667Smckusick char gname[RPCMNT_NAMELEN+1]; 5951667Smckusick struct namegrp *next; 6051667Smckusick struct namelist *names; 6151667Smckusick }; 6238460Smckusick /* 6338460Smckusick * Structures for keeping the mount list and export list 6438460Smckusick */ 6538460Smckusick struct mountlist { 6644015Smckusick struct mountlist *ml_next; 6738460Smckusick char ml_host[RPCMNT_NAMELEN+1]; 6838460Smckusick char ml_dirp[RPCMNT_PATHLEN+1]; 6938460Smckusick }; 7038460Smckusick 7138460Smckusick struct exportlist { 7238460Smckusick struct exportlist *ex_next; 7338460Smckusick struct exportlist *ex_prev; 7438460Smckusick struct grouplist *ex_groups; 7551667Smckusick int ex_defset; 7638460Smckusick char ex_dirp[RPCMNT_PATHLEN+1]; 7738460Smckusick }; 7838460Smckusick 7951667Smckusick union grouptypes { 8051667Smckusick struct hostent *gt_hostent; 8151667Smckusick struct groupnames *gt_grpname; 8251667Smckusick #ifdef ISO 8351667Smckusick struct sockaddr_iso *gt_isoaddr; 8451667Smckusick #endif 8551667Smckusick }; 8651667Smckusick 8738460Smckusick struct grouplist { 8851667Smckusick int type; 8951667Smckusick int exflags; 9051667Smckusick struct ucred anoncr; 9151667Smckusick union grouptypes gr_ptr; 9238460Smckusick struct grouplist *gr_next; 9338460Smckusick }; 9438460Smckusick 9551667Smckusick struct al_mnt { 9651667Smckusick struct al_mnt *al_next; 9751667Smckusick fsid_t al_mnted; 9851667Smckusick }; 9951667Smckusick 10051667Smckusick struct groupnames { 10151667Smckusick char gn_name[RPCMNT_NAMELEN+1]; 10251667Smckusick struct grouplist *gn_glist; 10351667Smckusick struct groupnames *gn_next; 10451667Smckusick }; 10551667Smckusick 10638460Smckusick /* Global defs */ 10746709Sbostic int mntsrv(), umntall_each(), xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist(); 10851667Smckusick void get_exportlist(), send_umntall(), nextfield(), do_opt(); 10951667Smckusick void get_mountlist(), add_mlist(), del_mlist(), free_exp(), free_grp(); 11051667Smckusick void get_group(), get_host(), do_group(); 11151667Smckusick char *realpath(); 11251667Smckusick #ifdef ISO 11351667Smckusick struct iso_addr *iso_addr(); 11451667Smckusick #endif 11538460Smckusick struct exportlist exphead; 11644015Smckusick struct mountlist *mlhead; 11751667Smckusick struct groupnames *grpnames; 11838460Smckusick char exname[MAXPATHLEN]; 11951667Smckusick struct ucred def_anon = { 12051667Smckusick (u_short) 1, 12151667Smckusick (uid_t) -2, 12251667Smckusick 1, 12351667Smckusick (gid_t) -2, 12451667Smckusick }; 12544015Smckusick int root_only = 1; 12638460Smckusick extern int errno; 12751667Smckusick struct al_mnt *al_head = (struct al_mnt *)0; 12838460Smckusick #ifdef DEBUG 12938460Smckusick int debug = 1; 13051711Smckusick void SYSLOG __P((int, const char *, ...)); 13151711Smckusick #define syslog SYSLOG 13238460Smckusick #else 13338460Smckusick int debug = 0; 13438460Smckusick #endif 13538460Smckusick 13638460Smckusick /* 13738460Smckusick * Mountd server for NFS mount protocol as described in: 13839681Smckusick * NFS: Network File System Protocol Specification, RFC1094, Appendix A 13944015Smckusick * The optional arguments are the exports file name 14039681Smckusick * default: _PATH_EXPORTS 14144015Smckusick * and "-n" to allow nonroot mount. 14238460Smckusick */ 14338460Smckusick main(argc, argv) 14438460Smckusick int argc; 14544015Smckusick char **argv; 14638460Smckusick { 14738460Smckusick SVCXPRT *transp; 14844015Smckusick int c; 14944015Smckusick extern int optind; 15044015Smckusick extern char *optarg; 15138460Smckusick 15244015Smckusick while ((c = getopt(argc, argv, "n")) != EOF) 15344015Smckusick switch (c) { 15444015Smckusick case 'n': 15544015Smckusick root_only = 0; 15644015Smckusick break; 15744015Smckusick default: 15844015Smckusick fprintf(stderr, "Usage: mountd [-n] [export_file]\n"); 15944015Smckusick exit(1); 16044015Smckusick }; 16144015Smckusick argc -= optind; 16244015Smckusick argv += optind; 16351667Smckusick grpnames = (struct groupnames *)0; 16444015Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 16544015Smckusick mlhead = (struct mountlist *)0; 16644015Smckusick if (argc == 1) { 16744015Smckusick strncpy(exname, *argv, MAXPATHLEN-1); 16844015Smckusick exname[MAXPATHLEN-1] = '\0'; 16944015Smckusick } else 17044015Smckusick strcpy(exname, _PATH_EXPORTS); 17144338Smckusick openlog("mountd:", LOG_PID, LOG_DAEMON); 17251667Smckusick if (debug) 17351667Smckusick fprintf(stderr,"Getting export list.\n"); 17444015Smckusick get_exportlist(); 17551667Smckusick if (debug) 17651667Smckusick fprintf(stderr,"Getting mount list.\n"); 17744015Smckusick get_mountlist(); 17851667Smckusick if (debug) 17951667Smckusick fprintf(stderr,"Here we go.\n"); 18038460Smckusick if (debug == 0) { 18144690Skarels daemon(0, 0); 18238460Smckusick signal(SIGINT, SIG_IGN); 18338460Smckusick signal(SIGQUIT, SIG_IGN); 18438460Smckusick } 18538460Smckusick signal(SIGHUP, get_exportlist); 18644015Smckusick signal(SIGTERM, send_umntall); 18740494Smckusick { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); 18840494Smckusick if (pidfile != NULL) { 18940494Smckusick fprintf(pidfile, "%d\n", getpid()); 19040494Smckusick fclose(pidfile); 19140494Smckusick } 19240494Smckusick } 19338460Smckusick if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL) { 19438460Smckusick syslog(LOG_ERR, "Can't create socket"); 19538460Smckusick exit(1); 19638460Smckusick } 19738460Smckusick pmap_unset(RPCPROG_MNT, RPCMNT_VER1); 19851667Smckusick if (!svc_register(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv, 19951667Smckusick IPPROTO_UDP)) { 20038460Smckusick syslog(LOG_ERR, "Can't register mount"); 20138460Smckusick exit(1); 20238460Smckusick } 20338460Smckusick svc_run(); 20438460Smckusick syslog(LOG_ERR, "Mountd died"); 20544690Skarels exit(1); 20638460Smckusick } 20738460Smckusick 20838460Smckusick /* 20938460Smckusick * The mount rpc service 21038460Smckusick */ 21138460Smckusick mntsrv(rqstp, transp) 21238460Smckusick register struct svc_req *rqstp; 21338460Smckusick register SVCXPRT *transp; 21438460Smckusick { 21539681Smckusick register struct grouplist *grp; 21639681Smckusick register u_long **addrp; 21738460Smckusick register struct exportlist *ep; 21838460Smckusick nfsv2fh_t nfh; 21938460Smckusick struct authunix_parms *ucr; 22038460Smckusick struct stat stb; 22138460Smckusick struct hostent *hp; 22239681Smckusick u_long saddr; 22351667Smckusick char rpcpath[RPCMNT_PATHLEN+1], dirpath[MAXPATHLEN]; 22438460Smckusick int bad = ENOENT; 22551667Smckusick int found, matched; 22638460Smckusick int omask; 22739681Smckusick uid_t uid = -2; 22838460Smckusick 22938460Smckusick /* Get authorization */ 23038460Smckusick switch (rqstp->rq_cred.oa_flavor) { 23138460Smckusick case AUTH_UNIX: 23238460Smckusick ucr = (struct authunix_parms *)rqstp->rq_clntcred; 23339681Smckusick uid = ucr->aup_uid; 23439681Smckusick break; 23538460Smckusick case AUTH_NULL: 23638460Smckusick default: 23739681Smckusick break; 23838460Smckusick } 23938460Smckusick 24039681Smckusick saddr = transp->xp_raddr.sin_addr.s_addr; 24139681Smckusick hp = (struct hostent *)0; 24238460Smckusick switch (rqstp->rq_proc) { 24339681Smckusick case NULLPROC: 24439681Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 24539681Smckusick syslog(LOG_ERR, "Can't send reply"); 24639681Smckusick return; 24738460Smckusick case RPCMNT_MOUNT: 24851667Smckusick if ((uid != 0 && root_only) || uid == -2) { 24939681Smckusick svcerr_weakauth(transp); 25039681Smckusick return; 25139681Smckusick } 25251667Smckusick if (!svc_getargs(transp, xdr_dir, rpcpath)) { 25338460Smckusick svcerr_decode(transp); 25438460Smckusick return; 25538460Smckusick } 25638460Smckusick 25751667Smckusick /* 25851667Smckusick * Get the real pathname and make sure it is a directory 25951667Smckusick * that exists. 26051667Smckusick */ 26151667Smckusick if (realpath(rpcpath, dirpath) == 0 || stat(dirpath, &stb) < 0 26251667Smckusick || (stb.st_mode&S_IFMT) != S_IFDIR) { 26351667Smckusick chdir("/"); /* Just in case realpath doesn't */ 26451667Smckusick if (debug) 26551667Smckusick fprintf(stderr,"stat failed on %s\n",dirpath); 26638460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 26738460Smckusick syslog(LOG_ERR, "Can't send reply"); 26838460Smckusick return; 26938460Smckusick } 27038460Smckusick 27138460Smckusick /* Check in the exports list */ 27238460Smckusick omask = sigblock(sigmask(SIGHUP)); 27338460Smckusick ep = exphead.ex_next; 27451667Smckusick found = FALSE; 27551667Smckusick matched = FALSE; 27651667Smckusick while (ep != NULL && !found && !matched) { 27751667Smckusick struct grouplist *tgrp; 27851667Smckusick if (debug) 27951667Smckusick fprintf(stderr,"dirp=[%s]\n",ep->ex_dirp); 28038460Smckusick if (!strcmp(ep->ex_dirp, dirpath)) { 28151667Smckusick if (ep->ex_defset) 28251667Smckusick grp = (struct grouplist *)0; 28351667Smckusick else 28438460Smckusick grp = ep->ex_groups; 28551667Smckusick if (grp == NULL) { 28651667Smckusick if (debug) 28751667Smckusick fprintf(stderr,"grp is null\n"); 28851667Smckusick found = TRUE; 28951667Smckusick } 29051667Smckusick while (grp && !found) { 29151667Smckusick matched = TRUE; 29251667Smckusick if (debug) 29351667Smckusick fprintf(stderr,"type = [%d]\n",grp->type); 29451667Smckusick if (grp->type == MNT_GROUP) { 29551667Smckusick tgrp = grp->gr_ptr.gt_grpname->gn_glist; 29651667Smckusick if (tgrp) 29751667Smckusick addrp = (u_long **) 29851667Smckusick tgrp->gr_ptr.gt_hostent->h_addr_list; 29951667Smckusick while(tgrp && !found) { 30051667Smckusick if (debug) 30151667Smckusick fprintf(stderr, "cmp [%d] [%d]\n", 30251667Smckusick **addrp,saddr); 30351667Smckusick if (**addrp == saddr) { 30451667Smckusick found = TRUE; 30551667Smckusick hp = tgrp->gr_ptr.gt_hostent; 30651667Smckusick break; 30751667Smckusick } 30851667Smckusick if (*++addrp == NULL) { 30951667Smckusick tgrp = tgrp->gr_next; 31051667Smckusick if (tgrp == NULL) 31138460Smckusick break; 31251667Smckusick addrp = (u_long **)tgrp-> 31351667Smckusick gr_ptr.gt_hostent->h_addr_list; 31451667Smckusick } 31551667Smckusick } 31651667Smckusick } else if (grp->type == MNT_HOST) { 31751667Smckusick addrp = (u_long **) 31851667Smckusick grp->gr_ptr.gt_hostent->h_addr_list; 31951667Smckusick while (*addrp) { 32051667Smckusick if (debug) 32151667Smckusick fprintf(stderr, "cmp [%d] [%d]\n", 32251667Smckusick **addrp,saddr); 32351667Smckusick if (**addrp == saddr) { 32451667Smckusick found = TRUE; 32551667Smckusick hp = grp->gr_ptr.gt_hostent; 32651667Smckusick break; 32751667Smckusick } 32851667Smckusick addrp++; 32951667Smckusick } 33038460Smckusick } 33151667Smckusick grp = grp->gr_next; 33251667Smckusick } 33338460Smckusick } 33438460Smckusick ep = ep->ex_next; 33538460Smckusick } 33651667Smckusick if (!found) { 33738460Smckusick bad = EACCES; 33838460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 33938460Smckusick syslog(LOG_ERR, "Can't send reply"); 34051667Smckusick sigsetmask(omask); 34138460Smckusick return; 34251667Smckusick } else { 34351667Smckusick /* Get the file handle */ 34451667Smckusick bzero((caddr_t)&nfh, sizeof(nfh)); 34551667Smckusick if (getfh(dirpath, (fhandle_t *)&nfh) < 0) { 34651667Smckusick bad = errno; 34751667Smckusick fprintf(stderr, 34851667Smckusick "Couldn't get file handle for %s.\n", 34951667Smckusick dirpath); 35051667Smckusick if (!svc_sendreply(transp, xdr_long, 35151667Smckusick (caddr_t)&bad)) 35251667Smckusick syslog(LOG_ERR, "Can't send reply"); 35351667Smckusick sigsetmask(omask); 35451667Smckusick return; 35551667Smckusick } 35651667Smckusick if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh)) 35738460Smckusick syslog(LOG_ERR, "Can't send reply"); 35851667Smckusick if (hp == NULL) 35951667Smckusick hp = gethostbyaddr((caddr_t)&saddr, 36051667Smckusick sizeof(saddr), AF_INET); 36151667Smckusick if (hp) 36251667Smckusick add_mlist(hp->h_name, dirpath); 36351667Smckusick else 36451667Smckusick add_mlist(inet_ntoa(transp->xp_raddr.sin_addr), 36551667Smckusick dirpath); 36651667Smckusick if (debug) 36751667Smckusick fprintf(stderr,"Mount successfull.\n"); 36838460Smckusick } 36951667Smckusick sigsetmask(omask); 37038460Smckusick return; 37138460Smckusick case RPCMNT_DUMP: 37238460Smckusick if (!svc_sendreply(transp, xdr_mlist, (caddr_t)0)) 37338460Smckusick syslog(LOG_ERR, "Can't send reply"); 37438460Smckusick return; 37538460Smckusick case RPCMNT_UMOUNT: 37651667Smckusick if ((uid != 0 && root_only) || uid == -2) { 37739681Smckusick svcerr_weakauth(transp); 37839681Smckusick return; 37939681Smckusick } 38038460Smckusick if (!svc_getargs(transp, xdr_dir, dirpath)) { 38138460Smckusick svcerr_decode(transp); 38238460Smckusick return; 38338460Smckusick } 38438460Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 38538460Smckusick syslog(LOG_ERR, "Can't send reply"); 38644015Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 38744015Smckusick if (hp) 38844015Smckusick del_mlist(hp->h_name, dirpath); 38951667Smckusick del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath); 39038460Smckusick return; 39138460Smckusick case RPCMNT_UMNTALL: 39251667Smckusick if ((uid != 0 && root_only) || uid == -2) { 39339681Smckusick svcerr_weakauth(transp); 39439681Smckusick return; 39539681Smckusick } 39638460Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 39738460Smckusick syslog(LOG_ERR, "Can't send reply"); 39844015Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 39944015Smckusick if (hp) 40044015Smckusick del_mlist(hp->h_name, (char *)0); 40151667Smckusick del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), (char *)0); 40238460Smckusick return; 40338460Smckusick case RPCMNT_EXPORT: 40438460Smckusick if (!svc_sendreply(transp, xdr_explist, (caddr_t)0)) 40538460Smckusick syslog(LOG_ERR, "Can't send reply"); 40638460Smckusick return; 40738460Smckusick default: 40838460Smckusick svcerr_noproc(transp); 40938460Smckusick return; 41038460Smckusick } 41138460Smckusick } 41238460Smckusick 41338460Smckusick /* 41438460Smckusick * Xdr conversion for a dirpath string 41538460Smckusick */ 41638460Smckusick xdr_dir(xdrsp, dirp) 41738460Smckusick XDR *xdrsp; 41838460Smckusick char *dirp; 41938460Smckusick { 42038460Smckusick return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 42138460Smckusick } 42238460Smckusick 42338460Smckusick /* 42438460Smckusick * Xdr routine to generate fhstatus 42538460Smckusick */ 42638460Smckusick xdr_fhs(xdrsp, nfh) 42738460Smckusick XDR *xdrsp; 42838460Smckusick nfsv2fh_t *nfh; 42938460Smckusick { 43038460Smckusick int ok = 0; 43138460Smckusick 43238460Smckusick if (!xdr_long(xdrsp, &ok)) 43338460Smckusick return (0); 43438460Smckusick return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH)); 43538460Smckusick } 43638460Smckusick 43738460Smckusick xdr_mlist(xdrsp, cp) 43838460Smckusick XDR *xdrsp; 43938460Smckusick caddr_t cp; 44038460Smckusick { 44144015Smckusick register struct mountlist *mlp; 44238460Smckusick int true = 1; 44338460Smckusick int false = 0; 44438460Smckusick char *strp; 44538460Smckusick 44644015Smckusick mlp = mlhead; 44744015Smckusick while (mlp) { 44844015Smckusick if (!xdr_bool(xdrsp, &true)) 44944015Smckusick return (0); 45044015Smckusick strp = &mlp->ml_host[0]; 45144015Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 45244015Smckusick return (0); 45344015Smckusick strp = &mlp->ml_dirp[0]; 45444015Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 45544015Smckusick return (0); 45644015Smckusick mlp = mlp->ml_next; 45738460Smckusick } 45838460Smckusick if (!xdr_bool(xdrsp, &false)) 45938460Smckusick return (0); 46038460Smckusick return (1); 46138460Smckusick } 46238460Smckusick 46338460Smckusick /* 46438460Smckusick * Xdr conversion for export list 46538460Smckusick */ 46638460Smckusick xdr_explist(xdrsp, cp) 46738460Smckusick XDR *xdrsp; 46838460Smckusick caddr_t cp; 46938460Smckusick { 47038460Smckusick register struct exportlist *ep; 47151667Smckusick register struct grouplist *grp, *tgrp; 47238460Smckusick int true = 1; 47338460Smckusick int false = 0; 47438460Smckusick char *strp; 47538460Smckusick int omask; 47638460Smckusick 47738460Smckusick omask = sigblock(sigmask(SIGHUP)); 47838460Smckusick ep = exphead.ex_next; 47938460Smckusick while (ep != NULL) { 48038460Smckusick if (!xdr_bool(xdrsp, &true)) 48138460Smckusick goto errout; 48238460Smckusick strp = &ep->ex_dirp[0]; 48338460Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 48438460Smckusick goto errout; 48538460Smckusick grp = ep->ex_groups; 48638460Smckusick while (grp != NULL) { 48751667Smckusick if (grp->type == MNT_GROUP) { 48851667Smckusick tgrp = grp->gr_ptr.gt_grpname->gn_glist; 48951667Smckusick while (tgrp) { 49051667Smckusick if (!xdr_bool(xdrsp, &true)) 49151667Smckusick goto errout; 49251667Smckusick strp = tgrp->gr_ptr.gt_hostent->h_name; 49351667Smckusick if (!xdr_string(xdrsp, &strp, 49451667Smckusick RPCMNT_NAMELEN)) 49551667Smckusick goto errout; 49651667Smckusick tgrp = tgrp->gr_next; 49751667Smckusick } 49851667Smckusick } else if (grp->type == MNT_HOST) { 49951667Smckusick if (!xdr_bool(xdrsp, &true)) 50051667Smckusick goto errout; 50151667Smckusick strp = grp->gr_ptr.gt_hostent->h_name; 50251667Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 50351667Smckusick goto errout; 50451667Smckusick } 50538460Smckusick grp = grp->gr_next; 50638460Smckusick } 50738460Smckusick if (!xdr_bool(xdrsp, &false)) 50838460Smckusick goto errout; 50938460Smckusick ep = ep->ex_next; 51038460Smckusick } 51138460Smckusick sigsetmask(omask); 51238460Smckusick if (!xdr_bool(xdrsp, &false)) 51338460Smckusick return (0); 51438460Smckusick return (1); 51538460Smckusick errout: 51638460Smckusick sigsetmask(omask); 51738460Smckusick return (0); 51838460Smckusick } 51938460Smckusick 52038460Smckusick #define LINESIZ 10240 52138460Smckusick char line[LINESIZ]; 52238460Smckusick 52338460Smckusick /* 52438460Smckusick * Get the export list 52538460Smckusick */ 52646709Sbostic void 52738460Smckusick get_exportlist() 52838460Smckusick { 52951667Smckusick struct grouplist *grp, *tgrp; 53051667Smckusick struct al_mnt *al_mp, *t_almp; 53138460Smckusick register struct exportlist *ep, *ep2; 53251667Smckusick struct groupnames *t_gn, *t_gn2; 53351667Smckusick struct ucred anoncr; 53438460Smckusick FILE *inf; 53538460Smckusick char *cp, *endcp; 53639681Smckusick char savedc; 53751667Smckusick int len, dirplen, def_set; 53851667Smckusick int exflags; 53938460Smckusick 54038460Smckusick /* 54138460Smckusick * First, get rid of the old list 54238460Smckusick */ 54338460Smckusick ep = exphead.ex_next; 54438460Smckusick while (ep != NULL) { 54538460Smckusick ep2 = ep; 54638460Smckusick ep = ep->ex_next; 54744015Smckusick free_exp(ep2); 54838460Smckusick } 54951667Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 55038460Smckusick 55151667Smckusick t_gn = grpnames; 55251667Smckusick while(t_gn != NULL) { 55351667Smckusick t_gn2 = t_gn; 55451667Smckusick t_gn = t_gn->gn_next; 55551667Smckusick free_grp(t_gn2); 55651667Smckusick } 55751667Smckusick grpnames = (struct groupnames *)0; 55851667Smckusick 55951667Smckusick al_mp = al_head; 56051667Smckusick while (al_mp) { 56151667Smckusick t_almp = al_mp; 56251667Smckusick al_mp = al_mp->al_next; 56351667Smckusick free((caddr_t)t_almp); 56451667Smckusick } 56551667Smckusick al_head = (struct al_mnt *)0; 56651667Smckusick 56738460Smckusick /* 56838460Smckusick * Read in the exports file and build the list, calling 56951667Smckusick * mount() as we go along to push the export rules into the kernel. 57038460Smckusick */ 57138460Smckusick if ((inf = fopen(exname, "r")) == NULL) { 57238460Smckusick syslog(LOG_ERR, "Can't open %s", exname); 57338460Smckusick exit(2); 57438460Smckusick } 57538460Smckusick while (fgets(line, LINESIZ, inf)) { 57651667Smckusick def_set = TRUE; 57751667Smckusick if (debug) 57851667Smckusick fprintf(stderr,"Got line %s\n",line); 57938460Smckusick cp = line; 58038460Smckusick nextfield(&cp, &endcp); 58151667Smckusick if (*cp == '#') 58251667Smckusick goto nextline; 58351667Smckusick if (*cp != '/') { 58451667Smckusick /* create group listing of names */ 58551667Smckusick get_group(cp, ep); 58651667Smckusick goto nextline; 58745271Smckusick } 58851667Smckusick exflags = MNT_EXPORTED; 58951667Smckusick anoncr = def_anon; 59044015Smckusick 59144015Smckusick /* 59244015Smckusick * Create new exports list entry 59344015Smckusick */ 59438460Smckusick len = endcp-cp; 59538460Smckusick if (len <= RPCMNT_PATHLEN && len > 0) { 59651667Smckusick /* 59751667Smckusick * See if this directory is already in the list. 59851667Smckusick */ 59951667Smckusick ep = exphead.ex_next; 60051667Smckusick while (ep) { 60151667Smckusick if (!strcmp(ep->ex_dirp, cp)) 60251667Smckusick break; 60351667Smckusick ep = ep->ex_next; 60451667Smckusick } 60551667Smckusick if (ep == (struct exportlist *)0) { 60651667Smckusick ep = (struct exportlist *)malloc(sizeof(*ep)); 60751667Smckusick if (ep == NULL) 60851667Smckusick goto err; 60951667Smckusick ep->ex_next = (struct exportlist *)0; 61051667Smckusick ep->ex_prev = (struct exportlist *)0; 61151667Smckusick ep->ex_groups = (struct grouplist *)0; 61251667Smckusick ep->ex_defset = FALSE; 61351667Smckusick bcopy(cp, ep->ex_dirp, len); 61451667Smckusick ep->ex_dirp[len] = '\0'; 61551667Smckusick } 61644015Smckusick dirplen = len; 61751667Smckusick if (debug) 61851667Smckusick fprintf(stderr, "Making new ep. [%s]\n", 61951667Smckusick ep->ex_dirp); 62045271Smckusick } else { 62151667Smckusick syslog(LOG_ERR, "Bad Exports File line: %s\n", line); 62251667Smckusick goto nextline; 62345271Smckusick } 62438460Smckusick cp = endcp; 62538460Smckusick nextfield(&cp, &endcp); 62638460Smckusick len = endcp-cp; 62738460Smckusick while (len > 0) { 62839681Smckusick savedc = *endcp; 62939681Smckusick *endcp = '\0'; 63045271Smckusick if (len > RPCMNT_NAMELEN) 63145271Smckusick goto more; 63245271Smckusick if (*cp == '-') { 63351667Smckusick do_opt(cp + 1, ep, &exflags, &anoncr); 63451667Smckusick exflags |= MNT_EXPORTED; 63551667Smckusick def_set = TRUE; 63651667Smckusick if (debug) 63751667Smckusick fprintf(stderr, "got r=%d, ex=%d\n", 63851667Smckusick anoncr.cr_uid,exflags); 63945271Smckusick goto more; 64051667Smckusick } else { 64151667Smckusick def_set = FALSE; 64251667Smckusick if (*cp == '$') { 64351667Smckusick do_group(cp + 1, endcp, &grp); 64451667Smckusick grp->type = MNT_GROUP; 64551667Smckusick } else { 64651667Smckusick get_host(cp, endcp, ep, &grp); 64738460Smckusick } 64851667Smckusick if (grp != NULL) { 64951667Smckusick grp->exflags = exflags; 65051667Smckusick grp->anoncr = anoncr; 65151667Smckusick grp->gr_next = ep->ex_groups; 65251667Smckusick ep->ex_groups = grp; 65351667Smckusick } 65438460Smckusick } 65545271Smckusick more: 65638460Smckusick cp = endcp; 65739681Smckusick *cp = savedc; 65838460Smckusick nextfield(&cp, &endcp); 65945271Smckusick len = endcp - cp; 66038460Smckusick } 66151667Smckusick if (def_set == TRUE) { 66251667Smckusick if (ep->ex_defset == TRUE) 66351667Smckusick syslog(LOG_ERR, "Default specified again dir:%s\n", 66451667Smckusick ep->ex_dirp); 66551667Smckusick else { 66651667Smckusick struct hostent *hpe; 66751667Smckusick 66851667Smckusick ep->ex_defset = TRUE; 66951667Smckusick if (debug) 67051667Smckusick fprintf(stderr,"Adding a default entry\n"); 67151667Smckusick /* add a default group and make the grp list NULL */ 67251667Smckusick hpe = (struct hostent *)malloc(sizeof(struct hostent)); 67351667Smckusick if (hpe == NULL) { 67451667Smckusick syslog(LOG_ERR,"No more memory: mountd Failed"); 67551667Smckusick exit(2); 67651667Smckusick } 67751667Smckusick tgrp = (struct grouplist *) 67851667Smckusick malloc(sizeof(struct grouplist)); 67951667Smckusick if (tgrp == NULL) { 68051667Smckusick syslog(LOG_ERR,"No more memory: mountd Failed"); 68151667Smckusick exit(2); 68251667Smckusick } 68351667Smckusick tgrp->anoncr = anoncr; 68451667Smckusick tgrp->exflags = exflags; 685*51712Smckusick tgrp->type = MNT_HOST; 686*51712Smckusick hpe->h_name = (char *)0; 68751667Smckusick hpe->h_addrtype = AF_INET; 68851667Smckusick hpe->h_length = sizeof (u_long); 689*51712Smckusick hpe->h_addr_list = (char **)0; 69051667Smckusick tgrp->gr_ptr.gt_hostent = hpe; 69151667Smckusick tgrp->gr_next = ep->ex_groups; 69251667Smckusick ep->ex_groups = tgrp; 69351667Smckusick } 69451667Smckusick } 69551667Smckusick grp = ep->ex_groups; 69651667Smckusick while (grp != NULL) { 69751667Smckusick exflags = grp->exflags; 69851667Smckusick anoncr = grp->anoncr; 69951667Smckusick if (grp->type == MNT_GROUP) { 70051667Smckusick tgrp = grp->gr_ptr.gt_grpname->gn_glist; 70151667Smckusick while(tgrp != NULL) { 70251667Smckusick if (do_mount(ep, tgrp, exflags, &anoncr, 70351667Smckusick dirplen) == FALSE) 70451667Smckusick goto nextline; 70551667Smckusick tgrp = tgrp->gr_next; 70651667Smckusick } 70751667Smckusick } else { 70851667Smckusick if (do_mount(ep, grp, exflags, &anoncr, dirplen) 70951667Smckusick == FALSE) 71051667Smckusick goto nextline; 71151667Smckusick } 71251667Smckusick grp = grp->gr_next; 71351667Smckusick } 71451667Smckusick if (cp) 71551667Smckusick *cp = savedc; 71651667Smckusick if (ep->ex_prev == (struct exportlist *)0) { 71751667Smckusick ep->ex_next = exphead.ex_next; 71851667Smckusick ep->ex_prev = &exphead; 71951667Smckusick if (ep->ex_next != NULL) 72051667Smckusick ep->ex_next->ex_prev = ep; 72151667Smckusick exphead.ex_next = ep; 72251667Smckusick } 72351667Smckusick nextline: 72451667Smckusick ; 72551667Smckusick } 72651667Smckusick fclose(inf); 72751667Smckusick return; 72851667Smckusick err: 72951667Smckusick syslog(LOG_ERR, "No more memory: mountd Failed"); 73051667Smckusick exit(2); 73151667Smckusick } 73251667Smckusick 73351667Smckusick do_mount(ep, grp, exflags, anoncrp, dirplen) 73451667Smckusick struct exportlist *ep; 73551667Smckusick struct grouplist *grp; 73651667Smckusick int exflags, dirplen; 73751667Smckusick struct ucred *anoncrp; 73851667Smckusick { 73951667Smckusick int done, found; 74051667Smckusick register u_long **addrp; 74151667Smckusick struct sockaddr_in sin; 74251667Smckusick struct statfs stfsbuf; 74351667Smckusick struct ufs_args args, targs; 74451667Smckusick struct al_mnt *al_mp; 74551667Smckusick char *cp, savedc; 74651667Smckusick 74751667Smckusick args.fspec = 0; 74851667Smckusick args.exflags = exflags; 74951667Smckusick args.anon = *anoncrp; 75051667Smckusick sin.sin_family = AF_INET; 75151667Smckusick sin.sin_port = 0; 75251667Smckusick sin.sin_len = sizeof(sin); 75351667Smckusick if (grp->type == MNT_HOST) 75451667Smckusick addrp = (u_long **)grp->gr_ptr.gt_hostent->h_addr_list; 75551667Smckusick done = FALSE; 75651667Smckusick while(!done) { 75751667Smckusick if (grp->type == MNT_HOST) { 758*51712Smckusick if (grp->gr_ptr.gt_hostent->h_name) 759*51712Smckusick sin.sin_addr.s_addr = **addrp; 760*51712Smckusick else 76151667Smckusick sin.sin_addr.s_addr = INADDR_ANY; 76251667Smckusick args.saddr = (struct sockaddr *)&sin; 76351667Smckusick args.slen = sizeof(sin); 76451667Smckusick #ifdef ISO 76551667Smckusick } else if (grp->type == MNT_ISO) { 76651667Smckusick args.saddr = (struct sockaddr *)grp->gr_ptr.gt_isoaddr; 76751667Smckusick args.slen = sizeof (struct sockaddr_iso); 76851667Smckusick #endif /* ISO */ 76951667Smckusick } else { 77051667Smckusick syslog(LOG_ERR, "Bad grouptype"); 77151667Smckusick free_exp(ep); 77251667Smckusick return (FALSE); 77351667Smckusick } 77451667Smckusick if (statfs(ep->ex_dirp, &stfsbuf) < 0) { 77551667Smckusick if (debug) { 77651667Smckusick fprintf(stderr,"statfs failed.\n"); 77751667Smckusick } 77851667Smckusick syslog(LOG_ERR, "Invalid path: %s", ep->ex_dirp); 77951667Smckusick free_exp(ep); 78051667Smckusick return(FALSE); 78151667Smckusick } 78251667Smckusick found = FALSE; 78351667Smckusick for (al_mp = al_head; al_mp && !found; al_mp = al_mp->al_next) 78451667Smckusick if (al_mp->al_mnted.val[0] == stfsbuf.f_fsid.val[0] && 78551667Smckusick al_mp->al_mnted.val[1] == stfsbuf.f_fsid.val[1]) 78651667Smckusick found = TRUE; 78751667Smckusick if (!found) { 78851667Smckusick /* first time for fs, so must send a MNT_DELEXPORT 78951667Smckusick * to clear the old export list held in the kernel 79051667Smckusick * for this fs. 79151667Smckusick */ 79251667Smckusick al_mp = (struct al_mnt *)malloc(sizeof (struct al_mnt)); 79351667Smckusick al_mp->al_mnted = stfsbuf.f_fsid; 79451667Smckusick al_mp->al_next = al_head; 79551667Smckusick al_head = al_mp; 79651667Smckusick targs.fspec = 0; 79751667Smckusick targs.exflags = MNT_DELEXPORT; 79844015Smckusick cp = (char *)0; 79951667Smckusick while (mount(MOUNT_UFS, ep->ex_dirp, 80051667Smckusick stfsbuf.f_flags | MNT_UPDATE, &targs) < 0) { 80151667Smckusick if (debug) { 80251667Smckusick fprintf(stderr, 80351667Smckusick "tried [%s][%d]\n", 80451667Smckusick ep->ex_dirp,errno); 80551667Smckusick } 80644015Smckusick if (cp == NULL) 80744015Smckusick cp = ep->ex_dirp + dirplen - 1; 80844015Smckusick else 80944015Smckusick *cp = savedc; 81051667Smckusick cp--; 81144015Smckusick /* back up over the last component */ 81244015Smckusick while (*cp == '/' && cp > ep->ex_dirp) 81344015Smckusick cp--; 81444015Smckusick while (*(cp - 1) != '/' && cp > ep->ex_dirp) 81544015Smckusick cp--; 81644015Smckusick if (cp == ep->ex_dirp) { 81751667Smckusick if (debug) { 81851667Smckusick fprintf(stderr,"mnt unsucc\n"); 81951667Smckusick } 82051667Smckusick syslog(LOG_ERR, 82151667Smckusick "Can't export %s", ep->ex_dirp); 82244015Smckusick free_exp(ep); 82351667Smckusick return(FALSE); 82444015Smckusick } 82544015Smckusick savedc = *cp; 82644015Smckusick *cp = '\0'; 82744015Smckusick } 82851667Smckusick if (cp != NULL) { 82944015Smckusick *cp = savedc; 83051667Smckusick } 83138460Smckusick } 83251667Smckusick cp = (char *)0; 83351667Smckusick while (mount(MOUNT_UFS, ep->ex_dirp, 83451667Smckusick stfsbuf.f_flags | MNT_UPDATE, &args) < 0) { 83551667Smckusick if (errno == EPERM) { 83651667Smckusick syslog(LOG_ERR, 83751667Smckusick "Can't change attributes for %s.\n", 83851667Smckusick ep->ex_dirp); 83951667Smckusick if (cp != NULL) 84051667Smckusick *cp = savedc; 84151667Smckusick break; 84251667Smckusick } 84351667Smckusick if (cp == NULL) 84451667Smckusick cp = ep->ex_dirp + dirplen - 1; 84551667Smckusick else 84651667Smckusick *cp = savedc; 84751667Smckusick cp--; 84851667Smckusick /* back up over the last component */ 84951667Smckusick while (*cp == '/' && cp > ep->ex_dirp) 85051667Smckusick cp--; 85151667Smckusick while (*(cp - 1) != '/' && cp > ep->ex_dirp) 85251667Smckusick cp--; 85351667Smckusick if (cp == ep->ex_dirp) { 85451667Smckusick if (debug) { 85551667Smckusick fprintf(stderr,"mnt unsucc\n"); 85651667Smckusick } 85751667Smckusick syslog(LOG_ERR, "Can't export %s", ep->ex_dirp); 85851667Smckusick free_exp(ep); 85951667Smckusick return(FALSE); 86051667Smckusick } 86151667Smckusick savedc = *cp; 86251667Smckusick *cp = '\0'; 86351667Smckusick } 86451667Smckusick if (addrp == NULL) 86551667Smckusick done = TRUE; 86651667Smckusick else { 86751667Smckusick ++addrp; 86851667Smckusick if (*addrp == NULL) 86951667Smckusick done = TRUE; 87051667Smckusick } 87151667Smckusick if (cp != NULL) 87251667Smckusick *cp = savedc; 87338460Smckusick } 87451667Smckusick return(TRUE); 87538460Smckusick } 87638460Smckusick 87751667Smckusick 87838460Smckusick /* 87938460Smckusick * Parse out the next white space separated field 88038460Smckusick */ 88151667Smckusick void 88238460Smckusick nextfield(cp, endcp) 88338460Smckusick char **cp; 88438460Smckusick char **endcp; 88538460Smckusick { 88638460Smckusick register char *p; 88738460Smckusick 88838460Smckusick p = *cp; 88938460Smckusick while (*p == ' ' || *p == '\t') 89038460Smckusick p++; 89138460Smckusick if (*p == '\n' || *p == '\0') { 89238460Smckusick *cp = *endcp = p; 89338460Smckusick return; 89438460Smckusick } 89538460Smckusick *cp = p++; 89638460Smckusick while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 89738460Smckusick p++; 89838460Smckusick *endcp = p; 89938460Smckusick } 90039681Smckusick 90139681Smckusick /* 90244015Smckusick * Parse the option string 90339681Smckusick */ 90451667Smckusick void 90551667Smckusick do_opt(cpopt, ep, exflagsp, cr) 90644015Smckusick register char *cpopt; 90751667Smckusick struct exportlist *ep; 90851667Smckusick int *exflagsp; 90951667Smckusick struct ucred *cr; 91039681Smckusick { 91144015Smckusick register char *cpoptarg, *cpoptend; 912*51712Smckusick int allflag = 1; 91339681Smckusick 91444015Smckusick while (cpopt && *cpopt) { 91544015Smckusick if (cpoptend = index(cpopt, ',')) 91644015Smckusick *cpoptend++ = '\0'; 91744015Smckusick if (cpoptarg = index(cpopt, '=')) 91844015Smckusick *cpoptarg++ = '\0'; 91944015Smckusick if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 92051667Smckusick *exflagsp |= MNT_EXRDONLY; 92151667Smckusick } else if ((!strcmp(cpopt, "root") || !strcmp(cpopt, "r") || 92251667Smckusick !(allflag = strcmp(cpopt, "allanon"))) && cpoptarg) { 92351667Smckusick parsecred(cpoptarg, cr); 92451667Smckusick if (allflag == 0) 92551667Smckusick *exflagsp |= MNT_EXPORTANON; 92651667Smckusick } else if (!strcmp(cpopt, "kerb") || !strcmp(cpopt, "k")) { 92751667Smckusick *exflagsp |= MNT_EXKERB; 92844015Smckusick } else 92951667Smckusick syslog(LOG_ERR, "opt %s ignored for %s", cpopt, 93044015Smckusick ep->ex_dirp); 93144015Smckusick cpopt = cpoptend; 93244015Smckusick } 93344015Smckusick } 93444015Smckusick 93551667Smckusick /* 93651667Smckusick * Parse a description of a credential. 93751667Smckusick */ 93851667Smckusick parsecred(namelist, cr) 93951667Smckusick char *namelist; 94051667Smckusick register struct ucred *cr; 94151667Smckusick { 94251667Smckusick register char *name; 94351667Smckusick register int cnt; 94451667Smckusick char *names; 94551667Smckusick struct passwd *pw; 94651667Smckusick struct group *gr; 94751667Smckusick int ngroups, groups[NGROUPS + 1]; 94851667Smckusick 94951667Smckusick /* 95051667Smckusick * Set up the unpriviledged user. 95151667Smckusick */ 95251667Smckusick cr->cr_ref = 1; 95351667Smckusick cr->cr_uid = -2; 95451667Smckusick cr->cr_groups[0] = -2; 95551667Smckusick cr->cr_ngroups = 1; 95651667Smckusick /* 95751667Smckusick * Get the user's password table entry. 95851667Smckusick */ 95951667Smckusick names = strsep(&namelist, " \t\n"); 96051667Smckusick name = strsep(&names, ":"); 96151667Smckusick if (isdigit(*name) || *name == '-') 96251667Smckusick pw = getpwuid(atoi(name)); 96351667Smckusick else 96451667Smckusick pw = getpwnam(name); 96551667Smckusick /* 96651667Smckusick * Credentials specified as those of a user. 96751667Smckusick */ 96851667Smckusick if (names == NULL) { 96951667Smckusick if (pw == NULL) { 97051667Smckusick syslog(LOG_ERR, "Unknown user: %s\n", name); 97151667Smckusick return; 97251667Smckusick } 97351667Smckusick cr->cr_uid = pw->pw_uid; 97451667Smckusick ngroups = NGROUPS + 1; 97551667Smckusick if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) 97651667Smckusick syslog(LOG_ERR, "Too many groups\n"); 97751667Smckusick /* 97851667Smckusick * Convert from int's to gid_t's and compress out duplicate 97951667Smckusick */ 98051667Smckusick cr->cr_ngroups = ngroups - 1; 98151667Smckusick cr->cr_groups[0] = groups[0]; 98251667Smckusick for (cnt = 2; cnt < ngroups; cnt++) 98351667Smckusick cr->cr_groups[cnt - 1] = groups[cnt]; 98451667Smckusick return; 98551667Smckusick } 98651667Smckusick /* 98751667Smckusick * Explicit credential specified as a colon separated list: 98851667Smckusick * uid:gid:gid:... 98951667Smckusick */ 99051667Smckusick if (pw != NULL) 99151667Smckusick cr->cr_uid = pw->pw_uid; 99251667Smckusick else if (isdigit(*name) || *name == '-') 99351667Smckusick cr->cr_uid = atoi(name); 99451667Smckusick else { 99551667Smckusick syslog(LOG_ERR, "Unknown user: %s\n", name); 99651667Smckusick return; 99751667Smckusick } 99851667Smckusick cr->cr_ngroups = 0; 99951667Smckusick while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { 100051667Smckusick name = strsep(&names, ":"); 100151667Smckusick if (isdigit(*name) || *name == '-') { 100251667Smckusick cr->cr_groups[cr->cr_ngroups++] = atoi(name); 100351667Smckusick } else { 100451667Smckusick if ((gr = getgrnam(name)) == NULL) { 100551667Smckusick syslog(LOG_ERR, "Unknown group: %s\n", name); 100651667Smckusick continue; 100751667Smckusick } 100851667Smckusick cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; 100951667Smckusick } 101051667Smckusick } 101151667Smckusick if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) 101251667Smckusick syslog(LOG_ERR, "Too many groups\n"); 101351667Smckusick } 101451667Smckusick 101544015Smckusick #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 101644015Smckusick /* 101744015Smckusick * Routines that maintain the remote mounttab 101844015Smckusick */ 101951667Smckusick void 102051667Smckusick get_mountlist() 102144015Smckusick { 102244015Smckusick register struct mountlist *mlp, **mlpp; 102344015Smckusick register char *eos, *dirp; 102444015Smckusick int len; 102544015Smckusick char str[STRSIZ]; 102644015Smckusick FILE *mlfile; 102744015Smckusick 1028*51712Smckusick if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) { 102951667Smckusick syslog(LOG_ERR, "Can't open %s", _PATH_RMOUNTLIST); 103044015Smckusick return; 103144015Smckusick } 103244015Smckusick mlpp = &mlhead; 103344015Smckusick while (fgets(str, STRSIZ, mlfile) != NULL) { 103444015Smckusick if ((dirp = index(str, '\t')) == NULL && 103544015Smckusick (dirp = index(str, ' ')) == NULL) 103644015Smckusick continue; 103744015Smckusick mlp = (struct mountlist *)malloc(sizeof (*mlp)); 103844015Smckusick len = dirp-str; 103944015Smckusick if (len > RPCMNT_NAMELEN) 104044015Smckusick len = RPCMNT_NAMELEN; 104144015Smckusick bcopy(str, mlp->ml_host, len); 104244015Smckusick mlp->ml_host[len] = '\0'; 104344015Smckusick while (*dirp == '\t' || *dirp == ' ') 104444015Smckusick dirp++; 104544015Smckusick if ((eos = index(dirp, '\t')) == NULL && 104644015Smckusick (eos = index(dirp, ' ')) == NULL && 104744015Smckusick (eos = index(dirp, '\n')) == NULL) 104844015Smckusick len = strlen(dirp); 104944015Smckusick else 105044015Smckusick len = eos-dirp; 105144015Smckusick if (len > RPCMNT_PATHLEN) 105244015Smckusick len = RPCMNT_PATHLEN; 105344015Smckusick bcopy(dirp, mlp->ml_dirp, len); 105444015Smckusick mlp->ml_dirp[len] = '\0'; 105544015Smckusick mlp->ml_next = (struct mountlist *)0; 105644015Smckusick *mlpp = mlp; 105744015Smckusick mlpp = &mlp->ml_next; 105844015Smckusick } 105944015Smckusick fclose(mlfile); 106044015Smckusick } 106144015Smckusick 106251667Smckusick void 106351667Smckusick del_mlist(hostp, dirp) 106444015Smckusick register char *hostp, *dirp; 106544015Smckusick { 106644015Smckusick register struct mountlist *mlp, **mlpp; 1067*51712Smckusick struct mountlist *mlp2; 106844015Smckusick FILE *mlfile; 106944015Smckusick int fnd = 0; 107044015Smckusick 107144015Smckusick mlpp = &mlhead; 107244015Smckusick mlp = mlhead; 107344015Smckusick while (mlp) { 107444015Smckusick if (!strcmp(mlp->ml_host, hostp) && 107544015Smckusick (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 107644015Smckusick fnd = 1; 1077*51712Smckusick mlp2 = mlp; 1078*51712Smckusick *mlpp = mlp = mlp->ml_next; 1079*51712Smckusick free((caddr_t)mlp2); 1080*51712Smckusick } else { 1081*51712Smckusick mlpp = &mlp->ml_next; 1082*51712Smckusick mlp = mlp->ml_next; 108339681Smckusick } 108439681Smckusick } 108544015Smckusick if (fnd) { 108644015Smckusick if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 108751667Smckusick syslog(LOG_WARNING,"Can't update %s", _PATH_RMOUNTLIST); 108844015Smckusick return; 108944015Smckusick } 109044015Smckusick mlp = mlhead; 109144015Smckusick while (mlp) { 109244015Smckusick fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 109344015Smckusick mlp = mlp->ml_next; 109444015Smckusick } 109544015Smckusick fclose(mlfile); 109644015Smckusick } 109739681Smckusick } 109844015Smckusick 109951667Smckusick void 110051667Smckusick add_mlist(hostp, dirp) 110144015Smckusick register char *hostp, *dirp; 110244015Smckusick { 110344015Smckusick register struct mountlist *mlp, **mlpp; 110444015Smckusick FILE *mlfile; 110544015Smckusick 110644015Smckusick mlpp = &mlhead; 110744015Smckusick mlp = mlhead; 110844015Smckusick while (mlp) { 110944015Smckusick if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 111044015Smckusick return; 111144015Smckusick mlpp = &mlp->ml_next; 111244015Smckusick mlp = mlp->ml_next; 111344015Smckusick } 111444015Smckusick mlp = (struct mountlist *)malloc(sizeof (*mlp)); 111544015Smckusick strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 111644015Smckusick mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 111744015Smckusick strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 111844015Smckusick mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 111944015Smckusick mlp->ml_next = (struct mountlist *)0; 112044015Smckusick *mlpp = mlp; 112144015Smckusick if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 112244015Smckusick syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST); 112344015Smckusick return; 112444015Smckusick } 112544015Smckusick fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 112644015Smckusick fclose(mlfile); 112744015Smckusick } 112844015Smckusick 112944015Smckusick /* 113044015Smckusick * This function is called via. SIGTERM when the system is going down. 113144015Smckusick * It sends a broadcast RPCMNT_UMNTALL. 113244015Smckusick */ 113346709Sbostic void 113444015Smckusick send_umntall() 113544015Smckusick { 113644015Smckusick (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL, 113744015Smckusick xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each); 113851667Smckusick exit(0); 113944015Smckusick } 114044015Smckusick 114144015Smckusick umntall_each(resultsp, raddr) 114244015Smckusick caddr_t resultsp; 114344015Smckusick struct sockaddr_in *raddr; 114444015Smckusick { 114544015Smckusick return (1); 114644015Smckusick } 114744015Smckusick 114844015Smckusick /* 114944015Smckusick * Free up an exports list component 115044015Smckusick */ 115151667Smckusick void 115244015Smckusick free_exp(ep) 115344015Smckusick register struct exportlist *ep; 115444015Smckusick { 115544015Smckusick register struct grouplist *grp; 115644015Smckusick struct grouplist *grp2; 115744015Smckusick 115844015Smckusick grp = ep->ex_groups; 115944015Smckusick while (grp != NULL) { 116044015Smckusick grp2 = grp; 116144015Smckusick grp = grp->gr_next; 116251667Smckusick free_grp(grp2); 116344015Smckusick } 116444015Smckusick free((caddr_t)ep); 116544015Smckusick } 116651667Smckusick 116751667Smckusick /* 116851667Smckusick * Free up a group list. 116951667Smckusick */ 117051667Smckusick void 117151667Smckusick free_grp(grp) 117251667Smckusick register struct grouplist *grp; 117351667Smckusick { 117451667Smckusick register char **addrp; 117551667Smckusick 117651667Smckusick if (grp->type == MNT_HOST) { 1177*51712Smckusick if (grp->gr_ptr.gt_hostent->h_name) { 1178*51712Smckusick addrp = grp->gr_ptr.gt_hostent->h_addr_list; 1179*51712Smckusick while (addrp && *addrp) 1180*51712Smckusick free(*addrp++); 1181*51712Smckusick free((caddr_t)grp->gr_ptr.gt_hostent->h_addr_list); 1182*51712Smckusick free(grp->gr_ptr.gt_hostent->h_name); 1183*51712Smckusick } 118451667Smckusick free((caddr_t)grp->gr_ptr.gt_hostent); 118551667Smckusick } 118651667Smckusick #ifdef ISO 118751667Smckusick else if (grp->type == MNT_ISO) 118851667Smckusick free((caddr_t)grp->gr_ptr.gt_isoaddr); 118951667Smckusick #endif 119051667Smckusick free((caddr_t)grp); 119151667Smckusick } 119251667Smckusick 119351667Smckusick void 119451667Smckusick get_group(line, ep) 119551667Smckusick char *line; 119651667Smckusick struct export_list *ep; 119751667Smckusick { 119851667Smckusick int done; 119951667Smckusick struct grouplist *grp; 120051667Smckusick struct groupnames *t_gn; 120151667Smckusick char *cp, *endcp, savedc; 120251667Smckusick 120351667Smckusick cp = line; 120451667Smckusick nextfield(&cp, &endcp); 120551667Smckusick savedc = *endcp; 120651667Smckusick *endcp = NULL; 120751667Smckusick if (*(endcp-1) == '=') { 120851667Smckusick *(endcp-1) = NULL; 120951667Smckusick } 121051667Smckusick /* check to see if this group exists already */ 121151667Smckusick t_gn = grpnames; 121251667Smckusick while(t_gn != NULL) { 121351667Smckusick if (strcmp(t_gn->gn_name,cp) == 0) { 121451667Smckusick syslog(LOG_ERR,"Group redifined, second ignored."); 121551667Smckusick return; 121651667Smckusick } 121751667Smckusick t_gn = t_gn->gn_next; 121851667Smckusick } 121951667Smckusick 122051667Smckusick /* make a new group list entry */ 122151667Smckusick t_gn = (struct groupnames *)malloc(sizeof(struct groupnames)); 122251667Smckusick if (t_gn == NULL) { 122351667Smckusick syslog(LOG_ERR,"Group: Couldn't Malloc."); 122451667Smckusick exit(2); 122551667Smckusick } 122651667Smckusick strcpy(t_gn->gn_name,cp); 122751667Smckusick t_gn->gn_next = grpnames; 122851667Smckusick grpnames = t_gn; 122951667Smckusick t_gn->gn_glist = NULL; 123051667Smckusick *endcp = savedc; 123151667Smckusick cp = endcp; 123251667Smckusick done = FALSE; 123351667Smckusick while(!done) { 123451667Smckusick nextfield(&cp, &endcp); 123551667Smckusick if (cp == endcp) 123651667Smckusick done = TRUE; 123751667Smckusick else { 123851667Smckusick savedc = *endcp; 123951667Smckusick *endcp = NULL; 124051667Smckusick if (strcmp(cp, "=")) { 124151667Smckusick /* add to group list */ 124251667Smckusick get_host(cp, endcp, ep, &grp); 124351667Smckusick if (grp != NULL) { 124451667Smckusick grp->gr_next = t_gn->gn_glist; 124551667Smckusick t_gn->gn_glist = grp; 124651667Smckusick } 124751667Smckusick } 124851667Smckusick *endcp = savedc; 124951667Smckusick cp = endcp; 125051667Smckusick } 125151667Smckusick } 125251667Smckusick } 125351667Smckusick 125451667Smckusick void 125551667Smckusick get_host(cp, endcp, ep, gp) 125651667Smckusick char *cp, *endcp; 125751667Smckusick struct exportlist *ep; 125851667Smckusick struct grouplist **gp; 125951667Smckusick { 126051667Smckusick register struct hostent *hp, *nhp; 126151667Smckusick register struct grouplist *grp; 126251667Smckusick register char **addrp, **naddrp; 126351667Smckusick struct hostent t_host; 126451667Smckusick int i; 126551667Smckusick u_long saddr; 126651667Smckusick char *aptr[2]; 126751667Smckusick #ifdef ISO 126851667Smckusick struct iso_addr *isop; 126951667Smckusick struct sockaddr_iso *isoaddr; 127051667Smckusick #endif 127151667Smckusick 127251667Smckusick if (isdigit(*cp)) { 127351667Smckusick saddr = inet_addr(cp); 127451667Smckusick if (saddr == -1) { 127551667Smckusick syslog(LOG_ERR, 127651667Smckusick "Bad Exports File, %s: %s", cp, 127751667Smckusick "inet_addr failed, ignored"); 127851667Smckusick *gp = NULL; 127951667Smckusick return; 128051667Smckusick } 128151667Smckusick hp = &t_host; 128251667Smckusick hp->h_name = cp; 128351667Smckusick hp->h_addrtype = AF_INET; 128451667Smckusick hp->h_length = sizeof (u_long); 128551667Smckusick hp->h_addr_list = aptr; 128651667Smckusick aptr[0] = (char *)&saddr; 128751667Smckusick aptr[1] = (char *)0; 128851667Smckusick #ifdef ISO 128951667Smckusick } else if (!strncmp(cp, "iso=", 4)) { 129051667Smckusick if ((isop = iso_addr(cp + 4)) == NULL) { 129151667Smckusick syslog(LOG_ERR, 129251667Smckusick "Bad Exports File, %s: %s", cp, 129351667Smckusick "iso_addr failed, ignored"); 129451667Smckusick *gp = NULL; 129551667Smckusick return; 129651667Smckusick } 129751667Smckusick isoaddr = (struct sockaddr_iso *) 129851667Smckusick malloc(sizeof (struct sockaddr_iso)); 129951667Smckusick if (isoaddr == NULL) 130051667Smckusick goto err1; 130151667Smckusick bzero((caddr_t)isoaddr, sizeof (struct sockaddr_iso)); 130251667Smckusick bcopy((caddr_t)isop, (caddr_t)isoaddr->siso_addr, 130351667Smckusick sizeof (struct iso_addr)); 130451667Smckusick isoaddr->siso_len = sizeof (struct sockaddr_iso); 130551667Smckusick isoaddr->siso_family = AF_ISO; 130651667Smckusick grp = (struct grouplist *) 130751667Smckusick malloc(sizeof(struct grouplist)); 130851667Smckusick if (grp == NULL) 130951667Smckusick goto err1; 131051667Smckusick grp->type = MNT_ISO; 131151667Smckusick grp->gr_ptr.gt_isoaddr = isoaddr; 131251667Smckusick *gp = grp; 131351667Smckusick return; 131451667Smckusick #endif /* ISO */ 131551667Smckusick } else if ((hp = gethostbyname(cp)) == NULL) { 131651667Smckusick syslog(LOG_ERR, "Bad Exports File, %s: %s", 131751667Smckusick cp, "Gethostbyname failed, ignored"); 131851667Smckusick *gp = NULL; 131951667Smckusick return; 132051667Smckusick } 132151667Smckusick grp = (struct grouplist *) 132251667Smckusick malloc(sizeof(struct grouplist)); 132351667Smckusick if (grp == NULL) 132451667Smckusick goto err1; 132551667Smckusick grp->type = MNT_HOST; 132651667Smckusick nhp = grp->gr_ptr.gt_hostent = (struct hostent *) 132751667Smckusick malloc(sizeof(struct hostent)); 132851667Smckusick if (nhp == NULL) 132951667Smckusick goto err1; 133051667Smckusick bcopy((caddr_t)hp, (caddr_t)nhp, 133151667Smckusick sizeof(struct hostent)); 133251667Smckusick i = strlen(hp->h_name)+1; 133351667Smckusick nhp->h_name = (char *)malloc(i); 133451667Smckusick if (nhp->h_name == NULL) 133551667Smckusick goto err1; 133651667Smckusick bcopy(hp->h_name, nhp->h_name, i); 133751667Smckusick addrp = hp->h_addr_list; 133851667Smckusick i = 1; 133951667Smckusick while (*addrp++) 134051667Smckusick i++; 134151667Smckusick naddrp = nhp->h_addr_list = (char **) 134251667Smckusick malloc(i*sizeof(char *)); 134351667Smckusick if (naddrp == NULL) 134451667Smckusick goto err1; 134551667Smckusick addrp = hp->h_addr_list; 134651667Smckusick while (*addrp) { 134751667Smckusick *naddrp = (char *) 134851667Smckusick malloc(hp->h_length); 134951667Smckusick if (*naddrp == NULL) 135051667Smckusick goto err1; 135151667Smckusick bcopy(*addrp, *naddrp, 135251667Smckusick hp->h_length); 135351667Smckusick addrp++; 135451667Smckusick naddrp++; 135551667Smckusick } 135651667Smckusick *naddrp = (char *)0; 135751667Smckusick *gp = grp; 135851667Smckusick return; 135951667Smckusick err1: 136051667Smckusick syslog(LOG_ERR, "No more memory: mountd Failed"); 136151667Smckusick exit(2); 136251667Smckusick } 136351667Smckusick 136451667Smckusick void 136551667Smckusick do_group(cp, endcp, gp) 136651667Smckusick char *cp, *endcp; 136751667Smckusick struct grouplist **gp; 136851667Smckusick { 136951667Smckusick int found; 137051667Smckusick struct groupnames *t_gn; 137151667Smckusick 137251667Smckusick t_gn = grpnames; 137351667Smckusick found = FALSE; 137451667Smckusick while((t_gn != NULL) && !found) { 137551667Smckusick if(strcmp(t_gn->gn_name,cp) == 0) { 137651667Smckusick found = TRUE; 137751667Smckusick *gp = (struct grouplist *) 137851667Smckusick malloc(sizeof(struct grouplist)); 137951667Smckusick if (*gp == NULL) { 138051667Smckusick syslog(LOG_ERR,"No more memory: mountd Failed"); 138151667Smckusick exit(2); 138251667Smckusick } 138351667Smckusick (*gp)->gr_ptr.gt_grpname = (struct groupnames *) 138451667Smckusick malloc(sizeof(struct groupnames)); 138551667Smckusick if ((*gp)->gr_ptr.gt_grpname == NULL) { 138651667Smckusick syslog(LOG_ERR,"No more memory: mountd Failed"); 138751667Smckusick exit(2); 138851667Smckusick } 138951667Smckusick (*gp)->gr_ptr.gt_grpname->gn_glist = t_gn->gn_glist; 139051667Smckusick return; 139151667Smckusick } 139251667Smckusick t_gn = t_gn->gn_next; 139351667Smckusick } 139451667Smckusick *gp = NULL; 139551667Smckusick } 139651667Smckusick 139751667Smckusick /* 139851667Smckusick * char *realpath(const char *path, char resolved_path[MAXPATHLEN]) 139951667Smckusick * 140051667Smckusick * find the real name of path, by removing all ".", ".." 140151667Smckusick * and symlink components. 140251667Smckusick * 140351667Smckusick * Jan-Simon Pendry, September 1991. 140451667Smckusick */ 140551667Smckusick char * 140651667Smckusick realpath(path, resolved) 140751667Smckusick char *path; 140851667Smckusick char resolved[MAXPATHLEN]; 140951667Smckusick { 141051667Smckusick int d = open(".", O_RDONLY); 141151667Smckusick int rootd = 0; 141251667Smckusick char *p, *q; 141351667Smckusick struct stat stb; 141451667Smckusick char wbuf[MAXPATHLEN]; 141551667Smckusick 141651667Smckusick strcpy(resolved, path); 141751667Smckusick 141851667Smckusick if (d < 0) 141951667Smckusick return 0; 142051667Smckusick 142151667Smckusick loop:; 142251667Smckusick q = strrchr(resolved, '/'); 142351667Smckusick if (q) { 142451667Smckusick p = q + 1; 142551667Smckusick if (q == resolved) 142651667Smckusick q = "/"; 142751667Smckusick else { 142851667Smckusick do 142951667Smckusick --q; 143051667Smckusick while (q > resolved && *q == '/'); 143151667Smckusick q[1] = '\0'; 143251667Smckusick q = resolved; 143351667Smckusick } 143451667Smckusick if (chdir(q) < 0) 143551667Smckusick goto out; 143651667Smckusick } else 143751667Smckusick p = resolved; 143851667Smckusick 143951667Smckusick if (lstat(p, &stb) == 0) { 144051667Smckusick if (S_ISLNK(stb.st_mode)) { 144151667Smckusick int n = readlink(p, resolved, MAXPATHLEN); 144251667Smckusick if (n < 0) 144351667Smckusick goto out; 144451667Smckusick resolved[n] = '\0'; 144551667Smckusick goto loop; 144651667Smckusick } 144751667Smckusick if (S_ISDIR(stb.st_mode)) { 144851667Smckusick if (chdir(p) < 0) 144951667Smckusick goto out; 145051667Smckusick p = ""; 145151667Smckusick } 145251667Smckusick } 145351667Smckusick 145451667Smckusick strcpy(wbuf, p); 145551667Smckusick if (getcwd(resolved, MAXPATHLEN) == 0) 145651667Smckusick goto out; 145751667Smckusick if (resolved[0] == '/' && resolved[1] == '\0') 145851667Smckusick rootd = 1; 145951667Smckusick 146051667Smckusick if (*wbuf) { 146151667Smckusick if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) { 146251667Smckusick errno = ENAMETOOLONG; 146351667Smckusick goto out; 146451667Smckusick } 146551667Smckusick if (rootd == 0) 146651667Smckusick strcat(resolved, "/"); 146751667Smckusick strcat(resolved, wbuf); 146851667Smckusick } 146951667Smckusick 147051667Smckusick if (fchdir(d) < 0) 147151667Smckusick goto out; 147251667Smckusick (void) close(d); 147351667Smckusick 147451667Smckusick return resolved; 147551667Smckusick 147651667Smckusick out:; 147751667Smckusick (void) close(d); 147851667Smckusick return 0; 147951667Smckusick } 148051711Smckusick 148151711Smckusick #ifdef DEBUG 148251711Smckusick void 148351711Smckusick SYSLOG(int pri, const char *fmt, ...) 148451711Smckusick { 148551711Smckusick va_list ap; 148651711Smckusick 148751711Smckusick va_start(ap, fmt); 148851711Smckusick vfprintf(stderr, fmt, ap); 148951711Smckusick va_end(ap); 149051711Smckusick } 149151711Smckusick #endif /* DEBUG */ 1492