18fae3551SRodney W. Grimes /* 28fae3551SRodney W. Grimes * Copyright (c) 1989, 1993 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * 58fae3551SRodney W. Grimes * This code is derived from software contributed to Berkeley by 68fae3551SRodney W. Grimes * Herb Hasler and Rick Macklem at The University of Guelph. 78fae3551SRodney W. Grimes * 88fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 98fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 108fae3551SRodney W. Grimes * are met: 118fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 128fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 138fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 148fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 158fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 168fae3551SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 178fae3551SRodney W. Grimes * must display the following acknowledgement: 188fae3551SRodney W. Grimes * This product includes software developed by the University of 198fae3551SRodney W. Grimes * California, Berkeley and its contributors. 208fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 218fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 228fae3551SRodney W. Grimes * without specific prior written permission. 238fae3551SRodney W. Grimes * 248fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 258fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 268fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 278fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 288fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 298fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 308fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 318fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 328fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 338fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 348fae3551SRodney W. Grimes * SUCH DAMAGE. 358fae3551SRodney W. Grimes */ 368fae3551SRodney W. Grimes 378fae3551SRodney W. Grimes #ifndef lint 3874853402SPhilippe Charnier static const char copyright[] = 398fae3551SRodney W. Grimes "@(#) Copyright (c) 1989, 1993\n\ 408fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 41d599144dSGarrett Wollman #endif /*not lint*/ 428fae3551SRodney W. Grimes 438fae3551SRodney W. Grimes #ifndef lint 4474853402SPhilippe Charnier #if 0 4574853402SPhilippe Charnier static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; 4674853402SPhilippe Charnier #endif 47d599144dSGarrett Wollman static const char rcsid[] = 487f3dea24SPeter Wemm "$FreeBSD$"; 49d599144dSGarrett Wollman #endif /*not lint*/ 508fae3551SRodney W. Grimes 518fae3551SRodney W. Grimes #include <sys/param.h> 528fae3551SRodney W. Grimes #include <sys/mount.h> 538360efbdSAlfred Perlstein #include <sys/fcntl.h> 548fae3551SRodney W. Grimes #include <sys/stat.h> 558fae3551SRodney W. Grimes #include <sys/syslog.h> 56394da4c1SGuido van Rooij #include <sys/sysctl.h> 5791ca1a91SIan Dowse #include <sys/linker.h> 5891ca1a91SIan Dowse #include <sys/module.h> 598fae3551SRodney W. Grimes 608fae3551SRodney W. Grimes #include <rpc/rpc.h> 618fae3551SRodney W. Grimes #include <rpc/pmap_clnt.h> 628360efbdSAlfred Perlstein #include <rpc/pmap_prot.h> 638360efbdSAlfred Perlstein #include <rpcsvc/mount.h> 648fae3551SRodney W. Grimes #include <nfs/rpcv2.h> 65a62dc406SDoug Rabson #include <nfs/nfsproto.h> 6691196234SPeter Wemm #include <nfsserver/nfs.h> 6787564113SPeter Wemm #include <ufs/ufs/ufsmount.h> 681166fb51SRuslan Ermilov #include <fs/msdosfs/msdosfsmount.h> 698a8402d3SRuslan Ermilov #include <fs/ntfs/ntfsmount.h> 7087564113SPeter Wemm #include <isofs/cd9660/cd9660_mount.h> /* XXX need isofs in include */ 718fae3551SRodney W. Grimes 728fae3551SRodney W. Grimes #include <arpa/inet.h> 738fae3551SRodney W. Grimes 748fae3551SRodney W. Grimes #include <ctype.h> 7574853402SPhilippe Charnier #include <err.h> 768fae3551SRodney W. Grimes #include <errno.h> 778fae3551SRodney W. Grimes #include <grp.h> 788fae3551SRodney W. Grimes #include <netdb.h> 798fae3551SRodney W. Grimes #include <pwd.h> 808fae3551SRodney W. Grimes #include <signal.h> 818fae3551SRodney W. Grimes #include <stdio.h> 828fae3551SRodney W. Grimes #include <stdlib.h> 838fae3551SRodney W. Grimes #include <string.h> 848fae3551SRodney W. Grimes #include <unistd.h> 858fae3551SRodney W. Grimes #include "pathnames.h" 868fae3551SRodney W. Grimes 878fae3551SRodney W. Grimes #ifdef DEBUG 888fae3551SRodney W. Grimes #include <stdarg.h> 898fae3551SRodney W. Grimes #endif 908fae3551SRodney W. Grimes 918360efbdSAlfred Perlstein #ifndef MOUNTDLOCK 928360efbdSAlfred Perlstein #define MOUNTDLOCK "/var/run/mountd.lock" 938360efbdSAlfred Perlstein #endif 948360efbdSAlfred Perlstein 958fae3551SRodney W. Grimes /* 968fae3551SRodney W. Grimes * Structures for keeping the mount list and export list 978fae3551SRodney W. Grimes */ 988fae3551SRodney W. Grimes struct mountlist { 998fae3551SRodney W. Grimes struct mountlist *ml_next; 1008fae3551SRodney W. Grimes char ml_host[RPCMNT_NAMELEN+1]; 1018fae3551SRodney W. Grimes char ml_dirp[RPCMNT_PATHLEN+1]; 1028fae3551SRodney W. Grimes }; 1038fae3551SRodney W. Grimes 1048fae3551SRodney W. Grimes struct dirlist { 1058fae3551SRodney W. Grimes struct dirlist *dp_left; 1068fae3551SRodney W. Grimes struct dirlist *dp_right; 1078fae3551SRodney W. Grimes int dp_flag; 1088fae3551SRodney W. Grimes struct hostlist *dp_hosts; /* List of hosts this dir exported to */ 1098fae3551SRodney W. Grimes char dp_dirp[1]; /* Actually malloc'd to size of dir */ 1108fae3551SRodney W. Grimes }; 1118fae3551SRodney W. Grimes /* dp_flag bits */ 1128fae3551SRodney W. Grimes #define DP_DEFSET 0x1 113a62dc406SDoug Rabson #define DP_HOSTSET 0x2 1148fae3551SRodney W. Grimes 1158fae3551SRodney W. Grimes struct exportlist { 1168fae3551SRodney W. Grimes struct exportlist *ex_next; 1178fae3551SRodney W. Grimes struct dirlist *ex_dirl; 1188fae3551SRodney W. Grimes struct dirlist *ex_defdir; 1198fae3551SRodney W. Grimes int ex_flag; 1208fae3551SRodney W. Grimes fsid_t ex_fs; 1218fae3551SRodney W. Grimes char *ex_fsdir; 122cb3923e0SDoug Rabson char *ex_indexfile; 1238fae3551SRodney W. Grimes }; 1248fae3551SRodney W. Grimes /* ex_flag bits */ 1258fae3551SRodney W. Grimes #define EX_LINKED 0x1 1268fae3551SRodney W. Grimes 1278fae3551SRodney W. Grimes struct netmsk { 1288360efbdSAlfred Perlstein struct sockaddr_storage nt_net; 12960caaee2SIan Dowse struct sockaddr_storage nt_mask; 1308fae3551SRodney W. Grimes char *nt_name; 1318fae3551SRodney W. Grimes }; 1328fae3551SRodney W. Grimes 1338fae3551SRodney W. Grimes union grouptypes { 1348360efbdSAlfred Perlstein struct addrinfo *gt_addrinfo; 1358fae3551SRodney W. Grimes struct netmsk gt_net; 1368fae3551SRodney W. Grimes }; 1378fae3551SRodney W. Grimes 1388fae3551SRodney W. Grimes struct grouplist { 1398fae3551SRodney W. Grimes int gr_type; 1408fae3551SRodney W. Grimes union grouptypes gr_ptr; 1418fae3551SRodney W. Grimes struct grouplist *gr_next; 1428fae3551SRodney W. Grimes }; 1438fae3551SRodney W. Grimes /* Group types */ 1448fae3551SRodney W. Grimes #define GT_NULL 0x0 1458fae3551SRodney W. Grimes #define GT_HOST 0x1 1468fae3551SRodney W. Grimes #define GT_NET 0x2 1476d359f31SIan Dowse #define GT_DEFAULT 0x3 1488b5a6d67SBill Paul #define GT_IGNORE 0x5 1498fae3551SRodney W. Grimes 1508fae3551SRodney W. Grimes struct hostlist { 151a62dc406SDoug Rabson int ht_flag; /* Uses DP_xx bits */ 1528fae3551SRodney W. Grimes struct grouplist *ht_grp; 1538fae3551SRodney W. Grimes struct hostlist *ht_next; 1548fae3551SRodney W. Grimes }; 1558fae3551SRodney W. Grimes 156a62dc406SDoug Rabson struct fhreturn { 157a62dc406SDoug Rabson int fhr_flag; 158a62dc406SDoug Rabson int fhr_vers; 159a62dc406SDoug Rabson nfsfh_t fhr_fh; 160a62dc406SDoug Rabson }; 161a62dc406SDoug Rabson 1628fae3551SRodney W. Grimes /* Global defs */ 16385429990SWarner Losh char *add_expdir(struct dirlist **, char *, int); 16485429990SWarner Losh void add_dlist(struct dirlist **, struct dirlist *, 16585429990SWarner Losh struct grouplist *, int); 16685429990SWarner Losh void add_mlist(char *, char *); 16785429990SWarner Losh int check_dirpath(char *); 16885429990SWarner Losh int check_options(struct dirlist *); 16960caaee2SIan Dowse int checkmask(struct sockaddr *sa); 17085429990SWarner Losh int chk_host(struct dirlist *, struct sockaddr *, int *, int *); 17101709abfSIan Dowse void del_mlist(char *hostp, char *dirp); 17285429990SWarner Losh struct dirlist *dirp_search(struct dirlist *, char *); 17385429990SWarner Losh int do_mount(struct exportlist *, struct grouplist *, int, 17485429990SWarner Losh struct xucred *, char *, int, struct statfs *); 17585429990SWarner Losh int do_opt(char **, char **, struct exportlist *, struct grouplist *, 17685429990SWarner Losh int *, int *, struct xucred *); 17785429990SWarner Losh struct exportlist *ex_search(fsid_t *); 17885429990SWarner Losh struct exportlist *get_exp(void); 17985429990SWarner Losh void free_dir(struct dirlist *); 18085429990SWarner Losh void free_exp(struct exportlist *); 18185429990SWarner Losh void free_grp(struct grouplist *); 18285429990SWarner Losh void free_host(struct hostlist *); 18385429990SWarner Losh void get_exportlist(void); 18485429990SWarner Losh int get_host(char *, struct grouplist *, struct grouplist *); 18585429990SWarner Losh struct hostlist *get_ht(void); 18685429990SWarner Losh int get_line(void); 18785429990SWarner Losh void get_mountlist(void); 18885429990SWarner Losh int get_net(char *, struct netmsk *, int); 18985429990SWarner Losh void getexp_err(struct exportlist *, struct grouplist *); 19085429990SWarner Losh struct grouplist *get_grp(void); 19185429990SWarner Losh void hang_dirp(struct dirlist *, struct grouplist *, 19285429990SWarner Losh struct exportlist *, int); 19369d65572SIan Dowse void huphandler(int sig); 19460caaee2SIan Dowse int makemask(struct sockaddr_storage *ssp, int bitlen); 19585429990SWarner Losh void mntsrv(struct svc_req *, SVCXPRT *); 19685429990SWarner Losh void nextfield(char **, char **); 19785429990SWarner Losh void out_of_mem(void); 19885429990SWarner Losh void parsecred(char *, struct xucred *); 19991acb349SAlfred Perlstein int put_exlist(struct dirlist *, XDR *, struct dirlist *, int *, int); 20060caaee2SIan Dowse void *sa_rawaddr(struct sockaddr *sa, int *nbytes); 20160caaee2SIan Dowse int sacmp(struct sockaddr *sa1, struct sockaddr *sa2, 20260caaee2SIan Dowse struct sockaddr *samask); 20385429990SWarner Losh int scan_tree(struct dirlist *, struct sockaddr *); 20485429990SWarner Losh static void usage(void); 20585429990SWarner Losh int xdr_dir(XDR *, char *); 20685429990SWarner Losh int xdr_explist(XDR *, caddr_t); 20791acb349SAlfred Perlstein int xdr_explist_brief(XDR *, caddr_t); 20885429990SWarner Losh int xdr_fhs(XDR *, caddr_t); 20985429990SWarner Losh int xdr_mlist(XDR *, caddr_t); 21085429990SWarner Losh void terminate(int); 2118fae3551SRodney W. Grimes 2128fae3551SRodney W. Grimes struct exportlist *exphead; 2138fae3551SRodney W. Grimes struct mountlist *mlhead; 2148fae3551SRodney W. Grimes struct grouplist *grphead; 2158fae3551SRodney W. Grimes char exname[MAXPATHLEN]; 216c0511d3bSBrian Feldman struct xucred def_anon = { 21776183f34SDima Dorfman XUCRED_VERSION, 2188fae3551SRodney W. Grimes (uid_t)-2, 2198fae3551SRodney W. Grimes 1, 220c0511d3bSBrian Feldman { (gid_t)-2 }, 221c0511d3bSBrian Feldman NULL 2228fae3551SRodney W. Grimes }; 2232a66cfc5SDoug Rabson int force_v2 = 0; 224a62dc406SDoug Rabson int resvport_only = 1; 225a62dc406SDoug Rabson int dir_only = 1; 226f2c90b95SGuido van Rooij int log = 0; 22769d65572SIan Dowse int got_sighup = 0; 2288360efbdSAlfred Perlstein 2298fae3551SRodney W. Grimes int opt_flags; 2308360efbdSAlfred Perlstein static int have_v6 = 1; 2318360efbdSAlfred Perlstein #ifdef NI_WITHSCOPEID 2328360efbdSAlfred Perlstein static const int ninumeric = NI_NUMERICHOST | NI_WITHSCOPEID; 2338360efbdSAlfred Perlstein #else 2348360efbdSAlfred Perlstein static const int ninumeric = NI_NUMERICHOST; 2358360efbdSAlfred Perlstein #endif 2368360efbdSAlfred Perlstein 2378360efbdSAlfred Perlstein int mountdlockfd; 23860caaee2SIan Dowse /* Bits for opt_flags above */ 2398fae3551SRodney W. Grimes #define OP_MAPROOT 0x01 2408fae3551SRodney W. Grimes #define OP_MAPALL 0x02 24191196234SPeter Wemm /* 0x4 free */ 2428fae3551SRodney W. Grimes #define OP_MASK 0x08 2438fae3551SRodney W. Grimes #define OP_NET 0x10 2448fae3551SRodney W. Grimes #define OP_ALLDIRS 0x40 24560caaee2SIan Dowse #define OP_HAVEMASK 0x80 /* A mask was specified or inferred. */ 246288fa14aSJoerg Wunsch #define OP_QUIET 0x100 2478360efbdSAlfred Perlstein #define OP_MASKLEN 0x200 2488fae3551SRodney W. Grimes 2498fae3551SRodney W. Grimes #ifdef DEBUG 2508fae3551SRodney W. Grimes int debug = 1; 25185429990SWarner Losh void SYSLOG(int, const char *, ...) __printflike(2, 3); 2528fae3551SRodney W. Grimes #define syslog SYSLOG 2538fae3551SRodney W. Grimes #else 2548fae3551SRodney W. Grimes int debug = 0; 2558fae3551SRodney W. Grimes #endif 2568fae3551SRodney W. Grimes 2578fae3551SRodney W. Grimes /* 2588fae3551SRodney W. Grimes * Mountd server for NFS mount protocol as described in: 2598fae3551SRodney W. Grimes * NFS: Network File System Protocol Specification, RFC1094, Appendix A 2608fae3551SRodney W. Grimes * The optional arguments are the exports file name 2618fae3551SRodney W. Grimes * default: _PATH_EXPORTS 2628fae3551SRodney W. Grimes * and "-n" to allow nonroot mount. 2638fae3551SRodney W. Grimes */ 2648fae3551SRodney W. Grimes int 2658fae3551SRodney W. Grimes main(argc, argv) 2668fae3551SRodney W. Grimes int argc; 2678fae3551SRodney W. Grimes char **argv; 2688fae3551SRodney W. Grimes { 26969d65572SIan Dowse fd_set readfds; 2708360efbdSAlfred Perlstein SVCXPRT *udptransp, *tcptransp, *udp6transp, *tcp6transp; 2718360efbdSAlfred Perlstein struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf; 2728360efbdSAlfred Perlstein int udpsock, tcpsock, udp6sock, tcp6sock; 2738360efbdSAlfred Perlstein int xcreated = 0, s; 2748360efbdSAlfred Perlstein int one = 1; 27591ca1a91SIan Dowse int c; 276d599144dSGarrett Wollman 27701709abfSIan Dowse udp6conf = tcp6conf = NULL; 27801709abfSIan Dowse udp6sock = tcp6sock = NULL; 2798360efbdSAlfred Perlstein 28001709abfSIan Dowse /* Check that another mountd isn't already running. */ 2818360efbdSAlfred Perlstein if ((mountdlockfd = (open(MOUNTDLOCK, O_RDONLY|O_CREAT, 0444))) == -1) 2828360efbdSAlfred Perlstein err(1, "%s", MOUNTDLOCK); 2838360efbdSAlfred Perlstein 2848360efbdSAlfred Perlstein if(flock(mountdlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) 2858360efbdSAlfred Perlstein errx(1, "another rpc.mountd is already running. Aborting"); 2868360efbdSAlfred Perlstein s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 2878360efbdSAlfred Perlstein if (s < 0) 2888360efbdSAlfred Perlstein have_v6 = 0; 2898360efbdSAlfred Perlstein else 2908360efbdSAlfred Perlstein close(s); 2914a0785aaSPeter Wemm if (modfind("nfsserver") < 0) { 2924a0785aaSPeter Wemm /* Not present in kernel, try loading it */ 2934a0785aaSPeter Wemm if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0) 2944a0785aaSPeter Wemm errx(1, "NFS server is not available or loadable"); 295d599144dSGarrett Wollman } 2968fae3551SRodney W. Grimes 297690c488dSGuido van Rooij while ((c = getopt(argc, argv, "2dlnr")) != -1) 2988fae3551SRodney W. Grimes switch (c) { 2992a66cfc5SDoug Rabson case '2': 3002a66cfc5SDoug Rabson force_v2 = 1; 3012a66cfc5SDoug Rabson break; 302a62dc406SDoug Rabson case 'n': 303a62dc406SDoug Rabson resvport_only = 0; 304a62dc406SDoug Rabson break; 305a62dc406SDoug Rabson case 'r': 306a62dc406SDoug Rabson dir_only = 0; 307a62dc406SDoug Rabson break; 3086444ef3bSPoul-Henning Kamp case 'd': 3096444ef3bSPoul-Henning Kamp debug = debug ? 0 : 1; 3106444ef3bSPoul-Henning Kamp break; 311f51631d7SGuido van Rooij case 'l': 312f51631d7SGuido van Rooij log = 1; 313f51631d7SGuido van Rooij break; 3148fae3551SRodney W. Grimes default: 31574853402SPhilippe Charnier usage(); 3168fae3551SRodney W. Grimes }; 3178fae3551SRodney W. Grimes argc -= optind; 3188fae3551SRodney W. Grimes argv += optind; 3198fae3551SRodney W. Grimes grphead = (struct grouplist *)NULL; 3208fae3551SRodney W. Grimes exphead = (struct exportlist *)NULL; 3218fae3551SRodney W. Grimes mlhead = (struct mountlist *)NULL; 3228fae3551SRodney W. Grimes if (argc == 1) { 3238fae3551SRodney W. Grimes strncpy(exname, *argv, MAXPATHLEN-1); 3248fae3551SRodney W. Grimes exname[MAXPATHLEN-1] = '\0'; 3258fae3551SRodney W. Grimes } else 3268fae3551SRodney W. Grimes strcpy(exname, _PATH_EXPORTS); 3278fae3551SRodney W. Grimes openlog("mountd", LOG_PID, LOG_DAEMON); 3288fae3551SRodney W. Grimes if (debug) 32974853402SPhilippe Charnier warnx("getting export list"); 3308fae3551SRodney W. Grimes get_exportlist(); 3318fae3551SRodney W. Grimes if (debug) 33274853402SPhilippe Charnier warnx("getting mount list"); 3338fae3551SRodney W. Grimes get_mountlist(); 3348fae3551SRodney W. Grimes if (debug) 33574853402SPhilippe Charnier warnx("here we go"); 3368fae3551SRodney W. Grimes if (debug == 0) { 3378fae3551SRodney W. Grimes daemon(0, 0); 3388fae3551SRodney W. Grimes signal(SIGINT, SIG_IGN); 3398fae3551SRodney W. Grimes signal(SIGQUIT, SIG_IGN); 3408fae3551SRodney W. Grimes } 34169d65572SIan Dowse signal(SIGHUP, huphandler); 3428360efbdSAlfred Perlstein signal(SIGTERM, terminate); 3438fae3551SRodney W. Grimes { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); 3448fae3551SRodney W. Grimes if (pidfile != NULL) { 3458fae3551SRodney W. Grimes fprintf(pidfile, "%d\n", getpid()); 3468fae3551SRodney W. Grimes fclose(pidfile); 3478fae3551SRodney W. Grimes } 3488fae3551SRodney W. Grimes } 3498360efbdSAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); 3508360efbdSAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); 3518360efbdSAlfred Perlstein udpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 3528360efbdSAlfred Perlstein tcpsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 35395b99739SAlfred Perlstein udpconf = getnetconfigent("udp"); 35495b99739SAlfred Perlstein tcpconf = getnetconfigent("tcp"); 35595b99739SAlfred Perlstein if (!have_v6) 35695b99739SAlfred Perlstein goto skip_v6; 3578360efbdSAlfred Perlstein udp6sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 3588360efbdSAlfred Perlstein tcp6sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); 3598360efbdSAlfred Perlstein /* 3608360efbdSAlfred Perlstein * We're doing host-based access checks here, so don't allow 3618360efbdSAlfred Perlstein * v4-in-v6 to confuse things. The kernel will disable it 3628360efbdSAlfred Perlstein * by default on NFS sockets too. 3638360efbdSAlfred Perlstein */ 3648360efbdSAlfred Perlstein if (udp6sock != -1 && setsockopt(udp6sock, IPPROTO_IPV6, 3658360efbdSAlfred Perlstein IPV6_BINDV6ONLY, &one, sizeof one) < 0){ 3668360efbdSAlfred Perlstein syslog(LOG_ERR, "can't disable v4-in-v6 on UDP socket"); 3678360efbdSAlfred Perlstein exit(1); 3688360efbdSAlfred Perlstein } 3698360efbdSAlfred Perlstein if (tcp6sock != -1 && setsockopt(tcp6sock, IPPROTO_IPV6, 3708360efbdSAlfred Perlstein IPV6_BINDV6ONLY, &one, sizeof one) < 0){ 3718360efbdSAlfred Perlstein syslog(LOG_ERR, "can't disable v4-in-v6 on UDP socket"); 3728360efbdSAlfred Perlstein exit(1); 3738360efbdSAlfred Perlstein } 3748360efbdSAlfred Perlstein udp6conf = getnetconfigent("udp6"); 3758360efbdSAlfred Perlstein tcp6conf = getnetconfigent("tcp6"); 37695b99739SAlfred Perlstein 37795b99739SAlfred Perlstein skip_v6: 378c6e5e158SGuido van Rooij if (!resvport_only) { 3794a0785aaSPeter Wemm if (sysctlbyname("vfs.nfsrv.nfs_privport", NULL, NULL, 3804a0785aaSPeter Wemm &resvport_only, sizeof(resvport_only)) != 0 && 3814a0785aaSPeter Wemm errno != ENOENT) { 382394da4c1SGuido van Rooij syslog(LOG_ERR, "sysctl: %m"); 383394da4c1SGuido van Rooij exit(1); 384394da4c1SGuido van Rooij } 385c6e5e158SGuido van Rooij } 3868360efbdSAlfred Perlstein if (udpsock != -1 && udpconf != NULL) { 3878360efbdSAlfred Perlstein bindresvport(udpsock, NULL); 3888360efbdSAlfred Perlstein udptransp = svc_dg_create(udpsock, 0, 0); 3898360efbdSAlfred Perlstein if (udptransp != NULL) { 3908360efbdSAlfred Perlstein if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER1, 3918360efbdSAlfred Perlstein mntsrv, udpconf)) 3928360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP RPCMNT_VER1 service"); 3938360efbdSAlfred Perlstein else 3948360efbdSAlfred Perlstein xcreated++; 3958360efbdSAlfred Perlstein if (!force_v2) { 3968360efbdSAlfred Perlstein if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER3, 3978360efbdSAlfred Perlstein mntsrv, udpconf)) 3988360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP RPCMNT_VER3 service"); 3998360efbdSAlfred Perlstein else 4008360efbdSAlfred Perlstein xcreated++; 4018fae3551SRodney W. Grimes } 4028360efbdSAlfred Perlstein } else 4038360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create UDP services"); 4048360efbdSAlfred Perlstein 4058360efbdSAlfred Perlstein } 4068360efbdSAlfred Perlstein if (tcpsock != -1 && tcpconf != NULL) { 4078360efbdSAlfred Perlstein bindresvport(tcpsock, NULL); 4088360efbdSAlfred Perlstein listen(tcpsock, SOMAXCONN); 4098360efbdSAlfred Perlstein tcptransp = svc_vc_create(tcpsock, 0, 0); 4108360efbdSAlfred Perlstein if (tcptransp != NULL) { 4118360efbdSAlfred Perlstein if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER1, 4128360efbdSAlfred Perlstein mntsrv, tcpconf)) 4138360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP RPCMNT_VER1 service"); 4148360efbdSAlfred Perlstein else 4158360efbdSAlfred Perlstein xcreated++; 4168360efbdSAlfred Perlstein if (!force_v2) { 4178360efbdSAlfred Perlstein if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER3, 4188360efbdSAlfred Perlstein mntsrv, tcpconf)) 4198360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP RPCMNT_VER3 service"); 4208360efbdSAlfred Perlstein else 4218360efbdSAlfred Perlstein xcreated++; 4228360efbdSAlfred Perlstein } 4238360efbdSAlfred Perlstein } else 4248360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create TCP service"); 4258360efbdSAlfred Perlstein 4268360efbdSAlfred Perlstein } 42795b99739SAlfred Perlstein if (have_v6 && udp6sock != -1 && udp6conf != NULL) { 4288360efbdSAlfred Perlstein bindresvport(udp6sock, NULL); 4298360efbdSAlfred Perlstein udp6transp = svc_dg_create(udp6sock, 0, 0); 4308360efbdSAlfred Perlstein if (udp6transp != NULL) { 4318360efbdSAlfred Perlstein if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER1, 4328360efbdSAlfred Perlstein mntsrv, udp6conf)) 4338360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER1 service"); 4348360efbdSAlfred Perlstein else 4358360efbdSAlfred Perlstein xcreated++; 4368360efbdSAlfred Perlstein if (!force_v2) { 4378360efbdSAlfred Perlstein if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER3, 4388360efbdSAlfred Perlstein mntsrv, udp6conf)) 4398360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER3 service"); 4408360efbdSAlfred Perlstein else 4418360efbdSAlfred Perlstein xcreated++; 4428360efbdSAlfred Perlstein } 4438360efbdSAlfred Perlstein } else 4448360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create UDP6 service"); 4458360efbdSAlfred Perlstein 4468360efbdSAlfred Perlstein } 44795b99739SAlfred Perlstein if (have_v6 && tcp6sock != -1 && tcp6conf != NULL) { 4488360efbdSAlfred Perlstein bindresvport(tcp6sock, NULL); 4498360efbdSAlfred Perlstein listen(tcp6sock, SOMAXCONN); 4508360efbdSAlfred Perlstein tcp6transp = svc_vc_create(tcp6sock, 0, 0); 4518360efbdSAlfred Perlstein if (tcp6transp != NULL) { 4528360efbdSAlfred Perlstein if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER1, 4538360efbdSAlfred Perlstein mntsrv, tcp6conf)) 4548360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER1 service"); 4558360efbdSAlfred Perlstein else 4568360efbdSAlfred Perlstein xcreated++; 4578360efbdSAlfred Perlstein if (!force_v2) { 4588360efbdSAlfred Perlstein if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER3, 4598360efbdSAlfred Perlstein mntsrv, tcp6conf)) 4608360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER3 service"); 4618360efbdSAlfred Perlstein else 4628360efbdSAlfred Perlstein xcreated++; 4638360efbdSAlfred Perlstein } 4648360efbdSAlfred Perlstein } else 4658360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create TCP6 service"); 4668360efbdSAlfred Perlstein 4678360efbdSAlfred Perlstein } 4688360efbdSAlfred Perlstein if (xcreated == 0) { 4698360efbdSAlfred Perlstein syslog(LOG_ERR, "could not create any services"); 4702a66cfc5SDoug Rabson exit(1); 4712a66cfc5SDoug Rabson } 47269d65572SIan Dowse 47369d65572SIan Dowse /* Expand svc_run() here so that we can call get_exportlist(). */ 47469d65572SIan Dowse for (;;) { 47569d65572SIan Dowse if (got_sighup) { 47669d65572SIan Dowse get_exportlist(); 47769d65572SIan Dowse got_sighup = 0; 47869d65572SIan Dowse } 47969d65572SIan Dowse readfds = svc_fdset; 48069d65572SIan Dowse switch (select(svc_maxfd + 1, &readfds, NULL, NULL, NULL)) { 48169d65572SIan Dowse case -1: 48269d65572SIan Dowse if (errno == EINTR) 48369d65572SIan Dowse continue; 48469d65572SIan Dowse syslog(LOG_ERR, "mountd died: select: %m"); 48574853402SPhilippe Charnier exit(1); 48669d65572SIan Dowse case 0: 48769d65572SIan Dowse continue; 48869d65572SIan Dowse default: 48969d65572SIan Dowse svc_getreqset(&readfds); 49069d65572SIan Dowse } 49169d65572SIan Dowse } 49274853402SPhilippe Charnier } 49374853402SPhilippe Charnier 49474853402SPhilippe Charnier static void 49574853402SPhilippe Charnier usage() 49674853402SPhilippe Charnier { 49774853402SPhilippe Charnier fprintf(stderr, 49874853402SPhilippe Charnier "usage: mountd [-2] [-d] [-l] [-n] [-r] [export_file]\n"); 4998fae3551SRodney W. Grimes exit(1); 5008fae3551SRodney W. Grimes } 5018fae3551SRodney W. Grimes 5028fae3551SRodney W. Grimes /* 5038fae3551SRodney W. Grimes * The mount rpc service 5048fae3551SRodney W. Grimes */ 5058fae3551SRodney W. Grimes void 5068fae3551SRodney W. Grimes mntsrv(rqstp, transp) 5078fae3551SRodney W. Grimes struct svc_req *rqstp; 5088fae3551SRodney W. Grimes SVCXPRT *transp; 5098fae3551SRodney W. Grimes { 5108fae3551SRodney W. Grimes struct exportlist *ep; 5118fae3551SRodney W. Grimes struct dirlist *dp; 512a62dc406SDoug Rabson struct fhreturn fhr; 5138fae3551SRodney W. Grimes struct stat stb; 5148fae3551SRodney W. Grimes struct statfs fsb; 5158360efbdSAlfred Perlstein struct addrinfo *ai; 5168360efbdSAlfred Perlstein char host[NI_MAXHOST], numerichost[NI_MAXHOST]; 5178360efbdSAlfred Perlstein int lookup_failed = 1; 5188360efbdSAlfred Perlstein struct sockaddr *saddr; 519a62dc406SDoug Rabson u_short sport; 5208fae3551SRodney W. Grimes char rpcpath[RPCMNT_PATHLEN + 1], dirpath[MAXPATHLEN]; 521e90cdb54SGuido van Rooij int bad = 0, defset, hostset; 522a62dc406SDoug Rabson sigset_t sighup_mask; 5238fae3551SRodney W. Grimes 524a62dc406SDoug Rabson sigemptyset(&sighup_mask); 525a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 5268360efbdSAlfred Perlstein saddr = svc_getrpccaller(transp)->buf; 5278360efbdSAlfred Perlstein switch (saddr->sa_family) { 5288360efbdSAlfred Perlstein case AF_INET6: 52901709abfSIan Dowse sport = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port); 5308360efbdSAlfred Perlstein break; 5318360efbdSAlfred Perlstein case AF_INET: 53201709abfSIan Dowse sport = ntohs(((struct sockaddr_in *)saddr)->sin_port); 5338360efbdSAlfred Perlstein break; 5348360efbdSAlfred Perlstein default: 5358360efbdSAlfred Perlstein syslog(LOG_ERR, "request from unknown address family"); 5368360efbdSAlfred Perlstein return; 5378360efbdSAlfred Perlstein } 5388360efbdSAlfred Perlstein lookup_failed = getnameinfo(saddr, saddr->sa_len, host, sizeof host, 5398360efbdSAlfred Perlstein NULL, 0, 0); 5408360efbdSAlfred Perlstein getnameinfo(saddr, saddr->sa_len, numerichost, 5418360efbdSAlfred Perlstein sizeof numerichost, NULL, 0, NI_NUMERICHOST); 5428360efbdSAlfred Perlstein ai = NULL; 5438fae3551SRodney W. Grimes switch (rqstp->rq_proc) { 5448fae3551SRodney W. Grimes case NULLPROC: 54591acb349SAlfred Perlstein if (!svc_sendreply(transp, xdr_void, NULL)) 54674853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 5478fae3551SRodney W. Grimes return; 5488fae3551SRodney W. Grimes case RPCMNT_MOUNT: 549a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 550f51631d7SGuido van Rooij syslog(LOG_NOTICE, 551f51631d7SGuido van Rooij "mount request from %s from unprivileged port", 5528360efbdSAlfred Perlstein numerichost); 5538fae3551SRodney W. Grimes svcerr_weakauth(transp); 5548fae3551SRodney W. Grimes return; 5558fae3551SRodney W. Grimes } 5568fae3551SRodney W. Grimes if (!svc_getargs(transp, xdr_dir, rpcpath)) { 557f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable mount request from %s", 5588360efbdSAlfred Perlstein numerichost); 5598fae3551SRodney W. Grimes svcerr_decode(transp); 5608fae3551SRodney W. Grimes return; 5618fae3551SRodney W. Grimes } 5628fae3551SRodney W. Grimes 5638fae3551SRodney W. Grimes /* 5648fae3551SRodney W. Grimes * Get the real pathname and make sure it is a directory 565a62dc406SDoug Rabson * or a regular file if the -r option was specified 566a62dc406SDoug Rabson * and it exists. 5678fae3551SRodney W. Grimes */ 568cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL || 5698fae3551SRodney W. Grimes stat(dirpath, &stb) < 0 || 570a62dc406SDoug Rabson (!S_ISDIR(stb.st_mode) && 571a62dc406SDoug Rabson (dir_only || !S_ISREG(stb.st_mode))) || 5728fae3551SRodney W. Grimes statfs(dirpath, &fsb) < 0) { 5738fae3551SRodney W. Grimes chdir("/"); /* Just in case realpath doesn't */ 574f51631d7SGuido van Rooij syslog(LOG_NOTICE, 57574853402SPhilippe Charnier "mount request from %s for non existent path %s", 5768360efbdSAlfred Perlstein numerichost, dirpath); 5778fae3551SRodney W. Grimes if (debug) 57874853402SPhilippe Charnier warnx("stat failed on %s", dirpath); 579e90cdb54SGuido van Rooij bad = ENOENT; /* We will send error reply later */ 5808fae3551SRodney W. Grimes } 5818fae3551SRodney W. Grimes 5828fae3551SRodney W. Grimes /* Check in the exports list */ 583a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 5848fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 585a62dc406SDoug Rabson hostset = defset = 0; 586a62dc406SDoug Rabson if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) || 5878fae3551SRodney W. Grimes ((dp = dirp_search(ep->ex_dirl, dirpath)) && 588a62dc406SDoug Rabson chk_host(dp, saddr, &defset, &hostset)) || 5898fae3551SRodney W. Grimes (defset && scan_tree(ep->ex_defdir, saddr) == 0 && 5908fae3551SRodney W. Grimes scan_tree(ep->ex_dirl, saddr) == 0))) { 591e90cdb54SGuido van Rooij if (bad) { 592e90cdb54SGuido van Rooij if (!svc_sendreply(transp, xdr_long, 593e90cdb54SGuido van Rooij (caddr_t)&bad)) 59474853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 595e90cdb54SGuido van Rooij sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 596e90cdb54SGuido van Rooij return; 597e90cdb54SGuido van Rooij } 598a62dc406SDoug Rabson if (hostset & DP_HOSTSET) 599a62dc406SDoug Rabson fhr.fhr_flag = hostset; 600a62dc406SDoug Rabson else 601a62dc406SDoug Rabson fhr.fhr_flag = defset; 602a62dc406SDoug Rabson fhr.fhr_vers = rqstp->rq_vers; 6038fae3551SRodney W. Grimes /* Get the file handle */ 60487564113SPeter Wemm memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t)); 605a62dc406SDoug Rabson if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) { 6068fae3551SRodney W. Grimes bad = errno; 60774853402SPhilippe Charnier syslog(LOG_ERR, "can't get fh for %s", dirpath); 6088fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_long, 6098fae3551SRodney W. Grimes (caddr_t)&bad)) 61074853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 611a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6128fae3551SRodney W. Grimes return; 6138fae3551SRodney W. Grimes } 614a62dc406SDoug Rabson if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr)) 61574853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6168360efbdSAlfred Perlstein if (!lookup_failed) 6178360efbdSAlfred Perlstein add_mlist(host, dirpath); 6188fae3551SRodney W. Grimes else 6198360efbdSAlfred Perlstein add_mlist(numerichost, dirpath); 6208fae3551SRodney W. Grimes if (debug) 62174853402SPhilippe Charnier warnx("mount successful"); 622f51631d7SGuido van Rooij if (log) 623f51631d7SGuido van Rooij syslog(LOG_NOTICE, 624f51631d7SGuido van Rooij "mount request succeeded from %s for %s", 6258360efbdSAlfred Perlstein numerichost, dirpath); 626f51631d7SGuido van Rooij } else { 6278fae3551SRodney W. Grimes bad = EACCES; 628f51631d7SGuido van Rooij syslog(LOG_NOTICE, 629f51631d7SGuido van Rooij "mount request denied from %s for %s", 6308360efbdSAlfred Perlstein numerichost, dirpath); 631f51631d7SGuido van Rooij } 632e90cdb54SGuido van Rooij 633e90cdb54SGuido van Rooij if (bad && !svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 63474853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 635a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6368fae3551SRodney W. Grimes return; 6378fae3551SRodney W. Grimes case RPCMNT_DUMP: 6388fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL)) 63974853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 640f51631d7SGuido van Rooij else if (log) 641f51631d7SGuido van Rooij syslog(LOG_NOTICE, 642f51631d7SGuido van Rooij "dump request succeeded from %s", 6438360efbdSAlfred Perlstein numerichost); 6448fae3551SRodney W. Grimes return; 6458fae3551SRodney W. Grimes case RPCMNT_UMOUNT: 646a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 647f51631d7SGuido van Rooij syslog(LOG_NOTICE, 648f51631d7SGuido van Rooij "umount request from %s from unprivileged port", 6498360efbdSAlfred Perlstein numerichost); 6508fae3551SRodney W. Grimes svcerr_weakauth(transp); 6518fae3551SRodney W. Grimes return; 6528fae3551SRodney W. Grimes } 653cb479b11SAlfred Perlstein if (!svc_getargs(transp, xdr_dir, rpcpath)) { 654f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable umount request from %s", 6558360efbdSAlfred Perlstein numerichost); 6568fae3551SRodney W. Grimes svcerr_decode(transp); 6578fae3551SRodney W. Grimes return; 6588fae3551SRodney W. Grimes } 659cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL) { 660cb479b11SAlfred Perlstein syslog(LOG_NOTICE, "umount request from %s " 661cb479b11SAlfred Perlstein "for non existent path %s", 6628360efbdSAlfred Perlstein numerichost, dirpath); 663cb479b11SAlfred Perlstein } 6648fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 66574853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6668360efbdSAlfred Perlstein if (!lookup_failed) 66701709abfSIan Dowse del_mlist(host, dirpath); 66801709abfSIan Dowse del_mlist(numerichost, dirpath); 669f51631d7SGuido van Rooij if (log) 670f51631d7SGuido van Rooij syslog(LOG_NOTICE, 671f51631d7SGuido van Rooij "umount request succeeded from %s for %s", 6728360efbdSAlfred Perlstein numerichost, dirpath); 6738fae3551SRodney W. Grimes return; 6748fae3551SRodney W. Grimes case RPCMNT_UMNTALL: 675a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 676f51631d7SGuido van Rooij syslog(LOG_NOTICE, 677f51631d7SGuido van Rooij "umountall request from %s from unprivileged port", 6788360efbdSAlfred Perlstein numerichost); 6798fae3551SRodney W. Grimes svcerr_weakauth(transp); 6808fae3551SRodney W. Grimes return; 6818fae3551SRodney W. Grimes } 6828fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 68374853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6848360efbdSAlfred Perlstein if (!lookup_failed) 68501709abfSIan Dowse del_mlist(host, NULL); 68601709abfSIan Dowse del_mlist(numerichost, NULL); 687f51631d7SGuido van Rooij if (log) 688f51631d7SGuido van Rooij syslog(LOG_NOTICE, 689f51631d7SGuido van Rooij "umountall request succeeded from %s", 6908360efbdSAlfred Perlstein numerichost); 6918fae3551SRodney W. Grimes return; 6928fae3551SRodney W. Grimes case RPCMNT_EXPORT: 6938fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL)) 69491acb349SAlfred Perlstein if (!svc_sendreply(transp, xdr_explist_brief, (caddr_t)NULL)) 69574853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 696f51631d7SGuido van Rooij if (log) 697f51631d7SGuido van Rooij syslog(LOG_NOTICE, 698f51631d7SGuido van Rooij "export request succeeded from %s", 6998360efbdSAlfred Perlstein numerichost); 7008fae3551SRodney W. Grimes return; 7018fae3551SRodney W. Grimes default: 7028fae3551SRodney W. Grimes svcerr_noproc(transp); 7038fae3551SRodney W. Grimes return; 7048fae3551SRodney W. Grimes } 7058fae3551SRodney W. Grimes } 7068fae3551SRodney W. Grimes 7078fae3551SRodney W. Grimes /* 7088fae3551SRodney W. Grimes * Xdr conversion for a dirpath string 7098fae3551SRodney W. Grimes */ 7108fae3551SRodney W. Grimes int 7118fae3551SRodney W. Grimes xdr_dir(xdrsp, dirp) 7128fae3551SRodney W. Grimes XDR *xdrsp; 7138fae3551SRodney W. Grimes char *dirp; 7148fae3551SRodney W. Grimes { 7158fae3551SRodney W. Grimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 7168fae3551SRodney W. Grimes } 7178fae3551SRodney W. Grimes 7188fae3551SRodney W. Grimes /* 719a62dc406SDoug Rabson * Xdr routine to generate file handle reply 7208fae3551SRodney W. Grimes */ 7218fae3551SRodney W. Grimes int 722a62dc406SDoug Rabson xdr_fhs(xdrsp, cp) 7238fae3551SRodney W. Grimes XDR *xdrsp; 724a62dc406SDoug Rabson caddr_t cp; 7258fae3551SRodney W. Grimes { 7263d438ad6SDavid E. O'Brien struct fhreturn *fhrp = (struct fhreturn *)cp; 727a62dc406SDoug Rabson u_long ok = 0, len, auth; 7288fae3551SRodney W. Grimes 7298fae3551SRodney W. Grimes if (!xdr_long(xdrsp, &ok)) 7308fae3551SRodney W. Grimes return (0); 731a62dc406SDoug Rabson switch (fhrp->fhr_vers) { 732a62dc406SDoug Rabson case 1: 733a62dc406SDoug Rabson return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH)); 734a62dc406SDoug Rabson case 3: 735a62dc406SDoug Rabson len = NFSX_V3FH; 736a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 737a62dc406SDoug Rabson return (0); 738a62dc406SDoug Rabson if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) 739a62dc406SDoug Rabson return (0); 740a62dc406SDoug Rabson auth = RPCAUTH_UNIX; 741a62dc406SDoug Rabson len = 1; 742a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 743a62dc406SDoug Rabson return (0); 744a62dc406SDoug Rabson return (xdr_long(xdrsp, &auth)); 745a62dc406SDoug Rabson }; 746a62dc406SDoug Rabson return (0); 7478fae3551SRodney W. Grimes } 7488fae3551SRodney W. Grimes 7498fae3551SRodney W. Grimes int 7508fae3551SRodney W. Grimes xdr_mlist(xdrsp, cp) 7518fae3551SRodney W. Grimes XDR *xdrsp; 7528fae3551SRodney W. Grimes caddr_t cp; 7538fae3551SRodney W. Grimes { 7548fae3551SRodney W. Grimes struct mountlist *mlp; 7558fae3551SRodney W. Grimes int true = 1; 7568fae3551SRodney W. Grimes int false = 0; 7578fae3551SRodney W. Grimes char *strp; 7588fae3551SRodney W. Grimes 7598fae3551SRodney W. Grimes mlp = mlhead; 7608fae3551SRodney W. Grimes while (mlp) { 7618fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 7628fae3551SRodney W. Grimes return (0); 7638fae3551SRodney W. Grimes strp = &mlp->ml_host[0]; 7648fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 7658fae3551SRodney W. Grimes return (0); 7668fae3551SRodney W. Grimes strp = &mlp->ml_dirp[0]; 7678fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 7688fae3551SRodney W. Grimes return (0); 7698fae3551SRodney W. Grimes mlp = mlp->ml_next; 7708fae3551SRodney W. Grimes } 7718fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 7728fae3551SRodney W. Grimes return (0); 7738fae3551SRodney W. Grimes return (1); 7748fae3551SRodney W. Grimes } 7758fae3551SRodney W. Grimes 7768fae3551SRodney W. Grimes /* 7778fae3551SRodney W. Grimes * Xdr conversion for export list 7788fae3551SRodney W. Grimes */ 7798fae3551SRodney W. Grimes int 78091acb349SAlfred Perlstein xdr_explist_common(xdrsp, cp, brief) 7818fae3551SRodney W. Grimes XDR *xdrsp; 7828fae3551SRodney W. Grimes caddr_t cp; 78391acb349SAlfred Perlstein int brief; 7848fae3551SRodney W. Grimes { 7858fae3551SRodney W. Grimes struct exportlist *ep; 7868fae3551SRodney W. Grimes int false = 0; 787a62dc406SDoug Rabson int putdef; 788a62dc406SDoug Rabson sigset_t sighup_mask; 7898fae3551SRodney W. Grimes 790a62dc406SDoug Rabson sigemptyset(&sighup_mask); 791a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 792a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 7938fae3551SRodney W. Grimes ep = exphead; 7948fae3551SRodney W. Grimes while (ep) { 7958fae3551SRodney W. Grimes putdef = 0; 79691acb349SAlfred Perlstein if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, 79791acb349SAlfred Perlstein &putdef, brief)) 7988fae3551SRodney W. Grimes goto errout; 7998fae3551SRodney W. Grimes if (ep->ex_defdir && putdef == 0 && 8008fae3551SRodney W. Grimes put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL, 80191acb349SAlfred Perlstein &putdef, brief)) 8028fae3551SRodney W. Grimes goto errout; 8038fae3551SRodney W. Grimes ep = ep->ex_next; 8048fae3551SRodney W. Grimes } 805a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 8068fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 8078fae3551SRodney W. Grimes return (0); 8088fae3551SRodney W. Grimes return (1); 8098fae3551SRodney W. Grimes errout: 810a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 8118fae3551SRodney W. Grimes return (0); 8128fae3551SRodney W. Grimes } 8138fae3551SRodney W. Grimes 8148fae3551SRodney W. Grimes /* 8158fae3551SRodney W. Grimes * Called from xdr_explist() to traverse the tree and export the 8168fae3551SRodney W. Grimes * directory paths. 8178fae3551SRodney W. Grimes */ 8188fae3551SRodney W. Grimes int 81991acb349SAlfred Perlstein put_exlist(dp, xdrsp, adp, putdefp, brief) 8208fae3551SRodney W. Grimes struct dirlist *dp; 8218fae3551SRodney W. Grimes XDR *xdrsp; 8228fae3551SRodney W. Grimes struct dirlist *adp; 8238fae3551SRodney W. Grimes int *putdefp; 82491acb349SAlfred Perlstein int brief; 8258fae3551SRodney W. Grimes { 8268fae3551SRodney W. Grimes struct grouplist *grp; 8278fae3551SRodney W. Grimes struct hostlist *hp; 8288fae3551SRodney W. Grimes int true = 1; 8298fae3551SRodney W. Grimes int false = 0; 8308fae3551SRodney W. Grimes int gotalldir = 0; 8318fae3551SRodney W. Grimes char *strp; 8328fae3551SRodney W. Grimes 8338fae3551SRodney W. Grimes if (dp) { 83491acb349SAlfred Perlstein if (put_exlist(dp->dp_left, xdrsp, adp, putdefp, brief)) 8358fae3551SRodney W. Grimes return (1); 8368fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 8378fae3551SRodney W. Grimes return (1); 8388fae3551SRodney W. Grimes strp = dp->dp_dirp; 8398fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 8408fae3551SRodney W. Grimes return (1); 8418fae3551SRodney W. Grimes if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) { 8428fae3551SRodney W. Grimes gotalldir = 1; 8438fae3551SRodney W. Grimes *putdefp = 1; 8448fae3551SRodney W. Grimes } 84591acb349SAlfred Perlstein if (brief) { 84691acb349SAlfred Perlstein if (!xdr_bool(xdrsp, &true)) 84791acb349SAlfred Perlstein return (1); 84891acb349SAlfred Perlstein strp = "(...)"; 84991acb349SAlfred Perlstein if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 85091acb349SAlfred Perlstein return (1); 85191acb349SAlfred Perlstein } else if ((dp->dp_flag & DP_DEFSET) == 0 && 8528fae3551SRodney W. Grimes (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) { 8538fae3551SRodney W. Grimes hp = dp->dp_hosts; 8548fae3551SRodney W. Grimes while (hp) { 8558fae3551SRodney W. Grimes grp = hp->ht_grp; 8568fae3551SRodney W. Grimes if (grp->gr_type == GT_HOST) { 8578fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 8588fae3551SRodney W. Grimes return (1); 8598360efbdSAlfred Perlstein strp = grp->gr_ptr.gt_addrinfo->ai_canonname; 8608fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, 8618fae3551SRodney W. Grimes RPCMNT_NAMELEN)) 8628fae3551SRodney W. Grimes return (1); 8638fae3551SRodney W. Grimes } else if (grp->gr_type == GT_NET) { 8648fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 8658fae3551SRodney W. Grimes return (1); 8668fae3551SRodney W. Grimes strp = grp->gr_ptr.gt_net.nt_name; 8678fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, 8688fae3551SRodney W. Grimes RPCMNT_NAMELEN)) 8698fae3551SRodney W. Grimes return (1); 8708fae3551SRodney W. Grimes } 8718fae3551SRodney W. Grimes hp = hp->ht_next; 8728fae3551SRodney W. Grimes if (gotalldir && hp == (struct hostlist *)NULL) { 8738fae3551SRodney W. Grimes hp = adp->dp_hosts; 8748fae3551SRodney W. Grimes gotalldir = 0; 8758fae3551SRodney W. Grimes } 8768fae3551SRodney W. Grimes } 8778fae3551SRodney W. Grimes } 8788fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 8798fae3551SRodney W. Grimes return (1); 88091acb349SAlfred Perlstein if (put_exlist(dp->dp_right, xdrsp, adp, putdefp, brief)) 8818fae3551SRodney W. Grimes return (1); 8828fae3551SRodney W. Grimes } 8838fae3551SRodney W. Grimes return (0); 8848fae3551SRodney W. Grimes } 8858fae3551SRodney W. Grimes 88691acb349SAlfred Perlstein int 88791acb349SAlfred Perlstein xdr_explist(xdrsp, cp) 88891acb349SAlfred Perlstein XDR *xdrsp; 88991acb349SAlfred Perlstein caddr_t cp; 89091acb349SAlfred Perlstein { 89191acb349SAlfred Perlstein 89291acb349SAlfred Perlstein return xdr_explist_common(xdrsp, cp, 0); 89391acb349SAlfred Perlstein } 89491acb349SAlfred Perlstein 89591acb349SAlfred Perlstein int 89691acb349SAlfred Perlstein xdr_explist_brief(xdrsp, cp) 89791acb349SAlfred Perlstein XDR *xdrsp; 89891acb349SAlfred Perlstein caddr_t cp; 89991acb349SAlfred Perlstein { 90091acb349SAlfred Perlstein 90191acb349SAlfred Perlstein return xdr_explist_common(xdrsp, cp, 1); 90291acb349SAlfred Perlstein } 90391acb349SAlfred Perlstein 90491ca1a91SIan Dowse char *line; 90591ca1a91SIan Dowse int linesize; 9068fae3551SRodney W. Grimes FILE *exp_file; 9078fae3551SRodney W. Grimes 9088fae3551SRodney W. Grimes /* 9098fae3551SRodney W. Grimes * Get the export list 9108fae3551SRodney W. Grimes */ 9118fae3551SRodney W. Grimes void 9128fae3551SRodney W. Grimes get_exportlist() 9138fae3551SRodney W. Grimes { 9148fae3551SRodney W. Grimes struct exportlist *ep, *ep2; 9158fae3551SRodney W. Grimes struct grouplist *grp, *tgrp; 9168fae3551SRodney W. Grimes struct exportlist **epp; 9178fae3551SRodney W. Grimes struct dirlist *dirhead; 9188fae3551SRodney W. Grimes struct statfs fsb, *fsp; 919c0511d3bSBrian Feldman struct xucred anon; 9208fae3551SRodney W. Grimes char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; 9218fae3551SRodney W. Grimes int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp; 9228fae3551SRodney W. Grimes 923cb479b11SAlfred Perlstein dirp = NULL; 924cb479b11SAlfred Perlstein dirplen = 0; 925cb479b11SAlfred Perlstein 9268fae3551SRodney W. Grimes /* 9278fae3551SRodney W. Grimes * First, get rid of the old list 9288fae3551SRodney W. Grimes */ 9298fae3551SRodney W. Grimes ep = exphead; 9308fae3551SRodney W. Grimes while (ep) { 9318fae3551SRodney W. Grimes ep2 = ep; 9328fae3551SRodney W. Grimes ep = ep->ex_next; 9338fae3551SRodney W. Grimes free_exp(ep2); 9348fae3551SRodney W. Grimes } 9358fae3551SRodney W. Grimes exphead = (struct exportlist *)NULL; 9368fae3551SRodney W. Grimes 9378fae3551SRodney W. Grimes grp = grphead; 9388fae3551SRodney W. Grimes while (grp) { 9398fae3551SRodney W. Grimes tgrp = grp; 9408fae3551SRodney W. Grimes grp = grp->gr_next; 9418fae3551SRodney W. Grimes free_grp(tgrp); 9428fae3551SRodney W. Grimes } 9438fae3551SRodney W. Grimes grphead = (struct grouplist *)NULL; 9448fae3551SRodney W. Grimes 9458fae3551SRodney W. Grimes /* 9468fae3551SRodney W. Grimes * And delete exports that are in the kernel for all local 9478fae3551SRodney W. Grimes * filesystems. 9488fae3551SRodney W. Grimes * XXX: Should know how to handle all local exportable filesystems 94987564113SPeter Wemm * instead of just "ufs". 9508fae3551SRodney W. Grimes */ 9518fae3551SRodney W. Grimes num = getmntinfo(&fsp, MNT_NOWAIT); 9528fae3551SRodney W. Grimes for (i = 0; i < num; i++) { 9538fae3551SRodney W. Grimes union { 9548fae3551SRodney W. Grimes struct ufs_args ua; 9558fae3551SRodney W. Grimes struct iso_args ia; 956a62dc406SDoug Rabson struct msdosfs_args da; 9579300c696SSemen Ustimenko struct ntfs_args na; 958a62dc406SDoug Rabson } targs; 959a62dc406SDoug Rabson 960753d4978SPoul-Henning Kamp if (!strcmp(fsp->f_fstypename, "ufs") || 9614ccd7546SRuslan Ermilov !strcmp(fsp->f_fstypename, "msdosfs") || 9629300c696SSemen Ustimenko !strcmp(fsp->f_fstypename, "ntfs") || 96387564113SPeter Wemm !strcmp(fsp->f_fstypename, "cd9660")) { 964a62dc406SDoug Rabson targs.ua.fspec = NULL; 965a62dc406SDoug Rabson targs.ua.export.ex_flags = MNT_DELEXPORT; 966a62dc406SDoug Rabson if (mount(fsp->f_fstypename, fsp->f_mntonname, 9675f558fa4SIan Dowse fsp->f_flags | MNT_UPDATE, (caddr_t)&targs) < 0 && 9685f558fa4SIan Dowse errno != ENOENT) 9695f558fa4SIan Dowse syslog(LOG_ERR, 9705f558fa4SIan Dowse "can't delete exports for %s: %m", 9718fae3551SRodney W. Grimes fsp->f_mntonname); 9728fae3551SRodney W. Grimes } 9738fae3551SRodney W. Grimes fsp++; 9748fae3551SRodney W. Grimes } 9758fae3551SRodney W. Grimes 9768fae3551SRodney W. Grimes /* 9778fae3551SRodney W. Grimes * Read in the exports file and build the list, calling 9788fae3551SRodney W. Grimes * mount() as we go along to push the export rules into the kernel. 9798fae3551SRodney W. Grimes */ 9808fae3551SRodney W. Grimes if ((exp_file = fopen(exname, "r")) == NULL) { 98174853402SPhilippe Charnier syslog(LOG_ERR, "can't open %s", exname); 9828fae3551SRodney W. Grimes exit(2); 9838fae3551SRodney W. Grimes } 9848fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 9858fae3551SRodney W. Grimes while (get_line()) { 9868fae3551SRodney W. Grimes if (debug) 98774853402SPhilippe Charnier warnx("got line %s", line); 9888fae3551SRodney W. Grimes cp = line; 9898fae3551SRodney W. Grimes nextfield(&cp, &endcp); 9908fae3551SRodney W. Grimes if (*cp == '#') 9918fae3551SRodney W. Grimes goto nextline; 9928fae3551SRodney W. Grimes 9938fae3551SRodney W. Grimes /* 9948fae3551SRodney W. Grimes * Set defaults. 9958fae3551SRodney W. Grimes */ 9968fae3551SRodney W. Grimes has_host = FALSE; 9978fae3551SRodney W. Grimes anon = def_anon; 9988fae3551SRodney W. Grimes exflags = MNT_EXPORTED; 9998fae3551SRodney W. Grimes got_nondir = 0; 10008fae3551SRodney W. Grimes opt_flags = 0; 10018fae3551SRodney W. Grimes ep = (struct exportlist *)NULL; 10028fae3551SRodney W. Grimes 10038fae3551SRodney W. Grimes /* 10048fae3551SRodney W. Grimes * Create new exports list entry 10058fae3551SRodney W. Grimes */ 10068fae3551SRodney W. Grimes len = endcp-cp; 10078fae3551SRodney W. Grimes tgrp = grp = get_grp(); 10088fae3551SRodney W. Grimes while (len > 0) { 10098fae3551SRodney W. Grimes if (len > RPCMNT_NAMELEN) { 10108fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10118fae3551SRodney W. Grimes goto nextline; 10128fae3551SRodney W. Grimes } 10138fae3551SRodney W. Grimes if (*cp == '-') { 10148fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10158fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10168fae3551SRodney W. Grimes goto nextline; 10178fae3551SRodney W. Grimes } 10188fae3551SRodney W. Grimes if (debug) 101974853402SPhilippe Charnier warnx("doing opt %s", cp); 10208fae3551SRodney W. Grimes got_nondir = 1; 10218fae3551SRodney W. Grimes if (do_opt(&cp, &endcp, ep, grp, &has_host, 10228fae3551SRodney W. Grimes &exflags, &anon)) { 10238fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10248fae3551SRodney W. Grimes goto nextline; 10258fae3551SRodney W. Grimes } 10268fae3551SRodney W. Grimes } else if (*cp == '/') { 10278fae3551SRodney W. Grimes savedc = *endcp; 10288fae3551SRodney W. Grimes *endcp = '\0'; 10298fae3551SRodney W. Grimes if (check_dirpath(cp) && 10308fae3551SRodney W. Grimes statfs(cp, &fsb) >= 0) { 10318fae3551SRodney W. Grimes if (got_nondir) { 103274853402SPhilippe Charnier syslog(LOG_ERR, "dirs must be first"); 10338fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10348fae3551SRodney W. Grimes goto nextline; 10358fae3551SRodney W. Grimes } 10368fae3551SRodney W. Grimes if (ep) { 10378fae3551SRodney W. Grimes if (ep->ex_fs.val[0] != fsb.f_fsid.val[0] || 10388fae3551SRodney W. Grimes ep->ex_fs.val[1] != fsb.f_fsid.val[1]) { 10398fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10408fae3551SRodney W. Grimes goto nextline; 10418fae3551SRodney W. Grimes } 10428fae3551SRodney W. Grimes } else { 10438fae3551SRodney W. Grimes /* 10448fae3551SRodney W. Grimes * See if this directory is already 10458fae3551SRodney W. Grimes * in the list. 10468fae3551SRodney W. Grimes */ 10478fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 10488fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10498fae3551SRodney W. Grimes ep = get_exp(); 10508fae3551SRodney W. Grimes ep->ex_fs = fsb.f_fsid; 10518fae3551SRodney W. Grimes ep->ex_fsdir = (char *) 10528fae3551SRodney W. Grimes malloc(strlen(fsb.f_mntonname) + 1); 10538fae3551SRodney W. Grimes if (ep->ex_fsdir) 10548fae3551SRodney W. Grimes strcpy(ep->ex_fsdir, 10558fae3551SRodney W. Grimes fsb.f_mntonname); 10568fae3551SRodney W. Grimes else 10578fae3551SRodney W. Grimes out_of_mem(); 10588fae3551SRodney W. Grimes if (debug) 105974853402SPhilippe Charnier warnx("making new ep fs=0x%x,0x%x", 10608fae3551SRodney W. Grimes fsb.f_fsid.val[0], 10618fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 10628fae3551SRodney W. Grimes } else if (debug) 106374853402SPhilippe Charnier warnx("found ep fs=0x%x,0x%x", 10648fae3551SRodney W. Grimes fsb.f_fsid.val[0], 10658fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 10668fae3551SRodney W. Grimes } 10678fae3551SRodney W. Grimes 10688fae3551SRodney W. Grimes /* 10698fae3551SRodney W. Grimes * Add dirpath to export mount point. 10708fae3551SRodney W. Grimes */ 10718fae3551SRodney W. Grimes dirp = add_expdir(&dirhead, cp, len); 10728fae3551SRodney W. Grimes dirplen = len; 10738fae3551SRodney W. Grimes } else { 10748fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10758fae3551SRodney W. Grimes goto nextline; 10768fae3551SRodney W. Grimes } 10778fae3551SRodney W. Grimes *endcp = savedc; 10788fae3551SRodney W. Grimes } else { 10798fae3551SRodney W. Grimes savedc = *endcp; 10808fae3551SRodney W. Grimes *endcp = '\0'; 10818fae3551SRodney W. Grimes got_nondir = 1; 10828fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10838fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10848fae3551SRodney W. Grimes goto nextline; 10858fae3551SRodney W. Grimes } 10868fae3551SRodney W. Grimes 10878fae3551SRodney W. Grimes /* 10888fae3551SRodney W. Grimes * Get the host or netgroup. 10898fae3551SRodney W. Grimes */ 10908fae3551SRodney W. Grimes setnetgrent(cp); 10918fae3551SRodney W. Grimes netgrp = getnetgrent(&hst, &usr, &dom); 10928fae3551SRodney W. Grimes do { 10938fae3551SRodney W. Grimes if (has_host) { 10948fae3551SRodney W. Grimes grp->gr_next = get_grp(); 10958fae3551SRodney W. Grimes grp = grp->gr_next; 10968fae3551SRodney W. Grimes } 10978fae3551SRodney W. Grimes if (netgrp) { 10989d70a156SJoerg Wunsch if (hst == 0) { 109974853402SPhilippe Charnier syslog(LOG_ERR, 110074853402SPhilippe Charnier "null hostname in netgroup %s, skipping", cp); 110101d48801SJoerg Wunsch grp->gr_type = GT_IGNORE; 11029d70a156SJoerg Wunsch } else if (get_host(hst, grp, tgrp)) { 110374853402SPhilippe Charnier syslog(LOG_ERR, 110474853402SPhilippe Charnier "bad host %s in netgroup %s, skipping", hst, cp); 1105a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 11068fae3551SRodney W. Grimes } 11078b5a6d67SBill Paul } else if (get_host(cp, grp, tgrp)) { 110874853402SPhilippe Charnier syslog(LOG_ERR, "bad host %s, skipping", cp); 1109a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 11108fae3551SRodney W. Grimes } 11118fae3551SRodney W. Grimes has_host = TRUE; 11128fae3551SRodney W. Grimes } while (netgrp && getnetgrent(&hst, &usr, &dom)); 11138fae3551SRodney W. Grimes endnetgrent(); 11148fae3551SRodney W. Grimes *endcp = savedc; 11158fae3551SRodney W. Grimes } 11168fae3551SRodney W. Grimes cp = endcp; 11178fae3551SRodney W. Grimes nextfield(&cp, &endcp); 11188fae3551SRodney W. Grimes len = endcp - cp; 11198fae3551SRodney W. Grimes } 11208fae3551SRodney W. Grimes if (check_options(dirhead)) { 11218fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11228fae3551SRodney W. Grimes goto nextline; 11238fae3551SRodney W. Grimes } 11248fae3551SRodney W. Grimes if (!has_host) { 11256d359f31SIan Dowse grp->gr_type = GT_DEFAULT; 11268fae3551SRodney W. Grimes if (debug) 112774853402SPhilippe Charnier warnx("adding a default entry"); 11288fae3551SRodney W. Grimes 11298fae3551SRodney W. Grimes /* 11308fae3551SRodney W. Grimes * Don't allow a network export coincide with a list of 11318fae3551SRodney W. Grimes * host(s) on the same line. 11328fae3551SRodney W. Grimes */ 11338fae3551SRodney W. Grimes } else if ((opt_flags & OP_NET) && tgrp->gr_next) { 113460caaee2SIan Dowse syslog(LOG_ERR, "network/host conflict"); 11358fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11368fae3551SRodney W. Grimes goto nextline; 1137a968cfd8SJonathan Lemon 1138a968cfd8SJonathan Lemon /* 1139a968cfd8SJonathan Lemon * If an export list was specified on this line, make sure 1140a968cfd8SJonathan Lemon * that we have at least one valid entry, otherwise skip it. 1141a968cfd8SJonathan Lemon */ 1142a968cfd8SJonathan Lemon } else { 1143a968cfd8SJonathan Lemon grp = tgrp; 1144a968cfd8SJonathan Lemon while (grp && grp->gr_type == GT_IGNORE) 1145a968cfd8SJonathan Lemon grp = grp->gr_next; 1146a968cfd8SJonathan Lemon if (! grp) { 1147a968cfd8SJonathan Lemon getexp_err(ep, tgrp); 1148a968cfd8SJonathan Lemon goto nextline; 1149a968cfd8SJonathan Lemon } 11508fae3551SRodney W. Grimes } 11518fae3551SRodney W. Grimes 11528fae3551SRodney W. Grimes /* 11538fae3551SRodney W. Grimes * Loop through hosts, pushing the exports into the kernel. 11548fae3551SRodney W. Grimes * After loop, tgrp points to the start of the list and 11558fae3551SRodney W. Grimes * grp points to the last entry in the list. 11568fae3551SRodney W. Grimes */ 11578fae3551SRodney W. Grimes grp = tgrp; 11588fae3551SRodney W. Grimes do { 115901709abfSIan Dowse if (do_mount(ep, grp, exflags, &anon, dirp, dirplen, 116001709abfSIan Dowse &fsb)) { 11618fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11628fae3551SRodney W. Grimes goto nextline; 11638fae3551SRodney W. Grimes } 11648fae3551SRodney W. Grimes } while (grp->gr_next && (grp = grp->gr_next)); 11658fae3551SRodney W. Grimes 11668fae3551SRodney W. Grimes /* 11678fae3551SRodney W. Grimes * Success. Update the data structures. 11688fae3551SRodney W. Grimes */ 11698fae3551SRodney W. Grimes if (has_host) { 1170a62dc406SDoug Rabson hang_dirp(dirhead, tgrp, ep, opt_flags); 11718fae3551SRodney W. Grimes grp->gr_next = grphead; 11728fae3551SRodney W. Grimes grphead = tgrp; 11738fae3551SRodney W. Grimes } else { 11748fae3551SRodney W. Grimes hang_dirp(dirhead, (struct grouplist *)NULL, ep, 1175a62dc406SDoug Rabson opt_flags); 11768fae3551SRodney W. Grimes free_grp(grp); 11778fae3551SRodney W. Grimes } 11788fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 11798fae3551SRodney W. Grimes if ((ep->ex_flag & EX_LINKED) == 0) { 11808fae3551SRodney W. Grimes ep2 = exphead; 11818fae3551SRodney W. Grimes epp = &exphead; 11828fae3551SRodney W. Grimes 11838fae3551SRodney W. Grimes /* 11848fae3551SRodney W. Grimes * Insert in the list in alphabetical order. 11858fae3551SRodney W. Grimes */ 11868fae3551SRodney W. Grimes while (ep2 && strcmp(ep2->ex_fsdir, ep->ex_fsdir) < 0) { 11878fae3551SRodney W. Grimes epp = &ep2->ex_next; 11888fae3551SRodney W. Grimes ep2 = ep2->ex_next; 11898fae3551SRodney W. Grimes } 11908fae3551SRodney W. Grimes if (ep2) 11918fae3551SRodney W. Grimes ep->ex_next = ep2; 11928fae3551SRodney W. Grimes *epp = ep; 11938fae3551SRodney W. Grimes ep->ex_flag |= EX_LINKED; 11948fae3551SRodney W. Grimes } 11958fae3551SRodney W. Grimes nextline: 11968fae3551SRodney W. Grimes if (dirhead) { 11978fae3551SRodney W. Grimes free_dir(dirhead); 11988fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 11998fae3551SRodney W. Grimes } 12008fae3551SRodney W. Grimes } 12018fae3551SRodney W. Grimes fclose(exp_file); 12028fae3551SRodney W. Grimes } 12038fae3551SRodney W. Grimes 12048fae3551SRodney W. Grimes /* 12058fae3551SRodney W. Grimes * Allocate an export list element 12068fae3551SRodney W. Grimes */ 12078fae3551SRodney W. Grimes struct exportlist * 12088fae3551SRodney W. Grimes get_exp() 12098fae3551SRodney W. Grimes { 12108fae3551SRodney W. Grimes struct exportlist *ep; 12118fae3551SRodney W. Grimes 12128fae3551SRodney W. Grimes ep = (struct exportlist *)malloc(sizeof (struct exportlist)); 12138fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) 12148fae3551SRodney W. Grimes out_of_mem(); 121587564113SPeter Wemm memset(ep, 0, sizeof(struct exportlist)); 12168fae3551SRodney W. Grimes return (ep); 12178fae3551SRodney W. Grimes } 12188fae3551SRodney W. Grimes 12198fae3551SRodney W. Grimes /* 12208fae3551SRodney W. Grimes * Allocate a group list element 12218fae3551SRodney W. Grimes */ 12228fae3551SRodney W. Grimes struct grouplist * 12238fae3551SRodney W. Grimes get_grp() 12248fae3551SRodney W. Grimes { 12258fae3551SRodney W. Grimes struct grouplist *gp; 12268fae3551SRodney W. Grimes 12278fae3551SRodney W. Grimes gp = (struct grouplist *)malloc(sizeof (struct grouplist)); 12288fae3551SRodney W. Grimes if (gp == (struct grouplist *)NULL) 12298fae3551SRodney W. Grimes out_of_mem(); 123087564113SPeter Wemm memset(gp, 0, sizeof(struct grouplist)); 12318fae3551SRodney W. Grimes return (gp); 12328fae3551SRodney W. Grimes } 12338fae3551SRodney W. Grimes 12348fae3551SRodney W. Grimes /* 12358fae3551SRodney W. Grimes * Clean up upon an error in get_exportlist(). 12368fae3551SRodney W. Grimes */ 12378fae3551SRodney W. Grimes void 12388fae3551SRodney W. Grimes getexp_err(ep, grp) 12398fae3551SRodney W. Grimes struct exportlist *ep; 12408fae3551SRodney W. Grimes struct grouplist *grp; 12418fae3551SRodney W. Grimes { 12428fae3551SRodney W. Grimes struct grouplist *tgrp; 12438fae3551SRodney W. Grimes 1244288fa14aSJoerg Wunsch if (!(opt_flags & OP_QUIET)) 124574853402SPhilippe Charnier syslog(LOG_ERR, "bad exports list line %s", line); 12468fae3551SRodney W. Grimes if (ep && (ep->ex_flag & EX_LINKED) == 0) 12478fae3551SRodney W. Grimes free_exp(ep); 12488fae3551SRodney W. Grimes while (grp) { 12498fae3551SRodney W. Grimes tgrp = grp; 12508fae3551SRodney W. Grimes grp = grp->gr_next; 12518fae3551SRodney W. Grimes free_grp(tgrp); 12528fae3551SRodney W. Grimes } 12538fae3551SRodney W. Grimes } 12548fae3551SRodney W. Grimes 12558fae3551SRodney W. Grimes /* 12568fae3551SRodney W. Grimes * Search the export list for a matching fs. 12578fae3551SRodney W. Grimes */ 12588fae3551SRodney W. Grimes struct exportlist * 12598fae3551SRodney W. Grimes ex_search(fsid) 12608fae3551SRodney W. Grimes fsid_t *fsid; 12618fae3551SRodney W. Grimes { 12628fae3551SRodney W. Grimes struct exportlist *ep; 12638fae3551SRodney W. Grimes 12648fae3551SRodney W. Grimes ep = exphead; 12658fae3551SRodney W. Grimes while (ep) { 12668fae3551SRodney W. Grimes if (ep->ex_fs.val[0] == fsid->val[0] && 12678fae3551SRodney W. Grimes ep->ex_fs.val[1] == fsid->val[1]) 12688fae3551SRodney W. Grimes return (ep); 12698fae3551SRodney W. Grimes ep = ep->ex_next; 12708fae3551SRodney W. Grimes } 12718fae3551SRodney W. Grimes return (ep); 12728fae3551SRodney W. Grimes } 12738fae3551SRodney W. Grimes 12748fae3551SRodney W. Grimes /* 12758fae3551SRodney W. Grimes * Add a directory path to the list. 12768fae3551SRodney W. Grimes */ 12778fae3551SRodney W. Grimes char * 12788fae3551SRodney W. Grimes add_expdir(dpp, cp, len) 12798fae3551SRodney W. Grimes struct dirlist **dpp; 12808fae3551SRodney W. Grimes char *cp; 12818fae3551SRodney W. Grimes int len; 12828fae3551SRodney W. Grimes { 12838fae3551SRodney W. Grimes struct dirlist *dp; 12848fae3551SRodney W. Grimes 12858fae3551SRodney W. Grimes dp = (struct dirlist *)malloc(sizeof (struct dirlist) + len); 128674853402SPhilippe Charnier if (dp == (struct dirlist *)NULL) 128774853402SPhilippe Charnier out_of_mem(); 12888fae3551SRodney W. Grimes dp->dp_left = *dpp; 12898fae3551SRodney W. Grimes dp->dp_right = (struct dirlist *)NULL; 12908fae3551SRodney W. Grimes dp->dp_flag = 0; 12918fae3551SRodney W. Grimes dp->dp_hosts = (struct hostlist *)NULL; 12928fae3551SRodney W. Grimes strcpy(dp->dp_dirp, cp); 12938fae3551SRodney W. Grimes *dpp = dp; 12948fae3551SRodney W. Grimes return (dp->dp_dirp); 12958fae3551SRodney W. Grimes } 12968fae3551SRodney W. Grimes 12978fae3551SRodney W. Grimes /* 12988fae3551SRodney W. Grimes * Hang the dir list element off the dirpath binary tree as required 12998fae3551SRodney W. Grimes * and update the entry for host. 13008fae3551SRodney W. Grimes */ 13018fae3551SRodney W. Grimes void 1302a62dc406SDoug Rabson hang_dirp(dp, grp, ep, flags) 13038fae3551SRodney W. Grimes struct dirlist *dp; 13048fae3551SRodney W. Grimes struct grouplist *grp; 13058fae3551SRodney W. Grimes struct exportlist *ep; 1306a62dc406SDoug Rabson int flags; 13078fae3551SRodney W. Grimes { 13088fae3551SRodney W. Grimes struct hostlist *hp; 13098fae3551SRodney W. Grimes struct dirlist *dp2; 13108fae3551SRodney W. Grimes 1311a62dc406SDoug Rabson if (flags & OP_ALLDIRS) { 13128fae3551SRodney W. Grimes if (ep->ex_defdir) 13138fae3551SRodney W. Grimes free((caddr_t)dp); 13148fae3551SRodney W. Grimes else 13158fae3551SRodney W. Grimes ep->ex_defdir = dp; 1316a62dc406SDoug Rabson if (grp == (struct grouplist *)NULL) { 13178fae3551SRodney W. Grimes ep->ex_defdir->dp_flag |= DP_DEFSET; 1318a62dc406SDoug Rabson } else while (grp) { 13198fae3551SRodney W. Grimes hp = get_ht(); 13208fae3551SRodney W. Grimes hp->ht_grp = grp; 13218fae3551SRodney W. Grimes hp->ht_next = ep->ex_defdir->dp_hosts; 13228fae3551SRodney W. Grimes ep->ex_defdir->dp_hosts = hp; 13238fae3551SRodney W. Grimes grp = grp->gr_next; 13248fae3551SRodney W. Grimes } 13258fae3551SRodney W. Grimes } else { 13268fae3551SRodney W. Grimes 13278fae3551SRodney W. Grimes /* 132874853402SPhilippe Charnier * Loop through the directories adding them to the tree. 13298fae3551SRodney W. Grimes */ 13308fae3551SRodney W. Grimes while (dp) { 13318fae3551SRodney W. Grimes dp2 = dp->dp_left; 1332a62dc406SDoug Rabson add_dlist(&ep->ex_dirl, dp, grp, flags); 13338fae3551SRodney W. Grimes dp = dp2; 13348fae3551SRodney W. Grimes } 13358fae3551SRodney W. Grimes } 13368fae3551SRodney W. Grimes } 13378fae3551SRodney W. Grimes 13388fae3551SRodney W. Grimes /* 13398fae3551SRodney W. Grimes * Traverse the binary tree either updating a node that is already there 13408fae3551SRodney W. Grimes * for the new directory or adding the new node. 13418fae3551SRodney W. Grimes */ 13428fae3551SRodney W. Grimes void 1343a62dc406SDoug Rabson add_dlist(dpp, newdp, grp, flags) 13448fae3551SRodney W. Grimes struct dirlist **dpp; 13458fae3551SRodney W. Grimes struct dirlist *newdp; 13468fae3551SRodney W. Grimes struct grouplist *grp; 1347a62dc406SDoug Rabson int flags; 13488fae3551SRodney W. Grimes { 13498fae3551SRodney W. Grimes struct dirlist *dp; 13508fae3551SRodney W. Grimes struct hostlist *hp; 13518fae3551SRodney W. Grimes int cmp; 13528fae3551SRodney W. Grimes 13538fae3551SRodney W. Grimes dp = *dpp; 13548fae3551SRodney W. Grimes if (dp) { 13558fae3551SRodney W. Grimes cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); 13568fae3551SRodney W. Grimes if (cmp > 0) { 1357a62dc406SDoug Rabson add_dlist(&dp->dp_left, newdp, grp, flags); 13588fae3551SRodney W. Grimes return; 13598fae3551SRodney W. Grimes } else if (cmp < 0) { 1360a62dc406SDoug Rabson add_dlist(&dp->dp_right, newdp, grp, flags); 13618fae3551SRodney W. Grimes return; 13628fae3551SRodney W. Grimes } else 13638fae3551SRodney W. Grimes free((caddr_t)newdp); 13648fae3551SRodney W. Grimes } else { 13658fae3551SRodney W. Grimes dp = newdp; 13668fae3551SRodney W. Grimes dp->dp_left = (struct dirlist *)NULL; 13678fae3551SRodney W. Grimes *dpp = dp; 13688fae3551SRodney W. Grimes } 13698fae3551SRodney W. Grimes if (grp) { 13708fae3551SRodney W. Grimes 13718fae3551SRodney W. Grimes /* 13728fae3551SRodney W. Grimes * Hang all of the host(s) off of the directory point. 13738fae3551SRodney W. Grimes */ 13748fae3551SRodney W. Grimes do { 13758fae3551SRodney W. Grimes hp = get_ht(); 13768fae3551SRodney W. Grimes hp->ht_grp = grp; 13778fae3551SRodney W. Grimes hp->ht_next = dp->dp_hosts; 13788fae3551SRodney W. Grimes dp->dp_hosts = hp; 13798fae3551SRodney W. Grimes grp = grp->gr_next; 13808fae3551SRodney W. Grimes } while (grp); 1381a62dc406SDoug Rabson } else { 13828fae3551SRodney W. Grimes dp->dp_flag |= DP_DEFSET; 1383a62dc406SDoug Rabson } 13848fae3551SRodney W. Grimes } 13858fae3551SRodney W. Grimes 13868fae3551SRodney W. Grimes /* 13878fae3551SRodney W. Grimes * Search for a dirpath on the export point. 13888fae3551SRodney W. Grimes */ 13898fae3551SRodney W. Grimes struct dirlist * 13908360efbdSAlfred Perlstein dirp_search(dp, dirp) 13918fae3551SRodney W. Grimes struct dirlist *dp; 13928360efbdSAlfred Perlstein char *dirp; 13938fae3551SRodney W. Grimes { 13948fae3551SRodney W. Grimes int cmp; 13958fae3551SRodney W. Grimes 13968fae3551SRodney W. Grimes if (dp) { 13978360efbdSAlfred Perlstein cmp = strcmp(dp->dp_dirp, dirp); 13988fae3551SRodney W. Grimes if (cmp > 0) 13998360efbdSAlfred Perlstein return (dirp_search(dp->dp_left, dirp)); 14008fae3551SRodney W. Grimes else if (cmp < 0) 14018360efbdSAlfred Perlstein return (dirp_search(dp->dp_right, dirp)); 14028fae3551SRodney W. Grimes else 14038fae3551SRodney W. Grimes return (dp); 14048fae3551SRodney W. Grimes } 14058fae3551SRodney W. Grimes return (dp); 14068fae3551SRodney W. Grimes } 14078fae3551SRodney W. Grimes 14088fae3551SRodney W. Grimes /* 14098fae3551SRodney W. Grimes * Scan for a host match in a directory tree. 14108fae3551SRodney W. Grimes */ 14118fae3551SRodney W. Grimes int 1412a62dc406SDoug Rabson chk_host(dp, saddr, defsetp, hostsetp) 14138fae3551SRodney W. Grimes struct dirlist *dp; 14148360efbdSAlfred Perlstein struct sockaddr *saddr; 14158fae3551SRodney W. Grimes int *defsetp; 1416a62dc406SDoug Rabson int *hostsetp; 14178fae3551SRodney W. Grimes { 14188fae3551SRodney W. Grimes struct hostlist *hp; 14198fae3551SRodney W. Grimes struct grouplist *grp; 14208360efbdSAlfred Perlstein struct addrinfo *ai; 14218fae3551SRodney W. Grimes 14228fae3551SRodney W. Grimes if (dp) { 14238fae3551SRodney W. Grimes if (dp->dp_flag & DP_DEFSET) 1424a62dc406SDoug Rabson *defsetp = dp->dp_flag; 14258fae3551SRodney W. Grimes hp = dp->dp_hosts; 14268fae3551SRodney W. Grimes while (hp) { 14278fae3551SRodney W. Grimes grp = hp->ht_grp; 14288fae3551SRodney W. Grimes switch (grp->gr_type) { 14298fae3551SRodney W. Grimes case GT_HOST: 14308360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 14318360efbdSAlfred Perlstein for (; ai; ai = ai->ai_next) { 143260caaee2SIan Dowse if (!sacmp(ai->ai_addr, saddr, NULL)) { 14338360efbdSAlfred Perlstein *hostsetp = 14348360efbdSAlfred Perlstein (hp->ht_flag | DP_HOSTSET); 14358fae3551SRodney W. Grimes return (1); 1436a62dc406SDoug Rabson } 14378fae3551SRodney W. Grimes } 14388fae3551SRodney W. Grimes break; 14398fae3551SRodney W. Grimes case GT_NET: 144060caaee2SIan Dowse if (!sacmp(saddr, (struct sockaddr *) 144160caaee2SIan Dowse &grp->gr_ptr.gt_net.nt_net, 144260caaee2SIan Dowse (struct sockaddr *) 144360caaee2SIan Dowse &grp->gr_ptr.gt_net.nt_mask)) { 1444a62dc406SDoug Rabson *hostsetp = (hp->ht_flag | DP_HOSTSET); 14458fae3551SRodney W. Grimes return (1); 1446a62dc406SDoug Rabson } 14478fae3551SRodney W. Grimes break; 144860caaee2SIan Dowse } 14498fae3551SRodney W. Grimes hp = hp->ht_next; 14508fae3551SRodney W. Grimes } 14518fae3551SRodney W. Grimes } 14528fae3551SRodney W. Grimes return (0); 14538fae3551SRodney W. Grimes } 14548fae3551SRodney W. Grimes 14558fae3551SRodney W. Grimes /* 14568fae3551SRodney W. Grimes * Scan tree for a host that matches the address. 14578fae3551SRodney W. Grimes */ 14588fae3551SRodney W. Grimes int 14598fae3551SRodney W. Grimes scan_tree(dp, saddr) 14608fae3551SRodney W. Grimes struct dirlist *dp; 14618360efbdSAlfred Perlstein struct sockaddr *saddr; 14628fae3551SRodney W. Grimes { 1463a62dc406SDoug Rabson int defset, hostset; 14648fae3551SRodney W. Grimes 14658fae3551SRodney W. Grimes if (dp) { 14668fae3551SRodney W. Grimes if (scan_tree(dp->dp_left, saddr)) 14678fae3551SRodney W. Grimes return (1); 1468a62dc406SDoug Rabson if (chk_host(dp, saddr, &defset, &hostset)) 14698fae3551SRodney W. Grimes return (1); 14708fae3551SRodney W. Grimes if (scan_tree(dp->dp_right, saddr)) 14718fae3551SRodney W. Grimes return (1); 14728fae3551SRodney W. Grimes } 14738fae3551SRodney W. Grimes return (0); 14748fae3551SRodney W. Grimes } 14758fae3551SRodney W. Grimes 14768fae3551SRodney W. Grimes /* 14778fae3551SRodney W. Grimes * Traverse the dirlist tree and free it up. 14788fae3551SRodney W. Grimes */ 14798fae3551SRodney W. Grimes void 14808fae3551SRodney W. Grimes free_dir(dp) 14818fae3551SRodney W. Grimes struct dirlist *dp; 14828fae3551SRodney W. Grimes { 14838fae3551SRodney W. Grimes 14848fae3551SRodney W. Grimes if (dp) { 14858fae3551SRodney W. Grimes free_dir(dp->dp_left); 14868fae3551SRodney W. Grimes free_dir(dp->dp_right); 14878fae3551SRodney W. Grimes free_host(dp->dp_hosts); 14888fae3551SRodney W. Grimes free((caddr_t)dp); 14898fae3551SRodney W. Grimes } 14908fae3551SRodney W. Grimes } 14918fae3551SRodney W. Grimes 14928fae3551SRodney W. Grimes /* 14938fae3551SRodney W. Grimes * Parse the option string and update fields. 14948fae3551SRodney W. Grimes * Option arguments may either be -<option>=<value> or 14958fae3551SRodney W. Grimes * -<option> <value> 14968fae3551SRodney W. Grimes */ 14978fae3551SRodney W. Grimes int 14988fae3551SRodney W. Grimes do_opt(cpp, endcpp, ep, grp, has_hostp, exflagsp, cr) 14998fae3551SRodney W. Grimes char **cpp, **endcpp; 15008fae3551SRodney W. Grimes struct exportlist *ep; 15018fae3551SRodney W. Grimes struct grouplist *grp; 15028fae3551SRodney W. Grimes int *has_hostp; 15038fae3551SRodney W. Grimes int *exflagsp; 1504c0511d3bSBrian Feldman struct xucred *cr; 15058fae3551SRodney W. Grimes { 15068fae3551SRodney W. Grimes char *cpoptarg, *cpoptend; 15078fae3551SRodney W. Grimes char *cp, *endcp, *cpopt, savedc, savedc2; 15088fae3551SRodney W. Grimes int allflag, usedarg; 15098fae3551SRodney W. Grimes 1510cb479b11SAlfred Perlstein savedc2 = '\0'; 15118fae3551SRodney W. Grimes cpopt = *cpp; 15128fae3551SRodney W. Grimes cpopt++; 15138fae3551SRodney W. Grimes cp = *endcpp; 15148fae3551SRodney W. Grimes savedc = *cp; 15158fae3551SRodney W. Grimes *cp = '\0'; 15168fae3551SRodney W. Grimes while (cpopt && *cpopt) { 15178fae3551SRodney W. Grimes allflag = 1; 15188fae3551SRodney W. Grimes usedarg = -2; 151974853402SPhilippe Charnier if ((cpoptend = strchr(cpopt, ','))) { 15208fae3551SRodney W. Grimes *cpoptend++ = '\0'; 152174853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 15228fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 15238fae3551SRodney W. Grimes } else { 152474853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 15258fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 15268fae3551SRodney W. Grimes else { 15278fae3551SRodney W. Grimes *cp = savedc; 15288fae3551SRodney W. Grimes nextfield(&cp, &endcp); 15298fae3551SRodney W. Grimes **endcpp = '\0'; 15308fae3551SRodney W. Grimes if (endcp > cp && *cp != '-') { 15318fae3551SRodney W. Grimes cpoptarg = cp; 15328fae3551SRodney W. Grimes savedc2 = *endcp; 15338fae3551SRodney W. Grimes *endcp = '\0'; 15348fae3551SRodney W. Grimes usedarg = 0; 15358fae3551SRodney W. Grimes } 15368fae3551SRodney W. Grimes } 15378fae3551SRodney W. Grimes } 15388fae3551SRodney W. Grimes if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 15398fae3551SRodney W. Grimes *exflagsp |= MNT_EXRDONLY; 15408fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "maproot") || 15418fae3551SRodney W. Grimes !(allflag = strcmp(cpopt, "mapall")) || 15428fae3551SRodney W. Grimes !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) { 15438fae3551SRodney W. Grimes usedarg++; 15448fae3551SRodney W. Grimes parsecred(cpoptarg, cr); 15458fae3551SRodney W. Grimes if (allflag == 0) { 15468fae3551SRodney W. Grimes *exflagsp |= MNT_EXPORTANON; 15478fae3551SRodney W. Grimes opt_flags |= OP_MAPALL; 15488fae3551SRodney W. Grimes } else 15498fae3551SRodney W. Grimes opt_flags |= OP_MAPROOT; 15508fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "mask") || 15518fae3551SRodney W. Grimes !strcmp(cpopt, "m"))) { 15528fae3551SRodney W. Grimes if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { 155374853402SPhilippe Charnier syslog(LOG_ERR, "bad mask: %s", cpoptarg); 15548fae3551SRodney W. Grimes return (1); 15558fae3551SRodney W. Grimes } 15568fae3551SRodney W. Grimes usedarg++; 15578fae3551SRodney W. Grimes opt_flags |= OP_MASK; 15588fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "network") || 15598fae3551SRodney W. Grimes !strcmp(cpopt, "n"))) { 15608360efbdSAlfred Perlstein if (strchr(cpoptarg, '/') != NULL) { 15618360efbdSAlfred Perlstein if (debug) 15628360efbdSAlfred Perlstein fprintf(stderr, "setting OP_MASKLEN\n"); 15638360efbdSAlfred Perlstein opt_flags |= OP_MASKLEN; 15648360efbdSAlfred Perlstein } 15658fae3551SRodney W. Grimes if (grp->gr_type != GT_NULL) { 156674853402SPhilippe Charnier syslog(LOG_ERR, "network/host conflict"); 15678fae3551SRodney W. Grimes return (1); 15688fae3551SRodney W. Grimes } else if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 0)) { 156974853402SPhilippe Charnier syslog(LOG_ERR, "bad net: %s", cpoptarg); 15708fae3551SRodney W. Grimes return (1); 15718fae3551SRodney W. Grimes } 15728fae3551SRodney W. Grimes grp->gr_type = GT_NET; 15738fae3551SRodney W. Grimes *has_hostp = 1; 15748fae3551SRodney W. Grimes usedarg++; 15758fae3551SRodney W. Grimes opt_flags |= OP_NET; 15768fae3551SRodney W. Grimes } else if (!strcmp(cpopt, "alldirs")) { 15778fae3551SRodney W. Grimes opt_flags |= OP_ALLDIRS; 1578cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "public")) { 1579cb3923e0SDoug Rabson *exflagsp |= MNT_EXPUBLIC; 1580cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "webnfs")) { 1581cb3923e0SDoug Rabson *exflagsp |= (MNT_EXPUBLIC|MNT_EXRDONLY|MNT_EXPORTANON); 1582cb3923e0SDoug Rabson opt_flags |= OP_MAPALL; 1583cb3923e0SDoug Rabson } else if (cpoptarg && !strcmp(cpopt, "index")) { 1584cb3923e0SDoug Rabson ep->ex_indexfile = strdup(cpoptarg); 1585288fa14aSJoerg Wunsch } else if (!strcmp(cpopt, "quiet")) { 1586288fa14aSJoerg Wunsch opt_flags |= OP_QUIET; 15878fae3551SRodney W. Grimes } else { 158874853402SPhilippe Charnier syslog(LOG_ERR, "bad opt %s", cpopt); 15898fae3551SRodney W. Grimes return (1); 15908fae3551SRodney W. Grimes } 15918fae3551SRodney W. Grimes if (usedarg >= 0) { 15928fae3551SRodney W. Grimes *endcp = savedc2; 15938fae3551SRodney W. Grimes **endcpp = savedc; 15948fae3551SRodney W. Grimes if (usedarg > 0) { 15958fae3551SRodney W. Grimes *cpp = cp; 15968fae3551SRodney W. Grimes *endcpp = endcp; 15978fae3551SRodney W. Grimes } 15988fae3551SRodney W. Grimes return (0); 15998fae3551SRodney W. Grimes } 16008fae3551SRodney W. Grimes cpopt = cpoptend; 16018fae3551SRodney W. Grimes } 16028fae3551SRodney W. Grimes **endcpp = savedc; 16038fae3551SRodney W. Grimes return (0); 16048fae3551SRodney W. Grimes } 16058fae3551SRodney W. Grimes 16068fae3551SRodney W. Grimes /* 16078fae3551SRodney W. Grimes * Translate a character string to the corresponding list of network 16088fae3551SRodney W. Grimes * addresses for a hostname. 16098fae3551SRodney W. Grimes */ 16108fae3551SRodney W. Grimes int 16118b5a6d67SBill Paul get_host(cp, grp, tgrp) 16128fae3551SRodney W. Grimes char *cp; 16138fae3551SRodney W. Grimes struct grouplist *grp; 16148b5a6d67SBill Paul struct grouplist *tgrp; 16158fae3551SRodney W. Grimes { 16168b5a6d67SBill Paul struct grouplist *checkgrp; 161701709abfSIan Dowse struct addrinfo *ai, *tai, hints; 16188360efbdSAlfred Perlstein int ecode; 16198360efbdSAlfred Perlstein char host[NI_MAXHOST]; 16208fae3551SRodney W. Grimes 16218360efbdSAlfred Perlstein if (grp->gr_type != GT_NULL) { 16228360efbdSAlfred Perlstein syslog(LOG_ERR, "Bad netgroup type for ip host %s", cp); 16238fae3551SRodney W. Grimes return (1); 16248fae3551SRodney W. Grimes } 16258360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 16268360efbdSAlfred Perlstein hints.ai_flags = AI_CANONNAME; 16278360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_UDP; 16288360efbdSAlfred Perlstein ecode = getaddrinfo(cp, NULL, &hints, &ai); 16298360efbdSAlfred Perlstein if (ecode != 0) { 163001709abfSIan Dowse syslog(LOG_ERR,"can't get address info for host %s", cp); 16318360efbdSAlfred Perlstein return 1; 16328fae3551SRodney W. Grimes } 16338360efbdSAlfred Perlstein grp->gr_ptr.gt_addrinfo = ai; 16348360efbdSAlfred Perlstein while (ai != NULL) { 16358360efbdSAlfred Perlstein if (ai->ai_canonname == NULL) { 16368360efbdSAlfred Perlstein if (getnameinfo(ai->ai_addr, ai->ai_addrlen, host, 16378360efbdSAlfred Perlstein sizeof host, NULL, 0, ninumeric) != 0) 16388360efbdSAlfred Perlstein strlcpy(host, "?", sizeof(host)); 16398360efbdSAlfred Perlstein ai->ai_canonname = strdup(host); 16408360efbdSAlfred Perlstein ai->ai_flags |= AI_CANONNAME; 16416d359f31SIan Dowse } 16428fae3551SRodney W. Grimes if (debug) 164301709abfSIan Dowse fprintf(stderr, "got host %s\n", ai->ai_canonname); 164401709abfSIan Dowse /* 164501709abfSIan Dowse * Sanity check: make sure we don't already have an entry 164601709abfSIan Dowse * for this host in the grouplist. 164701709abfSIan Dowse */ 164801709abfSIan Dowse for (checkgrp = tgrp; checkgrp != NULL; 164901709abfSIan Dowse checkgrp = checkgrp->gr_next) { 165001709abfSIan Dowse if (checkgrp->gr_type != GT_HOST) 165101709abfSIan Dowse continue; 165201709abfSIan Dowse for (tai = checkgrp->gr_ptr.gt_addrinfo; tai != NULL; 165301709abfSIan Dowse tai = tai->ai_next) { 165460caaee2SIan Dowse if (sacmp(tai->ai_addr, ai->ai_addr, NULL) != 0) 165501709abfSIan Dowse continue; 165601709abfSIan Dowse if (debug) 165701709abfSIan Dowse fprintf(stderr, 165801709abfSIan Dowse "ignoring duplicate host %s\n", 165901709abfSIan Dowse ai->ai_canonname); 166001709abfSIan Dowse grp->gr_type = GT_IGNORE; 166101709abfSIan Dowse return (0); 166201709abfSIan Dowse } 166301709abfSIan Dowse } 16648360efbdSAlfred Perlstein ai = ai->ai_next; 16658360efbdSAlfred Perlstein } 166601709abfSIan Dowse grp->gr_type = GT_HOST; 16678fae3551SRodney W. Grimes return (0); 16688fae3551SRodney W. Grimes } 16698fae3551SRodney W. Grimes 16708fae3551SRodney W. Grimes /* 16718fae3551SRodney W. Grimes * Free up an exports list component 16728fae3551SRodney W. Grimes */ 16738fae3551SRodney W. Grimes void 16748fae3551SRodney W. Grimes free_exp(ep) 16758fae3551SRodney W. Grimes struct exportlist *ep; 16768fae3551SRodney W. Grimes { 16778fae3551SRodney W. Grimes 16788fae3551SRodney W. Grimes if (ep->ex_defdir) { 16798fae3551SRodney W. Grimes free_host(ep->ex_defdir->dp_hosts); 16808fae3551SRodney W. Grimes free((caddr_t)ep->ex_defdir); 16818fae3551SRodney W. Grimes } 16828fae3551SRodney W. Grimes if (ep->ex_fsdir) 16838fae3551SRodney W. Grimes free(ep->ex_fsdir); 1684cb3923e0SDoug Rabson if (ep->ex_indexfile) 1685cb3923e0SDoug Rabson free(ep->ex_indexfile); 16868fae3551SRodney W. Grimes free_dir(ep->ex_dirl); 16878fae3551SRodney W. Grimes free((caddr_t)ep); 16888fae3551SRodney W. Grimes } 16898fae3551SRodney W. Grimes 16908fae3551SRodney W. Grimes /* 16918fae3551SRodney W. Grimes * Free hosts. 16928fae3551SRodney W. Grimes */ 16938fae3551SRodney W. Grimes void 16948fae3551SRodney W. Grimes free_host(hp) 16958fae3551SRodney W. Grimes struct hostlist *hp; 16968fae3551SRodney W. Grimes { 16978fae3551SRodney W. Grimes struct hostlist *hp2; 16988fae3551SRodney W. Grimes 16998fae3551SRodney W. Grimes while (hp) { 17008fae3551SRodney W. Grimes hp2 = hp; 17018fae3551SRodney W. Grimes hp = hp->ht_next; 17028fae3551SRodney W. Grimes free((caddr_t)hp2); 17038fae3551SRodney W. Grimes } 17048fae3551SRodney W. Grimes } 17058fae3551SRodney W. Grimes 17068fae3551SRodney W. Grimes struct hostlist * 17078fae3551SRodney W. Grimes get_ht() 17088fae3551SRodney W. Grimes { 17098fae3551SRodney W. Grimes struct hostlist *hp; 17108fae3551SRodney W. Grimes 17118fae3551SRodney W. Grimes hp = (struct hostlist *)malloc(sizeof (struct hostlist)); 17128fae3551SRodney W. Grimes if (hp == (struct hostlist *)NULL) 17138fae3551SRodney W. Grimes out_of_mem(); 17148fae3551SRodney W. Grimes hp->ht_next = (struct hostlist *)NULL; 1715a62dc406SDoug Rabson hp->ht_flag = 0; 17168fae3551SRodney W. Grimes return (hp); 17178fae3551SRodney W. Grimes } 17188fae3551SRodney W. Grimes 17198fae3551SRodney W. Grimes /* 17208fae3551SRodney W. Grimes * Out of memory, fatal 17218fae3551SRodney W. Grimes */ 17228fae3551SRodney W. Grimes void 17238fae3551SRodney W. Grimes out_of_mem() 17248fae3551SRodney W. Grimes { 17258fae3551SRodney W. Grimes 172674853402SPhilippe Charnier syslog(LOG_ERR, "out of memory"); 17278fae3551SRodney W. Grimes exit(2); 17288fae3551SRodney W. Grimes } 17298fae3551SRodney W. Grimes 17308fae3551SRodney W. Grimes /* 17318fae3551SRodney W. Grimes * Do the mount syscall with the update flag to push the export info into 17328fae3551SRodney W. Grimes * the kernel. 17338fae3551SRodney W. Grimes */ 17348fae3551SRodney W. Grimes int 17358fae3551SRodney W. Grimes do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb) 17368fae3551SRodney W. Grimes struct exportlist *ep; 17378fae3551SRodney W. Grimes struct grouplist *grp; 17388fae3551SRodney W. Grimes int exflags; 1739c0511d3bSBrian Feldman struct xucred *anoncrp; 17408fae3551SRodney W. Grimes char *dirp; 17418fae3551SRodney W. Grimes int dirplen; 17428fae3551SRodney W. Grimes struct statfs *fsb; 17438fae3551SRodney W. Grimes { 1744f93caef2SIan Dowse struct statfs fsb1; 17458360efbdSAlfred Perlstein struct addrinfo *ai; 174660caaee2SIan Dowse struct export_args *eap; 17478360efbdSAlfred Perlstein char *cp = NULL; 17488fae3551SRodney W. Grimes int done; 17498fae3551SRodney W. Grimes char savedc = '\0'; 17508fae3551SRodney W. Grimes union { 17518fae3551SRodney W. Grimes struct ufs_args ua; 17528fae3551SRodney W. Grimes struct iso_args ia; 1753a62dc406SDoug Rabson struct msdosfs_args da; 17549300c696SSemen Ustimenko struct ntfs_args na; 17558fae3551SRodney W. Grimes } args; 17568fae3551SRodney W. Grimes 175760caaee2SIan Dowse bzero(&args, sizeof args); 175860caaee2SIan Dowse /* XXX, we assume that all xx_args look like ufs_args. */ 17598fae3551SRodney W. Grimes args.ua.fspec = 0; 176060caaee2SIan Dowse eap = &args.ua.export; 176160caaee2SIan Dowse 176260caaee2SIan Dowse eap->ex_flags = exflags; 176360caaee2SIan Dowse eap->ex_anon = *anoncrp; 176460caaee2SIan Dowse eap->ex_indexfile = ep->ex_indexfile; 17656d359f31SIan Dowse if (grp->gr_type == GT_HOST) 17668360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 17676d359f31SIan Dowse else 17686d359f31SIan Dowse ai = NULL; 17698fae3551SRodney W. Grimes done = FALSE; 17708fae3551SRodney W. Grimes while (!done) { 17718fae3551SRodney W. Grimes switch (grp->gr_type) { 17728fae3551SRodney W. Grimes case GT_HOST: 17736d359f31SIan Dowse if (ai->ai_addr->sa_family == AF_INET6 && have_v6 == 0) 17748360efbdSAlfred Perlstein goto skip; 177560caaee2SIan Dowse eap->ex_addr = ai->ai_addr; 177660caaee2SIan Dowse eap->ex_addrlen = ai->ai_addrlen; 177760caaee2SIan Dowse eap->ex_masklen = 0; 17788fae3551SRodney W. Grimes break; 17798fae3551SRodney W. Grimes case GT_NET: 178060caaee2SIan Dowse if (grp->gr_ptr.gt_net.nt_net.ss_family == AF_INET6 && 17818360efbdSAlfred Perlstein have_v6 == 0) 17828360efbdSAlfred Perlstein goto skip; 178360caaee2SIan Dowse eap->ex_addr = 178460caaee2SIan Dowse (struct sockaddr *)&grp->gr_ptr.gt_net.nt_net; 178560caaee2SIan Dowse eap->ex_addrlen = args.ua.export.ex_addr->sa_len; 178660caaee2SIan Dowse eap->ex_mask = 178760caaee2SIan Dowse (struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask; 178860caaee2SIan Dowse eap->ex_masklen = args.ua.export.ex_mask->sa_len; 17898fae3551SRodney W. Grimes break; 17906d359f31SIan Dowse case GT_DEFAULT: 179160caaee2SIan Dowse eap->ex_addr = NULL; 179260caaee2SIan Dowse eap->ex_addrlen = 0; 179360caaee2SIan Dowse eap->ex_mask = NULL; 179460caaee2SIan Dowse eap->ex_masklen = 0; 17956d359f31SIan Dowse break; 17968b5a6d67SBill Paul case GT_IGNORE: 17978b5a6d67SBill Paul return(0); 17988b5a6d67SBill Paul break; 17998fae3551SRodney W. Grimes default: 180074853402SPhilippe Charnier syslog(LOG_ERR, "bad grouptype"); 18018fae3551SRodney W. Grimes if (cp) 18028fae3551SRodney W. Grimes *cp = savedc; 18038fae3551SRodney W. Grimes return (1); 18048fae3551SRodney W. Grimes }; 18058fae3551SRodney W. Grimes 18068fae3551SRodney W. Grimes /* 18078fae3551SRodney W. Grimes * XXX: 18088fae3551SRodney W. Grimes * Maybe I should just use the fsb->f_mntonname path instead 18098fae3551SRodney W. Grimes * of looping back up the dirp to the mount point?? 18108fae3551SRodney W. Grimes * Also, needs to know how to export all types of local 181187564113SPeter Wemm * exportable filesystems and not just "ufs". 18128fae3551SRodney W. Grimes */ 1813a62dc406SDoug Rabson while (mount(fsb->f_fstypename, dirp, 18148fae3551SRodney W. Grimes fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) { 18158fae3551SRodney W. Grimes if (cp) 18168fae3551SRodney W. Grimes *cp-- = savedc; 18178fae3551SRodney W. Grimes else 18188fae3551SRodney W. Grimes cp = dirp + dirplen - 1; 1819288fa14aSJoerg Wunsch if (opt_flags & OP_QUIET) 1820288fa14aSJoerg Wunsch return (1); 18218fae3551SRodney W. Grimes if (errno == EPERM) { 182201709abfSIan Dowse if (debug) 182301709abfSIan Dowse warnx("can't change attributes for %s", 182401709abfSIan Dowse dirp); 18258fae3551SRodney W. Grimes syslog(LOG_ERR, 182674853402SPhilippe Charnier "can't change attributes for %s", dirp); 18278fae3551SRodney W. Grimes return (1); 18288fae3551SRodney W. Grimes } 18298fae3551SRodney W. Grimes if (opt_flags & OP_ALLDIRS) { 1830288fa14aSJoerg Wunsch if (errno == EINVAL) 1831288fa14aSJoerg Wunsch syslog(LOG_ERR, 1832288fa14aSJoerg Wunsch "-alldirs requested but %s is not a filesystem mountpoint", 1833288fa14aSJoerg Wunsch dirp); 1834288fa14aSJoerg Wunsch else 1835288fa14aSJoerg Wunsch syslog(LOG_ERR, 1836288fa14aSJoerg Wunsch "could not remount %s: %m", 18373980ac4fSGarrett Wollman dirp); 18388fae3551SRodney W. Grimes return (1); 18398fae3551SRodney W. Grimes } 18408fae3551SRodney W. Grimes /* back up over the last component */ 18418fae3551SRodney W. Grimes while (*cp == '/' && cp > dirp) 18428fae3551SRodney W. Grimes cp--; 18438fae3551SRodney W. Grimes while (*(cp - 1) != '/' && cp > dirp) 18448fae3551SRodney W. Grimes cp--; 18458fae3551SRodney W. Grimes if (cp == dirp) { 18468fae3551SRodney W. Grimes if (debug) 184774853402SPhilippe Charnier warnx("mnt unsucc"); 184874853402SPhilippe Charnier syslog(LOG_ERR, "can't export %s", dirp); 18498fae3551SRodney W. Grimes return (1); 18508fae3551SRodney W. Grimes } 18518fae3551SRodney W. Grimes savedc = *cp; 18528fae3551SRodney W. Grimes *cp = '\0'; 1853f93caef2SIan Dowse /* Check that we're still on the same filesystem. */ 1854f93caef2SIan Dowse if (statfs(dirp, &fsb1) != 0 || bcmp(&fsb1.f_fsid, 1855f93caef2SIan Dowse &fsb->f_fsid, sizeof(fsb1.f_fsid)) != 0) { 1856f93caef2SIan Dowse *cp = savedc; 1857f93caef2SIan Dowse syslog(LOG_ERR, "can't export %s", dirp); 1858f93caef2SIan Dowse return (1); 1859f93caef2SIan Dowse } 18608fae3551SRodney W. Grimes } 18618360efbdSAlfred Perlstein skip: 18626d359f31SIan Dowse if (ai != NULL) 18638360efbdSAlfred Perlstein ai = ai->ai_next; 18648360efbdSAlfred Perlstein if (ai == NULL) 18658fae3551SRodney W. Grimes done = TRUE; 18668fae3551SRodney W. Grimes } 18678fae3551SRodney W. Grimes if (cp) 18688fae3551SRodney W. Grimes *cp = savedc; 18698fae3551SRodney W. Grimes return (0); 18708fae3551SRodney W. Grimes } 18718fae3551SRodney W. Grimes 18728fae3551SRodney W. Grimes /* 18738fae3551SRodney W. Grimes * Translate a net address. 187460caaee2SIan Dowse * 187560caaee2SIan Dowse * If `maskflg' is nonzero, then `cp' is a netmask, not a network address. 18768fae3551SRodney W. Grimes */ 18778fae3551SRodney W. Grimes int 18788fae3551SRodney W. Grimes get_net(cp, net, maskflg) 18798fae3551SRodney W. Grimes char *cp; 18808fae3551SRodney W. Grimes struct netmsk *net; 18818fae3551SRodney W. Grimes int maskflg; 18828fae3551SRodney W. Grimes { 1883931c04f1SIan Dowse struct netent *np = NULL; 18848360efbdSAlfred Perlstein char *name, *p, *prefp; 188560caaee2SIan Dowse struct sockaddr_in sin; 1886931c04f1SIan Dowse struct sockaddr *sa = NULL; 18878360efbdSAlfred Perlstein struct addrinfo hints, *ai = NULL; 18888360efbdSAlfred Perlstein char netname[NI_MAXHOST]; 18898360efbdSAlfred Perlstein long preflen; 18908fae3551SRodney W. Grimes 189101709abfSIan Dowse p = prefp = NULL; 18928360efbdSAlfred Perlstein if ((opt_flags & OP_MASKLEN) && !maskflg) { 18938360efbdSAlfred Perlstein p = strchr(cp, '/'); 18948360efbdSAlfred Perlstein *p = '\0'; 18958360efbdSAlfred Perlstein prefp = p + 1; 18968360efbdSAlfred Perlstein } 18978360efbdSAlfred Perlstein 1898931c04f1SIan Dowse /* 1899931c04f1SIan Dowse * Check for a numeric address first. We wish to avoid 1900931c04f1SIan Dowse * possible DNS lookups in getnetbyname(). 1901931c04f1SIan Dowse */ 1902931c04f1SIan Dowse if (isxdigit(*cp) || *cp == ':') { 19038360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 190460caaee2SIan Dowse /* Ensure the mask and the network have the same family. */ 190560caaee2SIan Dowse if (maskflg && (opt_flags & OP_NET)) 190660caaee2SIan Dowse hints.ai_family = net->nt_net.ss_family; 190760caaee2SIan Dowse else if (!maskflg && (opt_flags & OP_HAVEMASK)) 190860caaee2SIan Dowse hints.ai_family = net->nt_mask.ss_family; 190960caaee2SIan Dowse else 19108360efbdSAlfred Perlstein hints.ai_family = AF_UNSPEC; 19118360efbdSAlfred Perlstein hints.ai_flags = AI_NUMERICHOST; 1912931c04f1SIan Dowse if (getaddrinfo(cp, NULL, &hints, &ai) == 0) 1913931c04f1SIan Dowse sa = ai->ai_addr; 1914931c04f1SIan Dowse if (sa != NULL && ai->ai_family == AF_INET) { 19158fae3551SRodney W. Grimes /* 191660caaee2SIan Dowse * The address in `cp' is really a network address, so 191760caaee2SIan Dowse * use inet_network() to re-interpret this correctly. 191860caaee2SIan Dowse * e.g. "127.1" means 127.1.0.0, not 127.0.0.1. 19198fae3551SRodney W. Grimes */ 192060caaee2SIan Dowse bzero(&sin, sizeof sin); 19218360efbdSAlfred Perlstein sin.sin_family = AF_INET; 19228360efbdSAlfred Perlstein sin.sin_len = sizeof sin; 19238360efbdSAlfred Perlstein sin.sin_addr = inet_makeaddr(inet_network(cp), 0); 19248360efbdSAlfred Perlstein if (debug) 192560caaee2SIan Dowse fprintf(stderr, "get_net: v4 addr %s\n", 192660caaee2SIan Dowse inet_ntoa(sin.sin_addr)); 19278360efbdSAlfred Perlstein sa = (struct sockaddr *)&sin; 1928931c04f1SIan Dowse } 1929931c04f1SIan Dowse } 1930931c04f1SIan Dowse if (sa == NULL && (np = getnetbyname(cp)) != NULL) { 1931931c04f1SIan Dowse bzero(&sin, sizeof sin); 1932931c04f1SIan Dowse sin.sin_family = AF_INET; 1933931c04f1SIan Dowse sin.sin_len = sizeof sin; 1934931c04f1SIan Dowse sin.sin_addr = inet_makeaddr(np->n_net, 0); 1935931c04f1SIan Dowse sa = (struct sockaddr *)&sin; 1936931c04f1SIan Dowse } 1937931c04f1SIan Dowse if (sa == NULL) 19388360efbdSAlfred Perlstein goto fail; 19398360efbdSAlfred Perlstein 194060caaee2SIan Dowse if (maskflg) { 194160caaee2SIan Dowse /* The specified sockaddr is a mask. */ 194260caaee2SIan Dowse if (checkmask(sa) != 0) 19438360efbdSAlfred Perlstein goto fail; 194460caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 194560caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 194660caaee2SIan Dowse } else { 194760caaee2SIan Dowse /* The specified sockaddr is a network address. */ 194860caaee2SIan Dowse bcopy(sa, &net->nt_net, sa->sa_len); 19490f4b7baaSPaul Traina 195060caaee2SIan Dowse /* Get a network name for the export list. */ 195160caaee2SIan Dowse if (np) { 195260caaee2SIan Dowse name = np->n_name; 195360caaee2SIan Dowse } else if (getnameinfo(sa, sa->sa_len, netname, sizeof netname, 195460caaee2SIan Dowse NULL, 0, ninumeric) == 0) { 195560caaee2SIan Dowse name = netname; 195660caaee2SIan Dowse } else { 195760caaee2SIan Dowse goto fail; 195860caaee2SIan Dowse } 195960caaee2SIan Dowse if ((net->nt_name = strdup(name)) == NULL) 196060caaee2SIan Dowse out_of_mem(); 196160caaee2SIan Dowse 196260caaee2SIan Dowse /* 196360caaee2SIan Dowse * Extract a mask from either a "/<masklen>" suffix, or 196460caaee2SIan Dowse * from the class of an IPv4 address. 196560caaee2SIan Dowse */ 19668360efbdSAlfred Perlstein if (opt_flags & OP_MASKLEN) { 19678360efbdSAlfred Perlstein preflen = strtol(prefp, NULL, 10); 196860caaee2SIan Dowse if (preflen < 0L || preflen == LONG_MAX) 19698360efbdSAlfred Perlstein goto fail; 197060caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 197160caaee2SIan Dowse if (makemask(&net->nt_mask, (int)preflen) != 0) 197260caaee2SIan Dowse goto fail; 197360caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 19748360efbdSAlfred Perlstein *p = '/'; 197560caaee2SIan Dowse } else if (sa->sa_family == AF_INET && 197660caaee2SIan Dowse (opt_flags & OP_MASK) == 0) { 197760caaee2SIan Dowse in_addr_t addr; 19788360efbdSAlfred Perlstein 197960caaee2SIan Dowse addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; 198060caaee2SIan Dowse if (IN_CLASSA(addr)) 198160caaee2SIan Dowse preflen = 8; 198260caaee2SIan Dowse else if (IN_CLASSB(addr)) 198360caaee2SIan Dowse preflen = 16; 198460caaee2SIan Dowse else if (IN_CLASSC(addr)) 198560caaee2SIan Dowse preflen = 24; 198660caaee2SIan Dowse else if (IN_CLASSD(addr)) 198760caaee2SIan Dowse preflen = 28; 19888360efbdSAlfred Perlstein else 198960caaee2SIan Dowse preflen = 32; /* XXX */ 199060caaee2SIan Dowse 199160caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 199260caaee2SIan Dowse makemask(&net->nt_mask, (int)preflen); 199360caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 199460caaee2SIan Dowse } 19958360efbdSAlfred Perlstein } 19968360efbdSAlfred Perlstein 19978360efbdSAlfred Perlstein if (ai) 19988360efbdSAlfred Perlstein freeaddrinfo(ai); 19998360efbdSAlfred Perlstein return 0; 20008360efbdSAlfred Perlstein 20018360efbdSAlfred Perlstein fail: 20028360efbdSAlfred Perlstein if (ai) 20038360efbdSAlfred Perlstein freeaddrinfo(ai); 20048360efbdSAlfred Perlstein return 1; 20058fae3551SRodney W. Grimes } 20068fae3551SRodney W. Grimes 20078fae3551SRodney W. Grimes /* 20088fae3551SRodney W. Grimes * Parse out the next white space separated field 20098fae3551SRodney W. Grimes */ 20108fae3551SRodney W. Grimes void 20118fae3551SRodney W. Grimes nextfield(cp, endcp) 20128fae3551SRodney W. Grimes char **cp; 20138fae3551SRodney W. Grimes char **endcp; 20148fae3551SRodney W. Grimes { 20158fae3551SRodney W. Grimes char *p; 20168fae3551SRodney W. Grimes 20178fae3551SRodney W. Grimes p = *cp; 20188fae3551SRodney W. Grimes while (*p == ' ' || *p == '\t') 20198fae3551SRodney W. Grimes p++; 20208fae3551SRodney W. Grimes if (*p == '\n' || *p == '\0') 20218fae3551SRodney W. Grimes *cp = *endcp = p; 20228fae3551SRodney W. Grimes else { 20238fae3551SRodney W. Grimes *cp = p++; 20248fae3551SRodney W. Grimes while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 20258fae3551SRodney W. Grimes p++; 20268fae3551SRodney W. Grimes *endcp = p; 20278fae3551SRodney W. Grimes } 20288fae3551SRodney W. Grimes } 20298fae3551SRodney W. Grimes 20308fae3551SRodney W. Grimes /* 20318fae3551SRodney W. Grimes * Get an exports file line. Skip over blank lines and handle line 20328fae3551SRodney W. Grimes * continuations. 20338fae3551SRodney W. Grimes */ 20348fae3551SRodney W. Grimes int 20358fae3551SRodney W. Grimes get_line() 20368fae3551SRodney W. Grimes { 20378fae3551SRodney W. Grimes char *p, *cp; 203891ca1a91SIan Dowse size_t len; 20398fae3551SRodney W. Grimes int totlen, cont_line; 20408fae3551SRodney W. Grimes 20418fae3551SRodney W. Grimes /* 20428fae3551SRodney W. Grimes * Loop around ignoring blank lines and getting all continuation lines. 20438fae3551SRodney W. Grimes */ 20448fae3551SRodney W. Grimes p = line; 20458fae3551SRodney W. Grimes totlen = 0; 20468fae3551SRodney W. Grimes do { 204791ca1a91SIan Dowse if ((p = fgetln(exp_file, &len)) == NULL) 20488fae3551SRodney W. Grimes return (0); 20498fae3551SRodney W. Grimes cp = p + len - 1; 20508fae3551SRodney W. Grimes cont_line = 0; 20518fae3551SRodney W. Grimes while (cp >= p && 20528fae3551SRodney W. Grimes (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '\\')) { 20538fae3551SRodney W. Grimes if (*cp == '\\') 20548fae3551SRodney W. Grimes cont_line = 1; 20558fae3551SRodney W. Grimes cp--; 20568fae3551SRodney W. Grimes len--; 20578fae3551SRodney W. Grimes } 2058376f8390SDima Dorfman if (cont_line) { 2059376f8390SDima Dorfman *++cp = ' '; 2060376f8390SDima Dorfman len++; 2061376f8390SDima Dorfman } 206291ca1a91SIan Dowse if (linesize < len + totlen + 1) { 206391ca1a91SIan Dowse linesize = len + totlen + 1; 206491ca1a91SIan Dowse line = realloc(line, linesize); 206591ca1a91SIan Dowse if (line == NULL) 206691ca1a91SIan Dowse out_of_mem(); 206791ca1a91SIan Dowse } 206891ca1a91SIan Dowse memcpy(line + totlen, p, len); 20698fae3551SRodney W. Grimes totlen += len; 207091ca1a91SIan Dowse line[totlen] = '\0'; 20718fae3551SRodney W. Grimes } while (totlen == 0 || cont_line); 20728fae3551SRodney W. Grimes return (1); 20738fae3551SRodney W. Grimes } 20748fae3551SRodney W. Grimes 20758fae3551SRodney W. Grimes /* 20768fae3551SRodney W. Grimes * Parse a description of a credential. 20778fae3551SRodney W. Grimes */ 20788fae3551SRodney W. Grimes void 20798fae3551SRodney W. Grimes parsecred(namelist, cr) 20808fae3551SRodney W. Grimes char *namelist; 2081c0511d3bSBrian Feldman struct xucred *cr; 20828fae3551SRodney W. Grimes { 20838fae3551SRodney W. Grimes char *name; 20848fae3551SRodney W. Grimes int cnt; 20858fae3551SRodney W. Grimes char *names; 20868fae3551SRodney W. Grimes struct passwd *pw; 20878fae3551SRodney W. Grimes struct group *gr; 20888fae3551SRodney W. Grimes int ngroups, groups[NGROUPS + 1]; 20898fae3551SRodney W. Grimes 209076183f34SDima Dorfman cr->cr_version = XUCRED_VERSION; 20918fae3551SRodney W. Grimes /* 209274853402SPhilippe Charnier * Set up the unprivileged user. 20938fae3551SRodney W. Grimes */ 20948fae3551SRodney W. Grimes cr->cr_uid = -2; 20958fae3551SRodney W. Grimes cr->cr_groups[0] = -2; 20968fae3551SRodney W. Grimes cr->cr_ngroups = 1; 20978fae3551SRodney W. Grimes /* 20988fae3551SRodney W. Grimes * Get the user's password table entry. 20998fae3551SRodney W. Grimes */ 21008fae3551SRodney W. Grimes names = strsep(&namelist, " \t\n"); 21018fae3551SRodney W. Grimes name = strsep(&names, ":"); 21028fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') 21038fae3551SRodney W. Grimes pw = getpwuid(atoi(name)); 21048fae3551SRodney W. Grimes else 21058fae3551SRodney W. Grimes pw = getpwnam(name); 21068fae3551SRodney W. Grimes /* 21078fae3551SRodney W. Grimes * Credentials specified as those of a user. 21088fae3551SRodney W. Grimes */ 21098fae3551SRodney W. Grimes if (names == NULL) { 21108fae3551SRodney W. Grimes if (pw == NULL) { 211174853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 21128fae3551SRodney W. Grimes return; 21138fae3551SRodney W. Grimes } 21148fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 21158fae3551SRodney W. Grimes ngroups = NGROUPS + 1; 21168fae3551SRodney W. Grimes if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) 211774853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 21188fae3551SRodney W. Grimes /* 21198fae3551SRodney W. Grimes * Convert from int's to gid_t's and compress out duplicate 21208fae3551SRodney W. Grimes */ 21218fae3551SRodney W. Grimes cr->cr_ngroups = ngroups - 1; 21228fae3551SRodney W. Grimes cr->cr_groups[0] = groups[0]; 21238fae3551SRodney W. Grimes for (cnt = 2; cnt < ngroups; cnt++) 21248fae3551SRodney W. Grimes cr->cr_groups[cnt - 1] = groups[cnt]; 21258fae3551SRodney W. Grimes return; 21268fae3551SRodney W. Grimes } 21278fae3551SRodney W. Grimes /* 21288fae3551SRodney W. Grimes * Explicit credential specified as a colon separated list: 21298fae3551SRodney W. Grimes * uid:gid:gid:... 21308fae3551SRodney W. Grimes */ 21318fae3551SRodney W. Grimes if (pw != NULL) 21328fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 21338fae3551SRodney W. Grimes else if (isdigit(*name) || *name == '-') 21348fae3551SRodney W. Grimes cr->cr_uid = atoi(name); 21358fae3551SRodney W. Grimes else { 213674853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 21378fae3551SRodney W. Grimes return; 21388fae3551SRodney W. Grimes } 21398fae3551SRodney W. Grimes cr->cr_ngroups = 0; 21408fae3551SRodney W. Grimes while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { 21418fae3551SRodney W. Grimes name = strsep(&names, ":"); 21428fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') { 21438fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = atoi(name); 21448fae3551SRodney W. Grimes } else { 21458fae3551SRodney W. Grimes if ((gr = getgrnam(name)) == NULL) { 214674853402SPhilippe Charnier syslog(LOG_ERR, "unknown group: %s", name); 21478fae3551SRodney W. Grimes continue; 21488fae3551SRodney W. Grimes } 21498fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; 21508fae3551SRodney W. Grimes } 21518fae3551SRodney W. Grimes } 21528fae3551SRodney W. Grimes if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) 215374853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 21548fae3551SRodney W. Grimes } 21558fae3551SRodney W. Grimes 21568fae3551SRodney W. Grimes #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 21578fae3551SRodney W. Grimes /* 21588fae3551SRodney W. Grimes * Routines that maintain the remote mounttab 21598fae3551SRodney W. Grimes */ 21608fae3551SRodney W. Grimes void 21618fae3551SRodney W. Grimes get_mountlist() 21628fae3551SRodney W. Grimes { 21638fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 216487564113SPeter Wemm char *host, *dirp, *cp; 21658fae3551SRodney W. Grimes char str[STRSIZ]; 21668fae3551SRodney W. Grimes FILE *mlfile; 21678fae3551SRodney W. Grimes 21688fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) { 216939539916SBill Fumerola if (errno == ENOENT) 217039539916SBill Fumerola return; 217139539916SBill Fumerola else { 217274853402SPhilippe Charnier syslog(LOG_ERR, "can't open %s", _PATH_RMOUNTLIST); 21738fae3551SRodney W. Grimes return; 21748fae3551SRodney W. Grimes } 217539539916SBill Fumerola } 21768fae3551SRodney W. Grimes mlpp = &mlhead; 21778fae3551SRodney W. Grimes while (fgets(str, STRSIZ, mlfile) != NULL) { 217887564113SPeter Wemm cp = str; 217987564113SPeter Wemm host = strsep(&cp, " \t\n"); 218087564113SPeter Wemm dirp = strsep(&cp, " \t\n"); 218187564113SPeter Wemm if (host == NULL || dirp == NULL) 21828fae3551SRodney W. Grimes continue; 21838fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 218474853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 218574853402SPhilippe Charnier out_of_mem(); 218687564113SPeter Wemm strncpy(mlp->ml_host, host, RPCMNT_NAMELEN); 218787564113SPeter Wemm mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 218887564113SPeter Wemm strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 218987564113SPeter Wemm mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 21908fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 21918fae3551SRodney W. Grimes *mlpp = mlp; 21928fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 21938fae3551SRodney W. Grimes } 21948fae3551SRodney W. Grimes fclose(mlfile); 21958fae3551SRodney W. Grimes } 21968fae3551SRodney W. Grimes 219701709abfSIan Dowse void 219801709abfSIan Dowse del_mlist(char *hostp, char *dirp) 21998fae3551SRodney W. Grimes { 22008fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 22018fae3551SRodney W. Grimes struct mountlist *mlp2; 22028fae3551SRodney W. Grimes FILE *mlfile; 22038fae3551SRodney W. Grimes int fnd = 0; 22048fae3551SRodney W. Grimes 22058fae3551SRodney W. Grimes mlpp = &mlhead; 22068fae3551SRodney W. Grimes mlp = mlhead; 22078fae3551SRodney W. Grimes while (mlp) { 22088fae3551SRodney W. Grimes if (!strcmp(mlp->ml_host, hostp) && 22098fae3551SRodney W. Grimes (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 22108fae3551SRodney W. Grimes fnd = 1; 22118fae3551SRodney W. Grimes mlp2 = mlp; 22128fae3551SRodney W. Grimes *mlpp = mlp = mlp->ml_next; 22138fae3551SRodney W. Grimes free((caddr_t)mlp2); 22148fae3551SRodney W. Grimes } else { 22158fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 22168fae3551SRodney W. Grimes mlp = mlp->ml_next; 22178fae3551SRodney W. Grimes } 22188fae3551SRodney W. Grimes } 22198fae3551SRodney W. Grimes if (fnd) { 22208fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 222174853402SPhilippe Charnier syslog(LOG_ERR,"can't update %s", _PATH_RMOUNTLIST); 22228fae3551SRodney W. Grimes return; 22238fae3551SRodney W. Grimes } 22248fae3551SRodney W. Grimes mlp = mlhead; 22258fae3551SRodney W. Grimes while (mlp) { 22268fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 22278fae3551SRodney W. Grimes mlp = mlp->ml_next; 22288fae3551SRodney W. Grimes } 22298fae3551SRodney W. Grimes fclose(mlfile); 22308fae3551SRodney W. Grimes } 22318fae3551SRodney W. Grimes } 22328fae3551SRodney W. Grimes 22338fae3551SRodney W. Grimes void 22348fae3551SRodney W. Grimes add_mlist(hostp, dirp) 22358fae3551SRodney W. Grimes char *hostp, *dirp; 22368fae3551SRodney W. Grimes { 22378fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 22388fae3551SRodney W. Grimes FILE *mlfile; 22398fae3551SRodney W. Grimes 22408fae3551SRodney W. Grimes mlpp = &mlhead; 22418fae3551SRodney W. Grimes mlp = mlhead; 22428fae3551SRodney W. Grimes while (mlp) { 22438fae3551SRodney W. Grimes if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 22448fae3551SRodney W. Grimes return; 22458fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 22468fae3551SRodney W. Grimes mlp = mlp->ml_next; 22478fae3551SRodney W. Grimes } 22488fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 224974853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 225074853402SPhilippe Charnier out_of_mem(); 22518fae3551SRodney W. Grimes strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 22528fae3551SRodney W. Grimes mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 22538fae3551SRodney W. Grimes strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 22548fae3551SRodney W. Grimes mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 22558fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 22568fae3551SRodney W. Grimes *mlpp = mlp; 22578fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 225874853402SPhilippe Charnier syslog(LOG_ERR, "can't update %s", _PATH_RMOUNTLIST); 22598fae3551SRodney W. Grimes return; 22608fae3551SRodney W. Grimes } 22618fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 22628fae3551SRodney W. Grimes fclose(mlfile); 22638fae3551SRodney W. Grimes } 22648fae3551SRodney W. Grimes 22658fae3551SRodney W. Grimes /* 22668fae3551SRodney W. Grimes * Free up a group list. 22678fae3551SRodney W. Grimes */ 22688fae3551SRodney W. Grimes void 22698fae3551SRodney W. Grimes free_grp(grp) 22708fae3551SRodney W. Grimes struct grouplist *grp; 22718fae3551SRodney W. Grimes { 22728fae3551SRodney W. Grimes if (grp->gr_type == GT_HOST) { 22738360efbdSAlfred Perlstein if (grp->gr_ptr.gt_addrinfo != NULL) 22748360efbdSAlfred Perlstein freeaddrinfo(grp->gr_ptr.gt_addrinfo); 22758fae3551SRodney W. Grimes } else if (grp->gr_type == GT_NET) { 22768fae3551SRodney W. Grimes if (grp->gr_ptr.gt_net.nt_name) 22778fae3551SRodney W. Grimes free(grp->gr_ptr.gt_net.nt_name); 22788fae3551SRodney W. Grimes } 22798fae3551SRodney W. Grimes free((caddr_t)grp); 22808fae3551SRodney W. Grimes } 22818fae3551SRodney W. Grimes 22828fae3551SRodney W. Grimes #ifdef DEBUG 22838fae3551SRodney W. Grimes void 22848fae3551SRodney W. Grimes SYSLOG(int pri, const char *fmt, ...) 22858fae3551SRodney W. Grimes { 22868fae3551SRodney W. Grimes va_list ap; 22878fae3551SRodney W. Grimes 22888fae3551SRodney W. Grimes va_start(ap, fmt); 22898fae3551SRodney W. Grimes vfprintf(stderr, fmt, ap); 22908fae3551SRodney W. Grimes va_end(ap); 22918fae3551SRodney W. Grimes } 22928fae3551SRodney W. Grimes #endif /* DEBUG */ 22938fae3551SRodney W. Grimes 22948fae3551SRodney W. Grimes /* 22958fae3551SRodney W. Grimes * Check options for consistency. 22968fae3551SRodney W. Grimes */ 22978fae3551SRodney W. Grimes int 22988fae3551SRodney W. Grimes check_options(dp) 22998fae3551SRodney W. Grimes struct dirlist *dp; 23008fae3551SRodney W. Grimes { 23018fae3551SRodney W. Grimes 23028fae3551SRodney W. Grimes if (dp == (struct dirlist *)NULL) 23038fae3551SRodney W. Grimes return (1); 230491196234SPeter Wemm if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL)) { 230591196234SPeter Wemm syslog(LOG_ERR, "-mapall and -maproot mutually exclusive"); 23068fae3551SRodney W. Grimes return (1); 23078fae3551SRodney W. Grimes } 23088fae3551SRodney W. Grimes if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { 230960caaee2SIan Dowse syslog(LOG_ERR, "-mask requires -network"); 231060caaee2SIan Dowse return (1); 231160caaee2SIan Dowse } 231260caaee2SIan Dowse if ((opt_flags & OP_NET) && (opt_flags & OP_HAVEMASK) == 0) { 231360caaee2SIan Dowse syslog(LOG_ERR, "-network requires mask specification"); 231460caaee2SIan Dowse return (1); 231560caaee2SIan Dowse } 231660caaee2SIan Dowse if ((opt_flags & OP_MASK) && (opt_flags & OP_MASKLEN)) { 231760caaee2SIan Dowse syslog(LOG_ERR, "-mask and /masklen are mutually exclusive"); 23188fae3551SRodney W. Grimes return (1); 23198fae3551SRodney W. Grimes } 23208fae3551SRodney W. Grimes if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { 23216436fcb9SAlexander Langer syslog(LOG_ERR, "-alldirs has multiple directories"); 23228fae3551SRodney W. Grimes return (1); 23238fae3551SRodney W. Grimes } 23248fae3551SRodney W. Grimes return (0); 23258fae3551SRodney W. Grimes } 23268fae3551SRodney W. Grimes 23278fae3551SRodney W. Grimes /* 23288fae3551SRodney W. Grimes * Check an absolute directory path for any symbolic links. Return true 23298fae3551SRodney W. Grimes */ 23308fae3551SRodney W. Grimes int 23318fae3551SRodney W. Grimes check_dirpath(dirp) 23328fae3551SRodney W. Grimes char *dirp; 23338fae3551SRodney W. Grimes { 23348fae3551SRodney W. Grimes char *cp; 23358fae3551SRodney W. Grimes int ret = 1; 23368fae3551SRodney W. Grimes struct stat sb; 23378fae3551SRodney W. Grimes 23388fae3551SRodney W. Grimes cp = dirp + 1; 23398fae3551SRodney W. Grimes while (*cp && ret) { 23408fae3551SRodney W. Grimes if (*cp == '/') { 23418fae3551SRodney W. Grimes *cp = '\0'; 2342a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 23438fae3551SRodney W. Grimes ret = 0; 23448fae3551SRodney W. Grimes *cp = '/'; 23458fae3551SRodney W. Grimes } 23468fae3551SRodney W. Grimes cp++; 23478fae3551SRodney W. Grimes } 2348a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 23498fae3551SRodney W. Grimes ret = 0; 23508fae3551SRodney W. Grimes return (ret); 23518fae3551SRodney W. Grimes } 2352a62dc406SDoug Rabson 235360caaee2SIan Dowse /* 235460caaee2SIan Dowse * Make a netmask according to the specified prefix length. The ss_family 235560caaee2SIan Dowse * and other non-address fields must be initialised before calling this. 235660caaee2SIan Dowse */ 235760caaee2SIan Dowse int 235860caaee2SIan Dowse makemask(struct sockaddr_storage *ssp, int bitlen) 23598360efbdSAlfred Perlstein { 236060caaee2SIan Dowse u_char *p; 236160caaee2SIan Dowse int bits, i, len; 23628360efbdSAlfred Perlstein 236360caaee2SIan Dowse if ((p = sa_rawaddr((struct sockaddr *)ssp, &len)) == NULL) 236460caaee2SIan Dowse return (-1); 236560caaee2SIan Dowse if (bitlen > len * NBBY) 236660caaee2SIan Dowse return (-1); 23678360efbdSAlfred Perlstein 236860caaee2SIan Dowse for (i = 0; i < len; i++) { 236960caaee2SIan Dowse bits = (bitlen > NBBY) ? NBBY : bitlen; 237060caaee2SIan Dowse *p++ = (1 << bits) - 1; 237160caaee2SIan Dowse bitlen -= bits; 23728360efbdSAlfred Perlstein } 23738360efbdSAlfred Perlstein return 0; 23748360efbdSAlfred Perlstein } 23758360efbdSAlfred Perlstein 237660caaee2SIan Dowse /* 237760caaee2SIan Dowse * Check that the sockaddr is a valid netmask. Returns 0 if the mask 237860caaee2SIan Dowse * is acceptable (i.e. of the form 1...10....0). 237960caaee2SIan Dowse */ 238060caaee2SIan Dowse int 238160caaee2SIan Dowse checkmask(struct sockaddr *sa) 23828360efbdSAlfred Perlstein { 238360caaee2SIan Dowse u_char *mask; 238460caaee2SIan Dowse int i, len; 238560caaee2SIan Dowse 238660caaee2SIan Dowse if ((mask = sa_rawaddr(sa, &len)) == NULL) 238760caaee2SIan Dowse return (-1); 238860caaee2SIan Dowse 238960caaee2SIan Dowse for (i = 0; i < len; i++) 239060caaee2SIan Dowse if (mask[i] != 0xff) 239160caaee2SIan Dowse break; 239260caaee2SIan Dowse if (i < len) { 239360caaee2SIan Dowse if (~mask[i] & (u_char)(~mask[i] + 1)) 239460caaee2SIan Dowse return (-1); 239560caaee2SIan Dowse i++; 239660caaee2SIan Dowse } 239760caaee2SIan Dowse for (; i < len; i++) 239860caaee2SIan Dowse if (mask[i] != 0) 239960caaee2SIan Dowse return (-1); 240060caaee2SIan Dowse return (0); 240160caaee2SIan Dowse } 240260caaee2SIan Dowse 240360caaee2SIan Dowse /* 240460caaee2SIan Dowse * Compare two sockaddrs according to a specified mask. Return zero if 240560caaee2SIan Dowse * `sa1' matches `sa2' when filtered by the netmask in `samask'. 240660caaee2SIan Dowse * If samask is NULL, perform a full comparision. 240760caaee2SIan Dowse */ 240860caaee2SIan Dowse int 240960caaee2SIan Dowse sacmp(struct sockaddr *sa1, struct sockaddr *sa2, struct sockaddr *samask) 241060caaee2SIan Dowse { 241160caaee2SIan Dowse unsigned char *p1, *p2, *mask; 241260caaee2SIan Dowse int len, i; 241360caaee2SIan Dowse 241460caaee2SIan Dowse if (sa1->sa_family != sa2->sa_family || 241560caaee2SIan Dowse (p1 = sa_rawaddr(sa1, &len)) == NULL || 241660caaee2SIan Dowse (p2 = sa_rawaddr(sa2, NULL)) == NULL) 241760caaee2SIan Dowse return (1); 241860caaee2SIan Dowse 241960caaee2SIan Dowse switch (sa1->sa_family) { 242060caaee2SIan Dowse case AF_INET6: 242160caaee2SIan Dowse if (((struct sockaddr_in6 *)sa1)->sin6_scope_id != 242260caaee2SIan Dowse ((struct sockaddr_in6 *)sa2)->sin6_scope_id) 242360caaee2SIan Dowse return (1); 242460caaee2SIan Dowse break; 242560caaee2SIan Dowse } 242660caaee2SIan Dowse 242760caaee2SIan Dowse /* Simple binary comparison if no mask specified. */ 242860caaee2SIan Dowse if (samask == NULL) 242960caaee2SIan Dowse return (memcmp(p1, p2, len)); 243060caaee2SIan Dowse 243160caaee2SIan Dowse /* Set up the mask, and do a mask-based comparison. */ 243260caaee2SIan Dowse if (sa1->sa_family != samask->sa_family || 243360caaee2SIan Dowse (mask = sa_rawaddr(samask, NULL)) == NULL) 243460caaee2SIan Dowse return (1); 243560caaee2SIan Dowse 243660caaee2SIan Dowse for (i = 0; i < len; i++) 243760caaee2SIan Dowse if ((p1[i] & mask[i]) != (p2[i] & mask[i])) 243860caaee2SIan Dowse return (1); 243960caaee2SIan Dowse return (0); 244060caaee2SIan Dowse } 244160caaee2SIan Dowse 244260caaee2SIan Dowse /* 244360caaee2SIan Dowse * Return a pointer to the part of the sockaddr that contains the 244460caaee2SIan Dowse * raw address, and set *nbytes to its length in bytes. Returns 244560caaee2SIan Dowse * NULL if the address family is unknown. 244660caaee2SIan Dowse */ 244760caaee2SIan Dowse void * 244860caaee2SIan Dowse sa_rawaddr(struct sockaddr *sa, int *nbytes) { 244960caaee2SIan Dowse void *p; 245060caaee2SIan Dowse int len; 24518360efbdSAlfred Perlstein 24528360efbdSAlfred Perlstein switch (sa->sa_family) { 24538360efbdSAlfred Perlstein case AF_INET: 245460caaee2SIan Dowse len = sizeof(((struct sockaddr_in *)sa)->sin_addr); 245560caaee2SIan Dowse p = &((struct sockaddr_in *)sa)->sin_addr; 24568360efbdSAlfred Perlstein break; 24578360efbdSAlfred Perlstein case AF_INET6: 245860caaee2SIan Dowse len = sizeof(((struct sockaddr_in6 *)sa)->sin6_addr); 245960caaee2SIan Dowse p = &((struct sockaddr_in6 *)sa)->sin6_addr; 24608360efbdSAlfred Perlstein break; 24618360efbdSAlfred Perlstein default: 246260caaee2SIan Dowse p = NULL; 246360caaee2SIan Dowse len = 0; 24648360efbdSAlfred Perlstein } 24658360efbdSAlfred Perlstein 246660caaee2SIan Dowse if (nbytes != NULL) 246760caaee2SIan Dowse *nbytes = len; 246860caaee2SIan Dowse return (p); 24698360efbdSAlfred Perlstein } 24708360efbdSAlfred Perlstein 247169d65572SIan Dowse void 247269d65572SIan Dowse huphandler(int sig) 247369d65572SIan Dowse { 247469d65572SIan Dowse got_sighup = 1; 247569d65572SIan Dowse } 247669d65572SIan Dowse 24778360efbdSAlfred Perlstein void terminate(sig) 24788360efbdSAlfred Perlstein int sig; 24798360efbdSAlfred Perlstein { 24808360efbdSAlfred Perlstein close(mountdlockfd); 24818360efbdSAlfred Perlstein unlink(MOUNTDLOCK); 24827b98a1d6SAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); 24837b98a1d6SAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); 24848360efbdSAlfred Perlstein exit (0); 24858360efbdSAlfred Perlstein } 2486