mountd.c revision 29317
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1989, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * This code is derived from software contributed to Berkeley by 61558Srgrimes * Herb Hasler and Rick Macklem at The University of Guelph. 71558Srgrimes * 81558Srgrimes * Redistribution and use in source and binary forms, with or without 91558Srgrimes * modification, are permitted provided that the following conditions 101558Srgrimes * are met: 111558Srgrimes * 1. Redistributions of source code must retain the above copyright 121558Srgrimes * notice, this list of conditions and the following disclaimer. 131558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141558Srgrimes * notice, this list of conditions and the following disclaimer in the 151558Srgrimes * documentation and/or other materials provided with the distribution. 161558Srgrimes * 3. All advertising materials mentioning features or use of this software 171558Srgrimes * must display the following acknowledgement: 181558Srgrimes * This product includes software developed by the University of 191558Srgrimes * California, Berkeley and its contributors. 201558Srgrimes * 4. Neither the name of the University nor the names of its contributors 211558Srgrimes * may be used to endorse or promote products derived from this software 221558Srgrimes * without specific prior written permission. 231558Srgrimes * 241558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341558Srgrimes * SUCH DAMAGE. 351558Srgrimes */ 361558Srgrimes 371558Srgrimes#ifndef lint 381558Srgrimesstatic char copyright[] = 391558Srgrimes"@(#) Copyright (c) 1989, 1993\n\ 401558Srgrimes The Regents of the University of California. All rights reserved.\n"; 412999Swollman#endif /*not lint*/ 421558Srgrimes 431558Srgrimes#ifndef lint 4423681Speter/*static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; */ 452999Swollmanstatic const char rcsid[] = 4629317Sjlemon "$Id: mountd.c,v 1.23 1997/08/29 19:22:28 guido Exp $"; 472999Swollman#endif /*not lint*/ 481558Srgrimes 491558Srgrimes#include <sys/param.h> 501558Srgrimes#include <sys/file.h> 511558Srgrimes#include <sys/ioctl.h> 521558Srgrimes#include <sys/mount.h> 531558Srgrimes#include <sys/socket.h> 541558Srgrimes#include <sys/stat.h> 551558Srgrimes#include <sys/syslog.h> 561558Srgrimes#include <sys/ucred.h> 5724330Sguido#include <sys/sysctl.h> 581558Srgrimes 591558Srgrimes#include <rpc/rpc.h> 601558Srgrimes#include <rpc/pmap_clnt.h> 611558Srgrimes#include <rpc/pmap_prot.h> 621558Srgrimes#ifdef ISO 631558Srgrimes#include <netiso/iso.h> 641558Srgrimes#endif 651558Srgrimes#include <nfs/rpcv2.h> 669336Sdfr#include <nfs/nfsproto.h> 6724330Sguido#include <nfs/nfs.h> 6823681Speter#include <ufs/ufs/ufsmount.h> 6923681Speter#include <msdosfs/msdosfsmount.h> 7023681Speter#include <isofs/cd9660/cd9660_mount.h> /* XXX need isofs in include */ 711558Srgrimes 721558Srgrimes#include <arpa/inet.h> 731558Srgrimes 741558Srgrimes#include <ctype.h> 751558Srgrimes#include <errno.h> 761558Srgrimes#include <grp.h> 771558Srgrimes#include <netdb.h> 781558Srgrimes#include <pwd.h> 791558Srgrimes#include <signal.h> 801558Srgrimes#include <stdio.h> 811558Srgrimes#include <stdlib.h> 821558Srgrimes#include <string.h> 831558Srgrimes#include <unistd.h> 841558Srgrimes#include "pathnames.h" 851558Srgrimes 861558Srgrimes#ifdef DEBUG 871558Srgrimes#include <stdarg.h> 881558Srgrimes#endif 891558Srgrimes 901558Srgrimes/* 911558Srgrimes * Structures for keeping the mount list and export list 921558Srgrimes */ 931558Srgrimesstruct mountlist { 941558Srgrimes struct mountlist *ml_next; 951558Srgrimes char ml_host[RPCMNT_NAMELEN+1]; 961558Srgrimes char ml_dirp[RPCMNT_PATHLEN+1]; 971558Srgrimes}; 981558Srgrimes 991558Srgrimesstruct dirlist { 1001558Srgrimes struct dirlist *dp_left; 1011558Srgrimes struct dirlist *dp_right; 1021558Srgrimes int dp_flag; 1031558Srgrimes struct hostlist *dp_hosts; /* List of hosts this dir exported to */ 1041558Srgrimes char dp_dirp[1]; /* Actually malloc'd to size of dir */ 1051558Srgrimes}; 1061558Srgrimes/* dp_flag bits */ 1071558Srgrimes#define DP_DEFSET 0x1 1089336Sdfr#define DP_HOSTSET 0x2 1099336Sdfr#define DP_KERB 0x4 1101558Srgrimes 1111558Srgrimesstruct exportlist { 1121558Srgrimes struct exportlist *ex_next; 1131558Srgrimes struct dirlist *ex_dirl; 1141558Srgrimes struct dirlist *ex_defdir; 1151558Srgrimes int ex_flag; 1161558Srgrimes fsid_t ex_fs; 1171558Srgrimes char *ex_fsdir; 11827447Sdfr char *ex_indexfile; 1191558Srgrimes}; 1201558Srgrimes/* ex_flag bits */ 1211558Srgrimes#define EX_LINKED 0x1 1221558Srgrimes 1231558Srgrimesstruct netmsk { 1241558Srgrimes u_long nt_net; 1251558Srgrimes u_long nt_mask; 1261558Srgrimes char *nt_name; 1271558Srgrimes}; 1281558Srgrimes 1291558Srgrimesunion grouptypes { 1301558Srgrimes struct hostent *gt_hostent; 1311558Srgrimes struct netmsk gt_net; 1321558Srgrimes#ifdef ISO 1331558Srgrimes struct sockaddr_iso *gt_isoaddr; 1341558Srgrimes#endif 1351558Srgrimes}; 1361558Srgrimes 1371558Srgrimesstruct grouplist { 1381558Srgrimes int gr_type; 1391558Srgrimes union grouptypes gr_ptr; 1401558Srgrimes struct grouplist *gr_next; 1411558Srgrimes}; 1421558Srgrimes/* Group types */ 1431558Srgrimes#define GT_NULL 0x0 1441558Srgrimes#define GT_HOST 0x1 1451558Srgrimes#define GT_NET 0x2 1461558Srgrimes#define GT_ISO 0x4 1477401Swpaul#define GT_IGNORE 0x5 1481558Srgrimes 1491558Srgrimesstruct hostlist { 1509336Sdfr int ht_flag; /* Uses DP_xx bits */ 1511558Srgrimes struct grouplist *ht_grp; 1521558Srgrimes struct hostlist *ht_next; 1531558Srgrimes}; 1541558Srgrimes 1559336Sdfrstruct fhreturn { 1569336Sdfr int fhr_flag; 1579336Sdfr int fhr_vers; 1589336Sdfr nfsfh_t fhr_fh; 1599336Sdfr}; 1609336Sdfr 1611558Srgrimes/* Global defs */ 1621558Srgrimeschar *add_expdir __P((struct dirlist **, char *, int)); 1631558Srgrimesvoid add_dlist __P((struct dirlist **, struct dirlist *, 1649336Sdfr struct grouplist *, int)); 1651558Srgrimesvoid add_mlist __P((char *, char *)); 1661558Srgrimesint check_dirpath __P((char *)); 1671558Srgrimesint check_options __P((struct dirlist *)); 1689336Sdfrint chk_host __P((struct dirlist *, u_long, int *, int *)); 1691558Srgrimesvoid del_mlist __P((char *, char *)); 1701558Srgrimesstruct dirlist *dirp_search __P((struct dirlist *, char *)); 1711558Srgrimesint do_mount __P((struct exportlist *, struct grouplist *, int, 1729336Sdfr struct ucred *, char *, int, struct statfs *)); 1731558Srgrimesint do_opt __P((char **, char **, struct exportlist *, struct grouplist *, 1741558Srgrimes int *, int *, struct ucred *)); 1751558Srgrimesstruct exportlist *ex_search __P((fsid_t *)); 1761558Srgrimesstruct exportlist *get_exp __P((void)); 1771558Srgrimesvoid free_dir __P((struct dirlist *)); 1781558Srgrimesvoid free_exp __P((struct exportlist *)); 1791558Srgrimesvoid free_grp __P((struct grouplist *)); 1801558Srgrimesvoid free_host __P((struct hostlist *)); 1811558Srgrimesvoid get_exportlist __P((void)); 1827401Swpaulint get_host __P((char *, struct grouplist *, struct grouplist *)); 1839336Sdfrint get_num __P((char *)); 1841558Srgrimesstruct hostlist *get_ht __P((void)); 1851558Srgrimesint get_line __P((void)); 1861558Srgrimesvoid get_mountlist __P((void)); 1871558Srgrimesint get_net __P((char *, struct netmsk *, int)); 1881558Srgrimesvoid getexp_err __P((struct exportlist *, struct grouplist *)); 1891558Srgrimesstruct grouplist *get_grp __P((void)); 1901558Srgrimesvoid hang_dirp __P((struct dirlist *, struct grouplist *, 1911558Srgrimes struct exportlist *, int)); 1921558Srgrimesvoid mntsrv __P((struct svc_req *, SVCXPRT *)); 1931558Srgrimesvoid nextfield __P((char **, char **)); 1941558Srgrimesvoid out_of_mem __P((void)); 1951558Srgrimesvoid parsecred __P((char *, struct ucred *)); 1961558Srgrimesint put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *)); 1971558Srgrimesint scan_tree __P((struct dirlist *, u_long)); 1981558Srgrimesvoid send_umntall __P((void)); 1991558Srgrimesint umntall_each __P((caddr_t, struct sockaddr_in *)); 2001558Srgrimesint xdr_dir __P((XDR *, char *)); 2011558Srgrimesint xdr_explist __P((XDR *, caddr_t)); 2029336Sdfrint xdr_fhs __P((XDR *, caddr_t)); 2031558Srgrimesint xdr_mlist __P((XDR *, caddr_t)); 2041558Srgrimes 2051558Srgrimes/* C library */ 2061558Srgrimesint getnetgrent(); 2071558Srgrimesvoid endnetgrent(); 2081558Srgrimesvoid setnetgrent(); 2091558Srgrimes 2101558Srgrimes#ifdef ISO 2111558Srgrimesstruct iso_addr *iso_addr(); 2121558Srgrimes#endif 2131558Srgrimes 2141558Srgrimesstruct exportlist *exphead; 2151558Srgrimesstruct mountlist *mlhead; 2161558Srgrimesstruct grouplist *grphead; 2171558Srgrimeschar exname[MAXPATHLEN]; 2181558Srgrimesstruct ucred def_anon = { 2191558Srgrimes 1, 2201558Srgrimes (uid_t) -2, 2211558Srgrimes 1, 2221558Srgrimes { (gid_t) -2 } 2231558Srgrimes}; 22425087Sdfrint force_v2 = 0; 2259336Sdfrint resvport_only = 1; 2269336Sdfrint dir_only = 1; 2271558Srgrimesint opt_flags; 2281558Srgrimes/* Bits for above */ 2291558Srgrimes#define OP_MAPROOT 0x01 2301558Srgrimes#define OP_MAPALL 0x02 2311558Srgrimes#define OP_KERB 0x04 2321558Srgrimes#define OP_MASK 0x08 2331558Srgrimes#define OP_NET 0x10 2341558Srgrimes#define OP_ISO 0x20 2351558Srgrimes#define OP_ALLDIRS 0x40 2361558Srgrimes 2371558Srgrimes#ifdef DEBUG 2381558Srgrimesint debug = 1; 2391558Srgrimesvoid SYSLOG __P((int, const char *, ...)); 2401558Srgrimes#define syslog SYSLOG 2411558Srgrimes#else 2421558Srgrimesint debug = 0; 2431558Srgrimes#endif 2441558Srgrimes 2451558Srgrimes/* 2461558Srgrimes * Mountd server for NFS mount protocol as described in: 2471558Srgrimes * NFS: Network File System Protocol Specification, RFC1094, Appendix A 2481558Srgrimes * The optional arguments are the exports file name 2491558Srgrimes * default: _PATH_EXPORTS 2501558Srgrimes * and "-n" to allow nonroot mount. 2511558Srgrimes */ 2521558Srgrimesint 2531558Srgrimesmain(argc, argv) 2541558Srgrimes int argc; 2551558Srgrimes char **argv; 2561558Srgrimes{ 2579202Srgrimes SVCXPRT *udptransp, *tcptransp; 2581558Srgrimes int c; 25924489Sbde int mib[3]; 2609336Sdfr#ifdef __FreeBSD__ 26123681Speter struct vfsconf vfc; 26223681Speter int error; 2631558Srgrimes 26423681Speter error = getvfsbyname("nfs", &vfc); 26523681Speter if (error && vfsisloadable("nfs")) { 2662999Swollman if(vfsload("nfs")) 2672999Swollman err(1, "vfsload(nfs)"); 2682999Swollman endvfsent(); /* flush cache */ 26923681Speter error = getvfsbyname("nfs", &vfc); 2702999Swollman } 27123681Speter if (error) 2722999Swollman errx(1, "NFS support is not available in the running kernel"); 2739336Sdfr#endif /* __FreeBSD__ */ 2742999Swollman 27525087Sdfr while ((c = getopt(argc, argv, "2dnr")) != -1) 2761558Srgrimes switch (c) { 27725087Sdfr case '2': 27825087Sdfr force_v2 = 1; 27925087Sdfr break; 2809336Sdfr case 'n': 2819336Sdfr resvport_only = 0; 2829336Sdfr break; 2839336Sdfr case 'r': 2849336Sdfr dir_only = 0; 2859336Sdfr break; 2868688Sphk case 'd': 2878688Sphk debug = debug ? 0 : 1; 2888688Sphk break; 2891558Srgrimes default: 29023681Speter fprintf(stderr, "Usage: mountd [-d] [-r] [-n] [export_file]\n"); 2911558Srgrimes exit(1); 2921558Srgrimes }; 2931558Srgrimes argc -= optind; 2941558Srgrimes argv += optind; 2951558Srgrimes grphead = (struct grouplist *)NULL; 2961558Srgrimes exphead = (struct exportlist *)NULL; 2971558Srgrimes mlhead = (struct mountlist *)NULL; 2981558Srgrimes if (argc == 1) { 2991558Srgrimes strncpy(exname, *argv, MAXPATHLEN-1); 3001558Srgrimes exname[MAXPATHLEN-1] = '\0'; 3011558Srgrimes } else 3021558Srgrimes strcpy(exname, _PATH_EXPORTS); 3031558Srgrimes openlog("mountd", LOG_PID, LOG_DAEMON); 3041558Srgrimes if (debug) 3051558Srgrimes fprintf(stderr,"Getting export list.\n"); 3061558Srgrimes get_exportlist(); 3071558Srgrimes if (debug) 3081558Srgrimes fprintf(stderr,"Getting mount list.\n"); 3091558Srgrimes get_mountlist(); 3101558Srgrimes if (debug) 3111558Srgrimes fprintf(stderr,"Here we go.\n"); 3121558Srgrimes if (debug == 0) { 3131558Srgrimes daemon(0, 0); 3141558Srgrimes signal(SIGINT, SIG_IGN); 3151558Srgrimes signal(SIGQUIT, SIG_IGN); 3161558Srgrimes } 3171558Srgrimes signal(SIGHUP, (void (*) __P((int))) get_exportlist); 3181558Srgrimes signal(SIGTERM, (void (*) __P((int))) send_umntall); 3191558Srgrimes { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); 3201558Srgrimes if (pidfile != NULL) { 3211558Srgrimes fprintf(pidfile, "%d\n", getpid()); 3221558Srgrimes fclose(pidfile); 3231558Srgrimes } 3241558Srgrimes } 32524330Sguido 32624759Sguido if (!resvport_only) { 32724759Sguido mib[0] = CTL_VFS; 32824759Sguido mib[1] = MOUNT_NFS; 32924759Sguido mib[2] = NFS_NFSPRIVPORT; 33024759Sguido if (sysctl(mib, 3, NULL, NULL, &resvport_only, 33124759Sguido sizeof(resvport_only)) != 0 && errno != ENOENT) { 33224759Sguido syslog(LOG_ERR, "sysctl: %m"); 33324759Sguido exit(1); 33424759Sguido } 33524330Sguido } 33624330Sguido 3379202Srgrimes if ((udptransp = svcudp_create(RPC_ANYSOCK)) == NULL || 3389202Srgrimes (tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0)) == NULL) { 3391558Srgrimes syslog(LOG_ERR, "Can't create socket"); 3401558Srgrimes exit(1); 3411558Srgrimes } 3429336Sdfr pmap_unset(RPCPROG_MNT, 1); 3439336Sdfr pmap_unset(RPCPROG_MNT, 3); 34425087Sdfr if (!force_v2) 34525087Sdfr if (!svc_register(udptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_UDP) || 34625087Sdfr !svc_register(tcptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_TCP)) { 34725087Sdfr syslog(LOG_ERR, "Can't register mount"); 34825087Sdfr exit(1); 34925087Sdfr } 3509336Sdfr if (!svc_register(udptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_UDP) || 35125087Sdfr !svc_register(tcptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_TCP)) { 3521558Srgrimes syslog(LOG_ERR, "Can't register mount"); 3531558Srgrimes exit(1); 3541558Srgrimes } 3551558Srgrimes svc_run(); 3561558Srgrimes syslog(LOG_ERR, "Mountd died"); 3571558Srgrimes exit(1); 3581558Srgrimes} 3591558Srgrimes 3601558Srgrimes/* 3611558Srgrimes * The mount rpc service 3621558Srgrimes */ 3631558Srgrimesvoid 3641558Srgrimesmntsrv(rqstp, transp) 3651558Srgrimes struct svc_req *rqstp; 3661558Srgrimes SVCXPRT *transp; 3671558Srgrimes{ 3681558Srgrimes struct exportlist *ep; 3691558Srgrimes struct dirlist *dp; 3709336Sdfr struct fhreturn fhr; 3711558Srgrimes struct stat stb; 3721558Srgrimes struct statfs fsb; 3731558Srgrimes struct hostent *hp; 3741558Srgrimes u_long saddr; 3759336Sdfr u_short sport; 37623681Speter char rpcpath[RPCMNT_PATHLEN + 1], dirpath[MAXPATHLEN]; 37728911Sguido int bad = 0, defset, hostset; 3789336Sdfr sigset_t sighup_mask; 3791558Srgrimes 3809336Sdfr sigemptyset(&sighup_mask); 3819336Sdfr sigaddset(&sighup_mask, SIGHUP); 3821558Srgrimes saddr = transp->xp_raddr.sin_addr.s_addr; 3839336Sdfr sport = ntohs(transp->xp_raddr.sin_port); 3841558Srgrimes hp = (struct hostent *)NULL; 3851558Srgrimes switch (rqstp->rq_proc) { 3861558Srgrimes case NULLPROC: 3871558Srgrimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 3881558Srgrimes syslog(LOG_ERR, "Can't send reply"); 3891558Srgrimes return; 3901558Srgrimes case RPCMNT_MOUNT: 3919336Sdfr if (sport >= IPPORT_RESERVED && resvport_only) { 3921558Srgrimes svcerr_weakauth(transp); 3931558Srgrimes return; 3941558Srgrimes } 3951558Srgrimes if (!svc_getargs(transp, xdr_dir, rpcpath)) { 3961558Srgrimes svcerr_decode(transp); 3971558Srgrimes return; 3981558Srgrimes } 3991558Srgrimes 4001558Srgrimes /* 4011558Srgrimes * Get the real pathname and make sure it is a directory 4029336Sdfr * or a regular file if the -r option was specified 4039336Sdfr * and it exists. 4041558Srgrimes */ 4051558Srgrimes if (realpath(rpcpath, dirpath) == 0 || 4061558Srgrimes stat(dirpath, &stb) < 0 || 4079336Sdfr (!S_ISDIR(stb.st_mode) && 4089336Sdfr (dir_only || !S_ISREG(stb.st_mode))) || 4091558Srgrimes statfs(dirpath, &fsb) < 0) { 4101558Srgrimes chdir("/"); /* Just in case realpath doesn't */ 4111558Srgrimes if (debug) 4121558Srgrimes fprintf(stderr, "stat failed on %s\n", dirpath); 41328911Sguido bad = ENOENT; /* We will send error reply later */ 4141558Srgrimes } 4151558Srgrimes 4161558Srgrimes /* Check in the exports list */ 4179336Sdfr sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 4181558Srgrimes ep = ex_search(&fsb.f_fsid); 4199336Sdfr hostset = defset = 0; 4209336Sdfr if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) || 4211558Srgrimes ((dp = dirp_search(ep->ex_dirl, dirpath)) && 4229336Sdfr chk_host(dp, saddr, &defset, &hostset)) || 4231558Srgrimes (defset && scan_tree(ep->ex_defdir, saddr) == 0 && 4241558Srgrimes scan_tree(ep->ex_dirl, saddr) == 0))) { 42528911Sguido if (bad) { 42628911Sguido if (!svc_sendreply(transp, xdr_long, 42728911Sguido (caddr_t)&bad)) 42828911Sguido syslog(LOG_ERR, "Can't send reply"); 42928911Sguido sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 43028911Sguido return; 43128911Sguido } 4329336Sdfr if (hostset & DP_HOSTSET) 4339336Sdfr fhr.fhr_flag = hostset; 4349336Sdfr else 4359336Sdfr fhr.fhr_flag = defset; 4369336Sdfr fhr.fhr_vers = rqstp->rq_vers; 4371558Srgrimes /* Get the file handle */ 43823681Speter memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t)); 4399336Sdfr if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) { 4401558Srgrimes bad = errno; 4411558Srgrimes syslog(LOG_ERR, "Can't get fh for %s", dirpath); 4421558Srgrimes if (!svc_sendreply(transp, xdr_long, 4431558Srgrimes (caddr_t)&bad)) 4441558Srgrimes syslog(LOG_ERR, "Can't send reply"); 4459336Sdfr sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 4461558Srgrimes return; 4471558Srgrimes } 4489336Sdfr if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr)) 4491558Srgrimes syslog(LOG_ERR, "Can't send reply"); 4501558Srgrimes if (hp == NULL) 4511558Srgrimes hp = gethostbyaddr((caddr_t)&saddr, 4521558Srgrimes sizeof(saddr), AF_INET); 4531558Srgrimes if (hp) 4541558Srgrimes add_mlist(hp->h_name, dirpath); 4551558Srgrimes else 4561558Srgrimes add_mlist(inet_ntoa(transp->xp_raddr.sin_addr), 4571558Srgrimes dirpath); 4581558Srgrimes if (debug) 4591558Srgrimes fprintf(stderr,"Mount successfull.\n"); 46028911Sguido } else 4611558Srgrimes bad = EACCES; 46228911Sguido 46328911Sguido if (bad && !svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 46428911Sguido syslog(LOG_ERR, "Can't send reply"); 4659336Sdfr sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 4661558Srgrimes return; 4671558Srgrimes case RPCMNT_DUMP: 4681558Srgrimes if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL)) 4691558Srgrimes syslog(LOG_ERR, "Can't send reply"); 4701558Srgrimes return; 4711558Srgrimes case RPCMNT_UMOUNT: 4729336Sdfr if (sport >= IPPORT_RESERVED && resvport_only) { 4731558Srgrimes svcerr_weakauth(transp); 4741558Srgrimes return; 4751558Srgrimes } 4761558Srgrimes if (!svc_getargs(transp, xdr_dir, dirpath)) { 4771558Srgrimes svcerr_decode(transp); 4781558Srgrimes return; 4791558Srgrimes } 4801558Srgrimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 4811558Srgrimes syslog(LOG_ERR, "Can't send reply"); 4821558Srgrimes hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 4831558Srgrimes if (hp) 4841558Srgrimes del_mlist(hp->h_name, dirpath); 4851558Srgrimes del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath); 4861558Srgrimes return; 4871558Srgrimes case RPCMNT_UMNTALL: 4889336Sdfr if (sport >= IPPORT_RESERVED && resvport_only) { 4891558Srgrimes svcerr_weakauth(transp); 4901558Srgrimes return; 4911558Srgrimes } 4921558Srgrimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 4931558Srgrimes syslog(LOG_ERR, "Can't send reply"); 4941558Srgrimes hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 4951558Srgrimes if (hp) 4961558Srgrimes del_mlist(hp->h_name, (char *)NULL); 4971558Srgrimes del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), (char *)NULL); 4981558Srgrimes return; 4991558Srgrimes case RPCMNT_EXPORT: 5001558Srgrimes if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL)) 5011558Srgrimes syslog(LOG_ERR, "Can't send reply"); 5021558Srgrimes return; 5031558Srgrimes default: 5041558Srgrimes svcerr_noproc(transp); 5051558Srgrimes return; 5061558Srgrimes } 5071558Srgrimes} 5081558Srgrimes 5091558Srgrimes/* 5101558Srgrimes * Xdr conversion for a dirpath string 5111558Srgrimes */ 5121558Srgrimesint 5131558Srgrimesxdr_dir(xdrsp, dirp) 5141558Srgrimes XDR *xdrsp; 5151558Srgrimes char *dirp; 5161558Srgrimes{ 5171558Srgrimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 5181558Srgrimes} 5191558Srgrimes 5201558Srgrimes/* 5219336Sdfr * Xdr routine to generate file handle reply 5221558Srgrimes */ 5231558Srgrimesint 5249336Sdfrxdr_fhs(xdrsp, cp) 5251558Srgrimes XDR *xdrsp; 5269336Sdfr caddr_t cp; 5271558Srgrimes{ 5289336Sdfr register struct fhreturn *fhrp = (struct fhreturn *)cp; 5299336Sdfr u_long ok = 0, len, auth; 5301558Srgrimes 5311558Srgrimes if (!xdr_long(xdrsp, &ok)) 5321558Srgrimes return (0); 5339336Sdfr switch (fhrp->fhr_vers) { 5349336Sdfr case 1: 5359336Sdfr return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH)); 5369336Sdfr case 3: 5379336Sdfr len = NFSX_V3FH; 5389336Sdfr if (!xdr_long(xdrsp, &len)) 5399336Sdfr return (0); 5409336Sdfr if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) 5419336Sdfr return (0); 5429336Sdfr if (fhrp->fhr_flag & DP_KERB) 5439336Sdfr auth = RPCAUTH_KERB4; 5449336Sdfr else 5459336Sdfr auth = RPCAUTH_UNIX; 5469336Sdfr len = 1; 5479336Sdfr if (!xdr_long(xdrsp, &len)) 5489336Sdfr return (0); 5499336Sdfr return (xdr_long(xdrsp, &auth)); 5509336Sdfr }; 5519336Sdfr return (0); 5521558Srgrimes} 5531558Srgrimes 5541558Srgrimesint 5551558Srgrimesxdr_mlist(xdrsp, cp) 5561558Srgrimes XDR *xdrsp; 5571558Srgrimes caddr_t cp; 5581558Srgrimes{ 5591558Srgrimes struct mountlist *mlp; 5601558Srgrimes int true = 1; 5611558Srgrimes int false = 0; 5621558Srgrimes char *strp; 5631558Srgrimes 5641558Srgrimes mlp = mlhead; 5651558Srgrimes while (mlp) { 5661558Srgrimes if (!xdr_bool(xdrsp, &true)) 5671558Srgrimes return (0); 5681558Srgrimes strp = &mlp->ml_host[0]; 5691558Srgrimes if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 5701558Srgrimes return (0); 5711558Srgrimes strp = &mlp->ml_dirp[0]; 5721558Srgrimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 5731558Srgrimes return (0); 5741558Srgrimes mlp = mlp->ml_next; 5751558Srgrimes } 5761558Srgrimes if (!xdr_bool(xdrsp, &false)) 5771558Srgrimes return (0); 5781558Srgrimes return (1); 5791558Srgrimes} 5801558Srgrimes 5811558Srgrimes/* 5821558Srgrimes * Xdr conversion for export list 5831558Srgrimes */ 5841558Srgrimesint 5851558Srgrimesxdr_explist(xdrsp, cp) 5861558Srgrimes XDR *xdrsp; 5871558Srgrimes caddr_t cp; 5881558Srgrimes{ 5891558Srgrimes struct exportlist *ep; 5901558Srgrimes int false = 0; 5919336Sdfr int putdef; 5929336Sdfr sigset_t sighup_mask; 5931558Srgrimes 5949336Sdfr sigemptyset(&sighup_mask); 5959336Sdfr sigaddset(&sighup_mask, SIGHUP); 5969336Sdfr sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 5971558Srgrimes ep = exphead; 5981558Srgrimes while (ep) { 5991558Srgrimes putdef = 0; 6001558Srgrimes if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, &putdef)) 6011558Srgrimes goto errout; 6021558Srgrimes if (ep->ex_defdir && putdef == 0 && 6031558Srgrimes put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL, 6041558Srgrimes &putdef)) 6051558Srgrimes goto errout; 6061558Srgrimes ep = ep->ex_next; 6071558Srgrimes } 6089336Sdfr sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6091558Srgrimes if (!xdr_bool(xdrsp, &false)) 6101558Srgrimes return (0); 6111558Srgrimes return (1); 6121558Srgrimeserrout: 6139336Sdfr sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6141558Srgrimes return (0); 6151558Srgrimes} 6161558Srgrimes 6171558Srgrimes/* 6181558Srgrimes * Called from xdr_explist() to traverse the tree and export the 6191558Srgrimes * directory paths. 6201558Srgrimes */ 6211558Srgrimesint 6221558Srgrimesput_exlist(dp, xdrsp, adp, putdefp) 6231558Srgrimes struct dirlist *dp; 6241558Srgrimes XDR *xdrsp; 6251558Srgrimes struct dirlist *adp; 6261558Srgrimes int *putdefp; 6271558Srgrimes{ 6281558Srgrimes struct grouplist *grp; 6291558Srgrimes struct hostlist *hp; 6301558Srgrimes int true = 1; 6311558Srgrimes int false = 0; 6321558Srgrimes int gotalldir = 0; 6331558Srgrimes char *strp; 6341558Srgrimes 6351558Srgrimes if (dp) { 6361558Srgrimes if (put_exlist(dp->dp_left, xdrsp, adp, putdefp)) 6371558Srgrimes return (1); 6381558Srgrimes if (!xdr_bool(xdrsp, &true)) 6391558Srgrimes return (1); 6401558Srgrimes strp = dp->dp_dirp; 6411558Srgrimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 6421558Srgrimes return (1); 6431558Srgrimes if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) { 6441558Srgrimes gotalldir = 1; 6451558Srgrimes *putdefp = 1; 6461558Srgrimes } 6471558Srgrimes if ((dp->dp_flag & DP_DEFSET) == 0 && 6481558Srgrimes (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) { 6491558Srgrimes hp = dp->dp_hosts; 6501558Srgrimes while (hp) { 6511558Srgrimes grp = hp->ht_grp; 6521558Srgrimes if (grp->gr_type == GT_HOST) { 6531558Srgrimes if (!xdr_bool(xdrsp, &true)) 6541558Srgrimes return (1); 6551558Srgrimes strp = grp->gr_ptr.gt_hostent->h_name; 6568871Srgrimes if (!xdr_string(xdrsp, &strp, 6571558Srgrimes RPCMNT_NAMELEN)) 6581558Srgrimes return (1); 6591558Srgrimes } else if (grp->gr_type == GT_NET) { 6601558Srgrimes if (!xdr_bool(xdrsp, &true)) 6611558Srgrimes return (1); 6621558Srgrimes strp = grp->gr_ptr.gt_net.nt_name; 6638871Srgrimes if (!xdr_string(xdrsp, &strp, 6641558Srgrimes RPCMNT_NAMELEN)) 6651558Srgrimes return (1); 6661558Srgrimes } 6671558Srgrimes hp = hp->ht_next; 6681558Srgrimes if (gotalldir && hp == (struct hostlist *)NULL) { 6691558Srgrimes hp = adp->dp_hosts; 6701558Srgrimes gotalldir = 0; 6711558Srgrimes } 6721558Srgrimes } 6731558Srgrimes } 6741558Srgrimes if (!xdr_bool(xdrsp, &false)) 6751558Srgrimes return (1); 6761558Srgrimes if (put_exlist(dp->dp_right, xdrsp, adp, putdefp)) 6771558Srgrimes return (1); 6781558Srgrimes } 6791558Srgrimes return (0); 6801558Srgrimes} 6811558Srgrimes 6821558Srgrimes#define LINESIZ 10240 6831558Srgrimeschar line[LINESIZ]; 6841558SrgrimesFILE *exp_file; 6851558Srgrimes 6861558Srgrimes/* 6871558Srgrimes * Get the export list 6881558Srgrimes */ 6891558Srgrimesvoid 6901558Srgrimesget_exportlist() 6911558Srgrimes{ 6921558Srgrimes struct exportlist *ep, *ep2; 6931558Srgrimes struct grouplist *grp, *tgrp; 6941558Srgrimes struct exportlist **epp; 6951558Srgrimes struct dirlist *dirhead; 6961558Srgrimes struct statfs fsb, *fsp; 6971558Srgrimes struct hostent *hpe; 6981558Srgrimes struct ucred anon; 6991558Srgrimes char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; 7001558Srgrimes int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp; 7011558Srgrimes 7021558Srgrimes /* 7031558Srgrimes * First, get rid of the old list 7041558Srgrimes */ 7051558Srgrimes ep = exphead; 7061558Srgrimes while (ep) { 7071558Srgrimes ep2 = ep; 7081558Srgrimes ep = ep->ex_next; 7091558Srgrimes free_exp(ep2); 7101558Srgrimes } 7111558Srgrimes exphead = (struct exportlist *)NULL; 7121558Srgrimes 7131558Srgrimes grp = grphead; 7141558Srgrimes while (grp) { 7151558Srgrimes tgrp = grp; 7161558Srgrimes grp = grp->gr_next; 7171558Srgrimes free_grp(tgrp); 7181558Srgrimes } 7191558Srgrimes grphead = (struct grouplist *)NULL; 7201558Srgrimes 7211558Srgrimes /* 7221558Srgrimes * And delete exports that are in the kernel for all local 7231558Srgrimes * file systems. 7241558Srgrimes * XXX: Should know how to handle all local exportable file systems 72523681Speter * instead of just "ufs". 7261558Srgrimes */ 7271558Srgrimes num = getmntinfo(&fsp, MNT_NOWAIT); 7281558Srgrimes for (i = 0; i < num; i++) { 7291558Srgrimes union { 7301558Srgrimes struct ufs_args ua; 7311558Srgrimes struct iso_args ia; 7321558Srgrimes struct mfs_args ma; 7339336Sdfr struct msdosfs_args da; 7341558Srgrimes } targs; 7351558Srgrimes 73623681Speter if (!strcmp(fsp->f_fstypename, "mfs") || 73723681Speter !strcmp(fsp->f_fstypename, "ufs") || 73823681Speter !strcmp(fsp->f_fstypename, "msdos") || 73923681Speter !strcmp(fsp->f_fstypename, "cd9660")) { 7409336Sdfr targs.ua.fspec = NULL; 7419336Sdfr targs.ua.export.ex_flags = MNT_DELEXPORT; 7429336Sdfr if (mount(fsp->f_fstypename, fsp->f_mntonname, 7431558Srgrimes fsp->f_flags | MNT_UPDATE, 7441558Srgrimes (caddr_t)&targs) < 0) 7451558Srgrimes syslog(LOG_ERR, "Can't delete exports for %s", 7461558Srgrimes fsp->f_mntonname); 7471558Srgrimes } 7481558Srgrimes fsp++; 7491558Srgrimes } 7501558Srgrimes 7511558Srgrimes /* 7521558Srgrimes * Read in the exports file and build the list, calling 7531558Srgrimes * mount() as we go along to push the export rules into the kernel. 7541558Srgrimes */ 7551558Srgrimes if ((exp_file = fopen(exname, "r")) == NULL) { 7561558Srgrimes syslog(LOG_ERR, "Can't open %s", exname); 7571558Srgrimes exit(2); 7581558Srgrimes } 7591558Srgrimes dirhead = (struct dirlist *)NULL; 7601558Srgrimes while (get_line()) { 7611558Srgrimes if (debug) 7621558Srgrimes fprintf(stderr,"Got line %s\n",line); 7631558Srgrimes cp = line; 7641558Srgrimes nextfield(&cp, &endcp); 7651558Srgrimes if (*cp == '#') 7661558Srgrimes goto nextline; 7671558Srgrimes 7681558Srgrimes /* 7691558Srgrimes * Set defaults. 7701558Srgrimes */ 7711558Srgrimes has_host = FALSE; 7721558Srgrimes anon = def_anon; 7731558Srgrimes exflags = MNT_EXPORTED; 7741558Srgrimes got_nondir = 0; 7751558Srgrimes opt_flags = 0; 7761558Srgrimes ep = (struct exportlist *)NULL; 7771558Srgrimes 7781558Srgrimes /* 7791558Srgrimes * Create new exports list entry 7801558Srgrimes */ 7811558Srgrimes len = endcp-cp; 7821558Srgrimes tgrp = grp = get_grp(); 7831558Srgrimes while (len > 0) { 7841558Srgrimes if (len > RPCMNT_NAMELEN) { 7851558Srgrimes getexp_err(ep, tgrp); 7861558Srgrimes goto nextline; 7871558Srgrimes } 7881558Srgrimes if (*cp == '-') { 7891558Srgrimes if (ep == (struct exportlist *)NULL) { 7901558Srgrimes getexp_err(ep, tgrp); 7911558Srgrimes goto nextline; 7921558Srgrimes } 7931558Srgrimes if (debug) 7941558Srgrimes fprintf(stderr, "doing opt %s\n", cp); 7951558Srgrimes got_nondir = 1; 7961558Srgrimes if (do_opt(&cp, &endcp, ep, grp, &has_host, 7971558Srgrimes &exflags, &anon)) { 7981558Srgrimes getexp_err(ep, tgrp); 7991558Srgrimes goto nextline; 8001558Srgrimes } 8011558Srgrimes } else if (*cp == '/') { 8021558Srgrimes savedc = *endcp; 8031558Srgrimes *endcp = '\0'; 8041558Srgrimes if (check_dirpath(cp) && 8051558Srgrimes statfs(cp, &fsb) >= 0) { 8061558Srgrimes if (got_nondir) { 8071558Srgrimes syslog(LOG_ERR, "Dirs must be first"); 8081558Srgrimes getexp_err(ep, tgrp); 8091558Srgrimes goto nextline; 8101558Srgrimes } 8111558Srgrimes if (ep) { 8121558Srgrimes if (ep->ex_fs.val[0] != fsb.f_fsid.val[0] || 8131558Srgrimes ep->ex_fs.val[1] != fsb.f_fsid.val[1]) { 8141558Srgrimes getexp_err(ep, tgrp); 8151558Srgrimes goto nextline; 8161558Srgrimes } 8171558Srgrimes } else { 8181558Srgrimes /* 8191558Srgrimes * See if this directory is already 8201558Srgrimes * in the list. 8211558Srgrimes */ 8221558Srgrimes ep = ex_search(&fsb.f_fsid); 8231558Srgrimes if (ep == (struct exportlist *)NULL) { 8241558Srgrimes ep = get_exp(); 8251558Srgrimes ep->ex_fs = fsb.f_fsid; 8261558Srgrimes ep->ex_fsdir = (char *) 8271558Srgrimes malloc(strlen(fsb.f_mntonname) + 1); 8281558Srgrimes if (ep->ex_fsdir) 8291558Srgrimes strcpy(ep->ex_fsdir, 8301558Srgrimes fsb.f_mntonname); 8311558Srgrimes else 8321558Srgrimes out_of_mem(); 8331558Srgrimes if (debug) 8341558Srgrimes fprintf(stderr, 8351558Srgrimes "Making new ep fs=0x%x,0x%x\n", 8361558Srgrimes fsb.f_fsid.val[0], 8371558Srgrimes fsb.f_fsid.val[1]); 8381558Srgrimes } else if (debug) 8391558Srgrimes fprintf(stderr, 8401558Srgrimes "Found ep fs=0x%x,0x%x\n", 8411558Srgrimes fsb.f_fsid.val[0], 8421558Srgrimes fsb.f_fsid.val[1]); 8431558Srgrimes } 8441558Srgrimes 8451558Srgrimes /* 8461558Srgrimes * Add dirpath to export mount point. 8471558Srgrimes */ 8481558Srgrimes dirp = add_expdir(&dirhead, cp, len); 8491558Srgrimes dirplen = len; 8501558Srgrimes } else { 8511558Srgrimes getexp_err(ep, tgrp); 8521558Srgrimes goto nextline; 8531558Srgrimes } 8541558Srgrimes *endcp = savedc; 8551558Srgrimes } else { 8561558Srgrimes savedc = *endcp; 8571558Srgrimes *endcp = '\0'; 8581558Srgrimes got_nondir = 1; 8591558Srgrimes if (ep == (struct exportlist *)NULL) { 8601558Srgrimes getexp_err(ep, tgrp); 8611558Srgrimes goto nextline; 8621558Srgrimes } 8631558Srgrimes 8641558Srgrimes /* 8651558Srgrimes * Get the host or netgroup. 8661558Srgrimes */ 8671558Srgrimes setnetgrent(cp); 8681558Srgrimes netgrp = getnetgrent(&hst, &usr, &dom); 8691558Srgrimes do { 8701558Srgrimes if (has_host) { 8711558Srgrimes grp->gr_next = get_grp(); 8721558Srgrimes grp = grp->gr_next; 8731558Srgrimes } 8741558Srgrimes if (netgrp) { 8757401Swpaul if (get_host(hst, grp, tgrp)) { 87629317Sjlemon syslog(LOG_ERR, "Bad host %s in netgroup %s, skipping", hst, cp); 87729317Sjlemon grp->gr_type = GT_IGNORE; 8781558Srgrimes } 8797401Swpaul } else if (get_host(cp, grp, tgrp)) { 88029317Sjlemon syslog(LOG_ERR, "Bad host %s, skipping", cp); 88129317Sjlemon grp->gr_type = GT_IGNORE; 8821558Srgrimes } 8831558Srgrimes has_host = TRUE; 8841558Srgrimes } while (netgrp && getnetgrent(&hst, &usr, &dom)); 8851558Srgrimes endnetgrent(); 8861558Srgrimes *endcp = savedc; 8871558Srgrimes } 8881558Srgrimes cp = endcp; 8891558Srgrimes nextfield(&cp, &endcp); 8901558Srgrimes len = endcp - cp; 8911558Srgrimes } 8921558Srgrimes if (check_options(dirhead)) { 8931558Srgrimes getexp_err(ep, tgrp); 8941558Srgrimes goto nextline; 8951558Srgrimes } 8961558Srgrimes if (!has_host) { 8971558Srgrimes grp->gr_type = GT_HOST; 8981558Srgrimes if (debug) 8991558Srgrimes fprintf(stderr,"Adding a default entry\n"); 9001558Srgrimes /* add a default group and make the grp list NULL */ 9011558Srgrimes hpe = (struct hostent *)malloc(sizeof(struct hostent)); 9021558Srgrimes if (hpe == (struct hostent *)NULL) 9031558Srgrimes out_of_mem(); 90412348Sjoerg hpe->h_name = strdup("Default"); 9051558Srgrimes hpe->h_addrtype = AF_INET; 9061558Srgrimes hpe->h_length = sizeof (u_long); 9071558Srgrimes hpe->h_addr_list = (char **)NULL; 9081558Srgrimes grp->gr_ptr.gt_hostent = hpe; 9091558Srgrimes 9101558Srgrimes /* 9111558Srgrimes * Don't allow a network export coincide with a list of 9121558Srgrimes * host(s) on the same line. 9131558Srgrimes */ 9141558Srgrimes } else if ((opt_flags & OP_NET) && tgrp->gr_next) { 9151558Srgrimes getexp_err(ep, tgrp); 9161558Srgrimes goto nextline; 91729317Sjlemon 91829317Sjlemon /* 91929317Sjlemon * If an export list was specified on this line, make sure 92029317Sjlemon * that we have at least one valid entry, otherwise skip it. 92129317Sjlemon */ 92229317Sjlemon } else { 92329317Sjlemon grp = tgrp; 92429317Sjlemon while (grp && grp->gr_type == GT_IGNORE) 92529317Sjlemon grp = grp->gr_next; 92629317Sjlemon if (! grp) { 92729317Sjlemon getexp_err(ep, tgrp); 92829317Sjlemon goto nextline; 92929317Sjlemon } 9301558Srgrimes } 9311558Srgrimes 9321558Srgrimes /* 9331558Srgrimes * Loop through hosts, pushing the exports into the kernel. 9341558Srgrimes * After loop, tgrp points to the start of the list and 9351558Srgrimes * grp points to the last entry in the list. 9361558Srgrimes */ 9371558Srgrimes grp = tgrp; 9381558Srgrimes do { 9391558Srgrimes if (do_mount(ep, grp, exflags, &anon, dirp, 9401558Srgrimes dirplen, &fsb)) { 9411558Srgrimes getexp_err(ep, tgrp); 9421558Srgrimes goto nextline; 9431558Srgrimes } 9441558Srgrimes } while (grp->gr_next && (grp = grp->gr_next)); 9451558Srgrimes 9461558Srgrimes /* 9471558Srgrimes * Success. Update the data structures. 9481558Srgrimes */ 9491558Srgrimes if (has_host) { 9509336Sdfr hang_dirp(dirhead, tgrp, ep, opt_flags); 9511558Srgrimes grp->gr_next = grphead; 9521558Srgrimes grphead = tgrp; 9531558Srgrimes } else { 9541558Srgrimes hang_dirp(dirhead, (struct grouplist *)NULL, ep, 9559336Sdfr opt_flags); 9561558Srgrimes free_grp(grp); 9571558Srgrimes } 9581558Srgrimes dirhead = (struct dirlist *)NULL; 9591558Srgrimes if ((ep->ex_flag & EX_LINKED) == 0) { 9601558Srgrimes ep2 = exphead; 9611558Srgrimes epp = &exphead; 9621558Srgrimes 9631558Srgrimes /* 9641558Srgrimes * Insert in the list in alphabetical order. 9651558Srgrimes */ 9661558Srgrimes while (ep2 && strcmp(ep2->ex_fsdir, ep->ex_fsdir) < 0) { 9671558Srgrimes epp = &ep2->ex_next; 9681558Srgrimes ep2 = ep2->ex_next; 9691558Srgrimes } 9701558Srgrimes if (ep2) 9711558Srgrimes ep->ex_next = ep2; 9721558Srgrimes *epp = ep; 9731558Srgrimes ep->ex_flag |= EX_LINKED; 9741558Srgrimes } 9751558Srgrimesnextline: 9761558Srgrimes if (dirhead) { 9771558Srgrimes free_dir(dirhead); 9781558Srgrimes dirhead = (struct dirlist *)NULL; 9791558Srgrimes } 9801558Srgrimes } 9811558Srgrimes fclose(exp_file); 9821558Srgrimes} 9831558Srgrimes 9841558Srgrimes/* 9851558Srgrimes * Allocate an export list element 9861558Srgrimes */ 9871558Srgrimesstruct exportlist * 9881558Srgrimesget_exp() 9891558Srgrimes{ 9901558Srgrimes struct exportlist *ep; 9911558Srgrimes 9921558Srgrimes ep = (struct exportlist *)malloc(sizeof (struct exportlist)); 9931558Srgrimes if (ep == (struct exportlist *)NULL) 9941558Srgrimes out_of_mem(); 99523681Speter memset(ep, 0, sizeof(struct exportlist)); 9961558Srgrimes return (ep); 9971558Srgrimes} 9981558Srgrimes 9991558Srgrimes/* 10001558Srgrimes * Allocate a group list element 10011558Srgrimes */ 10021558Srgrimesstruct grouplist * 10031558Srgrimesget_grp() 10041558Srgrimes{ 10051558Srgrimes struct grouplist *gp; 10061558Srgrimes 10071558Srgrimes gp = (struct grouplist *)malloc(sizeof (struct grouplist)); 10081558Srgrimes if (gp == (struct grouplist *)NULL) 10091558Srgrimes out_of_mem(); 101023681Speter memset(gp, 0, sizeof(struct grouplist)); 10111558Srgrimes return (gp); 10121558Srgrimes} 10131558Srgrimes 10141558Srgrimes/* 10151558Srgrimes * Clean up upon an error in get_exportlist(). 10161558Srgrimes */ 10171558Srgrimesvoid 10181558Srgrimesgetexp_err(ep, grp) 10191558Srgrimes struct exportlist *ep; 10201558Srgrimes struct grouplist *grp; 10211558Srgrimes{ 10221558Srgrimes struct grouplist *tgrp; 10231558Srgrimes 10241558Srgrimes syslog(LOG_ERR, "Bad exports list line %s", line); 10251558Srgrimes if (ep && (ep->ex_flag & EX_LINKED) == 0) 10261558Srgrimes free_exp(ep); 10271558Srgrimes while (grp) { 10281558Srgrimes tgrp = grp; 10291558Srgrimes grp = grp->gr_next; 10301558Srgrimes free_grp(tgrp); 10311558Srgrimes } 10321558Srgrimes} 10331558Srgrimes 10341558Srgrimes/* 10351558Srgrimes * Search the export list for a matching fs. 10361558Srgrimes */ 10371558Srgrimesstruct exportlist * 10381558Srgrimesex_search(fsid) 10391558Srgrimes fsid_t *fsid; 10401558Srgrimes{ 10411558Srgrimes struct exportlist *ep; 10421558Srgrimes 10431558Srgrimes ep = exphead; 10441558Srgrimes while (ep) { 10451558Srgrimes if (ep->ex_fs.val[0] == fsid->val[0] && 10461558Srgrimes ep->ex_fs.val[1] == fsid->val[1]) 10471558Srgrimes return (ep); 10481558Srgrimes ep = ep->ex_next; 10491558Srgrimes } 10501558Srgrimes return (ep); 10511558Srgrimes} 10521558Srgrimes 10531558Srgrimes/* 10541558Srgrimes * Add a directory path to the list. 10551558Srgrimes */ 10561558Srgrimeschar * 10571558Srgrimesadd_expdir(dpp, cp, len) 10581558Srgrimes struct dirlist **dpp; 10591558Srgrimes char *cp; 10601558Srgrimes int len; 10611558Srgrimes{ 10621558Srgrimes struct dirlist *dp; 10631558Srgrimes 10641558Srgrimes dp = (struct dirlist *)malloc(sizeof (struct dirlist) + len); 10651558Srgrimes dp->dp_left = *dpp; 10661558Srgrimes dp->dp_right = (struct dirlist *)NULL; 10671558Srgrimes dp->dp_flag = 0; 10681558Srgrimes dp->dp_hosts = (struct hostlist *)NULL; 10691558Srgrimes strcpy(dp->dp_dirp, cp); 10701558Srgrimes *dpp = dp; 10711558Srgrimes return (dp->dp_dirp); 10721558Srgrimes} 10731558Srgrimes 10741558Srgrimes/* 10751558Srgrimes * Hang the dir list element off the dirpath binary tree as required 10761558Srgrimes * and update the entry for host. 10771558Srgrimes */ 10781558Srgrimesvoid 10799336Sdfrhang_dirp(dp, grp, ep, flags) 10801558Srgrimes struct dirlist *dp; 10811558Srgrimes struct grouplist *grp; 10821558Srgrimes struct exportlist *ep; 10839336Sdfr int flags; 10841558Srgrimes{ 10851558Srgrimes struct hostlist *hp; 10861558Srgrimes struct dirlist *dp2; 10871558Srgrimes 10889336Sdfr if (flags & OP_ALLDIRS) { 10891558Srgrimes if (ep->ex_defdir) 10901558Srgrimes free((caddr_t)dp); 10911558Srgrimes else 10921558Srgrimes ep->ex_defdir = dp; 10939336Sdfr if (grp == (struct grouplist *)NULL) { 10941558Srgrimes ep->ex_defdir->dp_flag |= DP_DEFSET; 10959336Sdfr if (flags & OP_KERB) 10969336Sdfr ep->ex_defdir->dp_flag |= DP_KERB; 10979336Sdfr } else while (grp) { 10981558Srgrimes hp = get_ht(); 10999336Sdfr if (flags & OP_KERB) 11009336Sdfr hp->ht_flag |= DP_KERB; 11011558Srgrimes hp->ht_grp = grp; 11021558Srgrimes hp->ht_next = ep->ex_defdir->dp_hosts; 11031558Srgrimes ep->ex_defdir->dp_hosts = hp; 11041558Srgrimes grp = grp->gr_next; 11051558Srgrimes } 11061558Srgrimes } else { 11071558Srgrimes 11081558Srgrimes /* 11091558Srgrimes * Loop throught the directories adding them to the tree. 11101558Srgrimes */ 11111558Srgrimes while (dp) { 11121558Srgrimes dp2 = dp->dp_left; 11139336Sdfr add_dlist(&ep->ex_dirl, dp, grp, flags); 11141558Srgrimes dp = dp2; 11151558Srgrimes } 11161558Srgrimes } 11171558Srgrimes} 11181558Srgrimes 11191558Srgrimes/* 11201558Srgrimes * Traverse the binary tree either updating a node that is already there 11211558Srgrimes * for the new directory or adding the new node. 11221558Srgrimes */ 11231558Srgrimesvoid 11249336Sdfradd_dlist(dpp, newdp, grp, flags) 11251558Srgrimes struct dirlist **dpp; 11261558Srgrimes struct dirlist *newdp; 11271558Srgrimes struct grouplist *grp; 11289336Sdfr int flags; 11291558Srgrimes{ 11301558Srgrimes struct dirlist *dp; 11311558Srgrimes struct hostlist *hp; 11321558Srgrimes int cmp; 11331558Srgrimes 11341558Srgrimes dp = *dpp; 11351558Srgrimes if (dp) { 11361558Srgrimes cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); 11371558Srgrimes if (cmp > 0) { 11389336Sdfr add_dlist(&dp->dp_left, newdp, grp, flags); 11391558Srgrimes return; 11401558Srgrimes } else if (cmp < 0) { 11419336Sdfr add_dlist(&dp->dp_right, newdp, grp, flags); 11421558Srgrimes return; 11431558Srgrimes } else 11441558Srgrimes free((caddr_t)newdp); 11451558Srgrimes } else { 11461558Srgrimes dp = newdp; 11471558Srgrimes dp->dp_left = (struct dirlist *)NULL; 11481558Srgrimes *dpp = dp; 11491558Srgrimes } 11501558Srgrimes if (grp) { 11511558Srgrimes 11521558Srgrimes /* 11531558Srgrimes * Hang all of the host(s) off of the directory point. 11541558Srgrimes */ 11551558Srgrimes do { 11561558Srgrimes hp = get_ht(); 11579336Sdfr if (flags & OP_KERB) 11589336Sdfr hp->ht_flag |= DP_KERB; 11591558Srgrimes hp->ht_grp = grp; 11601558Srgrimes hp->ht_next = dp->dp_hosts; 11611558Srgrimes dp->dp_hosts = hp; 11621558Srgrimes grp = grp->gr_next; 11631558Srgrimes } while (grp); 11649336Sdfr } else { 11651558Srgrimes dp->dp_flag |= DP_DEFSET; 11669336Sdfr if (flags & OP_KERB) 11679336Sdfr dp->dp_flag |= DP_KERB; 11689336Sdfr } 11691558Srgrimes} 11701558Srgrimes 11711558Srgrimes/* 11721558Srgrimes * Search for a dirpath on the export point. 11731558Srgrimes */ 11741558Srgrimesstruct dirlist * 11751558Srgrimesdirp_search(dp, dirpath) 11761558Srgrimes struct dirlist *dp; 11771558Srgrimes char *dirpath; 11781558Srgrimes{ 11791558Srgrimes int cmp; 11801558Srgrimes 11811558Srgrimes if (dp) { 11821558Srgrimes cmp = strcmp(dp->dp_dirp, dirpath); 11831558Srgrimes if (cmp > 0) 11841558Srgrimes return (dirp_search(dp->dp_left, dirpath)); 11851558Srgrimes else if (cmp < 0) 11861558Srgrimes return (dirp_search(dp->dp_right, dirpath)); 11871558Srgrimes else 11881558Srgrimes return (dp); 11891558Srgrimes } 11901558Srgrimes return (dp); 11911558Srgrimes} 11921558Srgrimes 11931558Srgrimes/* 11941558Srgrimes * Scan for a host match in a directory tree. 11951558Srgrimes */ 11961558Srgrimesint 11979336Sdfrchk_host(dp, saddr, defsetp, hostsetp) 11981558Srgrimes struct dirlist *dp; 11991558Srgrimes u_long saddr; 12001558Srgrimes int *defsetp; 12019336Sdfr int *hostsetp; 12021558Srgrimes{ 12031558Srgrimes struct hostlist *hp; 12041558Srgrimes struct grouplist *grp; 12051558Srgrimes u_long **addrp; 12061558Srgrimes 12071558Srgrimes if (dp) { 12081558Srgrimes if (dp->dp_flag & DP_DEFSET) 12099336Sdfr *defsetp = dp->dp_flag; 12101558Srgrimes hp = dp->dp_hosts; 12111558Srgrimes while (hp) { 12121558Srgrimes grp = hp->ht_grp; 12131558Srgrimes switch (grp->gr_type) { 12141558Srgrimes case GT_HOST: 12151558Srgrimes addrp = (u_long **) 12161558Srgrimes grp->gr_ptr.gt_hostent->h_addr_list; 12171558Srgrimes while (*addrp) { 12189336Sdfr if (**addrp == saddr) { 12199336Sdfr *hostsetp = (hp->ht_flag | DP_HOSTSET); 12201558Srgrimes return (1); 12219336Sdfr } 12221558Srgrimes addrp++; 12231558Srgrimes } 12241558Srgrimes break; 12251558Srgrimes case GT_NET: 12261558Srgrimes if ((saddr & grp->gr_ptr.gt_net.nt_mask) == 12279336Sdfr grp->gr_ptr.gt_net.nt_net) { 12289336Sdfr *hostsetp = (hp->ht_flag | DP_HOSTSET); 12291558Srgrimes return (1); 12309336Sdfr } 12311558Srgrimes break; 12321558Srgrimes }; 12331558Srgrimes hp = hp->ht_next; 12341558Srgrimes } 12351558Srgrimes } 12361558Srgrimes return (0); 12371558Srgrimes} 12381558Srgrimes 12391558Srgrimes/* 12401558Srgrimes * Scan tree for a host that matches the address. 12411558Srgrimes */ 12421558Srgrimesint 12431558Srgrimesscan_tree(dp, saddr) 12441558Srgrimes struct dirlist *dp; 12451558Srgrimes u_long saddr; 12461558Srgrimes{ 12479336Sdfr int defset, hostset; 12481558Srgrimes 12491558Srgrimes if (dp) { 12501558Srgrimes if (scan_tree(dp->dp_left, saddr)) 12511558Srgrimes return (1); 12529336Sdfr if (chk_host(dp, saddr, &defset, &hostset)) 12531558Srgrimes return (1); 12541558Srgrimes if (scan_tree(dp->dp_right, saddr)) 12551558Srgrimes return (1); 12561558Srgrimes } 12571558Srgrimes return (0); 12581558Srgrimes} 12591558Srgrimes 12601558Srgrimes/* 12611558Srgrimes * Traverse the dirlist tree and free it up. 12621558Srgrimes */ 12631558Srgrimesvoid 12641558Srgrimesfree_dir(dp) 12651558Srgrimes struct dirlist *dp; 12661558Srgrimes{ 12671558Srgrimes 12681558Srgrimes if (dp) { 12691558Srgrimes free_dir(dp->dp_left); 12701558Srgrimes free_dir(dp->dp_right); 12711558Srgrimes free_host(dp->dp_hosts); 12721558Srgrimes free((caddr_t)dp); 12731558Srgrimes } 12741558Srgrimes} 12751558Srgrimes 12761558Srgrimes/* 12771558Srgrimes * Parse the option string and update fields. 12781558Srgrimes * Option arguments may either be -<option>=<value> or 12791558Srgrimes * -<option> <value> 12801558Srgrimes */ 12811558Srgrimesint 12821558Srgrimesdo_opt(cpp, endcpp, ep, grp, has_hostp, exflagsp, cr) 12831558Srgrimes char **cpp, **endcpp; 12841558Srgrimes struct exportlist *ep; 12851558Srgrimes struct grouplist *grp; 12861558Srgrimes int *has_hostp; 12871558Srgrimes int *exflagsp; 12881558Srgrimes struct ucred *cr; 12891558Srgrimes{ 12901558Srgrimes char *cpoptarg, *cpoptend; 12911558Srgrimes char *cp, *endcp, *cpopt, savedc, savedc2; 12921558Srgrimes int allflag, usedarg; 12931558Srgrimes 12941558Srgrimes cpopt = *cpp; 12951558Srgrimes cpopt++; 12961558Srgrimes cp = *endcpp; 12971558Srgrimes savedc = *cp; 12981558Srgrimes *cp = '\0'; 12991558Srgrimes while (cpopt && *cpopt) { 13001558Srgrimes allflag = 1; 13011558Srgrimes usedarg = -2; 130223681Speter if (cpoptend = strchr(cpopt, ',')) { 13031558Srgrimes *cpoptend++ = '\0'; 130423681Speter if (cpoptarg = strchr(cpopt, '=')) 13051558Srgrimes *cpoptarg++ = '\0'; 13061558Srgrimes } else { 130723681Speter if (cpoptarg = strchr(cpopt, '=')) 13081558Srgrimes *cpoptarg++ = '\0'; 13091558Srgrimes else { 13101558Srgrimes *cp = savedc; 13111558Srgrimes nextfield(&cp, &endcp); 13121558Srgrimes **endcpp = '\0'; 13131558Srgrimes if (endcp > cp && *cp != '-') { 13141558Srgrimes cpoptarg = cp; 13151558Srgrimes savedc2 = *endcp; 13161558Srgrimes *endcp = '\0'; 13171558Srgrimes usedarg = 0; 13181558Srgrimes } 13191558Srgrimes } 13201558Srgrimes } 13211558Srgrimes if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 13221558Srgrimes *exflagsp |= MNT_EXRDONLY; 13231558Srgrimes } else if (cpoptarg && (!strcmp(cpopt, "maproot") || 13241558Srgrimes !(allflag = strcmp(cpopt, "mapall")) || 13251558Srgrimes !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) { 13261558Srgrimes usedarg++; 13271558Srgrimes parsecred(cpoptarg, cr); 13281558Srgrimes if (allflag == 0) { 13291558Srgrimes *exflagsp |= MNT_EXPORTANON; 13301558Srgrimes opt_flags |= OP_MAPALL; 13311558Srgrimes } else 13321558Srgrimes opt_flags |= OP_MAPROOT; 13331558Srgrimes } else if (!strcmp(cpopt, "kerb") || !strcmp(cpopt, "k")) { 13341558Srgrimes *exflagsp |= MNT_EXKERB; 13351558Srgrimes opt_flags |= OP_KERB; 13361558Srgrimes } else if (cpoptarg && (!strcmp(cpopt, "mask") || 13371558Srgrimes !strcmp(cpopt, "m"))) { 13381558Srgrimes if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { 13391558Srgrimes syslog(LOG_ERR, "Bad mask: %s", cpoptarg); 13401558Srgrimes return (1); 13411558Srgrimes } 13421558Srgrimes usedarg++; 13431558Srgrimes opt_flags |= OP_MASK; 13441558Srgrimes } else if (cpoptarg && (!strcmp(cpopt, "network") || 13451558Srgrimes !strcmp(cpopt, "n"))) { 13461558Srgrimes if (grp->gr_type != GT_NULL) { 13471558Srgrimes syslog(LOG_ERR, "Network/host conflict"); 13481558Srgrimes return (1); 13491558Srgrimes } else if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 0)) { 13501558Srgrimes syslog(LOG_ERR, "Bad net: %s", cpoptarg); 13511558Srgrimes return (1); 13521558Srgrimes } 13531558Srgrimes grp->gr_type = GT_NET; 13541558Srgrimes *has_hostp = 1; 13551558Srgrimes usedarg++; 13561558Srgrimes opt_flags |= OP_NET; 13571558Srgrimes } else if (!strcmp(cpopt, "alldirs")) { 13581558Srgrimes opt_flags |= OP_ALLDIRS; 135927447Sdfr } else if (!strcmp(cpopt, "public")) { 136027447Sdfr *exflagsp |= MNT_EXPUBLIC; 136127447Sdfr } else if (!strcmp(cpopt, "webnfs")) { 136227447Sdfr *exflagsp |= (MNT_EXPUBLIC|MNT_EXRDONLY|MNT_EXPORTANON); 136327447Sdfr opt_flags |= OP_MAPALL; 136427447Sdfr } else if (cpoptarg && !strcmp(cpopt, "index")) { 136527447Sdfr ep->ex_indexfile = strdup(cpoptarg); 13661558Srgrimes#ifdef ISO 13671558Srgrimes } else if (cpoptarg && !strcmp(cpopt, "iso")) { 13681558Srgrimes if (get_isoaddr(cpoptarg, grp)) { 13691558Srgrimes syslog(LOG_ERR, "Bad iso addr: %s", cpoptarg); 13701558Srgrimes return (1); 13711558Srgrimes } 13721558Srgrimes *has_hostp = 1; 13731558Srgrimes usedarg++; 13741558Srgrimes opt_flags |= OP_ISO; 13751558Srgrimes#endif /* ISO */ 13761558Srgrimes } else { 13771558Srgrimes syslog(LOG_ERR, "Bad opt %s", cpopt); 13781558Srgrimes return (1); 13791558Srgrimes } 13801558Srgrimes if (usedarg >= 0) { 13811558Srgrimes *endcp = savedc2; 13821558Srgrimes **endcpp = savedc; 13831558Srgrimes if (usedarg > 0) { 13841558Srgrimes *cpp = cp; 13851558Srgrimes *endcpp = endcp; 13861558Srgrimes } 13871558Srgrimes return (0); 13881558Srgrimes } 13891558Srgrimes cpopt = cpoptend; 13901558Srgrimes } 13911558Srgrimes **endcpp = savedc; 13921558Srgrimes return (0); 13931558Srgrimes} 13941558Srgrimes 13951558Srgrimes/* 13961558Srgrimes * Translate a character string to the corresponding list of network 13971558Srgrimes * addresses for a hostname. 13981558Srgrimes */ 13991558Srgrimesint 14007401Swpaulget_host(cp, grp, tgrp) 14011558Srgrimes char *cp; 14021558Srgrimes struct grouplist *grp; 14037401Swpaul struct grouplist *tgrp; 14041558Srgrimes{ 14057401Swpaul struct grouplist *checkgrp; 14061558Srgrimes struct hostent *hp, *nhp; 14071558Srgrimes char **addrp, **naddrp; 14081558Srgrimes struct hostent t_host; 14091558Srgrimes int i; 14101558Srgrimes u_long saddr; 14111558Srgrimes char *aptr[2]; 14121558Srgrimes 14131558Srgrimes if (grp->gr_type != GT_NULL) 14141558Srgrimes return (1); 14151558Srgrimes if ((hp = gethostbyname(cp)) == NULL) { 14161558Srgrimes if (isdigit(*cp)) { 14171558Srgrimes saddr = inet_addr(cp); 14181558Srgrimes if (saddr == -1) { 14199336Sdfr syslog(LOG_ERR, "Inet_addr failed for %s", cp); 14201558Srgrimes return (1); 14211558Srgrimes } 14221558Srgrimes if ((hp = gethostbyaddr((caddr_t)&saddr, sizeof (saddr), 14231558Srgrimes AF_INET)) == NULL) { 14241558Srgrimes hp = &t_host; 14251558Srgrimes hp->h_name = cp; 14261558Srgrimes hp->h_addrtype = AF_INET; 14271558Srgrimes hp->h_length = sizeof (u_long); 14281558Srgrimes hp->h_addr_list = aptr; 14291558Srgrimes aptr[0] = (char *)&saddr; 14301558Srgrimes aptr[1] = (char *)NULL; 14311558Srgrimes } 14321558Srgrimes } else { 14339336Sdfr syslog(LOG_ERR, "Gethostbyname failed for %s", cp); 14341558Srgrimes return (1); 14351558Srgrimes } 14361558Srgrimes } 14377401Swpaul /* 14387401Swpaul * Sanity check: make sure we don't already have an entry 14397401Swpaul * for this host in the grouplist. 14407401Swpaul */ 14417401Swpaul checkgrp = tgrp; 14427401Swpaul while (checkgrp) { 144317887Swpaul if (checkgrp->gr_type == GT_HOST && 144417887Swpaul checkgrp->gr_ptr.gt_hostent != NULL && 14457401Swpaul !strcmp(checkgrp->gr_ptr.gt_hostent->h_name, hp->h_name)) { 14467401Swpaul grp->gr_type = GT_IGNORE; 14477401Swpaul return(0); 14487401Swpaul } 14497401Swpaul checkgrp = checkgrp->gr_next; 14507401Swpaul } 14517401Swpaul 14521558Srgrimes grp->gr_type = GT_HOST; 14531558Srgrimes nhp = grp->gr_ptr.gt_hostent = (struct hostent *) 14541558Srgrimes malloc(sizeof(struct hostent)); 14551558Srgrimes if (nhp == (struct hostent *)NULL) 14561558Srgrimes out_of_mem(); 145723681Speter memmove(nhp, hp, sizeof(struct hostent)); 14581558Srgrimes i = strlen(hp->h_name)+1; 14591558Srgrimes nhp->h_name = (char *)malloc(i); 14601558Srgrimes if (nhp->h_name == (char *)NULL) 14611558Srgrimes out_of_mem(); 146223681Speter memmove(nhp->h_name, hp->h_name, i); 14631558Srgrimes addrp = hp->h_addr_list; 14641558Srgrimes i = 1; 14651558Srgrimes while (*addrp++) 14661558Srgrimes i++; 14671558Srgrimes naddrp = nhp->h_addr_list = (char **) 14681558Srgrimes malloc(i*sizeof(char *)); 14691558Srgrimes if (naddrp == (char **)NULL) 14701558Srgrimes out_of_mem(); 14711558Srgrimes addrp = hp->h_addr_list; 14721558Srgrimes while (*addrp) { 14731558Srgrimes *naddrp = (char *) 14741558Srgrimes malloc(hp->h_length); 14751558Srgrimes if (*naddrp == (char *)NULL) 14761558Srgrimes out_of_mem(); 147723681Speter memmove(*naddrp, *addrp, hp->h_length); 14781558Srgrimes addrp++; 14791558Srgrimes naddrp++; 14801558Srgrimes } 14811558Srgrimes *naddrp = (char *)NULL; 14821558Srgrimes if (debug) 14831558Srgrimes fprintf(stderr, "got host %s\n", hp->h_name); 14841558Srgrimes return (0); 14851558Srgrimes} 14861558Srgrimes 14871558Srgrimes/* 14881558Srgrimes * Free up an exports list component 14891558Srgrimes */ 14901558Srgrimesvoid 14911558Srgrimesfree_exp(ep) 14921558Srgrimes struct exportlist *ep; 14931558Srgrimes{ 14941558Srgrimes 14951558Srgrimes if (ep->ex_defdir) { 14961558Srgrimes free_host(ep->ex_defdir->dp_hosts); 14971558Srgrimes free((caddr_t)ep->ex_defdir); 14981558Srgrimes } 14991558Srgrimes if (ep->ex_fsdir) 15001558Srgrimes free(ep->ex_fsdir); 150127447Sdfr if (ep->ex_indexfile) 150227447Sdfr free(ep->ex_indexfile); 15031558Srgrimes free_dir(ep->ex_dirl); 15041558Srgrimes free((caddr_t)ep); 15051558Srgrimes} 15061558Srgrimes 15071558Srgrimes/* 15081558Srgrimes * Free hosts. 15091558Srgrimes */ 15101558Srgrimesvoid 15111558Srgrimesfree_host(hp) 15121558Srgrimes struct hostlist *hp; 15131558Srgrimes{ 15141558Srgrimes struct hostlist *hp2; 15151558Srgrimes 15161558Srgrimes while (hp) { 15171558Srgrimes hp2 = hp; 15181558Srgrimes hp = hp->ht_next; 15191558Srgrimes free((caddr_t)hp2); 15201558Srgrimes } 15211558Srgrimes} 15221558Srgrimes 15231558Srgrimesstruct hostlist * 15241558Srgrimesget_ht() 15251558Srgrimes{ 15261558Srgrimes struct hostlist *hp; 15271558Srgrimes 15281558Srgrimes hp = (struct hostlist *)malloc(sizeof (struct hostlist)); 15291558Srgrimes if (hp == (struct hostlist *)NULL) 15301558Srgrimes out_of_mem(); 15311558Srgrimes hp->ht_next = (struct hostlist *)NULL; 15329336Sdfr hp->ht_flag = 0; 15331558Srgrimes return (hp); 15341558Srgrimes} 15351558Srgrimes 15361558Srgrimes#ifdef ISO 15371558Srgrimes/* 15381558Srgrimes * Translate an iso address. 15391558Srgrimes */ 15401558Srgrimesget_isoaddr(cp, grp) 15411558Srgrimes char *cp; 15421558Srgrimes struct grouplist *grp; 15431558Srgrimes{ 15441558Srgrimes struct iso_addr *isop; 15451558Srgrimes struct sockaddr_iso *isoaddr; 15461558Srgrimes 15471558Srgrimes if (grp->gr_type != GT_NULL) 15481558Srgrimes return (1); 15491558Srgrimes if ((isop = iso_addr(cp)) == NULL) { 15501558Srgrimes syslog(LOG_ERR, 15511558Srgrimes "iso_addr failed, ignored"); 15521558Srgrimes return (1); 15531558Srgrimes } 15541558Srgrimes isoaddr = (struct sockaddr_iso *) 15551558Srgrimes malloc(sizeof (struct sockaddr_iso)); 15561558Srgrimes if (isoaddr == (struct sockaddr_iso *)NULL) 15571558Srgrimes out_of_mem(); 155823681Speter memset(isoaddr, 0, sizeof(struct sockaddr_iso)); 155923681Speter memmove(&isoaddr->siso_addr, isop, sizeof(struct iso_addr)); 156023681Speter isoaddr->siso_len = sizeof(struct sockaddr_iso); 15611558Srgrimes isoaddr->siso_family = AF_ISO; 15621558Srgrimes grp->gr_type = GT_ISO; 15631558Srgrimes grp->gr_ptr.gt_isoaddr = isoaddr; 15641558Srgrimes return (0); 15651558Srgrimes} 15661558Srgrimes#endif /* ISO */ 15671558Srgrimes 15681558Srgrimes/* 15691558Srgrimes * Out of memory, fatal 15701558Srgrimes */ 15711558Srgrimesvoid 15721558Srgrimesout_of_mem() 15731558Srgrimes{ 15741558Srgrimes 15751558Srgrimes syslog(LOG_ERR, "Out of memory"); 15761558Srgrimes exit(2); 15771558Srgrimes} 15781558Srgrimes 15791558Srgrimes/* 15801558Srgrimes * Do the mount syscall with the update flag to push the export info into 15811558Srgrimes * the kernel. 15821558Srgrimes */ 15831558Srgrimesint 15841558Srgrimesdo_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb) 15851558Srgrimes struct exportlist *ep; 15861558Srgrimes struct grouplist *grp; 15871558Srgrimes int exflags; 15881558Srgrimes struct ucred *anoncrp; 15891558Srgrimes char *dirp; 15901558Srgrimes int dirplen; 15911558Srgrimes struct statfs *fsb; 15921558Srgrimes{ 15931558Srgrimes char *cp = (char *)NULL; 15941558Srgrimes u_long **addrp; 15951558Srgrimes int done; 15961558Srgrimes char savedc = '\0'; 15971558Srgrimes struct sockaddr_in sin, imask; 15981558Srgrimes union { 15991558Srgrimes struct ufs_args ua; 16001558Srgrimes struct iso_args ia; 16011558Srgrimes struct mfs_args ma; 16029336Sdfr#ifdef __NetBSD__ 16039336Sdfr struct msdosfs_args da; 16049336Sdfr#endif 16051558Srgrimes } args; 16061558Srgrimes u_long net; 16071558Srgrimes 16081558Srgrimes args.ua.fspec = 0; 16091558Srgrimes args.ua.export.ex_flags = exflags; 16101558Srgrimes args.ua.export.ex_anon = *anoncrp; 161127447Sdfr args.ua.export.ex_indexfile = ep->ex_indexfile; 161223681Speter memset(&sin, 0, sizeof(sin)); 161323681Speter memset(&imask, 0, sizeof(imask)); 16141558Srgrimes sin.sin_family = AF_INET; 16151558Srgrimes sin.sin_len = sizeof(sin); 16161558Srgrimes imask.sin_family = AF_INET; 16171558Srgrimes imask.sin_len = sizeof(sin); 16181558Srgrimes if (grp->gr_type == GT_HOST) 16191558Srgrimes addrp = (u_long **)grp->gr_ptr.gt_hostent->h_addr_list; 16201558Srgrimes else 16211558Srgrimes addrp = (u_long **)NULL; 16221558Srgrimes done = FALSE; 16231558Srgrimes while (!done) { 16241558Srgrimes switch (grp->gr_type) { 16251558Srgrimes case GT_HOST: 16261558Srgrimes if (addrp) { 16271558Srgrimes sin.sin_addr.s_addr = **addrp; 16281558Srgrimes args.ua.export.ex_addrlen = sizeof(sin); 16291558Srgrimes } else 16301558Srgrimes args.ua.export.ex_addrlen = 0; 16311558Srgrimes args.ua.export.ex_addr = (struct sockaddr *)&sin; 16321558Srgrimes args.ua.export.ex_masklen = 0; 16331558Srgrimes break; 16341558Srgrimes case GT_NET: 16351558Srgrimes if (grp->gr_ptr.gt_net.nt_mask) 16361558Srgrimes imask.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_mask; 16371558Srgrimes else { 16381558Srgrimes net = ntohl(grp->gr_ptr.gt_net.nt_net); 16391558Srgrimes if (IN_CLASSA(net)) 16401558Srgrimes imask.sin_addr.s_addr = inet_addr("255.0.0.0"); 16411558Srgrimes else if (IN_CLASSB(net)) 16421558Srgrimes imask.sin_addr.s_addr = 16431558Srgrimes inet_addr("255.255.0.0"); 16441558Srgrimes else 16451558Srgrimes imask.sin_addr.s_addr = 16461558Srgrimes inet_addr("255.255.255.0"); 16471558Srgrimes grp->gr_ptr.gt_net.nt_mask = imask.sin_addr.s_addr; 16481558Srgrimes } 16491558Srgrimes sin.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_net; 16501558Srgrimes args.ua.export.ex_addr = (struct sockaddr *)&sin; 16511558Srgrimes args.ua.export.ex_addrlen = sizeof (sin); 16521558Srgrimes args.ua.export.ex_mask = (struct sockaddr *)&imask; 16531558Srgrimes args.ua.export.ex_masklen = sizeof (imask); 16541558Srgrimes break; 16551558Srgrimes#ifdef ISO 16561558Srgrimes case GT_ISO: 16571558Srgrimes args.ua.export.ex_addr = 16581558Srgrimes (struct sockaddr *)grp->gr_ptr.gt_isoaddr; 16591558Srgrimes args.ua.export.ex_addrlen = 16601558Srgrimes sizeof(struct sockaddr_iso); 16611558Srgrimes args.ua.export.ex_masklen = 0; 16621558Srgrimes break; 16631558Srgrimes#endif /* ISO */ 16647401Swpaul case GT_IGNORE: 16657401Swpaul return(0); 16667401Swpaul break; 16671558Srgrimes default: 16681558Srgrimes syslog(LOG_ERR, "Bad grouptype"); 16691558Srgrimes if (cp) 16701558Srgrimes *cp = savedc; 16711558Srgrimes return (1); 16721558Srgrimes }; 16731558Srgrimes 16741558Srgrimes /* 16751558Srgrimes * XXX: 16761558Srgrimes * Maybe I should just use the fsb->f_mntonname path instead 16771558Srgrimes * of looping back up the dirp to the mount point?? 16781558Srgrimes * Also, needs to know how to export all types of local 167923681Speter * exportable file systems and not just "ufs". 16801558Srgrimes */ 16819336Sdfr while (mount(fsb->f_fstypename, dirp, 16821558Srgrimes fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) { 16831558Srgrimes if (cp) 16841558Srgrimes *cp-- = savedc; 16851558Srgrimes else 16861558Srgrimes cp = dirp + dirplen - 1; 16871558Srgrimes if (errno == EPERM) { 16881558Srgrimes syslog(LOG_ERR, 16891558Srgrimes "Can't change attributes for %s.\n", dirp); 16901558Srgrimes return (1); 16911558Srgrimes } 16921558Srgrimes if (opt_flags & OP_ALLDIRS) { 16934895Swollman syslog(LOG_ERR, "Could not remount %s: %m", 16944895Swollman dirp); 16951558Srgrimes return (1); 16961558Srgrimes } 16971558Srgrimes /* back up over the last component */ 16981558Srgrimes while (*cp == '/' && cp > dirp) 16991558Srgrimes cp--; 17001558Srgrimes while (*(cp - 1) != '/' && cp > dirp) 17011558Srgrimes cp--; 17021558Srgrimes if (cp == dirp) { 17031558Srgrimes if (debug) 17041558Srgrimes fprintf(stderr,"mnt unsucc\n"); 17051558Srgrimes syslog(LOG_ERR, "Can't export %s", dirp); 17061558Srgrimes return (1); 17071558Srgrimes } 17081558Srgrimes savedc = *cp; 17091558Srgrimes *cp = '\0'; 17101558Srgrimes } 17111558Srgrimes if (addrp) { 17121558Srgrimes ++addrp; 17131558Srgrimes if (*addrp == (u_long *)NULL) 17141558Srgrimes done = TRUE; 17151558Srgrimes } else 17161558Srgrimes done = TRUE; 17171558Srgrimes } 17181558Srgrimes if (cp) 17191558Srgrimes *cp = savedc; 17201558Srgrimes return (0); 17211558Srgrimes} 17221558Srgrimes 17231558Srgrimes/* 17241558Srgrimes * Translate a net address. 17251558Srgrimes */ 17261558Srgrimesint 17271558Srgrimesget_net(cp, net, maskflg) 17281558Srgrimes char *cp; 17291558Srgrimes struct netmsk *net; 17301558Srgrimes int maskflg; 17311558Srgrimes{ 17321558Srgrimes struct netent *np; 17331558Srgrimes long netaddr; 17341558Srgrimes struct in_addr inetaddr, inetaddr2; 17351558Srgrimes char *name; 17361558Srgrimes 173725318Spst if (isdigit(*cp) && ((netaddr = inet_network(cp)) != -1)) { 17381558Srgrimes inetaddr = inet_makeaddr(netaddr, 0); 17391558Srgrimes /* 17401558Srgrimes * Due to arbritrary subnet masks, you don't know how many 17411558Srgrimes * bits to shift the address to make it into a network, 17421558Srgrimes * however you do know how to make a network address into 17431558Srgrimes * a host with host == 0 and then compare them. 17441558Srgrimes * (What a pest) 17451558Srgrimes */ 17461558Srgrimes if (!maskflg) { 17471558Srgrimes setnetent(0); 17481558Srgrimes while (np = getnetent()) { 17491558Srgrimes inetaddr2 = inet_makeaddr(np->n_net, 0); 17501558Srgrimes if (inetaddr2.s_addr == inetaddr.s_addr) 17511558Srgrimes break; 17521558Srgrimes } 17531558Srgrimes endnetent(); 17541558Srgrimes } 175525318Spst } else if ((np = getnetbyname(cp)) != NULL) { 175625318Spst inetaddr = inet_makeaddr(np->n_net, 0); 17571558Srgrimes } else 17581558Srgrimes return (1); 175925318Spst 17601558Srgrimes if (maskflg) 17611558Srgrimes net->nt_mask = inetaddr.s_addr; 17621558Srgrimes else { 17631558Srgrimes if (np) 17641558Srgrimes name = np->n_name; 17651558Srgrimes else 17661558Srgrimes name = inet_ntoa(inetaddr); 17671558Srgrimes net->nt_name = (char *)malloc(strlen(name) + 1); 17681558Srgrimes if (net->nt_name == (char *)NULL) 17691558Srgrimes out_of_mem(); 17701558Srgrimes strcpy(net->nt_name, name); 17711558Srgrimes net->nt_net = inetaddr.s_addr; 17721558Srgrimes } 17731558Srgrimes return (0); 17741558Srgrimes} 17751558Srgrimes 17761558Srgrimes/* 17771558Srgrimes * Parse out the next white space separated field 17781558Srgrimes */ 17791558Srgrimesvoid 17801558Srgrimesnextfield(cp, endcp) 17811558Srgrimes char **cp; 17821558Srgrimes char **endcp; 17831558Srgrimes{ 17841558Srgrimes char *p; 17851558Srgrimes 17861558Srgrimes p = *cp; 17871558Srgrimes while (*p == ' ' || *p == '\t') 17881558Srgrimes p++; 17891558Srgrimes if (*p == '\n' || *p == '\0') 17901558Srgrimes *cp = *endcp = p; 17911558Srgrimes else { 17921558Srgrimes *cp = p++; 17931558Srgrimes while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 17941558Srgrimes p++; 17951558Srgrimes *endcp = p; 17961558Srgrimes } 17971558Srgrimes} 17981558Srgrimes 17991558Srgrimes/* 18001558Srgrimes * Get an exports file line. Skip over blank lines and handle line 18011558Srgrimes * continuations. 18021558Srgrimes */ 18031558Srgrimesint 18041558Srgrimesget_line() 18051558Srgrimes{ 18061558Srgrimes char *p, *cp; 18071558Srgrimes int len; 18081558Srgrimes int totlen, cont_line; 18091558Srgrimes 18101558Srgrimes /* 18111558Srgrimes * Loop around ignoring blank lines and getting all continuation lines. 18121558Srgrimes */ 18131558Srgrimes p = line; 18141558Srgrimes totlen = 0; 18151558Srgrimes do { 18161558Srgrimes if (fgets(p, LINESIZ - totlen, exp_file) == NULL) 18171558Srgrimes return (0); 18181558Srgrimes len = strlen(p); 18191558Srgrimes cp = p + len - 1; 18201558Srgrimes cont_line = 0; 18211558Srgrimes while (cp >= p && 18221558Srgrimes (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '\\')) { 18231558Srgrimes if (*cp == '\\') 18241558Srgrimes cont_line = 1; 18251558Srgrimes cp--; 18261558Srgrimes len--; 18271558Srgrimes } 18281558Srgrimes *++cp = '\0'; 18291558Srgrimes if (len > 0) { 18301558Srgrimes totlen += len; 18311558Srgrimes if (totlen >= LINESIZ) { 18321558Srgrimes syslog(LOG_ERR, "Exports line too long"); 18331558Srgrimes exit(2); 18341558Srgrimes } 18351558Srgrimes p = cp; 18361558Srgrimes } 18371558Srgrimes } while (totlen == 0 || cont_line); 18381558Srgrimes return (1); 18391558Srgrimes} 18401558Srgrimes 18411558Srgrimes/* 18421558Srgrimes * Parse a description of a credential. 18431558Srgrimes */ 18441558Srgrimesvoid 18451558Srgrimesparsecred(namelist, cr) 18461558Srgrimes char *namelist; 18471558Srgrimes struct ucred *cr; 18481558Srgrimes{ 18491558Srgrimes char *name; 18501558Srgrimes int cnt; 18511558Srgrimes char *names; 18521558Srgrimes struct passwd *pw; 18531558Srgrimes struct group *gr; 18541558Srgrimes int ngroups, groups[NGROUPS + 1]; 18551558Srgrimes 18561558Srgrimes /* 18571558Srgrimes * Set up the unpriviledged user. 18581558Srgrimes */ 18591558Srgrimes cr->cr_ref = 1; 18601558Srgrimes cr->cr_uid = -2; 18611558Srgrimes cr->cr_groups[0] = -2; 18621558Srgrimes cr->cr_ngroups = 1; 18631558Srgrimes /* 18641558Srgrimes * Get the user's password table entry. 18651558Srgrimes */ 18661558Srgrimes names = strsep(&namelist, " \t\n"); 18671558Srgrimes name = strsep(&names, ":"); 18681558Srgrimes if (isdigit(*name) || *name == '-') 18691558Srgrimes pw = getpwuid(atoi(name)); 18701558Srgrimes else 18711558Srgrimes pw = getpwnam(name); 18721558Srgrimes /* 18731558Srgrimes * Credentials specified as those of a user. 18741558Srgrimes */ 18751558Srgrimes if (names == NULL) { 18761558Srgrimes if (pw == NULL) { 18771558Srgrimes syslog(LOG_ERR, "Unknown user: %s", name); 18781558Srgrimes return; 18791558Srgrimes } 18801558Srgrimes cr->cr_uid = pw->pw_uid; 18811558Srgrimes ngroups = NGROUPS + 1; 18821558Srgrimes if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) 18831558Srgrimes syslog(LOG_ERR, "Too many groups"); 18841558Srgrimes /* 18851558Srgrimes * Convert from int's to gid_t's and compress out duplicate 18861558Srgrimes */ 18871558Srgrimes cr->cr_ngroups = ngroups - 1; 18881558Srgrimes cr->cr_groups[0] = groups[0]; 18891558Srgrimes for (cnt = 2; cnt < ngroups; cnt++) 18901558Srgrimes cr->cr_groups[cnt - 1] = groups[cnt]; 18911558Srgrimes return; 18921558Srgrimes } 18931558Srgrimes /* 18941558Srgrimes * Explicit credential specified as a colon separated list: 18951558Srgrimes * uid:gid:gid:... 18961558Srgrimes */ 18971558Srgrimes if (pw != NULL) 18981558Srgrimes cr->cr_uid = pw->pw_uid; 18991558Srgrimes else if (isdigit(*name) || *name == '-') 19001558Srgrimes cr->cr_uid = atoi(name); 19011558Srgrimes else { 19021558Srgrimes syslog(LOG_ERR, "Unknown user: %s", name); 19031558Srgrimes return; 19041558Srgrimes } 19051558Srgrimes cr->cr_ngroups = 0; 19061558Srgrimes while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { 19071558Srgrimes name = strsep(&names, ":"); 19081558Srgrimes if (isdigit(*name) || *name == '-') { 19091558Srgrimes cr->cr_groups[cr->cr_ngroups++] = atoi(name); 19101558Srgrimes } else { 19111558Srgrimes if ((gr = getgrnam(name)) == NULL) { 19121558Srgrimes syslog(LOG_ERR, "Unknown group: %s", name); 19131558Srgrimes continue; 19141558Srgrimes } 19151558Srgrimes cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; 19161558Srgrimes } 19171558Srgrimes } 19181558Srgrimes if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) 19191558Srgrimes syslog(LOG_ERR, "Too many groups"); 19201558Srgrimes} 19211558Srgrimes 19221558Srgrimes#define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 19231558Srgrimes/* 19241558Srgrimes * Routines that maintain the remote mounttab 19251558Srgrimes */ 19261558Srgrimesvoid 19271558Srgrimesget_mountlist() 19281558Srgrimes{ 19291558Srgrimes struct mountlist *mlp, **mlpp; 193023681Speter char *host, *dirp, *cp; 19311558Srgrimes int len; 19321558Srgrimes char str[STRSIZ]; 19331558Srgrimes FILE *mlfile; 19341558Srgrimes 19351558Srgrimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) { 19361558Srgrimes syslog(LOG_ERR, "Can't open %s", _PATH_RMOUNTLIST); 19371558Srgrimes return; 19381558Srgrimes } 19391558Srgrimes mlpp = &mlhead; 19401558Srgrimes while (fgets(str, STRSIZ, mlfile) != NULL) { 194123681Speter cp = str; 194223681Speter host = strsep(&cp, " \t\n"); 194323681Speter dirp = strsep(&cp, " \t\n"); 194423681Speter if (host == NULL || dirp == NULL) 19451558Srgrimes continue; 19461558Srgrimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 194723681Speter strncpy(mlp->ml_host, host, RPCMNT_NAMELEN); 194823681Speter mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 194923681Speter strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 195023681Speter mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 19511558Srgrimes mlp->ml_next = (struct mountlist *)NULL; 19521558Srgrimes *mlpp = mlp; 19531558Srgrimes mlpp = &mlp->ml_next; 19541558Srgrimes } 19551558Srgrimes fclose(mlfile); 19561558Srgrimes} 19571558Srgrimes 19581558Srgrimesvoid 19591558Srgrimesdel_mlist(hostp, dirp) 19601558Srgrimes char *hostp, *dirp; 19611558Srgrimes{ 19621558Srgrimes struct mountlist *mlp, **mlpp; 19631558Srgrimes struct mountlist *mlp2; 19641558Srgrimes FILE *mlfile; 19651558Srgrimes int fnd = 0; 19661558Srgrimes 19671558Srgrimes mlpp = &mlhead; 19681558Srgrimes mlp = mlhead; 19691558Srgrimes while (mlp) { 19701558Srgrimes if (!strcmp(mlp->ml_host, hostp) && 19711558Srgrimes (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 19721558Srgrimes fnd = 1; 19731558Srgrimes mlp2 = mlp; 19741558Srgrimes *mlpp = mlp = mlp->ml_next; 19751558Srgrimes free((caddr_t)mlp2); 19761558Srgrimes } else { 19771558Srgrimes mlpp = &mlp->ml_next; 19781558Srgrimes mlp = mlp->ml_next; 19791558Srgrimes } 19801558Srgrimes } 19811558Srgrimes if (fnd) { 19821558Srgrimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 19831558Srgrimes syslog(LOG_ERR,"Can't update %s", _PATH_RMOUNTLIST); 19841558Srgrimes return; 19851558Srgrimes } 19861558Srgrimes mlp = mlhead; 19871558Srgrimes while (mlp) { 19881558Srgrimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 19891558Srgrimes mlp = mlp->ml_next; 19901558Srgrimes } 19911558Srgrimes fclose(mlfile); 19921558Srgrimes } 19931558Srgrimes} 19941558Srgrimes 19951558Srgrimesvoid 19961558Srgrimesadd_mlist(hostp, dirp) 19971558Srgrimes char *hostp, *dirp; 19981558Srgrimes{ 19991558Srgrimes struct mountlist *mlp, **mlpp; 20001558Srgrimes FILE *mlfile; 20011558Srgrimes 20021558Srgrimes mlpp = &mlhead; 20031558Srgrimes mlp = mlhead; 20041558Srgrimes while (mlp) { 20051558Srgrimes if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 20061558Srgrimes return; 20071558Srgrimes mlpp = &mlp->ml_next; 20081558Srgrimes mlp = mlp->ml_next; 20091558Srgrimes } 20101558Srgrimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 20111558Srgrimes strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 20121558Srgrimes mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 20131558Srgrimes strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 20141558Srgrimes mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 20151558Srgrimes mlp->ml_next = (struct mountlist *)NULL; 20161558Srgrimes *mlpp = mlp; 20171558Srgrimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 20181558Srgrimes syslog(LOG_ERR, "Can't update %s", _PATH_RMOUNTLIST); 20191558Srgrimes return; 20201558Srgrimes } 20211558Srgrimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 20221558Srgrimes fclose(mlfile); 20231558Srgrimes} 20241558Srgrimes 20251558Srgrimes/* 20261558Srgrimes * This function is called via. SIGTERM when the system is going down. 20271558Srgrimes * It sends a broadcast RPCMNT_UMNTALL. 20281558Srgrimes */ 20291558Srgrimesvoid 20301558Srgrimessend_umntall() 20311558Srgrimes{ 20321558Srgrimes (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL, 20331558Srgrimes xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each); 20341558Srgrimes exit(0); 20351558Srgrimes} 20361558Srgrimes 20371558Srgrimesint 20381558Srgrimesumntall_each(resultsp, raddr) 20391558Srgrimes caddr_t resultsp; 20401558Srgrimes struct sockaddr_in *raddr; 20411558Srgrimes{ 20421558Srgrimes return (1); 20431558Srgrimes} 20441558Srgrimes 20451558Srgrimes/* 20461558Srgrimes * Free up a group list. 20471558Srgrimes */ 20481558Srgrimesvoid 20491558Srgrimesfree_grp(grp) 20501558Srgrimes struct grouplist *grp; 20511558Srgrimes{ 20521558Srgrimes char **addrp; 20531558Srgrimes 20541558Srgrimes if (grp->gr_type == GT_HOST) { 20551558Srgrimes if (grp->gr_ptr.gt_hostent->h_name) { 20561558Srgrimes addrp = grp->gr_ptr.gt_hostent->h_addr_list; 20571558Srgrimes while (addrp && *addrp) 20581558Srgrimes free(*addrp++); 20591558Srgrimes free((caddr_t)grp->gr_ptr.gt_hostent->h_addr_list); 20601558Srgrimes free(grp->gr_ptr.gt_hostent->h_name); 20611558Srgrimes } 20621558Srgrimes free((caddr_t)grp->gr_ptr.gt_hostent); 20631558Srgrimes } else if (grp->gr_type == GT_NET) { 20641558Srgrimes if (grp->gr_ptr.gt_net.nt_name) 20651558Srgrimes free(grp->gr_ptr.gt_net.nt_name); 20661558Srgrimes } 20671558Srgrimes#ifdef ISO 20681558Srgrimes else if (grp->gr_type == GT_ISO) 20691558Srgrimes free((caddr_t)grp->gr_ptr.gt_isoaddr); 20701558Srgrimes#endif 20711558Srgrimes free((caddr_t)grp); 20721558Srgrimes} 20731558Srgrimes 20741558Srgrimes#ifdef DEBUG 20751558Srgrimesvoid 20761558SrgrimesSYSLOG(int pri, const char *fmt, ...) 20771558Srgrimes{ 20781558Srgrimes va_list ap; 20791558Srgrimes 20801558Srgrimes va_start(ap, fmt); 20811558Srgrimes vfprintf(stderr, fmt, ap); 20821558Srgrimes va_end(ap); 20831558Srgrimes} 20841558Srgrimes#endif /* DEBUG */ 20851558Srgrimes 20861558Srgrimes/* 20871558Srgrimes * Check options for consistency. 20881558Srgrimes */ 20891558Srgrimesint 20901558Srgrimescheck_options(dp) 20911558Srgrimes struct dirlist *dp; 20921558Srgrimes{ 20931558Srgrimes 20941558Srgrimes if (dp == (struct dirlist *)NULL) 20951558Srgrimes return (1); 20961558Srgrimes if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL) || 20971558Srgrimes (opt_flags & (OP_MAPROOT | OP_KERB)) == (OP_MAPROOT | OP_KERB) || 20981558Srgrimes (opt_flags & (OP_MAPALL | OP_KERB)) == (OP_MAPALL | OP_KERB)) { 20991558Srgrimes syslog(LOG_ERR, "-mapall, -maproot and -kerb mutually exclusive"); 21001558Srgrimes return (1); 21011558Srgrimes } 21021558Srgrimes if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { 21031558Srgrimes syslog(LOG_ERR, "-mask requires -net"); 21041558Srgrimes return (1); 21051558Srgrimes } 21061558Srgrimes if ((opt_flags & (OP_NET | OP_ISO)) == (OP_NET | OP_ISO)) { 21071558Srgrimes syslog(LOG_ERR, "-net and -iso mutually exclusive"); 21081558Srgrimes return (1); 21091558Srgrimes } 21101558Srgrimes if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { 21111558Srgrimes syslog(LOG_ERR, "-alldir has multiple directories"); 21121558Srgrimes return (1); 21131558Srgrimes } 21141558Srgrimes return (0); 21151558Srgrimes} 21161558Srgrimes 21171558Srgrimes/* 21181558Srgrimes * Check an absolute directory path for any symbolic links. Return true 21191558Srgrimes * if no symbolic links are found. 21201558Srgrimes */ 21211558Srgrimesint 21221558Srgrimescheck_dirpath(dirp) 21231558Srgrimes char *dirp; 21241558Srgrimes{ 21251558Srgrimes char *cp; 21261558Srgrimes int ret = 1; 21271558Srgrimes struct stat sb; 21281558Srgrimes 21291558Srgrimes cp = dirp + 1; 21301558Srgrimes while (*cp && ret) { 21311558Srgrimes if (*cp == '/') { 21321558Srgrimes *cp = '\0'; 21339336Sdfr if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 21341558Srgrimes ret = 0; 21351558Srgrimes *cp = '/'; 21361558Srgrimes } 21371558Srgrimes cp++; 21381558Srgrimes } 21399336Sdfr if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 21401558Srgrimes ret = 0; 21411558Srgrimes return (ret); 21421558Srgrimes} 21439336Sdfr 21449336Sdfr/* 21459336Sdfr * Just translate an ascii string to an integer. 21469336Sdfr */ 21479336Sdfrint 21489336Sdfrget_num(cp) 21499336Sdfr register char *cp; 21509336Sdfr{ 21519336Sdfr register int res = 0; 21529336Sdfr 21539336Sdfr while (*cp) { 21549336Sdfr if (*cp < '0' || *cp > '9') 21559336Sdfr return (-1); 21569336Sdfr res = res * 10 + (*cp++ - '0'); 21579336Sdfr } 21589336Sdfr return (res); 21599336Sdfr} 2160