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> 6491196234SPeter Wemm #include <nfsserver/nfs.h> 6587564113SPeter Wemm #include <ufs/ufs/ufsmount.h> 661166fb51SRuslan Ermilov #include <fs/msdosfs/msdosfsmount.h> 678a8402d3SRuslan Ermilov #include <fs/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 1128fae3551SRodney W. Grimes 1138fae3551SRodney W. Grimes struct exportlist { 1148fae3551SRodney W. Grimes struct exportlist *ex_next; 1158fae3551SRodney W. Grimes struct dirlist *ex_dirl; 1168fae3551SRodney W. Grimes struct dirlist *ex_defdir; 1178fae3551SRodney W. Grimes int ex_flag; 1188fae3551SRodney W. Grimes fsid_t ex_fs; 1198fae3551SRodney W. Grimes char *ex_fsdir; 120cb3923e0SDoug Rabson char *ex_indexfile; 1218fae3551SRodney W. Grimes }; 1228fae3551SRodney W. Grimes /* ex_flag bits */ 1238fae3551SRodney W. Grimes #define EX_LINKED 0x1 1248fae3551SRodney W. Grimes 1258fae3551SRodney W. Grimes struct netmsk { 1268360efbdSAlfred Perlstein struct sockaddr_storage nt_net; 12760caaee2SIan Dowse struct sockaddr_storage nt_mask; 1288fae3551SRodney W. Grimes char *nt_name; 1298fae3551SRodney W. Grimes }; 1308fae3551SRodney W. Grimes 1318fae3551SRodney W. Grimes union grouptypes { 1328360efbdSAlfred Perlstein struct addrinfo *gt_addrinfo; 1338fae3551SRodney W. Grimes struct netmsk gt_net; 1348fae3551SRodney W. Grimes }; 1358fae3551SRodney W. Grimes 1368fae3551SRodney W. Grimes struct grouplist { 1378fae3551SRodney W. Grimes int gr_type; 1388fae3551SRodney W. Grimes union grouptypes gr_ptr; 1398fae3551SRodney W. Grimes struct grouplist *gr_next; 1408fae3551SRodney W. Grimes }; 1418fae3551SRodney W. Grimes /* Group types */ 1428fae3551SRodney W. Grimes #define GT_NULL 0x0 1438fae3551SRodney W. Grimes #define GT_HOST 0x1 1448fae3551SRodney W. Grimes #define GT_NET 0x2 1456d359f31SIan Dowse #define GT_DEFAULT 0x3 1468b5a6d67SBill Paul #define GT_IGNORE 0x5 1478fae3551SRodney W. Grimes 1488fae3551SRodney W. Grimes struct hostlist { 149a62dc406SDoug Rabson int ht_flag; /* Uses DP_xx bits */ 1508fae3551SRodney W. Grimes struct grouplist *ht_grp; 1518fae3551SRodney W. Grimes struct hostlist *ht_next; 1528fae3551SRodney W. Grimes }; 1538fae3551SRodney W. Grimes 154a62dc406SDoug Rabson struct fhreturn { 155a62dc406SDoug Rabson int fhr_flag; 156a62dc406SDoug Rabson int fhr_vers; 157a62dc406SDoug Rabson nfsfh_t fhr_fh; 158a62dc406SDoug Rabson }; 159a62dc406SDoug Rabson 1608fae3551SRodney W. Grimes /* Global defs */ 16185429990SWarner Losh char *add_expdir(struct dirlist **, char *, int); 16285429990SWarner Losh void add_dlist(struct dirlist **, struct dirlist *, 16385429990SWarner Losh struct grouplist *, int); 16485429990SWarner Losh void add_mlist(char *, char *); 16585429990SWarner Losh int check_dirpath(char *); 16685429990SWarner Losh int check_options(struct dirlist *); 16760caaee2SIan Dowse int checkmask(struct sockaddr *sa); 16885429990SWarner Losh int chk_host(struct dirlist *, struct sockaddr *, int *, int *); 16901709abfSIan Dowse void del_mlist(char *hostp, char *dirp); 17085429990SWarner Losh struct dirlist *dirp_search(struct dirlist *, char *); 17185429990SWarner Losh int do_mount(struct exportlist *, struct grouplist *, int, 17285429990SWarner Losh struct xucred *, char *, int, struct statfs *); 17385429990SWarner Losh int do_opt(char **, char **, struct exportlist *, struct grouplist *, 17485429990SWarner Losh int *, int *, struct xucred *); 17585429990SWarner Losh struct exportlist *ex_search(fsid_t *); 17685429990SWarner Losh struct exportlist *get_exp(void); 17785429990SWarner Losh void free_dir(struct dirlist *); 17885429990SWarner Losh void free_exp(struct exportlist *); 17985429990SWarner Losh void free_grp(struct grouplist *); 18085429990SWarner Losh void free_host(struct hostlist *); 18185429990SWarner Losh void get_exportlist(void); 18285429990SWarner Losh int get_host(char *, struct grouplist *, struct grouplist *); 18385429990SWarner Losh struct hostlist *get_ht(void); 18485429990SWarner Losh int get_line(void); 18585429990SWarner Losh void get_mountlist(void); 18685429990SWarner Losh int get_net(char *, struct netmsk *, int); 18785429990SWarner Losh void getexp_err(struct exportlist *, struct grouplist *); 18885429990SWarner Losh struct grouplist *get_grp(void); 18985429990SWarner Losh void hang_dirp(struct dirlist *, struct grouplist *, 19085429990SWarner Losh struct exportlist *, int); 19169d65572SIan Dowse void huphandler(int sig); 19260caaee2SIan Dowse int makemask(struct sockaddr_storage *ssp, int bitlen); 19385429990SWarner Losh void mntsrv(struct svc_req *, SVCXPRT *); 19485429990SWarner Losh void nextfield(char **, char **); 19585429990SWarner Losh void out_of_mem(void); 19685429990SWarner Losh void parsecred(char *, struct xucred *); 19785429990SWarner Losh int put_exlist(struct dirlist *, XDR *, struct dirlist *, int *); 19860caaee2SIan Dowse void *sa_rawaddr(struct sockaddr *sa, int *nbytes); 19960caaee2SIan Dowse int sacmp(struct sockaddr *sa1, struct sockaddr *sa2, 20060caaee2SIan Dowse struct sockaddr *samask); 20185429990SWarner Losh int scan_tree(struct dirlist *, struct sockaddr *); 20285429990SWarner Losh static void usage(void); 20385429990SWarner Losh int xdr_dir(XDR *, char *); 20485429990SWarner Losh int xdr_explist(XDR *, caddr_t); 20585429990SWarner Losh int xdr_fhs(XDR *, caddr_t); 20685429990SWarner Losh int xdr_mlist(XDR *, caddr_t); 20785429990SWarner Losh void terminate(int); 2088fae3551SRodney W. Grimes 2098fae3551SRodney W. Grimes struct exportlist *exphead; 2108fae3551SRodney W. Grimes struct mountlist *mlhead; 2118fae3551SRodney W. Grimes struct grouplist *grphead; 2128fae3551SRodney W. Grimes char exname[MAXPATHLEN]; 213c0511d3bSBrian Feldman struct xucred def_anon = { 21476183f34SDima Dorfman XUCRED_VERSION, 2158fae3551SRodney W. Grimes (uid_t)-2, 2168fae3551SRodney W. Grimes 1, 217c0511d3bSBrian Feldman { (gid_t)-2 }, 218c0511d3bSBrian Feldman NULL 2198fae3551SRodney W. Grimes }; 2202a66cfc5SDoug Rabson int force_v2 = 0; 221a62dc406SDoug Rabson int resvport_only = 1; 222a62dc406SDoug Rabson int dir_only = 1; 223f2c90b95SGuido van Rooij int log = 0; 22469d65572SIan Dowse int got_sighup = 0; 2258360efbdSAlfred Perlstein 2268fae3551SRodney W. Grimes int opt_flags; 2278360efbdSAlfred Perlstein static int have_v6 = 1; 2288360efbdSAlfred Perlstein #ifdef NI_WITHSCOPEID 2298360efbdSAlfred Perlstein static const int ninumeric = NI_NUMERICHOST | NI_WITHSCOPEID; 2308360efbdSAlfred Perlstein #else 2318360efbdSAlfred Perlstein static const int ninumeric = NI_NUMERICHOST; 2328360efbdSAlfred Perlstein #endif 2338360efbdSAlfred Perlstein 2348360efbdSAlfred Perlstein int mountdlockfd; 23560caaee2SIan Dowse /* Bits for opt_flags above */ 2368fae3551SRodney W. Grimes #define OP_MAPROOT 0x01 2378fae3551SRodney W. Grimes #define OP_MAPALL 0x02 23891196234SPeter Wemm /* 0x4 free */ 2398fae3551SRodney W. Grimes #define OP_MASK 0x08 2408fae3551SRodney W. Grimes #define OP_NET 0x10 2418fae3551SRodney W. Grimes #define OP_ALLDIRS 0x40 24260caaee2SIan Dowse #define OP_HAVEMASK 0x80 /* A mask was specified or inferred. */ 2438360efbdSAlfred Perlstein #define OP_MASKLEN 0x200 2448fae3551SRodney W. Grimes 2458fae3551SRodney W. Grimes #ifdef DEBUG 2468fae3551SRodney W. Grimes int debug = 1; 24785429990SWarner Losh void SYSLOG(int, const char *, ...) __printflike(2, 3); 2488fae3551SRodney W. Grimes #define syslog SYSLOG 2498fae3551SRodney W. Grimes #else 2508fae3551SRodney W. Grimes int debug = 0; 2518fae3551SRodney W. Grimes #endif 2528fae3551SRodney W. Grimes 2538fae3551SRodney W. Grimes /* 2548fae3551SRodney W. Grimes * Mountd server for NFS mount protocol as described in: 2558fae3551SRodney W. Grimes * NFS: Network File System Protocol Specification, RFC1094, Appendix A 2568fae3551SRodney W. Grimes * The optional arguments are the exports file name 2578fae3551SRodney W. Grimes * default: _PATH_EXPORTS 2588fae3551SRodney W. Grimes * and "-n" to allow nonroot mount. 2598fae3551SRodney W. Grimes */ 2608fae3551SRodney W. Grimes int 2618fae3551SRodney W. Grimes main(argc, argv) 2628fae3551SRodney W. Grimes int argc; 2638fae3551SRodney W. Grimes char **argv; 2648fae3551SRodney W. Grimes { 26569d65572SIan Dowse fd_set readfds; 2668360efbdSAlfred Perlstein SVCXPRT *udptransp, *tcptransp, *udp6transp, *tcp6transp; 2678360efbdSAlfred Perlstein struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf; 2688360efbdSAlfred Perlstein int udpsock, tcpsock, udp6sock, tcp6sock; 2698360efbdSAlfred Perlstein int xcreated = 0, s; 2708360efbdSAlfred Perlstein int one = 1; 2714a0785aaSPeter Wemm int c, error; 272d599144dSGarrett Wollman 27301709abfSIan Dowse udp6conf = tcp6conf = NULL; 27401709abfSIan Dowse udp6sock = tcp6sock = NULL; 2758360efbdSAlfred Perlstein 27601709abfSIan Dowse /* Check that another mountd isn't already running. */ 2778360efbdSAlfred Perlstein if ((mountdlockfd = (open(MOUNTDLOCK, O_RDONLY|O_CREAT, 0444))) == -1) 2788360efbdSAlfred Perlstein err(1, "%s", MOUNTDLOCK); 2798360efbdSAlfred Perlstein 2808360efbdSAlfred Perlstein if(flock(mountdlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) 2818360efbdSAlfred Perlstein errx(1, "another rpc.mountd is already running. Aborting"); 2828360efbdSAlfred Perlstein s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 2838360efbdSAlfred Perlstein if (s < 0) 2848360efbdSAlfred Perlstein have_v6 = 0; 2858360efbdSAlfred Perlstein else 2868360efbdSAlfred Perlstein close(s); 2874a0785aaSPeter Wemm if (modfind("nfsserver") < 0) { 2884a0785aaSPeter Wemm /* Not present in kernel, try loading it */ 2894a0785aaSPeter Wemm if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0) 2904a0785aaSPeter Wemm errx(1, "NFS server is not available or loadable"); 291d599144dSGarrett Wollman } 2928fae3551SRodney W. Grimes 293690c488dSGuido van Rooij while ((c = getopt(argc, argv, "2dlnr")) != -1) 2948fae3551SRodney W. Grimes switch (c) { 2952a66cfc5SDoug Rabson case '2': 2962a66cfc5SDoug Rabson force_v2 = 1; 2972a66cfc5SDoug Rabson break; 298a62dc406SDoug Rabson case 'n': 299a62dc406SDoug Rabson resvport_only = 0; 300a62dc406SDoug Rabson break; 301a62dc406SDoug Rabson case 'r': 302a62dc406SDoug Rabson dir_only = 0; 303a62dc406SDoug Rabson break; 3046444ef3bSPoul-Henning Kamp case 'd': 3056444ef3bSPoul-Henning Kamp debug = debug ? 0 : 1; 3066444ef3bSPoul-Henning Kamp break; 307f51631d7SGuido van Rooij case 'l': 308f51631d7SGuido van Rooij log = 1; 309f51631d7SGuido van Rooij break; 3108fae3551SRodney W. Grimes default: 31174853402SPhilippe Charnier usage(); 3128fae3551SRodney W. Grimes }; 3138fae3551SRodney W. Grimes argc -= optind; 3148fae3551SRodney W. Grimes argv += optind; 3158fae3551SRodney W. Grimes grphead = (struct grouplist *)NULL; 3168fae3551SRodney W. Grimes exphead = (struct exportlist *)NULL; 3178fae3551SRodney W. Grimes mlhead = (struct mountlist *)NULL; 3188fae3551SRodney W. Grimes if (argc == 1) { 3198fae3551SRodney W. Grimes strncpy(exname, *argv, MAXPATHLEN-1); 3208fae3551SRodney W. Grimes exname[MAXPATHLEN-1] = '\0'; 3218fae3551SRodney W. Grimes } else 3228fae3551SRodney W. Grimes strcpy(exname, _PATH_EXPORTS); 3238fae3551SRodney W. Grimes openlog("mountd", LOG_PID, LOG_DAEMON); 3248fae3551SRodney W. Grimes if (debug) 32574853402SPhilippe Charnier warnx("getting export list"); 3268fae3551SRodney W. Grimes get_exportlist(); 3278fae3551SRodney W. Grimes if (debug) 32874853402SPhilippe Charnier warnx("getting mount list"); 3298fae3551SRodney W. Grimes get_mountlist(); 3308fae3551SRodney W. Grimes if (debug) 33174853402SPhilippe Charnier warnx("here we go"); 3328fae3551SRodney W. Grimes if (debug == 0) { 3338fae3551SRodney W. Grimes daemon(0, 0); 3348fae3551SRodney W. Grimes signal(SIGINT, SIG_IGN); 3358fae3551SRodney W. Grimes signal(SIGQUIT, SIG_IGN); 3368fae3551SRodney W. Grimes } 33769d65572SIan Dowse signal(SIGHUP, huphandler); 3388360efbdSAlfred Perlstein signal(SIGTERM, terminate); 3398fae3551SRodney W. Grimes { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); 3408fae3551SRodney W. Grimes if (pidfile != NULL) { 3418fae3551SRodney W. Grimes fprintf(pidfile, "%d\n", getpid()); 3428fae3551SRodney W. Grimes fclose(pidfile); 3438fae3551SRodney W. Grimes } 3448fae3551SRodney W. Grimes } 3458360efbdSAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); 3468360efbdSAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); 3478360efbdSAlfred Perlstein udpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 3488360efbdSAlfred Perlstein tcpsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 34995b99739SAlfred Perlstein udpconf = getnetconfigent("udp"); 35095b99739SAlfred Perlstein tcpconf = getnetconfigent("tcp"); 35195b99739SAlfred Perlstein if (!have_v6) 35295b99739SAlfred Perlstein goto skip_v6; 3538360efbdSAlfred Perlstein udp6sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 3548360efbdSAlfred Perlstein tcp6sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); 3558360efbdSAlfred Perlstein /* 3568360efbdSAlfred Perlstein * We're doing host-based access checks here, so don't allow 3578360efbdSAlfred Perlstein * v4-in-v6 to confuse things. The kernel will disable it 3588360efbdSAlfred Perlstein * by default on NFS sockets too. 3598360efbdSAlfred Perlstein */ 3608360efbdSAlfred Perlstein if (udp6sock != -1 && setsockopt(udp6sock, IPPROTO_IPV6, 3618360efbdSAlfred Perlstein IPV6_BINDV6ONLY, &one, sizeof one) < 0){ 3628360efbdSAlfred Perlstein syslog(LOG_ERR, "can't disable v4-in-v6 on UDP socket"); 3638360efbdSAlfred Perlstein exit(1); 3648360efbdSAlfred Perlstein } 3658360efbdSAlfred Perlstein if (tcp6sock != -1 && setsockopt(tcp6sock, IPPROTO_IPV6, 3668360efbdSAlfred Perlstein IPV6_BINDV6ONLY, &one, sizeof one) < 0){ 3678360efbdSAlfred Perlstein syslog(LOG_ERR, "can't disable v4-in-v6 on UDP socket"); 3688360efbdSAlfred Perlstein exit(1); 3698360efbdSAlfred Perlstein } 3708360efbdSAlfred Perlstein udp6conf = getnetconfigent("udp6"); 3718360efbdSAlfred Perlstein tcp6conf = getnetconfigent("tcp6"); 37295b99739SAlfred Perlstein 37395b99739SAlfred Perlstein skip_v6: 374c6e5e158SGuido van Rooij if (!resvport_only) { 3754a0785aaSPeter Wemm if (sysctlbyname("vfs.nfsrv.nfs_privport", NULL, NULL, 3764a0785aaSPeter Wemm &resvport_only, sizeof(resvport_only)) != 0 && 3774a0785aaSPeter Wemm errno != ENOENT) { 378394da4c1SGuido van Rooij syslog(LOG_ERR, "sysctl: %m"); 379394da4c1SGuido van Rooij exit(1); 380394da4c1SGuido van Rooij } 381c6e5e158SGuido van Rooij } 382d3628763SRodney W. Grimes if ((udptransp = svcudp_create(RPC_ANYSOCK)) == NULL || 383d3628763SRodney W. Grimes (tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0)) == NULL) { 38474853402SPhilippe Charnier syslog(LOG_ERR, "can't create socket"); 3858fae3551SRodney W. Grimes exit(1); 3868fae3551SRodney W. Grimes } 3878360efbdSAlfred Perlstein if (udpsock != -1 && udpconf != NULL) { 3888360efbdSAlfred Perlstein bindresvport(udpsock, NULL); 3898360efbdSAlfred Perlstein udptransp = svc_dg_create(udpsock, 0, 0); 3908360efbdSAlfred Perlstein if (udptransp != NULL) { 3918360efbdSAlfred Perlstein if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER1, 3928360efbdSAlfred Perlstein mntsrv, udpconf)) 3938360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP RPCMNT_VER1 service"); 3948360efbdSAlfred Perlstein else 3958360efbdSAlfred Perlstein xcreated++; 3968360efbdSAlfred Perlstein if (!force_v2) { 3978360efbdSAlfred Perlstein if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER3, 3988360efbdSAlfred Perlstein mntsrv, udpconf)) 3998360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP RPCMNT_VER3 service"); 4008360efbdSAlfred Perlstein else 4018360efbdSAlfred Perlstein xcreated++; 4028fae3551SRodney W. Grimes } 4038360efbdSAlfred Perlstein } else 4048360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create UDP services"); 4058360efbdSAlfred Perlstein 4068360efbdSAlfred Perlstein } 4078360efbdSAlfred Perlstein if (tcpsock != -1 && tcpconf != NULL) { 4088360efbdSAlfred Perlstein bindresvport(tcpsock, NULL); 4098360efbdSAlfred Perlstein listen(tcpsock, SOMAXCONN); 4108360efbdSAlfred Perlstein tcptransp = svc_vc_create(tcpsock, 0, 0); 4118360efbdSAlfred Perlstein if (tcptransp != NULL) { 4128360efbdSAlfred Perlstein if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER1, 4138360efbdSAlfred Perlstein mntsrv, tcpconf)) 4148360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP RPCMNT_VER1 service"); 4158360efbdSAlfred Perlstein else 4168360efbdSAlfred Perlstein xcreated++; 4178360efbdSAlfred Perlstein if (!force_v2) { 4188360efbdSAlfred Perlstein if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER3, 4198360efbdSAlfred Perlstein mntsrv, tcpconf)) 4208360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP RPCMNT_VER3 service"); 4218360efbdSAlfred Perlstein else 4228360efbdSAlfred Perlstein xcreated++; 4238360efbdSAlfred Perlstein } 4248360efbdSAlfred Perlstein } else 4258360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create TCP service"); 4268360efbdSAlfred Perlstein 4278360efbdSAlfred Perlstein } 42895b99739SAlfred Perlstein if (have_v6 && udp6sock != -1 && udp6conf != NULL) { 4298360efbdSAlfred Perlstein bindresvport(udp6sock, NULL); 4308360efbdSAlfred Perlstein udp6transp = svc_dg_create(udp6sock, 0, 0); 4318360efbdSAlfred Perlstein if (udp6transp != NULL) { 4328360efbdSAlfred Perlstein if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER1, 4338360efbdSAlfred Perlstein mntsrv, udp6conf)) 4348360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER1 service"); 4358360efbdSAlfred Perlstein else 4368360efbdSAlfred Perlstein xcreated++; 4378360efbdSAlfred Perlstein if (!force_v2) { 4388360efbdSAlfred Perlstein if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER3, 4398360efbdSAlfred Perlstein mntsrv, udp6conf)) 4408360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER3 service"); 4418360efbdSAlfred Perlstein else 4428360efbdSAlfred Perlstein xcreated++; 4438360efbdSAlfred Perlstein } 4448360efbdSAlfred Perlstein } else 4458360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create UDP6 service"); 4468360efbdSAlfred Perlstein 4478360efbdSAlfred Perlstein } 44895b99739SAlfred Perlstein if (have_v6 && tcp6sock != -1 && tcp6conf != NULL) { 4498360efbdSAlfred Perlstein bindresvport(tcp6sock, NULL); 4508360efbdSAlfred Perlstein listen(tcp6sock, SOMAXCONN); 4518360efbdSAlfred Perlstein tcp6transp = svc_vc_create(tcp6sock, 0, 0); 4528360efbdSAlfred Perlstein if (tcp6transp != NULL) { 4538360efbdSAlfred Perlstein if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER1, 4548360efbdSAlfred Perlstein mntsrv, tcp6conf)) 4558360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER1 service"); 4568360efbdSAlfred Perlstein else 4578360efbdSAlfred Perlstein xcreated++; 4588360efbdSAlfred Perlstein if (!force_v2) { 4598360efbdSAlfred Perlstein if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER3, 4608360efbdSAlfred Perlstein mntsrv, tcp6conf)) 4618360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER3 service"); 4628360efbdSAlfred Perlstein else 4638360efbdSAlfred Perlstein xcreated++; 4648360efbdSAlfred Perlstein } 4658360efbdSAlfred Perlstein } else 4668360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create TCP6 service"); 4678360efbdSAlfred Perlstein 4688360efbdSAlfred Perlstein } 4698360efbdSAlfred Perlstein if (xcreated == 0) { 4708360efbdSAlfred Perlstein syslog(LOG_ERR, "could not create any services"); 4712a66cfc5SDoug Rabson exit(1); 4722a66cfc5SDoug Rabson } 47369d65572SIan Dowse 47469d65572SIan Dowse /* Expand svc_run() here so that we can call get_exportlist(). */ 47569d65572SIan Dowse for (;;) { 47669d65572SIan Dowse if (got_sighup) { 47769d65572SIan Dowse get_exportlist(); 47869d65572SIan Dowse got_sighup = 0; 47969d65572SIan Dowse } 48069d65572SIan Dowse readfds = svc_fdset; 48169d65572SIan Dowse switch (select(svc_maxfd + 1, &readfds, NULL, NULL, NULL)) { 48269d65572SIan Dowse case -1: 48369d65572SIan Dowse if (errno == EINTR) 48469d65572SIan Dowse continue; 48569d65572SIan Dowse syslog(LOG_ERR, "mountd died: select: %m"); 48674853402SPhilippe Charnier exit(1); 48769d65572SIan Dowse case 0: 48869d65572SIan Dowse continue; 48969d65572SIan Dowse default: 49069d65572SIan Dowse svc_getreqset(&readfds); 49169d65572SIan Dowse } 49269d65572SIan Dowse } 49374853402SPhilippe Charnier } 49474853402SPhilippe Charnier 49574853402SPhilippe Charnier static void 49674853402SPhilippe Charnier usage() 49774853402SPhilippe Charnier { 49874853402SPhilippe Charnier fprintf(stderr, 49974853402SPhilippe Charnier "usage: mountd [-2] [-d] [-l] [-n] [-r] [export_file]\n"); 5008fae3551SRodney W. Grimes exit(1); 5018fae3551SRodney W. Grimes } 5028fae3551SRodney W. Grimes 5038fae3551SRodney W. Grimes /* 5048fae3551SRodney W. Grimes * The mount rpc service 5058fae3551SRodney W. Grimes */ 5068fae3551SRodney W. Grimes void 5078fae3551SRodney W. Grimes mntsrv(rqstp, transp) 5088fae3551SRodney W. Grimes struct svc_req *rqstp; 5098fae3551SRodney W. Grimes SVCXPRT *transp; 5108fae3551SRodney W. Grimes { 5118fae3551SRodney W. Grimes struct exportlist *ep; 5128fae3551SRodney W. Grimes struct dirlist *dp; 513a62dc406SDoug Rabson struct fhreturn fhr; 5148fae3551SRodney W. Grimes struct stat stb; 5158fae3551SRodney W. Grimes struct statfs fsb; 5168360efbdSAlfred Perlstein struct addrinfo *ai; 5178360efbdSAlfred Perlstein char host[NI_MAXHOST], numerichost[NI_MAXHOST]; 5188360efbdSAlfred Perlstein int lookup_failed = 1; 5198360efbdSAlfred Perlstein struct sockaddr *saddr; 520a62dc406SDoug Rabson u_short sport; 5218fae3551SRodney W. Grimes char rpcpath[RPCMNT_PATHLEN + 1], dirpath[MAXPATHLEN]; 522e90cdb54SGuido van Rooij int bad = 0, defset, hostset; 523a62dc406SDoug Rabson sigset_t sighup_mask; 5248fae3551SRodney W. Grimes 525a62dc406SDoug Rabson sigemptyset(&sighup_mask); 526a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 5278360efbdSAlfred Perlstein saddr = svc_getrpccaller(transp)->buf; 5288360efbdSAlfred Perlstein switch (saddr->sa_family) { 5298360efbdSAlfred Perlstein case AF_INET6: 53001709abfSIan Dowse sport = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port); 5318360efbdSAlfred Perlstein break; 5328360efbdSAlfred Perlstein case AF_INET: 53301709abfSIan Dowse sport = ntohs(((struct sockaddr_in *)saddr)->sin_port); 5348360efbdSAlfred Perlstein break; 5358360efbdSAlfred Perlstein default: 5368360efbdSAlfred Perlstein syslog(LOG_ERR, "request from unknown address family"); 5378360efbdSAlfred Perlstein return; 5388360efbdSAlfred Perlstein } 5398360efbdSAlfred Perlstein lookup_failed = getnameinfo(saddr, saddr->sa_len, host, sizeof host, 5408360efbdSAlfred Perlstein NULL, 0, 0); 5418360efbdSAlfred Perlstein getnameinfo(saddr, saddr->sa_len, numerichost, 5428360efbdSAlfred Perlstein sizeof numerichost, NULL, 0, NI_NUMERICHOST); 5438360efbdSAlfred Perlstein ai = NULL; 5448fae3551SRodney W. Grimes switch (rqstp->rq_proc) { 5458fae3551SRodney W. Grimes case NULLPROC: 5468fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 54774853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 5488fae3551SRodney W. Grimes return; 5498fae3551SRodney W. Grimes case RPCMNT_MOUNT: 550a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 551f51631d7SGuido van Rooij syslog(LOG_NOTICE, 552f51631d7SGuido van Rooij "mount request from %s from unprivileged port", 5538360efbdSAlfred Perlstein numerichost); 5548fae3551SRodney W. Grimes svcerr_weakauth(transp); 5558fae3551SRodney W. Grimes return; 5568fae3551SRodney W. Grimes } 5578fae3551SRodney W. Grimes if (!svc_getargs(transp, xdr_dir, rpcpath)) { 558f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable mount request from %s", 5598360efbdSAlfred Perlstein numerichost); 5608fae3551SRodney W. Grimes svcerr_decode(transp); 5618fae3551SRodney W. Grimes return; 5628fae3551SRodney W. Grimes } 5638fae3551SRodney W. Grimes 5648fae3551SRodney W. Grimes /* 5658fae3551SRodney W. Grimes * Get the real pathname and make sure it is a directory 566a62dc406SDoug Rabson * or a regular file if the -r option was specified 567a62dc406SDoug Rabson * and it exists. 5688fae3551SRodney W. Grimes */ 569cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL || 5708fae3551SRodney W. Grimes stat(dirpath, &stb) < 0 || 571a62dc406SDoug Rabson (!S_ISDIR(stb.st_mode) && 572a62dc406SDoug Rabson (dir_only || !S_ISREG(stb.st_mode))) || 5738fae3551SRodney W. Grimes statfs(dirpath, &fsb) < 0) { 5748fae3551SRodney W. Grimes chdir("/"); /* Just in case realpath doesn't */ 575f51631d7SGuido van Rooij syslog(LOG_NOTICE, 57674853402SPhilippe Charnier "mount request from %s for non existent path %s", 5778360efbdSAlfred Perlstein numerichost, dirpath); 5788fae3551SRodney W. Grimes if (debug) 57974853402SPhilippe Charnier warnx("stat failed on %s", dirpath); 580e90cdb54SGuido van Rooij bad = ENOENT; /* We will send error reply later */ 5818fae3551SRodney W. Grimes } 5828fae3551SRodney W. Grimes 5838fae3551SRodney W. Grimes /* Check in the exports list */ 584a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 5858fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 586a62dc406SDoug Rabson hostset = defset = 0; 587a62dc406SDoug Rabson if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) || 5888fae3551SRodney W. Grimes ((dp = dirp_search(ep->ex_dirl, dirpath)) && 589a62dc406SDoug Rabson chk_host(dp, saddr, &defset, &hostset)) || 5908fae3551SRodney W. Grimes (defset && scan_tree(ep->ex_defdir, saddr) == 0 && 5918fae3551SRodney W. Grimes scan_tree(ep->ex_dirl, saddr) == 0))) { 592e90cdb54SGuido van Rooij if (bad) { 593e90cdb54SGuido van Rooij if (!svc_sendreply(transp, xdr_long, 594e90cdb54SGuido van Rooij (caddr_t)&bad)) 59574853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 596e90cdb54SGuido van Rooij sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 597e90cdb54SGuido van Rooij return; 598e90cdb54SGuido van Rooij } 599a62dc406SDoug Rabson if (hostset & DP_HOSTSET) 600a62dc406SDoug Rabson fhr.fhr_flag = hostset; 601a62dc406SDoug Rabson else 602a62dc406SDoug Rabson fhr.fhr_flag = defset; 603a62dc406SDoug Rabson fhr.fhr_vers = rqstp->rq_vers; 6048fae3551SRodney W. Grimes /* Get the file handle */ 60587564113SPeter Wemm memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t)); 606a62dc406SDoug Rabson if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) { 6078fae3551SRodney W. Grimes bad = errno; 60874853402SPhilippe Charnier syslog(LOG_ERR, "can't get fh for %s", dirpath); 6098fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_long, 6108fae3551SRodney W. Grimes (caddr_t)&bad)) 61174853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 612a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6138fae3551SRodney W. Grimes return; 6148fae3551SRodney W. Grimes } 615a62dc406SDoug Rabson if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr)) 61674853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6178360efbdSAlfred Perlstein if (!lookup_failed) 6188360efbdSAlfred Perlstein add_mlist(host, dirpath); 6198fae3551SRodney W. Grimes else 6208360efbdSAlfred Perlstein add_mlist(numerichost, dirpath); 6218fae3551SRodney W. Grimes if (debug) 62274853402SPhilippe Charnier warnx("mount successful"); 623f51631d7SGuido van Rooij if (log) 624f51631d7SGuido van Rooij syslog(LOG_NOTICE, 625f51631d7SGuido van Rooij "mount request succeeded from %s for %s", 6268360efbdSAlfred Perlstein numerichost, dirpath); 627f51631d7SGuido van Rooij } else { 6288fae3551SRodney W. Grimes bad = EACCES; 629f51631d7SGuido van Rooij syslog(LOG_NOTICE, 630f51631d7SGuido van Rooij "mount request denied from %s for %s", 6318360efbdSAlfred Perlstein numerichost, dirpath); 632f51631d7SGuido van Rooij } 633e90cdb54SGuido van Rooij 634e90cdb54SGuido van Rooij if (bad && !svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 63574853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 636a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6378fae3551SRodney W. Grimes return; 6388fae3551SRodney W. Grimes case RPCMNT_DUMP: 6398fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL)) 64074853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 641f51631d7SGuido van Rooij else if (log) 642f51631d7SGuido van Rooij syslog(LOG_NOTICE, 643f51631d7SGuido van Rooij "dump request succeeded from %s", 6448360efbdSAlfred Perlstein numerichost); 6458fae3551SRodney W. Grimes return; 6468fae3551SRodney W. Grimes case RPCMNT_UMOUNT: 647a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 648f51631d7SGuido van Rooij syslog(LOG_NOTICE, 649f51631d7SGuido van Rooij "umount request from %s from unprivileged port", 6508360efbdSAlfred Perlstein numerichost); 6518fae3551SRodney W. Grimes svcerr_weakauth(transp); 6528fae3551SRodney W. Grimes return; 6538fae3551SRodney W. Grimes } 654cb479b11SAlfred Perlstein if (!svc_getargs(transp, xdr_dir, rpcpath)) { 655f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable umount request from %s", 6568360efbdSAlfred Perlstein numerichost); 6578fae3551SRodney W. Grimes svcerr_decode(transp); 6588fae3551SRodney W. Grimes return; 6598fae3551SRodney W. Grimes } 660cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL) { 661cb479b11SAlfred Perlstein syslog(LOG_NOTICE, "umount request from %s " 662cb479b11SAlfred Perlstein "for non existent path %s", 6638360efbdSAlfred Perlstein numerichost, dirpath); 664cb479b11SAlfred Perlstein } 6658fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 66674853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6678360efbdSAlfred Perlstein if (!lookup_failed) 66801709abfSIan Dowse del_mlist(host, dirpath); 66901709abfSIan Dowse del_mlist(numerichost, dirpath); 670f51631d7SGuido van Rooij if (log) 671f51631d7SGuido van Rooij syslog(LOG_NOTICE, 672f51631d7SGuido van Rooij "umount request succeeded from %s for %s", 6738360efbdSAlfred Perlstein numerichost, dirpath); 6748fae3551SRodney W. Grimes return; 6758fae3551SRodney W. Grimes case RPCMNT_UMNTALL: 676a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 677f51631d7SGuido van Rooij syslog(LOG_NOTICE, 678f51631d7SGuido van Rooij "umountall request from %s from unprivileged port", 6798360efbdSAlfred Perlstein numerichost); 6808fae3551SRodney W. Grimes svcerr_weakauth(transp); 6818fae3551SRodney W. Grimes return; 6828fae3551SRodney W. Grimes } 6838fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) 68474853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6858360efbdSAlfred Perlstein if (!lookup_failed) 68601709abfSIan Dowse del_mlist(host, NULL); 68701709abfSIan Dowse del_mlist(numerichost, NULL); 688f51631d7SGuido van Rooij if (log) 689f51631d7SGuido van Rooij syslog(LOG_NOTICE, 690f51631d7SGuido van Rooij "umountall request succeeded from %s", 6918360efbdSAlfred Perlstein numerichost); 6928fae3551SRodney W. Grimes return; 6938fae3551SRodney W. Grimes case RPCMNT_EXPORT: 6948fae3551SRodney W. Grimes if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL)) 69574853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 696f51631d7SGuido van Rooij if (log) 697f51631d7SGuido van Rooij syslog(LOG_NOTICE, 698f51631d7SGuido van Rooij "export request succeeded from %s", 6998360efbdSAlfred Perlstein numerichost); 7008fae3551SRodney W. Grimes return; 7018fae3551SRodney W. Grimes default: 7028fae3551SRodney W. Grimes svcerr_noproc(transp); 7038fae3551SRodney W. Grimes return; 7048fae3551SRodney W. Grimes } 7058fae3551SRodney W. Grimes } 7068fae3551SRodney W. Grimes 7078fae3551SRodney W. Grimes /* 7088fae3551SRodney W. Grimes * Xdr conversion for a dirpath string 7098fae3551SRodney W. Grimes */ 7108fae3551SRodney W. Grimes int 7118fae3551SRodney W. Grimes xdr_dir(xdrsp, dirp) 7128fae3551SRodney W. Grimes XDR *xdrsp; 7138fae3551SRodney W. Grimes char *dirp; 7148fae3551SRodney W. Grimes { 7158fae3551SRodney W. Grimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 7168fae3551SRodney W. Grimes } 7178fae3551SRodney W. Grimes 7188fae3551SRodney W. Grimes /* 719a62dc406SDoug Rabson * Xdr routine to generate file handle reply 7208fae3551SRodney W. Grimes */ 7218fae3551SRodney W. Grimes int 722a62dc406SDoug Rabson xdr_fhs(xdrsp, cp) 7238fae3551SRodney W. Grimes XDR *xdrsp; 724a62dc406SDoug Rabson caddr_t cp; 7258fae3551SRodney W. Grimes { 7263d438ad6SDavid E. O'Brien struct fhreturn *fhrp = (struct fhreturn *)cp; 727a62dc406SDoug Rabson u_long ok = 0, len, auth; 7288fae3551SRodney W. Grimes 7298fae3551SRodney W. Grimes if (!xdr_long(xdrsp, &ok)) 7308fae3551SRodney W. Grimes return (0); 731a62dc406SDoug Rabson switch (fhrp->fhr_vers) { 732a62dc406SDoug Rabson case 1: 733a62dc406SDoug Rabson return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH)); 734a62dc406SDoug Rabson case 3: 735a62dc406SDoug Rabson len = NFSX_V3FH; 736a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 737a62dc406SDoug Rabson return (0); 738a62dc406SDoug Rabson if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) 739a62dc406SDoug Rabson return (0); 740a62dc406SDoug Rabson auth = RPCAUTH_UNIX; 741a62dc406SDoug Rabson len = 1; 742a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 743a62dc406SDoug Rabson return (0); 744a62dc406SDoug Rabson return (xdr_long(xdrsp, &auth)); 745a62dc406SDoug Rabson }; 746a62dc406SDoug Rabson return (0); 7478fae3551SRodney W. Grimes } 7488fae3551SRodney W. Grimes 7498fae3551SRodney W. Grimes int 7508fae3551SRodney W. Grimes xdr_mlist(xdrsp, cp) 7518fae3551SRodney W. Grimes XDR *xdrsp; 7528fae3551SRodney W. Grimes caddr_t cp; 7538fae3551SRodney W. Grimes { 7548fae3551SRodney W. Grimes struct mountlist *mlp; 7558fae3551SRodney W. Grimes int true = 1; 7568fae3551SRodney W. Grimes int false = 0; 7578fae3551SRodney W. Grimes char *strp; 7588fae3551SRodney W. Grimes 7598fae3551SRodney W. Grimes mlp = mlhead; 7608fae3551SRodney W. Grimes while (mlp) { 7618fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 7628fae3551SRodney W. Grimes return (0); 7638fae3551SRodney W. Grimes strp = &mlp->ml_host[0]; 7648fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 7658fae3551SRodney W. Grimes return (0); 7668fae3551SRodney W. Grimes strp = &mlp->ml_dirp[0]; 7678fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 7688fae3551SRodney W. Grimes return (0); 7698fae3551SRodney W. Grimes mlp = mlp->ml_next; 7708fae3551SRodney W. Grimes } 7718fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 7728fae3551SRodney W. Grimes return (0); 7738fae3551SRodney W. Grimes return (1); 7748fae3551SRodney W. Grimes } 7758fae3551SRodney W. Grimes 7768fae3551SRodney W. Grimes /* 7778fae3551SRodney W. Grimes * Xdr conversion for export list 7788fae3551SRodney W. Grimes */ 7798fae3551SRodney W. Grimes int 7808fae3551SRodney W. Grimes xdr_explist(xdrsp, cp) 7818fae3551SRodney W. Grimes XDR *xdrsp; 7828fae3551SRodney W. Grimes caddr_t cp; 7838fae3551SRodney W. Grimes { 7848fae3551SRodney W. Grimes struct exportlist *ep; 7858fae3551SRodney W. Grimes int false = 0; 786a62dc406SDoug Rabson int putdef; 787a62dc406SDoug Rabson sigset_t sighup_mask; 7888fae3551SRodney W. Grimes 789a62dc406SDoug Rabson sigemptyset(&sighup_mask); 790a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 791a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 7928fae3551SRodney W. Grimes ep = exphead; 7938fae3551SRodney W. Grimes while (ep) { 7948fae3551SRodney W. Grimes putdef = 0; 7958fae3551SRodney W. Grimes if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, &putdef)) 7968fae3551SRodney W. Grimes goto errout; 7978fae3551SRodney W. Grimes if (ep->ex_defdir && putdef == 0 && 7988fae3551SRodney W. Grimes put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL, 7998fae3551SRodney W. Grimes &putdef)) 8008fae3551SRodney W. Grimes goto errout; 8018fae3551SRodney W. Grimes ep = ep->ex_next; 8028fae3551SRodney W. Grimes } 803a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 8048fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 8058fae3551SRodney W. Grimes return (0); 8068fae3551SRodney W. Grimes return (1); 8078fae3551SRodney W. Grimes errout: 808a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 8098fae3551SRodney W. Grimes return (0); 8108fae3551SRodney W. Grimes } 8118fae3551SRodney W. Grimes 8128fae3551SRodney W. Grimes /* 8138fae3551SRodney W. Grimes * Called from xdr_explist() to traverse the tree and export the 8148fae3551SRodney W. Grimes * directory paths. 8158fae3551SRodney W. Grimes */ 8168fae3551SRodney W. Grimes int 8178fae3551SRodney W. Grimes put_exlist(dp, xdrsp, adp, putdefp) 8188fae3551SRodney W. Grimes struct dirlist *dp; 8198fae3551SRodney W. Grimes XDR *xdrsp; 8208fae3551SRodney W. Grimes struct dirlist *adp; 8218fae3551SRodney W. Grimes int *putdefp; 8228fae3551SRodney W. Grimes { 8238fae3551SRodney W. Grimes struct grouplist *grp; 8248fae3551SRodney W. Grimes struct hostlist *hp; 8258fae3551SRodney W. Grimes int true = 1; 8268fae3551SRodney W. Grimes int false = 0; 8278fae3551SRodney W. Grimes int gotalldir = 0; 8288fae3551SRodney W. Grimes char *strp; 8298fae3551SRodney W. Grimes 8308fae3551SRodney W. Grimes if (dp) { 8318fae3551SRodney W. Grimes if (put_exlist(dp->dp_left, xdrsp, adp, putdefp)) 8328fae3551SRodney W. Grimes return (1); 8338fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 8348fae3551SRodney W. Grimes return (1); 8358fae3551SRodney W. Grimes strp = dp->dp_dirp; 8368fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 8378fae3551SRodney W. Grimes return (1); 8388fae3551SRodney W. Grimes if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) { 8398fae3551SRodney W. Grimes gotalldir = 1; 8408fae3551SRodney W. Grimes *putdefp = 1; 8418fae3551SRodney W. Grimes } 8428fae3551SRodney W. Grimes if ((dp->dp_flag & DP_DEFSET) == 0 && 8438fae3551SRodney W. Grimes (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) { 8448fae3551SRodney W. Grimes hp = dp->dp_hosts; 8458fae3551SRodney W. Grimes while (hp) { 8468fae3551SRodney W. Grimes grp = hp->ht_grp; 8478fae3551SRodney W. Grimes if (grp->gr_type == GT_HOST) { 8488fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 8498fae3551SRodney W. Grimes return (1); 8508360efbdSAlfred Perlstein strp = grp->gr_ptr.gt_addrinfo->ai_canonname; 8518fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, 8528fae3551SRodney W. Grimes RPCMNT_NAMELEN)) 8538fae3551SRodney W. Grimes return (1); 8548fae3551SRodney W. Grimes } else if (grp->gr_type == GT_NET) { 8558fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 8568fae3551SRodney W. Grimes return (1); 8578fae3551SRodney W. Grimes strp = grp->gr_ptr.gt_net.nt_name; 8588fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, 8598fae3551SRodney W. Grimes RPCMNT_NAMELEN)) 8608fae3551SRodney W. Grimes return (1); 8618fae3551SRodney W. Grimes } 8628fae3551SRodney W. Grimes hp = hp->ht_next; 8638fae3551SRodney W. Grimes if (gotalldir && hp == (struct hostlist *)NULL) { 8648fae3551SRodney W. Grimes hp = adp->dp_hosts; 8658fae3551SRodney W. Grimes gotalldir = 0; 8668fae3551SRodney W. Grimes } 8678fae3551SRodney W. Grimes } 8688fae3551SRodney W. Grimes } 8698fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 8708fae3551SRodney W. Grimes return (1); 8718fae3551SRodney W. Grimes if (put_exlist(dp->dp_right, xdrsp, adp, putdefp)) 8728fae3551SRodney W. Grimes return (1); 8738fae3551SRodney W. Grimes } 8748fae3551SRodney W. Grimes return (0); 8758fae3551SRodney W. Grimes } 8768fae3551SRodney W. Grimes 8778fae3551SRodney W. Grimes #define LINESIZ 10240 8788fae3551SRodney W. Grimes char line[LINESIZ]; 8798fae3551SRodney W. Grimes FILE *exp_file; 8808fae3551SRodney W. Grimes 8818fae3551SRodney W. Grimes /* 8828fae3551SRodney W. Grimes * Get the export list 8838fae3551SRodney W. Grimes */ 8848fae3551SRodney W. Grimes void 8858fae3551SRodney W. Grimes get_exportlist() 8868fae3551SRodney W. Grimes { 8878fae3551SRodney W. Grimes struct exportlist *ep, *ep2; 8888fae3551SRodney W. Grimes struct grouplist *grp, *tgrp; 8898fae3551SRodney W. Grimes struct exportlist **epp; 8908fae3551SRodney W. Grimes struct dirlist *dirhead; 8918fae3551SRodney W. Grimes struct statfs fsb, *fsp; 892c0511d3bSBrian Feldman struct xucred anon; 8938fae3551SRodney W. Grimes char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; 8948fae3551SRodney W. Grimes int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp; 8958fae3551SRodney W. Grimes 896cb479b11SAlfred Perlstein dirp = NULL; 897cb479b11SAlfred Perlstein dirplen = 0; 898cb479b11SAlfred Perlstein 8998fae3551SRodney W. Grimes /* 9008fae3551SRodney W. Grimes * First, get rid of the old list 9018fae3551SRodney W. Grimes */ 9028fae3551SRodney W. Grimes ep = exphead; 9038fae3551SRodney W. Grimes while (ep) { 9048fae3551SRodney W. Grimes ep2 = ep; 9058fae3551SRodney W. Grimes ep = ep->ex_next; 9068fae3551SRodney W. Grimes free_exp(ep2); 9078fae3551SRodney W. Grimes } 9088fae3551SRodney W. Grimes exphead = (struct exportlist *)NULL; 9098fae3551SRodney W. Grimes 9108fae3551SRodney W. Grimes grp = grphead; 9118fae3551SRodney W. Grimes while (grp) { 9128fae3551SRodney W. Grimes tgrp = grp; 9138fae3551SRodney W. Grimes grp = grp->gr_next; 9148fae3551SRodney W. Grimes free_grp(tgrp); 9158fae3551SRodney W. Grimes } 9168fae3551SRodney W. Grimes grphead = (struct grouplist *)NULL; 9178fae3551SRodney W. Grimes 9188fae3551SRodney W. Grimes /* 9198fae3551SRodney W. Grimes * And delete exports that are in the kernel for all local 9208fae3551SRodney W. Grimes * file systems. 9218fae3551SRodney W. Grimes * XXX: Should know how to handle all local exportable file systems 92287564113SPeter Wemm * instead of just "ufs". 9238fae3551SRodney W. Grimes */ 9248fae3551SRodney W. Grimes num = getmntinfo(&fsp, MNT_NOWAIT); 9258fae3551SRodney W. Grimes for (i = 0; i < num; i++) { 9268fae3551SRodney W. Grimes union { 9278fae3551SRodney W. Grimes struct ufs_args ua; 9288fae3551SRodney W. Grimes struct iso_args ia; 929a62dc406SDoug Rabson struct msdosfs_args da; 9309300c696SSemen Ustimenko struct ntfs_args na; 931a62dc406SDoug Rabson } targs; 932a62dc406SDoug Rabson 933753d4978SPoul-Henning Kamp if (!strcmp(fsp->f_fstypename, "ufs") || 9344ccd7546SRuslan Ermilov !strcmp(fsp->f_fstypename, "msdosfs") || 9359300c696SSemen Ustimenko !strcmp(fsp->f_fstypename, "ntfs") || 93687564113SPeter Wemm !strcmp(fsp->f_fstypename, "cd9660")) { 937a62dc406SDoug Rabson targs.ua.fspec = NULL; 938a62dc406SDoug Rabson targs.ua.export.ex_flags = MNT_DELEXPORT; 939a62dc406SDoug Rabson if (mount(fsp->f_fstypename, fsp->f_mntonname, 9405f558fa4SIan Dowse fsp->f_flags | MNT_UPDATE, (caddr_t)&targs) < 0 && 9415f558fa4SIan Dowse errno != ENOENT) 9425f558fa4SIan Dowse syslog(LOG_ERR, 9435f558fa4SIan Dowse "can't delete exports for %s: %m", 9448fae3551SRodney W. Grimes fsp->f_mntonname); 9458fae3551SRodney W. Grimes } 9468fae3551SRodney W. Grimes fsp++; 9478fae3551SRodney W. Grimes } 9488fae3551SRodney W. Grimes 9498fae3551SRodney W. Grimes /* 9508fae3551SRodney W. Grimes * Read in the exports file and build the list, calling 9518fae3551SRodney W. Grimes * mount() as we go along to push the export rules into the kernel. 9528fae3551SRodney W. Grimes */ 9538fae3551SRodney W. Grimes if ((exp_file = fopen(exname, "r")) == NULL) { 95474853402SPhilippe Charnier syslog(LOG_ERR, "can't open %s", exname); 9558fae3551SRodney W. Grimes exit(2); 9568fae3551SRodney W. Grimes } 9578fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 9588fae3551SRodney W. Grimes while (get_line()) { 9598fae3551SRodney W. Grimes if (debug) 96074853402SPhilippe Charnier warnx("got line %s", line); 9618fae3551SRodney W. Grimes cp = line; 9628fae3551SRodney W. Grimes nextfield(&cp, &endcp); 9638fae3551SRodney W. Grimes if (*cp == '#') 9648fae3551SRodney W. Grimes goto nextline; 9658fae3551SRodney W. Grimes 9668fae3551SRodney W. Grimes /* 9678fae3551SRodney W. Grimes * Set defaults. 9688fae3551SRodney W. Grimes */ 9698fae3551SRodney W. Grimes has_host = FALSE; 9708fae3551SRodney W. Grimes anon = def_anon; 9718fae3551SRodney W. Grimes exflags = MNT_EXPORTED; 9728fae3551SRodney W. Grimes got_nondir = 0; 9738fae3551SRodney W. Grimes opt_flags = 0; 9748fae3551SRodney W. Grimes ep = (struct exportlist *)NULL; 9758fae3551SRodney W. Grimes 9768fae3551SRodney W. Grimes /* 9778fae3551SRodney W. Grimes * Create new exports list entry 9788fae3551SRodney W. Grimes */ 9798fae3551SRodney W. Grimes len = endcp-cp; 9808fae3551SRodney W. Grimes tgrp = grp = get_grp(); 9818fae3551SRodney W. Grimes while (len > 0) { 9828fae3551SRodney W. Grimes if (len > RPCMNT_NAMELEN) { 9838fae3551SRodney W. Grimes getexp_err(ep, tgrp); 9848fae3551SRodney W. Grimes goto nextline; 9858fae3551SRodney W. Grimes } 9868fae3551SRodney W. Grimes if (*cp == '-') { 9878fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 9888fae3551SRodney W. Grimes getexp_err(ep, tgrp); 9898fae3551SRodney W. Grimes goto nextline; 9908fae3551SRodney W. Grimes } 9918fae3551SRodney W. Grimes if (debug) 99274853402SPhilippe Charnier warnx("doing opt %s", cp); 9938fae3551SRodney W. Grimes got_nondir = 1; 9948fae3551SRodney W. Grimes if (do_opt(&cp, &endcp, ep, grp, &has_host, 9958fae3551SRodney W. Grimes &exflags, &anon)) { 9968fae3551SRodney W. Grimes getexp_err(ep, tgrp); 9978fae3551SRodney W. Grimes goto nextline; 9988fae3551SRodney W. Grimes } 9998fae3551SRodney W. Grimes } else if (*cp == '/') { 10008fae3551SRodney W. Grimes savedc = *endcp; 10018fae3551SRodney W. Grimes *endcp = '\0'; 10028fae3551SRodney W. Grimes if (check_dirpath(cp) && 10038fae3551SRodney W. Grimes statfs(cp, &fsb) >= 0) { 10048fae3551SRodney W. Grimes if (got_nondir) { 100574853402SPhilippe Charnier syslog(LOG_ERR, "dirs must be first"); 10068fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10078fae3551SRodney W. Grimes goto nextline; 10088fae3551SRodney W. Grimes } 10098fae3551SRodney W. Grimes if (ep) { 10108fae3551SRodney W. Grimes if (ep->ex_fs.val[0] != fsb.f_fsid.val[0] || 10118fae3551SRodney W. Grimes ep->ex_fs.val[1] != fsb.f_fsid.val[1]) { 10128fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10138fae3551SRodney W. Grimes goto nextline; 10148fae3551SRodney W. Grimes } 10158fae3551SRodney W. Grimes } else { 10168fae3551SRodney W. Grimes /* 10178fae3551SRodney W. Grimes * See if this directory is already 10188fae3551SRodney W. Grimes * in the list. 10198fae3551SRodney W. Grimes */ 10208fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 10218fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10228fae3551SRodney W. Grimes ep = get_exp(); 10238fae3551SRodney W. Grimes ep->ex_fs = fsb.f_fsid; 10248fae3551SRodney W. Grimes ep->ex_fsdir = (char *) 10258fae3551SRodney W. Grimes malloc(strlen(fsb.f_mntonname) + 1); 10268fae3551SRodney W. Grimes if (ep->ex_fsdir) 10278fae3551SRodney W. Grimes strcpy(ep->ex_fsdir, 10288fae3551SRodney W. Grimes fsb.f_mntonname); 10298fae3551SRodney W. Grimes else 10308fae3551SRodney W. Grimes out_of_mem(); 10318fae3551SRodney W. Grimes if (debug) 103274853402SPhilippe Charnier warnx("making new ep fs=0x%x,0x%x", 10338fae3551SRodney W. Grimes fsb.f_fsid.val[0], 10348fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 10358fae3551SRodney W. Grimes } else if (debug) 103674853402SPhilippe Charnier warnx("found ep fs=0x%x,0x%x", 10378fae3551SRodney W. Grimes fsb.f_fsid.val[0], 10388fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 10398fae3551SRodney W. Grimes } 10408fae3551SRodney W. Grimes 10418fae3551SRodney W. Grimes /* 10428fae3551SRodney W. Grimes * Add dirpath to export mount point. 10438fae3551SRodney W. Grimes */ 10448fae3551SRodney W. Grimes dirp = add_expdir(&dirhead, cp, len); 10458fae3551SRodney W. Grimes dirplen = len; 10468fae3551SRodney W. Grimes } else { 10478fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10488fae3551SRodney W. Grimes goto nextline; 10498fae3551SRodney W. Grimes } 10508fae3551SRodney W. Grimes *endcp = savedc; 10518fae3551SRodney W. Grimes } else { 10528fae3551SRodney W. Grimes savedc = *endcp; 10538fae3551SRodney W. Grimes *endcp = '\0'; 10548fae3551SRodney W. Grimes got_nondir = 1; 10558fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10568fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10578fae3551SRodney W. Grimes goto nextline; 10588fae3551SRodney W. Grimes } 10598fae3551SRodney W. Grimes 10608fae3551SRodney W. Grimes /* 10618fae3551SRodney W. Grimes * Get the host or netgroup. 10628fae3551SRodney W. Grimes */ 10638fae3551SRodney W. Grimes setnetgrent(cp); 10648fae3551SRodney W. Grimes netgrp = getnetgrent(&hst, &usr, &dom); 10658fae3551SRodney W. Grimes do { 10668fae3551SRodney W. Grimes if (has_host) { 10678fae3551SRodney W. Grimes grp->gr_next = get_grp(); 10688fae3551SRodney W. Grimes grp = grp->gr_next; 10698fae3551SRodney W. Grimes } 10708fae3551SRodney W. Grimes if (netgrp) { 10719d70a156SJoerg Wunsch if (hst == 0) { 107274853402SPhilippe Charnier syslog(LOG_ERR, 107374853402SPhilippe Charnier "null hostname in netgroup %s, skipping", cp); 107401d48801SJoerg Wunsch grp->gr_type = GT_IGNORE; 10759d70a156SJoerg Wunsch } else if (get_host(hst, grp, tgrp)) { 107674853402SPhilippe Charnier syslog(LOG_ERR, 107774853402SPhilippe Charnier "bad host %s in netgroup %s, skipping", hst, cp); 1078a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 10798fae3551SRodney W. Grimes } 10808b5a6d67SBill Paul } else if (get_host(cp, grp, tgrp)) { 108174853402SPhilippe Charnier syslog(LOG_ERR, "bad host %s, skipping", cp); 1082a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 10838fae3551SRodney W. Grimes } 10848fae3551SRodney W. Grimes has_host = TRUE; 10858fae3551SRodney W. Grimes } while (netgrp && getnetgrent(&hst, &usr, &dom)); 10868fae3551SRodney W. Grimes endnetgrent(); 10878fae3551SRodney W. Grimes *endcp = savedc; 10888fae3551SRodney W. Grimes } 10898fae3551SRodney W. Grimes cp = endcp; 10908fae3551SRodney W. Grimes nextfield(&cp, &endcp); 10918fae3551SRodney W. Grimes len = endcp - cp; 10928fae3551SRodney W. Grimes } 10938fae3551SRodney W. Grimes if (check_options(dirhead)) { 10948fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10958fae3551SRodney W. Grimes goto nextline; 10968fae3551SRodney W. Grimes } 10978fae3551SRodney W. Grimes if (!has_host) { 10986d359f31SIan Dowse grp->gr_type = GT_DEFAULT; 10998fae3551SRodney W. Grimes if (debug) 110074853402SPhilippe Charnier warnx("adding a default entry"); 11018fae3551SRodney W. Grimes 11028fae3551SRodney W. Grimes /* 11038fae3551SRodney W. Grimes * Don't allow a network export coincide with a list of 11048fae3551SRodney W. Grimes * host(s) on the same line. 11058fae3551SRodney W. Grimes */ 11068fae3551SRodney W. Grimes } else if ((opt_flags & OP_NET) && tgrp->gr_next) { 110760caaee2SIan Dowse syslog(LOG_ERR, "network/host conflict"); 11088fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11098fae3551SRodney W. Grimes goto nextline; 1110a968cfd8SJonathan Lemon 1111a968cfd8SJonathan Lemon /* 1112a968cfd8SJonathan Lemon * If an export list was specified on this line, make sure 1113a968cfd8SJonathan Lemon * that we have at least one valid entry, otherwise skip it. 1114a968cfd8SJonathan Lemon */ 1115a968cfd8SJonathan Lemon } else { 1116a968cfd8SJonathan Lemon grp = tgrp; 1117a968cfd8SJonathan Lemon while (grp && grp->gr_type == GT_IGNORE) 1118a968cfd8SJonathan Lemon grp = grp->gr_next; 1119a968cfd8SJonathan Lemon if (! grp) { 1120a968cfd8SJonathan Lemon getexp_err(ep, tgrp); 1121a968cfd8SJonathan Lemon goto nextline; 1122a968cfd8SJonathan Lemon } 11238fae3551SRodney W. Grimes } 11248fae3551SRodney W. Grimes 11258fae3551SRodney W. Grimes /* 11268fae3551SRodney W. Grimes * Loop through hosts, pushing the exports into the kernel. 11278fae3551SRodney W. Grimes * After loop, tgrp points to the start of the list and 11288fae3551SRodney W. Grimes * grp points to the last entry in the list. 11298fae3551SRodney W. Grimes */ 11308fae3551SRodney W. Grimes grp = tgrp; 11318fae3551SRodney W. Grimes do { 113201709abfSIan Dowse if (do_mount(ep, grp, exflags, &anon, dirp, dirplen, 113301709abfSIan Dowse &fsb)) { 11348fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11358fae3551SRodney W. Grimes goto nextline; 11368fae3551SRodney W. Grimes } 11378fae3551SRodney W. Grimes } while (grp->gr_next && (grp = grp->gr_next)); 11388fae3551SRodney W. Grimes 11398fae3551SRodney W. Grimes /* 11408fae3551SRodney W. Grimes * Success. Update the data structures. 11418fae3551SRodney W. Grimes */ 11428fae3551SRodney W. Grimes if (has_host) { 1143a62dc406SDoug Rabson hang_dirp(dirhead, tgrp, ep, opt_flags); 11448fae3551SRodney W. Grimes grp->gr_next = grphead; 11458fae3551SRodney W. Grimes grphead = tgrp; 11468fae3551SRodney W. Grimes } else { 11478fae3551SRodney W. Grimes hang_dirp(dirhead, (struct grouplist *)NULL, ep, 1148a62dc406SDoug Rabson opt_flags); 11498fae3551SRodney W. Grimes free_grp(grp); 11508fae3551SRodney W. Grimes } 11518fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 11528fae3551SRodney W. Grimes if ((ep->ex_flag & EX_LINKED) == 0) { 11538fae3551SRodney W. Grimes ep2 = exphead; 11548fae3551SRodney W. Grimes epp = &exphead; 11558fae3551SRodney W. Grimes 11568fae3551SRodney W. Grimes /* 11578fae3551SRodney W. Grimes * Insert in the list in alphabetical order. 11588fae3551SRodney W. Grimes */ 11598fae3551SRodney W. Grimes while (ep2 && strcmp(ep2->ex_fsdir, ep->ex_fsdir) < 0) { 11608fae3551SRodney W. Grimes epp = &ep2->ex_next; 11618fae3551SRodney W. Grimes ep2 = ep2->ex_next; 11628fae3551SRodney W. Grimes } 11638fae3551SRodney W. Grimes if (ep2) 11648fae3551SRodney W. Grimes ep->ex_next = ep2; 11658fae3551SRodney W. Grimes *epp = ep; 11668fae3551SRodney W. Grimes ep->ex_flag |= EX_LINKED; 11678fae3551SRodney W. Grimes } 11688fae3551SRodney W. Grimes nextline: 11698fae3551SRodney W. Grimes if (dirhead) { 11708fae3551SRodney W. Grimes free_dir(dirhead); 11718fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 11728fae3551SRodney W. Grimes } 11738fae3551SRodney W. Grimes } 11748fae3551SRodney W. Grimes fclose(exp_file); 11758fae3551SRodney W. Grimes } 11768fae3551SRodney W. Grimes 11778fae3551SRodney W. Grimes /* 11788fae3551SRodney W. Grimes * Allocate an export list element 11798fae3551SRodney W. Grimes */ 11808fae3551SRodney W. Grimes struct exportlist * 11818fae3551SRodney W. Grimes get_exp() 11828fae3551SRodney W. Grimes { 11838fae3551SRodney W. Grimes struct exportlist *ep; 11848fae3551SRodney W. Grimes 11858fae3551SRodney W. Grimes ep = (struct exportlist *)malloc(sizeof (struct exportlist)); 11868fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) 11878fae3551SRodney W. Grimes out_of_mem(); 118887564113SPeter Wemm memset(ep, 0, sizeof(struct exportlist)); 11898fae3551SRodney W. Grimes return (ep); 11908fae3551SRodney W. Grimes } 11918fae3551SRodney W. Grimes 11928fae3551SRodney W. Grimes /* 11938fae3551SRodney W. Grimes * Allocate a group list element 11948fae3551SRodney W. Grimes */ 11958fae3551SRodney W. Grimes struct grouplist * 11968fae3551SRodney W. Grimes get_grp() 11978fae3551SRodney W. Grimes { 11988fae3551SRodney W. Grimes struct grouplist *gp; 11998fae3551SRodney W. Grimes 12008fae3551SRodney W. Grimes gp = (struct grouplist *)malloc(sizeof (struct grouplist)); 12018fae3551SRodney W. Grimes if (gp == (struct grouplist *)NULL) 12028fae3551SRodney W. Grimes out_of_mem(); 120387564113SPeter Wemm memset(gp, 0, sizeof(struct grouplist)); 12048fae3551SRodney W. Grimes return (gp); 12058fae3551SRodney W. Grimes } 12068fae3551SRodney W. Grimes 12078fae3551SRodney W. Grimes /* 12088fae3551SRodney W. Grimes * Clean up upon an error in get_exportlist(). 12098fae3551SRodney W. Grimes */ 12108fae3551SRodney W. Grimes void 12118fae3551SRodney W. Grimes getexp_err(ep, grp) 12128fae3551SRodney W. Grimes struct exportlist *ep; 12138fae3551SRodney W. Grimes struct grouplist *grp; 12148fae3551SRodney W. Grimes { 12158fae3551SRodney W. Grimes struct grouplist *tgrp; 12168fae3551SRodney W. Grimes 121774853402SPhilippe Charnier syslog(LOG_ERR, "bad exports list line %s", line); 12188fae3551SRodney W. Grimes if (ep && (ep->ex_flag & EX_LINKED) == 0) 12198fae3551SRodney W. Grimes free_exp(ep); 12208fae3551SRodney W. Grimes while (grp) { 12218fae3551SRodney W. Grimes tgrp = grp; 12228fae3551SRodney W. Grimes grp = grp->gr_next; 12238fae3551SRodney W. Grimes free_grp(tgrp); 12248fae3551SRodney W. Grimes } 12258fae3551SRodney W. Grimes } 12268fae3551SRodney W. Grimes 12278fae3551SRodney W. Grimes /* 12288fae3551SRodney W. Grimes * Search the export list for a matching fs. 12298fae3551SRodney W. Grimes */ 12308fae3551SRodney W. Grimes struct exportlist * 12318fae3551SRodney W. Grimes ex_search(fsid) 12328fae3551SRodney W. Grimes fsid_t *fsid; 12338fae3551SRodney W. Grimes { 12348fae3551SRodney W. Grimes struct exportlist *ep; 12358fae3551SRodney W. Grimes 12368fae3551SRodney W. Grimes ep = exphead; 12378fae3551SRodney W. Grimes while (ep) { 12388fae3551SRodney W. Grimes if (ep->ex_fs.val[0] == fsid->val[0] && 12398fae3551SRodney W. Grimes ep->ex_fs.val[1] == fsid->val[1]) 12408fae3551SRodney W. Grimes return (ep); 12418fae3551SRodney W. Grimes ep = ep->ex_next; 12428fae3551SRodney W. Grimes } 12438fae3551SRodney W. Grimes return (ep); 12448fae3551SRodney W. Grimes } 12458fae3551SRodney W. Grimes 12468fae3551SRodney W. Grimes /* 12478fae3551SRodney W. Grimes * Add a directory path to the list. 12488fae3551SRodney W. Grimes */ 12498fae3551SRodney W. Grimes char * 12508fae3551SRodney W. Grimes add_expdir(dpp, cp, len) 12518fae3551SRodney W. Grimes struct dirlist **dpp; 12528fae3551SRodney W. Grimes char *cp; 12538fae3551SRodney W. Grimes int len; 12548fae3551SRodney W. Grimes { 12558fae3551SRodney W. Grimes struct dirlist *dp; 12568fae3551SRodney W. Grimes 12578fae3551SRodney W. Grimes dp = (struct dirlist *)malloc(sizeof (struct dirlist) + len); 125874853402SPhilippe Charnier if (dp == (struct dirlist *)NULL) 125974853402SPhilippe Charnier out_of_mem(); 12608fae3551SRodney W. Grimes dp->dp_left = *dpp; 12618fae3551SRodney W. Grimes dp->dp_right = (struct dirlist *)NULL; 12628fae3551SRodney W. Grimes dp->dp_flag = 0; 12638fae3551SRodney W. Grimes dp->dp_hosts = (struct hostlist *)NULL; 12648fae3551SRodney W. Grimes strcpy(dp->dp_dirp, cp); 12658fae3551SRodney W. Grimes *dpp = dp; 12668fae3551SRodney W. Grimes return (dp->dp_dirp); 12678fae3551SRodney W. Grimes } 12688fae3551SRodney W. Grimes 12698fae3551SRodney W. Grimes /* 12708fae3551SRodney W. Grimes * Hang the dir list element off the dirpath binary tree as required 12718fae3551SRodney W. Grimes * and update the entry for host. 12728fae3551SRodney W. Grimes */ 12738fae3551SRodney W. Grimes void 1274a62dc406SDoug Rabson hang_dirp(dp, grp, ep, flags) 12758fae3551SRodney W. Grimes struct dirlist *dp; 12768fae3551SRodney W. Grimes struct grouplist *grp; 12778fae3551SRodney W. Grimes struct exportlist *ep; 1278a62dc406SDoug Rabson int flags; 12798fae3551SRodney W. Grimes { 12808fae3551SRodney W. Grimes struct hostlist *hp; 12818fae3551SRodney W. Grimes struct dirlist *dp2; 12828fae3551SRodney W. Grimes 1283a62dc406SDoug Rabson if (flags & OP_ALLDIRS) { 12848fae3551SRodney W. Grimes if (ep->ex_defdir) 12858fae3551SRodney W. Grimes free((caddr_t)dp); 12868fae3551SRodney W. Grimes else 12878fae3551SRodney W. Grimes ep->ex_defdir = dp; 1288a62dc406SDoug Rabson if (grp == (struct grouplist *)NULL) { 12898fae3551SRodney W. Grimes ep->ex_defdir->dp_flag |= DP_DEFSET; 1290a62dc406SDoug Rabson } else while (grp) { 12918fae3551SRodney W. Grimes hp = get_ht(); 12928fae3551SRodney W. Grimes hp->ht_grp = grp; 12938fae3551SRodney W. Grimes hp->ht_next = ep->ex_defdir->dp_hosts; 12948fae3551SRodney W. Grimes ep->ex_defdir->dp_hosts = hp; 12958fae3551SRodney W. Grimes grp = grp->gr_next; 12968fae3551SRodney W. Grimes } 12978fae3551SRodney W. Grimes } else { 12988fae3551SRodney W. Grimes 12998fae3551SRodney W. Grimes /* 130074853402SPhilippe Charnier * Loop through the directories adding them to the tree. 13018fae3551SRodney W. Grimes */ 13028fae3551SRodney W. Grimes while (dp) { 13038fae3551SRodney W. Grimes dp2 = dp->dp_left; 1304a62dc406SDoug Rabson add_dlist(&ep->ex_dirl, dp, grp, flags); 13058fae3551SRodney W. Grimes dp = dp2; 13068fae3551SRodney W. Grimes } 13078fae3551SRodney W. Grimes } 13088fae3551SRodney W. Grimes } 13098fae3551SRodney W. Grimes 13108fae3551SRodney W. Grimes /* 13118fae3551SRodney W. Grimes * Traverse the binary tree either updating a node that is already there 13128fae3551SRodney W. Grimes * for the new directory or adding the new node. 13138fae3551SRodney W. Grimes */ 13148fae3551SRodney W. Grimes void 1315a62dc406SDoug Rabson add_dlist(dpp, newdp, grp, flags) 13168fae3551SRodney W. Grimes struct dirlist **dpp; 13178fae3551SRodney W. Grimes struct dirlist *newdp; 13188fae3551SRodney W. Grimes struct grouplist *grp; 1319a62dc406SDoug Rabson int flags; 13208fae3551SRodney W. Grimes { 13218fae3551SRodney W. Grimes struct dirlist *dp; 13228fae3551SRodney W. Grimes struct hostlist *hp; 13238fae3551SRodney W. Grimes int cmp; 13248fae3551SRodney W. Grimes 13258fae3551SRodney W. Grimes dp = *dpp; 13268fae3551SRodney W. Grimes if (dp) { 13278fae3551SRodney W. Grimes cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); 13288fae3551SRodney W. Grimes if (cmp > 0) { 1329a62dc406SDoug Rabson add_dlist(&dp->dp_left, newdp, grp, flags); 13308fae3551SRodney W. Grimes return; 13318fae3551SRodney W. Grimes } else if (cmp < 0) { 1332a62dc406SDoug Rabson add_dlist(&dp->dp_right, newdp, grp, flags); 13338fae3551SRodney W. Grimes return; 13348fae3551SRodney W. Grimes } else 13358fae3551SRodney W. Grimes free((caddr_t)newdp); 13368fae3551SRodney W. Grimes } else { 13378fae3551SRodney W. Grimes dp = newdp; 13388fae3551SRodney W. Grimes dp->dp_left = (struct dirlist *)NULL; 13398fae3551SRodney W. Grimes *dpp = dp; 13408fae3551SRodney W. Grimes } 13418fae3551SRodney W. Grimes if (grp) { 13428fae3551SRodney W. Grimes 13438fae3551SRodney W. Grimes /* 13448fae3551SRodney W. Grimes * Hang all of the host(s) off of the directory point. 13458fae3551SRodney W. Grimes */ 13468fae3551SRodney W. Grimes do { 13478fae3551SRodney W. Grimes hp = get_ht(); 13488fae3551SRodney W. Grimes hp->ht_grp = grp; 13498fae3551SRodney W. Grimes hp->ht_next = dp->dp_hosts; 13508fae3551SRodney W. Grimes dp->dp_hosts = hp; 13518fae3551SRodney W. Grimes grp = grp->gr_next; 13528fae3551SRodney W. Grimes } while (grp); 1353a62dc406SDoug Rabson } else { 13548fae3551SRodney W. Grimes dp->dp_flag |= DP_DEFSET; 1355a62dc406SDoug Rabson } 13568fae3551SRodney W. Grimes } 13578fae3551SRodney W. Grimes 13588fae3551SRodney W. Grimes /* 13598fae3551SRodney W. Grimes * Search for a dirpath on the export point. 13608fae3551SRodney W. Grimes */ 13618fae3551SRodney W. Grimes struct dirlist * 13628360efbdSAlfred Perlstein dirp_search(dp, dirp) 13638fae3551SRodney W. Grimes struct dirlist *dp; 13648360efbdSAlfred Perlstein char *dirp; 13658fae3551SRodney W. Grimes { 13668fae3551SRodney W. Grimes int cmp; 13678fae3551SRodney W. Grimes 13688fae3551SRodney W. Grimes if (dp) { 13698360efbdSAlfred Perlstein cmp = strcmp(dp->dp_dirp, dirp); 13708fae3551SRodney W. Grimes if (cmp > 0) 13718360efbdSAlfred Perlstein return (dirp_search(dp->dp_left, dirp)); 13728fae3551SRodney W. Grimes else if (cmp < 0) 13738360efbdSAlfred Perlstein return (dirp_search(dp->dp_right, dirp)); 13748fae3551SRodney W. Grimes else 13758fae3551SRodney W. Grimes return (dp); 13768fae3551SRodney W. Grimes } 13778fae3551SRodney W. Grimes return (dp); 13788fae3551SRodney W. Grimes } 13798fae3551SRodney W. Grimes 13808fae3551SRodney W. Grimes /* 13818fae3551SRodney W. Grimes * Scan for a host match in a directory tree. 13828fae3551SRodney W. Grimes */ 13838fae3551SRodney W. Grimes int 1384a62dc406SDoug Rabson chk_host(dp, saddr, defsetp, hostsetp) 13858fae3551SRodney W. Grimes struct dirlist *dp; 13868360efbdSAlfred Perlstein struct sockaddr *saddr; 13878fae3551SRodney W. Grimes int *defsetp; 1388a62dc406SDoug Rabson int *hostsetp; 13898fae3551SRodney W. Grimes { 13908fae3551SRodney W. Grimes struct hostlist *hp; 13918fae3551SRodney W. Grimes struct grouplist *grp; 13928360efbdSAlfred Perlstein struct addrinfo *ai; 13938fae3551SRodney W. Grimes 13948fae3551SRodney W. Grimes if (dp) { 13958fae3551SRodney W. Grimes if (dp->dp_flag & DP_DEFSET) 1396a62dc406SDoug Rabson *defsetp = dp->dp_flag; 13978fae3551SRodney W. Grimes hp = dp->dp_hosts; 13988fae3551SRodney W. Grimes while (hp) { 13998fae3551SRodney W. Grimes grp = hp->ht_grp; 14008fae3551SRodney W. Grimes switch (grp->gr_type) { 14018fae3551SRodney W. Grimes case GT_HOST: 14028360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 14038360efbdSAlfred Perlstein for (; ai; ai = ai->ai_next) { 140460caaee2SIan Dowse if (!sacmp(ai->ai_addr, saddr, NULL)) { 14058360efbdSAlfred Perlstein *hostsetp = 14068360efbdSAlfred Perlstein (hp->ht_flag | DP_HOSTSET); 14078fae3551SRodney W. Grimes return (1); 1408a62dc406SDoug Rabson } 14098fae3551SRodney W. Grimes } 14108fae3551SRodney W. Grimes break; 14118fae3551SRodney W. Grimes case GT_NET: 141260caaee2SIan Dowse if (!sacmp(saddr, (struct sockaddr *) 141360caaee2SIan Dowse &grp->gr_ptr.gt_net.nt_net, 141460caaee2SIan Dowse (struct sockaddr *) 141560caaee2SIan Dowse &grp->gr_ptr.gt_net.nt_mask)) { 1416a62dc406SDoug Rabson *hostsetp = (hp->ht_flag | DP_HOSTSET); 14178fae3551SRodney W. Grimes return (1); 1418a62dc406SDoug Rabson } 14198fae3551SRodney W. Grimes break; 142060caaee2SIan Dowse } 14218fae3551SRodney W. Grimes hp = hp->ht_next; 14228fae3551SRodney W. Grimes } 14238fae3551SRodney W. Grimes } 14248fae3551SRodney W. Grimes return (0); 14258fae3551SRodney W. Grimes } 14268fae3551SRodney W. Grimes 14278fae3551SRodney W. Grimes /* 14288fae3551SRodney W. Grimes * Scan tree for a host that matches the address. 14298fae3551SRodney W. Grimes */ 14308fae3551SRodney W. Grimes int 14318fae3551SRodney W. Grimes scan_tree(dp, saddr) 14328fae3551SRodney W. Grimes struct dirlist *dp; 14338360efbdSAlfred Perlstein struct sockaddr *saddr; 14348fae3551SRodney W. Grimes { 1435a62dc406SDoug Rabson int defset, hostset; 14368fae3551SRodney W. Grimes 14378fae3551SRodney W. Grimes if (dp) { 14388fae3551SRodney W. Grimes if (scan_tree(dp->dp_left, saddr)) 14398fae3551SRodney W. Grimes return (1); 1440a62dc406SDoug Rabson if (chk_host(dp, saddr, &defset, &hostset)) 14418fae3551SRodney W. Grimes return (1); 14428fae3551SRodney W. Grimes if (scan_tree(dp->dp_right, saddr)) 14438fae3551SRodney W. Grimes return (1); 14448fae3551SRodney W. Grimes } 14458fae3551SRodney W. Grimes return (0); 14468fae3551SRodney W. Grimes } 14478fae3551SRodney W. Grimes 14488fae3551SRodney W. Grimes /* 14498fae3551SRodney W. Grimes * Traverse the dirlist tree and free it up. 14508fae3551SRodney W. Grimes */ 14518fae3551SRodney W. Grimes void 14528fae3551SRodney W. Grimes free_dir(dp) 14538fae3551SRodney W. Grimes struct dirlist *dp; 14548fae3551SRodney W. Grimes { 14558fae3551SRodney W. Grimes 14568fae3551SRodney W. Grimes if (dp) { 14578fae3551SRodney W. Grimes free_dir(dp->dp_left); 14588fae3551SRodney W. Grimes free_dir(dp->dp_right); 14598fae3551SRodney W. Grimes free_host(dp->dp_hosts); 14608fae3551SRodney W. Grimes free((caddr_t)dp); 14618fae3551SRodney W. Grimes } 14628fae3551SRodney W. Grimes } 14638fae3551SRodney W. Grimes 14648fae3551SRodney W. Grimes /* 14658fae3551SRodney W. Grimes * Parse the option string and update fields. 14668fae3551SRodney W. Grimes * Option arguments may either be -<option>=<value> or 14678fae3551SRodney W. Grimes * -<option> <value> 14688fae3551SRodney W. Grimes */ 14698fae3551SRodney W. Grimes int 14708fae3551SRodney W. Grimes do_opt(cpp, endcpp, ep, grp, has_hostp, exflagsp, cr) 14718fae3551SRodney W. Grimes char **cpp, **endcpp; 14728fae3551SRodney W. Grimes struct exportlist *ep; 14738fae3551SRodney W. Grimes struct grouplist *grp; 14748fae3551SRodney W. Grimes int *has_hostp; 14758fae3551SRodney W. Grimes int *exflagsp; 1476c0511d3bSBrian Feldman struct xucred *cr; 14778fae3551SRodney W. Grimes { 14788fae3551SRodney W. Grimes char *cpoptarg, *cpoptend; 14798fae3551SRodney W. Grimes char *cp, *endcp, *cpopt, savedc, savedc2; 14808fae3551SRodney W. Grimes int allflag, usedarg; 14818fae3551SRodney W. Grimes 1482cb479b11SAlfred Perlstein savedc2 = '\0'; 14838fae3551SRodney W. Grimes cpopt = *cpp; 14848fae3551SRodney W. Grimes cpopt++; 14858fae3551SRodney W. Grimes cp = *endcpp; 14868fae3551SRodney W. Grimes savedc = *cp; 14878fae3551SRodney W. Grimes *cp = '\0'; 14888fae3551SRodney W. Grimes while (cpopt && *cpopt) { 14898fae3551SRodney W. Grimes allflag = 1; 14908fae3551SRodney W. Grimes usedarg = -2; 149174853402SPhilippe Charnier if ((cpoptend = strchr(cpopt, ','))) { 14928fae3551SRodney W. Grimes *cpoptend++ = '\0'; 149374853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 14948fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 14958fae3551SRodney W. Grimes } else { 149674853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 14978fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 14988fae3551SRodney W. Grimes else { 14998fae3551SRodney W. Grimes *cp = savedc; 15008fae3551SRodney W. Grimes nextfield(&cp, &endcp); 15018fae3551SRodney W. Grimes **endcpp = '\0'; 15028fae3551SRodney W. Grimes if (endcp > cp && *cp != '-') { 15038fae3551SRodney W. Grimes cpoptarg = cp; 15048fae3551SRodney W. Grimes savedc2 = *endcp; 15058fae3551SRodney W. Grimes *endcp = '\0'; 15068fae3551SRodney W. Grimes usedarg = 0; 15078fae3551SRodney W. Grimes } 15088fae3551SRodney W. Grimes } 15098fae3551SRodney W. Grimes } 15108fae3551SRodney W. Grimes if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 15118fae3551SRodney W. Grimes *exflagsp |= MNT_EXRDONLY; 15128fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "maproot") || 15138fae3551SRodney W. Grimes !(allflag = strcmp(cpopt, "mapall")) || 15148fae3551SRodney W. Grimes !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) { 15158fae3551SRodney W. Grimes usedarg++; 15168fae3551SRodney W. Grimes parsecred(cpoptarg, cr); 15178fae3551SRodney W. Grimes if (allflag == 0) { 15188fae3551SRodney W. Grimes *exflagsp |= MNT_EXPORTANON; 15198fae3551SRodney W. Grimes opt_flags |= OP_MAPALL; 15208fae3551SRodney W. Grimes } else 15218fae3551SRodney W. Grimes opt_flags |= OP_MAPROOT; 15228fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "mask") || 15238fae3551SRodney W. Grimes !strcmp(cpopt, "m"))) { 15248fae3551SRodney W. Grimes if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { 152574853402SPhilippe Charnier syslog(LOG_ERR, "bad mask: %s", cpoptarg); 15268fae3551SRodney W. Grimes return (1); 15278fae3551SRodney W. Grimes } 15288fae3551SRodney W. Grimes usedarg++; 15298fae3551SRodney W. Grimes opt_flags |= OP_MASK; 15308fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "network") || 15318fae3551SRodney W. Grimes !strcmp(cpopt, "n"))) { 15328360efbdSAlfred Perlstein if (strchr(cpoptarg, '/') != NULL) { 15338360efbdSAlfred Perlstein if (debug) 15348360efbdSAlfred Perlstein fprintf(stderr, "setting OP_MASKLEN\n"); 15358360efbdSAlfred Perlstein opt_flags |= OP_MASKLEN; 15368360efbdSAlfred Perlstein } 15378fae3551SRodney W. Grimes if (grp->gr_type != GT_NULL) { 153874853402SPhilippe Charnier syslog(LOG_ERR, "network/host conflict"); 15398fae3551SRodney W. Grimes return (1); 15408fae3551SRodney W. Grimes } else if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 0)) { 154174853402SPhilippe Charnier syslog(LOG_ERR, "bad net: %s", cpoptarg); 15428fae3551SRodney W. Grimes return (1); 15438fae3551SRodney W. Grimes } 15448fae3551SRodney W. Grimes grp->gr_type = GT_NET; 15458fae3551SRodney W. Grimes *has_hostp = 1; 15468fae3551SRodney W. Grimes usedarg++; 15478fae3551SRodney W. Grimes opt_flags |= OP_NET; 15488fae3551SRodney W. Grimes } else if (!strcmp(cpopt, "alldirs")) { 15498fae3551SRodney W. Grimes opt_flags |= OP_ALLDIRS; 1550cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "public")) { 1551cb3923e0SDoug Rabson *exflagsp |= MNT_EXPUBLIC; 1552cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "webnfs")) { 1553cb3923e0SDoug Rabson *exflagsp |= (MNT_EXPUBLIC|MNT_EXRDONLY|MNT_EXPORTANON); 1554cb3923e0SDoug Rabson opt_flags |= OP_MAPALL; 1555cb3923e0SDoug Rabson } else if (cpoptarg && !strcmp(cpopt, "index")) { 1556cb3923e0SDoug Rabson ep->ex_indexfile = strdup(cpoptarg); 15578fae3551SRodney W. Grimes } else { 155874853402SPhilippe Charnier syslog(LOG_ERR, "bad opt %s", cpopt); 15598fae3551SRodney W. Grimes return (1); 15608fae3551SRodney W. Grimes } 15618fae3551SRodney W. Grimes if (usedarg >= 0) { 15628fae3551SRodney W. Grimes *endcp = savedc2; 15638fae3551SRodney W. Grimes **endcpp = savedc; 15648fae3551SRodney W. Grimes if (usedarg > 0) { 15658fae3551SRodney W. Grimes *cpp = cp; 15668fae3551SRodney W. Grimes *endcpp = endcp; 15678fae3551SRodney W. Grimes } 15688fae3551SRodney W. Grimes return (0); 15698fae3551SRodney W. Grimes } 15708fae3551SRodney W. Grimes cpopt = cpoptend; 15718fae3551SRodney W. Grimes } 15728fae3551SRodney W. Grimes **endcpp = savedc; 15738fae3551SRodney W. Grimes return (0); 15748fae3551SRodney W. Grimes } 15758fae3551SRodney W. Grimes 15768fae3551SRodney W. Grimes /* 15778fae3551SRodney W. Grimes * Translate a character string to the corresponding list of network 15788fae3551SRodney W. Grimes * addresses for a hostname. 15798fae3551SRodney W. Grimes */ 15808fae3551SRodney W. Grimes int 15818b5a6d67SBill Paul get_host(cp, grp, tgrp) 15828fae3551SRodney W. Grimes char *cp; 15838fae3551SRodney W. Grimes struct grouplist *grp; 15848b5a6d67SBill Paul struct grouplist *tgrp; 15858fae3551SRodney W. Grimes { 15868b5a6d67SBill Paul struct grouplist *checkgrp; 158701709abfSIan Dowse struct addrinfo *ai, *tai, hints; 15888360efbdSAlfred Perlstein int ecode; 15898360efbdSAlfred Perlstein char host[NI_MAXHOST]; 15908fae3551SRodney W. Grimes 15918360efbdSAlfred Perlstein if (grp->gr_type != GT_NULL) { 15928360efbdSAlfred Perlstein syslog(LOG_ERR, "Bad netgroup type for ip host %s", cp); 15938fae3551SRodney W. Grimes return (1); 15948fae3551SRodney W. Grimes } 15958360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 15968360efbdSAlfred Perlstein hints.ai_flags = AI_CANONNAME; 15978360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_UDP; 15988360efbdSAlfred Perlstein ecode = getaddrinfo(cp, NULL, &hints, &ai); 15998360efbdSAlfred Perlstein if (ecode != 0) { 160001709abfSIan Dowse syslog(LOG_ERR,"can't get address info for host %s", cp); 16018360efbdSAlfred Perlstein return 1; 16028fae3551SRodney W. Grimes } 16038360efbdSAlfred Perlstein grp->gr_ptr.gt_addrinfo = ai; 16048360efbdSAlfred Perlstein while (ai != NULL) { 16058360efbdSAlfred Perlstein if (ai->ai_canonname == NULL) { 16068360efbdSAlfred Perlstein if (getnameinfo(ai->ai_addr, ai->ai_addrlen, host, 16078360efbdSAlfred Perlstein sizeof host, NULL, 0, ninumeric) != 0) 16088360efbdSAlfred Perlstein strlcpy(host, "?", sizeof(host)); 16098360efbdSAlfred Perlstein ai->ai_canonname = strdup(host); 16108360efbdSAlfred Perlstein ai->ai_flags |= AI_CANONNAME; 16116d359f31SIan Dowse } 16128fae3551SRodney W. Grimes if (debug) 161301709abfSIan Dowse fprintf(stderr, "got host %s\n", ai->ai_canonname); 161401709abfSIan Dowse /* 161501709abfSIan Dowse * Sanity check: make sure we don't already have an entry 161601709abfSIan Dowse * for this host in the grouplist. 161701709abfSIan Dowse */ 161801709abfSIan Dowse for (checkgrp = tgrp; checkgrp != NULL; 161901709abfSIan Dowse checkgrp = checkgrp->gr_next) { 162001709abfSIan Dowse if (checkgrp->gr_type != GT_HOST) 162101709abfSIan Dowse continue; 162201709abfSIan Dowse for (tai = checkgrp->gr_ptr.gt_addrinfo; tai != NULL; 162301709abfSIan Dowse tai = tai->ai_next) { 162460caaee2SIan Dowse if (sacmp(tai->ai_addr, ai->ai_addr, NULL) != 0) 162501709abfSIan Dowse continue; 162601709abfSIan Dowse if (debug) 162701709abfSIan Dowse fprintf(stderr, 162801709abfSIan Dowse "ignoring duplicate host %s\n", 162901709abfSIan Dowse ai->ai_canonname); 163001709abfSIan Dowse grp->gr_type = GT_IGNORE; 163101709abfSIan Dowse return (0); 163201709abfSIan Dowse } 163301709abfSIan Dowse } 16348360efbdSAlfred Perlstein ai = ai->ai_next; 16358360efbdSAlfred Perlstein } 163601709abfSIan Dowse grp->gr_type = GT_HOST; 16378fae3551SRodney W. Grimes return (0); 16388fae3551SRodney W. Grimes } 16398fae3551SRodney W. Grimes 16408fae3551SRodney W. Grimes /* 16418fae3551SRodney W. Grimes * Free up an exports list component 16428fae3551SRodney W. Grimes */ 16438fae3551SRodney W. Grimes void 16448fae3551SRodney W. Grimes free_exp(ep) 16458fae3551SRodney W. Grimes struct exportlist *ep; 16468fae3551SRodney W. Grimes { 16478fae3551SRodney W. Grimes 16488fae3551SRodney W. Grimes if (ep->ex_defdir) { 16498fae3551SRodney W. Grimes free_host(ep->ex_defdir->dp_hosts); 16508fae3551SRodney W. Grimes free((caddr_t)ep->ex_defdir); 16518fae3551SRodney W. Grimes } 16528fae3551SRodney W. Grimes if (ep->ex_fsdir) 16538fae3551SRodney W. Grimes free(ep->ex_fsdir); 1654cb3923e0SDoug Rabson if (ep->ex_indexfile) 1655cb3923e0SDoug Rabson free(ep->ex_indexfile); 16568fae3551SRodney W. Grimes free_dir(ep->ex_dirl); 16578fae3551SRodney W. Grimes free((caddr_t)ep); 16588fae3551SRodney W. Grimes } 16598fae3551SRodney W. Grimes 16608fae3551SRodney W. Grimes /* 16618fae3551SRodney W. Grimes * Free hosts. 16628fae3551SRodney W. Grimes */ 16638fae3551SRodney W. Grimes void 16648fae3551SRodney W. Grimes free_host(hp) 16658fae3551SRodney W. Grimes struct hostlist *hp; 16668fae3551SRodney W. Grimes { 16678fae3551SRodney W. Grimes struct hostlist *hp2; 16688fae3551SRodney W. Grimes 16698fae3551SRodney W. Grimes while (hp) { 16708fae3551SRodney W. Grimes hp2 = hp; 16718fae3551SRodney W. Grimes hp = hp->ht_next; 16728fae3551SRodney W. Grimes free((caddr_t)hp2); 16738fae3551SRodney W. Grimes } 16748fae3551SRodney W. Grimes } 16758fae3551SRodney W. Grimes 16768fae3551SRodney W. Grimes struct hostlist * 16778fae3551SRodney W. Grimes get_ht() 16788fae3551SRodney W. Grimes { 16798fae3551SRodney W. Grimes struct hostlist *hp; 16808fae3551SRodney W. Grimes 16818fae3551SRodney W. Grimes hp = (struct hostlist *)malloc(sizeof (struct hostlist)); 16828fae3551SRodney W. Grimes if (hp == (struct hostlist *)NULL) 16838fae3551SRodney W. Grimes out_of_mem(); 16848fae3551SRodney W. Grimes hp->ht_next = (struct hostlist *)NULL; 1685a62dc406SDoug Rabson hp->ht_flag = 0; 16868fae3551SRodney W. Grimes return (hp); 16878fae3551SRodney W. Grimes } 16888fae3551SRodney W. Grimes 16898fae3551SRodney W. Grimes /* 16908fae3551SRodney W. Grimes * Out of memory, fatal 16918fae3551SRodney W. Grimes */ 16928fae3551SRodney W. Grimes void 16938fae3551SRodney W. Grimes out_of_mem() 16948fae3551SRodney W. Grimes { 16958fae3551SRodney W. Grimes 169674853402SPhilippe Charnier syslog(LOG_ERR, "out of memory"); 16978fae3551SRodney W. Grimes exit(2); 16988fae3551SRodney W. Grimes } 16998fae3551SRodney W. Grimes 17008fae3551SRodney W. Grimes /* 17018fae3551SRodney W. Grimes * Do the mount syscall with the update flag to push the export info into 17028fae3551SRodney W. Grimes * the kernel. 17038fae3551SRodney W. Grimes */ 17048fae3551SRodney W. Grimes int 17058fae3551SRodney W. Grimes do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb) 17068fae3551SRodney W. Grimes struct exportlist *ep; 17078fae3551SRodney W. Grimes struct grouplist *grp; 17088fae3551SRodney W. Grimes int exflags; 1709c0511d3bSBrian Feldman struct xucred *anoncrp; 17108fae3551SRodney W. Grimes char *dirp; 17118fae3551SRodney W. Grimes int dirplen; 17128fae3551SRodney W. Grimes struct statfs *fsb; 17138fae3551SRodney W. Grimes { 1714f93caef2SIan Dowse struct statfs fsb1; 17158360efbdSAlfred Perlstein struct addrinfo *ai; 171660caaee2SIan Dowse struct export_args *eap; 17178360efbdSAlfred Perlstein char *cp = NULL; 17188fae3551SRodney W. Grimes int done; 17198fae3551SRodney W. Grimes char savedc = '\0'; 17208fae3551SRodney W. Grimes union { 17218fae3551SRodney W. Grimes struct ufs_args ua; 17228fae3551SRodney W. Grimes struct iso_args ia; 1723a62dc406SDoug Rabson struct msdosfs_args da; 17249300c696SSemen Ustimenko struct ntfs_args na; 17258fae3551SRodney W. Grimes } args; 17268fae3551SRodney W. Grimes 172760caaee2SIan Dowse bzero(&args, sizeof args); 172860caaee2SIan Dowse /* XXX, we assume that all xx_args look like ufs_args. */ 17298fae3551SRodney W. Grimes args.ua.fspec = 0; 173060caaee2SIan Dowse eap = &args.ua.export; 173160caaee2SIan Dowse 173260caaee2SIan Dowse eap->ex_flags = exflags; 173360caaee2SIan Dowse eap->ex_anon = *anoncrp; 173460caaee2SIan Dowse eap->ex_indexfile = ep->ex_indexfile; 17356d359f31SIan Dowse if (grp->gr_type == GT_HOST) 17368360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 17376d359f31SIan Dowse else 17386d359f31SIan Dowse ai = NULL; 17398fae3551SRodney W. Grimes done = FALSE; 17408fae3551SRodney W. Grimes while (!done) { 17418fae3551SRodney W. Grimes switch (grp->gr_type) { 17428fae3551SRodney W. Grimes case GT_HOST: 17436d359f31SIan Dowse if (ai->ai_addr->sa_family == AF_INET6 && have_v6 == 0) 17448360efbdSAlfred Perlstein goto skip; 174560caaee2SIan Dowse eap->ex_addr = ai->ai_addr; 174660caaee2SIan Dowse eap->ex_addrlen = ai->ai_addrlen; 174760caaee2SIan Dowse eap->ex_masklen = 0; 17488fae3551SRodney W. Grimes break; 17498fae3551SRodney W. Grimes case GT_NET: 175060caaee2SIan Dowse if (grp->gr_ptr.gt_net.nt_net.ss_family == AF_INET6 && 17518360efbdSAlfred Perlstein have_v6 == 0) 17528360efbdSAlfred Perlstein goto skip; 175360caaee2SIan Dowse eap->ex_addr = 175460caaee2SIan Dowse (struct sockaddr *)&grp->gr_ptr.gt_net.nt_net; 175560caaee2SIan Dowse eap->ex_addrlen = args.ua.export.ex_addr->sa_len; 175660caaee2SIan Dowse eap->ex_mask = 175760caaee2SIan Dowse (struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask; 175860caaee2SIan Dowse eap->ex_masklen = args.ua.export.ex_mask->sa_len; 17598fae3551SRodney W. Grimes break; 17606d359f31SIan Dowse case GT_DEFAULT: 176160caaee2SIan Dowse eap->ex_addr = NULL; 176260caaee2SIan Dowse eap->ex_addrlen = 0; 176360caaee2SIan Dowse eap->ex_mask = NULL; 176460caaee2SIan Dowse eap->ex_masklen = 0; 17656d359f31SIan Dowse break; 17668b5a6d67SBill Paul case GT_IGNORE: 17678b5a6d67SBill Paul return(0); 17688b5a6d67SBill Paul break; 17698fae3551SRodney W. Grimes default: 177074853402SPhilippe Charnier syslog(LOG_ERR, "bad grouptype"); 17718fae3551SRodney W. Grimes if (cp) 17728fae3551SRodney W. Grimes *cp = savedc; 17738fae3551SRodney W. Grimes return (1); 17748fae3551SRodney W. Grimes }; 17758fae3551SRodney W. Grimes 17768fae3551SRodney W. Grimes /* 17778fae3551SRodney W. Grimes * XXX: 17788fae3551SRodney W. Grimes * Maybe I should just use the fsb->f_mntonname path instead 17798fae3551SRodney W. Grimes * of looping back up the dirp to the mount point?? 17808fae3551SRodney W. Grimes * Also, needs to know how to export all types of local 178187564113SPeter Wemm * exportable file systems and not just "ufs". 17828fae3551SRodney W. Grimes */ 1783a62dc406SDoug Rabson while (mount(fsb->f_fstypename, dirp, 17848fae3551SRodney W. Grimes fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) { 17858fae3551SRodney W. Grimes if (cp) 17868fae3551SRodney W. Grimes *cp-- = savedc; 17878fae3551SRodney W. Grimes else 17888fae3551SRodney W. Grimes cp = dirp + dirplen - 1; 17898fae3551SRodney W. Grimes if (errno == EPERM) { 179001709abfSIan Dowse if (debug) 179101709abfSIan Dowse warnx("can't change attributes for %s", 179201709abfSIan Dowse dirp); 17938fae3551SRodney W. Grimes syslog(LOG_ERR, 179474853402SPhilippe Charnier "can't change attributes for %s", dirp); 17958fae3551SRodney W. Grimes return (1); 17968fae3551SRodney W. Grimes } 17978fae3551SRodney W. Grimes if (opt_flags & OP_ALLDIRS) { 179874853402SPhilippe Charnier syslog(LOG_ERR, "could not remount %s: %m", 17993980ac4fSGarrett Wollman dirp); 18008fae3551SRodney W. Grimes return (1); 18018fae3551SRodney W. Grimes } 18028fae3551SRodney W. Grimes /* back up over the last component */ 18038fae3551SRodney W. Grimes while (*cp == '/' && cp > dirp) 18048fae3551SRodney W. Grimes cp--; 18058fae3551SRodney W. Grimes while (*(cp - 1) != '/' && cp > dirp) 18068fae3551SRodney W. Grimes cp--; 18078fae3551SRodney W. Grimes if (cp == dirp) { 18088fae3551SRodney W. Grimes if (debug) 180974853402SPhilippe Charnier warnx("mnt unsucc"); 181074853402SPhilippe Charnier syslog(LOG_ERR, "can't export %s", dirp); 18118fae3551SRodney W. Grimes return (1); 18128fae3551SRodney W. Grimes } 18138fae3551SRodney W. Grimes savedc = *cp; 18148fae3551SRodney W. Grimes *cp = '\0'; 1815f93caef2SIan Dowse /* Check that we're still on the same filesystem. */ 1816f93caef2SIan Dowse if (statfs(dirp, &fsb1) != 0 || bcmp(&fsb1.f_fsid, 1817f93caef2SIan Dowse &fsb->f_fsid, sizeof(fsb1.f_fsid)) != 0) { 1818f93caef2SIan Dowse *cp = savedc; 1819f93caef2SIan Dowse syslog(LOG_ERR, "can't export %s", dirp); 1820f93caef2SIan Dowse return (1); 1821f93caef2SIan Dowse } 18228fae3551SRodney W. Grimes } 18238360efbdSAlfred Perlstein skip: 18246d359f31SIan Dowse if (ai != NULL) 18258360efbdSAlfred Perlstein ai = ai->ai_next; 18268360efbdSAlfred Perlstein if (ai == NULL) 18278fae3551SRodney W. Grimes done = TRUE; 18288fae3551SRodney W. Grimes } 18298fae3551SRodney W. Grimes if (cp) 18308fae3551SRodney W. Grimes *cp = savedc; 18318fae3551SRodney W. Grimes return (0); 18328fae3551SRodney W. Grimes } 18338fae3551SRodney W. Grimes 18348fae3551SRodney W. Grimes /* 18358fae3551SRodney W. Grimes * Translate a net address. 183660caaee2SIan Dowse * 183760caaee2SIan Dowse * If `maskflg' is nonzero, then `cp' is a netmask, not a network address. 18388fae3551SRodney W. Grimes */ 18398fae3551SRodney W. Grimes int 18408fae3551SRodney W. Grimes get_net(cp, net, maskflg) 18418fae3551SRodney W. Grimes char *cp; 18428fae3551SRodney W. Grimes struct netmsk *net; 18438fae3551SRodney W. Grimes int maskflg; 18448fae3551SRodney W. Grimes { 1845931c04f1SIan Dowse struct netent *np = NULL; 18468360efbdSAlfred Perlstein char *name, *p, *prefp; 184760caaee2SIan Dowse struct sockaddr_in sin; 1848931c04f1SIan Dowse struct sockaddr *sa = NULL; 18498360efbdSAlfred Perlstein struct addrinfo hints, *ai = NULL; 18508360efbdSAlfred Perlstein char netname[NI_MAXHOST]; 18518360efbdSAlfred Perlstein long preflen; 18528fae3551SRodney W. Grimes 185301709abfSIan Dowse p = prefp = NULL; 18548360efbdSAlfred Perlstein if ((opt_flags & OP_MASKLEN) && !maskflg) { 18558360efbdSAlfred Perlstein p = strchr(cp, '/'); 18568360efbdSAlfred Perlstein *p = '\0'; 18578360efbdSAlfred Perlstein prefp = p + 1; 18588360efbdSAlfred Perlstein } 18598360efbdSAlfred Perlstein 1860931c04f1SIan Dowse /* 1861931c04f1SIan Dowse * Check for a numeric address first. We wish to avoid 1862931c04f1SIan Dowse * possible DNS lookups in getnetbyname(). 1863931c04f1SIan Dowse */ 1864931c04f1SIan Dowse if (isxdigit(*cp) || *cp == ':') { 18658360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 186660caaee2SIan Dowse /* Ensure the mask and the network have the same family. */ 186760caaee2SIan Dowse if (maskflg && (opt_flags & OP_NET)) 186860caaee2SIan Dowse hints.ai_family = net->nt_net.ss_family; 186960caaee2SIan Dowse else if (!maskflg && (opt_flags & OP_HAVEMASK)) 187060caaee2SIan Dowse hints.ai_family = net->nt_mask.ss_family; 187160caaee2SIan Dowse else 18728360efbdSAlfred Perlstein hints.ai_family = AF_UNSPEC; 18738360efbdSAlfred Perlstein hints.ai_flags = AI_NUMERICHOST; 1874931c04f1SIan Dowse if (getaddrinfo(cp, NULL, &hints, &ai) == 0) 1875931c04f1SIan Dowse sa = ai->ai_addr; 1876931c04f1SIan Dowse if (sa != NULL && ai->ai_family == AF_INET) { 18778fae3551SRodney W. Grimes /* 187860caaee2SIan Dowse * The address in `cp' is really a network address, so 187960caaee2SIan Dowse * use inet_network() to re-interpret this correctly. 188060caaee2SIan Dowse * e.g. "127.1" means 127.1.0.0, not 127.0.0.1. 18818fae3551SRodney W. Grimes */ 188260caaee2SIan Dowse bzero(&sin, sizeof sin); 18838360efbdSAlfred Perlstein sin.sin_family = AF_INET; 18848360efbdSAlfred Perlstein sin.sin_len = sizeof sin; 18858360efbdSAlfred Perlstein sin.sin_addr = inet_makeaddr(inet_network(cp), 0); 18868360efbdSAlfred Perlstein if (debug) 188760caaee2SIan Dowse fprintf(stderr, "get_net: v4 addr %s\n", 188860caaee2SIan Dowse inet_ntoa(sin.sin_addr)); 18898360efbdSAlfred Perlstein sa = (struct sockaddr *)&sin; 1890931c04f1SIan Dowse } 1891931c04f1SIan Dowse } 1892931c04f1SIan Dowse if (sa == NULL && (np = getnetbyname(cp)) != NULL) { 1893931c04f1SIan Dowse bzero(&sin, sizeof sin); 1894931c04f1SIan Dowse sin.sin_family = AF_INET; 1895931c04f1SIan Dowse sin.sin_len = sizeof sin; 1896931c04f1SIan Dowse sin.sin_addr = inet_makeaddr(np->n_net, 0); 1897931c04f1SIan Dowse sa = (struct sockaddr *)&sin; 1898931c04f1SIan Dowse } 1899931c04f1SIan Dowse if (sa == NULL) 19008360efbdSAlfred Perlstein goto fail; 19018360efbdSAlfred Perlstein 190260caaee2SIan Dowse if (maskflg) { 190360caaee2SIan Dowse /* The specified sockaddr is a mask. */ 190460caaee2SIan Dowse if (checkmask(sa) != 0) 19058360efbdSAlfred Perlstein goto fail; 190660caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 190760caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 190860caaee2SIan Dowse } else { 190960caaee2SIan Dowse /* The specified sockaddr is a network address. */ 191060caaee2SIan Dowse bcopy(sa, &net->nt_net, sa->sa_len); 19110f4b7baaSPaul Traina 191260caaee2SIan Dowse /* Get a network name for the export list. */ 191360caaee2SIan Dowse if (np) { 191460caaee2SIan Dowse name = np->n_name; 191560caaee2SIan Dowse } else if (getnameinfo(sa, sa->sa_len, netname, sizeof netname, 191660caaee2SIan Dowse NULL, 0, ninumeric) == 0) { 191760caaee2SIan Dowse name = netname; 191860caaee2SIan Dowse } else { 191960caaee2SIan Dowse goto fail; 192060caaee2SIan Dowse } 192160caaee2SIan Dowse if ((net->nt_name = strdup(name)) == NULL) 192260caaee2SIan Dowse out_of_mem(); 192360caaee2SIan Dowse 192460caaee2SIan Dowse /* 192560caaee2SIan Dowse * Extract a mask from either a "/<masklen>" suffix, or 192660caaee2SIan Dowse * from the class of an IPv4 address. 192760caaee2SIan Dowse */ 19288360efbdSAlfred Perlstein if (opt_flags & OP_MASKLEN) { 19298360efbdSAlfred Perlstein preflen = strtol(prefp, NULL, 10); 193060caaee2SIan Dowse if (preflen < 0L || preflen == LONG_MAX) 19318360efbdSAlfred Perlstein goto fail; 193260caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 193360caaee2SIan Dowse if (makemask(&net->nt_mask, (int)preflen) != 0) 193460caaee2SIan Dowse goto fail; 193560caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 19368360efbdSAlfred Perlstein *p = '/'; 193760caaee2SIan Dowse } else if (sa->sa_family == AF_INET && 193860caaee2SIan Dowse (opt_flags & OP_MASK) == 0) { 193960caaee2SIan Dowse in_addr_t addr; 19408360efbdSAlfred Perlstein 194160caaee2SIan Dowse addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; 194260caaee2SIan Dowse if (IN_CLASSA(addr)) 194360caaee2SIan Dowse preflen = 8; 194460caaee2SIan Dowse else if (IN_CLASSB(addr)) 194560caaee2SIan Dowse preflen = 16; 194660caaee2SIan Dowse else if (IN_CLASSC(addr)) 194760caaee2SIan Dowse preflen = 24; 194860caaee2SIan Dowse else if (IN_CLASSD(addr)) 194960caaee2SIan Dowse preflen = 28; 19508360efbdSAlfred Perlstein else 195160caaee2SIan Dowse preflen = 32; /* XXX */ 195260caaee2SIan Dowse 195360caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 195460caaee2SIan Dowse makemask(&net->nt_mask, (int)preflen); 195560caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 195660caaee2SIan Dowse } 19578360efbdSAlfred Perlstein } 19588360efbdSAlfred Perlstein 19598360efbdSAlfred Perlstein if (ai) 19608360efbdSAlfred Perlstein freeaddrinfo(ai); 19618360efbdSAlfred Perlstein return 0; 19628360efbdSAlfred Perlstein 19638360efbdSAlfred Perlstein fail: 19648360efbdSAlfred Perlstein if (ai) 19658360efbdSAlfred Perlstein freeaddrinfo(ai); 19668360efbdSAlfred Perlstein return 1; 19678fae3551SRodney W. Grimes } 19688fae3551SRodney W. Grimes 19698fae3551SRodney W. Grimes /* 19708fae3551SRodney W. Grimes * Parse out the next white space separated field 19718fae3551SRodney W. Grimes */ 19728fae3551SRodney W. Grimes void 19738fae3551SRodney W. Grimes nextfield(cp, endcp) 19748fae3551SRodney W. Grimes char **cp; 19758fae3551SRodney W. Grimes char **endcp; 19768fae3551SRodney W. Grimes { 19778fae3551SRodney W. Grimes char *p; 19788fae3551SRodney W. Grimes 19798fae3551SRodney W. Grimes p = *cp; 19808fae3551SRodney W. Grimes while (*p == ' ' || *p == '\t') 19818fae3551SRodney W. Grimes p++; 19828fae3551SRodney W. Grimes if (*p == '\n' || *p == '\0') 19838fae3551SRodney W. Grimes *cp = *endcp = p; 19848fae3551SRodney W. Grimes else { 19858fae3551SRodney W. Grimes *cp = p++; 19868fae3551SRodney W. Grimes while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 19878fae3551SRodney W. Grimes p++; 19888fae3551SRodney W. Grimes *endcp = p; 19898fae3551SRodney W. Grimes } 19908fae3551SRodney W. Grimes } 19918fae3551SRodney W. Grimes 19928fae3551SRodney W. Grimes /* 19938fae3551SRodney W. Grimes * Get an exports file line. Skip over blank lines and handle line 19948fae3551SRodney W. Grimes * continuations. 19958fae3551SRodney W. Grimes */ 19968fae3551SRodney W. Grimes int 19978fae3551SRodney W. Grimes get_line() 19988fae3551SRodney W. Grimes { 19998fae3551SRodney W. Grimes char *p, *cp; 20008fae3551SRodney W. Grimes int len; 20018fae3551SRodney W. Grimes int totlen, cont_line; 20028fae3551SRodney W. Grimes 20038fae3551SRodney W. Grimes /* 20048fae3551SRodney W. Grimes * Loop around ignoring blank lines and getting all continuation lines. 20058fae3551SRodney W. Grimes */ 20068fae3551SRodney W. Grimes p = line; 20078fae3551SRodney W. Grimes totlen = 0; 20088fae3551SRodney W. Grimes do { 20098fae3551SRodney W. Grimes if (fgets(p, LINESIZ - totlen, exp_file) == NULL) 20108fae3551SRodney W. Grimes return (0); 20118fae3551SRodney W. Grimes len = strlen(p); 20128fae3551SRodney W. Grimes cp = p + len - 1; 20138fae3551SRodney W. Grimes cont_line = 0; 20148fae3551SRodney W. Grimes while (cp >= p && 20158fae3551SRodney W. Grimes (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '\\')) { 20168fae3551SRodney W. Grimes if (*cp == '\\') 20178fae3551SRodney W. Grimes cont_line = 1; 20188fae3551SRodney W. Grimes cp--; 20198fae3551SRodney W. Grimes len--; 20208fae3551SRodney W. Grimes } 2021376f8390SDima Dorfman if (cont_line) { 2022376f8390SDima Dorfman *++cp = ' '; 2023376f8390SDima Dorfman len++; 2024376f8390SDima Dorfman } 20258fae3551SRodney W. Grimes *++cp = '\0'; 20268fae3551SRodney W. Grimes if (len > 0) { 20278fae3551SRodney W. Grimes totlen += len; 20288fae3551SRodney W. Grimes if (totlen >= LINESIZ) { 202974853402SPhilippe Charnier syslog(LOG_ERR, "exports line too long"); 20308fae3551SRodney W. Grimes exit(2); 20318fae3551SRodney W. Grimes } 20328fae3551SRodney W. Grimes p = cp; 20338fae3551SRodney W. Grimes } 20348fae3551SRodney W. Grimes } while (totlen == 0 || cont_line); 20358fae3551SRodney W. Grimes return (1); 20368fae3551SRodney W. Grimes } 20378fae3551SRodney W. Grimes 20388fae3551SRodney W. Grimes /* 20398fae3551SRodney W. Grimes * Parse a description of a credential. 20408fae3551SRodney W. Grimes */ 20418fae3551SRodney W. Grimes void 20428fae3551SRodney W. Grimes parsecred(namelist, cr) 20438fae3551SRodney W. Grimes char *namelist; 2044c0511d3bSBrian Feldman struct xucred *cr; 20458fae3551SRodney W. Grimes { 20468fae3551SRodney W. Grimes char *name; 20478fae3551SRodney W. Grimes int cnt; 20488fae3551SRodney W. Grimes char *names; 20498fae3551SRodney W. Grimes struct passwd *pw; 20508fae3551SRodney W. Grimes struct group *gr; 20518fae3551SRodney W. Grimes int ngroups, groups[NGROUPS + 1]; 20528fae3551SRodney W. Grimes 205376183f34SDima Dorfman cr->cr_version = XUCRED_VERSION; 20548fae3551SRodney W. Grimes /* 205574853402SPhilippe Charnier * Set up the unprivileged user. 20568fae3551SRodney W. Grimes */ 20578fae3551SRodney W. Grimes cr->cr_uid = -2; 20588fae3551SRodney W. Grimes cr->cr_groups[0] = -2; 20598fae3551SRodney W. Grimes cr->cr_ngroups = 1; 20608fae3551SRodney W. Grimes /* 20618fae3551SRodney W. Grimes * Get the user's password table entry. 20628fae3551SRodney W. Grimes */ 20638fae3551SRodney W. Grimes names = strsep(&namelist, " \t\n"); 20648fae3551SRodney W. Grimes name = strsep(&names, ":"); 20658fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') 20668fae3551SRodney W. Grimes pw = getpwuid(atoi(name)); 20678fae3551SRodney W. Grimes else 20688fae3551SRodney W. Grimes pw = getpwnam(name); 20698fae3551SRodney W. Grimes /* 20708fae3551SRodney W. Grimes * Credentials specified as those of a user. 20718fae3551SRodney W. Grimes */ 20728fae3551SRodney W. Grimes if (names == NULL) { 20738fae3551SRodney W. Grimes if (pw == NULL) { 207474853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 20758fae3551SRodney W. Grimes return; 20768fae3551SRodney W. Grimes } 20778fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 20788fae3551SRodney W. Grimes ngroups = NGROUPS + 1; 20798fae3551SRodney W. Grimes if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) 208074853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 20818fae3551SRodney W. Grimes /* 20828fae3551SRodney W. Grimes * Convert from int's to gid_t's and compress out duplicate 20838fae3551SRodney W. Grimes */ 20848fae3551SRodney W. Grimes cr->cr_ngroups = ngroups - 1; 20858fae3551SRodney W. Grimes cr->cr_groups[0] = groups[0]; 20868fae3551SRodney W. Grimes for (cnt = 2; cnt < ngroups; cnt++) 20878fae3551SRodney W. Grimes cr->cr_groups[cnt - 1] = groups[cnt]; 20888fae3551SRodney W. Grimes return; 20898fae3551SRodney W. Grimes } 20908fae3551SRodney W. Grimes /* 20918fae3551SRodney W. Grimes * Explicit credential specified as a colon separated list: 20928fae3551SRodney W. Grimes * uid:gid:gid:... 20938fae3551SRodney W. Grimes */ 20948fae3551SRodney W. Grimes if (pw != NULL) 20958fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 20968fae3551SRodney W. Grimes else if (isdigit(*name) || *name == '-') 20978fae3551SRodney W. Grimes cr->cr_uid = atoi(name); 20988fae3551SRodney W. Grimes else { 209974853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 21008fae3551SRodney W. Grimes return; 21018fae3551SRodney W. Grimes } 21028fae3551SRodney W. Grimes cr->cr_ngroups = 0; 21038fae3551SRodney W. Grimes while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { 21048fae3551SRodney W. Grimes name = strsep(&names, ":"); 21058fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') { 21068fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = atoi(name); 21078fae3551SRodney W. Grimes } else { 21088fae3551SRodney W. Grimes if ((gr = getgrnam(name)) == NULL) { 210974853402SPhilippe Charnier syslog(LOG_ERR, "unknown group: %s", name); 21108fae3551SRodney W. Grimes continue; 21118fae3551SRodney W. Grimes } 21128fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; 21138fae3551SRodney W. Grimes } 21148fae3551SRodney W. Grimes } 21158fae3551SRodney W. Grimes if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) 211674853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 21178fae3551SRodney W. Grimes } 21188fae3551SRodney W. Grimes 21198fae3551SRodney W. Grimes #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 21208fae3551SRodney W. Grimes /* 21218fae3551SRodney W. Grimes * Routines that maintain the remote mounttab 21228fae3551SRodney W. Grimes */ 21238fae3551SRodney W. Grimes void 21248fae3551SRodney W. Grimes get_mountlist() 21258fae3551SRodney W. Grimes { 21268fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 212787564113SPeter Wemm char *host, *dirp, *cp; 21288fae3551SRodney W. Grimes char str[STRSIZ]; 21298fae3551SRodney W. Grimes FILE *mlfile; 21308fae3551SRodney W. Grimes 21318fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) { 213239539916SBill Fumerola if (errno == ENOENT) 213339539916SBill Fumerola return; 213439539916SBill Fumerola else { 213574853402SPhilippe Charnier syslog(LOG_ERR, "can't open %s", _PATH_RMOUNTLIST); 21368fae3551SRodney W. Grimes return; 21378fae3551SRodney W. Grimes } 213839539916SBill Fumerola } 21398fae3551SRodney W. Grimes mlpp = &mlhead; 21408fae3551SRodney W. Grimes while (fgets(str, STRSIZ, mlfile) != NULL) { 214187564113SPeter Wemm cp = str; 214287564113SPeter Wemm host = strsep(&cp, " \t\n"); 214387564113SPeter Wemm dirp = strsep(&cp, " \t\n"); 214487564113SPeter Wemm if (host == NULL || dirp == NULL) 21458fae3551SRodney W. Grimes continue; 21468fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 214774853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 214874853402SPhilippe Charnier out_of_mem(); 214987564113SPeter Wemm strncpy(mlp->ml_host, host, RPCMNT_NAMELEN); 215087564113SPeter Wemm mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 215187564113SPeter Wemm strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 215287564113SPeter Wemm mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 21538fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 21548fae3551SRodney W. Grimes *mlpp = mlp; 21558fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 21568fae3551SRodney W. Grimes } 21578fae3551SRodney W. Grimes fclose(mlfile); 21588fae3551SRodney W. Grimes } 21598fae3551SRodney W. Grimes 216001709abfSIan Dowse void 216101709abfSIan Dowse del_mlist(char *hostp, char *dirp) 21628fae3551SRodney W. Grimes { 21638fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 21648fae3551SRodney W. Grimes struct mountlist *mlp2; 21658fae3551SRodney W. Grimes FILE *mlfile; 21668fae3551SRodney W. Grimes int fnd = 0; 21678fae3551SRodney W. Grimes 21688fae3551SRodney W. Grimes mlpp = &mlhead; 21698fae3551SRodney W. Grimes mlp = mlhead; 21708fae3551SRodney W. Grimes while (mlp) { 21718fae3551SRodney W. Grimes if (!strcmp(mlp->ml_host, hostp) && 21728fae3551SRodney W. Grimes (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 21738fae3551SRodney W. Grimes fnd = 1; 21748fae3551SRodney W. Grimes mlp2 = mlp; 21758fae3551SRodney W. Grimes *mlpp = mlp = mlp->ml_next; 21768fae3551SRodney W. Grimes free((caddr_t)mlp2); 21778fae3551SRodney W. Grimes } else { 21788fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 21798fae3551SRodney W. Grimes mlp = mlp->ml_next; 21808fae3551SRodney W. Grimes } 21818fae3551SRodney W. Grimes } 21828fae3551SRodney W. Grimes if (fnd) { 21838fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 218474853402SPhilippe Charnier syslog(LOG_ERR,"can't update %s", _PATH_RMOUNTLIST); 21858fae3551SRodney W. Grimes return; 21868fae3551SRodney W. Grimes } 21878fae3551SRodney W. Grimes mlp = mlhead; 21888fae3551SRodney W. Grimes while (mlp) { 21898fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 21908fae3551SRodney W. Grimes mlp = mlp->ml_next; 21918fae3551SRodney W. Grimes } 21928fae3551SRodney W. Grimes fclose(mlfile); 21938fae3551SRodney W. Grimes } 21948fae3551SRodney W. Grimes } 21958fae3551SRodney W. Grimes 21968fae3551SRodney W. Grimes void 21978fae3551SRodney W. Grimes add_mlist(hostp, dirp) 21988fae3551SRodney W. Grimes char *hostp, *dirp; 21998fae3551SRodney W. Grimes { 22008fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 22018fae3551SRodney W. Grimes FILE *mlfile; 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) && !strcmp(mlp->ml_dirp, dirp)) 22078fae3551SRodney W. Grimes return; 22088fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 22098fae3551SRodney W. Grimes mlp = mlp->ml_next; 22108fae3551SRodney W. Grimes } 22118fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 221274853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 221374853402SPhilippe Charnier out_of_mem(); 22148fae3551SRodney W. Grimes strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 22158fae3551SRodney W. Grimes mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 22168fae3551SRodney W. Grimes strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 22178fae3551SRodney W. Grimes mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 22188fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 22198fae3551SRodney W. Grimes *mlpp = mlp; 22208fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 222174853402SPhilippe Charnier syslog(LOG_ERR, "can't update %s", _PATH_RMOUNTLIST); 22228fae3551SRodney W. Grimes return; 22238fae3551SRodney W. Grimes } 22248fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 22258fae3551SRodney W. Grimes fclose(mlfile); 22268fae3551SRodney W. Grimes } 22278fae3551SRodney W. Grimes 22288fae3551SRodney W. Grimes /* 22298fae3551SRodney W. Grimes * Free up a group list. 22308fae3551SRodney W. Grimes */ 22318fae3551SRodney W. Grimes void 22328fae3551SRodney W. Grimes free_grp(grp) 22338fae3551SRodney W. Grimes struct grouplist *grp; 22348fae3551SRodney W. Grimes { 22358fae3551SRodney W. Grimes if (grp->gr_type == GT_HOST) { 22368360efbdSAlfred Perlstein if (grp->gr_ptr.gt_addrinfo != NULL) 22378360efbdSAlfred Perlstein freeaddrinfo(grp->gr_ptr.gt_addrinfo); 22388fae3551SRodney W. Grimes } else if (grp->gr_type == GT_NET) { 22398fae3551SRodney W. Grimes if (grp->gr_ptr.gt_net.nt_name) 22408fae3551SRodney W. Grimes free(grp->gr_ptr.gt_net.nt_name); 22418fae3551SRodney W. Grimes } 22428fae3551SRodney W. Grimes free((caddr_t)grp); 22438fae3551SRodney W. Grimes } 22448fae3551SRodney W. Grimes 22458fae3551SRodney W. Grimes #ifdef DEBUG 22468fae3551SRodney W. Grimes void 22478fae3551SRodney W. Grimes SYSLOG(int pri, const char *fmt, ...) 22488fae3551SRodney W. Grimes { 22498fae3551SRodney W. Grimes va_list ap; 22508fae3551SRodney W. Grimes 22518fae3551SRodney W. Grimes va_start(ap, fmt); 22528fae3551SRodney W. Grimes vfprintf(stderr, fmt, ap); 22538fae3551SRodney W. Grimes va_end(ap); 22548fae3551SRodney W. Grimes } 22558fae3551SRodney W. Grimes #endif /* DEBUG */ 22568fae3551SRodney W. Grimes 22578fae3551SRodney W. Grimes /* 22588fae3551SRodney W. Grimes * Check options for consistency. 22598fae3551SRodney W. Grimes */ 22608fae3551SRodney W. Grimes int 22618fae3551SRodney W. Grimes check_options(dp) 22628fae3551SRodney W. Grimes struct dirlist *dp; 22638fae3551SRodney W. Grimes { 22648fae3551SRodney W. Grimes 22658fae3551SRodney W. Grimes if (dp == (struct dirlist *)NULL) 22668fae3551SRodney W. Grimes return (1); 226791196234SPeter Wemm if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL)) { 226891196234SPeter Wemm syslog(LOG_ERR, "-mapall and -maproot mutually exclusive"); 22698fae3551SRodney W. Grimes return (1); 22708fae3551SRodney W. Grimes } 22718fae3551SRodney W. Grimes if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { 227260caaee2SIan Dowse syslog(LOG_ERR, "-mask requires -network"); 227360caaee2SIan Dowse return (1); 227460caaee2SIan Dowse } 227560caaee2SIan Dowse if ((opt_flags & OP_NET) && (opt_flags & OP_HAVEMASK) == 0) { 227660caaee2SIan Dowse syslog(LOG_ERR, "-network requires mask specification"); 227760caaee2SIan Dowse return (1); 227860caaee2SIan Dowse } 227960caaee2SIan Dowse if ((opt_flags & OP_MASK) && (opt_flags & OP_MASKLEN)) { 228060caaee2SIan Dowse syslog(LOG_ERR, "-mask and /masklen are mutually exclusive"); 22818fae3551SRodney W. Grimes return (1); 22828fae3551SRodney W. Grimes } 22838fae3551SRodney W. Grimes if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { 22846436fcb9SAlexander Langer syslog(LOG_ERR, "-alldirs has multiple directories"); 22858fae3551SRodney W. Grimes return (1); 22868fae3551SRodney W. Grimes } 22878fae3551SRodney W. Grimes return (0); 22888fae3551SRodney W. Grimes } 22898fae3551SRodney W. Grimes 22908fae3551SRodney W. Grimes /* 22918fae3551SRodney W. Grimes * Check an absolute directory path for any symbolic links. Return true 22928fae3551SRodney W. Grimes */ 22938fae3551SRodney W. Grimes int 22948fae3551SRodney W. Grimes check_dirpath(dirp) 22958fae3551SRodney W. Grimes char *dirp; 22968fae3551SRodney W. Grimes { 22978fae3551SRodney W. Grimes char *cp; 22988fae3551SRodney W. Grimes int ret = 1; 22998fae3551SRodney W. Grimes struct stat sb; 23008fae3551SRodney W. Grimes 23018fae3551SRodney W. Grimes cp = dirp + 1; 23028fae3551SRodney W. Grimes while (*cp && ret) { 23038fae3551SRodney W. Grimes if (*cp == '/') { 23048fae3551SRodney W. Grimes *cp = '\0'; 2305a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 23068fae3551SRodney W. Grimes ret = 0; 23078fae3551SRodney W. Grimes *cp = '/'; 23088fae3551SRodney W. Grimes } 23098fae3551SRodney W. Grimes cp++; 23108fae3551SRodney W. Grimes } 2311a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 23128fae3551SRodney W. Grimes ret = 0; 23138fae3551SRodney W. Grimes return (ret); 23148fae3551SRodney W. Grimes } 2315a62dc406SDoug Rabson 231660caaee2SIan Dowse /* 231760caaee2SIan Dowse * Make a netmask according to the specified prefix length. The ss_family 231860caaee2SIan Dowse * and other non-address fields must be initialised before calling this. 231960caaee2SIan Dowse */ 232060caaee2SIan Dowse int 232160caaee2SIan Dowse makemask(struct sockaddr_storage *ssp, int bitlen) 23228360efbdSAlfred Perlstein { 232360caaee2SIan Dowse u_char *p; 232460caaee2SIan Dowse int bits, i, len; 23258360efbdSAlfred Perlstein 232660caaee2SIan Dowse if ((p = sa_rawaddr((struct sockaddr *)ssp, &len)) == NULL) 232760caaee2SIan Dowse return (-1); 232860caaee2SIan Dowse if (bitlen > len * NBBY) 232960caaee2SIan Dowse return (-1); 23308360efbdSAlfred Perlstein 233160caaee2SIan Dowse for (i = 0; i < len; i++) { 233260caaee2SIan Dowse bits = (bitlen > NBBY) ? NBBY : bitlen; 233360caaee2SIan Dowse *p++ = (1 << bits) - 1; 233460caaee2SIan Dowse bitlen -= bits; 23358360efbdSAlfred Perlstein } 23368360efbdSAlfred Perlstein return 0; 23378360efbdSAlfred Perlstein } 23388360efbdSAlfred Perlstein 233960caaee2SIan Dowse /* 234060caaee2SIan Dowse * Check that the sockaddr is a valid netmask. Returns 0 if the mask 234160caaee2SIan Dowse * is acceptable (i.e. of the form 1...10....0). 234260caaee2SIan Dowse */ 234360caaee2SIan Dowse int 234460caaee2SIan Dowse checkmask(struct sockaddr *sa) 23458360efbdSAlfred Perlstein { 234660caaee2SIan Dowse u_char *mask; 234760caaee2SIan Dowse int i, len; 234860caaee2SIan Dowse 234960caaee2SIan Dowse if ((mask = sa_rawaddr(sa, &len)) == NULL) 235060caaee2SIan Dowse return (-1); 235160caaee2SIan Dowse 235260caaee2SIan Dowse for (i = 0; i < len; i++) 235360caaee2SIan Dowse if (mask[i] != 0xff) 235460caaee2SIan Dowse break; 235560caaee2SIan Dowse if (i < len) { 235660caaee2SIan Dowse if (~mask[i] & (u_char)(~mask[i] + 1)) 235760caaee2SIan Dowse return (-1); 235860caaee2SIan Dowse i++; 235960caaee2SIan Dowse } 236060caaee2SIan Dowse for (; i < len; i++) 236160caaee2SIan Dowse if (mask[i] != 0) 236260caaee2SIan Dowse return (-1); 236360caaee2SIan Dowse return (0); 236460caaee2SIan Dowse } 236560caaee2SIan Dowse 236660caaee2SIan Dowse /* 236760caaee2SIan Dowse * Compare two sockaddrs according to a specified mask. Return zero if 236860caaee2SIan Dowse * `sa1' matches `sa2' when filtered by the netmask in `samask'. 236960caaee2SIan Dowse * If samask is NULL, perform a full comparision. 237060caaee2SIan Dowse */ 237160caaee2SIan Dowse int 237260caaee2SIan Dowse sacmp(struct sockaddr *sa1, struct sockaddr *sa2, struct sockaddr *samask) 237360caaee2SIan Dowse { 237460caaee2SIan Dowse unsigned char *p1, *p2, *mask; 237560caaee2SIan Dowse int len, i; 237660caaee2SIan Dowse 237760caaee2SIan Dowse if (sa1->sa_family != sa2->sa_family || 237860caaee2SIan Dowse (p1 = sa_rawaddr(sa1, &len)) == NULL || 237960caaee2SIan Dowse (p2 = sa_rawaddr(sa2, NULL)) == NULL) 238060caaee2SIan Dowse return (1); 238160caaee2SIan Dowse 238260caaee2SIan Dowse switch (sa1->sa_family) { 238360caaee2SIan Dowse case AF_INET6: 238460caaee2SIan Dowse if (((struct sockaddr_in6 *)sa1)->sin6_scope_id != 238560caaee2SIan Dowse ((struct sockaddr_in6 *)sa2)->sin6_scope_id) 238660caaee2SIan Dowse return (1); 238760caaee2SIan Dowse break; 238860caaee2SIan Dowse } 238960caaee2SIan Dowse 239060caaee2SIan Dowse /* Simple binary comparison if no mask specified. */ 239160caaee2SIan Dowse if (samask == NULL) 239260caaee2SIan Dowse return (memcmp(p1, p2, len)); 239360caaee2SIan Dowse 239460caaee2SIan Dowse /* Set up the mask, and do a mask-based comparison. */ 239560caaee2SIan Dowse if (sa1->sa_family != samask->sa_family || 239660caaee2SIan Dowse (mask = sa_rawaddr(samask, NULL)) == NULL) 239760caaee2SIan Dowse return (1); 239860caaee2SIan Dowse 239960caaee2SIan Dowse for (i = 0; i < len; i++) 240060caaee2SIan Dowse if ((p1[i] & mask[i]) != (p2[i] & mask[i])) 240160caaee2SIan Dowse return (1); 240260caaee2SIan Dowse return (0); 240360caaee2SIan Dowse } 240460caaee2SIan Dowse 240560caaee2SIan Dowse /* 240660caaee2SIan Dowse * Return a pointer to the part of the sockaddr that contains the 240760caaee2SIan Dowse * raw address, and set *nbytes to its length in bytes. Returns 240860caaee2SIan Dowse * NULL if the address family is unknown. 240960caaee2SIan Dowse */ 241060caaee2SIan Dowse void * 241160caaee2SIan Dowse sa_rawaddr(struct sockaddr *sa, int *nbytes) { 241260caaee2SIan Dowse void *p; 241360caaee2SIan Dowse int len; 24148360efbdSAlfred Perlstein 24158360efbdSAlfred Perlstein switch (sa->sa_family) { 24168360efbdSAlfred Perlstein case AF_INET: 241760caaee2SIan Dowse len = sizeof(((struct sockaddr_in *)sa)->sin_addr); 241860caaee2SIan Dowse p = &((struct sockaddr_in *)sa)->sin_addr; 24198360efbdSAlfred Perlstein break; 24208360efbdSAlfred Perlstein case AF_INET6: 242160caaee2SIan Dowse len = sizeof(((struct sockaddr_in6 *)sa)->sin6_addr); 242260caaee2SIan Dowse p = &((struct sockaddr_in6 *)sa)->sin6_addr; 24238360efbdSAlfred Perlstein break; 24248360efbdSAlfred Perlstein default: 242560caaee2SIan Dowse p = NULL; 242660caaee2SIan Dowse len = 0; 24278360efbdSAlfred Perlstein } 24288360efbdSAlfred Perlstein 242960caaee2SIan Dowse if (nbytes != NULL) 243060caaee2SIan Dowse *nbytes = len; 243160caaee2SIan Dowse return (p); 24328360efbdSAlfred Perlstein } 24338360efbdSAlfred Perlstein 243469d65572SIan Dowse void 243569d65572SIan Dowse huphandler(int sig) 243669d65572SIan Dowse { 243769d65572SIan Dowse got_sighup = 1; 243869d65572SIan Dowse } 243969d65572SIan Dowse 24408360efbdSAlfred Perlstein void terminate(sig) 24418360efbdSAlfred Perlstein int sig; 24428360efbdSAlfred Perlstein { 24438360efbdSAlfred Perlstein close(mountdlockfd); 24448360efbdSAlfred Perlstein unlink(MOUNTDLOCK); 24457b98a1d6SAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); 24467b98a1d6SAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); 24478360efbdSAlfred Perlstein exit (0); 24488360efbdSAlfred Perlstein } 2449