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 4374853402SPhilippe Charnier #if 0 4475201fa4SPhilippe Charnier #ifndef lint 4574853402SPhilippe Charnier static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; 46d599144dSGarrett Wollman #endif /*not lint*/ 4775201fa4SPhilippe Charnier #endif 4875201fa4SPhilippe Charnier 4975201fa4SPhilippe Charnier #include <sys/cdefs.h> 5075201fa4SPhilippe Charnier __FBSDID("$FreeBSD$"); 518fae3551SRodney W. Grimes 528fae3551SRodney W. Grimes #include <sys/param.h> 538fae3551SRodney W. Grimes #include <sys/mount.h> 548360efbdSAlfred Perlstein #include <sys/fcntl.h> 558fae3551SRodney W. Grimes #include <sys/stat.h> 568fae3551SRodney W. Grimes #include <sys/syslog.h> 57394da4c1SGuido van Rooij #include <sys/sysctl.h> 5891ca1a91SIan Dowse #include <sys/linker.h> 5991ca1a91SIan Dowse #include <sys/module.h> 608fae3551SRodney W. Grimes 618fae3551SRodney W. Grimes #include <rpc/rpc.h> 628fae3551SRodney W. Grimes #include <rpc/pmap_clnt.h> 638360efbdSAlfred Perlstein #include <rpc/pmap_prot.h> 648360efbdSAlfred Perlstein #include <rpcsvc/mount.h> 658fae3551SRodney W. Grimes #include <nfs/rpcv2.h> 66a62dc406SDoug Rabson #include <nfs/nfsproto.h> 6791196234SPeter Wemm #include <nfsserver/nfs.h> 6887564113SPeter Wemm #include <ufs/ufs/ufsmount.h> 691166fb51SRuslan Ermilov #include <fs/msdosfs/msdosfsmount.h> 708a8402d3SRuslan Ermilov #include <fs/ntfs/ntfsmount.h> 7187564113SPeter Wemm #include <isofs/cd9660/cd9660_mount.h> /* XXX need isofs in include */ 728fae3551SRodney W. Grimes 738fae3551SRodney W. Grimes #include <arpa/inet.h> 748fae3551SRodney W. Grimes 758fae3551SRodney W. Grimes #include <ctype.h> 7674853402SPhilippe Charnier #include <err.h> 778fae3551SRodney W. Grimes #include <errno.h> 788fae3551SRodney W. Grimes #include <grp.h> 7989fdc4e1SMike Barcroft #include <limits.h> 808fae3551SRodney W. Grimes #include <netdb.h> 818fae3551SRodney W. Grimes #include <pwd.h> 828fae3551SRodney W. Grimes #include <signal.h> 838fae3551SRodney W. Grimes #include <stdio.h> 848fae3551SRodney W. Grimes #include <stdlib.h> 858fae3551SRodney W. Grimes #include <string.h> 868fae3551SRodney W. Grimes #include <unistd.h> 878fae3551SRodney W. Grimes #include "pathnames.h" 888fae3551SRodney W. Grimes 898fae3551SRodney W. Grimes #ifdef DEBUG 908fae3551SRodney W. Grimes #include <stdarg.h> 918fae3551SRodney W. Grimes #endif 928fae3551SRodney W. Grimes 938360efbdSAlfred Perlstein #ifndef MOUNTDLOCK 948360efbdSAlfred Perlstein #define MOUNTDLOCK "/var/run/mountd.lock" 958360efbdSAlfred Perlstein #endif 968360efbdSAlfred Perlstein 978fae3551SRodney W. Grimes /* 988fae3551SRodney W. Grimes * Structures for keeping the mount list and export list 998fae3551SRodney W. Grimes */ 1008fae3551SRodney W. Grimes struct mountlist { 1018fae3551SRodney W. Grimes struct mountlist *ml_next; 1028fae3551SRodney W. Grimes char ml_host[RPCMNT_NAMELEN+1]; 1038fae3551SRodney W. Grimes char ml_dirp[RPCMNT_PATHLEN+1]; 1048fae3551SRodney W. Grimes }; 1058fae3551SRodney W. Grimes 1068fae3551SRodney W. Grimes struct dirlist { 1078fae3551SRodney W. Grimes struct dirlist *dp_left; 1088fae3551SRodney W. Grimes struct dirlist *dp_right; 1098fae3551SRodney W. Grimes int dp_flag; 1108fae3551SRodney W. Grimes struct hostlist *dp_hosts; /* List of hosts this dir exported to */ 1118fae3551SRodney W. Grimes char dp_dirp[1]; /* Actually malloc'd to size of dir */ 1128fae3551SRodney W. Grimes }; 1138fae3551SRodney W. Grimes /* dp_flag bits */ 1148fae3551SRodney W. Grimes #define DP_DEFSET 0x1 115a62dc406SDoug Rabson #define DP_HOSTSET 0x2 1168fae3551SRodney W. Grimes 1178fae3551SRodney W. Grimes struct exportlist { 1188fae3551SRodney W. Grimes struct exportlist *ex_next; 1198fae3551SRodney W. Grimes struct dirlist *ex_dirl; 1208fae3551SRodney W. Grimes struct dirlist *ex_defdir; 1218fae3551SRodney W. Grimes int ex_flag; 1228fae3551SRodney W. Grimes fsid_t ex_fs; 1238fae3551SRodney W. Grimes char *ex_fsdir; 124cb3923e0SDoug Rabson char *ex_indexfile; 1258fae3551SRodney W. Grimes }; 1268fae3551SRodney W. Grimes /* ex_flag bits */ 1278fae3551SRodney W. Grimes #define EX_LINKED 0x1 1288fae3551SRodney W. Grimes 1298fae3551SRodney W. Grimes struct netmsk { 1308360efbdSAlfred Perlstein struct sockaddr_storage nt_net; 13160caaee2SIan Dowse struct sockaddr_storage nt_mask; 1328fae3551SRodney W. Grimes char *nt_name; 1338fae3551SRodney W. Grimes }; 1348fae3551SRodney W. Grimes 1358fae3551SRodney W. Grimes union grouptypes { 1368360efbdSAlfred Perlstein struct addrinfo *gt_addrinfo; 1378fae3551SRodney W. Grimes struct netmsk gt_net; 1388fae3551SRodney W. Grimes }; 1398fae3551SRodney W. Grimes 1408fae3551SRodney W. Grimes struct grouplist { 1418fae3551SRodney W. Grimes int gr_type; 1428fae3551SRodney W. Grimes union grouptypes gr_ptr; 1438fae3551SRodney W. Grimes struct grouplist *gr_next; 1448fae3551SRodney W. Grimes }; 1458fae3551SRodney W. Grimes /* Group types */ 1468fae3551SRodney W. Grimes #define GT_NULL 0x0 1478fae3551SRodney W. Grimes #define GT_HOST 0x1 1488fae3551SRodney W. Grimes #define GT_NET 0x2 1496d359f31SIan Dowse #define GT_DEFAULT 0x3 1508b5a6d67SBill Paul #define GT_IGNORE 0x5 1518fae3551SRodney W. Grimes 1528fae3551SRodney W. Grimes struct hostlist { 153a62dc406SDoug Rabson int ht_flag; /* Uses DP_xx bits */ 1548fae3551SRodney W. Grimes struct grouplist *ht_grp; 1558fae3551SRodney W. Grimes struct hostlist *ht_next; 1568fae3551SRodney W. Grimes }; 1578fae3551SRodney W. Grimes 158a62dc406SDoug Rabson struct fhreturn { 159a62dc406SDoug Rabson int fhr_flag; 160a62dc406SDoug Rabson int fhr_vers; 161a62dc406SDoug Rabson nfsfh_t fhr_fh; 162a62dc406SDoug Rabson }; 163a62dc406SDoug Rabson 1648fae3551SRodney W. Grimes /* Global defs */ 16585429990SWarner Losh char *add_expdir(struct dirlist **, char *, int); 16685429990SWarner Losh void add_dlist(struct dirlist **, struct dirlist *, 16785429990SWarner Losh struct grouplist *, int); 16885429990SWarner Losh void add_mlist(char *, char *); 16985429990SWarner Losh int check_dirpath(char *); 17085429990SWarner Losh int check_options(struct dirlist *); 17160caaee2SIan Dowse int checkmask(struct sockaddr *sa); 17285429990SWarner Losh int chk_host(struct dirlist *, struct sockaddr *, int *, int *); 17301709abfSIan Dowse void del_mlist(char *hostp, char *dirp); 17485429990SWarner Losh struct dirlist *dirp_search(struct dirlist *, char *); 17585429990SWarner Losh int do_mount(struct exportlist *, struct grouplist *, int, 17685429990SWarner Losh struct xucred *, char *, int, struct statfs *); 17785429990SWarner Losh int do_opt(char **, char **, struct exportlist *, struct grouplist *, 17885429990SWarner Losh int *, int *, struct xucred *); 17985429990SWarner Losh struct exportlist *ex_search(fsid_t *); 18085429990SWarner Losh struct exportlist *get_exp(void); 18185429990SWarner Losh void free_dir(struct dirlist *); 18285429990SWarner Losh void free_exp(struct exportlist *); 18385429990SWarner Losh void free_grp(struct grouplist *); 18485429990SWarner Losh void free_host(struct hostlist *); 18585429990SWarner Losh void get_exportlist(void); 18685429990SWarner Losh int get_host(char *, struct grouplist *, struct grouplist *); 18785429990SWarner Losh struct hostlist *get_ht(void); 18885429990SWarner Losh int get_line(void); 18985429990SWarner Losh void get_mountlist(void); 19085429990SWarner Losh int get_net(char *, struct netmsk *, int); 19185429990SWarner Losh void getexp_err(struct exportlist *, struct grouplist *); 19285429990SWarner Losh struct grouplist *get_grp(void); 19385429990SWarner Losh void hang_dirp(struct dirlist *, struct grouplist *, 19485429990SWarner Losh struct exportlist *, int); 19569d65572SIan Dowse void huphandler(int sig); 19660caaee2SIan Dowse int makemask(struct sockaddr_storage *ssp, int bitlen); 19785429990SWarner Losh void mntsrv(struct svc_req *, SVCXPRT *); 19885429990SWarner Losh void nextfield(char **, char **); 19985429990SWarner Losh void out_of_mem(void); 20085429990SWarner Losh void parsecred(char *, struct xucred *); 20191acb349SAlfred Perlstein int put_exlist(struct dirlist *, XDR *, struct dirlist *, int *, int); 20260caaee2SIan Dowse void *sa_rawaddr(struct sockaddr *sa, int *nbytes); 20360caaee2SIan Dowse int sacmp(struct sockaddr *sa1, struct sockaddr *sa2, 20460caaee2SIan Dowse struct sockaddr *samask); 20585429990SWarner Losh int scan_tree(struct dirlist *, struct sockaddr *); 20685429990SWarner Losh static void usage(void); 20785429990SWarner Losh int xdr_dir(XDR *, char *); 20885429990SWarner Losh int xdr_explist(XDR *, caddr_t); 20991acb349SAlfred Perlstein int xdr_explist_brief(XDR *, caddr_t); 21085429990SWarner Losh int xdr_fhs(XDR *, caddr_t); 21185429990SWarner Losh int xdr_mlist(XDR *, caddr_t); 21285429990SWarner Losh void terminate(int); 2138fae3551SRodney W. Grimes 2148fae3551SRodney W. Grimes struct exportlist *exphead; 2158fae3551SRodney W. Grimes struct mountlist *mlhead; 2168fae3551SRodney W. Grimes struct grouplist *grphead; 2178fae3551SRodney W. Grimes char exname[MAXPATHLEN]; 218c0511d3bSBrian Feldman struct xucred def_anon = { 21976183f34SDima Dorfman XUCRED_VERSION, 2208fae3551SRodney W. Grimes (uid_t)-2, 2218fae3551SRodney W. Grimes 1, 222c0511d3bSBrian Feldman { (gid_t)-2 }, 223c0511d3bSBrian Feldman NULL 2248fae3551SRodney W. Grimes }; 2252a66cfc5SDoug Rabson int force_v2 = 0; 226a62dc406SDoug Rabson int resvport_only = 1; 227a62dc406SDoug Rabson int dir_only = 1; 228f2c90b95SGuido van Rooij int log = 0; 22969d65572SIan Dowse int got_sighup = 0; 2308360efbdSAlfred Perlstein 2318fae3551SRodney W. Grimes int opt_flags; 2328360efbdSAlfred Perlstein static int have_v6 = 1; 2338360efbdSAlfred Perlstein #ifdef NI_WITHSCOPEID 2348360efbdSAlfred Perlstein static const int ninumeric = NI_NUMERICHOST | NI_WITHSCOPEID; 2358360efbdSAlfred Perlstein #else 2368360efbdSAlfred Perlstein static const int ninumeric = NI_NUMERICHOST; 2378360efbdSAlfred Perlstein #endif 2388360efbdSAlfred Perlstein 2398360efbdSAlfred Perlstein int mountdlockfd; 24060caaee2SIan Dowse /* Bits for opt_flags above */ 2418fae3551SRodney W. Grimes #define OP_MAPROOT 0x01 2428fae3551SRodney W. Grimes #define OP_MAPALL 0x02 24391196234SPeter Wemm /* 0x4 free */ 2448fae3551SRodney W. Grimes #define OP_MASK 0x08 2458fae3551SRodney W. Grimes #define OP_NET 0x10 2468fae3551SRodney W. Grimes #define OP_ALLDIRS 0x40 24760caaee2SIan Dowse #define OP_HAVEMASK 0x80 /* A mask was specified or inferred. */ 248288fa14aSJoerg Wunsch #define OP_QUIET 0x100 2498360efbdSAlfred Perlstein #define OP_MASKLEN 0x200 2508fae3551SRodney W. Grimes 2518fae3551SRodney W. Grimes #ifdef DEBUG 2528fae3551SRodney W. Grimes int debug = 1; 25385429990SWarner Losh void SYSLOG(int, const char *, ...) __printflike(2, 3); 2548fae3551SRodney W. Grimes #define syslog SYSLOG 2558fae3551SRodney W. Grimes #else 2568fae3551SRodney W. Grimes int debug = 0; 2578fae3551SRodney W. Grimes #endif 2588fae3551SRodney W. Grimes 2598fae3551SRodney W. Grimes /* 2608fae3551SRodney W. Grimes * Mountd server for NFS mount protocol as described in: 2618fae3551SRodney W. Grimes * NFS: Network File System Protocol Specification, RFC1094, Appendix A 2628fae3551SRodney W. Grimes * The optional arguments are the exports file name 2638fae3551SRodney W. Grimes * default: _PATH_EXPORTS 2648fae3551SRodney W. Grimes * and "-n" to allow nonroot mount. 2658fae3551SRodney W. Grimes */ 2668fae3551SRodney W. Grimes int 2678fae3551SRodney W. Grimes main(argc, argv) 2688fae3551SRodney W. Grimes int argc; 2698fae3551SRodney W. Grimes char **argv; 2708fae3551SRodney W. Grimes { 27169d65572SIan Dowse fd_set readfds; 2728360efbdSAlfred Perlstein SVCXPRT *udptransp, *tcptransp, *udp6transp, *tcp6transp; 2738360efbdSAlfred Perlstein struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf; 2748360efbdSAlfred Perlstein int udpsock, tcpsock, udp6sock, tcp6sock; 2758360efbdSAlfred Perlstein int xcreated = 0, s; 2768360efbdSAlfred Perlstein int one = 1; 27791ca1a91SIan Dowse int c; 278d599144dSGarrett Wollman 27901709abfSIan Dowse udp6conf = tcp6conf = NULL; 28001709abfSIan Dowse udp6sock = tcp6sock = NULL; 2818360efbdSAlfred Perlstein 28201709abfSIan Dowse /* Check that another mountd isn't already running. */ 2838360efbdSAlfred Perlstein if ((mountdlockfd = (open(MOUNTDLOCK, O_RDONLY|O_CREAT, 0444))) == -1) 2848360efbdSAlfred Perlstein err(1, "%s", MOUNTDLOCK); 2858360efbdSAlfred Perlstein 2868360efbdSAlfred Perlstein if(flock(mountdlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) 28775201fa4SPhilippe Charnier errx(1, "another mountd is already running. Aborting"); 2888360efbdSAlfred Perlstein s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 2898360efbdSAlfred Perlstein if (s < 0) 2908360efbdSAlfred Perlstein have_v6 = 0; 2918360efbdSAlfred Perlstein else 2928360efbdSAlfred Perlstein close(s); 2934a0785aaSPeter Wemm if (modfind("nfsserver") < 0) { 2944a0785aaSPeter Wemm /* Not present in kernel, try loading it */ 2954a0785aaSPeter Wemm if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0) 2964a0785aaSPeter Wemm errx(1, "NFS server is not available or loadable"); 297d599144dSGarrett Wollman } 2988fae3551SRodney W. Grimes 299690c488dSGuido van Rooij while ((c = getopt(argc, argv, "2dlnr")) != -1) 3008fae3551SRodney W. Grimes switch (c) { 3012a66cfc5SDoug Rabson case '2': 3022a66cfc5SDoug Rabson force_v2 = 1; 3032a66cfc5SDoug Rabson break; 304a62dc406SDoug Rabson case 'n': 305a62dc406SDoug Rabson resvport_only = 0; 306a62dc406SDoug Rabson break; 307a62dc406SDoug Rabson case 'r': 308a62dc406SDoug Rabson dir_only = 0; 309a62dc406SDoug Rabson break; 3106444ef3bSPoul-Henning Kamp case 'd': 3116444ef3bSPoul-Henning Kamp debug = debug ? 0 : 1; 3126444ef3bSPoul-Henning Kamp break; 313f51631d7SGuido van Rooij case 'l': 314f51631d7SGuido van Rooij log = 1; 315f51631d7SGuido van Rooij break; 3168fae3551SRodney W. Grimes default: 31774853402SPhilippe Charnier usage(); 3188fae3551SRodney W. Grimes }; 3198fae3551SRodney W. Grimes argc -= optind; 3208fae3551SRodney W. Grimes argv += optind; 3218fae3551SRodney W. Grimes grphead = (struct grouplist *)NULL; 3228fae3551SRodney W. Grimes exphead = (struct exportlist *)NULL; 3238fae3551SRodney W. Grimes mlhead = (struct mountlist *)NULL; 3248fae3551SRodney W. Grimes if (argc == 1) { 3258fae3551SRodney W. Grimes strncpy(exname, *argv, MAXPATHLEN-1); 3268fae3551SRodney W. Grimes exname[MAXPATHLEN-1] = '\0'; 3278fae3551SRodney W. Grimes } else 3288fae3551SRodney W. Grimes strcpy(exname, _PATH_EXPORTS); 3298fae3551SRodney W. Grimes openlog("mountd", LOG_PID, LOG_DAEMON); 3308fae3551SRodney W. Grimes if (debug) 33174853402SPhilippe Charnier warnx("getting export list"); 3328fae3551SRodney W. Grimes get_exportlist(); 3338fae3551SRodney W. Grimes if (debug) 33474853402SPhilippe Charnier warnx("getting mount list"); 3358fae3551SRodney W. Grimes get_mountlist(); 3368fae3551SRodney W. Grimes if (debug) 33774853402SPhilippe Charnier warnx("here we go"); 3388fae3551SRodney W. Grimes if (debug == 0) { 3398fae3551SRodney W. Grimes daemon(0, 0); 3408fae3551SRodney W. Grimes signal(SIGINT, SIG_IGN); 3418fae3551SRodney W. Grimes signal(SIGQUIT, SIG_IGN); 3428fae3551SRodney W. Grimes } 34369d65572SIan Dowse signal(SIGHUP, huphandler); 3448360efbdSAlfred Perlstein signal(SIGTERM, terminate); 3458fae3551SRodney W. Grimes { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); 3468fae3551SRodney W. Grimes if (pidfile != NULL) { 3478fae3551SRodney W. Grimes fprintf(pidfile, "%d\n", getpid()); 3488fae3551SRodney W. Grimes fclose(pidfile); 3498fae3551SRodney W. Grimes } 3508fae3551SRodney W. Grimes } 3518360efbdSAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); 3528360efbdSAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); 3538360efbdSAlfred Perlstein udpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 3548360efbdSAlfred Perlstein tcpsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 35595b99739SAlfred Perlstein udpconf = getnetconfigent("udp"); 35695b99739SAlfred Perlstein tcpconf = getnetconfigent("tcp"); 35795b99739SAlfred Perlstein if (!have_v6) 35895b99739SAlfred Perlstein goto skip_v6; 3598360efbdSAlfred Perlstein udp6sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 3608360efbdSAlfred Perlstein tcp6sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); 3618360efbdSAlfred Perlstein /* 3628360efbdSAlfred Perlstein * We're doing host-based access checks here, so don't allow 3638360efbdSAlfred Perlstein * v4-in-v6 to confuse things. The kernel will disable it 3648360efbdSAlfred Perlstein * by default on NFS sockets too. 3658360efbdSAlfred Perlstein */ 3668360efbdSAlfred Perlstein if (udp6sock != -1 && setsockopt(udp6sock, IPPROTO_IPV6, 367fc99a00cSHajimu UMEMOTO IPV6_V6ONLY, &one, sizeof one) < 0){ 3688360efbdSAlfred Perlstein syslog(LOG_ERR, "can't disable v4-in-v6 on UDP socket"); 3698360efbdSAlfred Perlstein exit(1); 3708360efbdSAlfred Perlstein } 3718360efbdSAlfred Perlstein if (tcp6sock != -1 && setsockopt(tcp6sock, IPPROTO_IPV6, 372fc99a00cSHajimu UMEMOTO IPV6_V6ONLY, &one, sizeof one) < 0){ 3738360efbdSAlfred Perlstein syslog(LOG_ERR, "can't disable v4-in-v6 on UDP socket"); 3748360efbdSAlfred Perlstein exit(1); 3758360efbdSAlfred Perlstein } 3768360efbdSAlfred Perlstein udp6conf = getnetconfigent("udp6"); 3778360efbdSAlfred Perlstein tcp6conf = getnetconfigent("tcp6"); 37895b99739SAlfred Perlstein 37995b99739SAlfred Perlstein skip_v6: 380c6e5e158SGuido van Rooij if (!resvport_only) { 3814a0785aaSPeter Wemm if (sysctlbyname("vfs.nfsrv.nfs_privport", NULL, NULL, 3824a0785aaSPeter Wemm &resvport_only, sizeof(resvport_only)) != 0 && 3834a0785aaSPeter Wemm errno != ENOENT) { 384394da4c1SGuido van Rooij syslog(LOG_ERR, "sysctl: %m"); 385394da4c1SGuido van Rooij exit(1); 386394da4c1SGuido van Rooij } 387c6e5e158SGuido van Rooij } 3888360efbdSAlfred Perlstein if (udpsock != -1 && udpconf != NULL) { 3898360efbdSAlfred Perlstein bindresvport(udpsock, NULL); 3908360efbdSAlfred Perlstein udptransp = svc_dg_create(udpsock, 0, 0); 3918360efbdSAlfred Perlstein if (udptransp != NULL) { 3928360efbdSAlfred Perlstein if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER1, 3938360efbdSAlfred Perlstein mntsrv, udpconf)) 3948360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP RPCMNT_VER1 service"); 3958360efbdSAlfred Perlstein else 3968360efbdSAlfred Perlstein xcreated++; 3978360efbdSAlfred Perlstein if (!force_v2) { 3988360efbdSAlfred Perlstein if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER3, 3998360efbdSAlfred Perlstein mntsrv, udpconf)) 4008360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP RPCMNT_VER3 service"); 4018360efbdSAlfred Perlstein else 4028360efbdSAlfred Perlstein xcreated++; 4038fae3551SRodney W. Grimes } 4048360efbdSAlfred Perlstein } else 4058360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create UDP services"); 4068360efbdSAlfred Perlstein 4078360efbdSAlfred Perlstein } 4088360efbdSAlfred Perlstein if (tcpsock != -1 && tcpconf != NULL) { 4098360efbdSAlfred Perlstein bindresvport(tcpsock, NULL); 4108360efbdSAlfred Perlstein listen(tcpsock, SOMAXCONN); 4118360efbdSAlfred Perlstein tcptransp = svc_vc_create(tcpsock, 0, 0); 4128360efbdSAlfred Perlstein if (tcptransp != NULL) { 4138360efbdSAlfred Perlstein if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER1, 4148360efbdSAlfred Perlstein mntsrv, tcpconf)) 4158360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP RPCMNT_VER1 service"); 4168360efbdSAlfred Perlstein else 4178360efbdSAlfred Perlstein xcreated++; 4188360efbdSAlfred Perlstein if (!force_v2) { 4198360efbdSAlfred Perlstein if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER3, 4208360efbdSAlfred Perlstein mntsrv, tcpconf)) 4218360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP RPCMNT_VER3 service"); 4228360efbdSAlfred Perlstein else 4238360efbdSAlfred Perlstein xcreated++; 4248360efbdSAlfred Perlstein } 4258360efbdSAlfred Perlstein } else 4268360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create TCP service"); 4278360efbdSAlfred Perlstein 4288360efbdSAlfred Perlstein } 42995b99739SAlfred Perlstein if (have_v6 && udp6sock != -1 && udp6conf != NULL) { 4308360efbdSAlfred Perlstein bindresvport(udp6sock, NULL); 4318360efbdSAlfred Perlstein udp6transp = svc_dg_create(udp6sock, 0, 0); 4328360efbdSAlfred Perlstein if (udp6transp != NULL) { 4338360efbdSAlfred Perlstein if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER1, 4348360efbdSAlfred Perlstein mntsrv, udp6conf)) 4358360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER1 service"); 4368360efbdSAlfred Perlstein else 4378360efbdSAlfred Perlstein xcreated++; 4388360efbdSAlfred Perlstein if (!force_v2) { 4398360efbdSAlfred Perlstein if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER3, 4408360efbdSAlfred Perlstein mntsrv, udp6conf)) 4418360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER3 service"); 4428360efbdSAlfred Perlstein else 4438360efbdSAlfred Perlstein xcreated++; 4448360efbdSAlfred Perlstein } 4458360efbdSAlfred Perlstein } else 4468360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create UDP6 service"); 4478360efbdSAlfred Perlstein 4488360efbdSAlfred Perlstein } 44995b99739SAlfred Perlstein if (have_v6 && tcp6sock != -1 && tcp6conf != NULL) { 4508360efbdSAlfred Perlstein bindresvport(tcp6sock, NULL); 4518360efbdSAlfred Perlstein listen(tcp6sock, SOMAXCONN); 4528360efbdSAlfred Perlstein tcp6transp = svc_vc_create(tcp6sock, 0, 0); 4538360efbdSAlfred Perlstein if (tcp6transp != NULL) { 4548360efbdSAlfred Perlstein if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER1, 4558360efbdSAlfred Perlstein mntsrv, tcp6conf)) 4568360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER1 service"); 4578360efbdSAlfred Perlstein else 4588360efbdSAlfred Perlstein xcreated++; 4598360efbdSAlfred Perlstein if (!force_v2) { 4608360efbdSAlfred Perlstein if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER3, 4618360efbdSAlfred Perlstein mntsrv, tcp6conf)) 4628360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER3 service"); 4638360efbdSAlfred Perlstein else 4648360efbdSAlfred Perlstein xcreated++; 4658360efbdSAlfred Perlstein } 4668360efbdSAlfred Perlstein } else 4678360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create TCP6 service"); 4688360efbdSAlfred Perlstein 4698360efbdSAlfred Perlstein } 4708360efbdSAlfred Perlstein if (xcreated == 0) { 4718360efbdSAlfred Perlstein syslog(LOG_ERR, "could not create any services"); 4722a66cfc5SDoug Rabson exit(1); 4732a66cfc5SDoug Rabson } 47469d65572SIan Dowse 47569d65572SIan Dowse /* Expand svc_run() here so that we can call get_exportlist(). */ 47669d65572SIan Dowse for (;;) { 47769d65572SIan Dowse if (got_sighup) { 47869d65572SIan Dowse get_exportlist(); 47969d65572SIan Dowse got_sighup = 0; 48069d65572SIan Dowse } 48169d65572SIan Dowse readfds = svc_fdset; 48269d65572SIan Dowse switch (select(svc_maxfd + 1, &readfds, NULL, NULL, NULL)) { 48369d65572SIan Dowse case -1: 48469d65572SIan Dowse if (errno == EINTR) 48569d65572SIan Dowse continue; 48669d65572SIan Dowse syslog(LOG_ERR, "mountd died: select: %m"); 48774853402SPhilippe Charnier exit(1); 48869d65572SIan Dowse case 0: 48969d65572SIan Dowse continue; 49069d65572SIan Dowse default: 49169d65572SIan Dowse svc_getreqset(&readfds); 49269d65572SIan Dowse } 49369d65572SIan Dowse } 49474853402SPhilippe Charnier } 49574853402SPhilippe Charnier 49674853402SPhilippe Charnier static void 49774853402SPhilippe Charnier usage() 49874853402SPhilippe Charnier { 49974853402SPhilippe Charnier fprintf(stderr, 50074853402SPhilippe Charnier "usage: mountd [-2] [-d] [-l] [-n] [-r] [export_file]\n"); 5018fae3551SRodney W. Grimes exit(1); 5028fae3551SRodney W. Grimes } 5038fae3551SRodney W. Grimes 5048fae3551SRodney W. Grimes /* 5058fae3551SRodney W. Grimes * The mount rpc service 5068fae3551SRodney W. Grimes */ 5078fae3551SRodney W. Grimes void 5088fae3551SRodney W. Grimes mntsrv(rqstp, transp) 5098fae3551SRodney W. Grimes struct svc_req *rqstp; 5108fae3551SRodney W. Grimes SVCXPRT *transp; 5118fae3551SRodney W. Grimes { 5128fae3551SRodney W. Grimes struct exportlist *ep; 5138fae3551SRodney W. Grimes struct dirlist *dp; 514a62dc406SDoug Rabson struct fhreturn fhr; 5158fae3551SRodney W. Grimes struct stat stb; 5168fae3551SRodney W. Grimes struct statfs fsb; 5178360efbdSAlfred Perlstein struct addrinfo *ai; 5188360efbdSAlfred Perlstein char host[NI_MAXHOST], numerichost[NI_MAXHOST]; 5198360efbdSAlfred Perlstein int lookup_failed = 1; 5208360efbdSAlfred Perlstein struct sockaddr *saddr; 521a62dc406SDoug Rabson u_short sport; 5228fae3551SRodney W. Grimes char rpcpath[RPCMNT_PATHLEN + 1], dirpath[MAXPATHLEN]; 523e90cdb54SGuido van Rooij int bad = 0, defset, hostset; 524a62dc406SDoug Rabson sigset_t sighup_mask; 5258fae3551SRodney W. Grimes 526a62dc406SDoug Rabson sigemptyset(&sighup_mask); 527a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 5288360efbdSAlfred Perlstein saddr = svc_getrpccaller(transp)->buf; 5298360efbdSAlfred Perlstein switch (saddr->sa_family) { 5308360efbdSAlfred Perlstein case AF_INET6: 53101709abfSIan Dowse sport = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port); 5328360efbdSAlfred Perlstein break; 5338360efbdSAlfred Perlstein case AF_INET: 53401709abfSIan Dowse sport = ntohs(((struct sockaddr_in *)saddr)->sin_port); 5358360efbdSAlfred Perlstein break; 5368360efbdSAlfred Perlstein default: 5378360efbdSAlfred Perlstein syslog(LOG_ERR, "request from unknown address family"); 5388360efbdSAlfred Perlstein return; 5398360efbdSAlfred Perlstein } 5408360efbdSAlfred Perlstein lookup_failed = getnameinfo(saddr, saddr->sa_len, host, sizeof host, 5418360efbdSAlfred Perlstein NULL, 0, 0); 5428360efbdSAlfred Perlstein getnameinfo(saddr, saddr->sa_len, numerichost, 5438360efbdSAlfred Perlstein sizeof numerichost, NULL, 0, NI_NUMERICHOST); 5448360efbdSAlfred Perlstein ai = NULL; 5458fae3551SRodney W. Grimes switch (rqstp->rq_proc) { 5468fae3551SRodney W. Grimes case NULLPROC: 54791acb349SAlfred Perlstein if (!svc_sendreply(transp, xdr_void, NULL)) 54874853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 5498fae3551SRodney W. Grimes return; 5508fae3551SRodney W. Grimes case RPCMNT_MOUNT: 551a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 552f51631d7SGuido van Rooij syslog(LOG_NOTICE, 553f51631d7SGuido van Rooij "mount request from %s from unprivileged port", 5548360efbdSAlfred Perlstein numerichost); 5558fae3551SRodney W. Grimes svcerr_weakauth(transp); 5568fae3551SRodney W. Grimes return; 5578fae3551SRodney W. Grimes } 5588fae3551SRodney W. Grimes if (!svc_getargs(transp, xdr_dir, rpcpath)) { 559f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable mount request from %s", 5608360efbdSAlfred Perlstein numerichost); 5618fae3551SRodney W. Grimes svcerr_decode(transp); 5628fae3551SRodney W. Grimes return; 5638fae3551SRodney W. Grimes } 5648fae3551SRodney W. Grimes 5658fae3551SRodney W. Grimes /* 5668fae3551SRodney W. Grimes * Get the real pathname and make sure it is a directory 567a62dc406SDoug Rabson * or a regular file if the -r option was specified 568a62dc406SDoug Rabson * and it exists. 5698fae3551SRodney W. Grimes */ 570cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL || 5718fae3551SRodney W. Grimes stat(dirpath, &stb) < 0 || 572a62dc406SDoug Rabson (!S_ISDIR(stb.st_mode) && 573a62dc406SDoug Rabson (dir_only || !S_ISREG(stb.st_mode))) || 5748fae3551SRodney W. Grimes statfs(dirpath, &fsb) < 0) { 5758fae3551SRodney W. Grimes chdir("/"); /* Just in case realpath doesn't */ 576f51631d7SGuido van Rooij syslog(LOG_NOTICE, 57774853402SPhilippe Charnier "mount request from %s for non existent path %s", 5788360efbdSAlfred Perlstein numerichost, dirpath); 5798fae3551SRodney W. Grimes if (debug) 58074853402SPhilippe Charnier warnx("stat failed on %s", dirpath); 581e90cdb54SGuido van Rooij bad = ENOENT; /* We will send error reply later */ 5828fae3551SRodney W. Grimes } 5838fae3551SRodney W. Grimes 5848fae3551SRodney W. Grimes /* Check in the exports list */ 585a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 5868fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 587a62dc406SDoug Rabson hostset = defset = 0; 588a62dc406SDoug Rabson if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) || 5898fae3551SRodney W. Grimes ((dp = dirp_search(ep->ex_dirl, dirpath)) && 590a62dc406SDoug Rabson chk_host(dp, saddr, &defset, &hostset)) || 5918fae3551SRodney W. Grimes (defset && scan_tree(ep->ex_defdir, saddr) == 0 && 5928fae3551SRodney W. Grimes scan_tree(ep->ex_dirl, saddr) == 0))) { 593e90cdb54SGuido van Rooij if (bad) { 594e90cdb54SGuido van Rooij if (!svc_sendreply(transp, xdr_long, 595e90cdb54SGuido van Rooij (caddr_t)&bad)) 59674853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 597e90cdb54SGuido van Rooij sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 598e90cdb54SGuido van Rooij return; 599e90cdb54SGuido van Rooij } 600a62dc406SDoug Rabson if (hostset & DP_HOSTSET) 601a62dc406SDoug Rabson fhr.fhr_flag = hostset; 602a62dc406SDoug Rabson else 603a62dc406SDoug Rabson fhr.fhr_flag = defset; 604a62dc406SDoug Rabson fhr.fhr_vers = rqstp->rq_vers; 6058fae3551SRodney W. Grimes /* Get the file handle */ 60687564113SPeter Wemm memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t)); 607a62dc406SDoug Rabson if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) { 6088fae3551SRodney W. Grimes bad = errno; 60974853402SPhilippe Charnier syslog(LOG_ERR, "can't get fh for %s", dirpath); 6108fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_long, 6118fae3551SRodney W. Grimes (caddr_t)&bad)) 61274853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 613a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6148fae3551SRodney W. Grimes return; 6158fae3551SRodney W. Grimes } 616a62dc406SDoug Rabson if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr)) 61774853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6188360efbdSAlfred Perlstein if (!lookup_failed) 6198360efbdSAlfred Perlstein add_mlist(host, dirpath); 6208fae3551SRodney W. Grimes else 6218360efbdSAlfred Perlstein add_mlist(numerichost, dirpath); 6228fae3551SRodney W. Grimes if (debug) 62374853402SPhilippe Charnier warnx("mount successful"); 624f51631d7SGuido van Rooij if (log) 625f51631d7SGuido van Rooij syslog(LOG_NOTICE, 626f51631d7SGuido van Rooij "mount request succeeded from %s for %s", 6278360efbdSAlfred Perlstein numerichost, dirpath); 628f51631d7SGuido van Rooij } else { 6298fae3551SRodney W. Grimes bad = EACCES; 630f51631d7SGuido van Rooij syslog(LOG_NOTICE, 631f51631d7SGuido van Rooij "mount request denied from %s for %s", 6328360efbdSAlfred Perlstein numerichost, dirpath); 633f51631d7SGuido van Rooij } 634e90cdb54SGuido van Rooij 635e90cdb54SGuido van Rooij if (bad && !svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 63674853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 637a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6388fae3551SRodney W. Grimes return; 6398fae3551SRodney W. Grimes case RPCMNT_DUMP: 6408fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL)) 64174853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 642f51631d7SGuido van Rooij else if (log) 643f51631d7SGuido van Rooij syslog(LOG_NOTICE, 644f51631d7SGuido van Rooij "dump request succeeded from %s", 6458360efbdSAlfred Perlstein numerichost); 6468fae3551SRodney W. Grimes return; 6478fae3551SRodney W. Grimes case RPCMNT_UMOUNT: 648a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 649f51631d7SGuido van Rooij syslog(LOG_NOTICE, 650f51631d7SGuido van Rooij "umount request from %s from unprivileged port", 6518360efbdSAlfred Perlstein numerichost); 6528fae3551SRodney W. Grimes svcerr_weakauth(transp); 6538fae3551SRodney W. Grimes return; 6548fae3551SRodney W. Grimes } 655cb479b11SAlfred Perlstein if (!svc_getargs(transp, xdr_dir, rpcpath)) { 656f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable umount request from %s", 6578360efbdSAlfred Perlstein numerichost); 6588fae3551SRodney W. Grimes svcerr_decode(transp); 6598fae3551SRodney W. Grimes return; 6608fae3551SRodney W. Grimes } 661cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL) { 662cb479b11SAlfred Perlstein syslog(LOG_NOTICE, "umount request from %s " 663cb479b11SAlfred Perlstein "for non existent path %s", 6648360efbdSAlfred Perlstein numerichost, dirpath); 665cb479b11SAlfred Perlstein } 6668fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 66774853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6688360efbdSAlfred Perlstein if (!lookup_failed) 66901709abfSIan Dowse del_mlist(host, dirpath); 67001709abfSIan Dowse del_mlist(numerichost, dirpath); 671f51631d7SGuido van Rooij if (log) 672f51631d7SGuido van Rooij syslog(LOG_NOTICE, 673f51631d7SGuido van Rooij "umount request succeeded from %s for %s", 6748360efbdSAlfred Perlstein numerichost, dirpath); 6758fae3551SRodney W. Grimes return; 6768fae3551SRodney W. Grimes case RPCMNT_UMNTALL: 677a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 678f51631d7SGuido van Rooij syslog(LOG_NOTICE, 679f51631d7SGuido van Rooij "umountall request from %s from unprivileged port", 6808360efbdSAlfred Perlstein numerichost); 6818fae3551SRodney W. Grimes svcerr_weakauth(transp); 6828fae3551SRodney W. Grimes return; 6838fae3551SRodney W. Grimes } 6848fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 68574853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6868360efbdSAlfred Perlstein if (!lookup_failed) 68701709abfSIan Dowse del_mlist(host, NULL); 68801709abfSIan Dowse del_mlist(numerichost, NULL); 689f51631d7SGuido van Rooij if (log) 690f51631d7SGuido van Rooij syslog(LOG_NOTICE, 691f51631d7SGuido van Rooij "umountall request succeeded from %s", 6928360efbdSAlfred Perlstein numerichost); 6938fae3551SRodney W. Grimes return; 6948fae3551SRodney W. Grimes case RPCMNT_EXPORT: 6958fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL)) 69691acb349SAlfred Perlstein if (!svc_sendreply(transp, xdr_explist_brief, (caddr_t)NULL)) 69774853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 698f51631d7SGuido van Rooij if (log) 699f51631d7SGuido van Rooij syslog(LOG_NOTICE, 700f51631d7SGuido van Rooij "export request succeeded from %s", 7018360efbdSAlfred Perlstein numerichost); 7028fae3551SRodney W. Grimes return; 7038fae3551SRodney W. Grimes default: 7048fae3551SRodney W. Grimes svcerr_noproc(transp); 7058fae3551SRodney W. Grimes return; 7068fae3551SRodney W. Grimes } 7078fae3551SRodney W. Grimes } 7088fae3551SRodney W. Grimes 7098fae3551SRodney W. Grimes /* 7108fae3551SRodney W. Grimes * Xdr conversion for a dirpath string 7118fae3551SRodney W. Grimes */ 7128fae3551SRodney W. Grimes int 7138fae3551SRodney W. Grimes xdr_dir(xdrsp, dirp) 7148fae3551SRodney W. Grimes XDR *xdrsp; 7158fae3551SRodney W. Grimes char *dirp; 7168fae3551SRodney W. Grimes { 7178fae3551SRodney W. Grimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 7188fae3551SRodney W. Grimes } 7198fae3551SRodney W. Grimes 7208fae3551SRodney W. Grimes /* 721a62dc406SDoug Rabson * Xdr routine to generate file handle reply 7228fae3551SRodney W. Grimes */ 7238fae3551SRodney W. Grimes int 724a62dc406SDoug Rabson xdr_fhs(xdrsp, cp) 7258fae3551SRodney W. Grimes XDR *xdrsp; 726a62dc406SDoug Rabson caddr_t cp; 7278fae3551SRodney W. Grimes { 7283d438ad6SDavid E. O'Brien struct fhreturn *fhrp = (struct fhreturn *)cp; 729a62dc406SDoug Rabson u_long ok = 0, len, auth; 7308fae3551SRodney W. Grimes 7318fae3551SRodney W. Grimes if (!xdr_long(xdrsp, &ok)) 7328fae3551SRodney W. Grimes return (0); 733a62dc406SDoug Rabson switch (fhrp->fhr_vers) { 734a62dc406SDoug Rabson case 1: 735a62dc406SDoug Rabson return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH)); 736a62dc406SDoug Rabson case 3: 737a62dc406SDoug Rabson len = NFSX_V3FH; 738a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 739a62dc406SDoug Rabson return (0); 740a62dc406SDoug Rabson if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) 741a62dc406SDoug Rabson return (0); 742a62dc406SDoug Rabson auth = RPCAUTH_UNIX; 743a62dc406SDoug Rabson len = 1; 744a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 745a62dc406SDoug Rabson return (0); 746a62dc406SDoug Rabson return (xdr_long(xdrsp, &auth)); 747a62dc406SDoug Rabson }; 748a62dc406SDoug Rabson return (0); 7498fae3551SRodney W. Grimes } 7508fae3551SRodney W. Grimes 7518fae3551SRodney W. Grimes int 7528fae3551SRodney W. Grimes xdr_mlist(xdrsp, cp) 7538fae3551SRodney W. Grimes XDR *xdrsp; 7548fae3551SRodney W. Grimes caddr_t cp; 7558fae3551SRodney W. Grimes { 7568fae3551SRodney W. Grimes struct mountlist *mlp; 7578fae3551SRodney W. Grimes int true = 1; 7588fae3551SRodney W. Grimes int false = 0; 7598fae3551SRodney W. Grimes char *strp; 7608fae3551SRodney W. Grimes 7618fae3551SRodney W. Grimes mlp = mlhead; 7628fae3551SRodney W. Grimes while (mlp) { 7638fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 7648fae3551SRodney W. Grimes return (0); 7658fae3551SRodney W. Grimes strp = &mlp->ml_host[0]; 7668fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 7678fae3551SRodney W. Grimes return (0); 7688fae3551SRodney W. Grimes strp = &mlp->ml_dirp[0]; 7698fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 7708fae3551SRodney W. Grimes return (0); 7718fae3551SRodney W. Grimes mlp = mlp->ml_next; 7728fae3551SRodney W. Grimes } 7738fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 7748fae3551SRodney W. Grimes return (0); 7758fae3551SRodney W. Grimes return (1); 7768fae3551SRodney W. Grimes } 7778fae3551SRodney W. Grimes 7788fae3551SRodney W. Grimes /* 7798fae3551SRodney W. Grimes * Xdr conversion for export list 7808fae3551SRodney W. Grimes */ 7818fae3551SRodney W. Grimes int 78291acb349SAlfred Perlstein xdr_explist_common(xdrsp, cp, brief) 7838fae3551SRodney W. Grimes XDR *xdrsp; 7848fae3551SRodney W. Grimes caddr_t cp; 78591acb349SAlfred Perlstein int brief; 7868fae3551SRodney W. Grimes { 7878fae3551SRodney W. Grimes struct exportlist *ep; 7888fae3551SRodney W. Grimes int false = 0; 789a62dc406SDoug Rabson int putdef; 790a62dc406SDoug Rabson sigset_t sighup_mask; 7918fae3551SRodney W. Grimes 792a62dc406SDoug Rabson sigemptyset(&sighup_mask); 793a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 794a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 7958fae3551SRodney W. Grimes ep = exphead; 7968fae3551SRodney W. Grimes while (ep) { 7978fae3551SRodney W. Grimes putdef = 0; 79891acb349SAlfred Perlstein if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, 79991acb349SAlfred Perlstein &putdef, brief)) 8008fae3551SRodney W. Grimes goto errout; 8018fae3551SRodney W. Grimes if (ep->ex_defdir && putdef == 0 && 8028fae3551SRodney W. Grimes put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL, 80391acb349SAlfred Perlstein &putdef, brief)) 8048fae3551SRodney W. Grimes goto errout; 8058fae3551SRodney W. Grimes ep = ep->ex_next; 8068fae3551SRodney W. Grimes } 807a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 8088fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 8098fae3551SRodney W. Grimes return (0); 8108fae3551SRodney W. Grimes return (1); 8118fae3551SRodney W. Grimes errout: 812a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 8138fae3551SRodney W. Grimes return (0); 8148fae3551SRodney W. Grimes } 8158fae3551SRodney W. Grimes 8168fae3551SRodney W. Grimes /* 8178fae3551SRodney W. Grimes * Called from xdr_explist() to traverse the tree and export the 8188fae3551SRodney W. Grimes * directory paths. 8198fae3551SRodney W. Grimes */ 8208fae3551SRodney W. Grimes int 82191acb349SAlfred Perlstein put_exlist(dp, xdrsp, adp, putdefp, brief) 8228fae3551SRodney W. Grimes struct dirlist *dp; 8238fae3551SRodney W. Grimes XDR *xdrsp; 8248fae3551SRodney W. Grimes struct dirlist *adp; 8258fae3551SRodney W. Grimes int *putdefp; 82691acb349SAlfred Perlstein int brief; 8278fae3551SRodney W. Grimes { 8288fae3551SRodney W. Grimes struct grouplist *grp; 8298fae3551SRodney W. Grimes struct hostlist *hp; 8308fae3551SRodney W. Grimes int true = 1; 8318fae3551SRodney W. Grimes int false = 0; 8328fae3551SRodney W. Grimes int gotalldir = 0; 8338fae3551SRodney W. Grimes char *strp; 8348fae3551SRodney W. Grimes 8358fae3551SRodney W. Grimes if (dp) { 83691acb349SAlfred Perlstein if (put_exlist(dp->dp_left, xdrsp, adp, putdefp, brief)) 8378fae3551SRodney W. Grimes return (1); 8388fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 8398fae3551SRodney W. Grimes return (1); 8408fae3551SRodney W. Grimes strp = dp->dp_dirp; 8418fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 8428fae3551SRodney W. Grimes return (1); 8438fae3551SRodney W. Grimes if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) { 8448fae3551SRodney W. Grimes gotalldir = 1; 8458fae3551SRodney W. Grimes *putdefp = 1; 8468fae3551SRodney W. Grimes } 84791acb349SAlfred Perlstein if (brief) { 84891acb349SAlfred Perlstein if (!xdr_bool(xdrsp, &true)) 84991acb349SAlfred Perlstein return (1); 85091acb349SAlfred Perlstein strp = "(...)"; 85191acb349SAlfred Perlstein if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 85291acb349SAlfred Perlstein return (1); 85391acb349SAlfred Perlstein } else if ((dp->dp_flag & DP_DEFSET) == 0 && 8548fae3551SRodney W. Grimes (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) { 8558fae3551SRodney W. Grimes hp = dp->dp_hosts; 8568fae3551SRodney W. Grimes while (hp) { 8578fae3551SRodney W. Grimes grp = hp->ht_grp; 8588fae3551SRodney W. Grimes if (grp->gr_type == GT_HOST) { 8598fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 8608fae3551SRodney W. Grimes return (1); 8618360efbdSAlfred Perlstein strp = grp->gr_ptr.gt_addrinfo->ai_canonname; 8628fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, 8638fae3551SRodney W. Grimes RPCMNT_NAMELEN)) 8648fae3551SRodney W. Grimes return (1); 8658fae3551SRodney W. Grimes } else if (grp->gr_type == GT_NET) { 8668fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 8678fae3551SRodney W. Grimes return (1); 8688fae3551SRodney W. Grimes strp = grp->gr_ptr.gt_net.nt_name; 8698fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, 8708fae3551SRodney W. Grimes RPCMNT_NAMELEN)) 8718fae3551SRodney W. Grimes return (1); 8728fae3551SRodney W. Grimes } 8738fae3551SRodney W. Grimes hp = hp->ht_next; 8748fae3551SRodney W. Grimes if (gotalldir && hp == (struct hostlist *)NULL) { 8758fae3551SRodney W. Grimes hp = adp->dp_hosts; 8768fae3551SRodney W. Grimes gotalldir = 0; 8778fae3551SRodney W. Grimes } 8788fae3551SRodney W. Grimes } 8798fae3551SRodney W. Grimes } 8808fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 8818fae3551SRodney W. Grimes return (1); 88291acb349SAlfred Perlstein if (put_exlist(dp->dp_right, xdrsp, adp, putdefp, brief)) 8838fae3551SRodney W. Grimes return (1); 8848fae3551SRodney W. Grimes } 8858fae3551SRodney W. Grimes return (0); 8868fae3551SRodney W. Grimes } 8878fae3551SRodney W. Grimes 88891acb349SAlfred Perlstein int 88991acb349SAlfred Perlstein xdr_explist(xdrsp, cp) 89091acb349SAlfred Perlstein XDR *xdrsp; 89191acb349SAlfred Perlstein caddr_t cp; 89291acb349SAlfred Perlstein { 89391acb349SAlfred Perlstein 89491acb349SAlfred Perlstein return xdr_explist_common(xdrsp, cp, 0); 89591acb349SAlfred Perlstein } 89691acb349SAlfred Perlstein 89791acb349SAlfred Perlstein int 89891acb349SAlfred Perlstein xdr_explist_brief(xdrsp, cp) 89991acb349SAlfred Perlstein XDR *xdrsp; 90091acb349SAlfred Perlstein caddr_t cp; 90191acb349SAlfred Perlstein { 90291acb349SAlfred Perlstein 90391acb349SAlfred Perlstein return xdr_explist_common(xdrsp, cp, 1); 90491acb349SAlfred Perlstein } 90591acb349SAlfred Perlstein 90691ca1a91SIan Dowse char *line; 90791ca1a91SIan Dowse int linesize; 9088fae3551SRodney W. Grimes FILE *exp_file; 9098fae3551SRodney W. Grimes 9108fae3551SRodney W. Grimes /* 9118fae3551SRodney W. Grimes * Get the export list 9128fae3551SRodney W. Grimes */ 9138fae3551SRodney W. Grimes void 9148fae3551SRodney W. Grimes get_exportlist() 9158fae3551SRodney W. Grimes { 9168fae3551SRodney W. Grimes struct exportlist *ep, *ep2; 9178fae3551SRodney W. Grimes struct grouplist *grp, *tgrp; 9188fae3551SRodney W. Grimes struct exportlist **epp; 9198fae3551SRodney W. Grimes struct dirlist *dirhead; 9208fae3551SRodney W. Grimes struct statfs fsb, *fsp; 921c0511d3bSBrian Feldman struct xucred anon; 9228fae3551SRodney W. Grimes char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; 9238fae3551SRodney W. Grimes int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp; 9248fae3551SRodney W. Grimes 925cb479b11SAlfred Perlstein dirp = NULL; 926cb479b11SAlfred Perlstein dirplen = 0; 927cb479b11SAlfred Perlstein 9288fae3551SRodney W. Grimes /* 9298fae3551SRodney W. Grimes * First, get rid of the old list 9308fae3551SRodney W. Grimes */ 9318fae3551SRodney W. Grimes ep = exphead; 9328fae3551SRodney W. Grimes while (ep) { 9338fae3551SRodney W. Grimes ep2 = ep; 9348fae3551SRodney W. Grimes ep = ep->ex_next; 9358fae3551SRodney W. Grimes free_exp(ep2); 9368fae3551SRodney W. Grimes } 9378fae3551SRodney W. Grimes exphead = (struct exportlist *)NULL; 9388fae3551SRodney W. Grimes 9398fae3551SRodney W. Grimes grp = grphead; 9408fae3551SRodney W. Grimes while (grp) { 9418fae3551SRodney W. Grimes tgrp = grp; 9428fae3551SRodney W. Grimes grp = grp->gr_next; 9438fae3551SRodney W. Grimes free_grp(tgrp); 9448fae3551SRodney W. Grimes } 9458fae3551SRodney W. Grimes grphead = (struct grouplist *)NULL; 9468fae3551SRodney W. Grimes 9478fae3551SRodney W. Grimes /* 9488fae3551SRodney W. Grimes * And delete exports that are in the kernel for all local 9498fae3551SRodney W. Grimes * filesystems. 9508fae3551SRodney W. Grimes * XXX: Should know how to handle all local exportable filesystems 95187564113SPeter Wemm * instead of just "ufs". 9528fae3551SRodney W. Grimes */ 9538fae3551SRodney W. Grimes num = getmntinfo(&fsp, MNT_NOWAIT); 9548fae3551SRodney W. Grimes for (i = 0; i < num; i++) { 9558fae3551SRodney W. Grimes union { 9568fae3551SRodney W. Grimes struct ufs_args ua; 9578fae3551SRodney W. Grimes struct iso_args ia; 958a62dc406SDoug Rabson struct msdosfs_args da; 9599300c696SSemen Ustimenko struct ntfs_args na; 960a62dc406SDoug Rabson } targs; 961a62dc406SDoug Rabson 962753d4978SPoul-Henning Kamp if (!strcmp(fsp->f_fstypename, "ufs") || 9634ccd7546SRuslan Ermilov !strcmp(fsp->f_fstypename, "msdosfs") || 9649300c696SSemen Ustimenko !strcmp(fsp->f_fstypename, "ntfs") || 96587564113SPeter Wemm !strcmp(fsp->f_fstypename, "cd9660")) { 966a62dc406SDoug Rabson targs.ua.fspec = NULL; 967a62dc406SDoug Rabson targs.ua.export.ex_flags = MNT_DELEXPORT; 968a62dc406SDoug Rabson if (mount(fsp->f_fstypename, fsp->f_mntonname, 9695f558fa4SIan Dowse fsp->f_flags | MNT_UPDATE, (caddr_t)&targs) < 0 && 9705f558fa4SIan Dowse errno != ENOENT) 9715f558fa4SIan Dowse syslog(LOG_ERR, 9725f558fa4SIan Dowse "can't delete exports for %s: %m", 9738fae3551SRodney W. Grimes fsp->f_mntonname); 9748fae3551SRodney W. Grimes } 9758fae3551SRodney W. Grimes fsp++; 9768fae3551SRodney W. Grimes } 9778fae3551SRodney W. Grimes 9788fae3551SRodney W. Grimes /* 9798fae3551SRodney W. Grimes * Read in the exports file and build the list, calling 9808fae3551SRodney W. Grimes * mount() as we go along to push the export rules into the kernel. 9818fae3551SRodney W. Grimes */ 9828fae3551SRodney W. Grimes if ((exp_file = fopen(exname, "r")) == NULL) { 98374853402SPhilippe Charnier syslog(LOG_ERR, "can't open %s", exname); 9848fae3551SRodney W. Grimes exit(2); 9858fae3551SRodney W. Grimes } 9868fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 9878fae3551SRodney W. Grimes while (get_line()) { 9888fae3551SRodney W. Grimes if (debug) 98974853402SPhilippe Charnier warnx("got line %s", line); 9908fae3551SRodney W. Grimes cp = line; 9918fae3551SRodney W. Grimes nextfield(&cp, &endcp); 9928fae3551SRodney W. Grimes if (*cp == '#') 9938fae3551SRodney W. Grimes goto nextline; 9948fae3551SRodney W. Grimes 9958fae3551SRodney W. Grimes /* 9968fae3551SRodney W. Grimes * Set defaults. 9978fae3551SRodney W. Grimes */ 9988fae3551SRodney W. Grimes has_host = FALSE; 9998fae3551SRodney W. Grimes anon = def_anon; 10008fae3551SRodney W. Grimes exflags = MNT_EXPORTED; 10018fae3551SRodney W. Grimes got_nondir = 0; 10028fae3551SRodney W. Grimes opt_flags = 0; 10038fae3551SRodney W. Grimes ep = (struct exportlist *)NULL; 10048fae3551SRodney W. Grimes 10058fae3551SRodney W. Grimes /* 10068fae3551SRodney W. Grimes * Create new exports list entry 10078fae3551SRodney W. Grimes */ 10088fae3551SRodney W. Grimes len = endcp-cp; 10098fae3551SRodney W. Grimes tgrp = grp = get_grp(); 10108fae3551SRodney W. Grimes while (len > 0) { 10118fae3551SRodney W. Grimes if (len > RPCMNT_NAMELEN) { 10128fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10138fae3551SRodney W. Grimes goto nextline; 10148fae3551SRodney W. Grimes } 10158fae3551SRodney W. Grimes if (*cp == '-') { 10168fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10178fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10188fae3551SRodney W. Grimes goto nextline; 10198fae3551SRodney W. Grimes } 10208fae3551SRodney W. Grimes if (debug) 102174853402SPhilippe Charnier warnx("doing opt %s", cp); 10228fae3551SRodney W. Grimes got_nondir = 1; 10238fae3551SRodney W. Grimes if (do_opt(&cp, &endcp, ep, grp, &has_host, 10248fae3551SRodney W. Grimes &exflags, &anon)) { 10258fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10268fae3551SRodney W. Grimes goto nextline; 10278fae3551SRodney W. Grimes } 10288fae3551SRodney W. Grimes } else if (*cp == '/') { 10298fae3551SRodney W. Grimes savedc = *endcp; 10308fae3551SRodney W. Grimes *endcp = '\0'; 10318fae3551SRodney W. Grimes if (check_dirpath(cp) && 10328fae3551SRodney W. Grimes statfs(cp, &fsb) >= 0) { 10338fae3551SRodney W. Grimes if (got_nondir) { 103474853402SPhilippe Charnier syslog(LOG_ERR, "dirs must be first"); 10358fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10368fae3551SRodney W. Grimes goto nextline; 10378fae3551SRodney W. Grimes } 10388fae3551SRodney W. Grimes if (ep) { 10398fae3551SRodney W. Grimes if (ep->ex_fs.val[0] != fsb.f_fsid.val[0] || 10408fae3551SRodney W. Grimes ep->ex_fs.val[1] != fsb.f_fsid.val[1]) { 10418fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10428fae3551SRodney W. Grimes goto nextline; 10438fae3551SRodney W. Grimes } 10448fae3551SRodney W. Grimes } else { 10458fae3551SRodney W. Grimes /* 10468fae3551SRodney W. Grimes * See if this directory is already 10478fae3551SRodney W. Grimes * in the list. 10488fae3551SRodney W. Grimes */ 10498fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 10508fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10518fae3551SRodney W. Grimes ep = get_exp(); 10528fae3551SRodney W. Grimes ep->ex_fs = fsb.f_fsid; 10538fae3551SRodney W. Grimes ep->ex_fsdir = (char *) 10548fae3551SRodney W. Grimes malloc(strlen(fsb.f_mntonname) + 1); 10558fae3551SRodney W. Grimes if (ep->ex_fsdir) 10568fae3551SRodney W. Grimes strcpy(ep->ex_fsdir, 10578fae3551SRodney W. Grimes fsb.f_mntonname); 10588fae3551SRodney W. Grimes else 10598fae3551SRodney W. Grimes out_of_mem(); 10608fae3551SRodney W. Grimes if (debug) 106174853402SPhilippe Charnier warnx("making new ep fs=0x%x,0x%x", 10628fae3551SRodney W. Grimes fsb.f_fsid.val[0], 10638fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 10648fae3551SRodney W. Grimes } else if (debug) 106574853402SPhilippe Charnier warnx("found ep fs=0x%x,0x%x", 10668fae3551SRodney W. Grimes fsb.f_fsid.val[0], 10678fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 10688fae3551SRodney W. Grimes } 10698fae3551SRodney W. Grimes 10708fae3551SRodney W. Grimes /* 10718fae3551SRodney W. Grimes * Add dirpath to export mount point. 10728fae3551SRodney W. Grimes */ 10738fae3551SRodney W. Grimes dirp = add_expdir(&dirhead, cp, len); 10748fae3551SRodney W. Grimes dirplen = len; 10758fae3551SRodney W. Grimes } else { 10768fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10778fae3551SRodney W. Grimes goto nextline; 10788fae3551SRodney W. Grimes } 10798fae3551SRodney W. Grimes *endcp = savedc; 10808fae3551SRodney W. Grimes } else { 10818fae3551SRodney W. Grimes savedc = *endcp; 10828fae3551SRodney W. Grimes *endcp = '\0'; 10838fae3551SRodney W. Grimes got_nondir = 1; 10848fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10858fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10868fae3551SRodney W. Grimes goto nextline; 10878fae3551SRodney W. Grimes } 10888fae3551SRodney W. Grimes 10898fae3551SRodney W. Grimes /* 10908fae3551SRodney W. Grimes * Get the host or netgroup. 10918fae3551SRodney W. Grimes */ 10928fae3551SRodney W. Grimes setnetgrent(cp); 10938fae3551SRodney W. Grimes netgrp = getnetgrent(&hst, &usr, &dom); 10948fae3551SRodney W. Grimes do { 10958fae3551SRodney W. Grimes if (has_host) { 10968fae3551SRodney W. Grimes grp->gr_next = get_grp(); 10978fae3551SRodney W. Grimes grp = grp->gr_next; 10988fae3551SRodney W. Grimes } 10998fae3551SRodney W. Grimes if (netgrp) { 11009d70a156SJoerg Wunsch if (hst == 0) { 110174853402SPhilippe Charnier syslog(LOG_ERR, 110274853402SPhilippe Charnier "null hostname in netgroup %s, skipping", cp); 110301d48801SJoerg Wunsch grp->gr_type = GT_IGNORE; 11049d70a156SJoerg Wunsch } else if (get_host(hst, grp, tgrp)) { 110574853402SPhilippe Charnier syslog(LOG_ERR, 110674853402SPhilippe Charnier "bad host %s in netgroup %s, skipping", hst, cp); 1107a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 11088fae3551SRodney W. Grimes } 11098b5a6d67SBill Paul } else if (get_host(cp, grp, tgrp)) { 111074853402SPhilippe Charnier syslog(LOG_ERR, "bad host %s, skipping", cp); 1111a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 11128fae3551SRodney W. Grimes } 11138fae3551SRodney W. Grimes has_host = TRUE; 11148fae3551SRodney W. Grimes } while (netgrp && getnetgrent(&hst, &usr, &dom)); 11158fae3551SRodney W. Grimes endnetgrent(); 11168fae3551SRodney W. Grimes *endcp = savedc; 11178fae3551SRodney W. Grimes } 11188fae3551SRodney W. Grimes cp = endcp; 11198fae3551SRodney W. Grimes nextfield(&cp, &endcp); 11208fae3551SRodney W. Grimes len = endcp - cp; 11218fae3551SRodney W. Grimes } 11228fae3551SRodney W. Grimes if (check_options(dirhead)) { 11238fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11248fae3551SRodney W. Grimes goto nextline; 11258fae3551SRodney W. Grimes } 11268fae3551SRodney W. Grimes if (!has_host) { 11276d359f31SIan Dowse grp->gr_type = GT_DEFAULT; 11288fae3551SRodney W. Grimes if (debug) 112974853402SPhilippe Charnier warnx("adding a default entry"); 11308fae3551SRodney W. Grimes 11318fae3551SRodney W. Grimes /* 11328fae3551SRodney W. Grimes * Don't allow a network export coincide with a list of 11338fae3551SRodney W. Grimes * host(s) on the same line. 11348fae3551SRodney W. Grimes */ 11358fae3551SRodney W. Grimes } else if ((opt_flags & OP_NET) && tgrp->gr_next) { 113660caaee2SIan Dowse syslog(LOG_ERR, "network/host conflict"); 11378fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11388fae3551SRodney W. Grimes goto nextline; 1139a968cfd8SJonathan Lemon 1140a968cfd8SJonathan Lemon /* 1141a968cfd8SJonathan Lemon * If an export list was specified on this line, make sure 1142a968cfd8SJonathan Lemon * that we have at least one valid entry, otherwise skip it. 1143a968cfd8SJonathan Lemon */ 1144a968cfd8SJonathan Lemon } else { 1145a968cfd8SJonathan Lemon grp = tgrp; 1146a968cfd8SJonathan Lemon while (grp && grp->gr_type == GT_IGNORE) 1147a968cfd8SJonathan Lemon grp = grp->gr_next; 1148a968cfd8SJonathan Lemon if (! grp) { 1149a968cfd8SJonathan Lemon getexp_err(ep, tgrp); 1150a968cfd8SJonathan Lemon goto nextline; 1151a968cfd8SJonathan Lemon } 11528fae3551SRodney W. Grimes } 11538fae3551SRodney W. Grimes 11548fae3551SRodney W. Grimes /* 11558fae3551SRodney W. Grimes * Loop through hosts, pushing the exports into the kernel. 11568fae3551SRodney W. Grimes * After loop, tgrp points to the start of the list and 11578fae3551SRodney W. Grimes * grp points to the last entry in the list. 11588fae3551SRodney W. Grimes */ 11598fae3551SRodney W. Grimes grp = tgrp; 11608fae3551SRodney W. Grimes do { 116101709abfSIan Dowse if (do_mount(ep, grp, exflags, &anon, dirp, dirplen, 116201709abfSIan Dowse &fsb)) { 11638fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11648fae3551SRodney W. Grimes goto nextline; 11658fae3551SRodney W. Grimes } 11668fae3551SRodney W. Grimes } while (grp->gr_next && (grp = grp->gr_next)); 11678fae3551SRodney W. Grimes 11688fae3551SRodney W. Grimes /* 11698fae3551SRodney W. Grimes * Success. Update the data structures. 11708fae3551SRodney W. Grimes */ 11718fae3551SRodney W. Grimes if (has_host) { 1172a62dc406SDoug Rabson hang_dirp(dirhead, tgrp, ep, opt_flags); 11738fae3551SRodney W. Grimes grp->gr_next = grphead; 11748fae3551SRodney W. Grimes grphead = tgrp; 11758fae3551SRodney W. Grimes } else { 11768fae3551SRodney W. Grimes hang_dirp(dirhead, (struct grouplist *)NULL, ep, 1177a62dc406SDoug Rabson opt_flags); 11788fae3551SRodney W. Grimes free_grp(grp); 11798fae3551SRodney W. Grimes } 11808fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 11818fae3551SRodney W. Grimes if ((ep->ex_flag & EX_LINKED) == 0) { 11828fae3551SRodney W. Grimes ep2 = exphead; 11838fae3551SRodney W. Grimes epp = &exphead; 11848fae3551SRodney W. Grimes 11858fae3551SRodney W. Grimes /* 11868fae3551SRodney W. Grimes * Insert in the list in alphabetical order. 11878fae3551SRodney W. Grimes */ 11888fae3551SRodney W. Grimes while (ep2 && strcmp(ep2->ex_fsdir, ep->ex_fsdir) < 0) { 11898fae3551SRodney W. Grimes epp = &ep2->ex_next; 11908fae3551SRodney W. Grimes ep2 = ep2->ex_next; 11918fae3551SRodney W. Grimes } 11928fae3551SRodney W. Grimes if (ep2) 11938fae3551SRodney W. Grimes ep->ex_next = ep2; 11948fae3551SRodney W. Grimes *epp = ep; 11958fae3551SRodney W. Grimes ep->ex_flag |= EX_LINKED; 11968fae3551SRodney W. Grimes } 11978fae3551SRodney W. Grimes nextline: 11988fae3551SRodney W. Grimes if (dirhead) { 11998fae3551SRodney W. Grimes free_dir(dirhead); 12008fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 12018fae3551SRodney W. Grimes } 12028fae3551SRodney W. Grimes } 12038fae3551SRodney W. Grimes fclose(exp_file); 12048fae3551SRodney W. Grimes } 12058fae3551SRodney W. Grimes 12068fae3551SRodney W. Grimes /* 12078fae3551SRodney W. Grimes * Allocate an export list element 12088fae3551SRodney W. Grimes */ 12098fae3551SRodney W. Grimes struct exportlist * 12108fae3551SRodney W. Grimes get_exp() 12118fae3551SRodney W. Grimes { 12128fae3551SRodney W. Grimes struct exportlist *ep; 12138fae3551SRodney W. Grimes 12148fae3551SRodney W. Grimes ep = (struct exportlist *)malloc(sizeof (struct exportlist)); 12158fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) 12168fae3551SRodney W. Grimes out_of_mem(); 121787564113SPeter Wemm memset(ep, 0, sizeof(struct exportlist)); 12188fae3551SRodney W. Grimes return (ep); 12198fae3551SRodney W. Grimes } 12208fae3551SRodney W. Grimes 12218fae3551SRodney W. Grimes /* 12228fae3551SRodney W. Grimes * Allocate a group list element 12238fae3551SRodney W. Grimes */ 12248fae3551SRodney W. Grimes struct grouplist * 12258fae3551SRodney W. Grimes get_grp() 12268fae3551SRodney W. Grimes { 12278fae3551SRodney W. Grimes struct grouplist *gp; 12288fae3551SRodney W. Grimes 12298fae3551SRodney W. Grimes gp = (struct grouplist *)malloc(sizeof (struct grouplist)); 12308fae3551SRodney W. Grimes if (gp == (struct grouplist *)NULL) 12318fae3551SRodney W. Grimes out_of_mem(); 123287564113SPeter Wemm memset(gp, 0, sizeof(struct grouplist)); 12338fae3551SRodney W. Grimes return (gp); 12348fae3551SRodney W. Grimes } 12358fae3551SRodney W. Grimes 12368fae3551SRodney W. Grimes /* 12378fae3551SRodney W. Grimes * Clean up upon an error in get_exportlist(). 12388fae3551SRodney W. Grimes */ 12398fae3551SRodney W. Grimes void 12408fae3551SRodney W. Grimes getexp_err(ep, grp) 12418fae3551SRodney W. Grimes struct exportlist *ep; 12428fae3551SRodney W. Grimes struct grouplist *grp; 12438fae3551SRodney W. Grimes { 12448fae3551SRodney W. Grimes struct grouplist *tgrp; 12458fae3551SRodney W. Grimes 1246288fa14aSJoerg Wunsch if (!(opt_flags & OP_QUIET)) 124774853402SPhilippe Charnier syslog(LOG_ERR, "bad exports list line %s", line); 12488fae3551SRodney W. Grimes if (ep && (ep->ex_flag & EX_LINKED) == 0) 12498fae3551SRodney W. Grimes free_exp(ep); 12508fae3551SRodney W. Grimes while (grp) { 12518fae3551SRodney W. Grimes tgrp = grp; 12528fae3551SRodney W. Grimes grp = grp->gr_next; 12538fae3551SRodney W. Grimes free_grp(tgrp); 12548fae3551SRodney W. Grimes } 12558fae3551SRodney W. Grimes } 12568fae3551SRodney W. Grimes 12578fae3551SRodney W. Grimes /* 12588fae3551SRodney W. Grimes * Search the export list for a matching fs. 12598fae3551SRodney W. Grimes */ 12608fae3551SRodney W. Grimes struct exportlist * 12618fae3551SRodney W. Grimes ex_search(fsid) 12628fae3551SRodney W. Grimes fsid_t *fsid; 12638fae3551SRodney W. Grimes { 12648fae3551SRodney W. Grimes struct exportlist *ep; 12658fae3551SRodney W. Grimes 12668fae3551SRodney W. Grimes ep = exphead; 12678fae3551SRodney W. Grimes while (ep) { 12688fae3551SRodney W. Grimes if (ep->ex_fs.val[0] == fsid->val[0] && 12698fae3551SRodney W. Grimes ep->ex_fs.val[1] == fsid->val[1]) 12708fae3551SRodney W. Grimes return (ep); 12718fae3551SRodney W. Grimes ep = ep->ex_next; 12728fae3551SRodney W. Grimes } 12738fae3551SRodney W. Grimes return (ep); 12748fae3551SRodney W. Grimes } 12758fae3551SRodney W. Grimes 12768fae3551SRodney W. Grimes /* 12778fae3551SRodney W. Grimes * Add a directory path to the list. 12788fae3551SRodney W. Grimes */ 12798fae3551SRodney W. Grimes char * 12808fae3551SRodney W. Grimes add_expdir(dpp, cp, len) 12818fae3551SRodney W. Grimes struct dirlist **dpp; 12828fae3551SRodney W. Grimes char *cp; 12838fae3551SRodney W. Grimes int len; 12848fae3551SRodney W. Grimes { 12858fae3551SRodney W. Grimes struct dirlist *dp; 12868fae3551SRodney W. Grimes 12878fae3551SRodney W. Grimes dp = (struct dirlist *)malloc(sizeof (struct dirlist) + len); 128874853402SPhilippe Charnier if (dp == (struct dirlist *)NULL) 128974853402SPhilippe Charnier out_of_mem(); 12908fae3551SRodney W. Grimes dp->dp_left = *dpp; 12918fae3551SRodney W. Grimes dp->dp_right = (struct dirlist *)NULL; 12928fae3551SRodney W. Grimes dp->dp_flag = 0; 12938fae3551SRodney W. Grimes dp->dp_hosts = (struct hostlist *)NULL; 12948fae3551SRodney W. Grimes strcpy(dp->dp_dirp, cp); 12958fae3551SRodney W. Grimes *dpp = dp; 12968fae3551SRodney W. Grimes return (dp->dp_dirp); 12978fae3551SRodney W. Grimes } 12988fae3551SRodney W. Grimes 12998fae3551SRodney W. Grimes /* 13008fae3551SRodney W. Grimes * Hang the dir list element off the dirpath binary tree as required 13018fae3551SRodney W. Grimes * and update the entry for host. 13028fae3551SRodney W. Grimes */ 13038fae3551SRodney W. Grimes void 1304a62dc406SDoug Rabson hang_dirp(dp, grp, ep, flags) 13058fae3551SRodney W. Grimes struct dirlist *dp; 13068fae3551SRodney W. Grimes struct grouplist *grp; 13078fae3551SRodney W. Grimes struct exportlist *ep; 1308a62dc406SDoug Rabson int flags; 13098fae3551SRodney W. Grimes { 13108fae3551SRodney W. Grimes struct hostlist *hp; 13118fae3551SRodney W. Grimes struct dirlist *dp2; 13128fae3551SRodney W. Grimes 1313a62dc406SDoug Rabson if (flags & OP_ALLDIRS) { 13148fae3551SRodney W. Grimes if (ep->ex_defdir) 13158fae3551SRodney W. Grimes free((caddr_t)dp); 13168fae3551SRodney W. Grimes else 13178fae3551SRodney W. Grimes ep->ex_defdir = dp; 1318a62dc406SDoug Rabson if (grp == (struct grouplist *)NULL) { 13198fae3551SRodney W. Grimes ep->ex_defdir->dp_flag |= DP_DEFSET; 1320a62dc406SDoug Rabson } else while (grp) { 13218fae3551SRodney W. Grimes hp = get_ht(); 13228fae3551SRodney W. Grimes hp->ht_grp = grp; 13238fae3551SRodney W. Grimes hp->ht_next = ep->ex_defdir->dp_hosts; 13248fae3551SRodney W. Grimes ep->ex_defdir->dp_hosts = hp; 13258fae3551SRodney W. Grimes grp = grp->gr_next; 13268fae3551SRodney W. Grimes } 13278fae3551SRodney W. Grimes } else { 13288fae3551SRodney W. Grimes 13298fae3551SRodney W. Grimes /* 133074853402SPhilippe Charnier * Loop through the directories adding them to the tree. 13318fae3551SRodney W. Grimes */ 13328fae3551SRodney W. Grimes while (dp) { 13338fae3551SRodney W. Grimes dp2 = dp->dp_left; 1334a62dc406SDoug Rabson add_dlist(&ep->ex_dirl, dp, grp, flags); 13358fae3551SRodney W. Grimes dp = dp2; 13368fae3551SRodney W. Grimes } 13378fae3551SRodney W. Grimes } 13388fae3551SRodney W. Grimes } 13398fae3551SRodney W. Grimes 13408fae3551SRodney W. Grimes /* 13418fae3551SRodney W. Grimes * Traverse the binary tree either updating a node that is already there 13428fae3551SRodney W. Grimes * for the new directory or adding the new node. 13438fae3551SRodney W. Grimes */ 13448fae3551SRodney W. Grimes void 1345a62dc406SDoug Rabson add_dlist(dpp, newdp, grp, flags) 13468fae3551SRodney W. Grimes struct dirlist **dpp; 13478fae3551SRodney W. Grimes struct dirlist *newdp; 13488fae3551SRodney W. Grimes struct grouplist *grp; 1349a62dc406SDoug Rabson int flags; 13508fae3551SRodney W. Grimes { 13518fae3551SRodney W. Grimes struct dirlist *dp; 13528fae3551SRodney W. Grimes struct hostlist *hp; 13538fae3551SRodney W. Grimes int cmp; 13548fae3551SRodney W. Grimes 13558fae3551SRodney W. Grimes dp = *dpp; 13568fae3551SRodney W. Grimes if (dp) { 13578fae3551SRodney W. Grimes cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); 13588fae3551SRodney W. Grimes if (cmp > 0) { 1359a62dc406SDoug Rabson add_dlist(&dp->dp_left, newdp, grp, flags); 13608fae3551SRodney W. Grimes return; 13618fae3551SRodney W. Grimes } else if (cmp < 0) { 1362a62dc406SDoug Rabson add_dlist(&dp->dp_right, newdp, grp, flags); 13638fae3551SRodney W. Grimes return; 13648fae3551SRodney W. Grimes } else 13658fae3551SRodney W. Grimes free((caddr_t)newdp); 13668fae3551SRodney W. Grimes } else { 13678fae3551SRodney W. Grimes dp = newdp; 13688fae3551SRodney W. Grimes dp->dp_left = (struct dirlist *)NULL; 13698fae3551SRodney W. Grimes *dpp = dp; 13708fae3551SRodney W. Grimes } 13718fae3551SRodney W. Grimes if (grp) { 13728fae3551SRodney W. Grimes 13738fae3551SRodney W. Grimes /* 13748fae3551SRodney W. Grimes * Hang all of the host(s) off of the directory point. 13758fae3551SRodney W. Grimes */ 13768fae3551SRodney W. Grimes do { 13778fae3551SRodney W. Grimes hp = get_ht(); 13788fae3551SRodney W. Grimes hp->ht_grp = grp; 13798fae3551SRodney W. Grimes hp->ht_next = dp->dp_hosts; 13808fae3551SRodney W. Grimes dp->dp_hosts = hp; 13818fae3551SRodney W. Grimes grp = grp->gr_next; 13828fae3551SRodney W. Grimes } while (grp); 1383a62dc406SDoug Rabson } else { 13848fae3551SRodney W. Grimes dp->dp_flag |= DP_DEFSET; 1385a62dc406SDoug Rabson } 13868fae3551SRodney W. Grimes } 13878fae3551SRodney W. Grimes 13888fae3551SRodney W. Grimes /* 13898fae3551SRodney W. Grimes * Search for a dirpath on the export point. 13908fae3551SRodney W. Grimes */ 13918fae3551SRodney W. Grimes struct dirlist * 13928360efbdSAlfred Perlstein dirp_search(dp, dirp) 13938fae3551SRodney W. Grimes struct dirlist *dp; 13948360efbdSAlfred Perlstein char *dirp; 13958fae3551SRodney W. Grimes { 13968fae3551SRodney W. Grimes int cmp; 13978fae3551SRodney W. Grimes 13988fae3551SRodney W. Grimes if (dp) { 13998360efbdSAlfred Perlstein cmp = strcmp(dp->dp_dirp, dirp); 14008fae3551SRodney W. Grimes if (cmp > 0) 14018360efbdSAlfred Perlstein return (dirp_search(dp->dp_left, dirp)); 14028fae3551SRodney W. Grimes else if (cmp < 0) 14038360efbdSAlfred Perlstein return (dirp_search(dp->dp_right, dirp)); 14048fae3551SRodney W. Grimes else 14058fae3551SRodney W. Grimes return (dp); 14068fae3551SRodney W. Grimes } 14078fae3551SRodney W. Grimes return (dp); 14088fae3551SRodney W. Grimes } 14098fae3551SRodney W. Grimes 14108fae3551SRodney W. Grimes /* 14118fae3551SRodney W. Grimes * Scan for a host match in a directory tree. 14128fae3551SRodney W. Grimes */ 14138fae3551SRodney W. Grimes int 1414a62dc406SDoug Rabson chk_host(dp, saddr, defsetp, hostsetp) 14158fae3551SRodney W. Grimes struct dirlist *dp; 14168360efbdSAlfred Perlstein struct sockaddr *saddr; 14178fae3551SRodney W. Grimes int *defsetp; 1418a62dc406SDoug Rabson int *hostsetp; 14198fae3551SRodney W. Grimes { 14208fae3551SRodney W. Grimes struct hostlist *hp; 14218fae3551SRodney W. Grimes struct grouplist *grp; 14228360efbdSAlfred Perlstein struct addrinfo *ai; 14238fae3551SRodney W. Grimes 14248fae3551SRodney W. Grimes if (dp) { 14258fae3551SRodney W. Grimes if (dp->dp_flag & DP_DEFSET) 1426a62dc406SDoug Rabson *defsetp = dp->dp_flag; 14278fae3551SRodney W. Grimes hp = dp->dp_hosts; 14288fae3551SRodney W. Grimes while (hp) { 14298fae3551SRodney W. Grimes grp = hp->ht_grp; 14308fae3551SRodney W. Grimes switch (grp->gr_type) { 14318fae3551SRodney W. Grimes case GT_HOST: 14328360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 14338360efbdSAlfred Perlstein for (; ai; ai = ai->ai_next) { 143460caaee2SIan Dowse if (!sacmp(ai->ai_addr, saddr, NULL)) { 14358360efbdSAlfred Perlstein *hostsetp = 14368360efbdSAlfred Perlstein (hp->ht_flag | DP_HOSTSET); 14378fae3551SRodney W. Grimes return (1); 1438a62dc406SDoug Rabson } 14398fae3551SRodney W. Grimes } 14408fae3551SRodney W. Grimes break; 14418fae3551SRodney W. Grimes case GT_NET: 144260caaee2SIan Dowse if (!sacmp(saddr, (struct sockaddr *) 144360caaee2SIan Dowse &grp->gr_ptr.gt_net.nt_net, 144460caaee2SIan Dowse (struct sockaddr *) 144560caaee2SIan Dowse &grp->gr_ptr.gt_net.nt_mask)) { 1446a62dc406SDoug Rabson *hostsetp = (hp->ht_flag | DP_HOSTSET); 14478fae3551SRodney W. Grimes return (1); 1448a62dc406SDoug Rabson } 14498fae3551SRodney W. Grimes break; 145060caaee2SIan Dowse } 14518fae3551SRodney W. Grimes hp = hp->ht_next; 14528fae3551SRodney W. Grimes } 14538fae3551SRodney W. Grimes } 14548fae3551SRodney W. Grimes return (0); 14558fae3551SRodney W. Grimes } 14568fae3551SRodney W. Grimes 14578fae3551SRodney W. Grimes /* 14588fae3551SRodney W. Grimes * Scan tree for a host that matches the address. 14598fae3551SRodney W. Grimes */ 14608fae3551SRodney W. Grimes int 14618fae3551SRodney W. Grimes scan_tree(dp, saddr) 14628fae3551SRodney W. Grimes struct dirlist *dp; 14638360efbdSAlfred Perlstein struct sockaddr *saddr; 14648fae3551SRodney W. Grimes { 1465a62dc406SDoug Rabson int defset, hostset; 14668fae3551SRodney W. Grimes 14678fae3551SRodney W. Grimes if (dp) { 14688fae3551SRodney W. Grimes if (scan_tree(dp->dp_left, saddr)) 14698fae3551SRodney W. Grimes return (1); 1470a62dc406SDoug Rabson if (chk_host(dp, saddr, &defset, &hostset)) 14718fae3551SRodney W. Grimes return (1); 14728fae3551SRodney W. Grimes if (scan_tree(dp->dp_right, saddr)) 14738fae3551SRodney W. Grimes return (1); 14748fae3551SRodney W. Grimes } 14758fae3551SRodney W. Grimes return (0); 14768fae3551SRodney W. Grimes } 14778fae3551SRodney W. Grimes 14788fae3551SRodney W. Grimes /* 14798fae3551SRodney W. Grimes * Traverse the dirlist tree and free it up. 14808fae3551SRodney W. Grimes */ 14818fae3551SRodney W. Grimes void 14828fae3551SRodney W. Grimes free_dir(dp) 14838fae3551SRodney W. Grimes struct dirlist *dp; 14848fae3551SRodney W. Grimes { 14858fae3551SRodney W. Grimes 14868fae3551SRodney W. Grimes if (dp) { 14878fae3551SRodney W. Grimes free_dir(dp->dp_left); 14888fae3551SRodney W. Grimes free_dir(dp->dp_right); 14898fae3551SRodney W. Grimes free_host(dp->dp_hosts); 14908fae3551SRodney W. Grimes free((caddr_t)dp); 14918fae3551SRodney W. Grimes } 14928fae3551SRodney W. Grimes } 14938fae3551SRodney W. Grimes 14948fae3551SRodney W. Grimes /* 14958fae3551SRodney W. Grimes * Parse the option string and update fields. 14968fae3551SRodney W. Grimes * Option arguments may either be -<option>=<value> or 14978fae3551SRodney W. Grimes * -<option> <value> 14988fae3551SRodney W. Grimes */ 14998fae3551SRodney W. Grimes int 15008fae3551SRodney W. Grimes do_opt(cpp, endcpp, ep, grp, has_hostp, exflagsp, cr) 15018fae3551SRodney W. Grimes char **cpp, **endcpp; 15028fae3551SRodney W. Grimes struct exportlist *ep; 15038fae3551SRodney W. Grimes struct grouplist *grp; 15048fae3551SRodney W. Grimes int *has_hostp; 15058fae3551SRodney W. Grimes int *exflagsp; 1506c0511d3bSBrian Feldman struct xucred *cr; 15078fae3551SRodney W. Grimes { 15088fae3551SRodney W. Grimes char *cpoptarg, *cpoptend; 15098fae3551SRodney W. Grimes char *cp, *endcp, *cpopt, savedc, savedc2; 15108fae3551SRodney W. Grimes int allflag, usedarg; 15118fae3551SRodney W. Grimes 1512cb479b11SAlfred Perlstein savedc2 = '\0'; 15138fae3551SRodney W. Grimes cpopt = *cpp; 15148fae3551SRodney W. Grimes cpopt++; 15158fae3551SRodney W. Grimes cp = *endcpp; 15168fae3551SRodney W. Grimes savedc = *cp; 15178fae3551SRodney W. Grimes *cp = '\0'; 15188fae3551SRodney W. Grimes while (cpopt && *cpopt) { 15198fae3551SRodney W. Grimes allflag = 1; 15208fae3551SRodney W. Grimes usedarg = -2; 152174853402SPhilippe Charnier if ((cpoptend = strchr(cpopt, ','))) { 15228fae3551SRodney W. Grimes *cpoptend++ = '\0'; 152374853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 15248fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 15258fae3551SRodney W. Grimes } else { 152674853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 15278fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 15288fae3551SRodney W. Grimes else { 15298fae3551SRodney W. Grimes *cp = savedc; 15308fae3551SRodney W. Grimes nextfield(&cp, &endcp); 15318fae3551SRodney W. Grimes **endcpp = '\0'; 15328fae3551SRodney W. Grimes if (endcp > cp && *cp != '-') { 15338fae3551SRodney W. Grimes cpoptarg = cp; 15348fae3551SRodney W. Grimes savedc2 = *endcp; 15358fae3551SRodney W. Grimes *endcp = '\0'; 15368fae3551SRodney W. Grimes usedarg = 0; 15378fae3551SRodney W. Grimes } 15388fae3551SRodney W. Grimes } 15398fae3551SRodney W. Grimes } 15408fae3551SRodney W. Grimes if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 15418fae3551SRodney W. Grimes *exflagsp |= MNT_EXRDONLY; 15428fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "maproot") || 15438fae3551SRodney W. Grimes !(allflag = strcmp(cpopt, "mapall")) || 15448fae3551SRodney W. Grimes !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) { 15458fae3551SRodney W. Grimes usedarg++; 15468fae3551SRodney W. Grimes parsecred(cpoptarg, cr); 15478fae3551SRodney W. Grimes if (allflag == 0) { 15488fae3551SRodney W. Grimes *exflagsp |= MNT_EXPORTANON; 15498fae3551SRodney W. Grimes opt_flags |= OP_MAPALL; 15508fae3551SRodney W. Grimes } else 15518fae3551SRodney W. Grimes opt_flags |= OP_MAPROOT; 15528fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "mask") || 15538fae3551SRodney W. Grimes !strcmp(cpopt, "m"))) { 15548fae3551SRodney W. Grimes if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { 155574853402SPhilippe Charnier syslog(LOG_ERR, "bad mask: %s", cpoptarg); 15568fae3551SRodney W. Grimes return (1); 15578fae3551SRodney W. Grimes } 15588fae3551SRodney W. Grimes usedarg++; 15598fae3551SRodney W. Grimes opt_flags |= OP_MASK; 15608fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "network") || 15618fae3551SRodney W. Grimes !strcmp(cpopt, "n"))) { 15628360efbdSAlfred Perlstein if (strchr(cpoptarg, '/') != NULL) { 15638360efbdSAlfred Perlstein if (debug) 15648360efbdSAlfred Perlstein fprintf(stderr, "setting OP_MASKLEN\n"); 15658360efbdSAlfred Perlstein opt_flags |= OP_MASKLEN; 15668360efbdSAlfred Perlstein } 15678fae3551SRodney W. Grimes if (grp->gr_type != GT_NULL) { 156874853402SPhilippe Charnier syslog(LOG_ERR, "network/host conflict"); 15698fae3551SRodney W. Grimes return (1); 15708fae3551SRodney W. Grimes } else if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 0)) { 157174853402SPhilippe Charnier syslog(LOG_ERR, "bad net: %s", cpoptarg); 15728fae3551SRodney W. Grimes return (1); 15738fae3551SRodney W. Grimes } 15748fae3551SRodney W. Grimes grp->gr_type = GT_NET; 15758fae3551SRodney W. Grimes *has_hostp = 1; 15768fae3551SRodney W. Grimes usedarg++; 15778fae3551SRodney W. Grimes opt_flags |= OP_NET; 15788fae3551SRodney W. Grimes } else if (!strcmp(cpopt, "alldirs")) { 15798fae3551SRodney W. Grimes opt_flags |= OP_ALLDIRS; 1580cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "public")) { 1581cb3923e0SDoug Rabson *exflagsp |= MNT_EXPUBLIC; 1582cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "webnfs")) { 1583cb3923e0SDoug Rabson *exflagsp |= (MNT_EXPUBLIC|MNT_EXRDONLY|MNT_EXPORTANON); 1584cb3923e0SDoug Rabson opt_flags |= OP_MAPALL; 1585cb3923e0SDoug Rabson } else if (cpoptarg && !strcmp(cpopt, "index")) { 1586cb3923e0SDoug Rabson ep->ex_indexfile = strdup(cpoptarg); 1587288fa14aSJoerg Wunsch } else if (!strcmp(cpopt, "quiet")) { 1588288fa14aSJoerg Wunsch opt_flags |= OP_QUIET; 15898fae3551SRodney W. Grimes } else { 159074853402SPhilippe Charnier syslog(LOG_ERR, "bad opt %s", cpopt); 15918fae3551SRodney W. Grimes return (1); 15928fae3551SRodney W. Grimes } 15938fae3551SRodney W. Grimes if (usedarg >= 0) { 15948fae3551SRodney W. Grimes *endcp = savedc2; 15958fae3551SRodney W. Grimes **endcpp = savedc; 15968fae3551SRodney W. Grimes if (usedarg > 0) { 15978fae3551SRodney W. Grimes *cpp = cp; 15988fae3551SRodney W. Grimes *endcpp = endcp; 15998fae3551SRodney W. Grimes } 16008fae3551SRodney W. Grimes return (0); 16018fae3551SRodney W. Grimes } 16028fae3551SRodney W. Grimes cpopt = cpoptend; 16038fae3551SRodney W. Grimes } 16048fae3551SRodney W. Grimes **endcpp = savedc; 16058fae3551SRodney W. Grimes return (0); 16068fae3551SRodney W. Grimes } 16078fae3551SRodney W. Grimes 16088fae3551SRodney W. Grimes /* 16098fae3551SRodney W. Grimes * Translate a character string to the corresponding list of network 16108fae3551SRodney W. Grimes * addresses for a hostname. 16118fae3551SRodney W. Grimes */ 16128fae3551SRodney W. Grimes int 16138b5a6d67SBill Paul get_host(cp, grp, tgrp) 16148fae3551SRodney W. Grimes char *cp; 16158fae3551SRodney W. Grimes struct grouplist *grp; 16168b5a6d67SBill Paul struct grouplist *tgrp; 16178fae3551SRodney W. Grimes { 16188b5a6d67SBill Paul struct grouplist *checkgrp; 161901709abfSIan Dowse struct addrinfo *ai, *tai, hints; 16208360efbdSAlfred Perlstein int ecode; 16218360efbdSAlfred Perlstein char host[NI_MAXHOST]; 16228fae3551SRodney W. Grimes 16238360efbdSAlfred Perlstein if (grp->gr_type != GT_NULL) { 16248360efbdSAlfred Perlstein syslog(LOG_ERR, "Bad netgroup type for ip host %s", cp); 16258fae3551SRodney W. Grimes return (1); 16268fae3551SRodney W. Grimes } 16278360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 16288360efbdSAlfred Perlstein hints.ai_flags = AI_CANONNAME; 16298360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_UDP; 16308360efbdSAlfred Perlstein ecode = getaddrinfo(cp, NULL, &hints, &ai); 16318360efbdSAlfred Perlstein if (ecode != 0) { 163201709abfSIan Dowse syslog(LOG_ERR,"can't get address info for host %s", cp); 16338360efbdSAlfred Perlstein return 1; 16348fae3551SRodney W. Grimes } 16358360efbdSAlfred Perlstein grp->gr_ptr.gt_addrinfo = ai; 16368360efbdSAlfred Perlstein while (ai != NULL) { 16378360efbdSAlfred Perlstein if (ai->ai_canonname == NULL) { 16388360efbdSAlfred Perlstein if (getnameinfo(ai->ai_addr, ai->ai_addrlen, host, 16398360efbdSAlfred Perlstein sizeof host, NULL, 0, ninumeric) != 0) 16408360efbdSAlfred Perlstein strlcpy(host, "?", sizeof(host)); 16418360efbdSAlfred Perlstein ai->ai_canonname = strdup(host); 16428360efbdSAlfred Perlstein ai->ai_flags |= AI_CANONNAME; 16436d359f31SIan Dowse } 16448fae3551SRodney W. Grimes if (debug) 164501709abfSIan Dowse fprintf(stderr, "got host %s\n", ai->ai_canonname); 164601709abfSIan Dowse /* 164701709abfSIan Dowse * Sanity check: make sure we don't already have an entry 164801709abfSIan Dowse * for this host in the grouplist. 164901709abfSIan Dowse */ 165001709abfSIan Dowse for (checkgrp = tgrp; checkgrp != NULL; 165101709abfSIan Dowse checkgrp = checkgrp->gr_next) { 165201709abfSIan Dowse if (checkgrp->gr_type != GT_HOST) 165301709abfSIan Dowse continue; 165401709abfSIan Dowse for (tai = checkgrp->gr_ptr.gt_addrinfo; tai != NULL; 165501709abfSIan Dowse tai = tai->ai_next) { 165660caaee2SIan Dowse if (sacmp(tai->ai_addr, ai->ai_addr, NULL) != 0) 165701709abfSIan Dowse continue; 165801709abfSIan Dowse if (debug) 165901709abfSIan Dowse fprintf(stderr, 166001709abfSIan Dowse "ignoring duplicate host %s\n", 166101709abfSIan Dowse ai->ai_canonname); 166201709abfSIan Dowse grp->gr_type = GT_IGNORE; 166301709abfSIan Dowse return (0); 166401709abfSIan Dowse } 166501709abfSIan Dowse } 16668360efbdSAlfred Perlstein ai = ai->ai_next; 16678360efbdSAlfred Perlstein } 166801709abfSIan Dowse grp->gr_type = GT_HOST; 16698fae3551SRodney W. Grimes return (0); 16708fae3551SRodney W. Grimes } 16718fae3551SRodney W. Grimes 16728fae3551SRodney W. Grimes /* 16738fae3551SRodney W. Grimes * Free up an exports list component 16748fae3551SRodney W. Grimes */ 16758fae3551SRodney W. Grimes void 16768fae3551SRodney W. Grimes free_exp(ep) 16778fae3551SRodney W. Grimes struct exportlist *ep; 16788fae3551SRodney W. Grimes { 16798fae3551SRodney W. Grimes 16808fae3551SRodney W. Grimes if (ep->ex_defdir) { 16818fae3551SRodney W. Grimes free_host(ep->ex_defdir->dp_hosts); 16828fae3551SRodney W. Grimes free((caddr_t)ep->ex_defdir); 16838fae3551SRodney W. Grimes } 16848fae3551SRodney W. Grimes if (ep->ex_fsdir) 16858fae3551SRodney W. Grimes free(ep->ex_fsdir); 1686cb3923e0SDoug Rabson if (ep->ex_indexfile) 1687cb3923e0SDoug Rabson free(ep->ex_indexfile); 16888fae3551SRodney W. Grimes free_dir(ep->ex_dirl); 16898fae3551SRodney W. Grimes free((caddr_t)ep); 16908fae3551SRodney W. Grimes } 16918fae3551SRodney W. Grimes 16928fae3551SRodney W. Grimes /* 16938fae3551SRodney W. Grimes * Free hosts. 16948fae3551SRodney W. Grimes */ 16958fae3551SRodney W. Grimes void 16968fae3551SRodney W. Grimes free_host(hp) 16978fae3551SRodney W. Grimes struct hostlist *hp; 16988fae3551SRodney W. Grimes { 16998fae3551SRodney W. Grimes struct hostlist *hp2; 17008fae3551SRodney W. Grimes 17018fae3551SRodney W. Grimes while (hp) { 17028fae3551SRodney W. Grimes hp2 = hp; 17038fae3551SRodney W. Grimes hp = hp->ht_next; 17048fae3551SRodney W. Grimes free((caddr_t)hp2); 17058fae3551SRodney W. Grimes } 17068fae3551SRodney W. Grimes } 17078fae3551SRodney W. Grimes 17088fae3551SRodney W. Grimes struct hostlist * 17098fae3551SRodney W. Grimes get_ht() 17108fae3551SRodney W. Grimes { 17118fae3551SRodney W. Grimes struct hostlist *hp; 17128fae3551SRodney W. Grimes 17138fae3551SRodney W. Grimes hp = (struct hostlist *)malloc(sizeof (struct hostlist)); 17148fae3551SRodney W. Grimes if (hp == (struct hostlist *)NULL) 17158fae3551SRodney W. Grimes out_of_mem(); 17168fae3551SRodney W. Grimes hp->ht_next = (struct hostlist *)NULL; 1717a62dc406SDoug Rabson hp->ht_flag = 0; 17188fae3551SRodney W. Grimes return (hp); 17198fae3551SRodney W. Grimes } 17208fae3551SRodney W. Grimes 17218fae3551SRodney W. Grimes /* 17228fae3551SRodney W. Grimes * Out of memory, fatal 17238fae3551SRodney W. Grimes */ 17248fae3551SRodney W. Grimes void 17258fae3551SRodney W. Grimes out_of_mem() 17268fae3551SRodney W. Grimes { 17278fae3551SRodney W. Grimes 172874853402SPhilippe Charnier syslog(LOG_ERR, "out of memory"); 17298fae3551SRodney W. Grimes exit(2); 17308fae3551SRodney W. Grimes } 17318fae3551SRodney W. Grimes 17328fae3551SRodney W. Grimes /* 17338fae3551SRodney W. Grimes * Do the mount syscall with the update flag to push the export info into 17348fae3551SRodney W. Grimes * the kernel. 17358fae3551SRodney W. Grimes */ 17368fae3551SRodney W. Grimes int 17378fae3551SRodney W. Grimes do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb) 17388fae3551SRodney W. Grimes struct exportlist *ep; 17398fae3551SRodney W. Grimes struct grouplist *grp; 17408fae3551SRodney W. Grimes int exflags; 1741c0511d3bSBrian Feldman struct xucred *anoncrp; 17428fae3551SRodney W. Grimes char *dirp; 17438fae3551SRodney W. Grimes int dirplen; 17448fae3551SRodney W. Grimes struct statfs *fsb; 17458fae3551SRodney W. Grimes { 1746f93caef2SIan Dowse struct statfs fsb1; 17478360efbdSAlfred Perlstein struct addrinfo *ai; 174860caaee2SIan Dowse struct export_args *eap; 17498360efbdSAlfred Perlstein char *cp = NULL; 17508fae3551SRodney W. Grimes int done; 17518fae3551SRodney W. Grimes char savedc = '\0'; 17528fae3551SRodney W. Grimes union { 17538fae3551SRodney W. Grimes struct ufs_args ua; 17548fae3551SRodney W. Grimes struct iso_args ia; 1755a62dc406SDoug Rabson struct msdosfs_args da; 17569300c696SSemen Ustimenko struct ntfs_args na; 17578fae3551SRodney W. Grimes } args; 17588fae3551SRodney W. Grimes 175960caaee2SIan Dowse bzero(&args, sizeof args); 176060caaee2SIan Dowse /* XXX, we assume that all xx_args look like ufs_args. */ 17618fae3551SRodney W. Grimes args.ua.fspec = 0; 176260caaee2SIan Dowse eap = &args.ua.export; 176360caaee2SIan Dowse 176460caaee2SIan Dowse eap->ex_flags = exflags; 176560caaee2SIan Dowse eap->ex_anon = *anoncrp; 176660caaee2SIan Dowse eap->ex_indexfile = ep->ex_indexfile; 17676d359f31SIan Dowse if (grp->gr_type == GT_HOST) 17688360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 17696d359f31SIan Dowse else 17706d359f31SIan Dowse ai = NULL; 17718fae3551SRodney W. Grimes done = FALSE; 17728fae3551SRodney W. Grimes while (!done) { 17738fae3551SRodney W. Grimes switch (grp->gr_type) { 17748fae3551SRodney W. Grimes case GT_HOST: 17756d359f31SIan Dowse if (ai->ai_addr->sa_family == AF_INET6 && have_v6 == 0) 17768360efbdSAlfred Perlstein goto skip; 177760caaee2SIan Dowse eap->ex_addr = ai->ai_addr; 177860caaee2SIan Dowse eap->ex_addrlen = ai->ai_addrlen; 177960caaee2SIan Dowse eap->ex_masklen = 0; 17808fae3551SRodney W. Grimes break; 17818fae3551SRodney W. Grimes case GT_NET: 178260caaee2SIan Dowse if (grp->gr_ptr.gt_net.nt_net.ss_family == AF_INET6 && 17838360efbdSAlfred Perlstein have_v6 == 0) 17848360efbdSAlfred Perlstein goto skip; 178560caaee2SIan Dowse eap->ex_addr = 178660caaee2SIan Dowse (struct sockaddr *)&grp->gr_ptr.gt_net.nt_net; 178760caaee2SIan Dowse eap->ex_addrlen = args.ua.export.ex_addr->sa_len; 178860caaee2SIan Dowse eap->ex_mask = 178960caaee2SIan Dowse (struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask; 179060caaee2SIan Dowse eap->ex_masklen = args.ua.export.ex_mask->sa_len; 17918fae3551SRodney W. Grimes break; 17926d359f31SIan Dowse case GT_DEFAULT: 179360caaee2SIan Dowse eap->ex_addr = NULL; 179460caaee2SIan Dowse eap->ex_addrlen = 0; 179560caaee2SIan Dowse eap->ex_mask = NULL; 179660caaee2SIan Dowse eap->ex_masklen = 0; 17976d359f31SIan Dowse break; 17988b5a6d67SBill Paul case GT_IGNORE: 17998b5a6d67SBill Paul return(0); 18008b5a6d67SBill Paul break; 18018fae3551SRodney W. Grimes default: 180274853402SPhilippe Charnier syslog(LOG_ERR, "bad grouptype"); 18038fae3551SRodney W. Grimes if (cp) 18048fae3551SRodney W. Grimes *cp = savedc; 18058fae3551SRodney W. Grimes return (1); 18068fae3551SRodney W. Grimes }; 18078fae3551SRodney W. Grimes 18088fae3551SRodney W. Grimes /* 18098fae3551SRodney W. Grimes * XXX: 18108fae3551SRodney W. Grimes * Maybe I should just use the fsb->f_mntonname path instead 18118fae3551SRodney W. Grimes * of looping back up the dirp to the mount point?? 18128fae3551SRodney W. Grimes * Also, needs to know how to export all types of local 181387564113SPeter Wemm * exportable filesystems and not just "ufs". 18148fae3551SRodney W. Grimes */ 1815a62dc406SDoug Rabson while (mount(fsb->f_fstypename, dirp, 18168fae3551SRodney W. Grimes fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) { 18178fae3551SRodney W. Grimes if (cp) 18188fae3551SRodney W. Grimes *cp-- = savedc; 18198fae3551SRodney W. Grimes else 18208fae3551SRodney W. Grimes cp = dirp + dirplen - 1; 1821288fa14aSJoerg Wunsch if (opt_flags & OP_QUIET) 1822288fa14aSJoerg Wunsch return (1); 18238fae3551SRodney W. Grimes if (errno == EPERM) { 182401709abfSIan Dowse if (debug) 182501709abfSIan Dowse warnx("can't change attributes for %s", 182601709abfSIan Dowse dirp); 18278fae3551SRodney W. Grimes syslog(LOG_ERR, 182874853402SPhilippe Charnier "can't change attributes for %s", dirp); 18298fae3551SRodney W. Grimes return (1); 18308fae3551SRodney W. Grimes } 18318fae3551SRodney W. Grimes if (opt_flags & OP_ALLDIRS) { 1832288fa14aSJoerg Wunsch if (errno == EINVAL) 1833288fa14aSJoerg Wunsch syslog(LOG_ERR, 1834288fa14aSJoerg Wunsch "-alldirs requested but %s is not a filesystem mountpoint", 1835288fa14aSJoerg Wunsch dirp); 1836288fa14aSJoerg Wunsch else 1837288fa14aSJoerg Wunsch syslog(LOG_ERR, 1838288fa14aSJoerg Wunsch "could not remount %s: %m", 18393980ac4fSGarrett Wollman dirp); 18408fae3551SRodney W. Grimes return (1); 18418fae3551SRodney W. Grimes } 18428fae3551SRodney W. Grimes /* back up over the last component */ 18438fae3551SRodney W. Grimes while (*cp == '/' && cp > dirp) 18448fae3551SRodney W. Grimes cp--; 18458fae3551SRodney W. Grimes while (*(cp - 1) != '/' && cp > dirp) 18468fae3551SRodney W. Grimes cp--; 18478fae3551SRodney W. Grimes if (cp == dirp) { 18488fae3551SRodney W. Grimes if (debug) 184974853402SPhilippe Charnier warnx("mnt unsucc"); 185074853402SPhilippe Charnier syslog(LOG_ERR, "can't export %s", dirp); 18518fae3551SRodney W. Grimes return (1); 18528fae3551SRodney W. Grimes } 18538fae3551SRodney W. Grimes savedc = *cp; 18548fae3551SRodney W. Grimes *cp = '\0'; 1855f93caef2SIan Dowse /* Check that we're still on the same filesystem. */ 1856f93caef2SIan Dowse if (statfs(dirp, &fsb1) != 0 || bcmp(&fsb1.f_fsid, 1857f93caef2SIan Dowse &fsb->f_fsid, sizeof(fsb1.f_fsid)) != 0) { 1858f93caef2SIan Dowse *cp = savedc; 1859f93caef2SIan Dowse syslog(LOG_ERR, "can't export %s", dirp); 1860f93caef2SIan Dowse return (1); 1861f93caef2SIan Dowse } 18628fae3551SRodney W. Grimes } 18638360efbdSAlfred Perlstein skip: 18646d359f31SIan Dowse if (ai != NULL) 18658360efbdSAlfred Perlstein ai = ai->ai_next; 18668360efbdSAlfred Perlstein if (ai == NULL) 18678fae3551SRodney W. Grimes done = TRUE; 18688fae3551SRodney W. Grimes } 18698fae3551SRodney W. Grimes if (cp) 18708fae3551SRodney W. Grimes *cp = savedc; 18718fae3551SRodney W. Grimes return (0); 18728fae3551SRodney W. Grimes } 18738fae3551SRodney W. Grimes 18748fae3551SRodney W. Grimes /* 18758fae3551SRodney W. Grimes * Translate a net address. 187660caaee2SIan Dowse * 187760caaee2SIan Dowse * If `maskflg' is nonzero, then `cp' is a netmask, not a network address. 18788fae3551SRodney W. Grimes */ 18798fae3551SRodney W. Grimes int 18808fae3551SRodney W. Grimes get_net(cp, net, maskflg) 18818fae3551SRodney W. Grimes char *cp; 18828fae3551SRodney W. Grimes struct netmsk *net; 18838fae3551SRodney W. Grimes int maskflg; 18848fae3551SRodney W. Grimes { 1885931c04f1SIan Dowse struct netent *np = NULL; 18868360efbdSAlfred Perlstein char *name, *p, *prefp; 188760caaee2SIan Dowse struct sockaddr_in sin; 1888931c04f1SIan Dowse struct sockaddr *sa = NULL; 18898360efbdSAlfred Perlstein struct addrinfo hints, *ai = NULL; 18908360efbdSAlfred Perlstein char netname[NI_MAXHOST]; 18918360efbdSAlfred Perlstein long preflen; 18928fae3551SRodney W. Grimes 189301709abfSIan Dowse p = prefp = NULL; 18948360efbdSAlfred Perlstein if ((opt_flags & OP_MASKLEN) && !maskflg) { 18958360efbdSAlfred Perlstein p = strchr(cp, '/'); 18968360efbdSAlfred Perlstein *p = '\0'; 18978360efbdSAlfred Perlstein prefp = p + 1; 18988360efbdSAlfred Perlstein } 18998360efbdSAlfred Perlstein 1900931c04f1SIan Dowse /* 1901931c04f1SIan Dowse * Check for a numeric address first. We wish to avoid 1902931c04f1SIan Dowse * possible DNS lookups in getnetbyname(). 1903931c04f1SIan Dowse */ 1904931c04f1SIan Dowse if (isxdigit(*cp) || *cp == ':') { 19058360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 190660caaee2SIan Dowse /* Ensure the mask and the network have the same family. */ 190760caaee2SIan Dowse if (maskflg && (opt_flags & OP_NET)) 190860caaee2SIan Dowse hints.ai_family = net->nt_net.ss_family; 190960caaee2SIan Dowse else if (!maskflg && (opt_flags & OP_HAVEMASK)) 191060caaee2SIan Dowse hints.ai_family = net->nt_mask.ss_family; 191160caaee2SIan Dowse else 19128360efbdSAlfred Perlstein hints.ai_family = AF_UNSPEC; 19138360efbdSAlfred Perlstein hints.ai_flags = AI_NUMERICHOST; 1914931c04f1SIan Dowse if (getaddrinfo(cp, NULL, &hints, &ai) == 0) 1915931c04f1SIan Dowse sa = ai->ai_addr; 1916931c04f1SIan Dowse if (sa != NULL && ai->ai_family == AF_INET) { 19178fae3551SRodney W. Grimes /* 191860caaee2SIan Dowse * The address in `cp' is really a network address, so 191960caaee2SIan Dowse * use inet_network() to re-interpret this correctly. 192060caaee2SIan Dowse * e.g. "127.1" means 127.1.0.0, not 127.0.0.1. 19218fae3551SRodney W. Grimes */ 192260caaee2SIan Dowse bzero(&sin, sizeof sin); 19238360efbdSAlfred Perlstein sin.sin_family = AF_INET; 19248360efbdSAlfred Perlstein sin.sin_len = sizeof sin; 19258360efbdSAlfred Perlstein sin.sin_addr = inet_makeaddr(inet_network(cp), 0); 19268360efbdSAlfred Perlstein if (debug) 192760caaee2SIan Dowse fprintf(stderr, "get_net: v4 addr %s\n", 192860caaee2SIan Dowse inet_ntoa(sin.sin_addr)); 19298360efbdSAlfred Perlstein sa = (struct sockaddr *)&sin; 1930931c04f1SIan Dowse } 1931931c04f1SIan Dowse } 1932931c04f1SIan Dowse if (sa == NULL && (np = getnetbyname(cp)) != NULL) { 1933931c04f1SIan Dowse bzero(&sin, sizeof sin); 1934931c04f1SIan Dowse sin.sin_family = AF_INET; 1935931c04f1SIan Dowse sin.sin_len = sizeof sin; 1936931c04f1SIan Dowse sin.sin_addr = inet_makeaddr(np->n_net, 0); 1937931c04f1SIan Dowse sa = (struct sockaddr *)&sin; 1938931c04f1SIan Dowse } 1939931c04f1SIan Dowse if (sa == NULL) 19408360efbdSAlfred Perlstein goto fail; 19418360efbdSAlfred Perlstein 194260caaee2SIan Dowse if (maskflg) { 194360caaee2SIan Dowse /* The specified sockaddr is a mask. */ 194460caaee2SIan Dowse if (checkmask(sa) != 0) 19458360efbdSAlfred Perlstein goto fail; 194660caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 194760caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 194860caaee2SIan Dowse } else { 194960caaee2SIan Dowse /* The specified sockaddr is a network address. */ 195060caaee2SIan Dowse bcopy(sa, &net->nt_net, sa->sa_len); 19510f4b7baaSPaul Traina 195260caaee2SIan Dowse /* Get a network name for the export list. */ 195360caaee2SIan Dowse if (np) { 195460caaee2SIan Dowse name = np->n_name; 195560caaee2SIan Dowse } else if (getnameinfo(sa, sa->sa_len, netname, sizeof netname, 195660caaee2SIan Dowse NULL, 0, ninumeric) == 0) { 195760caaee2SIan Dowse name = netname; 195860caaee2SIan Dowse } else { 195960caaee2SIan Dowse goto fail; 196060caaee2SIan Dowse } 196160caaee2SIan Dowse if ((net->nt_name = strdup(name)) == NULL) 196260caaee2SIan Dowse out_of_mem(); 196360caaee2SIan Dowse 196460caaee2SIan Dowse /* 196560caaee2SIan Dowse * Extract a mask from either a "/<masklen>" suffix, or 196660caaee2SIan Dowse * from the class of an IPv4 address. 196760caaee2SIan Dowse */ 19688360efbdSAlfred Perlstein if (opt_flags & OP_MASKLEN) { 19698360efbdSAlfred Perlstein preflen = strtol(prefp, NULL, 10); 197060caaee2SIan Dowse if (preflen < 0L || preflen == LONG_MAX) 19718360efbdSAlfred Perlstein goto fail; 197260caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 197360caaee2SIan Dowse if (makemask(&net->nt_mask, (int)preflen) != 0) 197460caaee2SIan Dowse goto fail; 197560caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 19768360efbdSAlfred Perlstein *p = '/'; 197760caaee2SIan Dowse } else if (sa->sa_family == AF_INET && 197860caaee2SIan Dowse (opt_flags & OP_MASK) == 0) { 197960caaee2SIan Dowse in_addr_t addr; 19808360efbdSAlfred Perlstein 198160caaee2SIan Dowse addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; 198260caaee2SIan Dowse if (IN_CLASSA(addr)) 198360caaee2SIan Dowse preflen = 8; 198460caaee2SIan Dowse else if (IN_CLASSB(addr)) 198560caaee2SIan Dowse preflen = 16; 198660caaee2SIan Dowse else if (IN_CLASSC(addr)) 198760caaee2SIan Dowse preflen = 24; 198860caaee2SIan Dowse else if (IN_CLASSD(addr)) 198960caaee2SIan Dowse preflen = 28; 19908360efbdSAlfred Perlstein else 199160caaee2SIan Dowse preflen = 32; /* XXX */ 199260caaee2SIan Dowse 199360caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 199460caaee2SIan Dowse makemask(&net->nt_mask, (int)preflen); 199560caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 199660caaee2SIan Dowse } 19978360efbdSAlfred Perlstein } 19988360efbdSAlfred Perlstein 19998360efbdSAlfred Perlstein if (ai) 20008360efbdSAlfred Perlstein freeaddrinfo(ai); 20018360efbdSAlfred Perlstein return 0; 20028360efbdSAlfred Perlstein 20038360efbdSAlfred Perlstein fail: 20048360efbdSAlfred Perlstein if (ai) 20058360efbdSAlfred Perlstein freeaddrinfo(ai); 20068360efbdSAlfred Perlstein return 1; 20078fae3551SRodney W. Grimes } 20088fae3551SRodney W. Grimes 20098fae3551SRodney W. Grimes /* 20108fae3551SRodney W. Grimes * Parse out the next white space separated field 20118fae3551SRodney W. Grimes */ 20128fae3551SRodney W. Grimes void 20138fae3551SRodney W. Grimes nextfield(cp, endcp) 20148fae3551SRodney W. Grimes char **cp; 20158fae3551SRodney W. Grimes char **endcp; 20168fae3551SRodney W. Grimes { 20178fae3551SRodney W. Grimes char *p; 20188fae3551SRodney W. Grimes 20198fae3551SRodney W. Grimes p = *cp; 20208fae3551SRodney W. Grimes while (*p == ' ' || *p == '\t') 20218fae3551SRodney W. Grimes p++; 20228fae3551SRodney W. Grimes if (*p == '\n' || *p == '\0') 20238fae3551SRodney W. Grimes *cp = *endcp = p; 20248fae3551SRodney W. Grimes else { 20258fae3551SRodney W. Grimes *cp = p++; 20268fae3551SRodney W. Grimes while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 20278fae3551SRodney W. Grimes p++; 20288fae3551SRodney W. Grimes *endcp = p; 20298fae3551SRodney W. Grimes } 20308fae3551SRodney W. Grimes } 20318fae3551SRodney W. Grimes 20328fae3551SRodney W. Grimes /* 20338fae3551SRodney W. Grimes * Get an exports file line. Skip over blank lines and handle line 20348fae3551SRodney W. Grimes * continuations. 20358fae3551SRodney W. Grimes */ 20368fae3551SRodney W. Grimes int 20378fae3551SRodney W. Grimes get_line() 20388fae3551SRodney W. Grimes { 20398fae3551SRodney W. Grimes char *p, *cp; 204091ca1a91SIan Dowse size_t len; 20418fae3551SRodney W. Grimes int totlen, cont_line; 20428fae3551SRodney W. Grimes 20438fae3551SRodney W. Grimes /* 20448fae3551SRodney W. Grimes * Loop around ignoring blank lines and getting all continuation lines. 20458fae3551SRodney W. Grimes */ 20468fae3551SRodney W. Grimes p = line; 20478fae3551SRodney W. Grimes totlen = 0; 20488fae3551SRodney W. Grimes do { 204991ca1a91SIan Dowse if ((p = fgetln(exp_file, &len)) == NULL) 20508fae3551SRodney W. Grimes return (0); 20518fae3551SRodney W. Grimes cp = p + len - 1; 20528fae3551SRodney W. Grimes cont_line = 0; 20538fae3551SRodney W. Grimes while (cp >= p && 20548fae3551SRodney W. Grimes (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '\\')) { 20558fae3551SRodney W. Grimes if (*cp == '\\') 20568fae3551SRodney W. Grimes cont_line = 1; 20578fae3551SRodney W. Grimes cp--; 20588fae3551SRodney W. Grimes len--; 20598fae3551SRodney W. Grimes } 2060376f8390SDima Dorfman if (cont_line) { 2061376f8390SDima Dorfman *++cp = ' '; 2062376f8390SDima Dorfman len++; 2063376f8390SDima Dorfman } 206491ca1a91SIan Dowse if (linesize < len + totlen + 1) { 206591ca1a91SIan Dowse linesize = len + totlen + 1; 206691ca1a91SIan Dowse line = realloc(line, linesize); 206791ca1a91SIan Dowse if (line == NULL) 206891ca1a91SIan Dowse out_of_mem(); 206991ca1a91SIan Dowse } 207091ca1a91SIan Dowse memcpy(line + totlen, p, len); 20718fae3551SRodney W. Grimes totlen += len; 207291ca1a91SIan Dowse line[totlen] = '\0'; 20738fae3551SRodney W. Grimes } while (totlen == 0 || cont_line); 20748fae3551SRodney W. Grimes return (1); 20758fae3551SRodney W. Grimes } 20768fae3551SRodney W. Grimes 20778fae3551SRodney W. Grimes /* 20788fae3551SRodney W. Grimes * Parse a description of a credential. 20798fae3551SRodney W. Grimes */ 20808fae3551SRodney W. Grimes void 20818fae3551SRodney W. Grimes parsecred(namelist, cr) 20828fae3551SRodney W. Grimes char *namelist; 2083c0511d3bSBrian Feldman struct xucred *cr; 20848fae3551SRodney W. Grimes { 20858fae3551SRodney W. Grimes char *name; 20868fae3551SRodney W. Grimes int cnt; 20878fae3551SRodney W. Grimes char *names; 20888fae3551SRodney W. Grimes struct passwd *pw; 20898fae3551SRodney W. Grimes struct group *gr; 20908fae3551SRodney W. Grimes int ngroups, groups[NGROUPS + 1]; 20918fae3551SRodney W. Grimes 209276183f34SDima Dorfman cr->cr_version = XUCRED_VERSION; 20938fae3551SRodney W. Grimes /* 209474853402SPhilippe Charnier * Set up the unprivileged user. 20958fae3551SRodney W. Grimes */ 20968fae3551SRodney W. Grimes cr->cr_uid = -2; 20978fae3551SRodney W. Grimes cr->cr_groups[0] = -2; 20988fae3551SRodney W. Grimes cr->cr_ngroups = 1; 20998fae3551SRodney W. Grimes /* 21008fae3551SRodney W. Grimes * Get the user's password table entry. 21018fae3551SRodney W. Grimes */ 21028fae3551SRodney W. Grimes names = strsep(&namelist, " \t\n"); 21038fae3551SRodney W. Grimes name = strsep(&names, ":"); 21048fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') 21058fae3551SRodney W. Grimes pw = getpwuid(atoi(name)); 21068fae3551SRodney W. Grimes else 21078fae3551SRodney W. Grimes pw = getpwnam(name); 21088fae3551SRodney W. Grimes /* 21098fae3551SRodney W. Grimes * Credentials specified as those of a user. 21108fae3551SRodney W. Grimes */ 21118fae3551SRodney W. Grimes if (names == NULL) { 21128fae3551SRodney W. Grimes if (pw == NULL) { 211374853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 21148fae3551SRodney W. Grimes return; 21158fae3551SRodney W. Grimes } 21168fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 21178fae3551SRodney W. Grimes ngroups = NGROUPS + 1; 21188fae3551SRodney W. Grimes if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) 211974853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 21208fae3551SRodney W. Grimes /* 21218fae3551SRodney W. Grimes * Convert from int's to gid_t's and compress out duplicate 21228fae3551SRodney W. Grimes */ 21238fae3551SRodney W. Grimes cr->cr_ngroups = ngroups - 1; 21248fae3551SRodney W. Grimes cr->cr_groups[0] = groups[0]; 21258fae3551SRodney W. Grimes for (cnt = 2; cnt < ngroups; cnt++) 21268fae3551SRodney W. Grimes cr->cr_groups[cnt - 1] = groups[cnt]; 21278fae3551SRodney W. Grimes return; 21288fae3551SRodney W. Grimes } 21298fae3551SRodney W. Grimes /* 21308fae3551SRodney W. Grimes * Explicit credential specified as a colon separated list: 21318fae3551SRodney W. Grimes * uid:gid:gid:... 21328fae3551SRodney W. Grimes */ 21338fae3551SRodney W. Grimes if (pw != NULL) 21348fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 21358fae3551SRodney W. Grimes else if (isdigit(*name) || *name == '-') 21368fae3551SRodney W. Grimes cr->cr_uid = atoi(name); 21378fae3551SRodney W. Grimes else { 213874853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 21398fae3551SRodney W. Grimes return; 21408fae3551SRodney W. Grimes } 21418fae3551SRodney W. Grimes cr->cr_ngroups = 0; 21428fae3551SRodney W. Grimes while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { 21438fae3551SRodney W. Grimes name = strsep(&names, ":"); 21448fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') { 21458fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = atoi(name); 21468fae3551SRodney W. Grimes } else { 21478fae3551SRodney W. Grimes if ((gr = getgrnam(name)) == NULL) { 214874853402SPhilippe Charnier syslog(LOG_ERR, "unknown group: %s", name); 21498fae3551SRodney W. Grimes continue; 21508fae3551SRodney W. Grimes } 21518fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; 21528fae3551SRodney W. Grimes } 21538fae3551SRodney W. Grimes } 21548fae3551SRodney W. Grimes if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) 215574853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 21568fae3551SRodney W. Grimes } 21578fae3551SRodney W. Grimes 21588fae3551SRodney W. Grimes #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 21598fae3551SRodney W. Grimes /* 21608fae3551SRodney W. Grimes * Routines that maintain the remote mounttab 21618fae3551SRodney W. Grimes */ 21628fae3551SRodney W. Grimes void 21638fae3551SRodney W. Grimes get_mountlist() 21648fae3551SRodney W. Grimes { 21658fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 216687564113SPeter Wemm char *host, *dirp, *cp; 21678fae3551SRodney W. Grimes char str[STRSIZ]; 21688fae3551SRodney W. Grimes FILE *mlfile; 21698fae3551SRodney W. Grimes 21708fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) { 217139539916SBill Fumerola if (errno == ENOENT) 217239539916SBill Fumerola return; 217339539916SBill Fumerola else { 217474853402SPhilippe Charnier syslog(LOG_ERR, "can't open %s", _PATH_RMOUNTLIST); 21758fae3551SRodney W. Grimes return; 21768fae3551SRodney W. Grimes } 217739539916SBill Fumerola } 21788fae3551SRodney W. Grimes mlpp = &mlhead; 21798fae3551SRodney W. Grimes while (fgets(str, STRSIZ, mlfile) != NULL) { 218087564113SPeter Wemm cp = str; 218187564113SPeter Wemm host = strsep(&cp, " \t\n"); 218287564113SPeter Wemm dirp = strsep(&cp, " \t\n"); 218387564113SPeter Wemm if (host == NULL || dirp == NULL) 21848fae3551SRodney W. Grimes continue; 21858fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 218674853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 218774853402SPhilippe Charnier out_of_mem(); 218887564113SPeter Wemm strncpy(mlp->ml_host, host, RPCMNT_NAMELEN); 218987564113SPeter Wemm mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 219087564113SPeter Wemm strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 219187564113SPeter Wemm mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 21928fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 21938fae3551SRodney W. Grimes *mlpp = mlp; 21948fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 21958fae3551SRodney W. Grimes } 21968fae3551SRodney W. Grimes fclose(mlfile); 21978fae3551SRodney W. Grimes } 21988fae3551SRodney W. Grimes 219901709abfSIan Dowse void 220001709abfSIan Dowse del_mlist(char *hostp, char *dirp) 22018fae3551SRodney W. Grimes { 22028fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 22038fae3551SRodney W. Grimes struct mountlist *mlp2; 22048fae3551SRodney W. Grimes FILE *mlfile; 22058fae3551SRodney W. Grimes int fnd = 0; 22068fae3551SRodney W. Grimes 22078fae3551SRodney W. Grimes mlpp = &mlhead; 22088fae3551SRodney W. Grimes mlp = mlhead; 22098fae3551SRodney W. Grimes while (mlp) { 22108fae3551SRodney W. Grimes if (!strcmp(mlp->ml_host, hostp) && 22118fae3551SRodney W. Grimes (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 22128fae3551SRodney W. Grimes fnd = 1; 22138fae3551SRodney W. Grimes mlp2 = mlp; 22148fae3551SRodney W. Grimes *mlpp = mlp = mlp->ml_next; 22158fae3551SRodney W. Grimes free((caddr_t)mlp2); 22168fae3551SRodney W. Grimes } else { 22178fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 22188fae3551SRodney W. Grimes mlp = mlp->ml_next; 22198fae3551SRodney W. Grimes } 22208fae3551SRodney W. Grimes } 22218fae3551SRodney W. Grimes if (fnd) { 22228fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 222374853402SPhilippe Charnier syslog(LOG_ERR,"can't update %s", _PATH_RMOUNTLIST); 22248fae3551SRodney W. Grimes return; 22258fae3551SRodney W. Grimes } 22268fae3551SRodney W. Grimes mlp = mlhead; 22278fae3551SRodney W. Grimes while (mlp) { 22288fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 22298fae3551SRodney W. Grimes mlp = mlp->ml_next; 22308fae3551SRodney W. Grimes } 22318fae3551SRodney W. Grimes fclose(mlfile); 22328fae3551SRodney W. Grimes } 22338fae3551SRodney W. Grimes } 22348fae3551SRodney W. Grimes 22358fae3551SRodney W. Grimes void 22368fae3551SRodney W. Grimes add_mlist(hostp, dirp) 22378fae3551SRodney W. Grimes char *hostp, *dirp; 22388fae3551SRodney W. Grimes { 22398fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 22408fae3551SRodney W. Grimes FILE *mlfile; 22418fae3551SRodney W. Grimes 22428fae3551SRodney W. Grimes mlpp = &mlhead; 22438fae3551SRodney W. Grimes mlp = mlhead; 22448fae3551SRodney W. Grimes while (mlp) { 22458fae3551SRodney W. Grimes if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 22468fae3551SRodney W. Grimes return; 22478fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 22488fae3551SRodney W. Grimes mlp = mlp->ml_next; 22498fae3551SRodney W. Grimes } 22508fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 225174853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 225274853402SPhilippe Charnier out_of_mem(); 22538fae3551SRodney W. Grimes strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 22548fae3551SRodney W. Grimes mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 22558fae3551SRodney W. Grimes strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 22568fae3551SRodney W. Grimes mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 22578fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 22588fae3551SRodney W. Grimes *mlpp = mlp; 22598fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 226074853402SPhilippe Charnier syslog(LOG_ERR, "can't update %s", _PATH_RMOUNTLIST); 22618fae3551SRodney W. Grimes return; 22628fae3551SRodney W. Grimes } 22638fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 22648fae3551SRodney W. Grimes fclose(mlfile); 22658fae3551SRodney W. Grimes } 22668fae3551SRodney W. Grimes 22678fae3551SRodney W. Grimes /* 22688fae3551SRodney W. Grimes * Free up a group list. 22698fae3551SRodney W. Grimes */ 22708fae3551SRodney W. Grimes void 22718fae3551SRodney W. Grimes free_grp(grp) 22728fae3551SRodney W. Grimes struct grouplist *grp; 22738fae3551SRodney W. Grimes { 22748fae3551SRodney W. Grimes if (grp->gr_type == GT_HOST) { 22758360efbdSAlfred Perlstein if (grp->gr_ptr.gt_addrinfo != NULL) 22768360efbdSAlfred Perlstein freeaddrinfo(grp->gr_ptr.gt_addrinfo); 22778fae3551SRodney W. Grimes } else if (grp->gr_type == GT_NET) { 22788fae3551SRodney W. Grimes if (grp->gr_ptr.gt_net.nt_name) 22798fae3551SRodney W. Grimes free(grp->gr_ptr.gt_net.nt_name); 22808fae3551SRodney W. Grimes } 22818fae3551SRodney W. Grimes free((caddr_t)grp); 22828fae3551SRodney W. Grimes } 22838fae3551SRodney W. Grimes 22848fae3551SRodney W. Grimes #ifdef DEBUG 22858fae3551SRodney W. Grimes void 22868fae3551SRodney W. Grimes SYSLOG(int pri, const char *fmt, ...) 22878fae3551SRodney W. Grimes { 22888fae3551SRodney W. Grimes va_list ap; 22898fae3551SRodney W. Grimes 22908fae3551SRodney W. Grimes va_start(ap, fmt); 22918fae3551SRodney W. Grimes vfprintf(stderr, fmt, ap); 22928fae3551SRodney W. Grimes va_end(ap); 22938fae3551SRodney W. Grimes } 22948fae3551SRodney W. Grimes #endif /* DEBUG */ 22958fae3551SRodney W. Grimes 22968fae3551SRodney W. Grimes /* 22978fae3551SRodney W. Grimes * Check options for consistency. 22988fae3551SRodney W. Grimes */ 22998fae3551SRodney W. Grimes int 23008fae3551SRodney W. Grimes check_options(dp) 23018fae3551SRodney W. Grimes struct dirlist *dp; 23028fae3551SRodney W. Grimes { 23038fae3551SRodney W. Grimes 23048fae3551SRodney W. Grimes if (dp == (struct dirlist *)NULL) 23058fae3551SRodney W. Grimes return (1); 230691196234SPeter Wemm if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL)) { 230791196234SPeter Wemm syslog(LOG_ERR, "-mapall and -maproot mutually exclusive"); 23088fae3551SRodney W. Grimes return (1); 23098fae3551SRodney W. Grimes } 23108fae3551SRodney W. Grimes if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { 231160caaee2SIan Dowse syslog(LOG_ERR, "-mask requires -network"); 231260caaee2SIan Dowse return (1); 231360caaee2SIan Dowse } 231460caaee2SIan Dowse if ((opt_flags & OP_NET) && (opt_flags & OP_HAVEMASK) == 0) { 231560caaee2SIan Dowse syslog(LOG_ERR, "-network requires mask specification"); 231660caaee2SIan Dowse return (1); 231760caaee2SIan Dowse } 231860caaee2SIan Dowse if ((opt_flags & OP_MASK) && (opt_flags & OP_MASKLEN)) { 231960caaee2SIan Dowse syslog(LOG_ERR, "-mask and /masklen are mutually exclusive"); 23208fae3551SRodney W. Grimes return (1); 23218fae3551SRodney W. Grimes } 23228fae3551SRodney W. Grimes if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { 23236436fcb9SAlexander Langer syslog(LOG_ERR, "-alldirs has multiple directories"); 23248fae3551SRodney W. Grimes return (1); 23258fae3551SRodney W. Grimes } 23268fae3551SRodney W. Grimes return (0); 23278fae3551SRodney W. Grimes } 23288fae3551SRodney W. Grimes 23298fae3551SRodney W. Grimes /* 23308fae3551SRodney W. Grimes * Check an absolute directory path for any symbolic links. Return true 23318fae3551SRodney W. Grimes */ 23328fae3551SRodney W. Grimes int 23338fae3551SRodney W. Grimes check_dirpath(dirp) 23348fae3551SRodney W. Grimes char *dirp; 23358fae3551SRodney W. Grimes { 23368fae3551SRodney W. Grimes char *cp; 23378fae3551SRodney W. Grimes int ret = 1; 23388fae3551SRodney W. Grimes struct stat sb; 23398fae3551SRodney W. Grimes 23408fae3551SRodney W. Grimes cp = dirp + 1; 23418fae3551SRodney W. Grimes while (*cp && ret) { 23428fae3551SRodney W. Grimes if (*cp == '/') { 23438fae3551SRodney W. Grimes *cp = '\0'; 2344a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 23458fae3551SRodney W. Grimes ret = 0; 23468fae3551SRodney W. Grimes *cp = '/'; 23478fae3551SRodney W. Grimes } 23488fae3551SRodney W. Grimes cp++; 23498fae3551SRodney W. Grimes } 2350a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 23518fae3551SRodney W. Grimes ret = 0; 23528fae3551SRodney W. Grimes return (ret); 23538fae3551SRodney W. Grimes } 2354a62dc406SDoug Rabson 235560caaee2SIan Dowse /* 235660caaee2SIan Dowse * Make a netmask according to the specified prefix length. The ss_family 235760caaee2SIan Dowse * and other non-address fields must be initialised before calling this. 235860caaee2SIan Dowse */ 235960caaee2SIan Dowse int 236060caaee2SIan Dowse makemask(struct sockaddr_storage *ssp, int bitlen) 23618360efbdSAlfred Perlstein { 236260caaee2SIan Dowse u_char *p; 236360caaee2SIan Dowse int bits, i, len; 23648360efbdSAlfred Perlstein 236560caaee2SIan Dowse if ((p = sa_rawaddr((struct sockaddr *)ssp, &len)) == NULL) 236660caaee2SIan Dowse return (-1); 236789fdc4e1SMike Barcroft if (bitlen > len * CHAR_BIT) 236860caaee2SIan Dowse return (-1); 23698360efbdSAlfred Perlstein 237060caaee2SIan Dowse for (i = 0; i < len; i++) { 237189fdc4e1SMike Barcroft bits = (bitlen > CHAR_BIT) ? CHAR_BIT : bitlen; 237260caaee2SIan Dowse *p++ = (1 << bits) - 1; 237360caaee2SIan Dowse bitlen -= bits; 23748360efbdSAlfred Perlstein } 23758360efbdSAlfred Perlstein return 0; 23768360efbdSAlfred Perlstein } 23778360efbdSAlfred Perlstein 237860caaee2SIan Dowse /* 237960caaee2SIan Dowse * Check that the sockaddr is a valid netmask. Returns 0 if the mask 238060caaee2SIan Dowse * is acceptable (i.e. of the form 1...10....0). 238160caaee2SIan Dowse */ 238260caaee2SIan Dowse int 238360caaee2SIan Dowse checkmask(struct sockaddr *sa) 23848360efbdSAlfred Perlstein { 238560caaee2SIan Dowse u_char *mask; 238660caaee2SIan Dowse int i, len; 238760caaee2SIan Dowse 238860caaee2SIan Dowse if ((mask = sa_rawaddr(sa, &len)) == NULL) 238960caaee2SIan Dowse return (-1); 239060caaee2SIan Dowse 239160caaee2SIan Dowse for (i = 0; i < len; i++) 239260caaee2SIan Dowse if (mask[i] != 0xff) 239360caaee2SIan Dowse break; 239460caaee2SIan Dowse if (i < len) { 239560caaee2SIan Dowse if (~mask[i] & (u_char)(~mask[i] + 1)) 239660caaee2SIan Dowse return (-1); 239760caaee2SIan Dowse i++; 239860caaee2SIan Dowse } 239960caaee2SIan Dowse for (; i < len; i++) 240060caaee2SIan Dowse if (mask[i] != 0) 240160caaee2SIan Dowse return (-1); 240260caaee2SIan Dowse return (0); 240360caaee2SIan Dowse } 240460caaee2SIan Dowse 240560caaee2SIan Dowse /* 240660caaee2SIan Dowse * Compare two sockaddrs according to a specified mask. Return zero if 240760caaee2SIan Dowse * `sa1' matches `sa2' when filtered by the netmask in `samask'. 240860caaee2SIan Dowse * If samask is NULL, perform a full comparision. 240960caaee2SIan Dowse */ 241060caaee2SIan Dowse int 241160caaee2SIan Dowse sacmp(struct sockaddr *sa1, struct sockaddr *sa2, struct sockaddr *samask) 241260caaee2SIan Dowse { 241360caaee2SIan Dowse unsigned char *p1, *p2, *mask; 241460caaee2SIan Dowse int len, i; 241560caaee2SIan Dowse 241660caaee2SIan Dowse if (sa1->sa_family != sa2->sa_family || 241760caaee2SIan Dowse (p1 = sa_rawaddr(sa1, &len)) == NULL || 241860caaee2SIan Dowse (p2 = sa_rawaddr(sa2, NULL)) == NULL) 241960caaee2SIan Dowse return (1); 242060caaee2SIan Dowse 242160caaee2SIan Dowse switch (sa1->sa_family) { 242260caaee2SIan Dowse case AF_INET6: 242360caaee2SIan Dowse if (((struct sockaddr_in6 *)sa1)->sin6_scope_id != 242460caaee2SIan Dowse ((struct sockaddr_in6 *)sa2)->sin6_scope_id) 242560caaee2SIan Dowse return (1); 242660caaee2SIan Dowse break; 242760caaee2SIan Dowse } 242860caaee2SIan Dowse 242960caaee2SIan Dowse /* Simple binary comparison if no mask specified. */ 243060caaee2SIan Dowse if (samask == NULL) 243160caaee2SIan Dowse return (memcmp(p1, p2, len)); 243260caaee2SIan Dowse 243360caaee2SIan Dowse /* Set up the mask, and do a mask-based comparison. */ 243460caaee2SIan Dowse if (sa1->sa_family != samask->sa_family || 243560caaee2SIan Dowse (mask = sa_rawaddr(samask, NULL)) == NULL) 243660caaee2SIan Dowse return (1); 243760caaee2SIan Dowse 243860caaee2SIan Dowse for (i = 0; i < len; i++) 243960caaee2SIan Dowse if ((p1[i] & mask[i]) != (p2[i] & mask[i])) 244060caaee2SIan Dowse return (1); 244160caaee2SIan Dowse return (0); 244260caaee2SIan Dowse } 244360caaee2SIan Dowse 244460caaee2SIan Dowse /* 244560caaee2SIan Dowse * Return a pointer to the part of the sockaddr that contains the 244660caaee2SIan Dowse * raw address, and set *nbytes to its length in bytes. Returns 244760caaee2SIan Dowse * NULL if the address family is unknown. 244860caaee2SIan Dowse */ 244960caaee2SIan Dowse void * 245060caaee2SIan Dowse sa_rawaddr(struct sockaddr *sa, int *nbytes) { 245160caaee2SIan Dowse void *p; 245260caaee2SIan Dowse int len; 24538360efbdSAlfred Perlstein 24548360efbdSAlfred Perlstein switch (sa->sa_family) { 24558360efbdSAlfred Perlstein case AF_INET: 245660caaee2SIan Dowse len = sizeof(((struct sockaddr_in *)sa)->sin_addr); 245760caaee2SIan Dowse p = &((struct sockaddr_in *)sa)->sin_addr; 24588360efbdSAlfred Perlstein break; 24598360efbdSAlfred Perlstein case AF_INET6: 246060caaee2SIan Dowse len = sizeof(((struct sockaddr_in6 *)sa)->sin6_addr); 246160caaee2SIan Dowse p = &((struct sockaddr_in6 *)sa)->sin6_addr; 24628360efbdSAlfred Perlstein break; 24638360efbdSAlfred Perlstein default: 246460caaee2SIan Dowse p = NULL; 246560caaee2SIan Dowse len = 0; 24668360efbdSAlfred Perlstein } 24678360efbdSAlfred Perlstein 246860caaee2SIan Dowse if (nbytes != NULL) 246960caaee2SIan Dowse *nbytes = len; 247060caaee2SIan Dowse return (p); 24718360efbdSAlfred Perlstein } 24728360efbdSAlfred Perlstein 247369d65572SIan Dowse void 247469d65572SIan Dowse huphandler(int sig) 247569d65572SIan Dowse { 247669d65572SIan Dowse got_sighup = 1; 247769d65572SIan Dowse } 247869d65572SIan Dowse 24798360efbdSAlfred Perlstein void terminate(sig) 24808360efbdSAlfred Perlstein int sig; 24818360efbdSAlfred Perlstein { 24828360efbdSAlfred Perlstein close(mountdlockfd); 24838360efbdSAlfred Perlstein unlink(MOUNTDLOCK); 24847b98a1d6SAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); 24857b98a1d6SAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); 24868360efbdSAlfred Perlstein exit (0); 24878360efbdSAlfred Perlstein } 2488