18fae3551SRodney W. Grimes /* 28fae3551SRodney W. Grimes * Copyright (c) 1989, 1993 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * 58fae3551SRodney W. Grimes * This code is derived from software contributed to Berkeley by 68fae3551SRodney W. Grimes * Herb Hasler and Rick Macklem at The University of Guelph. 78fae3551SRodney W. Grimes * 88fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 98fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 108fae3551SRodney W. Grimes * are met: 118fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 128fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 138fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 148fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 158fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 168fae3551SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 178fae3551SRodney W. Grimes * must display the following acknowledgement: 188fae3551SRodney W. Grimes * This product includes software developed by the University of 198fae3551SRodney W. Grimes * California, Berkeley and its contributors. 208fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 218fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 228fae3551SRodney W. Grimes * without specific prior written permission. 238fae3551SRodney W. Grimes * 248fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 258fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 268fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 278fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 288fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 298fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 308fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 318fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 328fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 338fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 348fae3551SRodney W. Grimes * SUCH DAMAGE. 358fae3551SRodney W. Grimes */ 368fae3551SRodney W. Grimes 378fae3551SRodney W. Grimes #ifndef lint 3874853402SPhilippe Charnier static const char copyright[] = 398fae3551SRodney W. Grimes "@(#) Copyright (c) 1989, 1993\n\ 408fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 41d599144dSGarrett Wollman #endif /*not lint*/ 428fae3551SRodney W. Grimes 438fae3551SRodney W. Grimes #ifndef lint 4474853402SPhilippe Charnier #if 0 4574853402SPhilippe Charnier static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; 4674853402SPhilippe Charnier #endif 47d599144dSGarrett Wollman static const char rcsid[] = 487f3dea24SPeter Wemm "$FreeBSD$"; 49d599144dSGarrett Wollman #endif /*not lint*/ 508fae3551SRodney W. Grimes 518fae3551SRodney W. Grimes #include <sys/param.h> 528fae3551SRodney W. Grimes #include <sys/mount.h> 538360efbdSAlfred Perlstein #include <sys/fcntl.h> 548fae3551SRodney W. Grimes #include <sys/stat.h> 558fae3551SRodney W. Grimes #include <sys/syslog.h> 56394da4c1SGuido van Rooij #include <sys/sysctl.h> 578fae3551SRodney W. Grimes 588fae3551SRodney W. Grimes #include <rpc/rpc.h> 598fae3551SRodney W. Grimes #include <rpc/pmap_clnt.h> 608360efbdSAlfred Perlstein #include <rpc/pmap_prot.h> 618360efbdSAlfred Perlstein #include <rpcsvc/mount.h> 628fae3551SRodney W. Grimes #include <nfs/rpcv2.h> 63a62dc406SDoug Rabson #include <nfs/nfsproto.h> 64394da4c1SGuido van Rooij #include <nfs/nfs.h> 6587564113SPeter Wemm #include <ufs/ufs/ufsmount.h> 6687564113SPeter Wemm #include <msdosfs/msdosfsmount.h> 679300c696SSemen Ustimenko #include <ntfs/ntfsmount.h> 6887564113SPeter Wemm #include <isofs/cd9660/cd9660_mount.h> /* XXX need isofs in include */ 698fae3551SRodney W. Grimes 708fae3551SRodney W. Grimes #include <arpa/inet.h> 718fae3551SRodney W. Grimes 728fae3551SRodney W. Grimes #include <ctype.h> 7374853402SPhilippe Charnier #include <err.h> 748fae3551SRodney W. Grimes #include <errno.h> 758fae3551SRodney W. Grimes #include <grp.h> 768fae3551SRodney W. Grimes #include <netdb.h> 778fae3551SRodney W. Grimes #include <pwd.h> 788fae3551SRodney W. Grimes #include <signal.h> 798fae3551SRodney W. Grimes #include <stdio.h> 808fae3551SRodney W. Grimes #include <stdlib.h> 818fae3551SRodney W. Grimes #include <string.h> 828fae3551SRodney W. Grimes #include <unistd.h> 838fae3551SRodney W. Grimes #include "pathnames.h" 848fae3551SRodney W. Grimes 858fae3551SRodney W. Grimes #ifdef DEBUG 868fae3551SRodney W. Grimes #include <stdarg.h> 878fae3551SRodney W. Grimes #endif 888fae3551SRodney W. Grimes 898360efbdSAlfred Perlstein #ifndef MOUNTDLOCK 908360efbdSAlfred Perlstein #define MOUNTDLOCK "/var/run/mountd.lock" 918360efbdSAlfred Perlstein #endif 928360efbdSAlfred Perlstein 938fae3551SRodney W. Grimes /* 948fae3551SRodney W. Grimes * Structures for keeping the mount list and export list 958fae3551SRodney W. Grimes */ 968fae3551SRodney W. Grimes struct mountlist { 978fae3551SRodney W. Grimes struct mountlist *ml_next; 988fae3551SRodney W. Grimes char ml_host[RPCMNT_NAMELEN+1]; 998fae3551SRodney W. Grimes char ml_dirp[RPCMNT_PATHLEN+1]; 1008fae3551SRodney W. Grimes }; 1018fae3551SRodney W. Grimes 1028fae3551SRodney W. Grimes struct dirlist { 1038fae3551SRodney W. Grimes struct dirlist *dp_left; 1048fae3551SRodney W. Grimes struct dirlist *dp_right; 1058fae3551SRodney W. Grimes int dp_flag; 1068fae3551SRodney W. Grimes struct hostlist *dp_hosts; /* List of hosts this dir exported to */ 1078fae3551SRodney W. Grimes char dp_dirp[1]; /* Actually malloc'd to size of dir */ 1088fae3551SRodney W. Grimes }; 1098fae3551SRodney W. Grimes /* dp_flag bits */ 1108fae3551SRodney W. Grimes #define DP_DEFSET 0x1 111a62dc406SDoug Rabson #define DP_HOSTSET 0x2 112a62dc406SDoug Rabson #define DP_KERB 0x4 1138fae3551SRodney W. Grimes 1148fae3551SRodney W. Grimes struct exportlist { 1158fae3551SRodney W. Grimes struct exportlist *ex_next; 1168fae3551SRodney W. Grimes struct dirlist *ex_dirl; 1178fae3551SRodney W. Grimes struct dirlist *ex_defdir; 1188fae3551SRodney W. Grimes int ex_flag; 1198fae3551SRodney W. Grimes fsid_t ex_fs; 1208fae3551SRodney W. Grimes char *ex_fsdir; 121cb3923e0SDoug Rabson char *ex_indexfile; 1228fae3551SRodney W. Grimes }; 1238fae3551SRodney W. Grimes /* ex_flag bits */ 1248fae3551SRodney W. Grimes #define EX_LINKED 0x1 1258fae3551SRodney W. Grimes 1268fae3551SRodney W. Grimes struct netmsk { 1278360efbdSAlfred Perlstein struct sockaddr_storage nt_net; 128f863ed7fSDoug Rabson u_int32_t nt_mask; 1298fae3551SRodney W. Grimes char *nt_name; 1308fae3551SRodney W. Grimes }; 1318fae3551SRodney W. Grimes 1328fae3551SRodney W. Grimes union grouptypes { 1338360efbdSAlfred Perlstein struct addrinfo *gt_addrinfo; 1348fae3551SRodney W. Grimes struct netmsk gt_net; 1358fae3551SRodney W. Grimes }; 1368fae3551SRodney W. Grimes 1378fae3551SRodney W. Grimes struct grouplist { 1388fae3551SRodney W. Grimes int gr_type; 1398fae3551SRodney W. Grimes union grouptypes gr_ptr; 1408fae3551SRodney W. Grimes struct grouplist *gr_next; 1418fae3551SRodney W. Grimes }; 1428fae3551SRodney W. Grimes /* Group types */ 1438fae3551SRodney W. Grimes #define GT_NULL 0x0 1448fae3551SRodney W. Grimes #define GT_HOST 0x1 1458fae3551SRodney W. Grimes #define GT_NET 0x2 1466d359f31SIan Dowse #define GT_DEFAULT 0x3 1478b5a6d67SBill Paul #define GT_IGNORE 0x5 1488fae3551SRodney W. Grimes 1498fae3551SRodney W. Grimes struct hostlist { 150a62dc406SDoug Rabson int ht_flag; /* Uses DP_xx bits */ 1518fae3551SRodney W. Grimes struct grouplist *ht_grp; 1528fae3551SRodney W. Grimes struct hostlist *ht_next; 1538fae3551SRodney W. Grimes }; 1548fae3551SRodney W. Grimes 155a62dc406SDoug Rabson struct fhreturn { 156a62dc406SDoug Rabson int fhr_flag; 157a62dc406SDoug Rabson int fhr_vers; 158a62dc406SDoug Rabson nfsfh_t fhr_fh; 159a62dc406SDoug Rabson }; 160a62dc406SDoug Rabson 1618fae3551SRodney W. Grimes /* Global defs */ 1628fae3551SRodney W. Grimes char *add_expdir __P((struct dirlist **, char *, int)); 1638fae3551SRodney W. Grimes void add_dlist __P((struct dirlist **, struct dirlist *, 164a62dc406SDoug Rabson struct grouplist *, int)); 1658fae3551SRodney W. Grimes void add_mlist __P((char *, char *)); 1668fae3551SRodney W. Grimes int check_dirpath __P((char *)); 1678fae3551SRodney W. Grimes int check_options __P((struct dirlist *)); 1688360efbdSAlfred Perlstein int chk_host __P((struct dirlist *, struct sockaddr *, int *, int *)); 16901709abfSIan Dowse void del_mlist(char *hostp, char *dirp); 1708fae3551SRodney W. Grimes struct dirlist *dirp_search __P((struct dirlist *, char *)); 1718fae3551SRodney W. Grimes int do_mount __P((struct exportlist *, struct grouplist *, int, 172c0511d3bSBrian Feldman struct xucred *, char *, int, struct statfs *)); 1738fae3551SRodney W. Grimes int do_opt __P((char **, char **, struct exportlist *, struct grouplist *, 174c0511d3bSBrian Feldman int *, int *, struct xucred *)); 1758fae3551SRodney W. Grimes struct exportlist *ex_search __P((fsid_t *)); 1768fae3551SRodney W. Grimes struct exportlist *get_exp __P((void)); 1778fae3551SRodney W. Grimes void free_dir __P((struct dirlist *)); 1788fae3551SRodney W. Grimes void free_exp __P((struct exportlist *)); 1798fae3551SRodney W. Grimes void free_grp __P((struct grouplist *)); 1808fae3551SRodney W. Grimes void free_host __P((struct hostlist *)); 1818fae3551SRodney W. Grimes void get_exportlist __P((void)); 1828b5a6d67SBill Paul int get_host __P((char *, struct grouplist *, struct grouplist *)); 1838fae3551SRodney W. Grimes struct hostlist *get_ht __P((void)); 1848fae3551SRodney W. Grimes int get_line __P((void)); 1858fae3551SRodney W. Grimes void get_mountlist __P((void)); 1868fae3551SRodney W. Grimes int get_net __P((char *, struct netmsk *, int)); 1878fae3551SRodney W. Grimes void getexp_err __P((struct exportlist *, struct grouplist *)); 1888fae3551SRodney W. Grimes struct grouplist *get_grp __P((void)); 1898fae3551SRodney W. Grimes void hang_dirp __P((struct dirlist *, struct grouplist *, 1908fae3551SRodney W. Grimes struct exportlist *, int)); 19169d65572SIan Dowse void huphandler(int sig); 1928fae3551SRodney W. Grimes void mntsrv __P((struct svc_req *, SVCXPRT *)); 1938fae3551SRodney W. Grimes void nextfield __P((char **, char **)); 1948fae3551SRodney W. Grimes void out_of_mem __P((void)); 195c0511d3bSBrian Feldman void parsecred __P((char *, struct xucred *)); 1968fae3551SRodney W. Grimes int put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *)); 1978360efbdSAlfred Perlstein int scan_tree __P((struct dirlist *, struct sockaddr *)); 19874853402SPhilippe Charnier static void usage __P((void)); 1998fae3551SRodney W. Grimes int xdr_dir __P((XDR *, char *)); 2008fae3551SRodney W. Grimes int xdr_explist __P((XDR *, caddr_t)); 201a62dc406SDoug Rabson int xdr_fhs __P((XDR *, caddr_t)); 2028fae3551SRodney W. Grimes int xdr_mlist __P((XDR *, caddr_t)); 2038360efbdSAlfred Perlstein void terminate __P((int)); 2048fae3551SRodney W. Grimes 2058360efbdSAlfred Perlstein static int bitcmp __P((void *, void *, int)); 2068360efbdSAlfred Perlstein static int netpartcmp __P((struct sockaddr *, struct sockaddr *, int)); 2078360efbdSAlfred Perlstein static int sacmp __P((struct sockaddr *, struct sockaddr *)); 2088360efbdSAlfred Perlstein static int allones __P((struct sockaddr_storage *, int)); 2098360efbdSAlfred Perlstein static int countones __P((struct sockaddr *)); 2108360efbdSAlfred Perlstein 2118fae3551SRodney W. Grimes struct exportlist *exphead; 2128fae3551SRodney W. Grimes struct mountlist *mlhead; 2138fae3551SRodney W. Grimes struct grouplist *grphead; 2148fae3551SRodney W. Grimes char exname[MAXPATHLEN]; 215c0511d3bSBrian Feldman struct xucred def_anon = { 216c0511d3bSBrian Feldman 0, 2178fae3551SRodney W. Grimes (uid_t)-2, 2188fae3551SRodney W. Grimes 1, 219c0511d3bSBrian Feldman { (gid_t)-2 }, 220c0511d3bSBrian Feldman NULL 2218fae3551SRodney W. Grimes }; 2222a66cfc5SDoug Rabson int force_v2 = 0; 223a62dc406SDoug Rabson int resvport_only = 1; 224a62dc406SDoug Rabson int dir_only = 1; 225f2c90b95SGuido van Rooij int log = 0; 22669d65572SIan Dowse int got_sighup = 0; 2278360efbdSAlfred Perlstein 2288fae3551SRodney W. Grimes int opt_flags; 2298360efbdSAlfred Perlstein static int have_v6 = 1; 2308360efbdSAlfred Perlstein #ifdef NI_WITHSCOPEID 2318360efbdSAlfred Perlstein static const int ninumeric = NI_NUMERICHOST | NI_WITHSCOPEID; 2328360efbdSAlfred Perlstein #else 2338360efbdSAlfred Perlstein static const int ninumeric = NI_NUMERICHOST; 2348360efbdSAlfred Perlstein #endif 2358360efbdSAlfred Perlstein 2368360efbdSAlfred Perlstein int mountdlockfd; 2378fae3551SRodney W. Grimes /* Bits for above */ 2388fae3551SRodney W. Grimes #define OP_MAPROOT 0x01 2398fae3551SRodney W. Grimes #define OP_MAPALL 0x02 2408fae3551SRodney W. Grimes #define OP_KERB 0x04 2418fae3551SRodney W. Grimes #define OP_MASK 0x08 2428fae3551SRodney W. Grimes #define OP_NET 0x10 2438fae3551SRodney W. Grimes #define OP_ALLDIRS 0x40 2448360efbdSAlfred Perlstein #define OP_MASKLEN 0x200 2458fae3551SRodney W. Grimes 2468fae3551SRodney W. Grimes #ifdef DEBUG 2478fae3551SRodney W. Grimes int debug = 1; 2488fae3551SRodney W. Grimes void SYSLOG __P((int, const char *, ...)); 2498fae3551SRodney W. Grimes #define syslog SYSLOG 2508fae3551SRodney W. Grimes #else 2518fae3551SRodney W. Grimes int debug = 0; 2528fae3551SRodney W. Grimes #endif 2538fae3551SRodney W. Grimes 2548fae3551SRodney W. Grimes /* 2558fae3551SRodney W. Grimes * Mountd server for NFS mount protocol as described in: 2568fae3551SRodney W. Grimes * NFS: Network File System Protocol Specification, RFC1094, Appendix A 2578fae3551SRodney W. Grimes * The optional arguments are the exports file name 2588fae3551SRodney W. Grimes * default: _PATH_EXPORTS 2598fae3551SRodney W. Grimes * and "-n" to allow nonroot mount. 2608fae3551SRodney W. Grimes */ 2618fae3551SRodney W. Grimes int 2628fae3551SRodney W. Grimes main(argc, argv) 2638fae3551SRodney W. Grimes int argc; 2648fae3551SRodney W. Grimes char **argv; 2658fae3551SRodney W. Grimes { 26669d65572SIan Dowse fd_set readfds; 2678360efbdSAlfred Perlstein SVCXPRT *udptransp, *tcptransp, *udp6transp, *tcp6transp; 2688360efbdSAlfred Perlstein struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf; 2698360efbdSAlfred Perlstein int udpsock, tcpsock, udp6sock, tcp6sock; 2708360efbdSAlfred Perlstein int xcreated = 0, s; 2718360efbdSAlfred Perlstein int one = 1; 272a798ce2eSBruce Evans int c, error, mib[3]; 27387564113SPeter Wemm struct vfsconf vfc; 274d599144dSGarrett Wollman 27501709abfSIan Dowse udp6conf = tcp6conf = NULL; 27601709abfSIan Dowse udp6sock = tcp6sock = NULL; 2778360efbdSAlfred Perlstein 27801709abfSIan Dowse /* Check that another mountd isn't already running. */ 2798360efbdSAlfred Perlstein if ((mountdlockfd = (open(MOUNTDLOCK, O_RDONLY|O_CREAT, 0444))) == -1) 2808360efbdSAlfred Perlstein err(1, "%s", MOUNTDLOCK); 2818360efbdSAlfred Perlstein 2828360efbdSAlfred Perlstein if(flock(mountdlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) 2838360efbdSAlfred Perlstein errx(1, "another rpc.mountd is already running. Aborting"); 2848360efbdSAlfred Perlstein s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 2858360efbdSAlfred Perlstein if (s < 0) 2868360efbdSAlfred Perlstein have_v6 = 0; 2878360efbdSAlfred Perlstein else 2888360efbdSAlfred Perlstein close(s); 28987564113SPeter Wemm error = getvfsbyname("nfs", &vfc); 29087564113SPeter Wemm if (error && vfsisloadable("nfs")) { 291d599144dSGarrett Wollman if(vfsload("nfs")) 292d599144dSGarrett Wollman err(1, "vfsload(nfs)"); 293d599144dSGarrett Wollman endvfsent(); /* flush cache */ 29487564113SPeter Wemm error = getvfsbyname("nfs", &vfc); 295d599144dSGarrett Wollman } 29687564113SPeter Wemm if (error) 297d599144dSGarrett Wollman errx(1, "NFS support is not available in the running kernel"); 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, 3678360efbdSAlfred Perlstein IPV6_BINDV6ONLY, &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, 3728360efbdSAlfred Perlstein IPV6_BINDV6ONLY, &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) { 381394da4c1SGuido van Rooij mib[0] = CTL_VFS; 382a798ce2eSBruce Evans mib[1] = vfc.vfc_typenum; 383394da4c1SGuido van Rooij mib[2] = NFS_NFSPRIVPORT; 3841f45d4d4SBruce Evans if (sysctl(mib, 3, NULL, NULL, &resvport_only, 3851f45d4d4SBruce Evans sizeof(resvport_only)) != 0 && errno != ENOENT) { 386394da4c1SGuido van Rooij syslog(LOG_ERR, "sysctl: %m"); 387394da4c1SGuido van Rooij exit(1); 388394da4c1SGuido van Rooij } 389c6e5e158SGuido van Rooij } 390d3628763SRodney W. Grimes if ((udptransp = svcudp_create(RPC_ANYSOCK)) == NULL || 391d3628763SRodney W. Grimes (tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0)) == NULL) { 39274853402SPhilippe Charnier syslog(LOG_ERR, "can't create socket"); 3938fae3551SRodney W. Grimes exit(1); 3948fae3551SRodney W. Grimes } 3958360efbdSAlfred Perlstein if (udpsock != -1 && udpconf != NULL) { 3968360efbdSAlfred Perlstein bindresvport(udpsock, NULL); 3978360efbdSAlfred Perlstein udptransp = svc_dg_create(udpsock, 0, 0); 3988360efbdSAlfred Perlstein if (udptransp != NULL) { 3998360efbdSAlfred Perlstein if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER1, 4008360efbdSAlfred Perlstein mntsrv, udpconf)) 4018360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP RPCMNT_VER1 service"); 4028360efbdSAlfred Perlstein else 4038360efbdSAlfred Perlstein xcreated++; 4048360efbdSAlfred Perlstein if (!force_v2) { 4058360efbdSAlfred Perlstein if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER3, 4068360efbdSAlfred Perlstein mntsrv, udpconf)) 4078360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP RPCMNT_VER3 service"); 4088360efbdSAlfred Perlstein else 4098360efbdSAlfred Perlstein xcreated++; 4108fae3551SRodney W. Grimes } 4118360efbdSAlfred Perlstein } else 4128360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create UDP services"); 4138360efbdSAlfred Perlstein 4148360efbdSAlfred Perlstein } 4158360efbdSAlfred Perlstein if (tcpsock != -1 && tcpconf != NULL) { 4168360efbdSAlfred Perlstein bindresvport(tcpsock, NULL); 4178360efbdSAlfred Perlstein listen(tcpsock, SOMAXCONN); 4188360efbdSAlfred Perlstein tcptransp = svc_vc_create(tcpsock, 0, 0); 4198360efbdSAlfred Perlstein if (tcptransp != NULL) { 4208360efbdSAlfred Perlstein if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER1, 4218360efbdSAlfred Perlstein mntsrv, tcpconf)) 4228360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP RPCMNT_VER1 service"); 4238360efbdSAlfred Perlstein else 4248360efbdSAlfred Perlstein xcreated++; 4258360efbdSAlfred Perlstein if (!force_v2) { 4268360efbdSAlfred Perlstein if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER3, 4278360efbdSAlfred Perlstein mntsrv, tcpconf)) 4288360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP RPCMNT_VER3 service"); 4298360efbdSAlfred Perlstein else 4308360efbdSAlfred Perlstein xcreated++; 4318360efbdSAlfred Perlstein } 4328360efbdSAlfred Perlstein } else 4338360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create TCP service"); 4348360efbdSAlfred Perlstein 4358360efbdSAlfred Perlstein } 43695b99739SAlfred Perlstein if (have_v6 && udp6sock != -1 && udp6conf != NULL) { 4378360efbdSAlfred Perlstein bindresvport(udp6sock, NULL); 4388360efbdSAlfred Perlstein udp6transp = svc_dg_create(udp6sock, 0, 0); 4398360efbdSAlfred Perlstein if (udp6transp != NULL) { 4408360efbdSAlfred Perlstein if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER1, 4418360efbdSAlfred Perlstein mntsrv, udp6conf)) 4428360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER1 service"); 4438360efbdSAlfred Perlstein else 4448360efbdSAlfred Perlstein xcreated++; 4458360efbdSAlfred Perlstein if (!force_v2) { 4468360efbdSAlfred Perlstein if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER3, 4478360efbdSAlfred Perlstein mntsrv, udp6conf)) 4488360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER3 service"); 4498360efbdSAlfred Perlstein else 4508360efbdSAlfred Perlstein xcreated++; 4518360efbdSAlfred Perlstein } 4528360efbdSAlfred Perlstein } else 4538360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create UDP6 service"); 4548360efbdSAlfred Perlstein 4558360efbdSAlfred Perlstein } 45695b99739SAlfred Perlstein if (have_v6 && tcp6sock != -1 && tcp6conf != NULL) { 4578360efbdSAlfred Perlstein bindresvport(tcp6sock, NULL); 4588360efbdSAlfred Perlstein listen(tcp6sock, SOMAXCONN); 4598360efbdSAlfred Perlstein tcp6transp = svc_vc_create(tcp6sock, 0, 0); 4608360efbdSAlfred Perlstein if (tcp6transp != NULL) { 4618360efbdSAlfred Perlstein if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER1, 4628360efbdSAlfred Perlstein mntsrv, tcp6conf)) 4638360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER1 service"); 4648360efbdSAlfred Perlstein else 4658360efbdSAlfred Perlstein xcreated++; 4668360efbdSAlfred Perlstein if (!force_v2) { 4678360efbdSAlfred Perlstein if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER3, 4688360efbdSAlfred Perlstein mntsrv, tcp6conf)) 4698360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER3 service"); 4708360efbdSAlfred Perlstein else 4718360efbdSAlfred Perlstein xcreated++; 4728360efbdSAlfred Perlstein } 4738360efbdSAlfred Perlstein } else 4748360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create TCP6 service"); 4758360efbdSAlfred Perlstein 4768360efbdSAlfred Perlstein } 4778360efbdSAlfred Perlstein if (xcreated == 0) { 4788360efbdSAlfred Perlstein syslog(LOG_ERR, "could not create any services"); 4792a66cfc5SDoug Rabson exit(1); 4802a66cfc5SDoug Rabson } 48169d65572SIan Dowse 48269d65572SIan Dowse /* Expand svc_run() here so that we can call get_exportlist(). */ 48369d65572SIan Dowse for (;;) { 48469d65572SIan Dowse if (got_sighup) { 48569d65572SIan Dowse get_exportlist(); 48669d65572SIan Dowse got_sighup = 0; 48769d65572SIan Dowse } 48869d65572SIan Dowse readfds = svc_fdset; 48969d65572SIan Dowse switch (select(svc_maxfd + 1, &readfds, NULL, NULL, NULL)) { 49069d65572SIan Dowse case -1: 49169d65572SIan Dowse if (errno == EINTR) 49269d65572SIan Dowse continue; 49369d65572SIan Dowse syslog(LOG_ERR, "mountd died: select: %m"); 49474853402SPhilippe Charnier exit(1); 49569d65572SIan Dowse case 0: 49669d65572SIan Dowse continue; 49769d65572SIan Dowse default: 49869d65572SIan Dowse svc_getreqset(&readfds); 49969d65572SIan Dowse } 50069d65572SIan Dowse } 50174853402SPhilippe Charnier } 50274853402SPhilippe Charnier 50374853402SPhilippe Charnier static void 50474853402SPhilippe Charnier usage() 50574853402SPhilippe Charnier { 50674853402SPhilippe Charnier fprintf(stderr, 50774853402SPhilippe Charnier "usage: mountd [-2] [-d] [-l] [-n] [-r] [export_file]\n"); 5088fae3551SRodney W. Grimes exit(1); 5098fae3551SRodney W. Grimes } 5108fae3551SRodney W. Grimes 5118fae3551SRodney W. Grimes /* 5128fae3551SRodney W. Grimes * The mount rpc service 5138fae3551SRodney W. Grimes */ 5148fae3551SRodney W. Grimes void 5158fae3551SRodney W. Grimes mntsrv(rqstp, transp) 5168fae3551SRodney W. Grimes struct svc_req *rqstp; 5178fae3551SRodney W. Grimes SVCXPRT *transp; 5188fae3551SRodney W. Grimes { 5198fae3551SRodney W. Grimes struct exportlist *ep; 5208fae3551SRodney W. Grimes struct dirlist *dp; 521a62dc406SDoug Rabson struct fhreturn fhr; 5228fae3551SRodney W. Grimes struct stat stb; 5238fae3551SRodney W. Grimes struct statfs fsb; 5248360efbdSAlfred Perlstein struct addrinfo *ai; 5258360efbdSAlfred Perlstein char host[NI_MAXHOST], numerichost[NI_MAXHOST]; 5268360efbdSAlfred Perlstein int lookup_failed = 1; 5278360efbdSAlfred Perlstein struct sockaddr *saddr; 528a62dc406SDoug Rabson u_short sport; 5298fae3551SRodney W. Grimes char rpcpath[RPCMNT_PATHLEN + 1], dirpath[MAXPATHLEN]; 530e90cdb54SGuido van Rooij int bad = 0, defset, hostset; 531a62dc406SDoug Rabson sigset_t sighup_mask; 5328fae3551SRodney W. Grimes 533a62dc406SDoug Rabson sigemptyset(&sighup_mask); 534a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 5358360efbdSAlfred Perlstein saddr = svc_getrpccaller(transp)->buf; 5368360efbdSAlfred Perlstein switch (saddr->sa_family) { 5378360efbdSAlfred Perlstein case AF_INET6: 53801709abfSIan Dowse sport = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port); 5398360efbdSAlfred Perlstein break; 5408360efbdSAlfred Perlstein case AF_INET: 54101709abfSIan Dowse sport = ntohs(((struct sockaddr_in *)saddr)->sin_port); 5428360efbdSAlfred Perlstein break; 5438360efbdSAlfred Perlstein default: 5448360efbdSAlfred Perlstein syslog(LOG_ERR, "request from unknown address family"); 5458360efbdSAlfred Perlstein return; 5468360efbdSAlfred Perlstein } 5478360efbdSAlfred Perlstein lookup_failed = getnameinfo(saddr, saddr->sa_len, host, sizeof host, 5488360efbdSAlfred Perlstein NULL, 0, 0); 5498360efbdSAlfred Perlstein getnameinfo(saddr, saddr->sa_len, numerichost, 5508360efbdSAlfred Perlstein sizeof numerichost, NULL, 0, NI_NUMERICHOST); 5518360efbdSAlfred Perlstein ai = NULL; 5528fae3551SRodney W. Grimes switch (rqstp->rq_proc) { 5538fae3551SRodney W. Grimes case NULLPROC: 5548fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 55574853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 5568fae3551SRodney W. Grimes return; 5578fae3551SRodney W. Grimes case RPCMNT_MOUNT: 558a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 559f51631d7SGuido van Rooij syslog(LOG_NOTICE, 560f51631d7SGuido van Rooij "mount request from %s from unprivileged port", 5618360efbdSAlfred Perlstein numerichost); 5628fae3551SRodney W. Grimes svcerr_weakauth(transp); 5638fae3551SRodney W. Grimes return; 5648fae3551SRodney W. Grimes } 5658fae3551SRodney W. Grimes if (!svc_getargs(transp, xdr_dir, rpcpath)) { 566f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable mount request from %s", 5678360efbdSAlfred Perlstein numerichost); 5688fae3551SRodney W. Grimes svcerr_decode(transp); 5698fae3551SRodney W. Grimes return; 5708fae3551SRodney W. Grimes } 5718fae3551SRodney W. Grimes 5728fae3551SRodney W. Grimes /* 5738fae3551SRodney W. Grimes * Get the real pathname and make sure it is a directory 574a62dc406SDoug Rabson * or a regular file if the -r option was specified 575a62dc406SDoug Rabson * and it exists. 5768fae3551SRodney W. Grimes */ 577cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL || 5788fae3551SRodney W. Grimes stat(dirpath, &stb) < 0 || 579a62dc406SDoug Rabson (!S_ISDIR(stb.st_mode) && 580a62dc406SDoug Rabson (dir_only || !S_ISREG(stb.st_mode))) || 5818fae3551SRodney W. Grimes statfs(dirpath, &fsb) < 0) { 5828fae3551SRodney W. Grimes chdir("/"); /* Just in case realpath doesn't */ 583f51631d7SGuido van Rooij syslog(LOG_NOTICE, 58474853402SPhilippe Charnier "mount request from %s for non existent path %s", 5858360efbdSAlfred Perlstein numerichost, dirpath); 5868fae3551SRodney W. Grimes if (debug) 58774853402SPhilippe Charnier warnx("stat failed on %s", dirpath); 588e90cdb54SGuido van Rooij bad = ENOENT; /* We will send error reply later */ 5898fae3551SRodney W. Grimes } 5908fae3551SRodney W. Grimes 5918fae3551SRodney W. Grimes /* Check in the exports list */ 592a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 5938fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 594a62dc406SDoug Rabson hostset = defset = 0; 595a62dc406SDoug Rabson if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) || 5968fae3551SRodney W. Grimes ((dp = dirp_search(ep->ex_dirl, dirpath)) && 597a62dc406SDoug Rabson chk_host(dp, saddr, &defset, &hostset)) || 5988fae3551SRodney W. Grimes (defset && scan_tree(ep->ex_defdir, saddr) == 0 && 5998fae3551SRodney W. Grimes scan_tree(ep->ex_dirl, saddr) == 0))) { 600e90cdb54SGuido van Rooij if (bad) { 601e90cdb54SGuido van Rooij if (!svc_sendreply(transp, xdr_long, 602e90cdb54SGuido van Rooij (caddr_t)&bad)) 60374853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 604e90cdb54SGuido van Rooij sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 605e90cdb54SGuido van Rooij return; 606e90cdb54SGuido van Rooij } 607a62dc406SDoug Rabson if (hostset & DP_HOSTSET) 608a62dc406SDoug Rabson fhr.fhr_flag = hostset; 609a62dc406SDoug Rabson else 610a62dc406SDoug Rabson fhr.fhr_flag = defset; 611a62dc406SDoug Rabson fhr.fhr_vers = rqstp->rq_vers; 6128fae3551SRodney W. Grimes /* Get the file handle */ 61387564113SPeter Wemm memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t)); 614a62dc406SDoug Rabson if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) { 6158fae3551SRodney W. Grimes bad = errno; 61674853402SPhilippe Charnier syslog(LOG_ERR, "can't get fh for %s", dirpath); 6178fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_long, 6188fae3551SRodney W. Grimes (caddr_t)&bad)) 61974853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 620a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6218fae3551SRodney W. Grimes return; 6228fae3551SRodney W. Grimes } 623a62dc406SDoug Rabson if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr)) 62474853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6258360efbdSAlfred Perlstein if (!lookup_failed) 6268360efbdSAlfred Perlstein add_mlist(host, dirpath); 6278fae3551SRodney W. Grimes else 6288360efbdSAlfred Perlstein add_mlist(numerichost, dirpath); 6298fae3551SRodney W. Grimes if (debug) 63074853402SPhilippe Charnier warnx("mount successful"); 631f51631d7SGuido van Rooij if (log) 632f51631d7SGuido van Rooij syslog(LOG_NOTICE, 633f51631d7SGuido van Rooij "mount request succeeded from %s for %s", 6348360efbdSAlfred Perlstein numerichost, dirpath); 635f51631d7SGuido van Rooij } else { 6368fae3551SRodney W. Grimes bad = EACCES; 637f51631d7SGuido van Rooij syslog(LOG_NOTICE, 638f51631d7SGuido van Rooij "mount request denied from %s for %s", 6398360efbdSAlfred Perlstein numerichost, dirpath); 640f51631d7SGuido van Rooij } 641e90cdb54SGuido van Rooij 642e90cdb54SGuido van Rooij if (bad && !svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 64374853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 644a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6458fae3551SRodney W. Grimes return; 6468fae3551SRodney W. Grimes case RPCMNT_DUMP: 6478fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL)) 64874853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 649f51631d7SGuido van Rooij else if (log) 650f51631d7SGuido van Rooij syslog(LOG_NOTICE, 651f51631d7SGuido van Rooij "dump request succeeded from %s", 6528360efbdSAlfred Perlstein numerichost); 6538fae3551SRodney W. Grimes return; 6548fae3551SRodney W. Grimes case RPCMNT_UMOUNT: 655a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 656f51631d7SGuido van Rooij syslog(LOG_NOTICE, 657f51631d7SGuido van Rooij "umount request from %s from unprivileged port", 6588360efbdSAlfred Perlstein numerichost); 6598fae3551SRodney W. Grimes svcerr_weakauth(transp); 6608fae3551SRodney W. Grimes return; 6618fae3551SRodney W. Grimes } 662cb479b11SAlfred Perlstein if (!svc_getargs(transp, xdr_dir, rpcpath)) { 663f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable umount request from %s", 6648360efbdSAlfred Perlstein numerichost); 6658fae3551SRodney W. Grimes svcerr_decode(transp); 6668fae3551SRodney W. Grimes return; 6678fae3551SRodney W. Grimes } 668cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL) { 669cb479b11SAlfred Perlstein syslog(LOG_NOTICE, "umount request from %s " 670cb479b11SAlfred Perlstein "for non existent path %s", 6718360efbdSAlfred Perlstein numerichost, dirpath); 672cb479b11SAlfred Perlstein } 6738fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 67474853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6758360efbdSAlfred Perlstein if (!lookup_failed) 67601709abfSIan Dowse del_mlist(host, dirpath); 67701709abfSIan Dowse del_mlist(numerichost, dirpath); 678f51631d7SGuido van Rooij if (log) 679f51631d7SGuido van Rooij syslog(LOG_NOTICE, 680f51631d7SGuido van Rooij "umount request succeeded from %s for %s", 6818360efbdSAlfred Perlstein numerichost, dirpath); 6828fae3551SRodney W. Grimes return; 6838fae3551SRodney W. Grimes case RPCMNT_UMNTALL: 684a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 685f51631d7SGuido van Rooij syslog(LOG_NOTICE, 686f51631d7SGuido van Rooij "umountall request from %s from unprivileged port", 6878360efbdSAlfred Perlstein numerichost); 6888fae3551SRodney W. Grimes svcerr_weakauth(transp); 6898fae3551SRodney W. Grimes return; 6908fae3551SRodney W. Grimes } 6918fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 69274853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6938360efbdSAlfred Perlstein if (!lookup_failed) 69401709abfSIan Dowse del_mlist(host, NULL); 69501709abfSIan Dowse del_mlist(numerichost, NULL); 696f51631d7SGuido van Rooij if (log) 697f51631d7SGuido van Rooij syslog(LOG_NOTICE, 698f51631d7SGuido van Rooij "umountall request succeeded from %s", 6998360efbdSAlfred Perlstein numerichost); 7008fae3551SRodney W. Grimes return; 7018fae3551SRodney W. Grimes case RPCMNT_EXPORT: 7028fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL)) 70374853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 704f51631d7SGuido van Rooij if (log) 705f51631d7SGuido van Rooij syslog(LOG_NOTICE, 706f51631d7SGuido van Rooij "export request succeeded from %s", 7078360efbdSAlfred Perlstein numerichost); 7088fae3551SRodney W. Grimes return; 7098fae3551SRodney W. Grimes default: 7108fae3551SRodney W. Grimes svcerr_noproc(transp); 7118fae3551SRodney W. Grimes return; 7128fae3551SRodney W. Grimes } 7138fae3551SRodney W. Grimes } 7148fae3551SRodney W. Grimes 7158fae3551SRodney W. Grimes /* 7168fae3551SRodney W. Grimes * Xdr conversion for a dirpath string 7178fae3551SRodney W. Grimes */ 7188fae3551SRodney W. Grimes int 7198fae3551SRodney W. Grimes xdr_dir(xdrsp, dirp) 7208fae3551SRodney W. Grimes XDR *xdrsp; 7218fae3551SRodney W. Grimes char *dirp; 7228fae3551SRodney W. Grimes { 7238fae3551SRodney W. Grimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 7248fae3551SRodney W. Grimes } 7258fae3551SRodney W. Grimes 7268fae3551SRodney W. Grimes /* 727a62dc406SDoug Rabson * Xdr routine to generate file handle reply 7288fae3551SRodney W. Grimes */ 7298fae3551SRodney W. Grimes int 730a62dc406SDoug Rabson xdr_fhs(xdrsp, cp) 7318fae3551SRodney W. Grimes XDR *xdrsp; 732a62dc406SDoug Rabson caddr_t cp; 7338fae3551SRodney W. Grimes { 734a62dc406SDoug Rabson register struct fhreturn *fhrp = (struct fhreturn *)cp; 735a62dc406SDoug Rabson u_long ok = 0, len, auth; 7368fae3551SRodney W. Grimes 7378fae3551SRodney W. Grimes if (!xdr_long(xdrsp, &ok)) 7388fae3551SRodney W. Grimes return (0); 739a62dc406SDoug Rabson switch (fhrp->fhr_vers) { 740a62dc406SDoug Rabson case 1: 741a62dc406SDoug Rabson return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH)); 742a62dc406SDoug Rabson case 3: 743a62dc406SDoug Rabson len = NFSX_V3FH; 744a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 745a62dc406SDoug Rabson return (0); 746a62dc406SDoug Rabson if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) 747a62dc406SDoug Rabson return (0); 748a62dc406SDoug Rabson if (fhrp->fhr_flag & DP_KERB) 749a62dc406SDoug Rabson auth = RPCAUTH_KERB4; 750a62dc406SDoug Rabson else 751a62dc406SDoug Rabson auth = RPCAUTH_UNIX; 752a62dc406SDoug Rabson len = 1; 753a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 754a62dc406SDoug Rabson return (0); 755a62dc406SDoug Rabson return (xdr_long(xdrsp, &auth)); 756a62dc406SDoug Rabson }; 757a62dc406SDoug Rabson return (0); 7588fae3551SRodney W. Grimes } 7598fae3551SRodney W. Grimes 7608fae3551SRodney W. Grimes int 7618fae3551SRodney W. Grimes xdr_mlist(xdrsp, cp) 7628fae3551SRodney W. Grimes XDR *xdrsp; 7638fae3551SRodney W. Grimes caddr_t cp; 7648fae3551SRodney W. Grimes { 7658fae3551SRodney W. Grimes struct mountlist *mlp; 7668fae3551SRodney W. Grimes int true = 1; 7678fae3551SRodney W. Grimes int false = 0; 7688fae3551SRodney W. Grimes char *strp; 7698fae3551SRodney W. Grimes 7708fae3551SRodney W. Grimes mlp = mlhead; 7718fae3551SRodney W. Grimes while (mlp) { 7728fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 7738fae3551SRodney W. Grimes return (0); 7748fae3551SRodney W. Grimes strp = &mlp->ml_host[0]; 7758fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 7768fae3551SRodney W. Grimes return (0); 7778fae3551SRodney W. Grimes strp = &mlp->ml_dirp[0]; 7788fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 7798fae3551SRodney W. Grimes return (0); 7808fae3551SRodney W. Grimes mlp = mlp->ml_next; 7818fae3551SRodney W. Grimes } 7828fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 7838fae3551SRodney W. Grimes return (0); 7848fae3551SRodney W. Grimes return (1); 7858fae3551SRodney W. Grimes } 7868fae3551SRodney W. Grimes 7878fae3551SRodney W. Grimes /* 7888fae3551SRodney W. Grimes * Xdr conversion for export list 7898fae3551SRodney W. Grimes */ 7908fae3551SRodney W. Grimes int 7918fae3551SRodney W. Grimes xdr_explist(xdrsp, cp) 7928fae3551SRodney W. Grimes XDR *xdrsp; 7938fae3551SRodney W. Grimes caddr_t cp; 7948fae3551SRodney W. Grimes { 7958fae3551SRodney W. Grimes struct exportlist *ep; 7968fae3551SRodney W. Grimes int false = 0; 797a62dc406SDoug Rabson int putdef; 798a62dc406SDoug Rabson sigset_t sighup_mask; 7998fae3551SRodney W. Grimes 800a62dc406SDoug Rabson sigemptyset(&sighup_mask); 801a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 802a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 8038fae3551SRodney W. Grimes ep = exphead; 8048fae3551SRodney W. Grimes while (ep) { 8058fae3551SRodney W. Grimes putdef = 0; 8068fae3551SRodney W. Grimes if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, &putdef)) 8078fae3551SRodney W. Grimes goto errout; 8088fae3551SRodney W. Grimes if (ep->ex_defdir && putdef == 0 && 8098fae3551SRodney W. Grimes put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL, 8108fae3551SRodney W. Grimes &putdef)) 8118fae3551SRodney W. Grimes goto errout; 8128fae3551SRodney W. Grimes ep = ep->ex_next; 8138fae3551SRodney W. Grimes } 814a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 8158fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 8168fae3551SRodney W. Grimes return (0); 8178fae3551SRodney W. Grimes return (1); 8188fae3551SRodney W. Grimes errout: 819a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 8208fae3551SRodney W. Grimes return (0); 8218fae3551SRodney W. Grimes } 8228fae3551SRodney W. Grimes 8238fae3551SRodney W. Grimes /* 8248fae3551SRodney W. Grimes * Called from xdr_explist() to traverse the tree and export the 8258fae3551SRodney W. Grimes * directory paths. 8268fae3551SRodney W. Grimes */ 8278fae3551SRodney W. Grimes int 8288fae3551SRodney W. Grimes put_exlist(dp, xdrsp, adp, putdefp) 8298fae3551SRodney W. Grimes struct dirlist *dp; 8308fae3551SRodney W. Grimes XDR *xdrsp; 8318fae3551SRodney W. Grimes struct dirlist *adp; 8328fae3551SRodney W. Grimes int *putdefp; 8338fae3551SRodney W. Grimes { 8348fae3551SRodney W. Grimes struct grouplist *grp; 8358fae3551SRodney W. Grimes struct hostlist *hp; 8368fae3551SRodney W. Grimes int true = 1; 8378fae3551SRodney W. Grimes int false = 0; 8388fae3551SRodney W. Grimes int gotalldir = 0; 8398fae3551SRodney W. Grimes char *strp; 8408fae3551SRodney W. Grimes 8418fae3551SRodney W. Grimes if (dp) { 8428fae3551SRodney W. Grimes if (put_exlist(dp->dp_left, xdrsp, adp, putdefp)) 8438fae3551SRodney W. Grimes return (1); 8448fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 8458fae3551SRodney W. Grimes return (1); 8468fae3551SRodney W. Grimes strp = dp->dp_dirp; 8478fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 8488fae3551SRodney W. Grimes return (1); 8498fae3551SRodney W. Grimes if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) { 8508fae3551SRodney W. Grimes gotalldir = 1; 8518fae3551SRodney W. Grimes *putdefp = 1; 8528fae3551SRodney W. Grimes } 8538fae3551SRodney W. Grimes 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); 8828fae3551SRodney W. Grimes if (put_exlist(dp->dp_right, xdrsp, adp, putdefp)) 8838fae3551SRodney W. Grimes return (1); 8848fae3551SRodney W. Grimes } 8858fae3551SRodney W. Grimes return (0); 8868fae3551SRodney W. Grimes } 8878fae3551SRodney W. Grimes 8888fae3551SRodney W. Grimes #define LINESIZ 10240 8898fae3551SRodney W. Grimes char line[LINESIZ]; 8908fae3551SRodney W. Grimes FILE *exp_file; 8918fae3551SRodney W. Grimes 8928fae3551SRodney W. Grimes /* 8938fae3551SRodney W. Grimes * Get the export list 8948fae3551SRodney W. Grimes */ 8958fae3551SRodney W. Grimes void 8968fae3551SRodney W. Grimes get_exportlist() 8978fae3551SRodney W. Grimes { 8988fae3551SRodney W. Grimes struct exportlist *ep, *ep2; 8998fae3551SRodney W. Grimes struct grouplist *grp, *tgrp; 9008fae3551SRodney W. Grimes struct exportlist **epp; 9018fae3551SRodney W. Grimes struct dirlist *dirhead; 9028fae3551SRodney W. Grimes struct statfs fsb, *fsp; 903c0511d3bSBrian Feldman struct xucred anon; 9048fae3551SRodney W. Grimes char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; 9058fae3551SRodney W. Grimes int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp; 9068fae3551SRodney W. Grimes 907cb479b11SAlfred Perlstein dirp = NULL; 908cb479b11SAlfred Perlstein dirplen = 0; 909cb479b11SAlfred Perlstein 9108fae3551SRodney W. Grimes /* 9118fae3551SRodney W. Grimes * First, get rid of the old list 9128fae3551SRodney W. Grimes */ 9138fae3551SRodney W. Grimes ep = exphead; 9148fae3551SRodney W. Grimes while (ep) { 9158fae3551SRodney W. Grimes ep2 = ep; 9168fae3551SRodney W. Grimes ep = ep->ex_next; 9178fae3551SRodney W. Grimes free_exp(ep2); 9188fae3551SRodney W. Grimes } 9198fae3551SRodney W. Grimes exphead = (struct exportlist *)NULL; 9208fae3551SRodney W. Grimes 9218fae3551SRodney W. Grimes grp = grphead; 9228fae3551SRodney W. Grimes while (grp) { 9238fae3551SRodney W. Grimes tgrp = grp; 9248fae3551SRodney W. Grimes grp = grp->gr_next; 9258fae3551SRodney W. Grimes free_grp(tgrp); 9268fae3551SRodney W. Grimes } 9278fae3551SRodney W. Grimes grphead = (struct grouplist *)NULL; 9288fae3551SRodney W. Grimes 9298fae3551SRodney W. Grimes /* 9308fae3551SRodney W. Grimes * And delete exports that are in the kernel for all local 9318fae3551SRodney W. Grimes * file systems. 9328fae3551SRodney W. Grimes * XXX: Should know how to handle all local exportable file systems 93387564113SPeter Wemm * instead of just "ufs". 9348fae3551SRodney W. Grimes */ 9358fae3551SRodney W. Grimes num = getmntinfo(&fsp, MNT_NOWAIT); 9368fae3551SRodney W. Grimes for (i = 0; i < num; i++) { 9378fae3551SRodney W. Grimes union { 9388fae3551SRodney W. Grimes struct ufs_args ua; 9398fae3551SRodney W. Grimes struct iso_args ia; 9408fae3551SRodney W. Grimes struct mfs_args ma; 941a62dc406SDoug Rabson struct msdosfs_args da; 9429300c696SSemen Ustimenko struct ntfs_args na; 943a62dc406SDoug Rabson } targs; 944a62dc406SDoug Rabson 94587564113SPeter Wemm if (!strcmp(fsp->f_fstypename, "mfs") || 94687564113SPeter Wemm !strcmp(fsp->f_fstypename, "ufs") || 94787564113SPeter Wemm !strcmp(fsp->f_fstypename, "msdos") || 9489300c696SSemen Ustimenko !strcmp(fsp->f_fstypename, "ntfs") || 94987564113SPeter Wemm !strcmp(fsp->f_fstypename, "cd9660")) { 950a62dc406SDoug Rabson targs.ua.fspec = NULL; 951a62dc406SDoug Rabson targs.ua.export.ex_flags = MNT_DELEXPORT; 952a62dc406SDoug Rabson if (mount(fsp->f_fstypename, fsp->f_mntonname, 9538fae3551SRodney W. Grimes fsp->f_flags | MNT_UPDATE, 9548fae3551SRodney W. Grimes (caddr_t)&targs) < 0) 95574853402SPhilippe Charnier syslog(LOG_ERR, "can't delete exports for %s", 9568fae3551SRodney W. Grimes fsp->f_mntonname); 9578fae3551SRodney W. Grimes } 9588fae3551SRodney W. Grimes fsp++; 9598fae3551SRodney W. Grimes } 9608fae3551SRodney W. Grimes 9618fae3551SRodney W. Grimes /* 9628fae3551SRodney W. Grimes * Read in the exports file and build the list, calling 9638fae3551SRodney W. Grimes * mount() as we go along to push the export rules into the kernel. 9648fae3551SRodney W. Grimes */ 9658fae3551SRodney W. Grimes if ((exp_file = fopen(exname, "r")) == NULL) { 96674853402SPhilippe Charnier syslog(LOG_ERR, "can't open %s", exname); 9678fae3551SRodney W. Grimes exit(2); 9688fae3551SRodney W. Grimes } 9698fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 9708fae3551SRodney W. Grimes while (get_line()) { 9718fae3551SRodney W. Grimes if (debug) 97274853402SPhilippe Charnier warnx("got line %s", line); 9738fae3551SRodney W. Grimes cp = line; 9748fae3551SRodney W. Grimes nextfield(&cp, &endcp); 9758fae3551SRodney W. Grimes if (*cp == '#') 9768fae3551SRodney W. Grimes goto nextline; 9778fae3551SRodney W. Grimes 9788fae3551SRodney W. Grimes /* 9798fae3551SRodney W. Grimes * Set defaults. 9808fae3551SRodney W. Grimes */ 9818fae3551SRodney W. Grimes has_host = FALSE; 9828fae3551SRodney W. Grimes anon = def_anon; 9838fae3551SRodney W. Grimes exflags = MNT_EXPORTED; 9848fae3551SRodney W. Grimes got_nondir = 0; 9858fae3551SRodney W. Grimes opt_flags = 0; 9868fae3551SRodney W. Grimes ep = (struct exportlist *)NULL; 9878fae3551SRodney W. Grimes 9888fae3551SRodney W. Grimes /* 9898fae3551SRodney W. Grimes * Create new exports list entry 9908fae3551SRodney W. Grimes */ 9918fae3551SRodney W. Grimes len = endcp-cp; 9928fae3551SRodney W. Grimes tgrp = grp = get_grp(); 9938fae3551SRodney W. Grimes while (len > 0) { 9948fae3551SRodney W. Grimes if (len > RPCMNT_NAMELEN) { 9958fae3551SRodney W. Grimes getexp_err(ep, tgrp); 9968fae3551SRodney W. Grimes goto nextline; 9978fae3551SRodney W. Grimes } 9988fae3551SRodney W. Grimes if (*cp == '-') { 9998fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10008fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10018fae3551SRodney W. Grimes goto nextline; 10028fae3551SRodney W. Grimes } 10038fae3551SRodney W. Grimes if (debug) 100474853402SPhilippe Charnier warnx("doing opt %s", cp); 10058fae3551SRodney W. Grimes got_nondir = 1; 10068fae3551SRodney W. Grimes if (do_opt(&cp, &endcp, ep, grp, &has_host, 10078fae3551SRodney W. Grimes &exflags, &anon)) { 10088fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10098fae3551SRodney W. Grimes goto nextline; 10108fae3551SRodney W. Grimes } 10118fae3551SRodney W. Grimes } else if (*cp == '/') { 10128fae3551SRodney W. Grimes savedc = *endcp; 10138fae3551SRodney W. Grimes *endcp = '\0'; 10148fae3551SRodney W. Grimes if (check_dirpath(cp) && 10158fae3551SRodney W. Grimes statfs(cp, &fsb) >= 0) { 10168fae3551SRodney W. Grimes if (got_nondir) { 101774853402SPhilippe Charnier syslog(LOG_ERR, "dirs must be first"); 10188fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10198fae3551SRodney W. Grimes goto nextline; 10208fae3551SRodney W. Grimes } 10218fae3551SRodney W. Grimes if (ep) { 10228fae3551SRodney W. Grimes if (ep->ex_fs.val[0] != fsb.f_fsid.val[0] || 10238fae3551SRodney W. Grimes ep->ex_fs.val[1] != fsb.f_fsid.val[1]) { 10248fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10258fae3551SRodney W. Grimes goto nextline; 10268fae3551SRodney W. Grimes } 10278fae3551SRodney W. Grimes } else { 10288fae3551SRodney W. Grimes /* 10298fae3551SRodney W. Grimes * See if this directory is already 10308fae3551SRodney W. Grimes * in the list. 10318fae3551SRodney W. Grimes */ 10328fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 10338fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10348fae3551SRodney W. Grimes ep = get_exp(); 10358fae3551SRodney W. Grimes ep->ex_fs = fsb.f_fsid; 10368fae3551SRodney W. Grimes ep->ex_fsdir = (char *) 10378fae3551SRodney W. Grimes malloc(strlen(fsb.f_mntonname) + 1); 10388fae3551SRodney W. Grimes if (ep->ex_fsdir) 10398fae3551SRodney W. Grimes strcpy(ep->ex_fsdir, 10408fae3551SRodney W. Grimes fsb.f_mntonname); 10418fae3551SRodney W. Grimes else 10428fae3551SRodney W. Grimes out_of_mem(); 10438fae3551SRodney W. Grimes if (debug) 104474853402SPhilippe Charnier warnx("making new ep fs=0x%x,0x%x", 10458fae3551SRodney W. Grimes fsb.f_fsid.val[0], 10468fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 10478fae3551SRodney W. Grimes } else if (debug) 104874853402SPhilippe Charnier warnx("found ep fs=0x%x,0x%x", 10498fae3551SRodney W. Grimes fsb.f_fsid.val[0], 10508fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 10518fae3551SRodney W. Grimes } 10528fae3551SRodney W. Grimes 10538fae3551SRodney W. Grimes /* 10548fae3551SRodney W. Grimes * Add dirpath to export mount point. 10558fae3551SRodney W. Grimes */ 10568fae3551SRodney W. Grimes dirp = add_expdir(&dirhead, cp, len); 10578fae3551SRodney W. Grimes dirplen = len; 10588fae3551SRodney W. Grimes } else { 10598fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10608fae3551SRodney W. Grimes goto nextline; 10618fae3551SRodney W. Grimes } 10628fae3551SRodney W. Grimes *endcp = savedc; 10638fae3551SRodney W. Grimes } else { 10648fae3551SRodney W. Grimes savedc = *endcp; 10658fae3551SRodney W. Grimes *endcp = '\0'; 10668fae3551SRodney W. Grimes got_nondir = 1; 10678fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10688fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10698fae3551SRodney W. Grimes goto nextline; 10708fae3551SRodney W. Grimes } 10718fae3551SRodney W. Grimes 10728fae3551SRodney W. Grimes /* 10738fae3551SRodney W. Grimes * Get the host or netgroup. 10748fae3551SRodney W. Grimes */ 10758fae3551SRodney W. Grimes setnetgrent(cp); 10768fae3551SRodney W. Grimes netgrp = getnetgrent(&hst, &usr, &dom); 10778fae3551SRodney W. Grimes do { 10788fae3551SRodney W. Grimes if (has_host) { 10798fae3551SRodney W. Grimes grp->gr_next = get_grp(); 10808fae3551SRodney W. Grimes grp = grp->gr_next; 10818fae3551SRodney W. Grimes } 10828fae3551SRodney W. Grimes if (netgrp) { 10839d70a156SJoerg Wunsch if (hst == 0) { 108474853402SPhilippe Charnier syslog(LOG_ERR, 108574853402SPhilippe Charnier "null hostname in netgroup %s, skipping", cp); 108601d48801SJoerg Wunsch grp->gr_type = GT_IGNORE; 10879d70a156SJoerg Wunsch } else if (get_host(hst, grp, tgrp)) { 108874853402SPhilippe Charnier syslog(LOG_ERR, 108974853402SPhilippe Charnier "bad host %s in netgroup %s, skipping", hst, cp); 1090a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 10918fae3551SRodney W. Grimes } 10928b5a6d67SBill Paul } else if (get_host(cp, grp, tgrp)) { 109374853402SPhilippe Charnier syslog(LOG_ERR, "bad host %s, skipping", cp); 1094a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 10958fae3551SRodney W. Grimes } 10968fae3551SRodney W. Grimes has_host = TRUE; 10978fae3551SRodney W. Grimes } while (netgrp && getnetgrent(&hst, &usr, &dom)); 10988fae3551SRodney W. Grimes endnetgrent(); 10998fae3551SRodney W. Grimes *endcp = savedc; 11008fae3551SRodney W. Grimes } 11018fae3551SRodney W. Grimes cp = endcp; 11028fae3551SRodney W. Grimes nextfield(&cp, &endcp); 11038fae3551SRodney W. Grimes len = endcp - cp; 11048fae3551SRodney W. Grimes } 11058fae3551SRodney W. Grimes if (check_options(dirhead)) { 11068fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11078fae3551SRodney W. Grimes goto nextline; 11088fae3551SRodney W. Grimes } 11098fae3551SRodney W. Grimes if (!has_host) { 11106d359f31SIan Dowse grp->gr_type = GT_DEFAULT; 11118fae3551SRodney W. Grimes if (debug) 111274853402SPhilippe Charnier warnx("adding a default entry"); 11138fae3551SRodney W. Grimes 11148fae3551SRodney W. Grimes /* 11158fae3551SRodney W. Grimes * Don't allow a network export coincide with a list of 11168fae3551SRodney W. Grimes * host(s) on the same line. 11178fae3551SRodney W. Grimes */ 11188fae3551SRodney W. Grimes } else if ((opt_flags & OP_NET) && tgrp->gr_next) { 11198fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11208fae3551SRodney W. Grimes goto nextline; 1121a968cfd8SJonathan Lemon 1122a968cfd8SJonathan Lemon /* 1123a968cfd8SJonathan Lemon * If an export list was specified on this line, make sure 1124a968cfd8SJonathan Lemon * that we have at least one valid entry, otherwise skip it. 1125a968cfd8SJonathan Lemon */ 1126a968cfd8SJonathan Lemon } else { 1127a968cfd8SJonathan Lemon grp = tgrp; 1128a968cfd8SJonathan Lemon while (grp && grp->gr_type == GT_IGNORE) 1129a968cfd8SJonathan Lemon grp = grp->gr_next; 1130a968cfd8SJonathan Lemon if (! grp) { 1131a968cfd8SJonathan Lemon getexp_err(ep, tgrp); 1132a968cfd8SJonathan Lemon goto nextline; 1133a968cfd8SJonathan Lemon } 11348fae3551SRodney W. Grimes } 11358fae3551SRodney W. Grimes 11368fae3551SRodney W. Grimes /* 11378fae3551SRodney W. Grimes * Loop through hosts, pushing the exports into the kernel. 11388fae3551SRodney W. Grimes * After loop, tgrp points to the start of the list and 11398fae3551SRodney W. Grimes * grp points to the last entry in the list. 11408fae3551SRodney W. Grimes */ 11418fae3551SRodney W. Grimes grp = tgrp; 11428fae3551SRodney W. Grimes do { 114301709abfSIan Dowse if (do_mount(ep, grp, exflags, &anon, dirp, dirplen, 114401709abfSIan Dowse &fsb)) { 11458fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11468fae3551SRodney W. Grimes goto nextline; 11478fae3551SRodney W. Grimes } 11488fae3551SRodney W. Grimes } while (grp->gr_next && (grp = grp->gr_next)); 11498fae3551SRodney W. Grimes 11508fae3551SRodney W. Grimes /* 11518fae3551SRodney W. Grimes * Success. Update the data structures. 11528fae3551SRodney W. Grimes */ 11538fae3551SRodney W. Grimes if (has_host) { 1154a62dc406SDoug Rabson hang_dirp(dirhead, tgrp, ep, opt_flags); 11558fae3551SRodney W. Grimes grp->gr_next = grphead; 11568fae3551SRodney W. Grimes grphead = tgrp; 11578fae3551SRodney W. Grimes } else { 11588fae3551SRodney W. Grimes hang_dirp(dirhead, (struct grouplist *)NULL, ep, 1159a62dc406SDoug Rabson opt_flags); 11608fae3551SRodney W. Grimes free_grp(grp); 11618fae3551SRodney W. Grimes } 11628fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 11638fae3551SRodney W. Grimes if ((ep->ex_flag & EX_LINKED) == 0) { 11648fae3551SRodney W. Grimes ep2 = exphead; 11658fae3551SRodney W. Grimes epp = &exphead; 11668fae3551SRodney W. Grimes 11678fae3551SRodney W. Grimes /* 11688fae3551SRodney W. Grimes * Insert in the list in alphabetical order. 11698fae3551SRodney W. Grimes */ 11708fae3551SRodney W. Grimes while (ep2 && strcmp(ep2->ex_fsdir, ep->ex_fsdir) < 0) { 11718fae3551SRodney W. Grimes epp = &ep2->ex_next; 11728fae3551SRodney W. Grimes ep2 = ep2->ex_next; 11738fae3551SRodney W. Grimes } 11748fae3551SRodney W. Grimes if (ep2) 11758fae3551SRodney W. Grimes ep->ex_next = ep2; 11768fae3551SRodney W. Grimes *epp = ep; 11778fae3551SRodney W. Grimes ep->ex_flag |= EX_LINKED; 11788fae3551SRodney W. Grimes } 11798fae3551SRodney W. Grimes nextline: 11808fae3551SRodney W. Grimes if (dirhead) { 11818fae3551SRodney W. Grimes free_dir(dirhead); 11828fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 11838fae3551SRodney W. Grimes } 11848fae3551SRodney W. Grimes } 11858fae3551SRodney W. Grimes fclose(exp_file); 11868fae3551SRodney W. Grimes } 11878fae3551SRodney W. Grimes 11888fae3551SRodney W. Grimes /* 11898fae3551SRodney W. Grimes * Allocate an export list element 11908fae3551SRodney W. Grimes */ 11918fae3551SRodney W. Grimes struct exportlist * 11928fae3551SRodney W. Grimes get_exp() 11938fae3551SRodney W. Grimes { 11948fae3551SRodney W. Grimes struct exportlist *ep; 11958fae3551SRodney W. Grimes 11968fae3551SRodney W. Grimes ep = (struct exportlist *)malloc(sizeof (struct exportlist)); 11978fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) 11988fae3551SRodney W. Grimes out_of_mem(); 119987564113SPeter Wemm memset(ep, 0, sizeof(struct exportlist)); 12008fae3551SRodney W. Grimes return (ep); 12018fae3551SRodney W. Grimes } 12028fae3551SRodney W. Grimes 12038fae3551SRodney W. Grimes /* 12048fae3551SRodney W. Grimes * Allocate a group list element 12058fae3551SRodney W. Grimes */ 12068fae3551SRodney W. Grimes struct grouplist * 12078fae3551SRodney W. Grimes get_grp() 12088fae3551SRodney W. Grimes { 12098fae3551SRodney W. Grimes struct grouplist *gp; 12108fae3551SRodney W. Grimes 12118fae3551SRodney W. Grimes gp = (struct grouplist *)malloc(sizeof (struct grouplist)); 12128fae3551SRodney W. Grimes if (gp == (struct grouplist *)NULL) 12138fae3551SRodney W. Grimes out_of_mem(); 121487564113SPeter Wemm memset(gp, 0, sizeof(struct grouplist)); 12158fae3551SRodney W. Grimes return (gp); 12168fae3551SRodney W. Grimes } 12178fae3551SRodney W. Grimes 12188fae3551SRodney W. Grimes /* 12198fae3551SRodney W. Grimes * Clean up upon an error in get_exportlist(). 12208fae3551SRodney W. Grimes */ 12218fae3551SRodney W. Grimes void 12228fae3551SRodney W. Grimes getexp_err(ep, grp) 12238fae3551SRodney W. Grimes struct exportlist *ep; 12248fae3551SRodney W. Grimes struct grouplist *grp; 12258fae3551SRodney W. Grimes { 12268fae3551SRodney W. Grimes struct grouplist *tgrp; 12278fae3551SRodney W. Grimes 122874853402SPhilippe Charnier syslog(LOG_ERR, "bad exports list line %s", line); 12298fae3551SRodney W. Grimes if (ep && (ep->ex_flag & EX_LINKED) == 0) 12308fae3551SRodney W. Grimes free_exp(ep); 12318fae3551SRodney W. Grimes while (grp) { 12328fae3551SRodney W. Grimes tgrp = grp; 12338fae3551SRodney W. Grimes grp = grp->gr_next; 12348fae3551SRodney W. Grimes free_grp(tgrp); 12358fae3551SRodney W. Grimes } 12368fae3551SRodney W. Grimes } 12378fae3551SRodney W. Grimes 12388fae3551SRodney W. Grimes /* 12398fae3551SRodney W. Grimes * Search the export list for a matching fs. 12408fae3551SRodney W. Grimes */ 12418fae3551SRodney W. Grimes struct exportlist * 12428fae3551SRodney W. Grimes ex_search(fsid) 12438fae3551SRodney W. Grimes fsid_t *fsid; 12448fae3551SRodney W. Grimes { 12458fae3551SRodney W. Grimes struct exportlist *ep; 12468fae3551SRodney W. Grimes 12478fae3551SRodney W. Grimes ep = exphead; 12488fae3551SRodney W. Grimes while (ep) { 12498fae3551SRodney W. Grimes if (ep->ex_fs.val[0] == fsid->val[0] && 12508fae3551SRodney W. Grimes ep->ex_fs.val[1] == fsid->val[1]) 12518fae3551SRodney W. Grimes return (ep); 12528fae3551SRodney W. Grimes ep = ep->ex_next; 12538fae3551SRodney W. Grimes } 12548fae3551SRodney W. Grimes return (ep); 12558fae3551SRodney W. Grimes } 12568fae3551SRodney W. Grimes 12578fae3551SRodney W. Grimes /* 12588fae3551SRodney W. Grimes * Add a directory path to the list. 12598fae3551SRodney W. Grimes */ 12608fae3551SRodney W. Grimes char * 12618fae3551SRodney W. Grimes add_expdir(dpp, cp, len) 12628fae3551SRodney W. Grimes struct dirlist **dpp; 12638fae3551SRodney W. Grimes char *cp; 12648fae3551SRodney W. Grimes int len; 12658fae3551SRodney W. Grimes { 12668fae3551SRodney W. Grimes struct dirlist *dp; 12678fae3551SRodney W. Grimes 12688fae3551SRodney W. Grimes dp = (struct dirlist *)malloc(sizeof (struct dirlist) + len); 126974853402SPhilippe Charnier if (dp == (struct dirlist *)NULL) 127074853402SPhilippe Charnier out_of_mem(); 12718fae3551SRodney W. Grimes dp->dp_left = *dpp; 12728fae3551SRodney W. Grimes dp->dp_right = (struct dirlist *)NULL; 12738fae3551SRodney W. Grimes dp->dp_flag = 0; 12748fae3551SRodney W. Grimes dp->dp_hosts = (struct hostlist *)NULL; 12758fae3551SRodney W. Grimes strcpy(dp->dp_dirp, cp); 12768fae3551SRodney W. Grimes *dpp = dp; 12778fae3551SRodney W. Grimes return (dp->dp_dirp); 12788fae3551SRodney W. Grimes } 12798fae3551SRodney W. Grimes 12808fae3551SRodney W. Grimes /* 12818fae3551SRodney W. Grimes * Hang the dir list element off the dirpath binary tree as required 12828fae3551SRodney W. Grimes * and update the entry for host. 12838fae3551SRodney W. Grimes */ 12848fae3551SRodney W. Grimes void 1285a62dc406SDoug Rabson hang_dirp(dp, grp, ep, flags) 12868fae3551SRodney W. Grimes struct dirlist *dp; 12878fae3551SRodney W. Grimes struct grouplist *grp; 12888fae3551SRodney W. Grimes struct exportlist *ep; 1289a62dc406SDoug Rabson int flags; 12908fae3551SRodney W. Grimes { 12918fae3551SRodney W. Grimes struct hostlist *hp; 12928fae3551SRodney W. Grimes struct dirlist *dp2; 12938fae3551SRodney W. Grimes 1294a62dc406SDoug Rabson if (flags & OP_ALLDIRS) { 12958fae3551SRodney W. Grimes if (ep->ex_defdir) 12968fae3551SRodney W. Grimes free((caddr_t)dp); 12978fae3551SRodney W. Grimes else 12988fae3551SRodney W. Grimes ep->ex_defdir = dp; 1299a62dc406SDoug Rabson if (grp == (struct grouplist *)NULL) { 13008fae3551SRodney W. Grimes ep->ex_defdir->dp_flag |= DP_DEFSET; 1301a62dc406SDoug Rabson if (flags & OP_KERB) 1302a62dc406SDoug Rabson ep->ex_defdir->dp_flag |= DP_KERB; 1303a62dc406SDoug Rabson } else while (grp) { 13048fae3551SRodney W. Grimes hp = get_ht(); 1305a62dc406SDoug Rabson if (flags & OP_KERB) 1306a62dc406SDoug Rabson hp->ht_flag |= DP_KERB; 13078fae3551SRodney W. Grimes hp->ht_grp = grp; 13088fae3551SRodney W. Grimes hp->ht_next = ep->ex_defdir->dp_hosts; 13098fae3551SRodney W. Grimes ep->ex_defdir->dp_hosts = hp; 13108fae3551SRodney W. Grimes grp = grp->gr_next; 13118fae3551SRodney W. Grimes } 13128fae3551SRodney W. Grimes } else { 13138fae3551SRodney W. Grimes 13148fae3551SRodney W. Grimes /* 131574853402SPhilippe Charnier * Loop through the directories adding them to the tree. 13168fae3551SRodney W. Grimes */ 13178fae3551SRodney W. Grimes while (dp) { 13188fae3551SRodney W. Grimes dp2 = dp->dp_left; 1319a62dc406SDoug Rabson add_dlist(&ep->ex_dirl, dp, grp, flags); 13208fae3551SRodney W. Grimes dp = dp2; 13218fae3551SRodney W. Grimes } 13228fae3551SRodney W. Grimes } 13238fae3551SRodney W. Grimes } 13248fae3551SRodney W. Grimes 13258fae3551SRodney W. Grimes /* 13268fae3551SRodney W. Grimes * Traverse the binary tree either updating a node that is already there 13278fae3551SRodney W. Grimes * for the new directory or adding the new node. 13288fae3551SRodney W. Grimes */ 13298fae3551SRodney W. Grimes void 1330a62dc406SDoug Rabson add_dlist(dpp, newdp, grp, flags) 13318fae3551SRodney W. Grimes struct dirlist **dpp; 13328fae3551SRodney W. Grimes struct dirlist *newdp; 13338fae3551SRodney W. Grimes struct grouplist *grp; 1334a62dc406SDoug Rabson int flags; 13358fae3551SRodney W. Grimes { 13368fae3551SRodney W. Grimes struct dirlist *dp; 13378fae3551SRodney W. Grimes struct hostlist *hp; 13388fae3551SRodney W. Grimes int cmp; 13398fae3551SRodney W. Grimes 13408fae3551SRodney W. Grimes dp = *dpp; 13418fae3551SRodney W. Grimes if (dp) { 13428fae3551SRodney W. Grimes cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); 13438fae3551SRodney W. Grimes if (cmp > 0) { 1344a62dc406SDoug Rabson add_dlist(&dp->dp_left, newdp, grp, flags); 13458fae3551SRodney W. Grimes return; 13468fae3551SRodney W. Grimes } else if (cmp < 0) { 1347a62dc406SDoug Rabson add_dlist(&dp->dp_right, newdp, grp, flags); 13488fae3551SRodney W. Grimes return; 13498fae3551SRodney W. Grimes } else 13508fae3551SRodney W. Grimes free((caddr_t)newdp); 13518fae3551SRodney W. Grimes } else { 13528fae3551SRodney W. Grimes dp = newdp; 13538fae3551SRodney W. Grimes dp->dp_left = (struct dirlist *)NULL; 13548fae3551SRodney W. Grimes *dpp = dp; 13558fae3551SRodney W. Grimes } 13568fae3551SRodney W. Grimes if (grp) { 13578fae3551SRodney W. Grimes 13588fae3551SRodney W. Grimes /* 13598fae3551SRodney W. Grimes * Hang all of the host(s) off of the directory point. 13608fae3551SRodney W. Grimes */ 13618fae3551SRodney W. Grimes do { 13628fae3551SRodney W. Grimes hp = get_ht(); 1363a62dc406SDoug Rabson if (flags & OP_KERB) 1364a62dc406SDoug Rabson hp->ht_flag |= DP_KERB; 13658fae3551SRodney W. Grimes hp->ht_grp = grp; 13668fae3551SRodney W. Grimes hp->ht_next = dp->dp_hosts; 13678fae3551SRodney W. Grimes dp->dp_hosts = hp; 13688fae3551SRodney W. Grimes grp = grp->gr_next; 13698fae3551SRodney W. Grimes } while (grp); 1370a62dc406SDoug Rabson } else { 13718fae3551SRodney W. Grimes dp->dp_flag |= DP_DEFSET; 1372a62dc406SDoug Rabson if (flags & OP_KERB) 1373a62dc406SDoug Rabson dp->dp_flag |= DP_KERB; 1374a62dc406SDoug Rabson } 13758fae3551SRodney W. Grimes } 13768fae3551SRodney W. Grimes 13778fae3551SRodney W. Grimes /* 13788fae3551SRodney W. Grimes * Search for a dirpath on the export point. 13798fae3551SRodney W. Grimes */ 13808fae3551SRodney W. Grimes struct dirlist * 13818360efbdSAlfred Perlstein dirp_search(dp, dirp) 13828fae3551SRodney W. Grimes struct dirlist *dp; 13838360efbdSAlfred Perlstein char *dirp; 13848fae3551SRodney W. Grimes { 13858fae3551SRodney W. Grimes int cmp; 13868fae3551SRodney W. Grimes 13878fae3551SRodney W. Grimes if (dp) { 13888360efbdSAlfred Perlstein cmp = strcmp(dp->dp_dirp, dirp); 13898fae3551SRodney W. Grimes if (cmp > 0) 13908360efbdSAlfred Perlstein return (dirp_search(dp->dp_left, dirp)); 13918fae3551SRodney W. Grimes else if (cmp < 0) 13928360efbdSAlfred Perlstein return (dirp_search(dp->dp_right, dirp)); 13938fae3551SRodney W. Grimes else 13948fae3551SRodney W. Grimes return (dp); 13958fae3551SRodney W. Grimes } 13968fae3551SRodney W. Grimes return (dp); 13978fae3551SRodney W. Grimes } 13988fae3551SRodney W. Grimes 13998fae3551SRodney W. Grimes /* 14008360efbdSAlfred Perlstein * Some helper functions for netmasks. They all assume masks in network 14018360efbdSAlfred Perlstein * order (big endian). 14028360efbdSAlfred Perlstein */ 14038360efbdSAlfred Perlstein static int 14048360efbdSAlfred Perlstein bitcmp(void *dst, void *src, int bitlen) 14058360efbdSAlfred Perlstein { 14068360efbdSAlfred Perlstein int i; 14078360efbdSAlfred Perlstein u_int8_t *p1 = dst, *p2 = src; 14088360efbdSAlfred Perlstein u_int8_t bitmask; 14098360efbdSAlfred Perlstein int bytelen, bitsleft; 14108360efbdSAlfred Perlstein 14118360efbdSAlfred Perlstein bytelen = bitlen / 8; 14128360efbdSAlfred Perlstein bitsleft = bitlen % 8; 14138360efbdSAlfred Perlstein 14148360efbdSAlfred Perlstein if (debug) { 14158360efbdSAlfred Perlstein printf("comparing:\n"); 14168360efbdSAlfred Perlstein for (i = 0; i < (bitsleft ? bytelen + 1 : bytelen); i++) 14178360efbdSAlfred Perlstein printf("%02x", p1[i]); 14188360efbdSAlfred Perlstein printf("\n"); 14198360efbdSAlfred Perlstein for (i = 0; i < (bitsleft ? bytelen + 1 : bytelen); i++) 14208360efbdSAlfred Perlstein printf("%02x", p2[i]); 14218360efbdSAlfred Perlstein printf("\n"); 14228360efbdSAlfred Perlstein } 14238360efbdSAlfred Perlstein 14248360efbdSAlfred Perlstein for (i = 0; i < bytelen; i++) { 14258360efbdSAlfred Perlstein if (*p1 != *p2) 14268360efbdSAlfred Perlstein return 1; 14278360efbdSAlfred Perlstein p1++; 14288360efbdSAlfred Perlstein p2++; 14298360efbdSAlfred Perlstein } 14308360efbdSAlfred Perlstein 14318360efbdSAlfred Perlstein for (i = 0; i < bitsleft; i++) { 14328360efbdSAlfred Perlstein bitmask = 1 << (7 - i); 14338360efbdSAlfred Perlstein if ((*p1 & bitmask) != (*p2 & bitmask)) 14348360efbdSAlfred Perlstein return 1; 14358360efbdSAlfred Perlstein } 14368360efbdSAlfred Perlstein 14378360efbdSAlfred Perlstein return 0; 14388360efbdSAlfred Perlstein } 14398360efbdSAlfred Perlstein 14408360efbdSAlfred Perlstein /* 14418fae3551SRodney W. Grimes * Scan for a host match in a directory tree. 14428fae3551SRodney W. Grimes */ 14438fae3551SRodney W. Grimes int 1444a62dc406SDoug Rabson chk_host(dp, saddr, defsetp, hostsetp) 14458fae3551SRodney W. Grimes struct dirlist *dp; 14468360efbdSAlfred Perlstein struct sockaddr *saddr; 14478fae3551SRodney W. Grimes int *defsetp; 1448a62dc406SDoug Rabson int *hostsetp; 14498fae3551SRodney W. Grimes { 14508fae3551SRodney W. Grimes struct hostlist *hp; 14518fae3551SRodney W. Grimes struct grouplist *grp; 14528360efbdSAlfred Perlstein struct addrinfo *ai; 14538fae3551SRodney W. Grimes 14548fae3551SRodney W. Grimes if (dp) { 14558fae3551SRodney W. Grimes if (dp->dp_flag & DP_DEFSET) 1456a62dc406SDoug Rabson *defsetp = dp->dp_flag; 14578fae3551SRodney W. Grimes hp = dp->dp_hosts; 14588fae3551SRodney W. Grimes while (hp) { 14598fae3551SRodney W. Grimes grp = hp->ht_grp; 14608fae3551SRodney W. Grimes switch (grp->gr_type) { 14618fae3551SRodney W. Grimes case GT_HOST: 14628360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 14638360efbdSAlfred Perlstein for (; ai; ai = ai->ai_next) { 14648360efbdSAlfred Perlstein if (!sacmp(ai->ai_addr, saddr)) { 14658360efbdSAlfred Perlstein *hostsetp = 14668360efbdSAlfred Perlstein (hp->ht_flag | DP_HOSTSET); 14678fae3551SRodney W. Grimes return (1); 1468a62dc406SDoug Rabson } 14698fae3551SRodney W. Grimes } 14708fae3551SRodney W. Grimes break; 14718fae3551SRodney W. Grimes case GT_NET: 14728360efbdSAlfred Perlstein if (!netpartcmp(saddr, 14738360efbdSAlfred Perlstein (struct sockaddr *) &grp->gr_ptr.gt_net.nt_net, 14748360efbdSAlfred Perlstein grp->gr_ptr.gt_net.nt_mask)) { 1475a62dc406SDoug Rabson *hostsetp = (hp->ht_flag | DP_HOSTSET); 14768fae3551SRodney W. Grimes return (1); 1477a62dc406SDoug Rabson } 14788fae3551SRodney W. Grimes break; 14798fae3551SRodney W. Grimes }; 14808fae3551SRodney W. Grimes hp = hp->ht_next; 14818fae3551SRodney W. Grimes } 14828fae3551SRodney W. Grimes } 14838fae3551SRodney W. Grimes return (0); 14848fae3551SRodney W. Grimes } 14858fae3551SRodney W. Grimes 14868fae3551SRodney W. Grimes /* 14878fae3551SRodney W. Grimes * Scan tree for a host that matches the address. 14888fae3551SRodney W. Grimes */ 14898fae3551SRodney W. Grimes int 14908fae3551SRodney W. Grimes scan_tree(dp, saddr) 14918fae3551SRodney W. Grimes struct dirlist *dp; 14928360efbdSAlfred Perlstein struct sockaddr *saddr; 14938fae3551SRodney W. Grimes { 1494a62dc406SDoug Rabson int defset, hostset; 14958fae3551SRodney W. Grimes 14968fae3551SRodney W. Grimes if (dp) { 14978fae3551SRodney W. Grimes if (scan_tree(dp->dp_left, saddr)) 14988fae3551SRodney W. Grimes return (1); 1499a62dc406SDoug Rabson if (chk_host(dp, saddr, &defset, &hostset)) 15008fae3551SRodney W. Grimes return (1); 15018fae3551SRodney W. Grimes if (scan_tree(dp->dp_right, saddr)) 15028fae3551SRodney W. Grimes return (1); 15038fae3551SRodney W. Grimes } 15048fae3551SRodney W. Grimes return (0); 15058fae3551SRodney W. Grimes } 15068fae3551SRodney W. Grimes 15078fae3551SRodney W. Grimes /* 15088fae3551SRodney W. Grimes * Traverse the dirlist tree and free it up. 15098fae3551SRodney W. Grimes */ 15108fae3551SRodney W. Grimes void 15118fae3551SRodney W. Grimes free_dir(dp) 15128fae3551SRodney W. Grimes struct dirlist *dp; 15138fae3551SRodney W. Grimes { 15148fae3551SRodney W. Grimes 15158fae3551SRodney W. Grimes if (dp) { 15168fae3551SRodney W. Grimes free_dir(dp->dp_left); 15178fae3551SRodney W. Grimes free_dir(dp->dp_right); 15188fae3551SRodney W. Grimes free_host(dp->dp_hosts); 15198fae3551SRodney W. Grimes free((caddr_t)dp); 15208fae3551SRodney W. Grimes } 15218fae3551SRodney W. Grimes } 15228fae3551SRodney W. Grimes 15238fae3551SRodney W. Grimes /* 15248fae3551SRodney W. Grimes * Parse the option string and update fields. 15258fae3551SRodney W. Grimes * Option arguments may either be -<option>=<value> or 15268fae3551SRodney W. Grimes * -<option> <value> 15278fae3551SRodney W. Grimes */ 15288fae3551SRodney W. Grimes int 15298fae3551SRodney W. Grimes do_opt(cpp, endcpp, ep, grp, has_hostp, exflagsp, cr) 15308fae3551SRodney W. Grimes char **cpp, **endcpp; 15318fae3551SRodney W. Grimes struct exportlist *ep; 15328fae3551SRodney W. Grimes struct grouplist *grp; 15338fae3551SRodney W. Grimes int *has_hostp; 15348fae3551SRodney W. Grimes int *exflagsp; 1535c0511d3bSBrian Feldman struct xucred *cr; 15368fae3551SRodney W. Grimes { 15378fae3551SRodney W. Grimes char *cpoptarg, *cpoptend; 15388fae3551SRodney W. Grimes char *cp, *endcp, *cpopt, savedc, savedc2; 15398fae3551SRodney W. Grimes int allflag, usedarg; 15408fae3551SRodney W. Grimes 1541cb479b11SAlfred Perlstein savedc2 = '\0'; 15428fae3551SRodney W. Grimes cpopt = *cpp; 15438fae3551SRodney W. Grimes cpopt++; 15448fae3551SRodney W. Grimes cp = *endcpp; 15458fae3551SRodney W. Grimes savedc = *cp; 15468fae3551SRodney W. Grimes *cp = '\0'; 15478fae3551SRodney W. Grimes while (cpopt && *cpopt) { 15488fae3551SRodney W. Grimes allflag = 1; 15498fae3551SRodney W. Grimes usedarg = -2; 155074853402SPhilippe Charnier if ((cpoptend = strchr(cpopt, ','))) { 15518fae3551SRodney W. Grimes *cpoptend++ = '\0'; 155274853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 15538fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 15548fae3551SRodney W. Grimes } else { 155574853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 15568fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 15578fae3551SRodney W. Grimes else { 15588fae3551SRodney W. Grimes *cp = savedc; 15598fae3551SRodney W. Grimes nextfield(&cp, &endcp); 15608fae3551SRodney W. Grimes **endcpp = '\0'; 15618fae3551SRodney W. Grimes if (endcp > cp && *cp != '-') { 15628fae3551SRodney W. Grimes cpoptarg = cp; 15638fae3551SRodney W. Grimes savedc2 = *endcp; 15648fae3551SRodney W. Grimes *endcp = '\0'; 15658fae3551SRodney W. Grimes usedarg = 0; 15668fae3551SRodney W. Grimes } 15678fae3551SRodney W. Grimes } 15688fae3551SRodney W. Grimes } 15698fae3551SRodney W. Grimes if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 15708fae3551SRodney W. Grimes *exflagsp |= MNT_EXRDONLY; 15718fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "maproot") || 15728fae3551SRodney W. Grimes !(allflag = strcmp(cpopt, "mapall")) || 15738fae3551SRodney W. Grimes !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) { 15748fae3551SRodney W. Grimes usedarg++; 15758fae3551SRodney W. Grimes parsecred(cpoptarg, cr); 15768fae3551SRodney W. Grimes if (allflag == 0) { 15778fae3551SRodney W. Grimes *exflagsp |= MNT_EXPORTANON; 15788fae3551SRodney W. Grimes opt_flags |= OP_MAPALL; 15798fae3551SRodney W. Grimes } else 15808fae3551SRodney W. Grimes opt_flags |= OP_MAPROOT; 15818fae3551SRodney W. Grimes } else if (!strcmp(cpopt, "kerb") || !strcmp(cpopt, "k")) { 15828fae3551SRodney W. Grimes *exflagsp |= MNT_EXKERB; 15838fae3551SRodney W. Grimes opt_flags |= OP_KERB; 15848fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "mask") || 15858fae3551SRodney W. Grimes !strcmp(cpopt, "m"))) { 15868fae3551SRodney W. Grimes if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { 158774853402SPhilippe Charnier syslog(LOG_ERR, "bad mask: %s", cpoptarg); 15888fae3551SRodney W. Grimes return (1); 15898fae3551SRodney W. Grimes } 15908fae3551SRodney W. Grimes usedarg++; 15918fae3551SRodney W. Grimes opt_flags |= OP_MASK; 15928fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "network") || 15938fae3551SRodney W. Grimes !strcmp(cpopt, "n"))) { 15948360efbdSAlfred Perlstein if (strchr(cpoptarg, '/') != NULL) { 15958360efbdSAlfred Perlstein if (debug) 15968360efbdSAlfred Perlstein fprintf(stderr, "setting OP_MASKLEN\n"); 15978360efbdSAlfred Perlstein opt_flags |= OP_MASKLEN; 15988360efbdSAlfred Perlstein } 15998fae3551SRodney W. Grimes if (grp->gr_type != GT_NULL) { 160074853402SPhilippe Charnier syslog(LOG_ERR, "network/host conflict"); 16018fae3551SRodney W. Grimes return (1); 16028fae3551SRodney W. Grimes } else if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 0)) { 160374853402SPhilippe Charnier syslog(LOG_ERR, "bad net: %s", cpoptarg); 16048fae3551SRodney W. Grimes return (1); 16058fae3551SRodney W. Grimes } 16068fae3551SRodney W. Grimes grp->gr_type = GT_NET; 16078fae3551SRodney W. Grimes *has_hostp = 1; 16088fae3551SRodney W. Grimes usedarg++; 16098fae3551SRodney W. Grimes opt_flags |= OP_NET; 16108fae3551SRodney W. Grimes } else if (!strcmp(cpopt, "alldirs")) { 16118fae3551SRodney W. Grimes opt_flags |= OP_ALLDIRS; 1612cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "public")) { 1613cb3923e0SDoug Rabson *exflagsp |= MNT_EXPUBLIC; 1614cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "webnfs")) { 1615cb3923e0SDoug Rabson *exflagsp |= (MNT_EXPUBLIC|MNT_EXRDONLY|MNT_EXPORTANON); 1616cb3923e0SDoug Rabson opt_flags |= OP_MAPALL; 1617cb3923e0SDoug Rabson } else if (cpoptarg && !strcmp(cpopt, "index")) { 1618cb3923e0SDoug Rabson ep->ex_indexfile = strdup(cpoptarg); 16198fae3551SRodney W. Grimes } else { 162074853402SPhilippe Charnier syslog(LOG_ERR, "bad opt %s", cpopt); 16218fae3551SRodney W. Grimes return (1); 16228fae3551SRodney W. Grimes } 16238fae3551SRodney W. Grimes if (usedarg >= 0) { 16248fae3551SRodney W. Grimes *endcp = savedc2; 16258fae3551SRodney W. Grimes **endcpp = savedc; 16268fae3551SRodney W. Grimes if (usedarg > 0) { 16278fae3551SRodney W. Grimes *cpp = cp; 16288fae3551SRodney W. Grimes *endcpp = endcp; 16298fae3551SRodney W. Grimes } 16308fae3551SRodney W. Grimes return (0); 16318fae3551SRodney W. Grimes } 16328fae3551SRodney W. Grimes cpopt = cpoptend; 16338fae3551SRodney W. Grimes } 16348fae3551SRodney W. Grimes **endcpp = savedc; 16358fae3551SRodney W. Grimes return (0); 16368fae3551SRodney W. Grimes } 16378fae3551SRodney W. Grimes 16388fae3551SRodney W. Grimes /* 16398fae3551SRodney W. Grimes * Translate a character string to the corresponding list of network 16408fae3551SRodney W. Grimes * addresses for a hostname. 16418fae3551SRodney W. Grimes */ 16428fae3551SRodney W. Grimes int 16438b5a6d67SBill Paul get_host(cp, grp, tgrp) 16448fae3551SRodney W. Grimes char *cp; 16458fae3551SRodney W. Grimes struct grouplist *grp; 16468b5a6d67SBill Paul struct grouplist *tgrp; 16478fae3551SRodney W. Grimes { 16488b5a6d67SBill Paul struct grouplist *checkgrp; 164901709abfSIan Dowse struct addrinfo *ai, *tai, hints; 16508360efbdSAlfred Perlstein int ecode; 16518360efbdSAlfred Perlstein char host[NI_MAXHOST]; 16528fae3551SRodney W. Grimes 16538360efbdSAlfred Perlstein if (grp->gr_type != GT_NULL) { 16548360efbdSAlfred Perlstein syslog(LOG_ERR, "Bad netgroup type for ip host %s", cp); 16558fae3551SRodney W. Grimes return (1); 16568fae3551SRodney W. Grimes } 16578360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 16588360efbdSAlfred Perlstein hints.ai_flags = AI_CANONNAME; 16598360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_UDP; 16608360efbdSAlfred Perlstein ecode = getaddrinfo(cp, NULL, &hints, &ai); 16618360efbdSAlfred Perlstein if (ecode != 0) { 166201709abfSIan Dowse syslog(LOG_ERR,"can't get address info for host %s", cp); 16638360efbdSAlfred Perlstein return 1; 16648fae3551SRodney W. Grimes } 16658360efbdSAlfred Perlstein grp->gr_ptr.gt_addrinfo = ai; 16668360efbdSAlfred Perlstein while (ai != NULL) { 16678360efbdSAlfred Perlstein if (ai->ai_canonname == NULL) { 16688360efbdSAlfred Perlstein if (getnameinfo(ai->ai_addr, ai->ai_addrlen, host, 16698360efbdSAlfred Perlstein sizeof host, NULL, 0, ninumeric) != 0) 16708360efbdSAlfred Perlstein strlcpy(host, "?", sizeof(host)); 16718360efbdSAlfred Perlstein ai->ai_canonname = strdup(host); 16728360efbdSAlfred Perlstein ai->ai_flags |= AI_CANONNAME; 16736d359f31SIan Dowse } 16748fae3551SRodney W. Grimes if (debug) 167501709abfSIan Dowse fprintf(stderr, "got host %s\n", ai->ai_canonname); 167601709abfSIan Dowse /* 167701709abfSIan Dowse * Sanity check: make sure we don't already have an entry 167801709abfSIan Dowse * for this host in the grouplist. 167901709abfSIan Dowse */ 168001709abfSIan Dowse for (checkgrp = tgrp; checkgrp != NULL; 168101709abfSIan Dowse checkgrp = checkgrp->gr_next) { 168201709abfSIan Dowse if (checkgrp->gr_type != GT_HOST) 168301709abfSIan Dowse continue; 168401709abfSIan Dowse for (tai = checkgrp->gr_ptr.gt_addrinfo; tai != NULL; 168501709abfSIan Dowse tai = tai->ai_next) { 168601709abfSIan Dowse if (sacmp(tai->ai_addr, ai->ai_addr) != 0) 168701709abfSIan Dowse continue; 168801709abfSIan Dowse if (debug) 168901709abfSIan Dowse fprintf(stderr, 169001709abfSIan Dowse "ignoring duplicate host %s\n", 169101709abfSIan Dowse ai->ai_canonname); 169201709abfSIan Dowse grp->gr_type = GT_IGNORE; 169301709abfSIan Dowse return (0); 169401709abfSIan Dowse } 169501709abfSIan Dowse } 16968360efbdSAlfred Perlstein ai = ai->ai_next; 16978360efbdSAlfred Perlstein } 169801709abfSIan Dowse grp->gr_type = GT_HOST; 16998fae3551SRodney W. Grimes return (0); 17008fae3551SRodney W. Grimes } 17018fae3551SRodney W. Grimes 17028fae3551SRodney W. Grimes /* 17038fae3551SRodney W. Grimes * Free up an exports list component 17048fae3551SRodney W. Grimes */ 17058fae3551SRodney W. Grimes void 17068fae3551SRodney W. Grimes free_exp(ep) 17078fae3551SRodney W. Grimes struct exportlist *ep; 17088fae3551SRodney W. Grimes { 17098fae3551SRodney W. Grimes 17108fae3551SRodney W. Grimes if (ep->ex_defdir) { 17118fae3551SRodney W. Grimes free_host(ep->ex_defdir->dp_hosts); 17128fae3551SRodney W. Grimes free((caddr_t)ep->ex_defdir); 17138fae3551SRodney W. Grimes } 17148fae3551SRodney W. Grimes if (ep->ex_fsdir) 17158fae3551SRodney W. Grimes free(ep->ex_fsdir); 1716cb3923e0SDoug Rabson if (ep->ex_indexfile) 1717cb3923e0SDoug Rabson free(ep->ex_indexfile); 17188fae3551SRodney W. Grimes free_dir(ep->ex_dirl); 17198fae3551SRodney W. Grimes free((caddr_t)ep); 17208fae3551SRodney W. Grimes } 17218fae3551SRodney W. Grimes 17228fae3551SRodney W. Grimes /* 17238fae3551SRodney W. Grimes * Free hosts. 17248fae3551SRodney W. Grimes */ 17258fae3551SRodney W. Grimes void 17268fae3551SRodney W. Grimes free_host(hp) 17278fae3551SRodney W. Grimes struct hostlist *hp; 17288fae3551SRodney W. Grimes { 17298fae3551SRodney W. Grimes struct hostlist *hp2; 17308fae3551SRodney W. Grimes 17318fae3551SRodney W. Grimes while (hp) { 17328fae3551SRodney W. Grimes hp2 = hp; 17338fae3551SRodney W. Grimes hp = hp->ht_next; 17348fae3551SRodney W. Grimes free((caddr_t)hp2); 17358fae3551SRodney W. Grimes } 17368fae3551SRodney W. Grimes } 17378fae3551SRodney W. Grimes 17388fae3551SRodney W. Grimes struct hostlist * 17398fae3551SRodney W. Grimes get_ht() 17408fae3551SRodney W. Grimes { 17418fae3551SRodney W. Grimes struct hostlist *hp; 17428fae3551SRodney W. Grimes 17438fae3551SRodney W. Grimes hp = (struct hostlist *)malloc(sizeof (struct hostlist)); 17448fae3551SRodney W. Grimes if (hp == (struct hostlist *)NULL) 17458fae3551SRodney W. Grimes out_of_mem(); 17468fae3551SRodney W. Grimes hp->ht_next = (struct hostlist *)NULL; 1747a62dc406SDoug Rabson hp->ht_flag = 0; 17488fae3551SRodney W. Grimes return (hp); 17498fae3551SRodney W. Grimes } 17508fae3551SRodney W. Grimes 17518fae3551SRodney W. Grimes /* 17528fae3551SRodney W. Grimes * Out of memory, fatal 17538fae3551SRodney W. Grimes */ 17548fae3551SRodney W. Grimes void 17558fae3551SRodney W. Grimes out_of_mem() 17568fae3551SRodney W. Grimes { 17578fae3551SRodney W. Grimes 175874853402SPhilippe Charnier syslog(LOG_ERR, "out of memory"); 17598fae3551SRodney W. Grimes exit(2); 17608fae3551SRodney W. Grimes } 17618fae3551SRodney W. Grimes 17628fae3551SRodney W. Grimes /* 17638fae3551SRodney W. Grimes * Do the mount syscall with the update flag to push the export info into 17648fae3551SRodney W. Grimes * the kernel. 17658fae3551SRodney W. Grimes */ 17668fae3551SRodney W. Grimes int 17678fae3551SRodney W. Grimes do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb) 17688fae3551SRodney W. Grimes struct exportlist *ep; 17698fae3551SRodney W. Grimes struct grouplist *grp; 17708fae3551SRodney W. Grimes int exflags; 1771c0511d3bSBrian Feldman struct xucred *anoncrp; 17728fae3551SRodney W. Grimes char *dirp; 17738fae3551SRodney W. Grimes int dirplen; 17748fae3551SRodney W. Grimes struct statfs *fsb; 17758fae3551SRodney W. Grimes { 17768360efbdSAlfred Perlstein struct sockaddr_storage ss; 17778360efbdSAlfred Perlstein struct addrinfo *ai; 17788360efbdSAlfred Perlstein char *cp = NULL; 17798fae3551SRodney W. Grimes int done; 17808fae3551SRodney W. Grimes char savedc = '\0'; 17818fae3551SRodney W. Grimes union { 17828fae3551SRodney W. Grimes struct ufs_args ua; 17838fae3551SRodney W. Grimes struct iso_args ia; 17848fae3551SRodney W. Grimes struct mfs_args ma; 1785a62dc406SDoug Rabson #ifdef __NetBSD__ 1786a62dc406SDoug Rabson struct msdosfs_args da; 17878360efbdSAlfred Perlstein struct adosfs_args aa; 1788a62dc406SDoug Rabson #endif 17899300c696SSemen Ustimenko struct ntfs_args na; 17908fae3551SRodney W. Grimes } args; 17918fae3551SRodney W. Grimes 17928fae3551SRodney W. Grimes args.ua.fspec = 0; 17938fae3551SRodney W. Grimes args.ua.export.ex_flags = exflags; 17948fae3551SRodney W. Grimes args.ua.export.ex_anon = *anoncrp; 1795cb3923e0SDoug Rabson args.ua.export.ex_indexfile = ep->ex_indexfile; 17966d359f31SIan Dowse if (grp->gr_type == GT_HOST) 17978360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 17986d359f31SIan Dowse else 17996d359f31SIan Dowse ai = NULL; 18008fae3551SRodney W. Grimes done = FALSE; 18018fae3551SRodney W. Grimes while (!done) { 18028fae3551SRodney W. Grimes switch (grp->gr_type) { 18038fae3551SRodney W. Grimes case GT_HOST: 18046d359f31SIan Dowse if (ai->ai_addr->sa_family == AF_INET6 && have_v6 == 0) 18058360efbdSAlfred Perlstein goto skip; 18066d359f31SIan Dowse args.ua.export.ex_addr = ai->ai_addr; 18076d359f31SIan Dowse args.ua.export.ex_addrlen = ai->ai_addrlen; 18088fae3551SRodney W. Grimes args.ua.export.ex_masklen = 0; 18098fae3551SRodney W. Grimes break; 18108fae3551SRodney W. Grimes case GT_NET: 18118360efbdSAlfred Perlstein args.ua.export.ex_addr = (struct sockaddr *) 18128360efbdSAlfred Perlstein &grp->gr_ptr.gt_net.nt_net; 18138360efbdSAlfred Perlstein if (args.ua.export.ex_addr->sa_family == AF_INET6 && 18148360efbdSAlfred Perlstein have_v6 == 0) 18158360efbdSAlfred Perlstein goto skip; 18168360efbdSAlfred Perlstein args.ua.export.ex_addrlen = 18178360efbdSAlfred Perlstein args.ua.export.ex_addr->sa_len; 18188360efbdSAlfred Perlstein memset(&ss, 0, sizeof ss); 18198360efbdSAlfred Perlstein ss.ss_family = args.ua.export.ex_addr->sa_family; 18208360efbdSAlfred Perlstein ss.ss_len = args.ua.export.ex_addr->sa_len; 18218360efbdSAlfred Perlstein if (allones(&ss, grp->gr_ptr.gt_net.nt_mask) != 0) { 18228360efbdSAlfred Perlstein syslog(LOG_ERR, "Bad network flag"); 18238360efbdSAlfred Perlstein if (cp) 18248360efbdSAlfred Perlstein *cp = savedc; 18258360efbdSAlfred Perlstein return (1); 18268fae3551SRodney W. Grimes } 18278360efbdSAlfred Perlstein args.ua.export.ex_mask = (struct sockaddr *)&ss; 18288360efbdSAlfred Perlstein args.ua.export.ex_masklen = ss.ss_len; 18298fae3551SRodney W. Grimes break; 18306d359f31SIan Dowse case GT_DEFAULT: 18316d359f31SIan Dowse args.ua.export.ex_addr = NULL; 18326d359f31SIan Dowse args.ua.export.ex_addrlen = 0; 18336d359f31SIan Dowse args.ua.export.ex_mask = NULL; 18346d359f31SIan Dowse args.ua.export.ex_masklen = 0; 18356d359f31SIan Dowse break; 18368b5a6d67SBill Paul case GT_IGNORE: 18378b5a6d67SBill Paul return(0); 18388b5a6d67SBill Paul break; 18398fae3551SRodney W. Grimes default: 184074853402SPhilippe Charnier syslog(LOG_ERR, "bad grouptype"); 18418fae3551SRodney W. Grimes if (cp) 18428fae3551SRodney W. Grimes *cp = savedc; 18438fae3551SRodney W. Grimes return (1); 18448fae3551SRodney W. Grimes }; 18458fae3551SRodney W. Grimes 18468fae3551SRodney W. Grimes /* 18478fae3551SRodney W. Grimes * XXX: 18488fae3551SRodney W. Grimes * Maybe I should just use the fsb->f_mntonname path instead 18498fae3551SRodney W. Grimes * of looping back up the dirp to the mount point?? 18508fae3551SRodney W. Grimes * Also, needs to know how to export all types of local 185187564113SPeter Wemm * exportable file systems and not just "ufs". 18528fae3551SRodney W. Grimes */ 1853a62dc406SDoug Rabson while (mount(fsb->f_fstypename, dirp, 18548fae3551SRodney W. Grimes fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) { 18558fae3551SRodney W. Grimes if (cp) 18568fae3551SRodney W. Grimes *cp-- = savedc; 18578fae3551SRodney W. Grimes else 18588fae3551SRodney W. Grimes cp = dirp + dirplen - 1; 18598fae3551SRodney W. Grimes if (errno == EPERM) { 186001709abfSIan Dowse if (debug) 186101709abfSIan Dowse warnx("can't change attributes for %s", 186201709abfSIan Dowse dirp); 18638fae3551SRodney W. Grimes syslog(LOG_ERR, 186474853402SPhilippe Charnier "can't change attributes for %s", dirp); 18658fae3551SRodney W. Grimes return (1); 18668fae3551SRodney W. Grimes } 18678fae3551SRodney W. Grimes if (opt_flags & OP_ALLDIRS) { 186874853402SPhilippe Charnier syslog(LOG_ERR, "could not remount %s: %m", 18693980ac4fSGarrett Wollman dirp); 18708fae3551SRodney W. Grimes return (1); 18718fae3551SRodney W. Grimes } 18728fae3551SRodney W. Grimes /* back up over the last component */ 18738fae3551SRodney W. Grimes while (*cp == '/' && cp > dirp) 18748fae3551SRodney W. Grimes cp--; 18758fae3551SRodney W. Grimes while (*(cp - 1) != '/' && cp > dirp) 18768fae3551SRodney W. Grimes cp--; 18778fae3551SRodney W. Grimes if (cp == dirp) { 18788fae3551SRodney W. Grimes if (debug) 187974853402SPhilippe Charnier warnx("mnt unsucc"); 188074853402SPhilippe Charnier syslog(LOG_ERR, "can't export %s", dirp); 18818fae3551SRodney W. Grimes return (1); 18828fae3551SRodney W. Grimes } 18838fae3551SRodney W. Grimes savedc = *cp; 18848fae3551SRodney W. Grimes *cp = '\0'; 18858fae3551SRodney W. Grimes } 18868360efbdSAlfred Perlstein skip: 18876d359f31SIan Dowse if (ai != NULL) 18888360efbdSAlfred Perlstein ai = ai->ai_next; 18898360efbdSAlfred Perlstein if (ai == NULL) 18908fae3551SRodney W. Grimes done = TRUE; 18918fae3551SRodney W. Grimes } 18928fae3551SRodney W. Grimes if (cp) 18938fae3551SRodney W. Grimes *cp = savedc; 18948fae3551SRodney W. Grimes return (0); 18958fae3551SRodney W. Grimes } 18968fae3551SRodney W. Grimes 18978fae3551SRodney W. Grimes /* 18988fae3551SRodney W. Grimes * Translate a net address. 18998fae3551SRodney W. Grimes */ 19008fae3551SRodney W. Grimes int 19018fae3551SRodney W. Grimes get_net(cp, net, maskflg) 19028fae3551SRodney W. Grimes char *cp; 19038fae3551SRodney W. Grimes struct netmsk *net; 19048fae3551SRodney W. Grimes int maskflg; 19058fae3551SRodney W. Grimes { 19068fae3551SRodney W. Grimes struct netent *np; 19078360efbdSAlfred Perlstein char *name, *p, *prefp; 19088360efbdSAlfred Perlstein struct sockaddr_in sin, *sinp; 19098360efbdSAlfred Perlstein struct sockaddr *sa; 19108360efbdSAlfred Perlstein struct addrinfo hints, *ai = NULL; 19118360efbdSAlfred Perlstein char netname[NI_MAXHOST]; 19128360efbdSAlfred Perlstein long preflen; 19138360efbdSAlfred Perlstein int ecode; 19148fae3551SRodney W. Grimes 191501709abfSIan Dowse p = prefp = NULL; 19168360efbdSAlfred Perlstein if ((opt_flags & OP_MASKLEN) && !maskflg) { 19178360efbdSAlfred Perlstein p = strchr(cp, '/'); 19188360efbdSAlfred Perlstein *p = '\0'; 19198360efbdSAlfred Perlstein prefp = p + 1; 19208360efbdSAlfred Perlstein } 19218360efbdSAlfred Perlstein 19228360efbdSAlfred Perlstein if ((np = getnetbyname(cp)) != NULL) { 19238360efbdSAlfred Perlstein sin.sin_family = AF_INET; 19248360efbdSAlfred Perlstein sin.sin_len = sizeof sin; 19258360efbdSAlfred Perlstein sin.sin_addr = inet_makeaddr(np->n_net, 0); 19268360efbdSAlfred Perlstein sa = (struct sockaddr *)&sin; 19278360efbdSAlfred Perlstein } else if (isdigit(*cp)) { 19288360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 19298360efbdSAlfred Perlstein hints.ai_family = AF_UNSPEC; 19308360efbdSAlfred Perlstein hints.ai_flags = AI_NUMERICHOST; 19318360efbdSAlfred Perlstein if (getaddrinfo(cp, NULL, &hints, &ai) != 0) { 19328fae3551SRodney W. Grimes /* 19338360efbdSAlfred Perlstein * If getaddrinfo() failed, try the inet4 network 19348360efbdSAlfred Perlstein * notation with less than 3 dots. 19358fae3551SRodney W. Grimes */ 19368360efbdSAlfred Perlstein sin.sin_family = AF_INET; 19378360efbdSAlfred Perlstein sin.sin_len = sizeof sin; 19388360efbdSAlfred Perlstein sin.sin_addr = inet_makeaddr(inet_network(cp),0); 19398360efbdSAlfred Perlstein if (debug) 19408360efbdSAlfred Perlstein fprintf(stderr, "get_net: v4 addr %x\n", 19418360efbdSAlfred Perlstein sin.sin_addr.s_addr); 19428360efbdSAlfred Perlstein sa = (struct sockaddr *)&sin; 19438fae3551SRodney W. Grimes } else 19448360efbdSAlfred Perlstein sa = ai->ai_addr; 19458360efbdSAlfred Perlstein } else if (isxdigit(*cp) || *cp == ':') { 19468360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 19478360efbdSAlfred Perlstein hints.ai_family = AF_UNSPEC; 19488360efbdSAlfred Perlstein hints.ai_flags = AI_NUMERICHOST; 19498360efbdSAlfred Perlstein if (getaddrinfo(cp, NULL, &hints, &ai) == 0) 19508360efbdSAlfred Perlstein sa = ai->ai_addr; 19518360efbdSAlfred Perlstein else 19528360efbdSAlfred Perlstein goto fail; 19538360efbdSAlfred Perlstein } else 19548360efbdSAlfred Perlstein goto fail; 19558360efbdSAlfred Perlstein 19568360efbdSAlfred Perlstein ecode = getnameinfo(sa, sa->sa_len, netname, sizeof netname, 19578360efbdSAlfred Perlstein NULL, 0, ninumeric); 19588360efbdSAlfred Perlstein if (ecode != 0) 19598360efbdSAlfred Perlstein goto fail; 19600f4b7baaSPaul Traina 19618fae3551SRodney W. Grimes if (maskflg) 19628360efbdSAlfred Perlstein net->nt_mask = countones(sa); 19638fae3551SRodney W. Grimes else { 19648360efbdSAlfred Perlstein if (opt_flags & OP_MASKLEN) { 19658360efbdSAlfred Perlstein preflen = strtol(prefp, NULL, 10); 19668360efbdSAlfred Perlstein if (preflen == LONG_MIN && errno == ERANGE) 19678360efbdSAlfred Perlstein goto fail; 19688360efbdSAlfred Perlstein net->nt_mask = (int)preflen; 19698360efbdSAlfred Perlstein *p = '/'; 19708360efbdSAlfred Perlstein } 19718360efbdSAlfred Perlstein 19728fae3551SRodney W. Grimes if (np) 19738fae3551SRodney W. Grimes name = np->n_name; 19748360efbdSAlfred Perlstein else { 19758360efbdSAlfred Perlstein if (getnameinfo(sa, sa->sa_len, netname, sizeof netname, 19768360efbdSAlfred Perlstein NULL, 0, ninumeric) != 0) 19778360efbdSAlfred Perlstein strlcpy(netname, "?", sizeof(netname)); 19788360efbdSAlfred Perlstein name = netname; 19798fae3551SRodney W. Grimes } 19808360efbdSAlfred Perlstein net->nt_name = strdup(name); 19818360efbdSAlfred Perlstein memcpy(&net->nt_net, sa, sa->sa_len); 19828360efbdSAlfred Perlstein } 19838360efbdSAlfred Perlstein 19848360efbdSAlfred Perlstein if (!maskflg && sa->sa_family == AF_INET && 19858360efbdSAlfred Perlstein !(opt_flags & (OP_MASK|OP_MASKLEN))) { 19868360efbdSAlfred Perlstein sinp = (struct sockaddr_in *)sa; 19878360efbdSAlfred Perlstein if (IN_CLASSA(sinp->sin_addr.s_addr)) 19888360efbdSAlfred Perlstein net->nt_mask = 8; 19898360efbdSAlfred Perlstein else if (IN_CLASSB(sinp->sin_addr.s_addr)) 19908360efbdSAlfred Perlstein net->nt_mask = 16; 19918360efbdSAlfred Perlstein else if (IN_CLASSC(sinp->sin_addr.s_addr)) 19928360efbdSAlfred Perlstein net->nt_mask = 24; 19938360efbdSAlfred Perlstein else if (IN_CLASSD(sinp->sin_addr.s_addr)) 19948360efbdSAlfred Perlstein net->nt_mask = 28; 19958360efbdSAlfred Perlstein else 19968360efbdSAlfred Perlstein net->nt_mask = 32; /* XXX */ 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; 20408fae3551SRodney W. Grimes int 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 { 20498fae3551SRodney W. Grimes if (fgets(p, LINESIZ - totlen, exp_file) == NULL) 20508fae3551SRodney W. Grimes return (0); 20518fae3551SRodney W. Grimes len = strlen(p); 20528fae3551SRodney W. Grimes cp = p + len - 1; 20538fae3551SRodney W. Grimes cont_line = 0; 20548fae3551SRodney W. Grimes while (cp >= p && 20558fae3551SRodney W. Grimes (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '\\')) { 20568fae3551SRodney W. Grimes if (*cp == '\\') 20578fae3551SRodney W. Grimes cont_line = 1; 20588fae3551SRodney W. Grimes cp--; 20598fae3551SRodney W. Grimes len--; 20608fae3551SRodney W. Grimes } 20618fae3551SRodney W. Grimes *++cp = '\0'; 20628fae3551SRodney W. Grimes if (len > 0) { 20638fae3551SRodney W. Grimes totlen += len; 20648fae3551SRodney W. Grimes if (totlen >= LINESIZ) { 206574853402SPhilippe Charnier syslog(LOG_ERR, "exports line too long"); 20668fae3551SRodney W. Grimes exit(2); 20678fae3551SRodney W. Grimes } 20688fae3551SRodney W. Grimes p = cp; 20698fae3551SRodney W. Grimes } 20708fae3551SRodney W. Grimes } while (totlen == 0 || cont_line); 20718fae3551SRodney W. Grimes return (1); 20728fae3551SRodney W. Grimes } 20738fae3551SRodney W. Grimes 20748fae3551SRodney W. Grimes /* 20758fae3551SRodney W. Grimes * Parse a description of a credential. 20768fae3551SRodney W. Grimes */ 20778fae3551SRodney W. Grimes void 20788fae3551SRodney W. Grimes parsecred(namelist, cr) 20798fae3551SRodney W. Grimes char *namelist; 2080c0511d3bSBrian Feldman struct xucred *cr; 20818fae3551SRodney W. Grimes { 20828fae3551SRodney W. Grimes char *name; 20838fae3551SRodney W. Grimes int cnt; 20848fae3551SRodney W. Grimes char *names; 20858fae3551SRodney W. Grimes struct passwd *pw; 20868fae3551SRodney W. Grimes struct group *gr; 20878fae3551SRodney W. Grimes int ngroups, groups[NGROUPS + 1]; 20888fae3551SRodney W. Grimes 20898fae3551SRodney W. Grimes /* 209074853402SPhilippe Charnier * Set up the unprivileged user. 20918fae3551SRodney W. Grimes */ 20928fae3551SRodney W. Grimes cr->cr_uid = -2; 20938fae3551SRodney W. Grimes cr->cr_groups[0] = -2; 20948fae3551SRodney W. Grimes cr->cr_ngroups = 1; 20958fae3551SRodney W. Grimes /* 20968fae3551SRodney W. Grimes * Get the user's password table entry. 20978fae3551SRodney W. Grimes */ 20988fae3551SRodney W. Grimes names = strsep(&namelist, " \t\n"); 20998fae3551SRodney W. Grimes name = strsep(&names, ":"); 21008fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') 21018fae3551SRodney W. Grimes pw = getpwuid(atoi(name)); 21028fae3551SRodney W. Grimes else 21038fae3551SRodney W. Grimes pw = getpwnam(name); 21048fae3551SRodney W. Grimes /* 21058fae3551SRodney W. Grimes * Credentials specified as those of a user. 21068fae3551SRodney W. Grimes */ 21078fae3551SRodney W. Grimes if (names == NULL) { 21088fae3551SRodney W. Grimes if (pw == NULL) { 210974853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 21108fae3551SRodney W. Grimes return; 21118fae3551SRodney W. Grimes } 21128fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 21138fae3551SRodney W. Grimes ngroups = NGROUPS + 1; 21148fae3551SRodney W. Grimes if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) 211574853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 21168fae3551SRodney W. Grimes /* 21178fae3551SRodney W. Grimes * Convert from int's to gid_t's and compress out duplicate 21188fae3551SRodney W. Grimes */ 21198fae3551SRodney W. Grimes cr->cr_ngroups = ngroups - 1; 21208fae3551SRodney W. Grimes cr->cr_groups[0] = groups[0]; 21218fae3551SRodney W. Grimes for (cnt = 2; cnt < ngroups; cnt++) 21228fae3551SRodney W. Grimes cr->cr_groups[cnt - 1] = groups[cnt]; 21238fae3551SRodney W. Grimes return; 21248fae3551SRodney W. Grimes } 21258fae3551SRodney W. Grimes /* 21268fae3551SRodney W. Grimes * Explicit credential specified as a colon separated list: 21278fae3551SRodney W. Grimes * uid:gid:gid:... 21288fae3551SRodney W. Grimes */ 21298fae3551SRodney W. Grimes if (pw != NULL) 21308fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 21318fae3551SRodney W. Grimes else if (isdigit(*name) || *name == '-') 21328fae3551SRodney W. Grimes cr->cr_uid = atoi(name); 21338fae3551SRodney W. Grimes else { 213474853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 21358fae3551SRodney W. Grimes return; 21368fae3551SRodney W. Grimes } 21378fae3551SRodney W. Grimes cr->cr_ngroups = 0; 21388fae3551SRodney W. Grimes while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { 21398fae3551SRodney W. Grimes name = strsep(&names, ":"); 21408fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') { 21418fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = atoi(name); 21428fae3551SRodney W. Grimes } else { 21438fae3551SRodney W. Grimes if ((gr = getgrnam(name)) == NULL) { 214474853402SPhilippe Charnier syslog(LOG_ERR, "unknown group: %s", name); 21458fae3551SRodney W. Grimes continue; 21468fae3551SRodney W. Grimes } 21478fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; 21488fae3551SRodney W. Grimes } 21498fae3551SRodney W. Grimes } 21508fae3551SRodney W. Grimes if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) 215174853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 21528fae3551SRodney W. Grimes } 21538fae3551SRodney W. Grimes 21548fae3551SRodney W. Grimes #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 21558fae3551SRodney W. Grimes /* 21568fae3551SRodney W. Grimes * Routines that maintain the remote mounttab 21578fae3551SRodney W. Grimes */ 21588fae3551SRodney W. Grimes void 21598fae3551SRodney W. Grimes get_mountlist() 21608fae3551SRodney W. Grimes { 21618fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 216287564113SPeter Wemm char *host, *dirp, *cp; 21638fae3551SRodney W. Grimes char str[STRSIZ]; 21648fae3551SRodney W. Grimes FILE *mlfile; 21658fae3551SRodney W. Grimes 21668fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) { 216739539916SBill Fumerola if (errno == ENOENT) 216839539916SBill Fumerola return; 216939539916SBill Fumerola else { 217074853402SPhilippe Charnier syslog(LOG_ERR, "can't open %s", _PATH_RMOUNTLIST); 21718fae3551SRodney W. Grimes return; 21728fae3551SRodney W. Grimes } 217339539916SBill Fumerola } 21748fae3551SRodney W. Grimes mlpp = &mlhead; 21758fae3551SRodney W. Grimes while (fgets(str, STRSIZ, mlfile) != NULL) { 217687564113SPeter Wemm cp = str; 217787564113SPeter Wemm host = strsep(&cp, " \t\n"); 217887564113SPeter Wemm dirp = strsep(&cp, " \t\n"); 217987564113SPeter Wemm if (host == NULL || dirp == NULL) 21808fae3551SRodney W. Grimes continue; 21818fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 218274853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 218374853402SPhilippe Charnier out_of_mem(); 218487564113SPeter Wemm strncpy(mlp->ml_host, host, RPCMNT_NAMELEN); 218587564113SPeter Wemm mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 218687564113SPeter Wemm strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 218787564113SPeter Wemm mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 21888fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 21898fae3551SRodney W. Grimes *mlpp = mlp; 21908fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 21918fae3551SRodney W. Grimes } 21928fae3551SRodney W. Grimes fclose(mlfile); 21938fae3551SRodney W. Grimes } 21948fae3551SRodney W. Grimes 219501709abfSIan Dowse void 219601709abfSIan Dowse del_mlist(char *hostp, char *dirp) 21978fae3551SRodney W. Grimes { 21988fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 21998fae3551SRodney W. Grimes struct mountlist *mlp2; 22008fae3551SRodney W. Grimes FILE *mlfile; 22018fae3551SRodney W. Grimes int fnd = 0; 22028fae3551SRodney W. Grimes 22038fae3551SRodney W. Grimes mlpp = &mlhead; 22048fae3551SRodney W. Grimes mlp = mlhead; 22058fae3551SRodney W. Grimes while (mlp) { 22068fae3551SRodney W. Grimes if (!strcmp(mlp->ml_host, hostp) && 22078fae3551SRodney W. Grimes (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 22088fae3551SRodney W. Grimes fnd = 1; 22098fae3551SRodney W. Grimes mlp2 = mlp; 22108fae3551SRodney W. Grimes *mlpp = mlp = mlp->ml_next; 22118fae3551SRodney W. Grimes free((caddr_t)mlp2); 22128fae3551SRodney W. Grimes } else { 22138fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 22148fae3551SRodney W. Grimes mlp = mlp->ml_next; 22158fae3551SRodney W. Grimes } 22168fae3551SRodney W. Grimes } 22178fae3551SRodney W. Grimes if (fnd) { 22188fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 221974853402SPhilippe Charnier syslog(LOG_ERR,"can't update %s", _PATH_RMOUNTLIST); 22208fae3551SRodney W. Grimes return; 22218fae3551SRodney W. Grimes } 22228fae3551SRodney W. Grimes mlp = mlhead; 22238fae3551SRodney W. Grimes while (mlp) { 22248fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 22258fae3551SRodney W. Grimes mlp = mlp->ml_next; 22268fae3551SRodney W. Grimes } 22278fae3551SRodney W. Grimes fclose(mlfile); 22288fae3551SRodney W. Grimes } 22298fae3551SRodney W. Grimes } 22308fae3551SRodney W. Grimes 22318fae3551SRodney W. Grimes void 22328fae3551SRodney W. Grimes add_mlist(hostp, dirp) 22338fae3551SRodney W. Grimes char *hostp, *dirp; 22348fae3551SRodney W. Grimes { 22358fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 22368fae3551SRodney W. Grimes FILE *mlfile; 22378fae3551SRodney W. Grimes 22388fae3551SRodney W. Grimes mlpp = &mlhead; 22398fae3551SRodney W. Grimes mlp = mlhead; 22408fae3551SRodney W. Grimes while (mlp) { 22418fae3551SRodney W. Grimes if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 22428fae3551SRodney W. Grimes return; 22438fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 22448fae3551SRodney W. Grimes mlp = mlp->ml_next; 22458fae3551SRodney W. Grimes } 22468fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 224774853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 224874853402SPhilippe Charnier out_of_mem(); 22498fae3551SRodney W. Grimes strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 22508fae3551SRodney W. Grimes mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 22518fae3551SRodney W. Grimes strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 22528fae3551SRodney W. Grimes mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 22538fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 22548fae3551SRodney W. Grimes *mlpp = mlp; 22558fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 225674853402SPhilippe Charnier syslog(LOG_ERR, "can't update %s", _PATH_RMOUNTLIST); 22578fae3551SRodney W. Grimes return; 22588fae3551SRodney W. Grimes } 22598fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 22608fae3551SRodney W. Grimes fclose(mlfile); 22618fae3551SRodney W. Grimes } 22628fae3551SRodney W. Grimes 22638fae3551SRodney W. Grimes /* 22648fae3551SRodney W. Grimes * Free up a group list. 22658fae3551SRodney W. Grimes */ 22668fae3551SRodney W. Grimes void 22678fae3551SRodney W. Grimes free_grp(grp) 22688fae3551SRodney W. Grimes struct grouplist *grp; 22698fae3551SRodney W. Grimes { 22708fae3551SRodney W. Grimes if (grp->gr_type == GT_HOST) { 22718360efbdSAlfred Perlstein if (grp->gr_ptr.gt_addrinfo != NULL) 22728360efbdSAlfred Perlstein freeaddrinfo(grp->gr_ptr.gt_addrinfo); 22738fae3551SRodney W. Grimes } else if (grp->gr_type == GT_NET) { 22748fae3551SRodney W. Grimes if (grp->gr_ptr.gt_net.nt_name) 22758fae3551SRodney W. Grimes free(grp->gr_ptr.gt_net.nt_name); 22768fae3551SRodney W. Grimes } 22778fae3551SRodney W. Grimes free((caddr_t)grp); 22788fae3551SRodney W. Grimes } 22798fae3551SRodney W. Grimes 22808fae3551SRodney W. Grimes #ifdef DEBUG 22818fae3551SRodney W. Grimes void 22828fae3551SRodney W. Grimes SYSLOG(int pri, const char *fmt, ...) 22838fae3551SRodney W. Grimes { 22848fae3551SRodney W. Grimes va_list ap; 22858fae3551SRodney W. Grimes 22868fae3551SRodney W. Grimes va_start(ap, fmt); 22878fae3551SRodney W. Grimes vfprintf(stderr, fmt, ap); 22888fae3551SRodney W. Grimes va_end(ap); 22898fae3551SRodney W. Grimes } 22908fae3551SRodney W. Grimes #endif /* DEBUG */ 22918fae3551SRodney W. Grimes 22928fae3551SRodney W. Grimes /* 22938fae3551SRodney W. Grimes * Check options for consistency. 22948fae3551SRodney W. Grimes */ 22958fae3551SRodney W. Grimes int 22968fae3551SRodney W. Grimes check_options(dp) 22978fae3551SRodney W. Grimes struct dirlist *dp; 22988fae3551SRodney W. Grimes { 22998fae3551SRodney W. Grimes 23008fae3551SRodney W. Grimes if (dp == (struct dirlist *)NULL) 23018fae3551SRodney W. Grimes return (1); 23028fae3551SRodney W. Grimes if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL) || 23038fae3551SRodney W. Grimes (opt_flags & (OP_MAPROOT | OP_KERB)) == (OP_MAPROOT | OP_KERB) || 23048fae3551SRodney W. Grimes (opt_flags & (OP_MAPALL | OP_KERB)) == (OP_MAPALL | OP_KERB)) { 23058fae3551SRodney W. Grimes syslog(LOG_ERR, "-mapall, -maproot and -kerb mutually exclusive"); 23068fae3551SRodney W. Grimes return (1); 23078fae3551SRodney W. Grimes } 23088fae3551SRodney W. Grimes if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { 23098fae3551SRodney W. Grimes syslog(LOG_ERR, "-mask requires -net"); 23108fae3551SRodney W. Grimes return (1); 23118fae3551SRodney W. Grimes } 23128fae3551SRodney W. Grimes if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { 23136436fcb9SAlexander Langer syslog(LOG_ERR, "-alldirs has multiple directories"); 23148fae3551SRodney W. Grimes return (1); 23158fae3551SRodney W. Grimes } 23168fae3551SRodney W. Grimes return (0); 23178fae3551SRodney W. Grimes } 23188fae3551SRodney W. Grimes 23198fae3551SRodney W. Grimes /* 23208fae3551SRodney W. Grimes * Check an absolute directory path for any symbolic links. Return true 23218fae3551SRodney W. Grimes */ 23228fae3551SRodney W. Grimes int 23238fae3551SRodney W. Grimes check_dirpath(dirp) 23248fae3551SRodney W. Grimes char *dirp; 23258fae3551SRodney W. Grimes { 23268fae3551SRodney W. Grimes char *cp; 23278fae3551SRodney W. Grimes int ret = 1; 23288fae3551SRodney W. Grimes struct stat sb; 23298fae3551SRodney W. Grimes 23308fae3551SRodney W. Grimes cp = dirp + 1; 23318fae3551SRodney W. Grimes while (*cp && ret) { 23328fae3551SRodney W. Grimes if (*cp == '/') { 23338fae3551SRodney W. Grimes *cp = '\0'; 2334a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 23358fae3551SRodney W. Grimes ret = 0; 23368fae3551SRodney W. Grimes *cp = '/'; 23378fae3551SRodney W. Grimes } 23388fae3551SRodney W. Grimes cp++; 23398fae3551SRodney W. Grimes } 2340a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 23418fae3551SRodney W. Grimes ret = 0; 23428fae3551SRodney W. Grimes return (ret); 23438fae3551SRodney W. Grimes } 2344a62dc406SDoug Rabson 23458360efbdSAlfred Perlstein static int 23468360efbdSAlfred Perlstein netpartcmp(struct sockaddr *s1, struct sockaddr *s2, int bitlen) 23478360efbdSAlfred Perlstein { 23488360efbdSAlfred Perlstein void *src, *dst; 23498360efbdSAlfred Perlstein 23508360efbdSAlfred Perlstein if (s1->sa_family != s2->sa_family) 23518360efbdSAlfred Perlstein return 1; 23528360efbdSAlfred Perlstein 23538360efbdSAlfred Perlstein switch (s1->sa_family) { 23548360efbdSAlfred Perlstein case AF_INET: 23558360efbdSAlfred Perlstein src = &((struct sockaddr_in *)s1)->sin_addr; 23568360efbdSAlfred Perlstein dst = &((struct sockaddr_in *)s2)->sin_addr; 23578360efbdSAlfred Perlstein if (bitlen > sizeof(((struct sockaddr_in *)s1)->sin_addr) * 8) 23588360efbdSAlfred Perlstein return 1; 23598360efbdSAlfred Perlstein break; 23608360efbdSAlfred Perlstein case AF_INET6: 23618360efbdSAlfred Perlstein src = &((struct sockaddr_in6 *)s1)->sin6_addr; 23628360efbdSAlfred Perlstein dst = &((struct sockaddr_in6 *)s2)->sin6_addr; 23638360efbdSAlfred Perlstein if (((struct sockaddr_in6 *)s1)->sin6_scope_id != 23648360efbdSAlfred Perlstein ((struct sockaddr_in6 *)s2)->sin6_scope_id) 23658360efbdSAlfred Perlstein return 1; 23668360efbdSAlfred Perlstein if (bitlen > sizeof(((struct sockaddr_in6 *)s1)->sin6_addr) * 8) 23678360efbdSAlfred Perlstein return 1; 23688360efbdSAlfred Perlstein break; 23698360efbdSAlfred Perlstein default: 23708360efbdSAlfred Perlstein return 1; 23718360efbdSAlfred Perlstein } 23728360efbdSAlfred Perlstein 23738360efbdSAlfred Perlstein return bitcmp(src, dst, bitlen); 23748360efbdSAlfred Perlstein } 23758360efbdSAlfred Perlstein 23768360efbdSAlfred Perlstein static int 23778360efbdSAlfred Perlstein allones(struct sockaddr_storage *ssp, int bitlen) 23788360efbdSAlfred Perlstein { 23798360efbdSAlfred Perlstein u_int8_t *p; 23808360efbdSAlfred Perlstein int bytelen, bitsleft, i; 23818360efbdSAlfred Perlstein int zerolen; 23828360efbdSAlfred Perlstein 23838360efbdSAlfred Perlstein switch (ssp->ss_family) { 23848360efbdSAlfred Perlstein case AF_INET: 23858360efbdSAlfred Perlstein p = (u_int8_t *)&((struct sockaddr_in *)ssp)->sin_addr; 23868360efbdSAlfred Perlstein zerolen = sizeof (((struct sockaddr_in *)ssp)->sin_addr); 23878360efbdSAlfred Perlstein break; 23888360efbdSAlfred Perlstein case AF_INET6: 23898360efbdSAlfred Perlstein p = (u_int8_t *)&((struct sockaddr_in6 *)ssp)->sin6_addr; 23908360efbdSAlfred Perlstein zerolen = sizeof (((struct sockaddr_in6 *)ssp)->sin6_addr); 23918360efbdSAlfred Perlstein break; 23928360efbdSAlfred Perlstein default: 23938360efbdSAlfred Perlstein return -1; 23948360efbdSAlfred Perlstein } 23958360efbdSAlfred Perlstein 23968360efbdSAlfred Perlstein memset(p, 0, zerolen); 23978360efbdSAlfred Perlstein 23988360efbdSAlfred Perlstein bytelen = bitlen / 8; 23998360efbdSAlfred Perlstein bitsleft = bitlen % 8; 24008360efbdSAlfred Perlstein 24018360efbdSAlfred Perlstein if (bytelen > zerolen) 24028360efbdSAlfred Perlstein return -1; 24038360efbdSAlfred Perlstein 24048360efbdSAlfred Perlstein for (i = 0; i < bytelen; i++) 24058360efbdSAlfred Perlstein *p++ = 0xff; 24068360efbdSAlfred Perlstein 24078360efbdSAlfred Perlstein for (i = 0; i < bitsleft; i++) 24088360efbdSAlfred Perlstein *p |= 1 << (7 - i); 24098360efbdSAlfred Perlstein 24108360efbdSAlfred Perlstein return 0; 24118360efbdSAlfred Perlstein } 24128360efbdSAlfred Perlstein 24138360efbdSAlfred Perlstein static int 24148360efbdSAlfred Perlstein countones(struct sockaddr *sa) 24158360efbdSAlfred Perlstein { 24168360efbdSAlfred Perlstein void *mask; 24178360efbdSAlfred Perlstein int i, bits = 0, bytelen; 24188360efbdSAlfred Perlstein u_int8_t *p; 24198360efbdSAlfred Perlstein 24208360efbdSAlfred Perlstein switch (sa->sa_family) { 24218360efbdSAlfred Perlstein case AF_INET: 24228360efbdSAlfred Perlstein mask = (u_int8_t *)&((struct sockaddr_in *)sa)->sin_addr; 24238360efbdSAlfred Perlstein bytelen = 4; 24248360efbdSAlfred Perlstein break; 24258360efbdSAlfred Perlstein case AF_INET6: 24268360efbdSAlfred Perlstein mask = (u_int8_t *)&((struct sockaddr_in6 *)sa)->sin6_addr; 24278360efbdSAlfred Perlstein bytelen = 16; 24288360efbdSAlfred Perlstein break; 24298360efbdSAlfred Perlstein default: 24308360efbdSAlfred Perlstein return 0; 24318360efbdSAlfred Perlstein } 24328360efbdSAlfred Perlstein 24338360efbdSAlfred Perlstein p = mask; 24348360efbdSAlfred Perlstein 24358360efbdSAlfred Perlstein for (i = 0; i < bytelen; i++, p++) { 24368360efbdSAlfred Perlstein if (*p != 0xff) { 24378360efbdSAlfred Perlstein for (bits = 0; bits < 8; bits++) { 24388360efbdSAlfred Perlstein if (!(*p & (1 << (7 - bits)))) 24398360efbdSAlfred Perlstein break; 24408360efbdSAlfred Perlstein } 24418360efbdSAlfred Perlstein break; 24428360efbdSAlfred Perlstein } 24438360efbdSAlfred Perlstein } 24448360efbdSAlfred Perlstein 24458360efbdSAlfred Perlstein return (i * 8 + bits); 24468360efbdSAlfred Perlstein } 24478360efbdSAlfred Perlstein 24488360efbdSAlfred Perlstein static int 24498360efbdSAlfred Perlstein sacmp(struct sockaddr *sa1, struct sockaddr *sa2) 24508360efbdSAlfred Perlstein { 24518360efbdSAlfred Perlstein void *p1, *p2; 24528360efbdSAlfred Perlstein int len; 24538360efbdSAlfred Perlstein 24548360efbdSAlfred Perlstein if (sa1->sa_family != sa2->sa_family) 24558360efbdSAlfred Perlstein return 1; 24568360efbdSAlfred Perlstein 24578360efbdSAlfred Perlstein switch (sa1->sa_family) { 24588360efbdSAlfred Perlstein case AF_INET: 24598360efbdSAlfred Perlstein p1 = &((struct sockaddr_in *)sa1)->sin_addr; 24608360efbdSAlfred Perlstein p2 = &((struct sockaddr_in *)sa2)->sin_addr; 24618360efbdSAlfred Perlstein len = 4; 24628360efbdSAlfred Perlstein break; 24638360efbdSAlfred Perlstein case AF_INET6: 24648360efbdSAlfred Perlstein p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr; 24658360efbdSAlfred Perlstein p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr; 24668360efbdSAlfred Perlstein len = 16; 24678360efbdSAlfred Perlstein if (((struct sockaddr_in6 *)sa1)->sin6_scope_id != 24688360efbdSAlfred Perlstein ((struct sockaddr_in6 *)sa2)->sin6_scope_id) 24698360efbdSAlfred Perlstein return 1; 24708360efbdSAlfred Perlstein break; 24718360efbdSAlfred Perlstein default: 24728360efbdSAlfred Perlstein return 1; 24738360efbdSAlfred Perlstein } 24748360efbdSAlfred Perlstein 24758360efbdSAlfred Perlstein return memcmp(p1, p2, len); 24768360efbdSAlfred Perlstein } 24778360efbdSAlfred Perlstein 247869d65572SIan Dowse void 247969d65572SIan Dowse huphandler(int sig) 248069d65572SIan Dowse { 248169d65572SIan Dowse got_sighup = 1; 248269d65572SIan Dowse } 248369d65572SIan Dowse 24848360efbdSAlfred Perlstein void terminate(sig) 24858360efbdSAlfred Perlstein int sig; 24868360efbdSAlfred Perlstein { 24878360efbdSAlfred Perlstein close(mountdlockfd); 24888360efbdSAlfred Perlstein unlink(MOUNTDLOCK); 24897b98a1d6SAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); 24907b98a1d6SAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); 24918360efbdSAlfred Perlstein exit (0); 24928360efbdSAlfred Perlstein } 2493