mountd.c revision 24759
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[] = 4624759Sguido "$Id: mountd.c,v 1.17 1997/04/01 14:15:30 bde 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; 1181558Srgrimes}; 1191558Srgrimes/* ex_flag bits */ 1201558Srgrimes#define EX_LINKED 0x1 1211558Srgrimes 1221558Srgrimesstruct netmsk { 1231558Srgrimes u_long nt_net; 1241558Srgrimes u_long nt_mask; 1251558Srgrimes char *nt_name; 1261558Srgrimes}; 1271558Srgrimes 1281558Srgrimesunion grouptypes { 1291558Srgrimes struct hostent *gt_hostent; 1301558Srgrimes struct netmsk gt_net; 1311558Srgrimes#ifdef ISO 1321558Srgrimes struct sockaddr_iso *gt_isoaddr; 1331558Srgrimes#endif 1341558Srgrimes}; 1351558Srgrimes 1361558Srgrimesstruct grouplist { 1371558Srgrimes int gr_type; 1381558Srgrimes union grouptypes gr_ptr; 1391558Srgrimes struct grouplist *gr_next; 1401558Srgrimes}; 1411558Srgrimes/* Group types */ 1421558Srgrimes#define GT_NULL 0x0 1431558Srgrimes#define GT_HOST 0x1 1441558Srgrimes#define GT_NET 0x2 1451558Srgrimes#define GT_ISO 0x4 1467401Swpaul#define GT_IGNORE 0x5 1471558Srgrimes 1481558Srgrimesstruct hostlist { 1499336Sdfr int ht_flag; /* Uses DP_xx bits */ 1501558Srgrimes struct grouplist *ht_grp; 1511558Srgrimes struct hostlist *ht_next; 1521558Srgrimes}; 1531558Srgrimes 1549336Sdfrstruct fhreturn { 1559336Sdfr int fhr_flag; 1569336Sdfr int fhr_vers; 1579336Sdfr nfsfh_t fhr_fh; 1589336Sdfr}; 1599336Sdfr 1601558Srgrimes/* Global defs */ 1611558Srgrimeschar *add_expdir __P((struct dirlist **, char *, int)); 1621558Srgrimesvoid add_dlist __P((struct dirlist **, struct dirlist *, 1639336Sdfr struct grouplist *, int)); 1641558Srgrimesvoid add_mlist __P((char *, char *)); 1651558Srgrimesint check_dirpath __P((char *)); 1661558Srgrimesint check_options __P((struct dirlist *)); 1679336Sdfrint chk_host __P((struct dirlist *, u_long, int *, int *)); 1681558Srgrimesvoid del_mlist __P((char *, char *)); 1691558Srgrimesstruct dirlist *dirp_search __P((struct dirlist *, char *)); 1701558Srgrimesint do_mount __P((struct exportlist *, struct grouplist *, int, 1719336Sdfr struct ucred *, char *, int, struct statfs *)); 1721558Srgrimesint do_opt __P((char **, char **, struct exportlist *, struct grouplist *, 1731558Srgrimes int *, int *, struct ucred *)); 1741558Srgrimesstruct exportlist *ex_search __P((fsid_t *)); 1751558Srgrimesstruct exportlist *get_exp __P((void)); 1761558Srgrimesvoid free_dir __P((struct dirlist *)); 1771558Srgrimesvoid free_exp __P((struct exportlist *)); 1781558Srgrimesvoid free_grp __P((struct grouplist *)); 1791558Srgrimesvoid free_host __P((struct hostlist *)); 1801558Srgrimesvoid get_exportlist __P((void)); 1817401Swpaulint get_host __P((char *, struct grouplist *, struct grouplist *)); 1829336Sdfrint get_num __P((char *)); 1831558Srgrimesstruct hostlist *get_ht __P((void)); 1841558Srgrimesint get_line __P((void)); 1851558Srgrimesvoid get_mountlist __P((void)); 1861558Srgrimesint get_net __P((char *, struct netmsk *, int)); 1871558Srgrimesvoid getexp_err __P((struct exportlist *, struct grouplist *)); 1881558Srgrimesstruct grouplist *get_grp __P((void)); 1891558Srgrimesvoid hang_dirp __P((struct dirlist *, struct grouplist *, 1901558Srgrimes struct exportlist *, int)); 1911558Srgrimesvoid mntsrv __P((struct svc_req *, SVCXPRT *)); 1921558Srgrimesvoid nextfield __P((char **, char **)); 1931558Srgrimesvoid out_of_mem __P((void)); 1941558Srgrimesvoid parsecred __P((char *, struct ucred *)); 1951558Srgrimesint put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *)); 1961558Srgrimesint scan_tree __P((struct dirlist *, u_long)); 1971558Srgrimesvoid send_umntall __P((void)); 1981558Srgrimesint umntall_each __P((caddr_t, struct sockaddr_in *)); 1991558Srgrimesint xdr_dir __P((XDR *, char *)); 2001558Srgrimesint xdr_explist __P((XDR *, caddr_t)); 2019336Sdfrint xdr_fhs __P((XDR *, caddr_t)); 2021558Srgrimesint xdr_mlist __P((XDR *, caddr_t)); 2031558Srgrimes 2041558Srgrimes/* C library */ 2051558Srgrimesint getnetgrent(); 2061558Srgrimesvoid endnetgrent(); 2071558Srgrimesvoid setnetgrent(); 2081558Srgrimes 2091558Srgrimes#ifdef ISO 2101558Srgrimesstruct iso_addr *iso_addr(); 2111558Srgrimes#endif 2121558Srgrimes 2131558Srgrimesstruct exportlist *exphead; 2141558Srgrimesstruct mountlist *mlhead; 2151558Srgrimesstruct grouplist *grphead; 2161558Srgrimeschar exname[MAXPATHLEN]; 2171558Srgrimesstruct ucred def_anon = { 2181558Srgrimes 1, 2191558Srgrimes (uid_t) -2, 2201558Srgrimes 1, 2211558Srgrimes { (gid_t) -2 } 2221558Srgrimes}; 2239336Sdfrint resvport_only = 1; 2249336Sdfrint dir_only = 1; 2251558Srgrimesint opt_flags; 2261558Srgrimes/* Bits for above */ 2271558Srgrimes#define OP_MAPROOT 0x01 2281558Srgrimes#define OP_MAPALL 0x02 2291558Srgrimes#define OP_KERB 0x04 2301558Srgrimes#define OP_MASK 0x08 2311558Srgrimes#define OP_NET 0x10 2321558Srgrimes#define OP_ISO 0x20 2331558Srgrimes#define OP_ALLDIRS 0x40 2341558Srgrimes 2351558Srgrimes#ifdef DEBUG 2361558Srgrimesint debug = 1; 2371558Srgrimesvoid SYSLOG __P((int, const char *, ...)); 2381558Srgrimes#define syslog SYSLOG 2391558Srgrimes#else 2401558Srgrimesint debug = 0; 2411558Srgrimes#endif 2421558Srgrimes 2431558Srgrimes/* 2441558Srgrimes * Mountd server for NFS mount protocol as described in: 2451558Srgrimes * NFS: Network File System Protocol Specification, RFC1094, Appendix A 2461558Srgrimes * The optional arguments are the exports file name 2471558Srgrimes * default: _PATH_EXPORTS 2481558Srgrimes * and "-n" to allow nonroot mount. 2491558Srgrimes */ 2501558Srgrimesint 2511558Srgrimesmain(argc, argv) 2521558Srgrimes int argc; 2531558Srgrimes char **argv; 2541558Srgrimes{ 2559202Srgrimes SVCXPRT *udptransp, *tcptransp; 2561558Srgrimes int c; 25724489Sbde int mib[3]; 2589336Sdfr#ifdef __FreeBSD__ 25923681Speter struct vfsconf vfc; 26023681Speter int error; 2611558Srgrimes 26223681Speter error = getvfsbyname("nfs", &vfc); 26323681Speter if (error && vfsisloadable("nfs")) { 2642999Swollman if(vfsload("nfs")) 2652999Swollman err(1, "vfsload(nfs)"); 2662999Swollman endvfsent(); /* flush cache */ 26723681Speter error = getvfsbyname("nfs", &vfc); 2682999Swollman } 26923681Speter if (error) 2702999Swollman errx(1, "NFS support is not available in the running kernel"); 2719336Sdfr#endif /* __FreeBSD__ */ 2722999Swollman 27324359Simp while ((c = getopt(argc, argv, "dnr")) != -1) 2741558Srgrimes switch (c) { 2759336Sdfr case 'n': 2769336Sdfr resvport_only = 0; 2779336Sdfr break; 2789336Sdfr case 'r': 2799336Sdfr dir_only = 0; 2809336Sdfr break; 2818688Sphk case 'd': 2828688Sphk debug = debug ? 0 : 1; 2838688Sphk break; 2841558Srgrimes default: 28523681Speter fprintf(stderr, "Usage: mountd [-d] [-r] [-n] [export_file]\n"); 2861558Srgrimes exit(1); 2871558Srgrimes }; 2881558Srgrimes argc -= optind; 2891558Srgrimes argv += optind; 2901558Srgrimes grphead = (struct grouplist *)NULL; 2911558Srgrimes exphead = (struct exportlist *)NULL; 2921558Srgrimes mlhead = (struct mountlist *)NULL; 2931558Srgrimes if (argc == 1) { 2941558Srgrimes strncpy(exname, *argv, MAXPATHLEN-1); 2951558Srgrimes exname[MAXPATHLEN-1] = '\0'; 2961558Srgrimes } else 2971558Srgrimes strcpy(exname, _PATH_EXPORTS); 2981558Srgrimes openlog("mountd", LOG_PID, LOG_DAEMON); 2991558Srgrimes if (debug) 3001558Srgrimes fprintf(stderr,"Getting export list.\n"); 3011558Srgrimes get_exportlist(); 3021558Srgrimes if (debug) 3031558Srgrimes fprintf(stderr,"Getting mount list.\n"); 3041558Srgrimes get_mountlist(); 3051558Srgrimes if (debug) 3061558Srgrimes fprintf(stderr,"Here we go.\n"); 3071558Srgrimes if (debug == 0) { 3081558Srgrimes daemon(0, 0); 3091558Srgrimes signal(SIGINT, SIG_IGN); 3101558Srgrimes signal(SIGQUIT, SIG_IGN); 3111558Srgrimes } 3121558Srgrimes signal(SIGHUP, (void (*) __P((int))) get_exportlist); 3131558Srgrimes signal(SIGTERM, (void (*) __P((int))) send_umntall); 3141558Srgrimes { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); 3151558Srgrimes if (pidfile != NULL) { 3161558Srgrimes fprintf(pidfile, "%d\n", getpid()); 3171558Srgrimes fclose(pidfile); 3181558Srgrimes } 3191558Srgrimes } 32024330Sguido 32124759Sguido if (!resvport_only) { 32224759Sguido mib[0] = CTL_VFS; 32324759Sguido mib[1] = MOUNT_NFS; 32424759Sguido mib[2] = NFS_NFSPRIVPORT; 32524759Sguido if (sysctl(mib, 3, NULL, NULL, &resvport_only, 32624759Sguido sizeof(resvport_only)) != 0 && errno != ENOENT) { 32724759Sguido syslog(LOG_ERR, "sysctl: %m"); 32824759Sguido exit(1); 32924759Sguido } 33024330Sguido } 33124330Sguido 3329202Srgrimes if ((udptransp = svcudp_create(RPC_ANYSOCK)) == NULL || 3339202Srgrimes (tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0)) == NULL) { 3341558Srgrimes syslog(LOG_ERR, "Can't create socket"); 3351558Srgrimes exit(1); 3361558Srgrimes } 3379336Sdfr pmap_unset(RPCPROG_MNT, 1); 3389336Sdfr pmap_unset(RPCPROG_MNT, 3); 3399336Sdfr if (!svc_register(udptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_UDP) || 3409336Sdfr !svc_register(udptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_UDP) || 3419336Sdfr !svc_register(tcptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_TCP) || 3429336Sdfr !svc_register(tcptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_TCP)) { 3431558Srgrimes syslog(LOG_ERR, "Can't register mount"); 3441558Srgrimes exit(1); 3451558Srgrimes } 3461558Srgrimes svc_run(); 3471558Srgrimes syslog(LOG_ERR, "Mountd died"); 3481558Srgrimes exit(1); 3491558Srgrimes} 3501558Srgrimes 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; 3651558Srgrimes u_long saddr; 3669336Sdfr u_short sport; 36723681Speter char rpcpath[RPCMNT_PATHLEN + 1], dirpath[MAXPATHLEN]; 3689336Sdfr int bad = ENOENT, defset, hostset; 3699336Sdfr sigset_t sighup_mask; 3701558Srgrimes 3719336Sdfr sigemptyset(&sighup_mask); 3729336Sdfr sigaddset(&sighup_mask, SIGHUP); 3731558Srgrimes saddr = transp->xp_raddr.sin_addr.s_addr; 3749336Sdfr sport = ntohs(transp->xp_raddr.sin_port); 3751558Srgrimes hp = (struct hostent *)NULL; 3761558Srgrimes switch (rqstp->rq_proc) { 3771558Srgrimes case NULLPROC: 3781558Srgrimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 3791558Srgrimes syslog(LOG_ERR, "Can't send reply"); 3801558Srgrimes return; 3811558Srgrimes case RPCMNT_MOUNT: 3829336Sdfr if (sport >= IPPORT_RESERVED && resvport_only) { 3831558Srgrimes svcerr_weakauth(transp); 3841558Srgrimes return; 3851558Srgrimes } 3861558Srgrimes if (!svc_getargs(transp, xdr_dir, rpcpath)) { 3871558Srgrimes svcerr_decode(transp); 3881558Srgrimes return; 3891558Srgrimes } 3901558Srgrimes 3911558Srgrimes /* 3921558Srgrimes * Get the real pathname and make sure it is a directory 3939336Sdfr * or a regular file if the -r option was specified 3949336Sdfr * and it exists. 3951558Srgrimes */ 3961558Srgrimes if (realpath(rpcpath, dirpath) == 0 || 3971558Srgrimes stat(dirpath, &stb) < 0 || 3989336Sdfr (!S_ISDIR(stb.st_mode) && 3999336Sdfr (dir_only || !S_ISREG(stb.st_mode))) || 4001558Srgrimes statfs(dirpath, &fsb) < 0) { 4011558Srgrimes chdir("/"); /* Just in case realpath doesn't */ 4021558Srgrimes if (debug) 4031558Srgrimes fprintf(stderr, "stat failed on %s\n", dirpath); 4041558Srgrimes if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 4051558Srgrimes syslog(LOG_ERR, "Can't send reply"); 4061558Srgrimes return; 4071558Srgrimes } 4081558Srgrimes 4091558Srgrimes /* Check in the exports list */ 4109336Sdfr sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 4111558Srgrimes ep = ex_search(&fsb.f_fsid); 4129336Sdfr hostset = defset = 0; 4139336Sdfr if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) || 4141558Srgrimes ((dp = dirp_search(ep->ex_dirl, dirpath)) && 4159336Sdfr chk_host(dp, saddr, &defset, &hostset)) || 4161558Srgrimes (defset && scan_tree(ep->ex_defdir, saddr) == 0 && 4171558Srgrimes scan_tree(ep->ex_dirl, saddr) == 0))) { 4189336Sdfr if (hostset & DP_HOSTSET) 4199336Sdfr fhr.fhr_flag = hostset; 4209336Sdfr else 4219336Sdfr fhr.fhr_flag = defset; 4229336Sdfr fhr.fhr_vers = rqstp->rq_vers; 4231558Srgrimes /* Get the file handle */ 42423681Speter memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t)); 4259336Sdfr if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) { 4261558Srgrimes bad = errno; 4271558Srgrimes syslog(LOG_ERR, "Can't get fh for %s", dirpath); 4281558Srgrimes if (!svc_sendreply(transp, xdr_long, 4291558Srgrimes (caddr_t)&bad)) 4301558Srgrimes syslog(LOG_ERR, "Can't send reply"); 4319336Sdfr sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 4321558Srgrimes return; 4331558Srgrimes } 4349336Sdfr if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr)) 4351558Srgrimes syslog(LOG_ERR, "Can't send reply"); 4361558Srgrimes if (hp == NULL) 4371558Srgrimes hp = gethostbyaddr((caddr_t)&saddr, 4381558Srgrimes sizeof(saddr), AF_INET); 4391558Srgrimes if (hp) 4401558Srgrimes add_mlist(hp->h_name, dirpath); 4411558Srgrimes else 4421558Srgrimes add_mlist(inet_ntoa(transp->xp_raddr.sin_addr), 4431558Srgrimes dirpath); 4441558Srgrimes if (debug) 4451558Srgrimes fprintf(stderr,"Mount successfull.\n"); 4461558Srgrimes } else { 4471558Srgrimes bad = EACCES; 4481558Srgrimes if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 4491558Srgrimes syslog(LOG_ERR, "Can't send reply"); 4501558Srgrimes } 4519336Sdfr sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 4521558Srgrimes return; 4531558Srgrimes case RPCMNT_DUMP: 4541558Srgrimes if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL)) 4551558Srgrimes syslog(LOG_ERR, "Can't send reply"); 4561558Srgrimes return; 4571558Srgrimes case RPCMNT_UMOUNT: 4589336Sdfr if (sport >= IPPORT_RESERVED && resvport_only) { 4591558Srgrimes svcerr_weakauth(transp); 4601558Srgrimes return; 4611558Srgrimes } 4621558Srgrimes if (!svc_getargs(transp, xdr_dir, dirpath)) { 4631558Srgrimes svcerr_decode(transp); 4641558Srgrimes return; 4651558Srgrimes } 4661558Srgrimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 4671558Srgrimes syslog(LOG_ERR, "Can't send reply"); 4681558Srgrimes hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 4691558Srgrimes if (hp) 4701558Srgrimes del_mlist(hp->h_name, dirpath); 4711558Srgrimes del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath); 4721558Srgrimes return; 4731558Srgrimes case RPCMNT_UMNTALL: 4749336Sdfr if (sport >= IPPORT_RESERVED && resvport_only) { 4751558Srgrimes svcerr_weakauth(transp); 4761558Srgrimes return; 4771558Srgrimes } 4781558Srgrimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 4791558Srgrimes syslog(LOG_ERR, "Can't send reply"); 4801558Srgrimes hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 4811558Srgrimes if (hp) 4821558Srgrimes del_mlist(hp->h_name, (char *)NULL); 4831558Srgrimes del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), (char *)NULL); 4841558Srgrimes return; 4851558Srgrimes case RPCMNT_EXPORT: 4861558Srgrimes if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL)) 4871558Srgrimes syslog(LOG_ERR, "Can't send reply"); 4881558Srgrimes return; 4891558Srgrimes default: 4901558Srgrimes svcerr_noproc(transp); 4911558Srgrimes return; 4921558Srgrimes } 4931558Srgrimes} 4941558Srgrimes 4951558Srgrimes/* 4961558Srgrimes * Xdr conversion for a dirpath string 4971558Srgrimes */ 4981558Srgrimesint 4991558Srgrimesxdr_dir(xdrsp, dirp) 5001558Srgrimes XDR *xdrsp; 5011558Srgrimes char *dirp; 5021558Srgrimes{ 5031558Srgrimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 5041558Srgrimes} 5051558Srgrimes 5061558Srgrimes/* 5079336Sdfr * Xdr routine to generate file handle reply 5081558Srgrimes */ 5091558Srgrimesint 5109336Sdfrxdr_fhs(xdrsp, cp) 5111558Srgrimes XDR *xdrsp; 5129336Sdfr caddr_t cp; 5131558Srgrimes{ 5149336Sdfr register struct fhreturn *fhrp = (struct fhreturn *)cp; 5159336Sdfr u_long ok = 0, len, auth; 5161558Srgrimes 5171558Srgrimes if (!xdr_long(xdrsp, &ok)) 5181558Srgrimes return (0); 5199336Sdfr switch (fhrp->fhr_vers) { 5209336Sdfr case 1: 5219336Sdfr return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH)); 5229336Sdfr case 3: 5239336Sdfr len = NFSX_V3FH; 5249336Sdfr if (!xdr_long(xdrsp, &len)) 5259336Sdfr return (0); 5269336Sdfr if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) 5279336Sdfr return (0); 5289336Sdfr if (fhrp->fhr_flag & DP_KERB) 5299336Sdfr auth = RPCAUTH_KERB4; 5309336Sdfr else 5319336Sdfr auth = RPCAUTH_UNIX; 5329336Sdfr len = 1; 5339336Sdfr if (!xdr_long(xdrsp, &len)) 5349336Sdfr return (0); 5359336Sdfr return (xdr_long(xdrsp, &auth)); 5369336Sdfr }; 5379336Sdfr return (0); 5381558Srgrimes} 5391558Srgrimes 5401558Srgrimesint 5411558Srgrimesxdr_mlist(xdrsp, cp) 5421558Srgrimes XDR *xdrsp; 5431558Srgrimes caddr_t cp; 5441558Srgrimes{ 5451558Srgrimes struct mountlist *mlp; 5461558Srgrimes int true = 1; 5471558Srgrimes int false = 0; 5481558Srgrimes char *strp; 5491558Srgrimes 5501558Srgrimes mlp = mlhead; 5511558Srgrimes while (mlp) { 5521558Srgrimes if (!xdr_bool(xdrsp, &true)) 5531558Srgrimes return (0); 5541558Srgrimes strp = &mlp->ml_host[0]; 5551558Srgrimes if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 5561558Srgrimes return (0); 5571558Srgrimes strp = &mlp->ml_dirp[0]; 5581558Srgrimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 5591558Srgrimes return (0); 5601558Srgrimes mlp = mlp->ml_next; 5611558Srgrimes } 5621558Srgrimes if (!xdr_bool(xdrsp, &false)) 5631558Srgrimes return (0); 5641558Srgrimes return (1); 5651558Srgrimes} 5661558Srgrimes 5671558Srgrimes/* 5681558Srgrimes * Xdr conversion for export list 5691558Srgrimes */ 5701558Srgrimesint 5711558Srgrimesxdr_explist(xdrsp, cp) 5721558Srgrimes XDR *xdrsp; 5731558Srgrimes caddr_t cp; 5741558Srgrimes{ 5751558Srgrimes struct exportlist *ep; 5761558Srgrimes int false = 0; 5779336Sdfr int putdef; 5789336Sdfr sigset_t sighup_mask; 5791558Srgrimes 5809336Sdfr sigemptyset(&sighup_mask); 5819336Sdfr sigaddset(&sighup_mask, SIGHUP); 5829336Sdfr sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 5831558Srgrimes ep = exphead; 5841558Srgrimes while (ep) { 5851558Srgrimes putdef = 0; 5861558Srgrimes if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, &putdef)) 5871558Srgrimes goto errout; 5881558Srgrimes if (ep->ex_defdir && putdef == 0 && 5891558Srgrimes put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL, 5901558Srgrimes &putdef)) 5911558Srgrimes goto errout; 5921558Srgrimes ep = ep->ex_next; 5931558Srgrimes } 5949336Sdfr sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 5951558Srgrimes if (!xdr_bool(xdrsp, &false)) 5961558Srgrimes return (0); 5971558Srgrimes return (1); 5981558Srgrimeserrout: 5999336Sdfr sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6001558Srgrimes return (0); 6011558Srgrimes} 6021558Srgrimes 6031558Srgrimes/* 6041558Srgrimes * Called from xdr_explist() to traverse the tree and export the 6051558Srgrimes * directory paths. 6061558Srgrimes */ 6071558Srgrimesint 6081558Srgrimesput_exlist(dp, xdrsp, adp, putdefp) 6091558Srgrimes struct dirlist *dp; 6101558Srgrimes XDR *xdrsp; 6111558Srgrimes struct dirlist *adp; 6121558Srgrimes int *putdefp; 6131558Srgrimes{ 6141558Srgrimes struct grouplist *grp; 6151558Srgrimes struct hostlist *hp; 6161558Srgrimes int true = 1; 6171558Srgrimes int false = 0; 6181558Srgrimes int gotalldir = 0; 6191558Srgrimes char *strp; 6201558Srgrimes 6211558Srgrimes if (dp) { 6221558Srgrimes if (put_exlist(dp->dp_left, xdrsp, adp, putdefp)) 6231558Srgrimes return (1); 6241558Srgrimes if (!xdr_bool(xdrsp, &true)) 6251558Srgrimes return (1); 6261558Srgrimes strp = dp->dp_dirp; 6271558Srgrimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 6281558Srgrimes return (1); 6291558Srgrimes if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) { 6301558Srgrimes gotalldir = 1; 6311558Srgrimes *putdefp = 1; 6321558Srgrimes } 6331558Srgrimes if ((dp->dp_flag & DP_DEFSET) == 0 && 6341558Srgrimes (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) { 6351558Srgrimes hp = dp->dp_hosts; 6361558Srgrimes while (hp) { 6371558Srgrimes grp = hp->ht_grp; 6381558Srgrimes if (grp->gr_type == GT_HOST) { 6391558Srgrimes if (!xdr_bool(xdrsp, &true)) 6401558Srgrimes return (1); 6411558Srgrimes strp = grp->gr_ptr.gt_hostent->h_name; 6428871Srgrimes if (!xdr_string(xdrsp, &strp, 6431558Srgrimes RPCMNT_NAMELEN)) 6441558Srgrimes return (1); 6451558Srgrimes } else if (grp->gr_type == GT_NET) { 6461558Srgrimes if (!xdr_bool(xdrsp, &true)) 6471558Srgrimes return (1); 6481558Srgrimes strp = grp->gr_ptr.gt_net.nt_name; 6498871Srgrimes if (!xdr_string(xdrsp, &strp, 6501558Srgrimes RPCMNT_NAMELEN)) 6511558Srgrimes return (1); 6521558Srgrimes } 6531558Srgrimes hp = hp->ht_next; 6541558Srgrimes if (gotalldir && hp == (struct hostlist *)NULL) { 6551558Srgrimes hp = adp->dp_hosts; 6561558Srgrimes gotalldir = 0; 6571558Srgrimes } 6581558Srgrimes } 6591558Srgrimes } 6601558Srgrimes if (!xdr_bool(xdrsp, &false)) 6611558Srgrimes return (1); 6621558Srgrimes if (put_exlist(dp->dp_right, xdrsp, adp, putdefp)) 6631558Srgrimes return (1); 6641558Srgrimes } 6651558Srgrimes return (0); 6661558Srgrimes} 6671558Srgrimes 6681558Srgrimes#define LINESIZ 10240 6691558Srgrimeschar line[LINESIZ]; 6701558SrgrimesFILE *exp_file; 6711558Srgrimes 6721558Srgrimes/* 6731558Srgrimes * Get the export list 6741558Srgrimes */ 6751558Srgrimesvoid 6761558Srgrimesget_exportlist() 6771558Srgrimes{ 6781558Srgrimes struct exportlist *ep, *ep2; 6791558Srgrimes struct grouplist *grp, *tgrp; 6801558Srgrimes struct exportlist **epp; 6811558Srgrimes struct dirlist *dirhead; 6821558Srgrimes struct statfs fsb, *fsp; 6831558Srgrimes struct hostent *hpe; 6841558Srgrimes struct ucred anon; 6851558Srgrimes char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; 6861558Srgrimes int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp; 6871558Srgrimes 6881558Srgrimes /* 6891558Srgrimes * First, get rid of the old list 6901558Srgrimes */ 6911558Srgrimes ep = exphead; 6921558Srgrimes while (ep) { 6931558Srgrimes ep2 = ep; 6941558Srgrimes ep = ep->ex_next; 6951558Srgrimes free_exp(ep2); 6961558Srgrimes } 6971558Srgrimes exphead = (struct exportlist *)NULL; 6981558Srgrimes 6991558Srgrimes grp = grphead; 7001558Srgrimes while (grp) { 7011558Srgrimes tgrp = grp; 7021558Srgrimes grp = grp->gr_next; 7031558Srgrimes free_grp(tgrp); 7041558Srgrimes } 7051558Srgrimes grphead = (struct grouplist *)NULL; 7061558Srgrimes 7071558Srgrimes /* 7081558Srgrimes * And delete exports that are in the kernel for all local 7091558Srgrimes * file systems. 7101558Srgrimes * XXX: Should know how to handle all local exportable file systems 71123681Speter * instead of just "ufs". 7121558Srgrimes */ 7131558Srgrimes num = getmntinfo(&fsp, MNT_NOWAIT); 7141558Srgrimes for (i = 0; i < num; i++) { 7151558Srgrimes union { 7161558Srgrimes struct ufs_args ua; 7171558Srgrimes struct iso_args ia; 7181558Srgrimes struct mfs_args ma; 7199336Sdfr struct msdosfs_args da; 7201558Srgrimes } targs; 7211558Srgrimes 72223681Speter if (!strcmp(fsp->f_fstypename, "mfs") || 72323681Speter !strcmp(fsp->f_fstypename, "ufs") || 72423681Speter !strcmp(fsp->f_fstypename, "msdos") || 72523681Speter !strcmp(fsp->f_fstypename, "cd9660")) { 7269336Sdfr targs.ua.fspec = NULL; 7279336Sdfr targs.ua.export.ex_flags = MNT_DELEXPORT; 7289336Sdfr if (mount(fsp->f_fstypename, fsp->f_mntonname, 7291558Srgrimes fsp->f_flags | MNT_UPDATE, 7301558Srgrimes (caddr_t)&targs) < 0) 7311558Srgrimes syslog(LOG_ERR, "Can't delete exports for %s", 7321558Srgrimes fsp->f_mntonname); 7331558Srgrimes } 7341558Srgrimes fsp++; 7351558Srgrimes } 7361558Srgrimes 7371558Srgrimes /* 7381558Srgrimes * Read in the exports file and build the list, calling 7391558Srgrimes * mount() as we go along to push the export rules into the kernel. 7401558Srgrimes */ 7411558Srgrimes if ((exp_file = fopen(exname, "r")) == NULL) { 7421558Srgrimes syslog(LOG_ERR, "Can't open %s", exname); 7431558Srgrimes exit(2); 7441558Srgrimes } 7451558Srgrimes dirhead = (struct dirlist *)NULL; 7461558Srgrimes while (get_line()) { 7471558Srgrimes if (debug) 7481558Srgrimes fprintf(stderr,"Got line %s\n",line); 7491558Srgrimes cp = line; 7501558Srgrimes nextfield(&cp, &endcp); 7511558Srgrimes if (*cp == '#') 7521558Srgrimes goto nextline; 7531558Srgrimes 7541558Srgrimes /* 7551558Srgrimes * Set defaults. 7561558Srgrimes */ 7571558Srgrimes has_host = FALSE; 7581558Srgrimes anon = def_anon; 7591558Srgrimes exflags = MNT_EXPORTED; 7601558Srgrimes got_nondir = 0; 7611558Srgrimes opt_flags = 0; 7621558Srgrimes ep = (struct exportlist *)NULL; 7631558Srgrimes 7641558Srgrimes /* 7651558Srgrimes * Create new exports list entry 7661558Srgrimes */ 7671558Srgrimes len = endcp-cp; 7681558Srgrimes tgrp = grp = get_grp(); 7691558Srgrimes while (len > 0) { 7701558Srgrimes if (len > RPCMNT_NAMELEN) { 7711558Srgrimes getexp_err(ep, tgrp); 7721558Srgrimes goto nextline; 7731558Srgrimes } 7741558Srgrimes if (*cp == '-') { 7751558Srgrimes if (ep == (struct exportlist *)NULL) { 7761558Srgrimes getexp_err(ep, tgrp); 7771558Srgrimes goto nextline; 7781558Srgrimes } 7791558Srgrimes if (debug) 7801558Srgrimes fprintf(stderr, "doing opt %s\n", cp); 7811558Srgrimes got_nondir = 1; 7821558Srgrimes if (do_opt(&cp, &endcp, ep, grp, &has_host, 7831558Srgrimes &exflags, &anon)) { 7841558Srgrimes getexp_err(ep, tgrp); 7851558Srgrimes goto nextline; 7861558Srgrimes } 7871558Srgrimes } else if (*cp == '/') { 7881558Srgrimes savedc = *endcp; 7891558Srgrimes *endcp = '\0'; 7901558Srgrimes if (check_dirpath(cp) && 7911558Srgrimes statfs(cp, &fsb) >= 0) { 7921558Srgrimes if (got_nondir) { 7931558Srgrimes syslog(LOG_ERR, "Dirs must be first"); 7941558Srgrimes getexp_err(ep, tgrp); 7951558Srgrimes goto nextline; 7961558Srgrimes } 7971558Srgrimes if (ep) { 7981558Srgrimes if (ep->ex_fs.val[0] != fsb.f_fsid.val[0] || 7991558Srgrimes ep->ex_fs.val[1] != fsb.f_fsid.val[1]) { 8001558Srgrimes getexp_err(ep, tgrp); 8011558Srgrimes goto nextline; 8021558Srgrimes } 8031558Srgrimes } else { 8041558Srgrimes /* 8051558Srgrimes * See if this directory is already 8061558Srgrimes * in the list. 8071558Srgrimes */ 8081558Srgrimes ep = ex_search(&fsb.f_fsid); 8091558Srgrimes if (ep == (struct exportlist *)NULL) { 8101558Srgrimes ep = get_exp(); 8111558Srgrimes ep->ex_fs = fsb.f_fsid; 8121558Srgrimes ep->ex_fsdir = (char *) 8131558Srgrimes malloc(strlen(fsb.f_mntonname) + 1); 8141558Srgrimes if (ep->ex_fsdir) 8151558Srgrimes strcpy(ep->ex_fsdir, 8161558Srgrimes fsb.f_mntonname); 8171558Srgrimes else 8181558Srgrimes out_of_mem(); 8191558Srgrimes if (debug) 8201558Srgrimes fprintf(stderr, 8211558Srgrimes "Making new ep fs=0x%x,0x%x\n", 8221558Srgrimes fsb.f_fsid.val[0], 8231558Srgrimes fsb.f_fsid.val[1]); 8241558Srgrimes } else if (debug) 8251558Srgrimes fprintf(stderr, 8261558Srgrimes "Found ep fs=0x%x,0x%x\n", 8271558Srgrimes fsb.f_fsid.val[0], 8281558Srgrimes fsb.f_fsid.val[1]); 8291558Srgrimes } 8301558Srgrimes 8311558Srgrimes /* 8321558Srgrimes * Add dirpath to export mount point. 8331558Srgrimes */ 8341558Srgrimes dirp = add_expdir(&dirhead, cp, len); 8351558Srgrimes dirplen = len; 8361558Srgrimes } else { 8371558Srgrimes getexp_err(ep, tgrp); 8381558Srgrimes goto nextline; 8391558Srgrimes } 8401558Srgrimes *endcp = savedc; 8411558Srgrimes } else { 8421558Srgrimes savedc = *endcp; 8431558Srgrimes *endcp = '\0'; 8441558Srgrimes got_nondir = 1; 8451558Srgrimes if (ep == (struct exportlist *)NULL) { 8461558Srgrimes getexp_err(ep, tgrp); 8471558Srgrimes goto nextline; 8481558Srgrimes } 8491558Srgrimes 8501558Srgrimes /* 8511558Srgrimes * Get the host or netgroup. 8521558Srgrimes */ 8531558Srgrimes setnetgrent(cp); 8541558Srgrimes netgrp = getnetgrent(&hst, &usr, &dom); 8551558Srgrimes do { 8561558Srgrimes if (has_host) { 8571558Srgrimes grp->gr_next = get_grp(); 8581558Srgrimes grp = grp->gr_next; 8591558Srgrimes } 8601558Srgrimes if (netgrp) { 8617401Swpaul if (get_host(hst, grp, tgrp)) { 8621558Srgrimes syslog(LOG_ERR, "Bad netgroup %s", cp); 8631558Srgrimes getexp_err(ep, tgrp); 8649336Sdfr endnetgrent(); 8651558Srgrimes goto nextline; 8661558Srgrimes } 8677401Swpaul } else if (get_host(cp, grp, tgrp)) { 8681558Srgrimes getexp_err(ep, tgrp); 8691558Srgrimes goto nextline; 8701558Srgrimes } 8711558Srgrimes has_host = TRUE; 8721558Srgrimes } while (netgrp && getnetgrent(&hst, &usr, &dom)); 8731558Srgrimes endnetgrent(); 8741558Srgrimes *endcp = savedc; 8751558Srgrimes } 8761558Srgrimes cp = endcp; 8771558Srgrimes nextfield(&cp, &endcp); 8781558Srgrimes len = endcp - cp; 8791558Srgrimes } 8801558Srgrimes if (check_options(dirhead)) { 8811558Srgrimes getexp_err(ep, tgrp); 8821558Srgrimes goto nextline; 8831558Srgrimes } 8841558Srgrimes if (!has_host) { 8851558Srgrimes grp->gr_type = GT_HOST; 8861558Srgrimes if (debug) 8871558Srgrimes fprintf(stderr,"Adding a default entry\n"); 8881558Srgrimes /* add a default group and make the grp list NULL */ 8891558Srgrimes hpe = (struct hostent *)malloc(sizeof(struct hostent)); 8901558Srgrimes if (hpe == (struct hostent *)NULL) 8911558Srgrimes out_of_mem(); 89212348Sjoerg hpe->h_name = strdup("Default"); 8931558Srgrimes hpe->h_addrtype = AF_INET; 8941558Srgrimes hpe->h_length = sizeof (u_long); 8951558Srgrimes hpe->h_addr_list = (char **)NULL; 8961558Srgrimes grp->gr_ptr.gt_hostent = hpe; 8971558Srgrimes 8981558Srgrimes /* 8991558Srgrimes * Don't allow a network export coincide with a list of 9001558Srgrimes * host(s) on the same line. 9011558Srgrimes */ 9021558Srgrimes } else if ((opt_flags & OP_NET) && tgrp->gr_next) { 9031558Srgrimes getexp_err(ep, tgrp); 9041558Srgrimes goto nextline; 9051558Srgrimes } 9061558Srgrimes 9071558Srgrimes /* 9081558Srgrimes * Loop through hosts, pushing the exports into the kernel. 9091558Srgrimes * After loop, tgrp points to the start of the list and 9101558Srgrimes * grp points to the last entry in the list. 9111558Srgrimes */ 9121558Srgrimes grp = tgrp; 9131558Srgrimes do { 9141558Srgrimes if (do_mount(ep, grp, exflags, &anon, dirp, 9151558Srgrimes dirplen, &fsb)) { 9161558Srgrimes getexp_err(ep, tgrp); 9171558Srgrimes goto nextline; 9181558Srgrimes } 9191558Srgrimes } while (grp->gr_next && (grp = grp->gr_next)); 9201558Srgrimes 9211558Srgrimes /* 9221558Srgrimes * Success. Update the data structures. 9231558Srgrimes */ 9241558Srgrimes if (has_host) { 9259336Sdfr hang_dirp(dirhead, tgrp, ep, opt_flags); 9261558Srgrimes grp->gr_next = grphead; 9271558Srgrimes grphead = tgrp; 9281558Srgrimes } else { 9291558Srgrimes hang_dirp(dirhead, (struct grouplist *)NULL, ep, 9309336Sdfr opt_flags); 9311558Srgrimes free_grp(grp); 9321558Srgrimes } 9331558Srgrimes dirhead = (struct dirlist *)NULL; 9341558Srgrimes if ((ep->ex_flag & EX_LINKED) == 0) { 9351558Srgrimes ep2 = exphead; 9361558Srgrimes epp = &exphead; 9371558Srgrimes 9381558Srgrimes /* 9391558Srgrimes * Insert in the list in alphabetical order. 9401558Srgrimes */ 9411558Srgrimes while (ep2 && strcmp(ep2->ex_fsdir, ep->ex_fsdir) < 0) { 9421558Srgrimes epp = &ep2->ex_next; 9431558Srgrimes ep2 = ep2->ex_next; 9441558Srgrimes } 9451558Srgrimes if (ep2) 9461558Srgrimes ep->ex_next = ep2; 9471558Srgrimes *epp = ep; 9481558Srgrimes ep->ex_flag |= EX_LINKED; 9491558Srgrimes } 9501558Srgrimesnextline: 9511558Srgrimes if (dirhead) { 9521558Srgrimes free_dir(dirhead); 9531558Srgrimes dirhead = (struct dirlist *)NULL; 9541558Srgrimes } 9551558Srgrimes } 9561558Srgrimes fclose(exp_file); 9571558Srgrimes} 9581558Srgrimes 9591558Srgrimes/* 9601558Srgrimes * Allocate an export list element 9611558Srgrimes */ 9621558Srgrimesstruct exportlist * 9631558Srgrimesget_exp() 9641558Srgrimes{ 9651558Srgrimes struct exportlist *ep; 9661558Srgrimes 9671558Srgrimes ep = (struct exportlist *)malloc(sizeof (struct exportlist)); 9681558Srgrimes if (ep == (struct exportlist *)NULL) 9691558Srgrimes out_of_mem(); 97023681Speter memset(ep, 0, sizeof(struct exportlist)); 9711558Srgrimes return (ep); 9721558Srgrimes} 9731558Srgrimes 9741558Srgrimes/* 9751558Srgrimes * Allocate a group list element 9761558Srgrimes */ 9771558Srgrimesstruct grouplist * 9781558Srgrimesget_grp() 9791558Srgrimes{ 9801558Srgrimes struct grouplist *gp; 9811558Srgrimes 9821558Srgrimes gp = (struct grouplist *)malloc(sizeof (struct grouplist)); 9831558Srgrimes if (gp == (struct grouplist *)NULL) 9841558Srgrimes out_of_mem(); 98523681Speter memset(gp, 0, sizeof(struct grouplist)); 9861558Srgrimes return (gp); 9871558Srgrimes} 9881558Srgrimes 9891558Srgrimes/* 9901558Srgrimes * Clean up upon an error in get_exportlist(). 9911558Srgrimes */ 9921558Srgrimesvoid 9931558Srgrimesgetexp_err(ep, grp) 9941558Srgrimes struct exportlist *ep; 9951558Srgrimes struct grouplist *grp; 9961558Srgrimes{ 9971558Srgrimes struct grouplist *tgrp; 9981558Srgrimes 9991558Srgrimes syslog(LOG_ERR, "Bad exports list line %s", line); 10001558Srgrimes if (ep && (ep->ex_flag & EX_LINKED) == 0) 10011558Srgrimes free_exp(ep); 10021558Srgrimes while (grp) { 10031558Srgrimes tgrp = grp; 10041558Srgrimes grp = grp->gr_next; 10051558Srgrimes free_grp(tgrp); 10061558Srgrimes } 10071558Srgrimes} 10081558Srgrimes 10091558Srgrimes/* 10101558Srgrimes * Search the export list for a matching fs. 10111558Srgrimes */ 10121558Srgrimesstruct exportlist * 10131558Srgrimesex_search(fsid) 10141558Srgrimes fsid_t *fsid; 10151558Srgrimes{ 10161558Srgrimes struct exportlist *ep; 10171558Srgrimes 10181558Srgrimes ep = exphead; 10191558Srgrimes while (ep) { 10201558Srgrimes if (ep->ex_fs.val[0] == fsid->val[0] && 10211558Srgrimes ep->ex_fs.val[1] == fsid->val[1]) 10221558Srgrimes return (ep); 10231558Srgrimes ep = ep->ex_next; 10241558Srgrimes } 10251558Srgrimes return (ep); 10261558Srgrimes} 10271558Srgrimes 10281558Srgrimes/* 10291558Srgrimes * Add a directory path to the list. 10301558Srgrimes */ 10311558Srgrimeschar * 10321558Srgrimesadd_expdir(dpp, cp, len) 10331558Srgrimes struct dirlist **dpp; 10341558Srgrimes char *cp; 10351558Srgrimes int len; 10361558Srgrimes{ 10371558Srgrimes struct dirlist *dp; 10381558Srgrimes 10391558Srgrimes dp = (struct dirlist *)malloc(sizeof (struct dirlist) + len); 10401558Srgrimes dp->dp_left = *dpp; 10411558Srgrimes dp->dp_right = (struct dirlist *)NULL; 10421558Srgrimes dp->dp_flag = 0; 10431558Srgrimes dp->dp_hosts = (struct hostlist *)NULL; 10441558Srgrimes strcpy(dp->dp_dirp, cp); 10451558Srgrimes *dpp = dp; 10461558Srgrimes return (dp->dp_dirp); 10471558Srgrimes} 10481558Srgrimes 10491558Srgrimes/* 10501558Srgrimes * Hang the dir list element off the dirpath binary tree as required 10511558Srgrimes * and update the entry for host. 10521558Srgrimes */ 10531558Srgrimesvoid 10549336Sdfrhang_dirp(dp, grp, ep, flags) 10551558Srgrimes struct dirlist *dp; 10561558Srgrimes struct grouplist *grp; 10571558Srgrimes struct exportlist *ep; 10589336Sdfr int flags; 10591558Srgrimes{ 10601558Srgrimes struct hostlist *hp; 10611558Srgrimes struct dirlist *dp2; 10621558Srgrimes 10639336Sdfr if (flags & OP_ALLDIRS) { 10641558Srgrimes if (ep->ex_defdir) 10651558Srgrimes free((caddr_t)dp); 10661558Srgrimes else 10671558Srgrimes ep->ex_defdir = dp; 10689336Sdfr if (grp == (struct grouplist *)NULL) { 10691558Srgrimes ep->ex_defdir->dp_flag |= DP_DEFSET; 10709336Sdfr if (flags & OP_KERB) 10719336Sdfr ep->ex_defdir->dp_flag |= DP_KERB; 10729336Sdfr } else while (grp) { 10731558Srgrimes hp = get_ht(); 10749336Sdfr if (flags & OP_KERB) 10759336Sdfr hp->ht_flag |= DP_KERB; 10761558Srgrimes hp->ht_grp = grp; 10771558Srgrimes hp->ht_next = ep->ex_defdir->dp_hosts; 10781558Srgrimes ep->ex_defdir->dp_hosts = hp; 10791558Srgrimes grp = grp->gr_next; 10801558Srgrimes } 10811558Srgrimes } else { 10821558Srgrimes 10831558Srgrimes /* 10841558Srgrimes * Loop throught the directories adding them to the tree. 10851558Srgrimes */ 10861558Srgrimes while (dp) { 10871558Srgrimes dp2 = dp->dp_left; 10889336Sdfr add_dlist(&ep->ex_dirl, dp, grp, flags); 10891558Srgrimes dp = dp2; 10901558Srgrimes } 10911558Srgrimes } 10921558Srgrimes} 10931558Srgrimes 10941558Srgrimes/* 10951558Srgrimes * Traverse the binary tree either updating a node that is already there 10961558Srgrimes * for the new directory or adding the new node. 10971558Srgrimes */ 10981558Srgrimesvoid 10999336Sdfradd_dlist(dpp, newdp, grp, flags) 11001558Srgrimes struct dirlist **dpp; 11011558Srgrimes struct dirlist *newdp; 11021558Srgrimes struct grouplist *grp; 11039336Sdfr int flags; 11041558Srgrimes{ 11051558Srgrimes struct dirlist *dp; 11061558Srgrimes struct hostlist *hp; 11071558Srgrimes int cmp; 11081558Srgrimes 11091558Srgrimes dp = *dpp; 11101558Srgrimes if (dp) { 11111558Srgrimes cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); 11121558Srgrimes if (cmp > 0) { 11139336Sdfr add_dlist(&dp->dp_left, newdp, grp, flags); 11141558Srgrimes return; 11151558Srgrimes } else if (cmp < 0) { 11169336Sdfr add_dlist(&dp->dp_right, newdp, grp, flags); 11171558Srgrimes return; 11181558Srgrimes } else 11191558Srgrimes free((caddr_t)newdp); 11201558Srgrimes } else { 11211558Srgrimes dp = newdp; 11221558Srgrimes dp->dp_left = (struct dirlist *)NULL; 11231558Srgrimes *dpp = dp; 11241558Srgrimes } 11251558Srgrimes if (grp) { 11261558Srgrimes 11271558Srgrimes /* 11281558Srgrimes * Hang all of the host(s) off of the directory point. 11291558Srgrimes */ 11301558Srgrimes do { 11311558Srgrimes hp = get_ht(); 11329336Sdfr if (flags & OP_KERB) 11339336Sdfr hp->ht_flag |= DP_KERB; 11341558Srgrimes hp->ht_grp = grp; 11351558Srgrimes hp->ht_next = dp->dp_hosts; 11361558Srgrimes dp->dp_hosts = hp; 11371558Srgrimes grp = grp->gr_next; 11381558Srgrimes } while (grp); 11399336Sdfr } else { 11401558Srgrimes dp->dp_flag |= DP_DEFSET; 11419336Sdfr if (flags & OP_KERB) 11429336Sdfr dp->dp_flag |= DP_KERB; 11439336Sdfr } 11441558Srgrimes} 11451558Srgrimes 11461558Srgrimes/* 11471558Srgrimes * Search for a dirpath on the export point. 11481558Srgrimes */ 11491558Srgrimesstruct dirlist * 11501558Srgrimesdirp_search(dp, dirpath) 11511558Srgrimes struct dirlist *dp; 11521558Srgrimes char *dirpath; 11531558Srgrimes{ 11541558Srgrimes int cmp; 11551558Srgrimes 11561558Srgrimes if (dp) { 11571558Srgrimes cmp = strcmp(dp->dp_dirp, dirpath); 11581558Srgrimes if (cmp > 0) 11591558Srgrimes return (dirp_search(dp->dp_left, dirpath)); 11601558Srgrimes else if (cmp < 0) 11611558Srgrimes return (dirp_search(dp->dp_right, dirpath)); 11621558Srgrimes else 11631558Srgrimes return (dp); 11641558Srgrimes } 11651558Srgrimes return (dp); 11661558Srgrimes} 11671558Srgrimes 11681558Srgrimes/* 11691558Srgrimes * Scan for a host match in a directory tree. 11701558Srgrimes */ 11711558Srgrimesint 11729336Sdfrchk_host(dp, saddr, defsetp, hostsetp) 11731558Srgrimes struct dirlist *dp; 11741558Srgrimes u_long saddr; 11751558Srgrimes int *defsetp; 11769336Sdfr int *hostsetp; 11771558Srgrimes{ 11781558Srgrimes struct hostlist *hp; 11791558Srgrimes struct grouplist *grp; 11801558Srgrimes u_long **addrp; 11811558Srgrimes 11821558Srgrimes if (dp) { 11831558Srgrimes if (dp->dp_flag & DP_DEFSET) 11849336Sdfr *defsetp = dp->dp_flag; 11851558Srgrimes hp = dp->dp_hosts; 11861558Srgrimes while (hp) { 11871558Srgrimes grp = hp->ht_grp; 11881558Srgrimes switch (grp->gr_type) { 11891558Srgrimes case GT_HOST: 11901558Srgrimes addrp = (u_long **) 11911558Srgrimes grp->gr_ptr.gt_hostent->h_addr_list; 11921558Srgrimes while (*addrp) { 11939336Sdfr if (**addrp == saddr) { 11949336Sdfr *hostsetp = (hp->ht_flag | DP_HOSTSET); 11951558Srgrimes return (1); 11969336Sdfr } 11971558Srgrimes addrp++; 11981558Srgrimes } 11991558Srgrimes break; 12001558Srgrimes case GT_NET: 12011558Srgrimes if ((saddr & grp->gr_ptr.gt_net.nt_mask) == 12029336Sdfr grp->gr_ptr.gt_net.nt_net) { 12039336Sdfr *hostsetp = (hp->ht_flag | DP_HOSTSET); 12041558Srgrimes return (1); 12059336Sdfr } 12061558Srgrimes break; 12071558Srgrimes }; 12081558Srgrimes hp = hp->ht_next; 12091558Srgrimes } 12101558Srgrimes } 12111558Srgrimes return (0); 12121558Srgrimes} 12131558Srgrimes 12141558Srgrimes/* 12151558Srgrimes * Scan tree for a host that matches the address. 12161558Srgrimes */ 12171558Srgrimesint 12181558Srgrimesscan_tree(dp, saddr) 12191558Srgrimes struct dirlist *dp; 12201558Srgrimes u_long saddr; 12211558Srgrimes{ 12229336Sdfr int defset, hostset; 12231558Srgrimes 12241558Srgrimes if (dp) { 12251558Srgrimes if (scan_tree(dp->dp_left, saddr)) 12261558Srgrimes return (1); 12279336Sdfr if (chk_host(dp, saddr, &defset, &hostset)) 12281558Srgrimes return (1); 12291558Srgrimes if (scan_tree(dp->dp_right, saddr)) 12301558Srgrimes return (1); 12311558Srgrimes } 12321558Srgrimes return (0); 12331558Srgrimes} 12341558Srgrimes 12351558Srgrimes/* 12361558Srgrimes * Traverse the dirlist tree and free it up. 12371558Srgrimes */ 12381558Srgrimesvoid 12391558Srgrimesfree_dir(dp) 12401558Srgrimes struct dirlist *dp; 12411558Srgrimes{ 12421558Srgrimes 12431558Srgrimes if (dp) { 12441558Srgrimes free_dir(dp->dp_left); 12451558Srgrimes free_dir(dp->dp_right); 12461558Srgrimes free_host(dp->dp_hosts); 12471558Srgrimes free((caddr_t)dp); 12481558Srgrimes } 12491558Srgrimes} 12501558Srgrimes 12511558Srgrimes/* 12521558Srgrimes * Parse the option string and update fields. 12531558Srgrimes * Option arguments may either be -<option>=<value> or 12541558Srgrimes * -<option> <value> 12551558Srgrimes */ 12561558Srgrimesint 12571558Srgrimesdo_opt(cpp, endcpp, ep, grp, has_hostp, exflagsp, cr) 12581558Srgrimes char **cpp, **endcpp; 12591558Srgrimes struct exportlist *ep; 12601558Srgrimes struct grouplist *grp; 12611558Srgrimes int *has_hostp; 12621558Srgrimes int *exflagsp; 12631558Srgrimes struct ucred *cr; 12641558Srgrimes{ 12651558Srgrimes char *cpoptarg, *cpoptend; 12661558Srgrimes char *cp, *endcp, *cpopt, savedc, savedc2; 12671558Srgrimes int allflag, usedarg; 12681558Srgrimes 12691558Srgrimes cpopt = *cpp; 12701558Srgrimes cpopt++; 12711558Srgrimes cp = *endcpp; 12721558Srgrimes savedc = *cp; 12731558Srgrimes *cp = '\0'; 12741558Srgrimes while (cpopt && *cpopt) { 12751558Srgrimes allflag = 1; 12761558Srgrimes usedarg = -2; 127723681Speter if (cpoptend = strchr(cpopt, ',')) { 12781558Srgrimes *cpoptend++ = '\0'; 127923681Speter if (cpoptarg = strchr(cpopt, '=')) 12801558Srgrimes *cpoptarg++ = '\0'; 12811558Srgrimes } else { 128223681Speter if (cpoptarg = strchr(cpopt, '=')) 12831558Srgrimes *cpoptarg++ = '\0'; 12841558Srgrimes else { 12851558Srgrimes *cp = savedc; 12861558Srgrimes nextfield(&cp, &endcp); 12871558Srgrimes **endcpp = '\0'; 12881558Srgrimes if (endcp > cp && *cp != '-') { 12891558Srgrimes cpoptarg = cp; 12901558Srgrimes savedc2 = *endcp; 12911558Srgrimes *endcp = '\0'; 12921558Srgrimes usedarg = 0; 12931558Srgrimes } 12941558Srgrimes } 12951558Srgrimes } 12961558Srgrimes if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 12971558Srgrimes *exflagsp |= MNT_EXRDONLY; 12981558Srgrimes } else if (cpoptarg && (!strcmp(cpopt, "maproot") || 12991558Srgrimes !(allflag = strcmp(cpopt, "mapall")) || 13001558Srgrimes !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) { 13011558Srgrimes usedarg++; 13021558Srgrimes parsecred(cpoptarg, cr); 13031558Srgrimes if (allflag == 0) { 13041558Srgrimes *exflagsp |= MNT_EXPORTANON; 13051558Srgrimes opt_flags |= OP_MAPALL; 13061558Srgrimes } else 13071558Srgrimes opt_flags |= OP_MAPROOT; 13081558Srgrimes } else if (!strcmp(cpopt, "kerb") || !strcmp(cpopt, "k")) { 13091558Srgrimes *exflagsp |= MNT_EXKERB; 13101558Srgrimes opt_flags |= OP_KERB; 13111558Srgrimes } else if (cpoptarg && (!strcmp(cpopt, "mask") || 13121558Srgrimes !strcmp(cpopt, "m"))) { 13131558Srgrimes if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { 13141558Srgrimes syslog(LOG_ERR, "Bad mask: %s", cpoptarg); 13151558Srgrimes return (1); 13161558Srgrimes } 13171558Srgrimes usedarg++; 13181558Srgrimes opt_flags |= OP_MASK; 13191558Srgrimes } else if (cpoptarg && (!strcmp(cpopt, "network") || 13201558Srgrimes !strcmp(cpopt, "n"))) { 13211558Srgrimes if (grp->gr_type != GT_NULL) { 13221558Srgrimes syslog(LOG_ERR, "Network/host conflict"); 13231558Srgrimes return (1); 13241558Srgrimes } else if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 0)) { 13251558Srgrimes syslog(LOG_ERR, "Bad net: %s", cpoptarg); 13261558Srgrimes return (1); 13271558Srgrimes } 13281558Srgrimes grp->gr_type = GT_NET; 13291558Srgrimes *has_hostp = 1; 13301558Srgrimes usedarg++; 13311558Srgrimes opt_flags |= OP_NET; 13321558Srgrimes } else if (!strcmp(cpopt, "alldirs")) { 13331558Srgrimes opt_flags |= OP_ALLDIRS; 13341558Srgrimes#ifdef ISO 13351558Srgrimes } else if (cpoptarg && !strcmp(cpopt, "iso")) { 13361558Srgrimes if (get_isoaddr(cpoptarg, grp)) { 13371558Srgrimes syslog(LOG_ERR, "Bad iso addr: %s", cpoptarg); 13381558Srgrimes return (1); 13391558Srgrimes } 13401558Srgrimes *has_hostp = 1; 13411558Srgrimes usedarg++; 13421558Srgrimes opt_flags |= OP_ISO; 13431558Srgrimes#endif /* ISO */ 13441558Srgrimes } else { 13451558Srgrimes syslog(LOG_ERR, "Bad opt %s", cpopt); 13461558Srgrimes return (1); 13471558Srgrimes } 13481558Srgrimes if (usedarg >= 0) { 13491558Srgrimes *endcp = savedc2; 13501558Srgrimes **endcpp = savedc; 13511558Srgrimes if (usedarg > 0) { 13521558Srgrimes *cpp = cp; 13531558Srgrimes *endcpp = endcp; 13541558Srgrimes } 13551558Srgrimes return (0); 13561558Srgrimes } 13571558Srgrimes cpopt = cpoptend; 13581558Srgrimes } 13591558Srgrimes **endcpp = savedc; 13601558Srgrimes return (0); 13611558Srgrimes} 13621558Srgrimes 13631558Srgrimes/* 13641558Srgrimes * Translate a character string to the corresponding list of network 13651558Srgrimes * addresses for a hostname. 13661558Srgrimes */ 13671558Srgrimesint 13687401Swpaulget_host(cp, grp, tgrp) 13691558Srgrimes char *cp; 13701558Srgrimes struct grouplist *grp; 13717401Swpaul struct grouplist *tgrp; 13721558Srgrimes{ 13737401Swpaul struct grouplist *checkgrp; 13741558Srgrimes struct hostent *hp, *nhp; 13751558Srgrimes char **addrp, **naddrp; 13761558Srgrimes struct hostent t_host; 13771558Srgrimes int i; 13781558Srgrimes u_long saddr; 13791558Srgrimes char *aptr[2]; 13801558Srgrimes 13811558Srgrimes if (grp->gr_type != GT_NULL) 13821558Srgrimes return (1); 13831558Srgrimes if ((hp = gethostbyname(cp)) == NULL) { 13841558Srgrimes if (isdigit(*cp)) { 13851558Srgrimes saddr = inet_addr(cp); 13861558Srgrimes if (saddr == -1) { 13879336Sdfr syslog(LOG_ERR, "Inet_addr failed for %s", cp); 13881558Srgrimes return (1); 13891558Srgrimes } 13901558Srgrimes if ((hp = gethostbyaddr((caddr_t)&saddr, sizeof (saddr), 13911558Srgrimes AF_INET)) == NULL) { 13921558Srgrimes hp = &t_host; 13931558Srgrimes hp->h_name = cp; 13941558Srgrimes hp->h_addrtype = AF_INET; 13951558Srgrimes hp->h_length = sizeof (u_long); 13961558Srgrimes hp->h_addr_list = aptr; 13971558Srgrimes aptr[0] = (char *)&saddr; 13981558Srgrimes aptr[1] = (char *)NULL; 13991558Srgrimes } 14001558Srgrimes } else { 14019336Sdfr syslog(LOG_ERR, "Gethostbyname failed for %s", cp); 14021558Srgrimes return (1); 14031558Srgrimes } 14041558Srgrimes } 14057401Swpaul /* 14067401Swpaul * Sanity check: make sure we don't already have an entry 14077401Swpaul * for this host in the grouplist. 14087401Swpaul */ 14097401Swpaul checkgrp = tgrp; 14107401Swpaul while (checkgrp) { 141117887Swpaul if (checkgrp->gr_type == GT_HOST && 141217887Swpaul checkgrp->gr_ptr.gt_hostent != NULL && 14137401Swpaul !strcmp(checkgrp->gr_ptr.gt_hostent->h_name, hp->h_name)) { 14147401Swpaul grp->gr_type = GT_IGNORE; 14157401Swpaul return(0); 14167401Swpaul } 14177401Swpaul checkgrp = checkgrp->gr_next; 14187401Swpaul } 14197401Swpaul 14201558Srgrimes grp->gr_type = GT_HOST; 14211558Srgrimes nhp = grp->gr_ptr.gt_hostent = (struct hostent *) 14221558Srgrimes malloc(sizeof(struct hostent)); 14231558Srgrimes if (nhp == (struct hostent *)NULL) 14241558Srgrimes out_of_mem(); 142523681Speter memmove(nhp, hp, sizeof(struct hostent)); 14261558Srgrimes i = strlen(hp->h_name)+1; 14271558Srgrimes nhp->h_name = (char *)malloc(i); 14281558Srgrimes if (nhp->h_name == (char *)NULL) 14291558Srgrimes out_of_mem(); 143023681Speter memmove(nhp->h_name, hp->h_name, i); 14311558Srgrimes addrp = hp->h_addr_list; 14321558Srgrimes i = 1; 14331558Srgrimes while (*addrp++) 14341558Srgrimes i++; 14351558Srgrimes naddrp = nhp->h_addr_list = (char **) 14361558Srgrimes malloc(i*sizeof(char *)); 14371558Srgrimes if (naddrp == (char **)NULL) 14381558Srgrimes out_of_mem(); 14391558Srgrimes addrp = hp->h_addr_list; 14401558Srgrimes while (*addrp) { 14411558Srgrimes *naddrp = (char *) 14421558Srgrimes malloc(hp->h_length); 14431558Srgrimes if (*naddrp == (char *)NULL) 14441558Srgrimes out_of_mem(); 144523681Speter memmove(*naddrp, *addrp, hp->h_length); 14461558Srgrimes addrp++; 14471558Srgrimes naddrp++; 14481558Srgrimes } 14491558Srgrimes *naddrp = (char *)NULL; 14501558Srgrimes if (debug) 14511558Srgrimes fprintf(stderr, "got host %s\n", hp->h_name); 14521558Srgrimes return (0); 14531558Srgrimes} 14541558Srgrimes 14551558Srgrimes/* 14561558Srgrimes * Free up an exports list component 14571558Srgrimes */ 14581558Srgrimesvoid 14591558Srgrimesfree_exp(ep) 14601558Srgrimes struct exportlist *ep; 14611558Srgrimes{ 14621558Srgrimes 14631558Srgrimes if (ep->ex_defdir) { 14641558Srgrimes free_host(ep->ex_defdir->dp_hosts); 14651558Srgrimes free((caddr_t)ep->ex_defdir); 14661558Srgrimes } 14671558Srgrimes if (ep->ex_fsdir) 14681558Srgrimes free(ep->ex_fsdir); 14691558Srgrimes free_dir(ep->ex_dirl); 14701558Srgrimes free((caddr_t)ep); 14711558Srgrimes} 14721558Srgrimes 14731558Srgrimes/* 14741558Srgrimes * Free hosts. 14751558Srgrimes */ 14761558Srgrimesvoid 14771558Srgrimesfree_host(hp) 14781558Srgrimes struct hostlist *hp; 14791558Srgrimes{ 14801558Srgrimes struct hostlist *hp2; 14811558Srgrimes 14821558Srgrimes while (hp) { 14831558Srgrimes hp2 = hp; 14841558Srgrimes hp = hp->ht_next; 14851558Srgrimes free((caddr_t)hp2); 14861558Srgrimes } 14871558Srgrimes} 14881558Srgrimes 14891558Srgrimesstruct hostlist * 14901558Srgrimesget_ht() 14911558Srgrimes{ 14921558Srgrimes struct hostlist *hp; 14931558Srgrimes 14941558Srgrimes hp = (struct hostlist *)malloc(sizeof (struct hostlist)); 14951558Srgrimes if (hp == (struct hostlist *)NULL) 14961558Srgrimes out_of_mem(); 14971558Srgrimes hp->ht_next = (struct hostlist *)NULL; 14989336Sdfr hp->ht_flag = 0; 14991558Srgrimes return (hp); 15001558Srgrimes} 15011558Srgrimes 15021558Srgrimes#ifdef ISO 15031558Srgrimes/* 15041558Srgrimes * Translate an iso address. 15051558Srgrimes */ 15061558Srgrimesget_isoaddr(cp, grp) 15071558Srgrimes char *cp; 15081558Srgrimes struct grouplist *grp; 15091558Srgrimes{ 15101558Srgrimes struct iso_addr *isop; 15111558Srgrimes struct sockaddr_iso *isoaddr; 15121558Srgrimes 15131558Srgrimes if (grp->gr_type != GT_NULL) 15141558Srgrimes return (1); 15151558Srgrimes if ((isop = iso_addr(cp)) == NULL) { 15161558Srgrimes syslog(LOG_ERR, 15171558Srgrimes "iso_addr failed, ignored"); 15181558Srgrimes return (1); 15191558Srgrimes } 15201558Srgrimes isoaddr = (struct sockaddr_iso *) 15211558Srgrimes malloc(sizeof (struct sockaddr_iso)); 15221558Srgrimes if (isoaddr == (struct sockaddr_iso *)NULL) 15231558Srgrimes out_of_mem(); 152423681Speter memset(isoaddr, 0, sizeof(struct sockaddr_iso)); 152523681Speter memmove(&isoaddr->siso_addr, isop, sizeof(struct iso_addr)); 152623681Speter isoaddr->siso_len = sizeof(struct sockaddr_iso); 15271558Srgrimes isoaddr->siso_family = AF_ISO; 15281558Srgrimes grp->gr_type = GT_ISO; 15291558Srgrimes grp->gr_ptr.gt_isoaddr = isoaddr; 15301558Srgrimes return (0); 15311558Srgrimes} 15321558Srgrimes#endif /* ISO */ 15331558Srgrimes 15341558Srgrimes/* 15351558Srgrimes * Out of memory, fatal 15361558Srgrimes */ 15371558Srgrimesvoid 15381558Srgrimesout_of_mem() 15391558Srgrimes{ 15401558Srgrimes 15411558Srgrimes syslog(LOG_ERR, "Out of memory"); 15421558Srgrimes exit(2); 15431558Srgrimes} 15441558Srgrimes 15451558Srgrimes/* 15461558Srgrimes * Do the mount syscall with the update flag to push the export info into 15471558Srgrimes * the kernel. 15481558Srgrimes */ 15491558Srgrimesint 15501558Srgrimesdo_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb) 15511558Srgrimes struct exportlist *ep; 15521558Srgrimes struct grouplist *grp; 15531558Srgrimes int exflags; 15541558Srgrimes struct ucred *anoncrp; 15551558Srgrimes char *dirp; 15561558Srgrimes int dirplen; 15571558Srgrimes struct statfs *fsb; 15581558Srgrimes{ 15591558Srgrimes char *cp = (char *)NULL; 15601558Srgrimes u_long **addrp; 15611558Srgrimes int done; 15621558Srgrimes char savedc = '\0'; 15631558Srgrimes struct sockaddr_in sin, imask; 15641558Srgrimes union { 15651558Srgrimes struct ufs_args ua; 15661558Srgrimes struct iso_args ia; 15671558Srgrimes struct mfs_args ma; 15689336Sdfr#ifdef __NetBSD__ 15699336Sdfr struct msdosfs_args da; 15709336Sdfr#endif 15711558Srgrimes } args; 15721558Srgrimes u_long net; 15731558Srgrimes 15741558Srgrimes args.ua.fspec = 0; 15751558Srgrimes args.ua.export.ex_flags = exflags; 15761558Srgrimes args.ua.export.ex_anon = *anoncrp; 157723681Speter memset(&sin, 0, sizeof(sin)); 157823681Speter memset(&imask, 0, sizeof(imask)); 15791558Srgrimes sin.sin_family = AF_INET; 15801558Srgrimes sin.sin_len = sizeof(sin); 15811558Srgrimes imask.sin_family = AF_INET; 15821558Srgrimes imask.sin_len = sizeof(sin); 15831558Srgrimes if (grp->gr_type == GT_HOST) 15841558Srgrimes addrp = (u_long **)grp->gr_ptr.gt_hostent->h_addr_list; 15851558Srgrimes else 15861558Srgrimes addrp = (u_long **)NULL; 15871558Srgrimes done = FALSE; 15881558Srgrimes while (!done) { 15891558Srgrimes switch (grp->gr_type) { 15901558Srgrimes case GT_HOST: 15911558Srgrimes if (addrp) { 15921558Srgrimes sin.sin_addr.s_addr = **addrp; 15931558Srgrimes args.ua.export.ex_addrlen = sizeof(sin); 15941558Srgrimes } else 15951558Srgrimes args.ua.export.ex_addrlen = 0; 15961558Srgrimes args.ua.export.ex_addr = (struct sockaddr *)&sin; 15971558Srgrimes args.ua.export.ex_masklen = 0; 15981558Srgrimes break; 15991558Srgrimes case GT_NET: 16001558Srgrimes if (grp->gr_ptr.gt_net.nt_mask) 16011558Srgrimes imask.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_mask; 16021558Srgrimes else { 16031558Srgrimes net = ntohl(grp->gr_ptr.gt_net.nt_net); 16041558Srgrimes if (IN_CLASSA(net)) 16051558Srgrimes imask.sin_addr.s_addr = inet_addr("255.0.0.0"); 16061558Srgrimes else if (IN_CLASSB(net)) 16071558Srgrimes imask.sin_addr.s_addr = 16081558Srgrimes inet_addr("255.255.0.0"); 16091558Srgrimes else 16101558Srgrimes imask.sin_addr.s_addr = 16111558Srgrimes inet_addr("255.255.255.0"); 16121558Srgrimes grp->gr_ptr.gt_net.nt_mask = imask.sin_addr.s_addr; 16131558Srgrimes } 16141558Srgrimes sin.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_net; 16151558Srgrimes args.ua.export.ex_addr = (struct sockaddr *)&sin; 16161558Srgrimes args.ua.export.ex_addrlen = sizeof (sin); 16171558Srgrimes args.ua.export.ex_mask = (struct sockaddr *)&imask; 16181558Srgrimes args.ua.export.ex_masklen = sizeof (imask); 16191558Srgrimes break; 16201558Srgrimes#ifdef ISO 16211558Srgrimes case GT_ISO: 16221558Srgrimes args.ua.export.ex_addr = 16231558Srgrimes (struct sockaddr *)grp->gr_ptr.gt_isoaddr; 16241558Srgrimes args.ua.export.ex_addrlen = 16251558Srgrimes sizeof(struct sockaddr_iso); 16261558Srgrimes args.ua.export.ex_masklen = 0; 16271558Srgrimes break; 16281558Srgrimes#endif /* ISO */ 16297401Swpaul case GT_IGNORE: 16307401Swpaul return(0); 16317401Swpaul break; 16321558Srgrimes default: 16331558Srgrimes syslog(LOG_ERR, "Bad grouptype"); 16341558Srgrimes if (cp) 16351558Srgrimes *cp = savedc; 16361558Srgrimes return (1); 16371558Srgrimes }; 16381558Srgrimes 16391558Srgrimes /* 16401558Srgrimes * XXX: 16411558Srgrimes * Maybe I should just use the fsb->f_mntonname path instead 16421558Srgrimes * of looping back up the dirp to the mount point?? 16431558Srgrimes * Also, needs to know how to export all types of local 164423681Speter * exportable file systems and not just "ufs". 16451558Srgrimes */ 16469336Sdfr while (mount(fsb->f_fstypename, dirp, 16471558Srgrimes fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) { 16481558Srgrimes if (cp) 16491558Srgrimes *cp-- = savedc; 16501558Srgrimes else 16511558Srgrimes cp = dirp + dirplen - 1; 16521558Srgrimes if (errno == EPERM) { 16531558Srgrimes syslog(LOG_ERR, 16541558Srgrimes "Can't change attributes for %s.\n", dirp); 16551558Srgrimes return (1); 16561558Srgrimes } 16571558Srgrimes if (opt_flags & OP_ALLDIRS) { 16584895Swollman syslog(LOG_ERR, "Could not remount %s: %m", 16594895Swollman dirp); 16601558Srgrimes return (1); 16611558Srgrimes } 16621558Srgrimes /* back up over the last component */ 16631558Srgrimes while (*cp == '/' && cp > dirp) 16641558Srgrimes cp--; 16651558Srgrimes while (*(cp - 1) != '/' && cp > dirp) 16661558Srgrimes cp--; 16671558Srgrimes if (cp == dirp) { 16681558Srgrimes if (debug) 16691558Srgrimes fprintf(stderr,"mnt unsucc\n"); 16701558Srgrimes syslog(LOG_ERR, "Can't export %s", dirp); 16711558Srgrimes return (1); 16721558Srgrimes } 16731558Srgrimes savedc = *cp; 16741558Srgrimes *cp = '\0'; 16751558Srgrimes } 16761558Srgrimes if (addrp) { 16771558Srgrimes ++addrp; 16781558Srgrimes if (*addrp == (u_long *)NULL) 16791558Srgrimes done = TRUE; 16801558Srgrimes } else 16811558Srgrimes done = TRUE; 16821558Srgrimes } 16831558Srgrimes if (cp) 16841558Srgrimes *cp = savedc; 16851558Srgrimes return (0); 16861558Srgrimes} 16871558Srgrimes 16881558Srgrimes/* 16891558Srgrimes * Translate a net address. 16901558Srgrimes */ 16911558Srgrimesint 16921558Srgrimesget_net(cp, net, maskflg) 16931558Srgrimes char *cp; 16941558Srgrimes struct netmsk *net; 16951558Srgrimes int maskflg; 16961558Srgrimes{ 16971558Srgrimes struct netent *np; 16981558Srgrimes long netaddr; 16991558Srgrimes struct in_addr inetaddr, inetaddr2; 17001558Srgrimes char *name; 17011558Srgrimes 17021558Srgrimes if (np = getnetbyname(cp)) 17031558Srgrimes inetaddr = inet_makeaddr(np->n_net, 0); 17041558Srgrimes else if (isdigit(*cp)) { 17051558Srgrimes if ((netaddr = inet_network(cp)) == -1) 17061558Srgrimes return (1); 17071558Srgrimes inetaddr = inet_makeaddr(netaddr, 0); 17081558Srgrimes /* 17091558Srgrimes * Due to arbritrary subnet masks, you don't know how many 17101558Srgrimes * bits to shift the address to make it into a network, 17111558Srgrimes * however you do know how to make a network address into 17121558Srgrimes * a host with host == 0 and then compare them. 17131558Srgrimes * (What a pest) 17141558Srgrimes */ 17151558Srgrimes if (!maskflg) { 17161558Srgrimes setnetent(0); 17171558Srgrimes while (np = getnetent()) { 17181558Srgrimes inetaddr2 = inet_makeaddr(np->n_net, 0); 17191558Srgrimes if (inetaddr2.s_addr == inetaddr.s_addr) 17201558Srgrimes break; 17211558Srgrimes } 17221558Srgrimes endnetent(); 17231558Srgrimes } 17241558Srgrimes } else 17251558Srgrimes return (1); 17261558Srgrimes if (maskflg) 17271558Srgrimes net->nt_mask = inetaddr.s_addr; 17281558Srgrimes else { 17291558Srgrimes if (np) 17301558Srgrimes name = np->n_name; 17311558Srgrimes else 17321558Srgrimes name = inet_ntoa(inetaddr); 17331558Srgrimes net->nt_name = (char *)malloc(strlen(name) + 1); 17341558Srgrimes if (net->nt_name == (char *)NULL) 17351558Srgrimes out_of_mem(); 17361558Srgrimes strcpy(net->nt_name, name); 17371558Srgrimes net->nt_net = inetaddr.s_addr; 17381558Srgrimes } 17391558Srgrimes return (0); 17401558Srgrimes} 17411558Srgrimes 17421558Srgrimes/* 17431558Srgrimes * Parse out the next white space separated field 17441558Srgrimes */ 17451558Srgrimesvoid 17461558Srgrimesnextfield(cp, endcp) 17471558Srgrimes char **cp; 17481558Srgrimes char **endcp; 17491558Srgrimes{ 17501558Srgrimes char *p; 17511558Srgrimes 17521558Srgrimes p = *cp; 17531558Srgrimes while (*p == ' ' || *p == '\t') 17541558Srgrimes p++; 17551558Srgrimes if (*p == '\n' || *p == '\0') 17561558Srgrimes *cp = *endcp = p; 17571558Srgrimes else { 17581558Srgrimes *cp = p++; 17591558Srgrimes while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 17601558Srgrimes p++; 17611558Srgrimes *endcp = p; 17621558Srgrimes } 17631558Srgrimes} 17641558Srgrimes 17651558Srgrimes/* 17661558Srgrimes * Get an exports file line. Skip over blank lines and handle line 17671558Srgrimes * continuations. 17681558Srgrimes */ 17691558Srgrimesint 17701558Srgrimesget_line() 17711558Srgrimes{ 17721558Srgrimes char *p, *cp; 17731558Srgrimes int len; 17741558Srgrimes int totlen, cont_line; 17751558Srgrimes 17761558Srgrimes /* 17771558Srgrimes * Loop around ignoring blank lines and getting all continuation lines. 17781558Srgrimes */ 17791558Srgrimes p = line; 17801558Srgrimes totlen = 0; 17811558Srgrimes do { 17821558Srgrimes if (fgets(p, LINESIZ - totlen, exp_file) == NULL) 17831558Srgrimes return (0); 17841558Srgrimes len = strlen(p); 17851558Srgrimes cp = p + len - 1; 17861558Srgrimes cont_line = 0; 17871558Srgrimes while (cp >= p && 17881558Srgrimes (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '\\')) { 17891558Srgrimes if (*cp == '\\') 17901558Srgrimes cont_line = 1; 17911558Srgrimes cp--; 17921558Srgrimes len--; 17931558Srgrimes } 17941558Srgrimes *++cp = '\0'; 17951558Srgrimes if (len > 0) { 17961558Srgrimes totlen += len; 17971558Srgrimes if (totlen >= LINESIZ) { 17981558Srgrimes syslog(LOG_ERR, "Exports line too long"); 17991558Srgrimes exit(2); 18001558Srgrimes } 18011558Srgrimes p = cp; 18021558Srgrimes } 18031558Srgrimes } while (totlen == 0 || cont_line); 18041558Srgrimes return (1); 18051558Srgrimes} 18061558Srgrimes 18071558Srgrimes/* 18081558Srgrimes * Parse a description of a credential. 18091558Srgrimes */ 18101558Srgrimesvoid 18111558Srgrimesparsecred(namelist, cr) 18121558Srgrimes char *namelist; 18131558Srgrimes struct ucred *cr; 18141558Srgrimes{ 18151558Srgrimes char *name; 18161558Srgrimes int cnt; 18171558Srgrimes char *names; 18181558Srgrimes struct passwd *pw; 18191558Srgrimes struct group *gr; 18201558Srgrimes int ngroups, groups[NGROUPS + 1]; 18211558Srgrimes 18221558Srgrimes /* 18231558Srgrimes * Set up the unpriviledged user. 18241558Srgrimes */ 18251558Srgrimes cr->cr_ref = 1; 18261558Srgrimes cr->cr_uid = -2; 18271558Srgrimes cr->cr_groups[0] = -2; 18281558Srgrimes cr->cr_ngroups = 1; 18291558Srgrimes /* 18301558Srgrimes * Get the user's password table entry. 18311558Srgrimes */ 18321558Srgrimes names = strsep(&namelist, " \t\n"); 18331558Srgrimes name = strsep(&names, ":"); 18341558Srgrimes if (isdigit(*name) || *name == '-') 18351558Srgrimes pw = getpwuid(atoi(name)); 18361558Srgrimes else 18371558Srgrimes pw = getpwnam(name); 18381558Srgrimes /* 18391558Srgrimes * Credentials specified as those of a user. 18401558Srgrimes */ 18411558Srgrimes if (names == NULL) { 18421558Srgrimes if (pw == NULL) { 18431558Srgrimes syslog(LOG_ERR, "Unknown user: %s", name); 18441558Srgrimes return; 18451558Srgrimes } 18461558Srgrimes cr->cr_uid = pw->pw_uid; 18471558Srgrimes ngroups = NGROUPS + 1; 18481558Srgrimes if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) 18491558Srgrimes syslog(LOG_ERR, "Too many groups"); 18501558Srgrimes /* 18511558Srgrimes * Convert from int's to gid_t's and compress out duplicate 18521558Srgrimes */ 18531558Srgrimes cr->cr_ngroups = ngroups - 1; 18541558Srgrimes cr->cr_groups[0] = groups[0]; 18551558Srgrimes for (cnt = 2; cnt < ngroups; cnt++) 18561558Srgrimes cr->cr_groups[cnt - 1] = groups[cnt]; 18571558Srgrimes return; 18581558Srgrimes } 18591558Srgrimes /* 18601558Srgrimes * Explicit credential specified as a colon separated list: 18611558Srgrimes * uid:gid:gid:... 18621558Srgrimes */ 18631558Srgrimes if (pw != NULL) 18641558Srgrimes cr->cr_uid = pw->pw_uid; 18651558Srgrimes else if (isdigit(*name) || *name == '-') 18661558Srgrimes cr->cr_uid = atoi(name); 18671558Srgrimes else { 18681558Srgrimes syslog(LOG_ERR, "Unknown user: %s", name); 18691558Srgrimes return; 18701558Srgrimes } 18711558Srgrimes cr->cr_ngroups = 0; 18721558Srgrimes while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { 18731558Srgrimes name = strsep(&names, ":"); 18741558Srgrimes if (isdigit(*name) || *name == '-') { 18751558Srgrimes cr->cr_groups[cr->cr_ngroups++] = atoi(name); 18761558Srgrimes } else { 18771558Srgrimes if ((gr = getgrnam(name)) == NULL) { 18781558Srgrimes syslog(LOG_ERR, "Unknown group: %s", name); 18791558Srgrimes continue; 18801558Srgrimes } 18811558Srgrimes cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; 18821558Srgrimes } 18831558Srgrimes } 18841558Srgrimes if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) 18851558Srgrimes syslog(LOG_ERR, "Too many groups"); 18861558Srgrimes} 18871558Srgrimes 18881558Srgrimes#define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 18891558Srgrimes/* 18901558Srgrimes * Routines that maintain the remote mounttab 18911558Srgrimes */ 18921558Srgrimesvoid 18931558Srgrimesget_mountlist() 18941558Srgrimes{ 18951558Srgrimes struct mountlist *mlp, **mlpp; 189623681Speter char *host, *dirp, *cp; 18971558Srgrimes int len; 18981558Srgrimes char str[STRSIZ]; 18991558Srgrimes FILE *mlfile; 19001558Srgrimes 19011558Srgrimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) { 19021558Srgrimes syslog(LOG_ERR, "Can't open %s", _PATH_RMOUNTLIST); 19031558Srgrimes return; 19041558Srgrimes } 19051558Srgrimes mlpp = &mlhead; 19061558Srgrimes while (fgets(str, STRSIZ, mlfile) != NULL) { 190723681Speter cp = str; 190823681Speter host = strsep(&cp, " \t\n"); 190923681Speter dirp = strsep(&cp, " \t\n"); 191023681Speter if (host == NULL || dirp == NULL) 19111558Srgrimes continue; 19121558Srgrimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 191323681Speter strncpy(mlp->ml_host, host, RPCMNT_NAMELEN); 191423681Speter mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 191523681Speter strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 191623681Speter mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 19171558Srgrimes mlp->ml_next = (struct mountlist *)NULL; 19181558Srgrimes *mlpp = mlp; 19191558Srgrimes mlpp = &mlp->ml_next; 19201558Srgrimes } 19211558Srgrimes fclose(mlfile); 19221558Srgrimes} 19231558Srgrimes 19241558Srgrimesvoid 19251558Srgrimesdel_mlist(hostp, dirp) 19261558Srgrimes char *hostp, *dirp; 19271558Srgrimes{ 19281558Srgrimes struct mountlist *mlp, **mlpp; 19291558Srgrimes struct mountlist *mlp2; 19301558Srgrimes FILE *mlfile; 19311558Srgrimes int fnd = 0; 19321558Srgrimes 19331558Srgrimes mlpp = &mlhead; 19341558Srgrimes mlp = mlhead; 19351558Srgrimes while (mlp) { 19361558Srgrimes if (!strcmp(mlp->ml_host, hostp) && 19371558Srgrimes (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 19381558Srgrimes fnd = 1; 19391558Srgrimes mlp2 = mlp; 19401558Srgrimes *mlpp = mlp = mlp->ml_next; 19411558Srgrimes free((caddr_t)mlp2); 19421558Srgrimes } else { 19431558Srgrimes mlpp = &mlp->ml_next; 19441558Srgrimes mlp = mlp->ml_next; 19451558Srgrimes } 19461558Srgrimes } 19471558Srgrimes if (fnd) { 19481558Srgrimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 19491558Srgrimes syslog(LOG_ERR,"Can't update %s", _PATH_RMOUNTLIST); 19501558Srgrimes return; 19511558Srgrimes } 19521558Srgrimes mlp = mlhead; 19531558Srgrimes while (mlp) { 19541558Srgrimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 19551558Srgrimes mlp = mlp->ml_next; 19561558Srgrimes } 19571558Srgrimes fclose(mlfile); 19581558Srgrimes } 19591558Srgrimes} 19601558Srgrimes 19611558Srgrimesvoid 19621558Srgrimesadd_mlist(hostp, dirp) 19631558Srgrimes char *hostp, *dirp; 19641558Srgrimes{ 19651558Srgrimes struct mountlist *mlp, **mlpp; 19661558Srgrimes FILE *mlfile; 19671558Srgrimes 19681558Srgrimes mlpp = &mlhead; 19691558Srgrimes mlp = mlhead; 19701558Srgrimes while (mlp) { 19711558Srgrimes if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 19721558Srgrimes return; 19731558Srgrimes mlpp = &mlp->ml_next; 19741558Srgrimes mlp = mlp->ml_next; 19751558Srgrimes } 19761558Srgrimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 19771558Srgrimes strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 19781558Srgrimes mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 19791558Srgrimes strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 19801558Srgrimes mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 19811558Srgrimes mlp->ml_next = (struct mountlist *)NULL; 19821558Srgrimes *mlpp = mlp; 19831558Srgrimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 19841558Srgrimes syslog(LOG_ERR, "Can't update %s", _PATH_RMOUNTLIST); 19851558Srgrimes return; 19861558Srgrimes } 19871558Srgrimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 19881558Srgrimes fclose(mlfile); 19891558Srgrimes} 19901558Srgrimes 19911558Srgrimes/* 19921558Srgrimes * This function is called via. SIGTERM when the system is going down. 19931558Srgrimes * It sends a broadcast RPCMNT_UMNTALL. 19941558Srgrimes */ 19951558Srgrimesvoid 19961558Srgrimessend_umntall() 19971558Srgrimes{ 19981558Srgrimes (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL, 19991558Srgrimes xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each); 20001558Srgrimes exit(0); 20011558Srgrimes} 20021558Srgrimes 20031558Srgrimesint 20041558Srgrimesumntall_each(resultsp, raddr) 20051558Srgrimes caddr_t resultsp; 20061558Srgrimes struct sockaddr_in *raddr; 20071558Srgrimes{ 20081558Srgrimes return (1); 20091558Srgrimes} 20101558Srgrimes 20111558Srgrimes/* 20121558Srgrimes * Free up a group list. 20131558Srgrimes */ 20141558Srgrimesvoid 20151558Srgrimesfree_grp(grp) 20161558Srgrimes struct grouplist *grp; 20171558Srgrimes{ 20181558Srgrimes char **addrp; 20191558Srgrimes 20201558Srgrimes if (grp->gr_type == GT_HOST) { 20211558Srgrimes if (grp->gr_ptr.gt_hostent->h_name) { 20221558Srgrimes addrp = grp->gr_ptr.gt_hostent->h_addr_list; 20231558Srgrimes while (addrp && *addrp) 20241558Srgrimes free(*addrp++); 20251558Srgrimes free((caddr_t)grp->gr_ptr.gt_hostent->h_addr_list); 20261558Srgrimes free(grp->gr_ptr.gt_hostent->h_name); 20271558Srgrimes } 20281558Srgrimes free((caddr_t)grp->gr_ptr.gt_hostent); 20291558Srgrimes } else if (grp->gr_type == GT_NET) { 20301558Srgrimes if (grp->gr_ptr.gt_net.nt_name) 20311558Srgrimes free(grp->gr_ptr.gt_net.nt_name); 20321558Srgrimes } 20331558Srgrimes#ifdef ISO 20341558Srgrimes else if (grp->gr_type == GT_ISO) 20351558Srgrimes free((caddr_t)grp->gr_ptr.gt_isoaddr); 20361558Srgrimes#endif 20371558Srgrimes free((caddr_t)grp); 20381558Srgrimes} 20391558Srgrimes 20401558Srgrimes#ifdef DEBUG 20411558Srgrimesvoid 20421558SrgrimesSYSLOG(int pri, const char *fmt, ...) 20431558Srgrimes{ 20441558Srgrimes va_list ap; 20451558Srgrimes 20461558Srgrimes va_start(ap, fmt); 20471558Srgrimes vfprintf(stderr, fmt, ap); 20481558Srgrimes va_end(ap); 20491558Srgrimes} 20501558Srgrimes#endif /* DEBUG */ 20511558Srgrimes 20521558Srgrimes/* 20531558Srgrimes * Check options for consistency. 20541558Srgrimes */ 20551558Srgrimesint 20561558Srgrimescheck_options(dp) 20571558Srgrimes struct dirlist *dp; 20581558Srgrimes{ 20591558Srgrimes 20601558Srgrimes if (dp == (struct dirlist *)NULL) 20611558Srgrimes return (1); 20621558Srgrimes if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL) || 20631558Srgrimes (opt_flags & (OP_MAPROOT | OP_KERB)) == (OP_MAPROOT | OP_KERB) || 20641558Srgrimes (opt_flags & (OP_MAPALL | OP_KERB)) == (OP_MAPALL | OP_KERB)) { 20651558Srgrimes syslog(LOG_ERR, "-mapall, -maproot and -kerb mutually exclusive"); 20661558Srgrimes return (1); 20671558Srgrimes } 20681558Srgrimes if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { 20691558Srgrimes syslog(LOG_ERR, "-mask requires -net"); 20701558Srgrimes return (1); 20711558Srgrimes } 20721558Srgrimes if ((opt_flags & (OP_NET | OP_ISO)) == (OP_NET | OP_ISO)) { 20731558Srgrimes syslog(LOG_ERR, "-net and -iso mutually exclusive"); 20741558Srgrimes return (1); 20751558Srgrimes } 20761558Srgrimes if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { 20771558Srgrimes syslog(LOG_ERR, "-alldir has multiple directories"); 20781558Srgrimes return (1); 20791558Srgrimes } 20801558Srgrimes return (0); 20811558Srgrimes} 20821558Srgrimes 20831558Srgrimes/* 20841558Srgrimes * Check an absolute directory path for any symbolic links. Return true 20851558Srgrimes * if no symbolic links are found. 20861558Srgrimes */ 20871558Srgrimesint 20881558Srgrimescheck_dirpath(dirp) 20891558Srgrimes char *dirp; 20901558Srgrimes{ 20911558Srgrimes char *cp; 20921558Srgrimes int ret = 1; 20931558Srgrimes struct stat sb; 20941558Srgrimes 20951558Srgrimes cp = dirp + 1; 20961558Srgrimes while (*cp && ret) { 20971558Srgrimes if (*cp == '/') { 20981558Srgrimes *cp = '\0'; 20999336Sdfr if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 21001558Srgrimes ret = 0; 21011558Srgrimes *cp = '/'; 21021558Srgrimes } 21031558Srgrimes cp++; 21041558Srgrimes } 21059336Sdfr if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 21061558Srgrimes ret = 0; 21071558Srgrimes return (ret); 21081558Srgrimes} 21099336Sdfr 21109336Sdfr/* 21119336Sdfr * Just translate an ascii string to an integer. 21129336Sdfr */ 21139336Sdfrint 21149336Sdfrget_num(cp) 21159336Sdfr register char *cp; 21169336Sdfr{ 21179336Sdfr register int res = 0; 21189336Sdfr 21199336Sdfr while (*cp) { 21209336Sdfr if (*cp < '0' || *cp > '9') 21219336Sdfr return (-1); 21229336Sdfr res = res * 10 + (*cp++ - '0'); 21239336Sdfr } 21249336Sdfr return (res); 21259336Sdfr} 2126