mountd.c revision 72650
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 3837663Scharnierstatic const 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 4437663Scharnier#if 0 4537663Scharnierstatic char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; 4637663Scharnier#endif 472999Swollmanstatic const char rcsid[] = 4850476Speter "$FreeBSD: head/usr.sbin/mountd/mountd.c 72650 2001-02-18 13:30:20Z green $"; 492999Swollman#endif /*not lint*/ 501558Srgrimes 511558Srgrimes#include <sys/param.h> 521558Srgrimes#include <sys/mount.h> 531558Srgrimes#include <sys/stat.h> 541558Srgrimes#include <sys/syslog.h> 5524330Sguido#include <sys/sysctl.h> 561558Srgrimes 571558Srgrimes#include <rpc/rpc.h> 581558Srgrimes#include <rpc/pmap_clnt.h> 591558Srgrimes#include <nfs/rpcv2.h> 609336Sdfr#include <nfs/nfsproto.h> 6124330Sguido#include <nfs/nfs.h> 6223681Speter#include <ufs/ufs/ufsmount.h> 6323681Speter#include <msdosfs/msdosfsmount.h> 6454093Ssemenu#include <ntfs/ntfsmount.h> 6523681Speter#include <isofs/cd9660/cd9660_mount.h> /* XXX need isofs in include */ 661558Srgrimes 671558Srgrimes#include <arpa/inet.h> 681558Srgrimes 691558Srgrimes#include <ctype.h> 7037663Scharnier#include <err.h> 711558Srgrimes#include <errno.h> 721558Srgrimes#include <grp.h> 731558Srgrimes#include <netdb.h> 741558Srgrimes#include <pwd.h> 751558Srgrimes#include <signal.h> 761558Srgrimes#include <stdio.h> 771558Srgrimes#include <stdlib.h> 781558Srgrimes#include <string.h> 791558Srgrimes#include <unistd.h> 801558Srgrimes#include "pathnames.h" 811558Srgrimes 821558Srgrimes#ifdef DEBUG 831558Srgrimes#include <stdarg.h> 841558Srgrimes#endif 851558Srgrimes 861558Srgrimes/* 871558Srgrimes * Structures for keeping the mount list and export list 881558Srgrimes */ 891558Srgrimesstruct mountlist { 901558Srgrimes struct mountlist *ml_next; 911558Srgrimes char ml_host[RPCMNT_NAMELEN+1]; 921558Srgrimes char ml_dirp[RPCMNT_PATHLEN+1]; 931558Srgrimes}; 941558Srgrimes 951558Srgrimesstruct dirlist { 961558Srgrimes struct dirlist *dp_left; 971558Srgrimes struct dirlist *dp_right; 981558Srgrimes int dp_flag; 991558Srgrimes struct hostlist *dp_hosts; /* List of hosts this dir exported to */ 1001558Srgrimes char dp_dirp[1]; /* Actually malloc'd to size of dir */ 1011558Srgrimes}; 1021558Srgrimes/* dp_flag bits */ 1031558Srgrimes#define DP_DEFSET 0x1 1049336Sdfr#define DP_HOSTSET 0x2 1059336Sdfr#define DP_KERB 0x4 1061558Srgrimes 1071558Srgrimesstruct exportlist { 1081558Srgrimes struct exportlist *ex_next; 1091558Srgrimes struct dirlist *ex_dirl; 1101558Srgrimes struct dirlist *ex_defdir; 1111558Srgrimes int ex_flag; 1121558Srgrimes fsid_t ex_fs; 1131558Srgrimes char *ex_fsdir; 11427447Sdfr char *ex_indexfile; 1151558Srgrimes}; 1161558Srgrimes/* ex_flag bits */ 1171558Srgrimes#define EX_LINKED 0x1 1181558Srgrimes 1191558Srgrimesstruct netmsk { 12042144Sdfr u_int32_t nt_net; 12142144Sdfr u_int32_t nt_mask; 12242144Sdfr char *nt_name; 1231558Srgrimes}; 1241558Srgrimes 1251558Srgrimesunion grouptypes { 1261558Srgrimes struct hostent *gt_hostent; 1271558Srgrimes struct netmsk gt_net; 1281558Srgrimes}; 1291558Srgrimes 1301558Srgrimesstruct grouplist { 1311558Srgrimes int gr_type; 1321558Srgrimes union grouptypes gr_ptr; 1331558Srgrimes struct grouplist *gr_next; 1341558Srgrimes}; 1351558Srgrimes/* Group types */ 1361558Srgrimes#define GT_NULL 0x0 1371558Srgrimes#define GT_HOST 0x1 1381558Srgrimes#define GT_NET 0x2 1397401Swpaul#define GT_IGNORE 0x5 1401558Srgrimes 1411558Srgrimesstruct hostlist { 1429336Sdfr int ht_flag; /* Uses DP_xx bits */ 1431558Srgrimes struct grouplist *ht_grp; 1441558Srgrimes struct hostlist *ht_next; 1451558Srgrimes}; 1461558Srgrimes 1479336Sdfrstruct fhreturn { 1489336Sdfr int fhr_flag; 1499336Sdfr int fhr_vers; 1509336Sdfr nfsfh_t fhr_fh; 1519336Sdfr}; 1529336Sdfr 1531558Srgrimes/* Global defs */ 1541558Srgrimeschar *add_expdir __P((struct dirlist **, char *, int)); 1551558Srgrimesvoid add_dlist __P((struct dirlist **, struct dirlist *, 1569336Sdfr struct grouplist *, int)); 1571558Srgrimesvoid add_mlist __P((char *, char *)); 1581558Srgrimesint check_dirpath __P((char *)); 1591558Srgrimesint check_options __P((struct dirlist *)); 16042144Sdfrint chk_host __P((struct dirlist *, u_int32_t, int *, int *)); 1611558Srgrimesvoid del_mlist __P((char *, char *)); 1621558Srgrimesstruct dirlist *dirp_search __P((struct dirlist *, char *)); 1631558Srgrimesint do_mount __P((struct exportlist *, struct grouplist *, int, 16472650Sgreen struct xucred *, char *, int, struct statfs *)); 1651558Srgrimesint do_opt __P((char **, char **, struct exportlist *, struct grouplist *, 16672650Sgreen int *, int *, struct xucred *)); 1671558Srgrimesstruct exportlist *ex_search __P((fsid_t *)); 1681558Srgrimesstruct exportlist *get_exp __P((void)); 1691558Srgrimesvoid free_dir __P((struct dirlist *)); 1701558Srgrimesvoid free_exp __P((struct exportlist *)); 1711558Srgrimesvoid free_grp __P((struct grouplist *)); 1721558Srgrimesvoid free_host __P((struct hostlist *)); 1731558Srgrimesvoid get_exportlist __P((void)); 1747401Swpaulint get_host __P((char *, struct grouplist *, struct grouplist *)); 1759336Sdfrint get_num __P((char *)); 1761558Srgrimesstruct hostlist *get_ht __P((void)); 1771558Srgrimesint get_line __P((void)); 1781558Srgrimesvoid get_mountlist __P((void)); 1791558Srgrimesint get_net __P((char *, struct netmsk *, int)); 1801558Srgrimesvoid getexp_err __P((struct exportlist *, struct grouplist *)); 1811558Srgrimesstruct grouplist *get_grp __P((void)); 1821558Srgrimesvoid hang_dirp __P((struct dirlist *, struct grouplist *, 1831558Srgrimes struct exportlist *, int)); 1841558Srgrimesvoid mntsrv __P((struct svc_req *, SVCXPRT *)); 1851558Srgrimesvoid nextfield __P((char **, char **)); 1861558Srgrimesvoid out_of_mem __P((void)); 18772650Sgreenvoid parsecred __P((char *, struct xucred *)); 1881558Srgrimesint put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *)); 18942144Sdfrint scan_tree __P((struct dirlist *, u_int32_t)); 19037663Scharnierstatic void usage __P((void)); 1911558Srgrimesint xdr_dir __P((XDR *, char *)); 1921558Srgrimesint xdr_explist __P((XDR *, caddr_t)); 1939336Sdfrint xdr_fhs __P((XDR *, caddr_t)); 1941558Srgrimesint xdr_mlist __P((XDR *, caddr_t)); 1951558Srgrimes 1961558Srgrimes/* C library */ 1971558Srgrimesint getnetgrent(); 1981558Srgrimesvoid endnetgrent(); 1991558Srgrimesvoid setnetgrent(); 2001558Srgrimes 2011558Srgrimesstruct exportlist *exphead; 2021558Srgrimesstruct mountlist *mlhead; 2031558Srgrimesstruct grouplist *grphead; 2041558Srgrimeschar exname[MAXPATHLEN]; 20572650Sgreenstruct xucred def_anon = { 20672650Sgreen 0, 20772650Sgreen (uid_t)-2, 2081558Srgrimes 1, 20972650Sgreen { (gid_t)-2 }, 21072650Sgreen NULL 2111558Srgrimes}; 21225087Sdfrint force_v2 = 0; 2139336Sdfrint resvport_only = 1; 2149336Sdfrint dir_only = 1; 21531705Sguidoint log = 0; 2161558Srgrimesint opt_flags; 2171558Srgrimes/* Bits for above */ 2181558Srgrimes#define OP_MAPROOT 0x01 2191558Srgrimes#define OP_MAPALL 0x02 2201558Srgrimes#define OP_KERB 0x04 2211558Srgrimes#define OP_MASK 0x08 2221558Srgrimes#define OP_NET 0x10 2231558Srgrimes#define OP_ALLDIRS 0x40 2241558Srgrimes 2251558Srgrimes#ifdef DEBUG 2261558Srgrimesint debug = 1; 2271558Srgrimesvoid SYSLOG __P((int, const char *, ...)); 2281558Srgrimes#define syslog SYSLOG 2291558Srgrimes#else 2301558Srgrimesint debug = 0; 2311558Srgrimes#endif 2321558Srgrimes 2331558Srgrimes/* 2341558Srgrimes * Mountd server for NFS mount protocol as described in: 2351558Srgrimes * NFS: Network File System Protocol Specification, RFC1094, Appendix A 2361558Srgrimes * The optional arguments are the exports file name 2371558Srgrimes * default: _PATH_EXPORTS 2381558Srgrimes * and "-n" to allow nonroot mount. 2391558Srgrimes */ 2401558Srgrimesint 2411558Srgrimesmain(argc, argv) 2421558Srgrimes int argc; 2431558Srgrimes char **argv; 2441558Srgrimes{ 2459202Srgrimes SVCXPRT *udptransp, *tcptransp; 24632656Sbde int c, error, mib[3]; 24723681Speter struct vfsconf vfc; 2481558Srgrimes 24923681Speter error = getvfsbyname("nfs", &vfc); 25023681Speter if (error && vfsisloadable("nfs")) { 2512999Swollman if(vfsload("nfs")) 2522999Swollman err(1, "vfsload(nfs)"); 2532999Swollman endvfsent(); /* flush cache */ 25423681Speter error = getvfsbyname("nfs", &vfc); 2552999Swollman } 25623681Speter if (error) 2572999Swollman errx(1, "NFS support is not available in the running kernel"); 2582999Swollman 25931665Sguido while ((c = getopt(argc, argv, "2dlnr")) != -1) 2601558Srgrimes switch (c) { 26125087Sdfr case '2': 26225087Sdfr force_v2 = 1; 26325087Sdfr break; 2649336Sdfr case 'n': 2659336Sdfr resvport_only = 0; 2669336Sdfr break; 2679336Sdfr case 'r': 2689336Sdfr dir_only = 0; 2699336Sdfr break; 2708688Sphk case 'd': 2718688Sphk debug = debug ? 0 : 1; 2728688Sphk break; 27331656Sguido case 'l': 27431656Sguido log = 1; 27531656Sguido break; 2761558Srgrimes default: 27737663Scharnier usage(); 2781558Srgrimes }; 2791558Srgrimes argc -= optind; 2801558Srgrimes argv += optind; 2811558Srgrimes grphead = (struct grouplist *)NULL; 2821558Srgrimes exphead = (struct exportlist *)NULL; 2831558Srgrimes mlhead = (struct mountlist *)NULL; 2841558Srgrimes if (argc == 1) { 2851558Srgrimes strncpy(exname, *argv, MAXPATHLEN-1); 2861558Srgrimes exname[MAXPATHLEN-1] = '\0'; 2871558Srgrimes } else 2881558Srgrimes strcpy(exname, _PATH_EXPORTS); 2891558Srgrimes openlog("mountd", LOG_PID, LOG_DAEMON); 2901558Srgrimes if (debug) 29137663Scharnier warnx("getting export list"); 2921558Srgrimes get_exportlist(); 2931558Srgrimes if (debug) 29437663Scharnier warnx("getting mount list"); 2951558Srgrimes get_mountlist(); 2961558Srgrimes if (debug) 29737663Scharnier warnx("here we go"); 2981558Srgrimes if (debug == 0) { 2991558Srgrimes daemon(0, 0); 3001558Srgrimes signal(SIGINT, SIG_IGN); 3011558Srgrimes signal(SIGQUIT, SIG_IGN); 3021558Srgrimes } 3031558Srgrimes signal(SIGHUP, (void (*) __P((int))) get_exportlist); 3041558Srgrimes { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); 3051558Srgrimes if (pidfile != NULL) { 3061558Srgrimes fprintf(pidfile, "%d\n", getpid()); 3071558Srgrimes fclose(pidfile); 3081558Srgrimes } 3091558Srgrimes } 31024759Sguido if (!resvport_only) { 31124759Sguido mib[0] = CTL_VFS; 31232656Sbde mib[1] = vfc.vfc_typenum; 31324759Sguido mib[2] = NFS_NFSPRIVPORT; 31424759Sguido if (sysctl(mib, 3, NULL, NULL, &resvport_only, 31524759Sguido sizeof(resvport_only)) != 0 && errno != ENOENT) { 31624759Sguido syslog(LOG_ERR, "sysctl: %m"); 31724759Sguido exit(1); 31824759Sguido } 31924330Sguido } 3209202Srgrimes if ((udptransp = svcudp_create(RPC_ANYSOCK)) == NULL || 3219202Srgrimes (tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0)) == NULL) { 32237663Scharnier syslog(LOG_ERR, "can't create socket"); 3231558Srgrimes exit(1); 3241558Srgrimes } 3259336Sdfr pmap_unset(RPCPROG_MNT, 1); 3269336Sdfr pmap_unset(RPCPROG_MNT, 3); 32725087Sdfr if (!force_v2) 32825087Sdfr if (!svc_register(udptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_UDP) || 32925087Sdfr !svc_register(tcptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_TCP)) { 33037663Scharnier syslog(LOG_ERR, "can't register mount"); 33125087Sdfr exit(1); 33225087Sdfr } 3339336Sdfr if (!svc_register(udptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_UDP) || 33425087Sdfr !svc_register(tcptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_TCP)) { 33537663Scharnier syslog(LOG_ERR, "can't register mount"); 3361558Srgrimes exit(1); 3371558Srgrimes } 3381558Srgrimes svc_run(); 33937663Scharnier syslog(LOG_ERR, "mountd died"); 3401558Srgrimes exit(1); 3411558Srgrimes} 3421558Srgrimes 34337663Scharnierstatic void 34437663Scharnierusage() 34537663Scharnier{ 34637663Scharnier fprintf(stderr, 34737663Scharnier "usage: mountd [-2] [-d] [-l] [-n] [-r] [export_file]\n"); 34837663Scharnier exit(1); 34937663Scharnier} 35037663Scharnier 3511558Srgrimes/* 3521558Srgrimes * The mount rpc service 3531558Srgrimes */ 3541558Srgrimesvoid 3551558Srgrimesmntsrv(rqstp, transp) 3561558Srgrimes struct svc_req *rqstp; 3571558Srgrimes SVCXPRT *transp; 3581558Srgrimes{ 3591558Srgrimes struct exportlist *ep; 3601558Srgrimes struct dirlist *dp; 3619336Sdfr struct fhreturn fhr; 3621558Srgrimes struct stat stb; 3631558Srgrimes struct statfs fsb; 3641558Srgrimes struct hostent *hp; 36531656Sguido struct in_addr saddrin; 36642144Sdfr u_int32_t saddr; 3679336Sdfr u_short sport; 36823681Speter char rpcpath[RPCMNT_PATHLEN + 1], dirpath[MAXPATHLEN]; 36928911Sguido int bad = 0, defset, hostset; 3709336Sdfr sigset_t sighup_mask; 3711558Srgrimes 3729336Sdfr sigemptyset(&sighup_mask); 3739336Sdfr sigaddset(&sighup_mask, SIGHUP); 3741558Srgrimes saddr = transp->xp_raddr.sin_addr.s_addr; 37531656Sguido saddrin = transp->xp_raddr.sin_addr; 3769336Sdfr sport = ntohs(transp->xp_raddr.sin_port); 3771558Srgrimes hp = (struct hostent *)NULL; 3781558Srgrimes switch (rqstp->rq_proc) { 3791558Srgrimes case NULLPROC: 3801558Srgrimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 38137663Scharnier syslog(LOG_ERR, "can't send reply"); 3821558Srgrimes return; 3831558Srgrimes case RPCMNT_MOUNT: 3849336Sdfr if (sport >= IPPORT_RESERVED && resvport_only) { 38531656Sguido syslog(LOG_NOTICE, 38631656Sguido "mount request from %s from unprivileged port", 38731656Sguido inet_ntoa(saddrin)); 3881558Srgrimes svcerr_weakauth(transp); 3891558Srgrimes return; 3901558Srgrimes } 3911558Srgrimes if (!svc_getargs(transp, xdr_dir, rpcpath)) { 39231656Sguido syslog(LOG_NOTICE, "undecodable mount request from %s", 39331656Sguido inet_ntoa(saddrin)); 3941558Srgrimes svcerr_decode(transp); 3951558Srgrimes return; 3961558Srgrimes } 3971558Srgrimes 3981558Srgrimes /* 3991558Srgrimes * Get the real pathname and make sure it is a directory 4009336Sdfr * or a regular file if the -r option was specified 4019336Sdfr * and it exists. 4021558Srgrimes */ 40351968Salfred if (realpath(rpcpath, dirpath) == NULL || 4041558Srgrimes stat(dirpath, &stb) < 0 || 4059336Sdfr (!S_ISDIR(stb.st_mode) && 4069336Sdfr (dir_only || !S_ISREG(stb.st_mode))) || 4071558Srgrimes statfs(dirpath, &fsb) < 0) { 4081558Srgrimes chdir("/"); /* Just in case realpath doesn't */ 40931656Sguido syslog(LOG_NOTICE, 41037663Scharnier "mount request from %s for non existent path %s", 41131656Sguido inet_ntoa(saddrin), dirpath); 4121558Srgrimes if (debug) 41337663Scharnier warnx("stat failed on %s", dirpath); 41428911Sguido bad = ENOENT; /* We will send error reply later */ 4151558Srgrimes } 4161558Srgrimes 4171558Srgrimes /* Check in the exports list */ 4189336Sdfr sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 4191558Srgrimes ep = ex_search(&fsb.f_fsid); 4209336Sdfr hostset = defset = 0; 4219336Sdfr if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) || 4221558Srgrimes ((dp = dirp_search(ep->ex_dirl, dirpath)) && 4239336Sdfr chk_host(dp, saddr, &defset, &hostset)) || 4241558Srgrimes (defset && scan_tree(ep->ex_defdir, saddr) == 0 && 4251558Srgrimes scan_tree(ep->ex_dirl, saddr) == 0))) { 42628911Sguido if (bad) { 42728911Sguido if (!svc_sendreply(transp, xdr_long, 42828911Sguido (caddr_t)&bad)) 42937663Scharnier syslog(LOG_ERR, "can't send reply"); 43028911Sguido sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 43128911Sguido return; 43228911Sguido } 4339336Sdfr if (hostset & DP_HOSTSET) 4349336Sdfr fhr.fhr_flag = hostset; 4359336Sdfr else 4369336Sdfr fhr.fhr_flag = defset; 4379336Sdfr fhr.fhr_vers = rqstp->rq_vers; 4381558Srgrimes /* Get the file handle */ 43923681Speter memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t)); 4409336Sdfr if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) { 4411558Srgrimes bad = errno; 44237663Scharnier syslog(LOG_ERR, "can't get fh for %s", dirpath); 4431558Srgrimes if (!svc_sendreply(transp, xdr_long, 4441558Srgrimes (caddr_t)&bad)) 44537663Scharnier syslog(LOG_ERR, "can't send reply"); 4469336Sdfr sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 4471558Srgrimes return; 4481558Srgrimes } 4499336Sdfr if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr)) 45037663Scharnier syslog(LOG_ERR, "can't send reply"); 4511558Srgrimes if (hp == NULL) 4521558Srgrimes hp = gethostbyaddr((caddr_t)&saddr, 4531558Srgrimes sizeof(saddr), AF_INET); 4541558Srgrimes if (hp) 4551558Srgrimes add_mlist(hp->h_name, dirpath); 4561558Srgrimes else 45731656Sguido add_mlist(inet_ntoa(saddrin), 4581558Srgrimes dirpath); 4591558Srgrimes if (debug) 46037663Scharnier warnx("mount successful"); 46131656Sguido if (log) 46231656Sguido syslog(LOG_NOTICE, 46331656Sguido "mount request succeeded from %s for %s", 46431656Sguido inet_ntoa(saddrin), dirpath); 46531656Sguido } else { 4661558Srgrimes bad = EACCES; 46731656Sguido syslog(LOG_NOTICE, 46831656Sguido "mount request denied from %s for %s", 46931656Sguido inet_ntoa(saddrin), dirpath); 47031656Sguido } 47128911Sguido 47228911Sguido if (bad && !svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 47337663Scharnier syslog(LOG_ERR, "can't send reply"); 4749336Sdfr sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 4751558Srgrimes return; 4761558Srgrimes case RPCMNT_DUMP: 4771558Srgrimes if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL)) 47837663Scharnier syslog(LOG_ERR, "can't send reply"); 47931656Sguido else if (log) 48031656Sguido syslog(LOG_NOTICE, 48131656Sguido "dump request succeeded from %s", 48238023Sbde inet_ntoa(saddrin)); 4831558Srgrimes return; 4841558Srgrimes case RPCMNT_UMOUNT: 4859336Sdfr if (sport >= IPPORT_RESERVED && resvport_only) { 48631656Sguido syslog(LOG_NOTICE, 48731656Sguido "umount request from %s from unprivileged port", 48831656Sguido inet_ntoa(saddrin)); 4891558Srgrimes svcerr_weakauth(transp); 4901558Srgrimes return; 4911558Srgrimes } 49251968Salfred if (!svc_getargs(transp, xdr_dir, rpcpath)) { 49331656Sguido syslog(LOG_NOTICE, "undecodable umount request from %s", 49431656Sguido inet_ntoa(saddrin)); 4951558Srgrimes svcerr_decode(transp); 4961558Srgrimes return; 4971558Srgrimes } 49851968Salfred if (realpath(rpcpath, dirpath) == NULL) { 49951968Salfred syslog(LOG_NOTICE, "umount request from %s " 50051968Salfred "for non existent path %s", 50151968Salfred inet_ntoa(saddrin), dirpath); 50251968Salfred } 5031558Srgrimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 50437663Scharnier syslog(LOG_ERR, "can't send reply"); 5051558Srgrimes hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 5061558Srgrimes if (hp) 5071558Srgrimes del_mlist(hp->h_name, dirpath); 50831656Sguido del_mlist(inet_ntoa(saddrin), dirpath); 50931656Sguido if (log) 51031656Sguido syslog(LOG_NOTICE, 51131656Sguido "umount request succeeded from %s for %s", 51231656Sguido inet_ntoa(saddrin), dirpath); 5131558Srgrimes return; 5141558Srgrimes case RPCMNT_UMNTALL: 5159336Sdfr if (sport >= IPPORT_RESERVED && resvport_only) { 51631656Sguido syslog(LOG_NOTICE, 51731656Sguido "umountall request from %s from unprivileged port", 51831656Sguido inet_ntoa(saddrin)); 5191558Srgrimes svcerr_weakauth(transp); 5201558Srgrimes return; 5211558Srgrimes } 5221558Srgrimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 52337663Scharnier syslog(LOG_ERR, "can't send reply"); 5241558Srgrimes hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 5251558Srgrimes if (hp) 5261558Srgrimes del_mlist(hp->h_name, (char *)NULL); 52731656Sguido del_mlist(inet_ntoa(saddrin), (char *)NULL); 52831656Sguido if (log) 52931656Sguido syslog(LOG_NOTICE, 53031656Sguido "umountall request succeeded from %s", 53131656Sguido inet_ntoa(saddrin)); 5321558Srgrimes return; 5331558Srgrimes case RPCMNT_EXPORT: 5341558Srgrimes if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL)) 53537663Scharnier syslog(LOG_ERR, "can't send reply"); 53631656Sguido if (log) 53731656Sguido syslog(LOG_NOTICE, 53831656Sguido "export request succeeded from %s", 53931656Sguido inet_ntoa(saddrin)); 5401558Srgrimes return; 5411558Srgrimes default: 5421558Srgrimes svcerr_noproc(transp); 5431558Srgrimes return; 5441558Srgrimes } 5451558Srgrimes} 5461558Srgrimes 5471558Srgrimes/* 5481558Srgrimes * Xdr conversion for a dirpath string 5491558Srgrimes */ 5501558Srgrimesint 5511558Srgrimesxdr_dir(xdrsp, dirp) 5521558Srgrimes XDR *xdrsp; 5531558Srgrimes char *dirp; 5541558Srgrimes{ 5551558Srgrimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 5561558Srgrimes} 5571558Srgrimes 5581558Srgrimes/* 5599336Sdfr * Xdr routine to generate file handle reply 5601558Srgrimes */ 5611558Srgrimesint 5629336Sdfrxdr_fhs(xdrsp, cp) 5631558Srgrimes XDR *xdrsp; 5649336Sdfr caddr_t cp; 5651558Srgrimes{ 5669336Sdfr register struct fhreturn *fhrp = (struct fhreturn *)cp; 5679336Sdfr u_long ok = 0, len, auth; 5681558Srgrimes 5691558Srgrimes if (!xdr_long(xdrsp, &ok)) 5701558Srgrimes return (0); 5719336Sdfr switch (fhrp->fhr_vers) { 5729336Sdfr case 1: 5739336Sdfr return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH)); 5749336Sdfr case 3: 5759336Sdfr len = NFSX_V3FH; 5769336Sdfr if (!xdr_long(xdrsp, &len)) 5779336Sdfr return (0); 5789336Sdfr if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) 5799336Sdfr return (0); 5809336Sdfr if (fhrp->fhr_flag & DP_KERB) 5819336Sdfr auth = RPCAUTH_KERB4; 5829336Sdfr else 5839336Sdfr auth = RPCAUTH_UNIX; 5849336Sdfr len = 1; 5859336Sdfr if (!xdr_long(xdrsp, &len)) 5869336Sdfr return (0); 5879336Sdfr return (xdr_long(xdrsp, &auth)); 5889336Sdfr }; 5899336Sdfr return (0); 5901558Srgrimes} 5911558Srgrimes 5921558Srgrimesint 5931558Srgrimesxdr_mlist(xdrsp, cp) 5941558Srgrimes XDR *xdrsp; 5951558Srgrimes caddr_t cp; 5961558Srgrimes{ 5971558Srgrimes struct mountlist *mlp; 5981558Srgrimes int true = 1; 5991558Srgrimes int false = 0; 6001558Srgrimes char *strp; 6011558Srgrimes 6021558Srgrimes mlp = mlhead; 6031558Srgrimes while (mlp) { 6041558Srgrimes if (!xdr_bool(xdrsp, &true)) 6051558Srgrimes return (0); 6061558Srgrimes strp = &mlp->ml_host[0]; 6071558Srgrimes if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 6081558Srgrimes return (0); 6091558Srgrimes strp = &mlp->ml_dirp[0]; 6101558Srgrimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 6111558Srgrimes return (0); 6121558Srgrimes mlp = mlp->ml_next; 6131558Srgrimes } 6141558Srgrimes if (!xdr_bool(xdrsp, &false)) 6151558Srgrimes return (0); 6161558Srgrimes return (1); 6171558Srgrimes} 6181558Srgrimes 6191558Srgrimes/* 6201558Srgrimes * Xdr conversion for export list 6211558Srgrimes */ 6221558Srgrimesint 6231558Srgrimesxdr_explist(xdrsp, cp) 6241558Srgrimes XDR *xdrsp; 6251558Srgrimes caddr_t cp; 6261558Srgrimes{ 6271558Srgrimes struct exportlist *ep; 6281558Srgrimes int false = 0; 6299336Sdfr int putdef; 6309336Sdfr sigset_t sighup_mask; 6311558Srgrimes 6329336Sdfr sigemptyset(&sighup_mask); 6339336Sdfr sigaddset(&sighup_mask, SIGHUP); 6349336Sdfr sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 6351558Srgrimes ep = exphead; 6361558Srgrimes while (ep) { 6371558Srgrimes putdef = 0; 6381558Srgrimes if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, &putdef)) 6391558Srgrimes goto errout; 6401558Srgrimes if (ep->ex_defdir && putdef == 0 && 6411558Srgrimes put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL, 6421558Srgrimes &putdef)) 6431558Srgrimes goto errout; 6441558Srgrimes ep = ep->ex_next; 6451558Srgrimes } 6469336Sdfr sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6471558Srgrimes if (!xdr_bool(xdrsp, &false)) 6481558Srgrimes return (0); 6491558Srgrimes return (1); 6501558Srgrimeserrout: 6519336Sdfr sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6521558Srgrimes return (0); 6531558Srgrimes} 6541558Srgrimes 6551558Srgrimes/* 6561558Srgrimes * Called from xdr_explist() to traverse the tree and export the 6571558Srgrimes * directory paths. 6581558Srgrimes */ 6591558Srgrimesint 6601558Srgrimesput_exlist(dp, xdrsp, adp, putdefp) 6611558Srgrimes struct dirlist *dp; 6621558Srgrimes XDR *xdrsp; 6631558Srgrimes struct dirlist *adp; 6641558Srgrimes int *putdefp; 6651558Srgrimes{ 6661558Srgrimes struct grouplist *grp; 6671558Srgrimes struct hostlist *hp; 6681558Srgrimes int true = 1; 6691558Srgrimes int false = 0; 6701558Srgrimes int gotalldir = 0; 6711558Srgrimes char *strp; 6721558Srgrimes 6731558Srgrimes if (dp) { 6741558Srgrimes if (put_exlist(dp->dp_left, xdrsp, adp, putdefp)) 6751558Srgrimes return (1); 6761558Srgrimes if (!xdr_bool(xdrsp, &true)) 6771558Srgrimes return (1); 6781558Srgrimes strp = dp->dp_dirp; 6791558Srgrimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 6801558Srgrimes return (1); 6811558Srgrimes if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) { 6821558Srgrimes gotalldir = 1; 6831558Srgrimes *putdefp = 1; 6841558Srgrimes } 6851558Srgrimes if ((dp->dp_flag & DP_DEFSET) == 0 && 6861558Srgrimes (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) { 6871558Srgrimes hp = dp->dp_hosts; 6881558Srgrimes while (hp) { 6891558Srgrimes grp = hp->ht_grp; 6901558Srgrimes if (grp->gr_type == GT_HOST) { 6911558Srgrimes if (!xdr_bool(xdrsp, &true)) 6921558Srgrimes return (1); 6931558Srgrimes strp = grp->gr_ptr.gt_hostent->h_name; 6948871Srgrimes if (!xdr_string(xdrsp, &strp, 6951558Srgrimes RPCMNT_NAMELEN)) 6961558Srgrimes return (1); 6971558Srgrimes } else if (grp->gr_type == GT_NET) { 6981558Srgrimes if (!xdr_bool(xdrsp, &true)) 6991558Srgrimes return (1); 7001558Srgrimes strp = grp->gr_ptr.gt_net.nt_name; 7018871Srgrimes if (!xdr_string(xdrsp, &strp, 7021558Srgrimes RPCMNT_NAMELEN)) 7031558Srgrimes return (1); 7041558Srgrimes } 7051558Srgrimes hp = hp->ht_next; 7061558Srgrimes if (gotalldir && hp == (struct hostlist *)NULL) { 7071558Srgrimes hp = adp->dp_hosts; 7081558Srgrimes gotalldir = 0; 7091558Srgrimes } 7101558Srgrimes } 7111558Srgrimes } 7121558Srgrimes if (!xdr_bool(xdrsp, &false)) 7131558Srgrimes return (1); 7141558Srgrimes if (put_exlist(dp->dp_right, xdrsp, adp, putdefp)) 7151558Srgrimes return (1); 7161558Srgrimes } 7171558Srgrimes return (0); 7181558Srgrimes} 7191558Srgrimes 7201558Srgrimes#define LINESIZ 10240 7211558Srgrimeschar line[LINESIZ]; 7221558SrgrimesFILE *exp_file; 7231558Srgrimes 7241558Srgrimes/* 7251558Srgrimes * Get the export list 7261558Srgrimes */ 7271558Srgrimesvoid 7281558Srgrimesget_exportlist() 7291558Srgrimes{ 7301558Srgrimes struct exportlist *ep, *ep2; 7311558Srgrimes struct grouplist *grp, *tgrp; 7321558Srgrimes struct exportlist **epp; 7331558Srgrimes struct dirlist *dirhead; 7341558Srgrimes struct statfs fsb, *fsp; 7351558Srgrimes struct hostent *hpe; 73672650Sgreen struct xucred anon; 7371558Srgrimes char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; 7381558Srgrimes int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp; 7391558Srgrimes 74051968Salfred dirp = NULL; 74151968Salfred dirplen = 0; 74251968Salfred 7431558Srgrimes /* 7441558Srgrimes * First, get rid of the old list 7451558Srgrimes */ 7461558Srgrimes ep = exphead; 7471558Srgrimes while (ep) { 7481558Srgrimes ep2 = ep; 7491558Srgrimes ep = ep->ex_next; 7501558Srgrimes free_exp(ep2); 7511558Srgrimes } 7521558Srgrimes exphead = (struct exportlist *)NULL; 7531558Srgrimes 7541558Srgrimes grp = grphead; 7551558Srgrimes while (grp) { 7561558Srgrimes tgrp = grp; 7571558Srgrimes grp = grp->gr_next; 7581558Srgrimes free_grp(tgrp); 7591558Srgrimes } 7601558Srgrimes grphead = (struct grouplist *)NULL; 7611558Srgrimes 7621558Srgrimes /* 7631558Srgrimes * And delete exports that are in the kernel for all local 7641558Srgrimes * file systems. 7651558Srgrimes * XXX: Should know how to handle all local exportable file systems 76623681Speter * instead of just "ufs". 7671558Srgrimes */ 7681558Srgrimes num = getmntinfo(&fsp, MNT_NOWAIT); 7691558Srgrimes for (i = 0; i < num; i++) { 7701558Srgrimes union { 7711558Srgrimes struct ufs_args ua; 7721558Srgrimes struct iso_args ia; 7731558Srgrimes struct mfs_args ma; 7749336Sdfr struct msdosfs_args da; 77554093Ssemenu struct ntfs_args na; 7761558Srgrimes } targs; 7771558Srgrimes 77823681Speter if (!strcmp(fsp->f_fstypename, "mfs") || 77923681Speter !strcmp(fsp->f_fstypename, "ufs") || 78023681Speter !strcmp(fsp->f_fstypename, "msdos") || 78154093Ssemenu !strcmp(fsp->f_fstypename, "ntfs") || 78223681Speter !strcmp(fsp->f_fstypename, "cd9660")) { 7839336Sdfr targs.ua.fspec = NULL; 7849336Sdfr targs.ua.export.ex_flags = MNT_DELEXPORT; 7859336Sdfr if (mount(fsp->f_fstypename, fsp->f_mntonname, 7861558Srgrimes fsp->f_flags | MNT_UPDATE, 7871558Srgrimes (caddr_t)&targs) < 0) 78837663Scharnier syslog(LOG_ERR, "can't delete exports for %s", 7891558Srgrimes fsp->f_mntonname); 7901558Srgrimes } 7911558Srgrimes fsp++; 7921558Srgrimes } 7931558Srgrimes 7941558Srgrimes /* 7951558Srgrimes * Read in the exports file and build the list, calling 7961558Srgrimes * mount() as we go along to push the export rules into the kernel. 7971558Srgrimes */ 7981558Srgrimes if ((exp_file = fopen(exname, "r")) == NULL) { 79937663Scharnier syslog(LOG_ERR, "can't open %s", exname); 8001558Srgrimes exit(2); 8011558Srgrimes } 8021558Srgrimes dirhead = (struct dirlist *)NULL; 8031558Srgrimes while (get_line()) { 8041558Srgrimes if (debug) 80537663Scharnier warnx("got line %s", line); 8061558Srgrimes cp = line; 8071558Srgrimes nextfield(&cp, &endcp); 8081558Srgrimes if (*cp == '#') 8091558Srgrimes goto nextline; 8101558Srgrimes 8111558Srgrimes /* 8121558Srgrimes * Set defaults. 8131558Srgrimes */ 8141558Srgrimes has_host = FALSE; 8151558Srgrimes anon = def_anon; 8161558Srgrimes exflags = MNT_EXPORTED; 8171558Srgrimes got_nondir = 0; 8181558Srgrimes opt_flags = 0; 8191558Srgrimes ep = (struct exportlist *)NULL; 8201558Srgrimes 8211558Srgrimes /* 8221558Srgrimes * Create new exports list entry 8231558Srgrimes */ 8241558Srgrimes len = endcp-cp; 8251558Srgrimes tgrp = grp = get_grp(); 8261558Srgrimes while (len > 0) { 8271558Srgrimes if (len > RPCMNT_NAMELEN) { 8281558Srgrimes getexp_err(ep, tgrp); 8291558Srgrimes goto nextline; 8301558Srgrimes } 8311558Srgrimes if (*cp == '-') { 8321558Srgrimes if (ep == (struct exportlist *)NULL) { 8331558Srgrimes getexp_err(ep, tgrp); 8341558Srgrimes goto nextline; 8351558Srgrimes } 8361558Srgrimes if (debug) 83737663Scharnier warnx("doing opt %s", cp); 8381558Srgrimes got_nondir = 1; 8391558Srgrimes if (do_opt(&cp, &endcp, ep, grp, &has_host, 8401558Srgrimes &exflags, &anon)) { 8411558Srgrimes getexp_err(ep, tgrp); 8421558Srgrimes goto nextline; 8431558Srgrimes } 8441558Srgrimes } else if (*cp == '/') { 8451558Srgrimes savedc = *endcp; 8461558Srgrimes *endcp = '\0'; 8471558Srgrimes if (check_dirpath(cp) && 8481558Srgrimes statfs(cp, &fsb) >= 0) { 8491558Srgrimes if (got_nondir) { 85037663Scharnier syslog(LOG_ERR, "dirs must be first"); 8511558Srgrimes getexp_err(ep, tgrp); 8521558Srgrimes goto nextline; 8531558Srgrimes } 8541558Srgrimes if (ep) { 8551558Srgrimes if (ep->ex_fs.val[0] != fsb.f_fsid.val[0] || 8561558Srgrimes ep->ex_fs.val[1] != fsb.f_fsid.val[1]) { 8571558Srgrimes getexp_err(ep, tgrp); 8581558Srgrimes goto nextline; 8591558Srgrimes } 8601558Srgrimes } else { 8611558Srgrimes /* 8621558Srgrimes * See if this directory is already 8631558Srgrimes * in the list. 8641558Srgrimes */ 8651558Srgrimes ep = ex_search(&fsb.f_fsid); 8661558Srgrimes if (ep == (struct exportlist *)NULL) { 8671558Srgrimes ep = get_exp(); 8681558Srgrimes ep->ex_fs = fsb.f_fsid; 8691558Srgrimes ep->ex_fsdir = (char *) 8701558Srgrimes malloc(strlen(fsb.f_mntonname) + 1); 8711558Srgrimes if (ep->ex_fsdir) 8721558Srgrimes strcpy(ep->ex_fsdir, 8731558Srgrimes fsb.f_mntonname); 8741558Srgrimes else 8751558Srgrimes out_of_mem(); 8761558Srgrimes if (debug) 87737663Scharnier warnx("making new ep fs=0x%x,0x%x", 8781558Srgrimes fsb.f_fsid.val[0], 8791558Srgrimes fsb.f_fsid.val[1]); 8801558Srgrimes } else if (debug) 88137663Scharnier warnx("found ep fs=0x%x,0x%x", 8821558Srgrimes fsb.f_fsid.val[0], 8831558Srgrimes fsb.f_fsid.val[1]); 8841558Srgrimes } 8851558Srgrimes 8861558Srgrimes /* 8871558Srgrimes * Add dirpath to export mount point. 8881558Srgrimes */ 8891558Srgrimes dirp = add_expdir(&dirhead, cp, len); 8901558Srgrimes dirplen = len; 8911558Srgrimes } else { 8921558Srgrimes getexp_err(ep, tgrp); 8931558Srgrimes goto nextline; 8941558Srgrimes } 8951558Srgrimes *endcp = savedc; 8961558Srgrimes } else { 8971558Srgrimes savedc = *endcp; 8981558Srgrimes *endcp = '\0'; 8991558Srgrimes got_nondir = 1; 9001558Srgrimes if (ep == (struct exportlist *)NULL) { 9011558Srgrimes getexp_err(ep, tgrp); 9021558Srgrimes goto nextline; 9031558Srgrimes } 9041558Srgrimes 9051558Srgrimes /* 9061558Srgrimes * Get the host or netgroup. 9071558Srgrimes */ 9081558Srgrimes setnetgrent(cp); 9091558Srgrimes netgrp = getnetgrent(&hst, &usr, &dom); 9101558Srgrimes do { 9111558Srgrimes if (has_host) { 9121558Srgrimes grp->gr_next = get_grp(); 9131558Srgrimes grp = grp->gr_next; 9141558Srgrimes } 9151558Srgrimes if (netgrp) { 91637003Sjoerg if (hst == 0) { 91737663Scharnier syslog(LOG_ERR, 91837663Scharnier "null hostname in netgroup %s, skipping", cp); 91937004Sjoerg grp->gr_type = GT_IGNORE; 92037003Sjoerg } else if (get_host(hst, grp, tgrp)) { 92137663Scharnier syslog(LOG_ERR, 92237663Scharnier "bad host %s in netgroup %s, skipping", hst, cp); 92329317Sjlemon grp->gr_type = GT_IGNORE; 9241558Srgrimes } 9257401Swpaul } else if (get_host(cp, grp, tgrp)) { 92637663Scharnier syslog(LOG_ERR, "bad host %s, skipping", cp); 92729317Sjlemon grp->gr_type = GT_IGNORE; 9281558Srgrimes } 9291558Srgrimes has_host = TRUE; 9301558Srgrimes } while (netgrp && getnetgrent(&hst, &usr, &dom)); 9311558Srgrimes endnetgrent(); 9321558Srgrimes *endcp = savedc; 9331558Srgrimes } 9341558Srgrimes cp = endcp; 9351558Srgrimes nextfield(&cp, &endcp); 9361558Srgrimes len = endcp - cp; 9371558Srgrimes } 9381558Srgrimes if (check_options(dirhead)) { 9391558Srgrimes getexp_err(ep, tgrp); 9401558Srgrimes goto nextline; 9411558Srgrimes } 9421558Srgrimes if (!has_host) { 9431558Srgrimes grp->gr_type = GT_HOST; 9441558Srgrimes if (debug) 94537663Scharnier warnx("adding a default entry"); 9461558Srgrimes /* add a default group and make the grp list NULL */ 9471558Srgrimes hpe = (struct hostent *)malloc(sizeof(struct hostent)); 9481558Srgrimes if (hpe == (struct hostent *)NULL) 9491558Srgrimes out_of_mem(); 95012348Sjoerg hpe->h_name = strdup("Default"); 9511558Srgrimes hpe->h_addrtype = AF_INET; 95242144Sdfr hpe->h_length = sizeof (u_int32_t); 9531558Srgrimes hpe->h_addr_list = (char **)NULL; 9541558Srgrimes grp->gr_ptr.gt_hostent = hpe; 9551558Srgrimes 9561558Srgrimes /* 9571558Srgrimes * Don't allow a network export coincide with a list of 9581558Srgrimes * host(s) on the same line. 9591558Srgrimes */ 9601558Srgrimes } else if ((opt_flags & OP_NET) && tgrp->gr_next) { 9611558Srgrimes getexp_err(ep, tgrp); 9621558Srgrimes goto nextline; 96329317Sjlemon 96429317Sjlemon /* 96529317Sjlemon * If an export list was specified on this line, make sure 96629317Sjlemon * that we have at least one valid entry, otherwise skip it. 96729317Sjlemon */ 96829317Sjlemon } else { 96929317Sjlemon grp = tgrp; 97029317Sjlemon while (grp && grp->gr_type == GT_IGNORE) 97129317Sjlemon grp = grp->gr_next; 97229317Sjlemon if (! grp) { 97329317Sjlemon getexp_err(ep, tgrp); 97429317Sjlemon goto nextline; 97529317Sjlemon } 9761558Srgrimes } 9771558Srgrimes 9781558Srgrimes /* 9791558Srgrimes * Loop through hosts, pushing the exports into the kernel. 9801558Srgrimes * After loop, tgrp points to the start of the list and 9811558Srgrimes * grp points to the last entry in the list. 9821558Srgrimes */ 9831558Srgrimes grp = tgrp; 9841558Srgrimes do { 9851558Srgrimes if (do_mount(ep, grp, exflags, &anon, dirp, 9861558Srgrimes dirplen, &fsb)) { 9871558Srgrimes getexp_err(ep, tgrp); 9881558Srgrimes goto nextline; 9891558Srgrimes } 9901558Srgrimes } while (grp->gr_next && (grp = grp->gr_next)); 9911558Srgrimes 9921558Srgrimes /* 9931558Srgrimes * Success. Update the data structures. 9941558Srgrimes */ 9951558Srgrimes if (has_host) { 9969336Sdfr hang_dirp(dirhead, tgrp, ep, opt_flags); 9971558Srgrimes grp->gr_next = grphead; 9981558Srgrimes grphead = tgrp; 9991558Srgrimes } else { 10001558Srgrimes hang_dirp(dirhead, (struct grouplist *)NULL, ep, 10019336Sdfr opt_flags); 10021558Srgrimes free_grp(grp); 10031558Srgrimes } 10041558Srgrimes dirhead = (struct dirlist *)NULL; 10051558Srgrimes if ((ep->ex_flag & EX_LINKED) == 0) { 10061558Srgrimes ep2 = exphead; 10071558Srgrimes epp = &exphead; 10081558Srgrimes 10091558Srgrimes /* 10101558Srgrimes * Insert in the list in alphabetical order. 10111558Srgrimes */ 10121558Srgrimes while (ep2 && strcmp(ep2->ex_fsdir, ep->ex_fsdir) < 0) { 10131558Srgrimes epp = &ep2->ex_next; 10141558Srgrimes ep2 = ep2->ex_next; 10151558Srgrimes } 10161558Srgrimes if (ep2) 10171558Srgrimes ep->ex_next = ep2; 10181558Srgrimes *epp = ep; 10191558Srgrimes ep->ex_flag |= EX_LINKED; 10201558Srgrimes } 10211558Srgrimesnextline: 10221558Srgrimes if (dirhead) { 10231558Srgrimes free_dir(dirhead); 10241558Srgrimes dirhead = (struct dirlist *)NULL; 10251558Srgrimes } 10261558Srgrimes } 10271558Srgrimes fclose(exp_file); 10281558Srgrimes} 10291558Srgrimes 10301558Srgrimes/* 10311558Srgrimes * Allocate an export list element 10321558Srgrimes */ 10331558Srgrimesstruct exportlist * 10341558Srgrimesget_exp() 10351558Srgrimes{ 10361558Srgrimes struct exportlist *ep; 10371558Srgrimes 10381558Srgrimes ep = (struct exportlist *)malloc(sizeof (struct exportlist)); 10391558Srgrimes if (ep == (struct exportlist *)NULL) 10401558Srgrimes out_of_mem(); 104123681Speter memset(ep, 0, sizeof(struct exportlist)); 10421558Srgrimes return (ep); 10431558Srgrimes} 10441558Srgrimes 10451558Srgrimes/* 10461558Srgrimes * Allocate a group list element 10471558Srgrimes */ 10481558Srgrimesstruct grouplist * 10491558Srgrimesget_grp() 10501558Srgrimes{ 10511558Srgrimes struct grouplist *gp; 10521558Srgrimes 10531558Srgrimes gp = (struct grouplist *)malloc(sizeof (struct grouplist)); 10541558Srgrimes if (gp == (struct grouplist *)NULL) 10551558Srgrimes out_of_mem(); 105623681Speter memset(gp, 0, sizeof(struct grouplist)); 10571558Srgrimes return (gp); 10581558Srgrimes} 10591558Srgrimes 10601558Srgrimes/* 10611558Srgrimes * Clean up upon an error in get_exportlist(). 10621558Srgrimes */ 10631558Srgrimesvoid 10641558Srgrimesgetexp_err(ep, grp) 10651558Srgrimes struct exportlist *ep; 10661558Srgrimes struct grouplist *grp; 10671558Srgrimes{ 10681558Srgrimes struct grouplist *tgrp; 10691558Srgrimes 107037663Scharnier syslog(LOG_ERR, "bad exports list line %s", line); 10711558Srgrimes if (ep && (ep->ex_flag & EX_LINKED) == 0) 10721558Srgrimes free_exp(ep); 10731558Srgrimes while (grp) { 10741558Srgrimes tgrp = grp; 10751558Srgrimes grp = grp->gr_next; 10761558Srgrimes free_grp(tgrp); 10771558Srgrimes } 10781558Srgrimes} 10791558Srgrimes 10801558Srgrimes/* 10811558Srgrimes * Search the export list for a matching fs. 10821558Srgrimes */ 10831558Srgrimesstruct exportlist * 10841558Srgrimesex_search(fsid) 10851558Srgrimes fsid_t *fsid; 10861558Srgrimes{ 10871558Srgrimes struct exportlist *ep; 10881558Srgrimes 10891558Srgrimes ep = exphead; 10901558Srgrimes while (ep) { 10911558Srgrimes if (ep->ex_fs.val[0] == fsid->val[0] && 10921558Srgrimes ep->ex_fs.val[1] == fsid->val[1]) 10931558Srgrimes return (ep); 10941558Srgrimes ep = ep->ex_next; 10951558Srgrimes } 10961558Srgrimes return (ep); 10971558Srgrimes} 10981558Srgrimes 10991558Srgrimes/* 11001558Srgrimes * Add a directory path to the list. 11011558Srgrimes */ 11021558Srgrimeschar * 11031558Srgrimesadd_expdir(dpp, cp, len) 11041558Srgrimes struct dirlist **dpp; 11051558Srgrimes char *cp; 11061558Srgrimes int len; 11071558Srgrimes{ 11081558Srgrimes struct dirlist *dp; 11091558Srgrimes 11101558Srgrimes dp = (struct dirlist *)malloc(sizeof (struct dirlist) + len); 111137663Scharnier if (dp == (struct dirlist *)NULL) 111237663Scharnier out_of_mem(); 11131558Srgrimes dp->dp_left = *dpp; 11141558Srgrimes dp->dp_right = (struct dirlist *)NULL; 11151558Srgrimes dp->dp_flag = 0; 11161558Srgrimes dp->dp_hosts = (struct hostlist *)NULL; 11171558Srgrimes strcpy(dp->dp_dirp, cp); 11181558Srgrimes *dpp = dp; 11191558Srgrimes return (dp->dp_dirp); 11201558Srgrimes} 11211558Srgrimes 11221558Srgrimes/* 11231558Srgrimes * Hang the dir list element off the dirpath binary tree as required 11241558Srgrimes * and update the entry for host. 11251558Srgrimes */ 11261558Srgrimesvoid 11279336Sdfrhang_dirp(dp, grp, ep, flags) 11281558Srgrimes struct dirlist *dp; 11291558Srgrimes struct grouplist *grp; 11301558Srgrimes struct exportlist *ep; 11319336Sdfr int flags; 11321558Srgrimes{ 11331558Srgrimes struct hostlist *hp; 11341558Srgrimes struct dirlist *dp2; 11351558Srgrimes 11369336Sdfr if (flags & OP_ALLDIRS) { 11371558Srgrimes if (ep->ex_defdir) 11381558Srgrimes free((caddr_t)dp); 11391558Srgrimes else 11401558Srgrimes ep->ex_defdir = dp; 11419336Sdfr if (grp == (struct grouplist *)NULL) { 11421558Srgrimes ep->ex_defdir->dp_flag |= DP_DEFSET; 11439336Sdfr if (flags & OP_KERB) 11449336Sdfr ep->ex_defdir->dp_flag |= DP_KERB; 11459336Sdfr } else while (grp) { 11461558Srgrimes hp = get_ht(); 11479336Sdfr if (flags & OP_KERB) 11489336Sdfr hp->ht_flag |= DP_KERB; 11491558Srgrimes hp->ht_grp = grp; 11501558Srgrimes hp->ht_next = ep->ex_defdir->dp_hosts; 11511558Srgrimes ep->ex_defdir->dp_hosts = hp; 11521558Srgrimes grp = grp->gr_next; 11531558Srgrimes } 11541558Srgrimes } else { 11551558Srgrimes 11561558Srgrimes /* 115737663Scharnier * Loop through the directories adding them to the tree. 11581558Srgrimes */ 11591558Srgrimes while (dp) { 11601558Srgrimes dp2 = dp->dp_left; 11619336Sdfr add_dlist(&ep->ex_dirl, dp, grp, flags); 11621558Srgrimes dp = dp2; 11631558Srgrimes } 11641558Srgrimes } 11651558Srgrimes} 11661558Srgrimes 11671558Srgrimes/* 11681558Srgrimes * Traverse the binary tree either updating a node that is already there 11691558Srgrimes * for the new directory or adding the new node. 11701558Srgrimes */ 11711558Srgrimesvoid 11729336Sdfradd_dlist(dpp, newdp, grp, flags) 11731558Srgrimes struct dirlist **dpp; 11741558Srgrimes struct dirlist *newdp; 11751558Srgrimes struct grouplist *grp; 11769336Sdfr int flags; 11771558Srgrimes{ 11781558Srgrimes struct dirlist *dp; 11791558Srgrimes struct hostlist *hp; 11801558Srgrimes int cmp; 11811558Srgrimes 11821558Srgrimes dp = *dpp; 11831558Srgrimes if (dp) { 11841558Srgrimes cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); 11851558Srgrimes if (cmp > 0) { 11869336Sdfr add_dlist(&dp->dp_left, newdp, grp, flags); 11871558Srgrimes return; 11881558Srgrimes } else if (cmp < 0) { 11899336Sdfr add_dlist(&dp->dp_right, newdp, grp, flags); 11901558Srgrimes return; 11911558Srgrimes } else 11921558Srgrimes free((caddr_t)newdp); 11931558Srgrimes } else { 11941558Srgrimes dp = newdp; 11951558Srgrimes dp->dp_left = (struct dirlist *)NULL; 11961558Srgrimes *dpp = dp; 11971558Srgrimes } 11981558Srgrimes if (grp) { 11991558Srgrimes 12001558Srgrimes /* 12011558Srgrimes * Hang all of the host(s) off of the directory point. 12021558Srgrimes */ 12031558Srgrimes do { 12041558Srgrimes hp = get_ht(); 12059336Sdfr if (flags & OP_KERB) 12069336Sdfr hp->ht_flag |= DP_KERB; 12071558Srgrimes hp->ht_grp = grp; 12081558Srgrimes hp->ht_next = dp->dp_hosts; 12091558Srgrimes dp->dp_hosts = hp; 12101558Srgrimes grp = grp->gr_next; 12111558Srgrimes } while (grp); 12129336Sdfr } else { 12131558Srgrimes dp->dp_flag |= DP_DEFSET; 12149336Sdfr if (flags & OP_KERB) 12159336Sdfr dp->dp_flag |= DP_KERB; 12169336Sdfr } 12171558Srgrimes} 12181558Srgrimes 12191558Srgrimes/* 12201558Srgrimes * Search for a dirpath on the export point. 12211558Srgrimes */ 12221558Srgrimesstruct dirlist * 12231558Srgrimesdirp_search(dp, dirpath) 12241558Srgrimes struct dirlist *dp; 12251558Srgrimes char *dirpath; 12261558Srgrimes{ 12271558Srgrimes int cmp; 12281558Srgrimes 12291558Srgrimes if (dp) { 12301558Srgrimes cmp = strcmp(dp->dp_dirp, dirpath); 12311558Srgrimes if (cmp > 0) 12321558Srgrimes return (dirp_search(dp->dp_left, dirpath)); 12331558Srgrimes else if (cmp < 0) 12341558Srgrimes return (dirp_search(dp->dp_right, dirpath)); 12351558Srgrimes else 12361558Srgrimes return (dp); 12371558Srgrimes } 12381558Srgrimes return (dp); 12391558Srgrimes} 12401558Srgrimes 12411558Srgrimes/* 12421558Srgrimes * Scan for a host match in a directory tree. 12431558Srgrimes */ 12441558Srgrimesint 12459336Sdfrchk_host(dp, saddr, defsetp, hostsetp) 12461558Srgrimes struct dirlist *dp; 124742144Sdfr u_int32_t saddr; 12481558Srgrimes int *defsetp; 12499336Sdfr int *hostsetp; 12501558Srgrimes{ 12511558Srgrimes struct hostlist *hp; 12521558Srgrimes struct grouplist *grp; 125342144Sdfr u_int32_t **addrp; 12541558Srgrimes 12551558Srgrimes if (dp) { 12561558Srgrimes if (dp->dp_flag & DP_DEFSET) 12579336Sdfr *defsetp = dp->dp_flag; 12581558Srgrimes hp = dp->dp_hosts; 12591558Srgrimes while (hp) { 12601558Srgrimes grp = hp->ht_grp; 12611558Srgrimes switch (grp->gr_type) { 12621558Srgrimes case GT_HOST: 126342144Sdfr addrp = (u_int32_t **) 12641558Srgrimes grp->gr_ptr.gt_hostent->h_addr_list; 12651558Srgrimes while (*addrp) { 12669336Sdfr if (**addrp == saddr) { 12679336Sdfr *hostsetp = (hp->ht_flag | DP_HOSTSET); 12681558Srgrimes return (1); 12699336Sdfr } 12701558Srgrimes addrp++; 12711558Srgrimes } 12721558Srgrimes break; 12731558Srgrimes case GT_NET: 12741558Srgrimes if ((saddr & grp->gr_ptr.gt_net.nt_mask) == 12759336Sdfr grp->gr_ptr.gt_net.nt_net) { 12769336Sdfr *hostsetp = (hp->ht_flag | DP_HOSTSET); 12771558Srgrimes return (1); 12789336Sdfr } 12791558Srgrimes break; 12801558Srgrimes }; 12811558Srgrimes hp = hp->ht_next; 12821558Srgrimes } 12831558Srgrimes } 12841558Srgrimes return (0); 12851558Srgrimes} 12861558Srgrimes 12871558Srgrimes/* 12881558Srgrimes * Scan tree for a host that matches the address. 12891558Srgrimes */ 12901558Srgrimesint 12911558Srgrimesscan_tree(dp, saddr) 12921558Srgrimes struct dirlist *dp; 129342144Sdfr u_int32_t saddr; 12941558Srgrimes{ 12959336Sdfr int defset, hostset; 12961558Srgrimes 12971558Srgrimes if (dp) { 12981558Srgrimes if (scan_tree(dp->dp_left, saddr)) 12991558Srgrimes return (1); 13009336Sdfr if (chk_host(dp, saddr, &defset, &hostset)) 13011558Srgrimes return (1); 13021558Srgrimes if (scan_tree(dp->dp_right, saddr)) 13031558Srgrimes return (1); 13041558Srgrimes } 13051558Srgrimes return (0); 13061558Srgrimes} 13071558Srgrimes 13081558Srgrimes/* 13091558Srgrimes * Traverse the dirlist tree and free it up. 13101558Srgrimes */ 13111558Srgrimesvoid 13121558Srgrimesfree_dir(dp) 13131558Srgrimes struct dirlist *dp; 13141558Srgrimes{ 13151558Srgrimes 13161558Srgrimes if (dp) { 13171558Srgrimes free_dir(dp->dp_left); 13181558Srgrimes free_dir(dp->dp_right); 13191558Srgrimes free_host(dp->dp_hosts); 13201558Srgrimes free((caddr_t)dp); 13211558Srgrimes } 13221558Srgrimes} 13231558Srgrimes 13241558Srgrimes/* 13251558Srgrimes * Parse the option string and update fields. 13261558Srgrimes * Option arguments may either be -<option>=<value> or 13271558Srgrimes * -<option> <value> 13281558Srgrimes */ 13291558Srgrimesint 13301558Srgrimesdo_opt(cpp, endcpp, ep, grp, has_hostp, exflagsp, cr) 13311558Srgrimes char **cpp, **endcpp; 13321558Srgrimes struct exportlist *ep; 13331558Srgrimes struct grouplist *grp; 13341558Srgrimes int *has_hostp; 13351558Srgrimes int *exflagsp; 133672650Sgreen struct xucred *cr; 13371558Srgrimes{ 13381558Srgrimes char *cpoptarg, *cpoptend; 13391558Srgrimes char *cp, *endcp, *cpopt, savedc, savedc2; 13401558Srgrimes int allflag, usedarg; 13411558Srgrimes 134251968Salfred savedc2 = '\0'; 13431558Srgrimes cpopt = *cpp; 13441558Srgrimes cpopt++; 13451558Srgrimes cp = *endcpp; 13461558Srgrimes savedc = *cp; 13471558Srgrimes *cp = '\0'; 13481558Srgrimes while (cpopt && *cpopt) { 13491558Srgrimes allflag = 1; 13501558Srgrimes usedarg = -2; 135137663Scharnier if ((cpoptend = strchr(cpopt, ','))) { 13521558Srgrimes *cpoptend++ = '\0'; 135337663Scharnier if ((cpoptarg = strchr(cpopt, '='))) 13541558Srgrimes *cpoptarg++ = '\0'; 13551558Srgrimes } else { 135637663Scharnier if ((cpoptarg = strchr(cpopt, '='))) 13571558Srgrimes *cpoptarg++ = '\0'; 13581558Srgrimes else { 13591558Srgrimes *cp = savedc; 13601558Srgrimes nextfield(&cp, &endcp); 13611558Srgrimes **endcpp = '\0'; 13621558Srgrimes if (endcp > cp && *cp != '-') { 13631558Srgrimes cpoptarg = cp; 13641558Srgrimes savedc2 = *endcp; 13651558Srgrimes *endcp = '\0'; 13661558Srgrimes usedarg = 0; 13671558Srgrimes } 13681558Srgrimes } 13691558Srgrimes } 13701558Srgrimes if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 13711558Srgrimes *exflagsp |= MNT_EXRDONLY; 13721558Srgrimes } else if (cpoptarg && (!strcmp(cpopt, "maproot") || 13731558Srgrimes !(allflag = strcmp(cpopt, "mapall")) || 13741558Srgrimes !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) { 13751558Srgrimes usedarg++; 13761558Srgrimes parsecred(cpoptarg, cr); 13771558Srgrimes if (allflag == 0) { 13781558Srgrimes *exflagsp |= MNT_EXPORTANON; 13791558Srgrimes opt_flags |= OP_MAPALL; 13801558Srgrimes } else 13811558Srgrimes opt_flags |= OP_MAPROOT; 13821558Srgrimes } else if (!strcmp(cpopt, "kerb") || !strcmp(cpopt, "k")) { 13831558Srgrimes *exflagsp |= MNT_EXKERB; 13841558Srgrimes opt_flags |= OP_KERB; 13851558Srgrimes } else if (cpoptarg && (!strcmp(cpopt, "mask") || 13861558Srgrimes !strcmp(cpopt, "m"))) { 13871558Srgrimes if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { 138837663Scharnier syslog(LOG_ERR, "bad mask: %s", cpoptarg); 13891558Srgrimes return (1); 13901558Srgrimes } 13911558Srgrimes usedarg++; 13921558Srgrimes opt_flags |= OP_MASK; 13931558Srgrimes } else if (cpoptarg && (!strcmp(cpopt, "network") || 13941558Srgrimes !strcmp(cpopt, "n"))) { 13951558Srgrimes if (grp->gr_type != GT_NULL) { 139637663Scharnier syslog(LOG_ERR, "network/host conflict"); 13971558Srgrimes return (1); 13981558Srgrimes } else if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 0)) { 139937663Scharnier syslog(LOG_ERR, "bad net: %s", cpoptarg); 14001558Srgrimes return (1); 14011558Srgrimes } 14021558Srgrimes grp->gr_type = GT_NET; 14031558Srgrimes *has_hostp = 1; 14041558Srgrimes usedarg++; 14051558Srgrimes opt_flags |= OP_NET; 14061558Srgrimes } else if (!strcmp(cpopt, "alldirs")) { 14071558Srgrimes opt_flags |= OP_ALLDIRS; 140827447Sdfr } else if (!strcmp(cpopt, "public")) { 140927447Sdfr *exflagsp |= MNT_EXPUBLIC; 141027447Sdfr } else if (!strcmp(cpopt, "webnfs")) { 141127447Sdfr *exflagsp |= (MNT_EXPUBLIC|MNT_EXRDONLY|MNT_EXPORTANON); 141227447Sdfr opt_flags |= OP_MAPALL; 141327447Sdfr } else if (cpoptarg && !strcmp(cpopt, "index")) { 141427447Sdfr ep->ex_indexfile = strdup(cpoptarg); 14151558Srgrimes } else { 141637663Scharnier syslog(LOG_ERR, "bad opt %s", cpopt); 14171558Srgrimes return (1); 14181558Srgrimes } 14191558Srgrimes if (usedarg >= 0) { 14201558Srgrimes *endcp = savedc2; 14211558Srgrimes **endcpp = savedc; 14221558Srgrimes if (usedarg > 0) { 14231558Srgrimes *cpp = cp; 14241558Srgrimes *endcpp = endcp; 14251558Srgrimes } 14261558Srgrimes return (0); 14271558Srgrimes } 14281558Srgrimes cpopt = cpoptend; 14291558Srgrimes } 14301558Srgrimes **endcpp = savedc; 14311558Srgrimes return (0); 14321558Srgrimes} 14331558Srgrimes 14341558Srgrimes/* 14351558Srgrimes * Translate a character string to the corresponding list of network 14361558Srgrimes * addresses for a hostname. 14371558Srgrimes */ 14381558Srgrimesint 14397401Swpaulget_host(cp, grp, tgrp) 14401558Srgrimes char *cp; 14411558Srgrimes struct grouplist *grp; 14427401Swpaul struct grouplist *tgrp; 14431558Srgrimes{ 14447401Swpaul struct grouplist *checkgrp; 14451558Srgrimes struct hostent *hp, *nhp; 14461558Srgrimes char **addrp, **naddrp; 14471558Srgrimes struct hostent t_host; 14481558Srgrimes int i; 144942144Sdfr u_int32_t saddr; 14501558Srgrimes char *aptr[2]; 14511558Srgrimes 14521558Srgrimes if (grp->gr_type != GT_NULL) 14531558Srgrimes return (1); 14541558Srgrimes if ((hp = gethostbyname(cp)) == NULL) { 14551558Srgrimes if (isdigit(*cp)) { 14561558Srgrimes saddr = inet_addr(cp); 14571558Srgrimes if (saddr == -1) { 145837663Scharnier syslog(LOG_ERR, "inet_addr failed for %s", cp); 14591558Srgrimes return (1); 14601558Srgrimes } 14611558Srgrimes if ((hp = gethostbyaddr((caddr_t)&saddr, sizeof (saddr), 14621558Srgrimes AF_INET)) == NULL) { 14631558Srgrimes hp = &t_host; 14641558Srgrimes hp->h_name = cp; 14651558Srgrimes hp->h_addrtype = AF_INET; 146642144Sdfr hp->h_length = sizeof (u_int32_t); 14671558Srgrimes hp->h_addr_list = aptr; 14681558Srgrimes aptr[0] = (char *)&saddr; 14691558Srgrimes aptr[1] = (char *)NULL; 14701558Srgrimes } 14711558Srgrimes } else { 147237663Scharnier syslog(LOG_ERR, "gethostbyname failed for %s", cp); 14731558Srgrimes return (1); 14741558Srgrimes } 14751558Srgrimes } 14767401Swpaul /* 14777401Swpaul * Sanity check: make sure we don't already have an entry 14787401Swpaul * for this host in the grouplist. 14797401Swpaul */ 14807401Swpaul checkgrp = tgrp; 148137157Swpaul while (checkgrp != NULL) { 148217887Swpaul if (checkgrp->gr_type == GT_HOST && 148317887Swpaul checkgrp->gr_ptr.gt_hostent != NULL && 148437157Swpaul (!strcmp(checkgrp->gr_ptr.gt_hostent->h_name, hp->h_name) 148542144Sdfr || *(u_int32_t *)checkgrp->gr_ptr.gt_hostent->h_addr == 148642144Sdfr *(u_int32_t *)hp->h_addr)) { 14877401Swpaul grp->gr_type = GT_IGNORE; 14887401Swpaul return(0); 14897401Swpaul } 14907401Swpaul checkgrp = checkgrp->gr_next; 14917401Swpaul } 14927401Swpaul 14931558Srgrimes grp->gr_type = GT_HOST; 14941558Srgrimes nhp = grp->gr_ptr.gt_hostent = (struct hostent *) 14951558Srgrimes malloc(sizeof(struct hostent)); 14961558Srgrimes if (nhp == (struct hostent *)NULL) 14971558Srgrimes out_of_mem(); 149823681Speter memmove(nhp, hp, sizeof(struct hostent)); 14991558Srgrimes i = strlen(hp->h_name)+1; 15001558Srgrimes nhp->h_name = (char *)malloc(i); 15011558Srgrimes if (nhp->h_name == (char *)NULL) 15021558Srgrimes out_of_mem(); 150323681Speter memmove(nhp->h_name, hp->h_name, i); 15041558Srgrimes addrp = hp->h_addr_list; 15051558Srgrimes i = 1; 15061558Srgrimes while (*addrp++) 15071558Srgrimes i++; 150837663Scharnier naddrp = nhp->h_addr_list = (char **)malloc(i*sizeof(char *)); 15091558Srgrimes if (naddrp == (char **)NULL) 15101558Srgrimes out_of_mem(); 15111558Srgrimes addrp = hp->h_addr_list; 15121558Srgrimes while (*addrp) { 151337663Scharnier *naddrp = (char *)malloc(hp->h_length); 15141558Srgrimes if (*naddrp == (char *)NULL) 15151558Srgrimes out_of_mem(); 151623681Speter memmove(*naddrp, *addrp, hp->h_length); 15171558Srgrimes addrp++; 15181558Srgrimes naddrp++; 15191558Srgrimes } 15201558Srgrimes *naddrp = (char *)NULL; 15211558Srgrimes if (debug) 152237663Scharnier warnx("got host %s", hp->h_name); 15231558Srgrimes return (0); 15241558Srgrimes} 15251558Srgrimes 15261558Srgrimes/* 15271558Srgrimes * Free up an exports list component 15281558Srgrimes */ 15291558Srgrimesvoid 15301558Srgrimesfree_exp(ep) 15311558Srgrimes struct exportlist *ep; 15321558Srgrimes{ 15331558Srgrimes 15341558Srgrimes if (ep->ex_defdir) { 15351558Srgrimes free_host(ep->ex_defdir->dp_hosts); 15361558Srgrimes free((caddr_t)ep->ex_defdir); 15371558Srgrimes } 15381558Srgrimes if (ep->ex_fsdir) 15391558Srgrimes free(ep->ex_fsdir); 154027447Sdfr if (ep->ex_indexfile) 154127447Sdfr free(ep->ex_indexfile); 15421558Srgrimes free_dir(ep->ex_dirl); 15431558Srgrimes free((caddr_t)ep); 15441558Srgrimes} 15451558Srgrimes 15461558Srgrimes/* 15471558Srgrimes * Free hosts. 15481558Srgrimes */ 15491558Srgrimesvoid 15501558Srgrimesfree_host(hp) 15511558Srgrimes struct hostlist *hp; 15521558Srgrimes{ 15531558Srgrimes struct hostlist *hp2; 15541558Srgrimes 15551558Srgrimes while (hp) { 15561558Srgrimes hp2 = hp; 15571558Srgrimes hp = hp->ht_next; 15581558Srgrimes free((caddr_t)hp2); 15591558Srgrimes } 15601558Srgrimes} 15611558Srgrimes 15621558Srgrimesstruct hostlist * 15631558Srgrimesget_ht() 15641558Srgrimes{ 15651558Srgrimes struct hostlist *hp; 15661558Srgrimes 15671558Srgrimes hp = (struct hostlist *)malloc(sizeof (struct hostlist)); 15681558Srgrimes if (hp == (struct hostlist *)NULL) 15691558Srgrimes out_of_mem(); 15701558Srgrimes hp->ht_next = (struct hostlist *)NULL; 15719336Sdfr hp->ht_flag = 0; 15721558Srgrimes return (hp); 15731558Srgrimes} 15741558Srgrimes 15751558Srgrimes/* 15761558Srgrimes * Out of memory, fatal 15771558Srgrimes */ 15781558Srgrimesvoid 15791558Srgrimesout_of_mem() 15801558Srgrimes{ 15811558Srgrimes 158237663Scharnier syslog(LOG_ERR, "out of memory"); 15831558Srgrimes exit(2); 15841558Srgrimes} 15851558Srgrimes 15861558Srgrimes/* 15871558Srgrimes * Do the mount syscall with the update flag to push the export info into 15881558Srgrimes * the kernel. 15891558Srgrimes */ 15901558Srgrimesint 15911558Srgrimesdo_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb) 15921558Srgrimes struct exportlist *ep; 15931558Srgrimes struct grouplist *grp; 15941558Srgrimes int exflags; 159572650Sgreen struct xucred *anoncrp; 15961558Srgrimes char *dirp; 15971558Srgrimes int dirplen; 15981558Srgrimes struct statfs *fsb; 15991558Srgrimes{ 16001558Srgrimes char *cp = (char *)NULL; 160142144Sdfr u_int32_t **addrp; 16021558Srgrimes int done; 16031558Srgrimes char savedc = '\0'; 16041558Srgrimes struct sockaddr_in sin, imask; 16051558Srgrimes union { 16061558Srgrimes struct ufs_args ua; 16071558Srgrimes struct iso_args ia; 16081558Srgrimes struct mfs_args ma; 16099336Sdfr#ifdef __NetBSD__ 16109336Sdfr struct msdosfs_args da; 16119336Sdfr#endif 161254093Ssemenu struct ntfs_args na; 16131558Srgrimes } args; 161442144Sdfr u_int32_t net; 16151558Srgrimes 16161558Srgrimes args.ua.fspec = 0; 16171558Srgrimes args.ua.export.ex_flags = exflags; 16181558Srgrimes args.ua.export.ex_anon = *anoncrp; 161927447Sdfr args.ua.export.ex_indexfile = ep->ex_indexfile; 162023681Speter memset(&sin, 0, sizeof(sin)); 162123681Speter memset(&imask, 0, sizeof(imask)); 16221558Srgrimes sin.sin_family = AF_INET; 16231558Srgrimes sin.sin_len = sizeof(sin); 16241558Srgrimes imask.sin_family = AF_INET; 16251558Srgrimes imask.sin_len = sizeof(sin); 16261558Srgrimes if (grp->gr_type == GT_HOST) 162742144Sdfr addrp = (u_int32_t **)grp->gr_ptr.gt_hostent->h_addr_list; 16281558Srgrimes else 162942144Sdfr addrp = (u_int32_t **)NULL; 16301558Srgrimes done = FALSE; 16311558Srgrimes while (!done) { 16321558Srgrimes switch (grp->gr_type) { 16331558Srgrimes case GT_HOST: 16341558Srgrimes if (addrp) { 16351558Srgrimes sin.sin_addr.s_addr = **addrp; 16361558Srgrimes args.ua.export.ex_addrlen = sizeof(sin); 16371558Srgrimes } else 16381558Srgrimes args.ua.export.ex_addrlen = 0; 16391558Srgrimes args.ua.export.ex_addr = (struct sockaddr *)&sin; 16401558Srgrimes args.ua.export.ex_masklen = 0; 16411558Srgrimes break; 16421558Srgrimes case GT_NET: 16431558Srgrimes if (grp->gr_ptr.gt_net.nt_mask) 16441558Srgrimes imask.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_mask; 16451558Srgrimes else { 16461558Srgrimes net = ntohl(grp->gr_ptr.gt_net.nt_net); 16471558Srgrimes if (IN_CLASSA(net)) 16481558Srgrimes imask.sin_addr.s_addr = inet_addr("255.0.0.0"); 16491558Srgrimes else if (IN_CLASSB(net)) 16501558Srgrimes imask.sin_addr.s_addr = 16511558Srgrimes inet_addr("255.255.0.0"); 16521558Srgrimes else 16531558Srgrimes imask.sin_addr.s_addr = 16541558Srgrimes inet_addr("255.255.255.0"); 16551558Srgrimes grp->gr_ptr.gt_net.nt_mask = imask.sin_addr.s_addr; 16561558Srgrimes } 16571558Srgrimes sin.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_net; 16581558Srgrimes args.ua.export.ex_addr = (struct sockaddr *)&sin; 16591558Srgrimes args.ua.export.ex_addrlen = sizeof (sin); 16601558Srgrimes args.ua.export.ex_mask = (struct sockaddr *)&imask; 16611558Srgrimes args.ua.export.ex_masklen = sizeof (imask); 16621558Srgrimes break; 16637401Swpaul case GT_IGNORE: 16647401Swpaul return(0); 16657401Swpaul break; 16661558Srgrimes default: 166737663Scharnier syslog(LOG_ERR, "bad grouptype"); 16681558Srgrimes if (cp) 16691558Srgrimes *cp = savedc; 16701558Srgrimes return (1); 16711558Srgrimes }; 16721558Srgrimes 16731558Srgrimes /* 16741558Srgrimes * XXX: 16751558Srgrimes * Maybe I should just use the fsb->f_mntonname path instead 16761558Srgrimes * of looping back up the dirp to the mount point?? 16771558Srgrimes * Also, needs to know how to export all types of local 167823681Speter * exportable file systems and not just "ufs". 16791558Srgrimes */ 16809336Sdfr while (mount(fsb->f_fstypename, dirp, 16811558Srgrimes fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) { 16821558Srgrimes if (cp) 16831558Srgrimes *cp-- = savedc; 16841558Srgrimes else 16851558Srgrimes cp = dirp + dirplen - 1; 16861558Srgrimes if (errno == EPERM) { 16871558Srgrimes syslog(LOG_ERR, 168837663Scharnier "can't change attributes for %s", dirp); 16891558Srgrimes return (1); 16901558Srgrimes } 16911558Srgrimes if (opt_flags & OP_ALLDIRS) { 169237663Scharnier syslog(LOG_ERR, "could not remount %s: %m", 16934895Swollman dirp); 16941558Srgrimes return (1); 16951558Srgrimes } 16961558Srgrimes /* back up over the last component */ 16971558Srgrimes while (*cp == '/' && cp > dirp) 16981558Srgrimes cp--; 16991558Srgrimes while (*(cp - 1) != '/' && cp > dirp) 17001558Srgrimes cp--; 17011558Srgrimes if (cp == dirp) { 17021558Srgrimes if (debug) 170337663Scharnier warnx("mnt unsucc"); 170437663Scharnier syslog(LOG_ERR, "can't export %s", dirp); 17051558Srgrimes return (1); 17061558Srgrimes } 17071558Srgrimes savedc = *cp; 17081558Srgrimes *cp = '\0'; 17091558Srgrimes } 17101558Srgrimes if (addrp) { 17111558Srgrimes ++addrp; 171242144Sdfr if (*addrp == (u_int32_t *)NULL) 17131558Srgrimes done = TRUE; 17141558Srgrimes } else 17151558Srgrimes done = TRUE; 17161558Srgrimes } 17171558Srgrimes if (cp) 17181558Srgrimes *cp = savedc; 17191558Srgrimes return (0); 17201558Srgrimes} 17211558Srgrimes 17221558Srgrimes/* 17231558Srgrimes * Translate a net address. 17241558Srgrimes */ 17251558Srgrimesint 17261558Srgrimesget_net(cp, net, maskflg) 17271558Srgrimes char *cp; 17281558Srgrimes struct netmsk *net; 17291558Srgrimes int maskflg; 17301558Srgrimes{ 17311558Srgrimes struct netent *np; 17321558Srgrimes long netaddr; 17331558Srgrimes struct in_addr inetaddr, inetaddr2; 17341558Srgrimes char *name; 17351558Srgrimes 173625318Spst if (isdigit(*cp) && ((netaddr = inet_network(cp)) != -1)) { 17371558Srgrimes inetaddr = inet_makeaddr(netaddr, 0); 17381558Srgrimes /* 173937663Scharnier * Due to arbitrary subnet masks, you don't know how many 17401558Srgrimes * bits to shift the address to make it into a network, 17411558Srgrimes * however you do know how to make a network address into 17421558Srgrimes * a host with host == 0 and then compare them. 17431558Srgrimes * (What a pest) 17441558Srgrimes */ 17451558Srgrimes if (!maskflg) { 17461558Srgrimes setnetent(0); 174737663Scharnier while ((np = getnetent())) { 17481558Srgrimes inetaddr2 = inet_makeaddr(np->n_net, 0); 17491558Srgrimes if (inetaddr2.s_addr == inetaddr.s_addr) 17501558Srgrimes break; 17511558Srgrimes } 17521558Srgrimes endnetent(); 17531558Srgrimes } 175425318Spst } else if ((np = getnetbyname(cp)) != NULL) { 175525318Spst inetaddr = inet_makeaddr(np->n_net, 0); 17561558Srgrimes } else 17571558Srgrimes return (1); 175825318Spst 17591558Srgrimes if (maskflg) 17601558Srgrimes net->nt_mask = inetaddr.s_addr; 17611558Srgrimes else { 17621558Srgrimes if (np) 17631558Srgrimes name = np->n_name; 17641558Srgrimes else 17651558Srgrimes name = inet_ntoa(inetaddr); 17661558Srgrimes net->nt_name = (char *)malloc(strlen(name) + 1); 17671558Srgrimes if (net->nt_name == (char *)NULL) 17681558Srgrimes out_of_mem(); 17691558Srgrimes strcpy(net->nt_name, name); 17701558Srgrimes net->nt_net = inetaddr.s_addr; 17711558Srgrimes } 17721558Srgrimes return (0); 17731558Srgrimes} 17741558Srgrimes 17751558Srgrimes/* 17761558Srgrimes * Parse out the next white space separated field 17771558Srgrimes */ 17781558Srgrimesvoid 17791558Srgrimesnextfield(cp, endcp) 17801558Srgrimes char **cp; 17811558Srgrimes char **endcp; 17821558Srgrimes{ 17831558Srgrimes char *p; 17841558Srgrimes 17851558Srgrimes p = *cp; 17861558Srgrimes while (*p == ' ' || *p == '\t') 17871558Srgrimes p++; 17881558Srgrimes if (*p == '\n' || *p == '\0') 17891558Srgrimes *cp = *endcp = p; 17901558Srgrimes else { 17911558Srgrimes *cp = p++; 17921558Srgrimes while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 17931558Srgrimes p++; 17941558Srgrimes *endcp = p; 17951558Srgrimes } 17961558Srgrimes} 17971558Srgrimes 17981558Srgrimes/* 17991558Srgrimes * Get an exports file line. Skip over blank lines and handle line 18001558Srgrimes * continuations. 18011558Srgrimes */ 18021558Srgrimesint 18031558Srgrimesget_line() 18041558Srgrimes{ 18051558Srgrimes char *p, *cp; 18061558Srgrimes int len; 18071558Srgrimes int totlen, cont_line; 18081558Srgrimes 18091558Srgrimes /* 18101558Srgrimes * Loop around ignoring blank lines and getting all continuation lines. 18111558Srgrimes */ 18121558Srgrimes p = line; 18131558Srgrimes totlen = 0; 18141558Srgrimes do { 18151558Srgrimes if (fgets(p, LINESIZ - totlen, exp_file) == NULL) 18161558Srgrimes return (0); 18171558Srgrimes len = strlen(p); 18181558Srgrimes cp = p + len - 1; 18191558Srgrimes cont_line = 0; 18201558Srgrimes while (cp >= p && 18211558Srgrimes (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '\\')) { 18221558Srgrimes if (*cp == '\\') 18231558Srgrimes cont_line = 1; 18241558Srgrimes cp--; 18251558Srgrimes len--; 18261558Srgrimes } 18271558Srgrimes *++cp = '\0'; 18281558Srgrimes if (len > 0) { 18291558Srgrimes totlen += len; 18301558Srgrimes if (totlen >= LINESIZ) { 183137663Scharnier syslog(LOG_ERR, "exports line too long"); 18321558Srgrimes exit(2); 18331558Srgrimes } 18341558Srgrimes p = cp; 18351558Srgrimes } 18361558Srgrimes } while (totlen == 0 || cont_line); 18371558Srgrimes return (1); 18381558Srgrimes} 18391558Srgrimes 18401558Srgrimes/* 18411558Srgrimes * Parse a description of a credential. 18421558Srgrimes */ 18431558Srgrimesvoid 18441558Srgrimesparsecred(namelist, cr) 18451558Srgrimes char *namelist; 184672650Sgreen struct xucred *cr; 18471558Srgrimes{ 18481558Srgrimes char *name; 18491558Srgrimes int cnt; 18501558Srgrimes char *names; 18511558Srgrimes struct passwd *pw; 18521558Srgrimes struct group *gr; 18531558Srgrimes int ngroups, groups[NGROUPS + 1]; 18541558Srgrimes 18551558Srgrimes /* 185637663Scharnier * Set up the unprivileged user. 18571558Srgrimes */ 18581558Srgrimes cr->cr_uid = -2; 18591558Srgrimes cr->cr_groups[0] = -2; 18601558Srgrimes cr->cr_ngroups = 1; 18611558Srgrimes /* 18621558Srgrimes * Get the user's password table entry. 18631558Srgrimes */ 18641558Srgrimes names = strsep(&namelist, " \t\n"); 18651558Srgrimes name = strsep(&names, ":"); 18661558Srgrimes if (isdigit(*name) || *name == '-') 18671558Srgrimes pw = getpwuid(atoi(name)); 18681558Srgrimes else 18691558Srgrimes pw = getpwnam(name); 18701558Srgrimes /* 18711558Srgrimes * Credentials specified as those of a user. 18721558Srgrimes */ 18731558Srgrimes if (names == NULL) { 18741558Srgrimes if (pw == NULL) { 187537663Scharnier syslog(LOG_ERR, "unknown user: %s", name); 18761558Srgrimes return; 18771558Srgrimes } 18781558Srgrimes cr->cr_uid = pw->pw_uid; 18791558Srgrimes ngroups = NGROUPS + 1; 18801558Srgrimes if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) 188137663Scharnier syslog(LOG_ERR, "too many groups"); 18821558Srgrimes /* 18831558Srgrimes * Convert from int's to gid_t's and compress out duplicate 18841558Srgrimes */ 18851558Srgrimes cr->cr_ngroups = ngroups - 1; 18861558Srgrimes cr->cr_groups[0] = groups[0]; 18871558Srgrimes for (cnt = 2; cnt < ngroups; cnt++) 18881558Srgrimes cr->cr_groups[cnt - 1] = groups[cnt]; 18891558Srgrimes return; 18901558Srgrimes } 18911558Srgrimes /* 18921558Srgrimes * Explicit credential specified as a colon separated list: 18931558Srgrimes * uid:gid:gid:... 18941558Srgrimes */ 18951558Srgrimes if (pw != NULL) 18961558Srgrimes cr->cr_uid = pw->pw_uid; 18971558Srgrimes else if (isdigit(*name) || *name == '-') 18981558Srgrimes cr->cr_uid = atoi(name); 18991558Srgrimes else { 190037663Scharnier syslog(LOG_ERR, "unknown user: %s", name); 19011558Srgrimes return; 19021558Srgrimes } 19031558Srgrimes cr->cr_ngroups = 0; 19041558Srgrimes while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { 19051558Srgrimes name = strsep(&names, ":"); 19061558Srgrimes if (isdigit(*name) || *name == '-') { 19071558Srgrimes cr->cr_groups[cr->cr_ngroups++] = atoi(name); 19081558Srgrimes } else { 19091558Srgrimes if ((gr = getgrnam(name)) == NULL) { 191037663Scharnier syslog(LOG_ERR, "unknown group: %s", name); 19111558Srgrimes continue; 19121558Srgrimes } 19131558Srgrimes cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; 19141558Srgrimes } 19151558Srgrimes } 19161558Srgrimes if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) 191737663Scharnier syslog(LOG_ERR, "too many groups"); 19181558Srgrimes} 19191558Srgrimes 19201558Srgrimes#define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 19211558Srgrimes/* 19221558Srgrimes * Routines that maintain the remote mounttab 19231558Srgrimes */ 19241558Srgrimesvoid 19251558Srgrimesget_mountlist() 19261558Srgrimes{ 19271558Srgrimes struct mountlist *mlp, **mlpp; 192823681Speter char *host, *dirp, *cp; 19291558Srgrimes char str[STRSIZ]; 19301558Srgrimes FILE *mlfile; 19311558Srgrimes 19321558Srgrimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) { 193353117Sbillf if (errno == ENOENT) 193453117Sbillf return; 193553117Sbillf else { 193653117Sbillf syslog(LOG_ERR, "can't open %s", _PATH_RMOUNTLIST); 193753117Sbillf return; 193853117Sbillf } 19391558Srgrimes } 19401558Srgrimes mlpp = &mlhead; 19411558Srgrimes while (fgets(str, STRSIZ, mlfile) != NULL) { 194223681Speter cp = str; 194323681Speter host = strsep(&cp, " \t\n"); 194423681Speter dirp = strsep(&cp, " \t\n"); 194523681Speter if (host == NULL || dirp == NULL) 19461558Srgrimes continue; 19471558Srgrimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 194837663Scharnier if (mlp == (struct mountlist *)NULL) 194937663Scharnier out_of_mem(); 195023681Speter strncpy(mlp->ml_host, host, RPCMNT_NAMELEN); 195123681Speter mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 195223681Speter strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 195323681Speter mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 19541558Srgrimes mlp->ml_next = (struct mountlist *)NULL; 19551558Srgrimes *mlpp = mlp; 19561558Srgrimes mlpp = &mlp->ml_next; 19571558Srgrimes } 19581558Srgrimes fclose(mlfile); 19591558Srgrimes} 19601558Srgrimes 19611558Srgrimesvoid 19621558Srgrimesdel_mlist(hostp, dirp) 19631558Srgrimes char *hostp, *dirp; 19641558Srgrimes{ 19651558Srgrimes struct mountlist *mlp, **mlpp; 19661558Srgrimes struct mountlist *mlp2; 19671558Srgrimes FILE *mlfile; 19681558Srgrimes int fnd = 0; 19691558Srgrimes 19701558Srgrimes mlpp = &mlhead; 19711558Srgrimes mlp = mlhead; 19721558Srgrimes while (mlp) { 19731558Srgrimes if (!strcmp(mlp->ml_host, hostp) && 19741558Srgrimes (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 19751558Srgrimes fnd = 1; 19761558Srgrimes mlp2 = mlp; 19771558Srgrimes *mlpp = mlp = mlp->ml_next; 19781558Srgrimes free((caddr_t)mlp2); 19791558Srgrimes } else { 19801558Srgrimes mlpp = &mlp->ml_next; 19811558Srgrimes mlp = mlp->ml_next; 19821558Srgrimes } 19831558Srgrimes } 19841558Srgrimes if (fnd) { 19851558Srgrimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 198637663Scharnier syslog(LOG_ERR,"can't update %s", _PATH_RMOUNTLIST); 19871558Srgrimes return; 19881558Srgrimes } 19891558Srgrimes mlp = mlhead; 19901558Srgrimes while (mlp) { 19911558Srgrimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 19921558Srgrimes mlp = mlp->ml_next; 19931558Srgrimes } 19941558Srgrimes fclose(mlfile); 19951558Srgrimes } 19961558Srgrimes} 19971558Srgrimes 19981558Srgrimesvoid 19991558Srgrimesadd_mlist(hostp, dirp) 20001558Srgrimes char *hostp, *dirp; 20011558Srgrimes{ 20021558Srgrimes struct mountlist *mlp, **mlpp; 20031558Srgrimes FILE *mlfile; 20041558Srgrimes 20051558Srgrimes mlpp = &mlhead; 20061558Srgrimes mlp = mlhead; 20071558Srgrimes while (mlp) { 20081558Srgrimes if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 20091558Srgrimes return; 20101558Srgrimes mlpp = &mlp->ml_next; 20111558Srgrimes mlp = mlp->ml_next; 20121558Srgrimes } 20131558Srgrimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 201437663Scharnier if (mlp == (struct mountlist *)NULL) 201537663Scharnier out_of_mem(); 20161558Srgrimes strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 20171558Srgrimes mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 20181558Srgrimes strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 20191558Srgrimes mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 20201558Srgrimes mlp->ml_next = (struct mountlist *)NULL; 20211558Srgrimes *mlpp = mlp; 20221558Srgrimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 202337663Scharnier syslog(LOG_ERR, "can't update %s", _PATH_RMOUNTLIST); 20241558Srgrimes return; 20251558Srgrimes } 20261558Srgrimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 20271558Srgrimes fclose(mlfile); 20281558Srgrimes} 20291558Srgrimes 20301558Srgrimes/* 20311558Srgrimes * Free up a group list. 20321558Srgrimes */ 20331558Srgrimesvoid 20341558Srgrimesfree_grp(grp) 20351558Srgrimes struct grouplist *grp; 20361558Srgrimes{ 20371558Srgrimes char **addrp; 20381558Srgrimes 20391558Srgrimes if (grp->gr_type == GT_HOST) { 20401558Srgrimes if (grp->gr_ptr.gt_hostent->h_name) { 20411558Srgrimes addrp = grp->gr_ptr.gt_hostent->h_addr_list; 20421558Srgrimes while (addrp && *addrp) 20431558Srgrimes free(*addrp++); 20441558Srgrimes free((caddr_t)grp->gr_ptr.gt_hostent->h_addr_list); 20451558Srgrimes free(grp->gr_ptr.gt_hostent->h_name); 20461558Srgrimes } 20471558Srgrimes free((caddr_t)grp->gr_ptr.gt_hostent); 20481558Srgrimes } else if (grp->gr_type == GT_NET) { 20491558Srgrimes if (grp->gr_ptr.gt_net.nt_name) 20501558Srgrimes free(grp->gr_ptr.gt_net.nt_name); 20511558Srgrimes } 20521558Srgrimes free((caddr_t)grp); 20531558Srgrimes} 20541558Srgrimes 20551558Srgrimes#ifdef DEBUG 20561558Srgrimesvoid 20571558SrgrimesSYSLOG(int pri, const char *fmt, ...) 20581558Srgrimes{ 20591558Srgrimes va_list ap; 20601558Srgrimes 20611558Srgrimes va_start(ap, fmt); 20621558Srgrimes vfprintf(stderr, fmt, ap); 20631558Srgrimes va_end(ap); 20641558Srgrimes} 20651558Srgrimes#endif /* DEBUG */ 20661558Srgrimes 20671558Srgrimes/* 20681558Srgrimes * Check options for consistency. 20691558Srgrimes */ 20701558Srgrimesint 20711558Srgrimescheck_options(dp) 20721558Srgrimes struct dirlist *dp; 20731558Srgrimes{ 20741558Srgrimes 20751558Srgrimes if (dp == (struct dirlist *)NULL) 20761558Srgrimes return (1); 20771558Srgrimes if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL) || 20781558Srgrimes (opt_flags & (OP_MAPROOT | OP_KERB)) == (OP_MAPROOT | OP_KERB) || 20791558Srgrimes (opt_flags & (OP_MAPALL | OP_KERB)) == (OP_MAPALL | OP_KERB)) { 20801558Srgrimes syslog(LOG_ERR, "-mapall, -maproot and -kerb mutually exclusive"); 20811558Srgrimes return (1); 20821558Srgrimes } 20831558Srgrimes if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { 20841558Srgrimes syslog(LOG_ERR, "-mask requires -net"); 20851558Srgrimes return (1); 20861558Srgrimes } 20871558Srgrimes if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { 208845927Salex syslog(LOG_ERR, "-alldirs has multiple directories"); 20891558Srgrimes return (1); 20901558Srgrimes } 20911558Srgrimes return (0); 20921558Srgrimes} 20931558Srgrimes 20941558Srgrimes/* 20951558Srgrimes * Check an absolute directory path for any symbolic links. Return true 20961558Srgrimes * if no symbolic links are found. 20971558Srgrimes */ 20981558Srgrimesint 20991558Srgrimescheck_dirpath(dirp) 21001558Srgrimes char *dirp; 21011558Srgrimes{ 21021558Srgrimes char *cp; 21031558Srgrimes int ret = 1; 21041558Srgrimes struct stat sb; 21051558Srgrimes 21061558Srgrimes cp = dirp + 1; 21071558Srgrimes while (*cp && ret) { 21081558Srgrimes if (*cp == '/') { 21091558Srgrimes *cp = '\0'; 21109336Sdfr if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 21111558Srgrimes ret = 0; 21121558Srgrimes *cp = '/'; 21131558Srgrimes } 21141558Srgrimes cp++; 21151558Srgrimes } 21169336Sdfr if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 21171558Srgrimes ret = 0; 21181558Srgrimes return (ret); 21191558Srgrimes} 21209336Sdfr 21219336Sdfr/* 21229336Sdfr * Just translate an ascii string to an integer. 21239336Sdfr */ 21249336Sdfrint 21259336Sdfrget_num(cp) 21269336Sdfr register char *cp; 21279336Sdfr{ 21289336Sdfr register int res = 0; 21299336Sdfr 21309336Sdfr while (*cp) { 21319336Sdfr if (*cp < '0' || *cp > '9') 21329336Sdfr return (-1); 21339336Sdfr res = res * 10 + (*cp++ - '0'); 21349336Sdfr } 21359336Sdfr return (res); 21369336Sdfr} 2137