mountd.c revision 21673
1296077Sadrian/* 2296077Sadrian * Copyright (c) 1989, 1993 3296077Sadrian * The Regents of the University of California. All rights reserved. 4296077Sadrian * 5296077Sadrian * This code is derived from software contributed to Berkeley by 6296077Sadrian * Herb Hasler and Rick Macklem at The University of Guelph. 7296077Sadrian * 8296077Sadrian * Redistribution and use in source and binary forms, with or without 9296077Sadrian * modification, are permitted provided that the following conditions 10296077Sadrian * are met: 11296077Sadrian * 1. Redistributions of source code must retain the above copyright 12296077Sadrian * notice, this list of conditions and the following disclaimer. 13296077Sadrian * 2. Redistributions in binary form must reproduce the above copyright 14296077Sadrian * notice, this list of conditions and the following disclaimer in the 15296077Sadrian * documentation and/or other materials provided with the distribution. 16296077Sadrian * 3. All advertising materials mentioning features or use of this software 17296077Sadrian * must display the following acknowledgement: 18296077Sadrian * This product includes software developed by the University of 19296077Sadrian * California, Berkeley and its contributors. 20296077Sadrian * 4. Neither the name of the University nor the names of its contributors 21296077Sadrian * may be used to endorse or promote products derived from this software 22296077Sadrian * without specific prior written permission. 23296077Sadrian * 24296077Sadrian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25296077Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26296077Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27296077Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28296077Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29296077Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30296077Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31296077Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32296077Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33296077Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34298943Sadrian * SUCH DAMAGE. 35296077Sadrian */ 36296077Sadrian 37296077Sadrian#ifndef lint 38296077Sadrianstatic char copyright[] = 39296077Sadrian"@(#) Copyright (c) 1989, 1993\n\ 40296077Sadrian The Regents of the University of California. All rights reserved.\n"; 41296077Sadrian#endif /*not lint*/ 42296077Sadrian 43296077Sadrian#ifndef lint 44299996Sadrian/*static char sccsid[] = "From: @(#)mountd.c 8.8 (Berkeley) 2/20/94";*/ 45299996Sadrianstatic const char rcsid[] = 46299996Sadrian "$FreeBSD: head/usr.sbin/mountd/mountd.c 21673 1997-01-14 07:20:47Z jkh $"; 47299996Sadrian#endif /*not lint*/ 48299996Sadrian 49299996Sadrian#include <sys/param.h> 50299996Sadrian#include <sys/file.h> 51296077Sadrian#include <sys/ioctl.h> 52296077Sadrian#include <sys/mount.h> 53296077Sadrian#include <sys/socket.h> 54299996Sadrian#include <sys/stat.h> 55299996Sadrian#include <sys/syslog.h> 56296077Sadrian#include <sys/ucred.h> 57296077Sadrian 58296077Sadrian#include <rpc/rpc.h> 59296077Sadrian#include <rpc/pmap_clnt.h> 60296077Sadrian#include <rpc/pmap_prot.h> 61296077Sadrian#ifdef ISO 62296077Sadrian#include <netiso/iso.h> 63296077Sadrian#endif 64296077Sadrian#include <nfs/rpcv2.h> 65296077Sadrian#include <nfs/nfsproto.h> 66296077Sadrian 67296077Sadrian#include <arpa/inet.h> 68296077Sadrian 69296077Sadrian#include <ctype.h> 70296077Sadrian#include <errno.h> 71296077Sadrian#include <grp.h> 72296077Sadrian#include <netdb.h> 73296077Sadrian#include <pwd.h> 74296077Sadrian#include <signal.h> 75296077Sadrian#include <stdio.h> 76296077Sadrian#include <stdlib.h> 77296077Sadrian#include <string.h> 78296077Sadrian#include <unistd.h> 79296077Sadrian#include "pathnames.h" 80296077Sadrian 81296077Sadrian#ifdef DEBUG 82296077Sadrian#include <stdarg.h> 83296077Sadrian#endif 84296077Sadrian 85296077Sadrian/* 86296077Sadrian * Structures for keeping the mount list and export list 87296077Sadrian */ 88296077Sadrianstruct mountlist { 89301698Slandonf struct mountlist *ml_next; 90296077Sadrian char ml_host[RPCMNT_NAMELEN+1]; 91296077Sadrian char ml_dirp[RPCMNT_PATHLEN+1]; 92296077Sadrian}; 93296077Sadrian 94296077Sadrianstruct dirlist { 95296077Sadrian struct dirlist *dp_left; 96296077Sadrian struct dirlist *dp_right; 97296077Sadrian int dp_flag; 98296077Sadrian struct hostlist *dp_hosts; /* List of hosts this dir exported to */ 99296077Sadrian char dp_dirp[1]; /* Actually malloc'd to size of dir */ 100296077Sadrian}; 101296077Sadrian/* dp_flag bits */ 102296077Sadrian#define DP_DEFSET 0x1 103296077Sadrian#define DP_HOSTSET 0x2 104296077Sadrian#define DP_KERB 0x4 105296077Sadrian 106296077Sadrianstruct exportlist { 107296077Sadrian struct exportlist *ex_next; 108296077Sadrian struct dirlist *ex_dirl; 109296077Sadrian struct dirlist *ex_defdir; 110296077Sadrian int ex_flag; 111301698Slandonf fsid_t ex_fs; 112296077Sadrian char *ex_fsdir; 113296077Sadrian}; 114296077Sadrian/* ex_flag bits */ 115296077Sadrian#define EX_LINKED 0x1 116296077Sadrian 117296077Sadrianstruct netmsk { 118296077Sadrian u_long nt_net; 119296077Sadrian u_long nt_mask; 120296077Sadrian char *nt_name; 121296077Sadrian}; 122296077Sadrian 123296077Sadrianunion grouptypes { 124296077Sadrian struct hostent *gt_hostent; 125296077Sadrian struct netmsk gt_net; 126296077Sadrian#ifdef ISO 127296077Sadrian struct sockaddr_iso *gt_isoaddr; 128296077Sadrian#endif 129296077Sadrian}; 130296077Sadrian 131296077Sadrianstruct grouplist { 132296077Sadrian int gr_type; 133296077Sadrian union grouptypes gr_ptr; 134296077Sadrian struct grouplist *gr_next; 135296077Sadrian}; 136296077Sadrian/* Group types */ 137296077Sadrian#define GT_NULL 0x0 138296077Sadrian#define GT_HOST 0x1 139296077Sadrian#define GT_NET 0x2 140296077Sadrian#define GT_ISO 0x4 141296077Sadrian#define GT_IGNORE 0x5 142296077Sadrian 143296077Sadrianstruct hostlist { 144296077Sadrian int ht_flag; /* Uses DP_xx bits */ 145296077Sadrian struct grouplist *ht_grp; 146296077Sadrian struct hostlist *ht_next; 147296077Sadrian}; 148296077Sadrian 149296077Sadrianstruct fhreturn { 150296077Sadrian int fhr_flag; 151296077Sadrian int fhr_vers; 152296077Sadrian nfsfh_t fhr_fh; 153296077Sadrian}; 154296077Sadrian 155296077Sadrian/* Global defs */ 156296077Sadrianchar *add_expdir __P((struct dirlist **, char *, int)); 157296077Sadrianvoid add_dlist __P((struct dirlist **, struct dirlist *, 158296077Sadrian struct grouplist *, int)); 159296077Sadrianvoid add_mlist __P((char *, char *)); 160296077Sadrianint check_dirpath __P((char *)); 161296077Sadrianint check_options __P((struct dirlist *)); 162296077Sadrianint chk_host __P((struct dirlist *, u_long, int *, int *)); 163296077Sadrianvoid del_mlist __P((char *, char *)); 164296077Sadrianstruct dirlist *dirp_search __P((struct dirlist *, char *)); 165296077Sadrianint do_mount __P((struct exportlist *, struct grouplist *, int, 166296077Sadrian struct ucred *, char *, int, struct statfs *)); 167296077Sadrianint do_opt __P((char **, char **, struct exportlist *, struct grouplist *, 168296077Sadrian int *, int *, struct ucred *)); 169296077Sadrianstruct exportlist *ex_search __P((fsid_t *)); 170296077Sadrianstruct exportlist *get_exp __P((void)); 171296077Sadrianvoid free_dir __P((struct dirlist *)); 172296077Sadrianvoid free_exp __P((struct exportlist *)); 173296077Sadrianvoid free_grp __P((struct grouplist *)); 174296077Sadrianvoid free_host __P((struct hostlist *)); 175296077Sadrianvoid get_exportlist __P((void)); 176296077Sadrianint get_host __P((char *, struct grouplist *, struct grouplist *)); 177296077Sadrianint get_num __P((char *)); 178296077Sadrianstruct hostlist *get_ht __P((void)); 179296077Sadrianint get_line __P((void)); 180296077Sadrianvoid get_mountlist __P((void)); 181296077Sadrianint get_net __P((char *, struct netmsk *, int)); 182296077Sadrianvoid getexp_err __P((struct exportlist *, struct grouplist *)); 183296077Sadrianstruct grouplist *get_grp __P((void)); 184296077Sadrianvoid hang_dirp __P((struct dirlist *, struct grouplist *, 185296077Sadrian struct exportlist *, int)); 186296077Sadrianvoid mntsrv __P((struct svc_req *, SVCXPRT *)); 187296077Sadrianvoid nextfield __P((char **, char **)); 188296077Sadrianvoid out_of_mem __P((void)); 189296077Sadrianvoid parsecred __P((char *, struct ucred *)); 190296077Sadrianint put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *)); 191296077Sadrianint scan_tree __P((struct dirlist *, u_long)); 192296077Sadrianvoid send_umntall __P((void)); 193296077Sadrianint umntall_each __P((caddr_t, struct sockaddr_in *)); 194296077Sadrianint xdr_dir __P((XDR *, char *)); 195296077Sadrianint xdr_explist __P((XDR *, caddr_t)); 196299119Semasteint xdr_fhs __P((XDR *, caddr_t)); 197299119Semasteint xdr_mlist __P((XDR *, caddr_t)); 198296077Sadrian 199296077Sadrian/* C library */ 200296077Sadrianint getnetgrent(); 201296077Sadrianvoid endnetgrent(); 202296077Sadrianvoid setnetgrent(); 203296077Sadrian 204296077Sadrian#ifdef ISO 205296077Sadrianstruct iso_addr *iso_addr(); 206296077Sadrian#endif 207296077Sadrian 208296077Sadrianstruct exportlist *exphead; 209296077Sadrianstruct mountlist *mlhead; 210296077Sadrianstruct grouplist *grphead; 211296077Sadrianchar exname[MAXPATHLEN]; 212296077Sadrianstruct ucred def_anon = { 213296077Sadrian 1, 214296077Sadrian (uid_t) -2, 215296077Sadrian 1, 216296077Sadrian { (gid_t) -2 } 217296077Sadrian}; 218296077Sadrianint resvport_only = 1; 219296077Sadrianint dir_only = 1; 220296077Sadrianint opt_flags; 221296077Sadrian/* Bits for above */ 222296077Sadrian#define OP_MAPROOT 0x01 223296077Sadrian#define OP_MAPALL 0x02 224296077Sadrian#define OP_KERB 0x04 225296077Sadrian#define OP_MASK 0x08 226296077Sadrian#define OP_NET 0x10 227296077Sadrian#define OP_ISO 0x20 228296077Sadrian#define OP_ALLDIRS 0x40 229296077Sadrian 230296077Sadrian#ifdef DEBUG 231296077Sadrianint debug = 1; 232296077Sadrianvoid SYSLOG __P((int, const char *, ...)); 233296077Sadrian#define syslog SYSLOG 234296077Sadrian#else 235296077Sadrianint debug = 0; 236296077Sadrian#endif 237296077Sadrian 238296077Sadrian/* 239296077Sadrian * Mountd server for NFS mount protocol as described in: 240296077Sadrian * NFS: Network File System Protocol Specification, RFC1094, Appendix A 241296077Sadrian * The optional arguments are the exports file name 242296077Sadrian * default: _PATH_EXPORTS 243296077Sadrian * and "-n" to allow nonroot mount. 244296077Sadrian */ 245296077Sadrianint 246296077Sadrianmain(argc, argv) 247296077Sadrian int argc; 248296077Sadrian char **argv; 249296077Sadrian{ 250296077Sadrian SVCXPRT *udptransp, *tcptransp; 251296077Sadrian int c; 252296077Sadrian#ifdef __FreeBSD__ 253296077Sadrian struct vfsconf *vfc; 254296077Sadrian 255296077Sadrian vfc = getvfsbyname("nfs"); 256296077Sadrian if(!vfc && vfsisloadable("nfs")) { 257296077Sadrian if(vfsload("nfs")) 258296077Sadrian err(1, "vfsload(nfs)"); 259296077Sadrian endvfsent(); /* flush cache */ 260296077Sadrian vfc = getvfsbyname("nfs"); 261296077Sadrian } 262296077Sadrian if(!vfc) { 263296077Sadrian errx(1, "NFS support is not available in the running kernel"); 264296077Sadrian } 265296077Sadrian#endif /* __FreeBSD__ */ 266296077Sadrian 267296077Sadrian while ((c = getopt(argc, argv, "dnr")) != EOF) 268296077Sadrian switch (c) { 269296077Sadrian case 'n': 270296077Sadrian resvport_only = 0; 271296077Sadrian break; 272296077Sadrian case 'r': 273296077Sadrian dir_only = 0; 274296077Sadrian break; 275296077Sadrian case 'd': 276296077Sadrian debug = debug ? 0 : 1; 277296077Sadrian break; 278296077Sadrian default: 279296077Sadrian fprintf(stderr, "Usage: mountd [-r] [-n] [export_file]\n"); 280296077Sadrian exit(1); 281296077Sadrian }; 282296077Sadrian argc -= optind; 283296077Sadrian argv += optind; 284296077Sadrian grphead = (struct grouplist *)NULL; 285296077Sadrian exphead = (struct exportlist *)NULL; 286296077Sadrian mlhead = (struct mountlist *)NULL; 287296077Sadrian if (argc == 1) { 288296077Sadrian strncpy(exname, *argv, MAXPATHLEN-1); 289296077Sadrian exname[MAXPATHLEN-1] = '\0'; 290296077Sadrian } else 291296077Sadrian strcpy(exname, _PATH_EXPORTS); 292296077Sadrian openlog("mountd", LOG_PID, LOG_DAEMON); 293296077Sadrian if (debug) 294296077Sadrian fprintf(stderr,"Getting export list.\n"); 295296077Sadrian get_exportlist(); 296296077Sadrian if (debug) 297296077Sadrian fprintf(stderr,"Getting mount list.\n"); 298296077Sadrian get_mountlist(); 299296077Sadrian if (debug) 300296077Sadrian fprintf(stderr,"Here we go.\n"); 301296077Sadrian if (debug == 0) { 302296077Sadrian daemon(0, 0); 303296077Sadrian signal(SIGINT, SIG_IGN); 304296077Sadrian signal(SIGQUIT, SIG_IGN); 305296077Sadrian } 306300628Sadrian signal(SIGHUP, (void (*) __P((int))) get_exportlist); 307300628Sadrian signal(SIGTERM, (void (*) __P((int))) send_umntall); 308296077Sadrian { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); 309296077Sadrian if (pidfile != NULL) { 310300628Sadrian fprintf(pidfile, "%d\n", getpid()); 311300628Sadrian fclose(pidfile); 312300628Sadrian } 313296077Sadrian } 314296077Sadrian if ((udptransp = svcudp_create(RPC_ANYSOCK)) == NULL || 315296077Sadrian (tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0)) == NULL) { 316296077Sadrian syslog(LOG_ERR, "Can't create socket"); 317296077Sadrian exit(1); 318296077Sadrian } 319296077Sadrian pmap_unset(RPCPROG_MNT, 1); 320296077Sadrian pmap_unset(RPCPROG_MNT, 3); 321296077Sadrian if (!svc_register(udptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_UDP) || 322296077Sadrian !svc_register(udptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_UDP) || 323296077Sadrian !svc_register(tcptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_TCP) || 324296077Sadrian !svc_register(tcptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_TCP)) { 325296077Sadrian syslog(LOG_ERR, "Can't register mount"); 326296077Sadrian exit(1); 327296077Sadrian } 328296077Sadrian svc_run(); 329296077Sadrian syslog(LOG_ERR, "Mountd died"); 330296077Sadrian exit(1); 331296077Sadrian} 332296077Sadrian 333296077Sadrian/* 334296077Sadrian * The mount rpc service 335296077Sadrian */ 336296077Sadrianvoid 337296077Sadrianmntsrv(rqstp, transp) 338296077Sadrian struct svc_req *rqstp; 339300628Sadrian SVCXPRT *transp; 340300628Sadrian{ 341300628Sadrian struct exportlist *ep; 342300628Sadrian struct dirlist *dp; 343296077Sadrian struct fhreturn fhr; 344296077Sadrian struct authunix_parms *ucr; 345296077Sadrian struct stat stb; 346296077Sadrian struct statfs fsb; 347296077Sadrian struct hostent *hp; 348296077Sadrian u_long saddr; 349296077Sadrian u_short sport; 350296077Sadrian char rpcpath[RPCMNT_PATHLEN+1], dirpath[MAXPATHLEN]; 351296077Sadrian int bad = ENOENT, defset, hostset; 352296077Sadrian sigset_t sighup_mask; 353300015Sadrian 354300015Sadrian sigemptyset(&sighup_mask); 355300015Sadrian sigaddset(&sighup_mask, SIGHUP); 356300015Sadrian saddr = transp->xp_raddr.sin_addr.s_addr; 357300015Sadrian sport = ntohs(transp->xp_raddr.sin_port); 358300015Sadrian hp = (struct hostent *)NULL; 359300015Sadrian switch (rqstp->rq_proc) { 360300015Sadrian case NULLPROC: 361300015Sadrian if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 362300015Sadrian syslog(LOG_ERR, "Can't send reply"); 363300015Sadrian return; 364300015Sadrian case RPCMNT_MOUNT: 365300015Sadrian if (sport >= IPPORT_RESERVED && resvport_only) { 366300015Sadrian svcerr_weakauth(transp); 367300015Sadrian return; 368300015Sadrian } 369300015Sadrian if (!svc_getargs(transp, xdr_dir, rpcpath)) { 370300015Sadrian svcerr_decode(transp); 371300015Sadrian return; 372300015Sadrian } 373300015Sadrian 374300015Sadrian /* 375300015Sadrian * Get the real pathname and make sure it is a directory 376300015Sadrian * or a regular file if the -r option was specified 377300015Sadrian * and it exists. 378300015Sadrian */ 379300015Sadrian if (realpath(rpcpath, dirpath) == 0 || 380300015Sadrian stat(dirpath, &stb) < 0 || 381300015Sadrian (!S_ISDIR(stb.st_mode) && 382300015Sadrian (dir_only || !S_ISREG(stb.st_mode))) || 383300015Sadrian statfs(dirpath, &fsb) < 0) { 384300015Sadrian chdir("/"); /* Just in case realpath doesn't */ 385300015Sadrian if (debug) 386300015Sadrian fprintf(stderr, "stat failed on %s\n", dirpath); 387300015Sadrian if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 388300015Sadrian syslog(LOG_ERR, "Can't send reply"); 389300015Sadrian return; 390300015Sadrian } 391300015Sadrian 392300015Sadrian /* Check in the exports list */ 393300015Sadrian sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 394300015Sadrian ep = ex_search(&fsb.f_fsid); 395300015Sadrian hostset = defset = 0; 396300015Sadrian if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) || 397300015Sadrian ((dp = dirp_search(ep->ex_dirl, dirpath)) && 398300015Sadrian chk_host(dp, saddr, &defset, &hostset)) || 399300015Sadrian (defset && scan_tree(ep->ex_defdir, saddr) == 0 && 400300015Sadrian scan_tree(ep->ex_dirl, saddr) == 0))) { 401300015Sadrian if (hostset & DP_HOSTSET) 402300015Sadrian fhr.fhr_flag = hostset; 403296077Sadrian else 404296077Sadrian fhr.fhr_flag = defset; 405296077Sadrian fhr.fhr_vers = rqstp->rq_vers; 406296077Sadrian /* Get the file handle */ 407296077Sadrian bzero((caddr_t)&fhr.fhr_fh, sizeof(nfsfh_t)); 408296077Sadrian if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) { 409296077Sadrian bad = errno; 410296077Sadrian syslog(LOG_ERR, "Can't get fh for %s", dirpath); 411296077Sadrian if (!svc_sendreply(transp, xdr_long, 412296077Sadrian (caddr_t)&bad)) 413296077Sadrian syslog(LOG_ERR, "Can't send reply"); 414296077Sadrian sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 415296077Sadrian return; 416296077Sadrian } 417296077Sadrian if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr)) 418296077Sadrian syslog(LOG_ERR, "Can't send reply"); 419296077Sadrian if (hp == NULL) 420296077Sadrian hp = gethostbyaddr((caddr_t)&saddr, 421296077Sadrian sizeof(saddr), AF_INET); 422296077Sadrian if (hp) 423296077Sadrian add_mlist(hp->h_name, dirpath); 424296077Sadrian else 425296077Sadrian add_mlist(inet_ntoa(transp->xp_raddr.sin_addr), 426296077Sadrian dirpath); 427296077Sadrian if (debug) 428296077Sadrian fprintf(stderr,"Mount successfull.\n"); 429296077Sadrian } else { 430296077Sadrian bad = EACCES; 431296077Sadrian if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 432296077Sadrian syslog(LOG_ERR, "Can't send reply"); 433296077Sadrian } 434296077Sadrian sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 435296077Sadrian return; 436296077Sadrian case RPCMNT_DUMP: 437296077Sadrian if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL)) 438296077Sadrian syslog(LOG_ERR, "Can't send reply"); 439296077Sadrian return; 440300628Sadrian case RPCMNT_UMOUNT: 441296077Sadrian if (sport >= IPPORT_RESERVED && resvport_only) { 442296077Sadrian svcerr_weakauth(transp); 443296077Sadrian return; 444296077Sadrian } 445296077Sadrian if (!svc_getargs(transp, xdr_dir, dirpath)) { 446296077Sadrian svcerr_decode(transp); 447296077Sadrian return; 448296077Sadrian } 449296077Sadrian if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 450296077Sadrian syslog(LOG_ERR, "Can't send reply"); 451296077Sadrian hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 452296077Sadrian if (hp) 453296077Sadrian del_mlist(hp->h_name, dirpath); 454296077Sadrian del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath); 455296077Sadrian return; 456296077Sadrian case RPCMNT_UMNTALL: 457296077Sadrian if (sport >= IPPORT_RESERVED && resvport_only) { 458296077Sadrian svcerr_weakauth(transp); 459300628Sadrian return; 460296077Sadrian } 461296077Sadrian if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 462300628Sadrian syslog(LOG_ERR, "Can't send reply"); 463296077Sadrian hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 464296077Sadrian if (hp) 465300628Sadrian del_mlist(hp->h_name, (char *)NULL); 466296077Sadrian del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), (char *)NULL); 467296077Sadrian return; 468300628Sadrian case RPCMNT_EXPORT: 469300628Sadrian if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL)) 470296077Sadrian syslog(LOG_ERR, "Can't send reply"); 471296077Sadrian return; 472300628Sadrian default: 473300628Sadrian svcerr_noproc(transp); 474296077Sadrian return; 475296077Sadrian } 476296077Sadrian} 477296077Sadrian 478296077Sadrian/* 479296077Sadrian * Xdr conversion for a dirpath string 480299240Sadrian */ 481299240Sadrianint 482299240Sadrianxdr_dir(xdrsp, dirp) 483299240Sadrian XDR *xdrsp; 484299240Sadrian char *dirp; 485299240Sadrian{ 486299240Sadrian return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 487299240Sadrian} 488299240Sadrian 489299240Sadrian/* 490299240Sadrian * Xdr routine to generate file handle reply 491299240Sadrian */ 492300628Sadrianint 493299996Sadrianxdr_fhs(xdrsp, cp) 494299996Sadrian XDR *xdrsp; 495300628Sadrian caddr_t cp; 496299240Sadrian{ 497299240Sadrian register struct fhreturn *fhrp = (struct fhreturn *)cp; 498300628Sadrian u_long ok = 0, len, auth; 499299240Sadrian 500299240Sadrian if (!xdr_long(xdrsp, &ok)) 501299240Sadrian return (0); 502300628Sadrian switch (fhrp->fhr_vers) { 503300628Sadrian case 1: 504299996Sadrian return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH)); 505300628Sadrian case 3: 506300628Sadrian len = NFSX_V3FH; 507300628Sadrian if (!xdr_long(xdrsp, &len)) 508300628Sadrian return (0); 509300628Sadrian if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) 510300628Sadrian return (0); 511300628Sadrian if (fhrp->fhr_flag & DP_KERB) 512300628Sadrian auth = RPCAUTH_KERB4; 513300628Sadrian else 514300628Sadrian auth = RPCAUTH_UNIX; 515300628Sadrian len = 1; 516300628Sadrian if (!xdr_long(xdrsp, &len)) 517300628Sadrian return (0); 518300628Sadrian return (xdr_long(xdrsp, &auth)); 519299996Sadrian }; 520299996Sadrian return (0); 521299996Sadrian} 522300628Sadrian 523300628Sadrianint 524299996Sadrianxdr_mlist(xdrsp, cp) 525299996Sadrian XDR *xdrsp; 526300628Sadrian caddr_t cp; 527299996Sadrian{ 528299996Sadrian struct mountlist *mlp; 529300628Sadrian int true = 1; 530299996Sadrian int false = 0; 531299996Sadrian char *strp; 532299996Sadrian 533299240Sadrian mlp = mlhead; 534299240Sadrian while (mlp) { 535299240Sadrian if (!xdr_bool(xdrsp, &true)) 536299240Sadrian return (0); 537296077Sadrian strp = &mlp->ml_host[0]; 538296077Sadrian if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 539296077Sadrian return (0); 540296077Sadrian strp = &mlp->ml_dirp[0]; 541296077Sadrian if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 542296077Sadrian return (0); 543296077Sadrian mlp = mlp->ml_next; 544296077Sadrian } 545296077Sadrian if (!xdr_bool(xdrsp, &false)) 546296077Sadrian return (0); 547296077Sadrian return (1); 548296077Sadrian} 549296077Sadrian 550296077Sadrian/* 551296077Sadrian * Xdr conversion for export list 552296077Sadrian */ 553296077Sadrianint 554296077Sadrianxdr_explist(xdrsp, cp) 555296077Sadrian XDR *xdrsp; 556296077Sadrian caddr_t cp; 557296077Sadrian{ 558296077Sadrian struct exportlist *ep; 559296077Sadrian int false = 0; 560296077Sadrian int putdef; 561296077Sadrian sigset_t sighup_mask; 562296077Sadrian 563296077Sadrian sigemptyset(&sighup_mask); 564296077Sadrian sigaddset(&sighup_mask, SIGHUP); 565296077Sadrian sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 566296077Sadrian ep = exphead; 567296077Sadrian while (ep) { 568296077Sadrian putdef = 0; 569300628Sadrian if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, &putdef)) 570296077Sadrian goto errout; 571300628Sadrian if (ep->ex_defdir && putdef == 0 && 572300628Sadrian put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL, 573300628Sadrian &putdef)) 574300628Sadrian goto errout; 575300628Sadrian ep = ep->ex_next; 576296077Sadrian } 577300628Sadrian sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 578300628Sadrian if (!xdr_bool(xdrsp, &false)) 579300628Sadrian return (0); 580300628Sadrian return (1); 581300628Sadrianerrout: 582300628Sadrian sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 583300628Sadrian return (0); 584300628Sadrian} 585300628Sadrian 586300628Sadrian/* 587300628Sadrian * Called from xdr_explist() to traverse the tree and export the 588300628Sadrian * directory paths. 589300628Sadrian */ 590300628Sadrianint 591300628Sadrianput_exlist(dp, xdrsp, adp, putdefp) 592300628Sadrian struct dirlist *dp; 593300628Sadrian XDR *xdrsp; 594300628Sadrian struct dirlist *adp; 595300628Sadrian int *putdefp; 596300628Sadrian{ 597300628Sadrian struct grouplist *grp; 598300628Sadrian struct hostlist *hp; 599300628Sadrian int true = 1; 600300628Sadrian int false = 0; 601300628Sadrian int gotalldir = 0; 602300628Sadrian char *strp; 603300628Sadrian 604300628Sadrian if (dp) { 605300628Sadrian if (put_exlist(dp->dp_left, xdrsp, adp, putdefp)) 606300628Sadrian return (1); 607300628Sadrian if (!xdr_bool(xdrsp, &true)) 608300628Sadrian return (1); 609300628Sadrian strp = dp->dp_dirp; 610300628Sadrian if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 611300628Sadrian return (1); 612300628Sadrian if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) { 613300628Sadrian gotalldir = 1; 614300628Sadrian *putdefp = 1; 615300628Sadrian } 616300628Sadrian if ((dp->dp_flag & DP_DEFSET) == 0 && 617300628Sadrian (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) { 618300628Sadrian hp = dp->dp_hosts; 619300628Sadrian while (hp) { 620300628Sadrian grp = hp->ht_grp; 621300628Sadrian if (grp->gr_type == GT_HOST) { 622296077Sadrian if (!xdr_bool(xdrsp, &true)) 623296077Sadrian return (1); 624296077Sadrian strp = grp->gr_ptr.gt_hostent->h_name; 625298278Sadrian if (!xdr_string(xdrsp, &strp, 626298278Sadrian RPCMNT_NAMELEN)) 627298278Sadrian return (1); 628298278Sadrian } else if (grp->gr_type == GT_NET) { 629298278Sadrian if (!xdr_bool(xdrsp, &true)) 630298278Sadrian return (1); 631298278Sadrian strp = grp->gr_ptr.gt_net.nt_name; 632298278Sadrian if (!xdr_string(xdrsp, &strp, 633298278Sadrian RPCMNT_NAMELEN)) 634298278Sadrian return (1); 635298278Sadrian } 636298278Sadrian hp = hp->ht_next; 637298278Sadrian if (gotalldir && hp == (struct hostlist *)NULL) { 638299235Sadrian hp = adp->dp_hosts; 639299235Sadrian gotalldir = 0; 640300628Sadrian } 641300628Sadrian } 642298278Sadrian } 643299235Sadrian if (!xdr_bool(xdrsp, &false)) 644299235Sadrian return (1); 645300628Sadrian if (put_exlist(dp->dp_right, xdrsp, adp, putdefp)) 646299235Sadrian return (1); 647300628Sadrian } 648298278Sadrian return (0); 649298278Sadrian} 650298278Sadrian 651298278Sadrian#define LINESIZ 10240 652298278Sadrianchar line[LINESIZ]; 653298278SadrianFILE *exp_file; 654298278Sadrian 655300628Sadrian/* 656300628Sadrian * Get the export list 657300628Sadrian */ 658300628Sadrianvoid 659300628Sadrianget_exportlist() 660300628Sadrian{ 661300628Sadrian struct exportlist *ep, *ep2; 662300628Sadrian struct grouplist *grp, *tgrp; 663300628Sadrian struct exportlist **epp; 664300628Sadrian struct dirlist *dirhead; 665300628Sadrian struct statfs fsb, *fsp; 666299235Sadrian struct hostent *hpe; 667298278Sadrian struct ucred anon; 668298278Sadrian char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; 669300628Sadrian int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp; 670300628Sadrian 671300628Sadrian /* 672300628Sadrian * First, get rid of the old list 673298278Sadrian */ 674298278Sadrian ep = exphead; 675298278Sadrian while (ep) { 676298278Sadrian ep2 = ep; 677298278Sadrian ep = ep->ex_next; 678298278Sadrian free_exp(ep2); 679298278Sadrian } 680298278Sadrian exphead = (struct exportlist *)NULL; 681298278Sadrian 682300628Sadrian grp = grphead; 683299240Sadrian while (grp) { 684298278Sadrian tgrp = grp; 685298278Sadrian grp = grp->gr_next; 686298278Sadrian free_grp(tgrp); 687298278Sadrian } 688298278Sadrian grphead = (struct grouplist *)NULL; 689298278Sadrian 690298278Sadrian /* 691298278Sadrian * And delete exports that are in the kernel for all local 692298278Sadrian * file systems. 693298278Sadrian * XXX: Should know how to handle all local exportable file systems 694300628Sadrian * instead of just MOUNT_UFS. 695298278Sadrian */ 696298278Sadrian num = getmntinfo(&fsp, MNT_NOWAIT); 697300628Sadrian for (i = 0; i < num; i++) { 698300628Sadrian union { 699300628Sadrian struct ufs_args ua; 700298278Sadrian struct iso_args ia; 701300628Sadrian struct mfs_args ma; 702300628Sadrian#ifdef __NetBSD__ 703300628Sadrian struct msdosfs_args da; 704298278Sadrian } targs; 705298278Sadrian 706299996Sadrian if (!strcmp(fsp->f_fstypename, MOUNT_MFS) || 707300628Sadrian !strcmp(fsp->f_fstypename, MOUNT_UFS) || 708300628Sadrian !strcmp(fsp->f_fstypename, MOUNT_MSDOS) || 709300628Sadrian !strcmp(fsp->f_fstypename, MOUNT_CD9660)) { 710300628Sadrian targs.ua.fspec = NULL; 711298278Sadrian targs.ua.export.ex_flags = MNT_DELEXPORT; 712298278Sadrian if (mount(fsp->f_fstypename, fsp->f_mntonname, 713298278Sadrian#else 714298278Sadrian } targs; 715298278Sadrian 716298278Sadrian switch (fsp->f_type) { 717298278Sadrian case MOUNT_MFS: 718296077Sadrian case MOUNT_UFS: 719296077Sadrian case MOUNT_CD9660: 720296077Sadrian case MOUNT_MSDOS: 721296077Sadrian targs.ua.fspec = NULL; 722296077Sadrian targs.ua.export.ex_flags = MNT_DELEXPORT; 723296077Sadrian if (mount(fsp->f_type, fsp->f_mntonname, 724296077Sadrian#endif 725296077Sadrian fsp->f_flags | MNT_UPDATE, 726296077Sadrian (caddr_t)&targs) < 0) 727296077Sadrian syslog(LOG_ERR, "Can't delete exports for %s", 728296077Sadrian fsp->f_mntonname); 729296077Sadrian } 730296077Sadrian fsp++; 731296077Sadrian } 732296077Sadrian 733296077Sadrian /* 734296077Sadrian * Read in the exports file and build the list, calling 735296077Sadrian * mount() as we go along to push the export rules into the kernel. 736296077Sadrian */ 737296077Sadrian if ((exp_file = fopen(exname, "r")) == NULL) { 738296077Sadrian syslog(LOG_ERR, "Can't open %s", exname); 739296077Sadrian exit(2); 740296077Sadrian } 741296077Sadrian dirhead = (struct dirlist *)NULL; 742296077Sadrian while (get_line()) { 743296077Sadrian if (debug) 744296077Sadrian fprintf(stderr,"Got line %s\n",line); 745296077Sadrian cp = line; 746296077Sadrian nextfield(&cp, &endcp); 747296077Sadrian if (*cp == '#') 748296077Sadrian goto nextline; 749296077Sadrian 750296077Sadrian /* 751296077Sadrian * Set defaults. 752296077Sadrian */ 753296077Sadrian has_host = FALSE; 754296077Sadrian anon = def_anon; 755296077Sadrian exflags = MNT_EXPORTED; 756296077Sadrian got_nondir = 0; 757296077Sadrian opt_flags = 0; 758296077Sadrian ep = (struct exportlist *)NULL; 759296077Sadrian 760296077Sadrian /* 761296077Sadrian * Create new exports list entry 762296077Sadrian */ 763296077Sadrian len = endcp-cp; 764296077Sadrian tgrp = grp = get_grp(); 765296077Sadrian while (len > 0) { 766296077Sadrian if (len > RPCMNT_NAMELEN) { 767296077Sadrian getexp_err(ep, tgrp); 768296077Sadrian goto nextline; 769296077Sadrian } 770296077Sadrian if (*cp == '-') { 771296077Sadrian if (ep == (struct exportlist *)NULL) { 772296077Sadrian getexp_err(ep, tgrp); 773296077Sadrian goto nextline; 774296077Sadrian } 775296077Sadrian if (debug) 776296077Sadrian fprintf(stderr, "doing opt %s\n", cp); 777296077Sadrian got_nondir = 1; 778296077Sadrian if (do_opt(&cp, &endcp, ep, grp, &has_host, 779296077Sadrian &exflags, &anon)) { 780296077Sadrian getexp_err(ep, tgrp); 781296077Sadrian goto nextline; 782296077Sadrian } 783296077Sadrian } else if (*cp == '/') { 784296077Sadrian savedc = *endcp; 785296077Sadrian *endcp = '\0'; 786296077Sadrian if (check_dirpath(cp) && 787296077Sadrian statfs(cp, &fsb) >= 0) { 788296077Sadrian if (got_nondir) { 789296077Sadrian syslog(LOG_ERR, "Dirs must be first"); 790296077Sadrian getexp_err(ep, tgrp); 791296077Sadrian goto nextline; 792300548Sadrian } 793300548Sadrian if (ep) { 794300548Sadrian if (ep->ex_fs.val[0] != fsb.f_fsid.val[0] || 795300548Sadrian ep->ex_fs.val[1] != fsb.f_fsid.val[1]) { 796300548Sadrian getexp_err(ep, tgrp); 797296077Sadrian goto nextline; 798296077Sadrian } 799296077Sadrian } else { 800296077Sadrian /* 801296077Sadrian * See if this directory is already 802296077Sadrian * in the list. 803296077Sadrian */ 804296077Sadrian ep = ex_search(&fsb.f_fsid); 805296077Sadrian if (ep == (struct exportlist *)NULL) { 806296077Sadrian ep = get_exp(); 807296077Sadrian ep->ex_fs = fsb.f_fsid; 808296077Sadrian ep->ex_fsdir = (char *) 809296077Sadrian malloc(strlen(fsb.f_mntonname) + 1); 810296077Sadrian if (ep->ex_fsdir) 811296077Sadrian strcpy(ep->ex_fsdir, 812296077Sadrian fsb.f_mntonname); 813296077Sadrian else 814296077Sadrian out_of_mem(); 815296077Sadrian if (debug) 816296077Sadrian fprintf(stderr, 817296077Sadrian "Making new ep fs=0x%x,0x%x\n", 818296077Sadrian fsb.f_fsid.val[0], 819296077Sadrian fsb.f_fsid.val[1]); 820296077Sadrian } else if (debug) 821296077Sadrian fprintf(stderr, 822296077Sadrian "Found ep fs=0x%x,0x%x\n", 823296077Sadrian fsb.f_fsid.val[0], 824296077Sadrian fsb.f_fsid.val[1]); 825296077Sadrian } 826296077Sadrian 827296077Sadrian /* 828296077Sadrian * Add dirpath to export mount point. 829296077Sadrian */ 830296077Sadrian dirp = add_expdir(&dirhead, cp, len); 831296077Sadrian dirplen = len; 832296077Sadrian } else { 833296077Sadrian getexp_err(ep, tgrp); 834296077Sadrian goto nextline; 835296077Sadrian } 836296077Sadrian *endcp = savedc; 837296077Sadrian } else { 838296077Sadrian savedc = *endcp; 839296077Sadrian *endcp = '\0'; 840296077Sadrian got_nondir = 1; 841296077Sadrian if (ep == (struct exportlist *)NULL) { 842296077Sadrian getexp_err(ep, tgrp); 843296077Sadrian goto nextline; 844296077Sadrian } 845296077Sadrian 846296077Sadrian /* 847296077Sadrian * Get the host or netgroup. 848296077Sadrian */ 849296077Sadrian setnetgrent(cp); 850296077Sadrian netgrp = getnetgrent(&hst, &usr, &dom); 851296077Sadrian do { 852296077Sadrian if (has_host) { 853296077Sadrian grp->gr_next = get_grp(); 854296077Sadrian grp = grp->gr_next; 855296077Sadrian } 856296077Sadrian if (netgrp) { 857296077Sadrian if (get_host(hst, grp, tgrp)) { 858296077Sadrian syslog(LOG_ERR, "Bad netgroup %s", cp); 859296077Sadrian getexp_err(ep, tgrp); 860296077Sadrian endnetgrent(); 861296077Sadrian goto nextline; 862296077Sadrian } 863296077Sadrian } else if (get_host(cp, grp, tgrp)) { 864296077Sadrian getexp_err(ep, tgrp); 865296077Sadrian goto nextline; 866296077Sadrian } 867298278Sadrian has_host = TRUE; 868298278Sadrian } while (netgrp && getnetgrent(&hst, &usr, &dom)); 869296077Sadrian endnetgrent(); 870296077Sadrian *endcp = savedc; 871298278Sadrian } 872296077Sadrian cp = endcp; 873296077Sadrian nextfield(&cp, &endcp); 874298278Sadrian len = endcp - cp; 875296077Sadrian } 876296077Sadrian if (check_options(dirhead)) { 877296077Sadrian getexp_err(ep, tgrp); 878296077Sadrian goto nextline; 879296077Sadrian } 880298278Sadrian if (!has_host) { 881298278Sadrian grp->gr_type = GT_HOST; 882296077Sadrian if (debug) 883296077Sadrian fprintf(stderr,"Adding a default entry\n"); 884296077Sadrian /* add a default group and make the grp list NULL */ 885296077Sadrian hpe = (struct hostent *)malloc(sizeof(struct hostent)); 886296077Sadrian if (hpe == (struct hostent *)NULL) 887296077Sadrian out_of_mem(); 888296077Sadrian hpe->h_name = strdup("Default"); 889296077Sadrian hpe->h_addrtype = AF_INET; 890298277Sadrian hpe->h_length = sizeof (u_long); 891298277Sadrian hpe->h_addr_list = (char **)NULL; 892298278Sadrian grp->gr_ptr.gt_hostent = hpe; 893298278Sadrian 894298278Sadrian /* 895298278Sadrian * Don't allow a network export coincide with a list of 896298278Sadrian * host(s) on the same line. 897298278Sadrian */ 898298278Sadrian } else if ((opt_flags & OP_NET) && tgrp->gr_next) { 899298278Sadrian getexp_err(ep, tgrp); 900298278Sadrian goto nextline; 901298278Sadrian } 902298278Sadrian 903298278Sadrian /* 904298277Sadrian * Loop through hosts, pushing the exports into the kernel. 905298277Sadrian * After loop, tgrp points to the start of the list and 906298277Sadrian * grp points to the last entry in the list. 907298277Sadrian */ 908298277Sadrian grp = tgrp; 909298277Sadrian do { 910298277Sadrian if (do_mount(ep, grp, exflags, &anon, dirp, 911298277Sadrian dirplen, &fsb)) { 912298277Sadrian getexp_err(ep, tgrp); 913298277Sadrian goto nextline; 914298277Sadrian } 915298277Sadrian } while (grp->gr_next && (grp = grp->gr_next)); 916298277Sadrian 917298277Sadrian /* 918298277Sadrian * Success. Update the data structures. 919298277Sadrian */ 920298277Sadrian if (has_host) { 921298277Sadrian hang_dirp(dirhead, tgrp, ep, opt_flags); 922298277Sadrian grp->gr_next = grphead; 923298277Sadrian grphead = tgrp; 924298277Sadrian } else { 925298277Sadrian hang_dirp(dirhead, (struct grouplist *)NULL, ep, 926298277Sadrian opt_flags); 927298277Sadrian free_grp(grp); 928298277Sadrian } 929298277Sadrian dirhead = (struct dirlist *)NULL; 930298277Sadrian if ((ep->ex_flag & EX_LINKED) == 0) { 931298277Sadrian ep2 = exphead; 932298277Sadrian epp = &exphead; 933298277Sadrian 934298277Sadrian /* 935298277Sadrian * Insert in the list in alphabetical order. 936298277Sadrian */ 937299996Sadrian while (ep2 && strcmp(ep2->ex_fsdir, ep->ex_fsdir) < 0) { 938299996Sadrian epp = &ep2->ex_next; 939299996Sadrian ep2 = ep2->ex_next; 940299996Sadrian } 941299996Sadrian if (ep2) 942299996Sadrian ep->ex_next = ep2; 943299996Sadrian *epp = ep; 944299996Sadrian ep->ex_flag |= EX_LINKED; 945299996Sadrian } 946299996Sadriannextline: 947299996Sadrian if (dirhead) { 948299996Sadrian free_dir(dirhead); 949299996Sadrian dirhead = (struct dirlist *)NULL; 950299996Sadrian } 951299996Sadrian } 952299996Sadrian fclose(exp_file); 953299996Sadrian} 954299996Sadrian 955299996Sadrian/* 956299996Sadrian * Allocate an export list element 957299996Sadrian */ 958299996Sadrianstruct exportlist * 959299996Sadrianget_exp() 960299996Sadrian{ 961298277Sadrian struct exportlist *ep; 962299996Sadrian 963299996Sadrian ep = (struct exportlist *)malloc(sizeof (struct exportlist)); 964299996Sadrian if (ep == (struct exportlist *)NULL) 965299996Sadrian out_of_mem(); 966299996Sadrian bzero((caddr_t)ep, sizeof (struct exportlist)); 967299996Sadrian return (ep); 968299996Sadrian} 969299996Sadrian 970299996Sadrian/* 971299996Sadrian * Allocate a group list element 972299996Sadrian */ 973299996Sadrianstruct grouplist * 974299996Sadrianget_grp() 975299996Sadrian{ 976299996Sadrian struct grouplist *gp; 977299996Sadrian 978299996Sadrian gp = (struct grouplist *)malloc(sizeof (struct grouplist)); 979299996Sadrian if (gp == (struct grouplist *)NULL) 980299996Sadrian out_of_mem(); 981299996Sadrian bzero((caddr_t)gp, sizeof (struct grouplist)); 982299996Sadrian return (gp); 983299996Sadrian} 984299996Sadrian 985299996Sadrian/* 986299996Sadrian * Clean up upon an error in get_exportlist(). 987299996Sadrian */ 988299996Sadrianvoid 989299996Sadriangetexp_err(ep, grp) 990299996Sadrian struct exportlist *ep; 991299996Sadrian struct grouplist *grp; 992299996Sadrian{ 993299996Sadrian struct grouplist *tgrp; 994299996Sadrian 995299996Sadrian syslog(LOG_ERR, "Bad exports list line %s", line); 996299996Sadrian if (ep && (ep->ex_flag & EX_LINKED) == 0) 997299996Sadrian free_exp(ep); 998299996Sadrian while (grp) { 999299996Sadrian tgrp = grp; 1000299996Sadrian grp = grp->gr_next; 1001299996Sadrian free_grp(tgrp); 1002299996Sadrian } 1003299996Sadrian} 1004299996Sadrian 1005299996Sadrian/* 1006299996Sadrian * Search the export list for a matching fs. 1007299996Sadrian */ 1008299996Sadrianstruct exportlist * 1009299996Sadrianex_search(fsid) 1010299996Sadrian fsid_t *fsid; 1011299996Sadrian{ 1012299996Sadrian struct exportlist *ep; 1013299996Sadrian 1014299996Sadrian ep = exphead; 1015300548Sadrian while (ep) { 1016299996Sadrian if (ep->ex_fs.val[0] == fsid->val[0] && 1017300548Sadrian ep->ex_fs.val[1] == fsid->val[1]) 1018300548Sadrian return (ep); 1019300548Sadrian ep = ep->ex_next; 1020299996Sadrian } 1021299996Sadrian return (ep); 1022299996Sadrian} 1023299996Sadrian 1024299996Sadrian/* 1025299996Sadrian * Add a directory path to the list. 1026299996Sadrian */ 1027299996Sadrianchar * 1028299996Sadrianadd_expdir(dpp, cp, len) 1029299996Sadrian struct dirlist **dpp; 1030299996Sadrian char *cp; 1031299996Sadrian int len; 1032299996Sadrian{ 1033299996Sadrian struct dirlist *dp; 1034299996Sadrian 1035299996Sadrian dp = (struct dirlist *)malloc(sizeof (struct dirlist) + len); 1036299996Sadrian dp->dp_left = *dpp; 1037299996Sadrian dp->dp_right = (struct dirlist *)NULL; 1038299996Sadrian dp->dp_flag = 0; 1039299996Sadrian dp->dp_hosts = (struct hostlist *)NULL; 1040299996Sadrian strcpy(dp->dp_dirp, cp); 1041299996Sadrian *dpp = dp; 1042299996Sadrian return (dp->dp_dirp); 1043299996Sadrian} 1044299996Sadrian 1045299996Sadrian/* 1046299996Sadrian * Hang the dir list element off the dirpath binary tree as required 1047299996Sadrian * and update the entry for host. 1048299996Sadrian */ 1049299996Sadrianvoid 1050299996Sadrianhang_dirp(dp, grp, ep, flags) 1051299996Sadrian struct dirlist *dp; 1052299996Sadrian struct grouplist *grp; 1053299996Sadrian struct exportlist *ep; 1054299996Sadrian int flags; 1055299996Sadrian{ 1056299996Sadrian struct hostlist *hp; 1057299996Sadrian struct dirlist *dp2; 1058298277Sadrian 1059298277Sadrian if (flags & OP_ALLDIRS) { 1060298277Sadrian if (ep->ex_defdir) 1061298277Sadrian free((caddr_t)dp); 1062298277Sadrian else 1063298277Sadrian ep->ex_defdir = dp; 1064298277Sadrian if (grp == (struct grouplist *)NULL) { 1065298277Sadrian ep->ex_defdir->dp_flag |= DP_DEFSET; 1066298277Sadrian if (flags & OP_KERB) 1067298277Sadrian ep->ex_defdir->dp_flag |= DP_KERB; 1068298277Sadrian } else while (grp) { 1069298277Sadrian hp = get_ht(); 1070298277Sadrian if (flags & OP_KERB) 1071298277Sadrian hp->ht_flag |= DP_KERB; 1072298277Sadrian hp->ht_grp = grp; 1073298277Sadrian hp->ht_next = ep->ex_defdir->dp_hosts; 1074298277Sadrian ep->ex_defdir->dp_hosts = hp; 1075298277Sadrian grp = grp->gr_next; 1076298277Sadrian } 1077298277Sadrian } else { 1078298277Sadrian 1079298277Sadrian /* 1080298277Sadrian * Loop throught the directories adding them to the tree. 1081298277Sadrian */ 1082298277Sadrian while (dp) { 1083298277Sadrian dp2 = dp->dp_left; 1084298277Sadrian add_dlist(&ep->ex_dirl, dp, grp, flags); 1085298277Sadrian dp = dp2; 1086298277Sadrian } 1087298277Sadrian } 1088298277Sadrian} 1089298277Sadrian 1090298277Sadrian/* 1091298277Sadrian * Traverse the binary tree either updating a node that is already there 1092298277Sadrian * for the new directory or adding the new node. 1093298277Sadrian */ 1094298277Sadrianvoid 1095298277Sadrianadd_dlist(dpp, newdp, grp, flags) 1096298277Sadrian struct dirlist **dpp; 1097298277Sadrian struct dirlist *newdp; 1098298277Sadrian struct grouplist *grp; 1099298277Sadrian int flags; 1100298277Sadrian{ 1101298277Sadrian struct dirlist *dp; 1102298277Sadrian struct hostlist *hp; 1103298277Sadrian int cmp; 1104298277Sadrian 1105298277Sadrian dp = *dpp; 1106298277Sadrian if (dp) { 1107298277Sadrian cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); 1108298277Sadrian if (cmp > 0) { 1109298277Sadrian add_dlist(&dp->dp_left, newdp, grp, flags); 1110298277Sadrian return; 1111298277Sadrian } else if (cmp < 0) { 1112298277Sadrian add_dlist(&dp->dp_right, newdp, grp, flags); 1113298277Sadrian return; 1114298277Sadrian } else 1115298277Sadrian free((caddr_t)newdp); 1116298277Sadrian } else { 1117298277Sadrian dp = newdp; 1118298277Sadrian dp->dp_left = (struct dirlist *)NULL; 1119298277Sadrian *dpp = dp; 1120298277Sadrian } 1121298277Sadrian if (grp) { 1122298277Sadrian 1123298277Sadrian /* 1124298277Sadrian * Hang all of the host(s) off of the directory point. 1125298277Sadrian */ 1126298277Sadrian do { 1127298277Sadrian hp = get_ht(); 1128298277Sadrian if (flags & OP_KERB) 1129298277Sadrian hp->ht_flag |= DP_KERB; 1130298277Sadrian hp->ht_grp = grp; 1131298277Sadrian hp->ht_next = dp->dp_hosts; 1132298277Sadrian dp->dp_hosts = hp; 1133298277Sadrian grp = grp->gr_next; 1134298277Sadrian } while (grp); 1135298277Sadrian } else { 1136298277Sadrian dp->dp_flag |= DP_DEFSET; 1137298277Sadrian if (flags & OP_KERB) 1138298277Sadrian dp->dp_flag |= DP_KERB; 1139298277Sadrian } 1140298277Sadrian} 1141298277Sadrian 1142298277Sadrian/* 1143298277Sadrian * Search for a dirpath on the export point. 1144298277Sadrian */ 1145298277Sadrianstruct dirlist * 1146298277Sadriandirp_search(dp, dirpath) 1147298277Sadrian struct dirlist *dp; 1148298277Sadrian char *dirpath; 1149298277Sadrian{ 1150298277Sadrian int cmp; 1151298277Sadrian 1152298277Sadrian if (dp) { 1153298277Sadrian cmp = strcmp(dp->dp_dirp, dirpath); 1154298277Sadrian if (cmp > 0) 1155298277Sadrian return (dirp_search(dp->dp_left, dirpath)); 1156298277Sadrian else if (cmp < 0) 1157298277Sadrian return (dirp_search(dp->dp_right, dirpath)); 1158298277Sadrian else 1159298277Sadrian return (dp); 1160298943Sadrian } 1161301408Slandonf return (dp); 1162} 1163 1164/* 1165 * Scan for a host match in a directory tree. 1166 */ 1167int 1168chk_host(dp, saddr, defsetp, hostsetp) 1169 struct dirlist *dp; 1170 u_long saddr; 1171 int *defsetp; 1172 int *hostsetp; 1173{ 1174 struct hostlist *hp; 1175 struct grouplist *grp; 1176 u_long **addrp; 1177 1178 if (dp) { 1179 if (dp->dp_flag & DP_DEFSET) 1180 *defsetp = dp->dp_flag; 1181 hp = dp->dp_hosts; 1182 while (hp) { 1183 grp = hp->ht_grp; 1184 switch (grp->gr_type) { 1185 case GT_HOST: 1186 addrp = (u_long **) 1187 grp->gr_ptr.gt_hostent->h_addr_list; 1188 while (*addrp) { 1189 if (**addrp == saddr) { 1190 *hostsetp = (hp->ht_flag | DP_HOSTSET); 1191 return (1); 1192 } 1193 addrp++; 1194 } 1195 break; 1196 case GT_NET: 1197 if ((saddr & grp->gr_ptr.gt_net.nt_mask) == 1198 grp->gr_ptr.gt_net.nt_net) { 1199 *hostsetp = (hp->ht_flag | DP_HOSTSET); 1200 return (1); 1201 } 1202 break; 1203 }; 1204 hp = hp->ht_next; 1205 } 1206 } 1207 return (0); 1208} 1209 1210/* 1211 * Scan tree for a host that matches the address. 1212 */ 1213int 1214scan_tree(dp, saddr) 1215 struct dirlist *dp; 1216 u_long saddr; 1217{ 1218 int defset, hostset; 1219 1220 if (dp) { 1221 if (scan_tree(dp->dp_left, saddr)) 1222 return (1); 1223 if (chk_host(dp, saddr, &defset, &hostset)) 1224 return (1); 1225 if (scan_tree(dp->dp_right, saddr)) 1226 return (1); 1227 } 1228 return (0); 1229} 1230 1231/* 1232 * Traverse the dirlist tree and free it up. 1233 */ 1234void 1235free_dir(dp) 1236 struct dirlist *dp; 1237{ 1238 1239 if (dp) { 1240 free_dir(dp->dp_left); 1241 free_dir(dp->dp_right); 1242 free_host(dp->dp_hosts); 1243 free((caddr_t)dp); 1244 } 1245} 1246 1247/* 1248 * Parse the option string and update fields. 1249 * Option arguments may either be -<option>=<value> or 1250 * -<option> <value> 1251 */ 1252int 1253do_opt(cpp, endcpp, ep, grp, has_hostp, exflagsp, cr) 1254 char **cpp, **endcpp; 1255 struct exportlist *ep; 1256 struct grouplist *grp; 1257 int *has_hostp; 1258 int *exflagsp; 1259 struct ucred *cr; 1260{ 1261 char *cpoptarg, *cpoptend; 1262 char *cp, *endcp, *cpopt, savedc, savedc2; 1263 int allflag, usedarg; 1264 1265 cpopt = *cpp; 1266 cpopt++; 1267 cp = *endcpp; 1268 savedc = *cp; 1269 *cp = '\0'; 1270 while (cpopt && *cpopt) { 1271 allflag = 1; 1272 usedarg = -2; 1273 if (cpoptend = index(cpopt, ',')) { 1274 *cpoptend++ = '\0'; 1275 if (cpoptarg = index(cpopt, '=')) 1276 *cpoptarg++ = '\0'; 1277 } else { 1278 if (cpoptarg = index(cpopt, '=')) 1279 *cpoptarg++ = '\0'; 1280 else { 1281 *cp = savedc; 1282 nextfield(&cp, &endcp); 1283 **endcpp = '\0'; 1284 if (endcp > cp && *cp != '-') { 1285 cpoptarg = cp; 1286 savedc2 = *endcp; 1287 *endcp = '\0'; 1288 usedarg = 0; 1289 } 1290 } 1291 } 1292 if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 1293 *exflagsp |= MNT_EXRDONLY; 1294 } else if (cpoptarg && (!strcmp(cpopt, "maproot") || 1295 !(allflag = strcmp(cpopt, "mapall")) || 1296 !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) { 1297 usedarg++; 1298 parsecred(cpoptarg, cr); 1299 if (allflag == 0) { 1300 *exflagsp |= MNT_EXPORTANON; 1301 opt_flags |= OP_MAPALL; 1302 } else 1303 opt_flags |= OP_MAPROOT; 1304 } else if (!strcmp(cpopt, "kerb") || !strcmp(cpopt, "k")) { 1305 *exflagsp |= MNT_EXKERB; 1306 opt_flags |= OP_KERB; 1307 } else if (cpoptarg && (!strcmp(cpopt, "mask") || 1308 !strcmp(cpopt, "m"))) { 1309 if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { 1310 syslog(LOG_ERR, "Bad mask: %s", cpoptarg); 1311 return (1); 1312 } 1313 usedarg++; 1314 opt_flags |= OP_MASK; 1315 } else if (cpoptarg && (!strcmp(cpopt, "network") || 1316 !strcmp(cpopt, "n"))) { 1317 if (grp->gr_type != GT_NULL) { 1318 syslog(LOG_ERR, "Network/host conflict"); 1319 return (1); 1320 } else if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 0)) { 1321 syslog(LOG_ERR, "Bad net: %s", cpoptarg); 1322 return (1); 1323 } 1324 grp->gr_type = GT_NET; 1325 *has_hostp = 1; 1326 usedarg++; 1327 opt_flags |= OP_NET; 1328 } else if (!strcmp(cpopt, "alldirs")) { 1329 opt_flags |= OP_ALLDIRS; 1330#ifdef ISO 1331 } else if (cpoptarg && !strcmp(cpopt, "iso")) { 1332 if (get_isoaddr(cpoptarg, grp)) { 1333 syslog(LOG_ERR, "Bad iso addr: %s", cpoptarg); 1334 return (1); 1335 } 1336 *has_hostp = 1; 1337 usedarg++; 1338 opt_flags |= OP_ISO; 1339#endif /* ISO */ 1340 } else { 1341 syslog(LOG_ERR, "Bad opt %s", cpopt); 1342 return (1); 1343 } 1344 if (usedarg >= 0) { 1345 *endcp = savedc2; 1346 **endcpp = savedc; 1347 if (usedarg > 0) { 1348 *cpp = cp; 1349 *endcpp = endcp; 1350 } 1351 return (0); 1352 } 1353 cpopt = cpoptend; 1354 } 1355 **endcpp = savedc; 1356 return (0); 1357} 1358 1359/* 1360 * Translate a character string to the corresponding list of network 1361 * addresses for a hostname. 1362 */ 1363int 1364get_host(cp, grp, tgrp) 1365 char *cp; 1366 struct grouplist *grp; 1367 struct grouplist *tgrp; 1368{ 1369 struct grouplist *checkgrp; 1370 struct hostent *hp, *nhp; 1371 char **addrp, **naddrp; 1372 struct hostent t_host; 1373 int i; 1374 u_long saddr; 1375 char *aptr[2]; 1376 1377 if (grp->gr_type != GT_NULL) 1378 return (1); 1379 if ((hp = gethostbyname(cp)) == NULL) { 1380 if (isdigit(*cp)) { 1381 saddr = inet_addr(cp); 1382 if (saddr == -1) { 1383 syslog(LOG_ERR, "Inet_addr failed for %s", cp); 1384 return (1); 1385 } 1386 if ((hp = gethostbyaddr((caddr_t)&saddr, sizeof (saddr), 1387 AF_INET)) == NULL) { 1388 hp = &t_host; 1389 hp->h_name = cp; 1390 hp->h_addrtype = AF_INET; 1391 hp->h_length = sizeof (u_long); 1392 hp->h_addr_list = aptr; 1393 aptr[0] = (char *)&saddr; 1394 aptr[1] = (char *)NULL; 1395 } 1396 } else { 1397 syslog(LOG_ERR, "Gethostbyname failed for %s", cp); 1398 return (1); 1399 } 1400 } 1401 /* 1402 * Sanity check: make sure we don't already have an entry 1403 * for this host in the grouplist. 1404 */ 1405 checkgrp = tgrp; 1406 while (checkgrp) { 1407 if (checkgrp->gr_type == GT_HOST && 1408 checkgrp->gr_ptr.gt_hostent != NULL && 1409 !strcmp(checkgrp->gr_ptr.gt_hostent->h_name, hp->h_name)) { 1410 grp->gr_type = GT_IGNORE; 1411 return(0); 1412 } 1413 checkgrp = checkgrp->gr_next; 1414 } 1415 1416 grp->gr_type = GT_HOST; 1417 nhp = grp->gr_ptr.gt_hostent = (struct hostent *) 1418 malloc(sizeof(struct hostent)); 1419 if (nhp == (struct hostent *)NULL) 1420 out_of_mem(); 1421 bcopy((caddr_t)hp, (caddr_t)nhp, 1422 sizeof(struct hostent)); 1423 i = strlen(hp->h_name)+1; 1424 nhp->h_name = (char *)malloc(i); 1425 if (nhp->h_name == (char *)NULL) 1426 out_of_mem(); 1427 bcopy(hp->h_name, nhp->h_name, i); 1428 addrp = hp->h_addr_list; 1429 i = 1; 1430 while (*addrp++) 1431 i++; 1432 naddrp = nhp->h_addr_list = (char **) 1433 malloc(i*sizeof(char *)); 1434 if (naddrp == (char **)NULL) 1435 out_of_mem(); 1436 addrp = hp->h_addr_list; 1437 while (*addrp) { 1438 *naddrp = (char *) 1439 malloc(hp->h_length); 1440 if (*naddrp == (char *)NULL) 1441 out_of_mem(); 1442 bcopy(*addrp, *naddrp, 1443 hp->h_length); 1444 addrp++; 1445 naddrp++; 1446 } 1447 *naddrp = (char *)NULL; 1448 if (debug) 1449 fprintf(stderr, "got host %s\n", hp->h_name); 1450 return (0); 1451} 1452 1453/* 1454 * Free up an exports list component 1455 */ 1456void 1457free_exp(ep) 1458 struct exportlist *ep; 1459{ 1460 1461 if (ep->ex_defdir) { 1462 free_host(ep->ex_defdir->dp_hosts); 1463 free((caddr_t)ep->ex_defdir); 1464 } 1465 if (ep->ex_fsdir) 1466 free(ep->ex_fsdir); 1467 free_dir(ep->ex_dirl); 1468 free((caddr_t)ep); 1469} 1470 1471/* 1472 * Free hosts. 1473 */ 1474void 1475free_host(hp) 1476 struct hostlist *hp; 1477{ 1478 struct hostlist *hp2; 1479 1480 while (hp) { 1481 hp2 = hp; 1482 hp = hp->ht_next; 1483 free((caddr_t)hp2); 1484 } 1485} 1486 1487struct hostlist * 1488get_ht() 1489{ 1490 struct hostlist *hp; 1491 1492 hp = (struct hostlist *)malloc(sizeof (struct hostlist)); 1493 if (hp == (struct hostlist *)NULL) 1494 out_of_mem(); 1495 hp->ht_next = (struct hostlist *)NULL; 1496 hp->ht_flag = 0; 1497 return (hp); 1498} 1499 1500#ifdef ISO 1501/* 1502 * Translate an iso address. 1503 */ 1504get_isoaddr(cp, grp) 1505 char *cp; 1506 struct grouplist *grp; 1507{ 1508 struct iso_addr *isop; 1509 struct sockaddr_iso *isoaddr; 1510 1511 if (grp->gr_type != GT_NULL) 1512 return (1); 1513 if ((isop = iso_addr(cp)) == NULL) { 1514 syslog(LOG_ERR, 1515 "iso_addr failed, ignored"); 1516 return (1); 1517 } 1518 isoaddr = (struct sockaddr_iso *) 1519 malloc(sizeof (struct sockaddr_iso)); 1520 if (isoaddr == (struct sockaddr_iso *)NULL) 1521 out_of_mem(); 1522 bzero((caddr_t)isoaddr, sizeof (struct sockaddr_iso)); 1523 bcopy((caddr_t)isop, (caddr_t)&isoaddr->siso_addr, 1524 sizeof (struct iso_addr)); 1525 isoaddr->siso_len = sizeof (struct sockaddr_iso); 1526 isoaddr->siso_family = AF_ISO; 1527 grp->gr_type = GT_ISO; 1528 grp->gr_ptr.gt_isoaddr = isoaddr; 1529 return (0); 1530} 1531#endif /* ISO */ 1532 1533/* 1534 * Out of memory, fatal 1535 */ 1536void 1537out_of_mem() 1538{ 1539 1540 syslog(LOG_ERR, "Out of memory"); 1541 exit(2); 1542} 1543 1544/* 1545 * Do the mount syscall with the update flag to push the export info into 1546 * the kernel. 1547 */ 1548int 1549do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb) 1550 struct exportlist *ep; 1551 struct grouplist *grp; 1552 int exflags; 1553 struct ucred *anoncrp; 1554 char *dirp; 1555 int dirplen; 1556 struct statfs *fsb; 1557{ 1558 char *cp = (char *)NULL; 1559 u_long **addrp; 1560 int done; 1561 char savedc = '\0'; 1562 struct sockaddr_in sin, imask; 1563 union { 1564 struct ufs_args ua; 1565 struct iso_args ia; 1566 struct mfs_args ma; 1567#ifdef __NetBSD__ 1568 struct msdosfs_args da; 1569#endif 1570 } args; 1571 u_long net; 1572 1573 args.ua.fspec = 0; 1574 args.ua.export.ex_flags = exflags; 1575 args.ua.export.ex_anon = *anoncrp; 1576 bzero((char *)&sin, sizeof(sin)); 1577 bzero((char *)&imask, sizeof(imask)); 1578 sin.sin_family = AF_INET; 1579 sin.sin_len = sizeof(sin); 1580 imask.sin_family = AF_INET; 1581 imask.sin_len = sizeof(sin); 1582 if (grp->gr_type == GT_HOST) 1583 addrp = (u_long **)grp->gr_ptr.gt_hostent->h_addr_list; 1584 else 1585 addrp = (u_long **)NULL; 1586 done = FALSE; 1587 while (!done) { 1588 switch (grp->gr_type) { 1589 case GT_HOST: 1590 if (addrp) { 1591 sin.sin_addr.s_addr = **addrp; 1592 args.ua.export.ex_addrlen = sizeof(sin); 1593 } else 1594 args.ua.export.ex_addrlen = 0; 1595 args.ua.export.ex_addr = (struct sockaddr *)&sin; 1596 args.ua.export.ex_masklen = 0; 1597 break; 1598 case GT_NET: 1599 if (grp->gr_ptr.gt_net.nt_mask) 1600 imask.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_mask; 1601 else { 1602 net = ntohl(grp->gr_ptr.gt_net.nt_net); 1603 if (IN_CLASSA(net)) 1604 imask.sin_addr.s_addr = inet_addr("255.0.0.0"); 1605 else if (IN_CLASSB(net)) 1606 imask.sin_addr.s_addr = 1607 inet_addr("255.255.0.0"); 1608 else 1609 imask.sin_addr.s_addr = 1610 inet_addr("255.255.255.0"); 1611 grp->gr_ptr.gt_net.nt_mask = imask.sin_addr.s_addr; 1612 } 1613 sin.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_net; 1614 args.ua.export.ex_addr = (struct sockaddr *)&sin; 1615 args.ua.export.ex_addrlen = sizeof (sin); 1616 args.ua.export.ex_mask = (struct sockaddr *)&imask; 1617 args.ua.export.ex_masklen = sizeof (imask); 1618 break; 1619#ifdef ISO 1620 case GT_ISO: 1621 args.ua.export.ex_addr = 1622 (struct sockaddr *)grp->gr_ptr.gt_isoaddr; 1623 args.ua.export.ex_addrlen = 1624 sizeof(struct sockaddr_iso); 1625 args.ua.export.ex_masklen = 0; 1626 break; 1627#endif /* ISO */ 1628 case GT_IGNORE: 1629 return(0); 1630 break; 1631 default: 1632 syslog(LOG_ERR, "Bad grouptype"); 1633 if (cp) 1634 *cp = savedc; 1635 return (1); 1636 }; 1637 1638 /* 1639 * XXX: 1640 * Maybe I should just use the fsb->f_mntonname path instead 1641 * of looping back up the dirp to the mount point?? 1642 * Also, needs to know how to export all types of local 1643 * exportable file systems and not just MOUNT_UFS. 1644 */ 1645#ifdef __NetBSD__ 1646 while (mount(fsb->f_fstypename, dirp, 1647#else 1648 while (mount(fsb->f_type, dirp, 1649#endif 1650 fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) { 1651 if (cp) 1652 *cp-- = savedc; 1653 else 1654 cp = dirp + dirplen - 1; 1655 if (errno == EPERM) { 1656 syslog(LOG_ERR, 1657 "Can't change attributes for %s.\n", dirp); 1658 return (1); 1659 } 1660 if (opt_flags & OP_ALLDIRS) { 1661 syslog(LOG_ERR, "Could not remount %s: %m", 1662 dirp); 1663 return (1); 1664 } 1665 /* back up over the last component */ 1666 while (*cp == '/' && cp > dirp) 1667 cp--; 1668 while (*(cp - 1) != '/' && cp > dirp) 1669 cp--; 1670 if (cp == dirp) { 1671 if (debug) 1672 fprintf(stderr,"mnt unsucc\n"); 1673 syslog(LOG_ERR, "Can't export %s", dirp); 1674 return (1); 1675 } 1676 savedc = *cp; 1677 *cp = '\0'; 1678 } 1679 if (addrp) { 1680 ++addrp; 1681 if (*addrp == (u_long *)NULL) 1682 done = TRUE; 1683 } else 1684 done = TRUE; 1685 } 1686 if (cp) 1687 *cp = savedc; 1688 return (0); 1689} 1690 1691/* 1692 * Translate a net address. 1693 */ 1694int 1695get_net(cp, net, maskflg) 1696 char *cp; 1697 struct netmsk *net; 1698 int maskflg; 1699{ 1700 struct netent *np; 1701 long netaddr; 1702 struct in_addr inetaddr, inetaddr2; 1703 char *name; 1704 1705 if (np = getnetbyname(cp)) 1706 inetaddr = inet_makeaddr(np->n_net, 0); 1707 else if (isdigit(*cp)) { 1708 if ((netaddr = inet_network(cp)) == -1) 1709 return (1); 1710 inetaddr = inet_makeaddr(netaddr, 0); 1711 /* 1712 * Due to arbritrary subnet masks, you don't know how many 1713 * bits to shift the address to make it into a network, 1714 * however you do know how to make a network address into 1715 * a host with host == 0 and then compare them. 1716 * (What a pest) 1717 */ 1718 if (!maskflg) { 1719 setnetent(0); 1720 while (np = getnetent()) { 1721 inetaddr2 = inet_makeaddr(np->n_net, 0); 1722 if (inetaddr2.s_addr == inetaddr.s_addr) 1723 break; 1724 } 1725 endnetent(); 1726 } 1727 } else 1728 return (1); 1729 if (maskflg) 1730 net->nt_mask = inetaddr.s_addr; 1731 else { 1732 if (np) 1733 name = np->n_name; 1734 else 1735 name = inet_ntoa(inetaddr); 1736 net->nt_name = (char *)malloc(strlen(name) + 1); 1737 if (net->nt_name == (char *)NULL) 1738 out_of_mem(); 1739 strcpy(net->nt_name, name); 1740 net->nt_net = inetaddr.s_addr; 1741 } 1742 return (0); 1743} 1744 1745/* 1746 * Parse out the next white space separated field 1747 */ 1748void 1749nextfield(cp, endcp) 1750 char **cp; 1751 char **endcp; 1752{ 1753 char *p; 1754 1755 p = *cp; 1756 while (*p == ' ' || *p == '\t') 1757 p++; 1758 if (*p == '\n' || *p == '\0') 1759 *cp = *endcp = p; 1760 else { 1761 *cp = p++; 1762 while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 1763 p++; 1764 *endcp = p; 1765 } 1766} 1767 1768/* 1769 * Get an exports file line. Skip over blank lines and handle line 1770 * continuations. 1771 */ 1772int 1773get_line() 1774{ 1775 char *p, *cp; 1776 int len; 1777 int totlen, cont_line; 1778 1779 /* 1780 * Loop around ignoring blank lines and getting all continuation lines. 1781 */ 1782 p = line; 1783 totlen = 0; 1784 do { 1785 if (fgets(p, LINESIZ - totlen, exp_file) == NULL) 1786 return (0); 1787 len = strlen(p); 1788 cp = p + len - 1; 1789 cont_line = 0; 1790 while (cp >= p && 1791 (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '\\')) { 1792 if (*cp == '\\') 1793 cont_line = 1; 1794 cp--; 1795 len--; 1796 } 1797 *++cp = '\0'; 1798 if (len > 0) { 1799 totlen += len; 1800 if (totlen >= LINESIZ) { 1801 syslog(LOG_ERR, "Exports line too long"); 1802 exit(2); 1803 } 1804 p = cp; 1805 } 1806 } while (totlen == 0 || cont_line); 1807 return (1); 1808} 1809 1810/* 1811 * Parse a description of a credential. 1812 */ 1813void 1814parsecred(namelist, cr) 1815 char *namelist; 1816 struct ucred *cr; 1817{ 1818 char *name; 1819 int cnt; 1820 char *names; 1821 struct passwd *pw; 1822 struct group *gr; 1823 int ngroups, groups[NGROUPS + 1]; 1824 1825 /* 1826 * Set up the unpriviledged user. 1827 */ 1828 cr->cr_ref = 1; 1829 cr->cr_uid = -2; 1830 cr->cr_groups[0] = -2; 1831 cr->cr_ngroups = 1; 1832 /* 1833 * Get the user's password table entry. 1834 */ 1835 names = strsep(&namelist, " \t\n"); 1836 name = strsep(&names, ":"); 1837 if (isdigit(*name) || *name == '-') 1838 pw = getpwuid(atoi(name)); 1839 else 1840 pw = getpwnam(name); 1841 /* 1842 * Credentials specified as those of a user. 1843 */ 1844 if (names == NULL) { 1845 if (pw == NULL) { 1846 syslog(LOG_ERR, "Unknown user: %s", name); 1847 return; 1848 } 1849 cr->cr_uid = pw->pw_uid; 1850 ngroups = NGROUPS + 1; 1851 if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) 1852 syslog(LOG_ERR, "Too many groups"); 1853 /* 1854 * Convert from int's to gid_t's and compress out duplicate 1855 */ 1856 cr->cr_ngroups = ngroups - 1; 1857 cr->cr_groups[0] = groups[0]; 1858 for (cnt = 2; cnt < ngroups; cnt++) 1859 cr->cr_groups[cnt - 1] = groups[cnt]; 1860 return; 1861 } 1862 /* 1863 * Explicit credential specified as a colon separated list: 1864 * uid:gid:gid:... 1865 */ 1866 if (pw != NULL) 1867 cr->cr_uid = pw->pw_uid; 1868 else if (isdigit(*name) || *name == '-') 1869 cr->cr_uid = atoi(name); 1870 else { 1871 syslog(LOG_ERR, "Unknown user: %s", name); 1872 return; 1873 } 1874 cr->cr_ngroups = 0; 1875 while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { 1876 name = strsep(&names, ":"); 1877 if (isdigit(*name) || *name == '-') { 1878 cr->cr_groups[cr->cr_ngroups++] = atoi(name); 1879 } else { 1880 if ((gr = getgrnam(name)) == NULL) { 1881 syslog(LOG_ERR, "Unknown group: %s", name); 1882 continue; 1883 } 1884 cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; 1885 } 1886 } 1887 if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) 1888 syslog(LOG_ERR, "Too many groups"); 1889} 1890 1891#define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 1892/* 1893 * Routines that maintain the remote mounttab 1894 */ 1895void 1896get_mountlist() 1897{ 1898 struct mountlist *mlp, **mlpp; 1899 char *eos, *dirp; 1900 int len; 1901 char str[STRSIZ]; 1902 FILE *mlfile; 1903 1904 if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) { 1905 syslog(LOG_ERR, "Can't open %s", _PATH_RMOUNTLIST); 1906 return; 1907 } 1908 mlpp = &mlhead; 1909 while (fgets(str, STRSIZ, mlfile) != NULL) { 1910 if ((dirp = index(str, '\t')) == NULL && 1911 (dirp = index(str, ' ')) == NULL) 1912 continue; 1913 mlp = (struct mountlist *)malloc(sizeof (*mlp)); 1914 len = dirp-str; 1915 if (len > RPCMNT_NAMELEN) 1916 len = RPCMNT_NAMELEN; 1917 bcopy(str, mlp->ml_host, len); 1918 mlp->ml_host[len] = '\0'; 1919 while (*dirp == '\t' || *dirp == ' ') 1920 dirp++; 1921 if ((eos = index(dirp, '\t')) == NULL && 1922 (eos = index(dirp, ' ')) == NULL && 1923 (eos = index(dirp, '\n')) == NULL) 1924 len = strlen(dirp); 1925 else 1926 len = eos-dirp; 1927 if (len > RPCMNT_PATHLEN) 1928 len = RPCMNT_PATHLEN; 1929 bcopy(dirp, mlp->ml_dirp, len); 1930 mlp->ml_dirp[len] = '\0'; 1931 mlp->ml_next = (struct mountlist *)NULL; 1932 *mlpp = mlp; 1933 mlpp = &mlp->ml_next; 1934 } 1935 fclose(mlfile); 1936} 1937 1938void 1939del_mlist(hostp, dirp) 1940 char *hostp, *dirp; 1941{ 1942 struct mountlist *mlp, **mlpp; 1943 struct mountlist *mlp2; 1944 FILE *mlfile; 1945 int fnd = 0; 1946 1947 mlpp = &mlhead; 1948 mlp = mlhead; 1949 while (mlp) { 1950 if (!strcmp(mlp->ml_host, hostp) && 1951 (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 1952 fnd = 1; 1953 mlp2 = mlp; 1954 *mlpp = mlp = mlp->ml_next; 1955 free((caddr_t)mlp2); 1956 } else { 1957 mlpp = &mlp->ml_next; 1958 mlp = mlp->ml_next; 1959 } 1960 } 1961 if (fnd) { 1962 if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 1963 syslog(LOG_ERR,"Can't update %s", _PATH_RMOUNTLIST); 1964 return; 1965 } 1966 mlp = mlhead; 1967 while (mlp) { 1968 fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 1969 mlp = mlp->ml_next; 1970 } 1971 fclose(mlfile); 1972 } 1973} 1974 1975void 1976add_mlist(hostp, dirp) 1977 char *hostp, *dirp; 1978{ 1979 struct mountlist *mlp, **mlpp; 1980 FILE *mlfile; 1981 1982 mlpp = &mlhead; 1983 mlp = mlhead; 1984 while (mlp) { 1985 if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 1986 return; 1987 mlpp = &mlp->ml_next; 1988 mlp = mlp->ml_next; 1989 } 1990 mlp = (struct mountlist *)malloc(sizeof (*mlp)); 1991 strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 1992 mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 1993 strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 1994 mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 1995 mlp->ml_next = (struct mountlist *)NULL; 1996 *mlpp = mlp; 1997 if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 1998 syslog(LOG_ERR, "Can't update %s", _PATH_RMOUNTLIST); 1999 return; 2000 } 2001 fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 2002 fclose(mlfile); 2003} 2004 2005/* 2006 * This function is called via. SIGTERM when the system is going down. 2007 * It sends a broadcast RPCMNT_UMNTALL. 2008 */ 2009void 2010send_umntall() 2011{ 2012 (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL, 2013 xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each); 2014 exit(0); 2015} 2016 2017int 2018umntall_each(resultsp, raddr) 2019 caddr_t resultsp; 2020 struct sockaddr_in *raddr; 2021{ 2022 return (1); 2023} 2024 2025/* 2026 * Free up a group list. 2027 */ 2028void 2029free_grp(grp) 2030 struct grouplist *grp; 2031{ 2032 char **addrp; 2033 2034 if (grp->gr_type == GT_HOST) { 2035 if (grp->gr_ptr.gt_hostent->h_name) { 2036 addrp = grp->gr_ptr.gt_hostent->h_addr_list; 2037 while (addrp && *addrp) 2038 free(*addrp++); 2039 free((caddr_t)grp->gr_ptr.gt_hostent->h_addr_list); 2040 free(grp->gr_ptr.gt_hostent->h_name); 2041 } 2042 free((caddr_t)grp->gr_ptr.gt_hostent); 2043 } else if (grp->gr_type == GT_NET) { 2044 if (grp->gr_ptr.gt_net.nt_name) 2045 free(grp->gr_ptr.gt_net.nt_name); 2046 } 2047#ifdef ISO 2048 else if (grp->gr_type == GT_ISO) 2049 free((caddr_t)grp->gr_ptr.gt_isoaddr); 2050#endif 2051 free((caddr_t)grp); 2052} 2053 2054#ifdef DEBUG 2055void 2056SYSLOG(int pri, const char *fmt, ...) 2057{ 2058 va_list ap; 2059 2060 va_start(ap, fmt); 2061 vfprintf(stderr, fmt, ap); 2062 va_end(ap); 2063} 2064#endif /* DEBUG */ 2065 2066/* 2067 * Check options for consistency. 2068 */ 2069int 2070check_options(dp) 2071 struct dirlist *dp; 2072{ 2073 2074 if (dp == (struct dirlist *)NULL) 2075 return (1); 2076 if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL) || 2077 (opt_flags & (OP_MAPROOT | OP_KERB)) == (OP_MAPROOT | OP_KERB) || 2078 (opt_flags & (OP_MAPALL | OP_KERB)) == (OP_MAPALL | OP_KERB)) { 2079 syslog(LOG_ERR, "-mapall, -maproot and -kerb mutually exclusive"); 2080 return (1); 2081 } 2082 if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { 2083 syslog(LOG_ERR, "-mask requires -net"); 2084 return (1); 2085 } 2086 if ((opt_flags & (OP_NET | OP_ISO)) == (OP_NET | OP_ISO)) { 2087 syslog(LOG_ERR, "-net and -iso mutually exclusive"); 2088 return (1); 2089 } 2090 if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { 2091 syslog(LOG_ERR, "-alldir has multiple directories"); 2092 return (1); 2093 } 2094 return (0); 2095} 2096 2097/* 2098 * Check an absolute directory path for any symbolic links. Return true 2099 * if no symbolic links are found. 2100 */ 2101int 2102check_dirpath(dirp) 2103 char *dirp; 2104{ 2105 char *cp; 2106 int ret = 1; 2107 struct stat sb; 2108 2109 cp = dirp + 1; 2110 while (*cp && ret) { 2111 if (*cp == '/') { 2112 *cp = '\0'; 2113 if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 2114 ret = 0; 2115 *cp = '/'; 2116 } 2117 cp++; 2118 } 2119 if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 2120 ret = 0; 2121 return (ret); 2122} 2123 2124/* 2125 * Just translate an ascii string to an integer. 2126 */ 2127int 2128get_num(cp) 2129 register char *cp; 2130{ 2131 register int res = 0; 2132 2133 while (*cp) { 2134 if (*cp < '0' || *cp > '9') 2135 return (-1); 2136 res = res * 10 + (*cp++ - '0'); 2137 } 2138 return (res); 2139} 2140