18fae3551SRodney W. Grimes /* 28fae3551SRodney W. Grimes * Copyright (c) 1989, 1993 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * 58fae3551SRodney W. Grimes * This code is derived from software contributed to Berkeley by 68fae3551SRodney W. Grimes * Herb Hasler and Rick Macklem at The University of Guelph. 78fae3551SRodney W. Grimes * 88fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 98fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 108fae3551SRodney W. Grimes * are met: 118fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 128fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 138fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 148fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 158fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 168fae3551SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 178fae3551SRodney W. Grimes * must display the following acknowledgement: 188fae3551SRodney W. Grimes * This product includes software developed by the University of 198fae3551SRodney W. Grimes * California, Berkeley and its contributors. 208fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 218fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 228fae3551SRodney W. Grimes * without specific prior written permission. 238fae3551SRodney W. Grimes * 248fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 258fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 268fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 278fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 288fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 298fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 308fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 318fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 328fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 338fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 348fae3551SRodney W. Grimes * SUCH DAMAGE. 358fae3551SRodney W. Grimes */ 368fae3551SRodney W. Grimes 378fae3551SRodney W. Grimes #ifndef lint 3874853402SPhilippe Charnier static const char copyright[] = 398fae3551SRodney W. Grimes "@(#) Copyright (c) 1989, 1993\n\ 408fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 41d599144dSGarrett Wollman #endif /*not lint*/ 428fae3551SRodney W. Grimes 4374853402SPhilippe Charnier #if 0 4475201fa4SPhilippe Charnier #ifndef lint 4574853402SPhilippe Charnier static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; 46d599144dSGarrett Wollman #endif /*not lint*/ 4775201fa4SPhilippe Charnier #endif 4875201fa4SPhilippe Charnier 4975201fa4SPhilippe Charnier #include <sys/cdefs.h> 5075201fa4SPhilippe Charnier __FBSDID("$FreeBSD$"); 518fae3551SRodney W. Grimes 528fae3551SRodney W. Grimes #include <sys/param.h> 538fae3551SRodney W. Grimes #include <sys/mount.h> 548360efbdSAlfred Perlstein #include <sys/fcntl.h> 558fae3551SRodney W. Grimes #include <sys/stat.h> 568fae3551SRodney W. Grimes #include <sys/syslog.h> 57394da4c1SGuido van Rooij #include <sys/sysctl.h> 5891ca1a91SIan Dowse #include <sys/linker.h> 5991ca1a91SIan Dowse #include <sys/module.h> 608fae3551SRodney W. Grimes 618fae3551SRodney W. Grimes #include <rpc/rpc.h> 62bcb53b16SMartin Blapp #include <rpc/rpc_com.h> 638fae3551SRodney W. Grimes #include <rpc/pmap_clnt.h> 648360efbdSAlfred Perlstein #include <rpc/pmap_prot.h> 658360efbdSAlfred Perlstein #include <rpcsvc/mount.h> 668fae3551SRodney W. Grimes #include <nfs/rpcv2.h> 67a62dc406SDoug Rabson #include <nfs/nfsproto.h> 6891196234SPeter Wemm #include <nfsserver/nfs.h> 6987564113SPeter Wemm #include <ufs/ufs/ufsmount.h> 701166fb51SRuslan Ermilov #include <fs/msdosfs/msdosfsmount.h> 718a8402d3SRuslan Ermilov #include <fs/ntfs/ntfsmount.h> 7287564113SPeter Wemm #include <isofs/cd9660/cd9660_mount.h> /* XXX need isofs in include */ 738fae3551SRodney W. Grimes 748fae3551SRodney W. Grimes #include <arpa/inet.h> 758fae3551SRodney W. Grimes 768fae3551SRodney W. Grimes #include <ctype.h> 7774853402SPhilippe Charnier #include <err.h> 788fae3551SRodney W. Grimes #include <errno.h> 798fae3551SRodney W. Grimes #include <grp.h> 8089fdc4e1SMike Barcroft #include <limits.h> 818fae3551SRodney W. Grimes #include <netdb.h> 828fae3551SRodney W. Grimes #include <pwd.h> 838fae3551SRodney W. Grimes #include <signal.h> 848fae3551SRodney W. Grimes #include <stdio.h> 858fae3551SRodney W. Grimes #include <stdlib.h> 868fae3551SRodney W. Grimes #include <string.h> 878fae3551SRodney W. Grimes #include <unistd.h> 888fae3551SRodney W. Grimes #include "pathnames.h" 898fae3551SRodney W. Grimes 908fae3551SRodney W. Grimes #ifdef DEBUG 918fae3551SRodney W. Grimes #include <stdarg.h> 928fae3551SRodney W. Grimes #endif 938fae3551SRodney W. Grimes 948360efbdSAlfred Perlstein #ifndef MOUNTDLOCK 958360efbdSAlfred Perlstein #define MOUNTDLOCK "/var/run/mountd.lock" 968360efbdSAlfred Perlstein #endif 978360efbdSAlfred Perlstein 988fae3551SRodney W. Grimes /* 998fae3551SRodney W. Grimes * Structures for keeping the mount list and export list 1008fae3551SRodney W. Grimes */ 1018fae3551SRodney W. Grimes struct mountlist { 1028fae3551SRodney W. Grimes struct mountlist *ml_next; 1038fae3551SRodney W. Grimes char ml_host[RPCMNT_NAMELEN+1]; 1048fae3551SRodney W. Grimes char ml_dirp[RPCMNT_PATHLEN+1]; 1058fae3551SRodney W. Grimes }; 1068fae3551SRodney W. Grimes 1078fae3551SRodney W. Grimes struct dirlist { 1088fae3551SRodney W. Grimes struct dirlist *dp_left; 1098fae3551SRodney W. Grimes struct dirlist *dp_right; 1108fae3551SRodney W. Grimes int dp_flag; 1118fae3551SRodney W. Grimes struct hostlist *dp_hosts; /* List of hosts this dir exported to */ 1128fae3551SRodney W. Grimes char dp_dirp[1]; /* Actually malloc'd to size of dir */ 1138fae3551SRodney W. Grimes }; 1148fae3551SRodney W. Grimes /* dp_flag bits */ 1158fae3551SRodney W. Grimes #define DP_DEFSET 0x1 116a62dc406SDoug Rabson #define DP_HOSTSET 0x2 1178fae3551SRodney W. Grimes 1188fae3551SRodney W. Grimes struct exportlist { 1198fae3551SRodney W. Grimes struct exportlist *ex_next; 1208fae3551SRodney W. Grimes struct dirlist *ex_dirl; 1218fae3551SRodney W. Grimes struct dirlist *ex_defdir; 1228fae3551SRodney W. Grimes int ex_flag; 1238fae3551SRodney W. Grimes fsid_t ex_fs; 1248fae3551SRodney W. Grimes char *ex_fsdir; 125cb3923e0SDoug Rabson char *ex_indexfile; 1268fae3551SRodney W. Grimes }; 1278fae3551SRodney W. Grimes /* ex_flag bits */ 1288fae3551SRodney W. Grimes #define EX_LINKED 0x1 1298fae3551SRodney W. Grimes 1308fae3551SRodney W. Grimes struct netmsk { 1318360efbdSAlfred Perlstein struct sockaddr_storage nt_net; 13260caaee2SIan Dowse struct sockaddr_storage nt_mask; 1338fae3551SRodney W. Grimes char *nt_name; 1348fae3551SRodney W. Grimes }; 1358fae3551SRodney W. Grimes 1368fae3551SRodney W. Grimes union grouptypes { 1378360efbdSAlfred Perlstein struct addrinfo *gt_addrinfo; 1388fae3551SRodney W. Grimes struct netmsk gt_net; 1398fae3551SRodney W. Grimes }; 1408fae3551SRodney W. Grimes 1418fae3551SRodney W. Grimes struct grouplist { 1428fae3551SRodney W. Grimes int gr_type; 1438fae3551SRodney W. Grimes union grouptypes gr_ptr; 1448fae3551SRodney W. Grimes struct grouplist *gr_next; 1458fae3551SRodney W. Grimes }; 1468fae3551SRodney W. Grimes /* Group types */ 1478fae3551SRodney W. Grimes #define GT_NULL 0x0 1488fae3551SRodney W. Grimes #define GT_HOST 0x1 1498fae3551SRodney W. Grimes #define GT_NET 0x2 1506d359f31SIan Dowse #define GT_DEFAULT 0x3 1518b5a6d67SBill Paul #define GT_IGNORE 0x5 1528fae3551SRodney W. Grimes 1538fae3551SRodney W. Grimes struct hostlist { 154a62dc406SDoug Rabson int ht_flag; /* Uses DP_xx bits */ 1558fae3551SRodney W. Grimes struct grouplist *ht_grp; 1568fae3551SRodney W. Grimes struct hostlist *ht_next; 1578fae3551SRodney W. Grimes }; 1588fae3551SRodney W. Grimes 159a62dc406SDoug Rabson struct fhreturn { 160a62dc406SDoug Rabson int fhr_flag; 161a62dc406SDoug Rabson int fhr_vers; 162a62dc406SDoug Rabson nfsfh_t fhr_fh; 163a62dc406SDoug Rabson }; 164a62dc406SDoug Rabson 1658fae3551SRodney W. Grimes /* Global defs */ 16685429990SWarner Losh char *add_expdir(struct dirlist **, char *, int); 16785429990SWarner Losh void add_dlist(struct dirlist **, struct dirlist *, 16885429990SWarner Losh struct grouplist *, int); 16985429990SWarner Losh void add_mlist(char *, char *); 17085429990SWarner Losh int check_dirpath(char *); 17185429990SWarner Losh int check_options(struct dirlist *); 17260caaee2SIan Dowse int checkmask(struct sockaddr *sa); 17385429990SWarner Losh int chk_host(struct dirlist *, struct sockaddr *, int *, int *); 17401709abfSIan Dowse void del_mlist(char *hostp, char *dirp); 17585429990SWarner Losh struct dirlist *dirp_search(struct dirlist *, char *); 17685429990SWarner Losh int do_mount(struct exportlist *, struct grouplist *, int, 17785429990SWarner Losh struct xucred *, char *, int, struct statfs *); 17885429990SWarner Losh int do_opt(char **, char **, struct exportlist *, struct grouplist *, 17985429990SWarner Losh int *, int *, struct xucred *); 18085429990SWarner Losh struct exportlist *ex_search(fsid_t *); 18185429990SWarner Losh struct exportlist *get_exp(void); 18285429990SWarner Losh void free_dir(struct dirlist *); 18385429990SWarner Losh void free_exp(struct exportlist *); 18485429990SWarner Losh void free_grp(struct grouplist *); 18585429990SWarner Losh void free_host(struct hostlist *); 18685429990SWarner Losh void get_exportlist(void); 18785429990SWarner Losh int get_host(char *, struct grouplist *, struct grouplist *); 18885429990SWarner Losh struct hostlist *get_ht(void); 18985429990SWarner Losh int get_line(void); 19085429990SWarner Losh void get_mountlist(void); 19185429990SWarner Losh int get_net(char *, struct netmsk *, int); 19285429990SWarner Losh void getexp_err(struct exportlist *, struct grouplist *); 19385429990SWarner Losh struct grouplist *get_grp(void); 19485429990SWarner Losh void hang_dirp(struct dirlist *, struct grouplist *, 19585429990SWarner Losh struct exportlist *, int); 19669d65572SIan Dowse void huphandler(int sig); 19760caaee2SIan Dowse int makemask(struct sockaddr_storage *ssp, int bitlen); 19885429990SWarner Losh void mntsrv(struct svc_req *, SVCXPRT *); 19985429990SWarner Losh void nextfield(char **, char **); 20085429990SWarner Losh void out_of_mem(void); 20185429990SWarner Losh void parsecred(char *, struct xucred *); 20291acb349SAlfred Perlstein int put_exlist(struct dirlist *, XDR *, struct dirlist *, int *, int); 20360caaee2SIan Dowse void *sa_rawaddr(struct sockaddr *sa, int *nbytes); 20460caaee2SIan Dowse int sacmp(struct sockaddr *sa1, struct sockaddr *sa2, 20560caaee2SIan Dowse struct sockaddr *samask); 20685429990SWarner Losh int scan_tree(struct dirlist *, struct sockaddr *); 20785429990SWarner Losh static void usage(void); 20885429990SWarner Losh int xdr_dir(XDR *, char *); 20985429990SWarner Losh int xdr_explist(XDR *, caddr_t); 21091acb349SAlfred Perlstein int xdr_explist_brief(XDR *, caddr_t); 21185429990SWarner Losh int xdr_fhs(XDR *, caddr_t); 21285429990SWarner Losh int xdr_mlist(XDR *, caddr_t); 21385429990SWarner Losh void terminate(int); 2148fae3551SRodney W. Grimes 2158fae3551SRodney W. Grimes struct exportlist *exphead; 2168fae3551SRodney W. Grimes struct mountlist *mlhead; 2178fae3551SRodney W. Grimes struct grouplist *grphead; 2188fae3551SRodney W. Grimes char exname[MAXPATHLEN]; 219c0511d3bSBrian Feldman struct xucred def_anon = { 22076183f34SDima Dorfman XUCRED_VERSION, 2218fae3551SRodney W. Grimes (uid_t)-2, 2228fae3551SRodney W. Grimes 1, 223c0511d3bSBrian Feldman { (gid_t)-2 }, 224c0511d3bSBrian Feldman NULL 2258fae3551SRodney W. Grimes }; 2262a66cfc5SDoug Rabson int force_v2 = 0; 227a62dc406SDoug Rabson int resvport_only = 1; 228a62dc406SDoug Rabson int dir_only = 1; 229c903443aSPeter Wemm int dolog = 0; 23069d65572SIan Dowse int got_sighup = 0; 2318360efbdSAlfred Perlstein 2328fae3551SRodney W. Grimes int opt_flags; 2338360efbdSAlfred Perlstein static int have_v6 = 1; 2348360efbdSAlfred Perlstein #ifdef NI_WITHSCOPEID 2358360efbdSAlfred Perlstein static const int ninumeric = NI_NUMERICHOST | NI_WITHSCOPEID; 2368360efbdSAlfred Perlstein #else 2378360efbdSAlfred Perlstein static const int ninumeric = NI_NUMERICHOST; 2388360efbdSAlfred Perlstein #endif 2398360efbdSAlfred Perlstein 2408360efbdSAlfred Perlstein int mountdlockfd; 24160caaee2SIan Dowse /* Bits for opt_flags above */ 2428fae3551SRodney W. Grimes #define OP_MAPROOT 0x01 2438fae3551SRodney W. Grimes #define OP_MAPALL 0x02 24491196234SPeter Wemm /* 0x4 free */ 2458fae3551SRodney W. Grimes #define OP_MASK 0x08 2468fae3551SRodney W. Grimes #define OP_NET 0x10 2478fae3551SRodney W. Grimes #define OP_ALLDIRS 0x40 24860caaee2SIan Dowse #define OP_HAVEMASK 0x80 /* A mask was specified or inferred. */ 249288fa14aSJoerg Wunsch #define OP_QUIET 0x100 2508360efbdSAlfred Perlstein #define OP_MASKLEN 0x200 2518fae3551SRodney W. Grimes 2528fae3551SRodney W. Grimes #ifdef DEBUG 2538fae3551SRodney W. Grimes int debug = 1; 25485429990SWarner Losh void SYSLOG(int, const char *, ...) __printflike(2, 3); 2558fae3551SRodney W. Grimes #define syslog SYSLOG 2568fae3551SRodney W. Grimes #else 2578fae3551SRodney W. Grimes int debug = 0; 2588fae3551SRodney W. Grimes #endif 2598fae3551SRodney W. Grimes 2608fae3551SRodney W. Grimes /* 2618fae3551SRodney W. Grimes * Mountd server for NFS mount protocol as described in: 2628fae3551SRodney W. Grimes * NFS: Network File System Protocol Specification, RFC1094, Appendix A 2638fae3551SRodney W. Grimes * The optional arguments are the exports file name 2648fae3551SRodney W. Grimes * default: _PATH_EXPORTS 2658fae3551SRodney W. Grimes * and "-n" to allow nonroot mount. 2668fae3551SRodney W. Grimes */ 2678fae3551SRodney W. Grimes int 2688fae3551SRodney W. Grimes main(argc, argv) 2698fae3551SRodney W. Grimes int argc; 2708fae3551SRodney W. Grimes char **argv; 2718fae3551SRodney W. Grimes { 27269d65572SIan Dowse fd_set readfds; 2738360efbdSAlfred Perlstein SVCXPRT *udptransp, *tcptransp, *udp6transp, *tcp6transp; 2748360efbdSAlfred Perlstein struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf; 2758360efbdSAlfred Perlstein int udpsock, tcpsock, udp6sock, tcp6sock; 2768360efbdSAlfred Perlstein int xcreated = 0, s; 277bcb53b16SMartin Blapp int maxrec = RPC_MAXDATASIZE; 2788360efbdSAlfred Perlstein int one = 1; 27991ca1a91SIan Dowse int c; 280d599144dSGarrett Wollman 28101709abfSIan Dowse udp6conf = tcp6conf = NULL; 28201709abfSIan Dowse udp6sock = tcp6sock = NULL; 2838360efbdSAlfred Perlstein 28401709abfSIan Dowse /* Check that another mountd isn't already running. */ 2858360efbdSAlfred Perlstein if ((mountdlockfd = (open(MOUNTDLOCK, O_RDONLY|O_CREAT, 0444))) == -1) 2868360efbdSAlfred Perlstein err(1, "%s", MOUNTDLOCK); 2878360efbdSAlfred Perlstein 2888360efbdSAlfred Perlstein if(flock(mountdlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) 28975201fa4SPhilippe Charnier errx(1, "another mountd is already running. Aborting"); 2908360efbdSAlfred Perlstein s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 2918360efbdSAlfred Perlstein if (s < 0) 2928360efbdSAlfred Perlstein have_v6 = 0; 2938360efbdSAlfred Perlstein else 2948360efbdSAlfred Perlstein close(s); 2954a0785aaSPeter Wemm if (modfind("nfsserver") < 0) { 2964a0785aaSPeter Wemm /* Not present in kernel, try loading it */ 2974a0785aaSPeter Wemm if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0) 2984a0785aaSPeter Wemm errx(1, "NFS server is not available or loadable"); 299d599144dSGarrett Wollman } 3008fae3551SRodney W. Grimes 301690c488dSGuido van Rooij while ((c = getopt(argc, argv, "2dlnr")) != -1) 3028fae3551SRodney W. Grimes switch (c) { 3032a66cfc5SDoug Rabson case '2': 3042a66cfc5SDoug Rabson force_v2 = 1; 3052a66cfc5SDoug Rabson break; 306a62dc406SDoug Rabson case 'n': 307a62dc406SDoug Rabson resvport_only = 0; 308a62dc406SDoug Rabson break; 309a62dc406SDoug Rabson case 'r': 310a62dc406SDoug Rabson dir_only = 0; 311a62dc406SDoug Rabson break; 3126444ef3bSPoul-Henning Kamp case 'd': 3136444ef3bSPoul-Henning Kamp debug = debug ? 0 : 1; 3146444ef3bSPoul-Henning Kamp break; 315f51631d7SGuido van Rooij case 'l': 316c903443aSPeter Wemm dolog = 1; 317f51631d7SGuido van Rooij break; 3188fae3551SRodney W. Grimes default: 31974853402SPhilippe Charnier usage(); 3208fae3551SRodney W. Grimes }; 3218fae3551SRodney W. Grimes argc -= optind; 3228fae3551SRodney W. Grimes argv += optind; 3238fae3551SRodney W. Grimes grphead = (struct grouplist *)NULL; 3248fae3551SRodney W. Grimes exphead = (struct exportlist *)NULL; 3258fae3551SRodney W. Grimes mlhead = (struct mountlist *)NULL; 3268fae3551SRodney W. Grimes if (argc == 1) { 3278fae3551SRodney W. Grimes strncpy(exname, *argv, MAXPATHLEN-1); 3288fae3551SRodney W. Grimes exname[MAXPATHLEN-1] = '\0'; 3298fae3551SRodney W. Grimes } else 3308fae3551SRodney W. Grimes strcpy(exname, _PATH_EXPORTS); 3318fae3551SRodney W. Grimes openlog("mountd", LOG_PID, LOG_DAEMON); 3328fae3551SRodney W. Grimes if (debug) 33374853402SPhilippe Charnier warnx("getting export list"); 3348fae3551SRodney W. Grimes get_exportlist(); 3358fae3551SRodney W. Grimes if (debug) 33674853402SPhilippe Charnier warnx("getting mount list"); 3378fae3551SRodney W. Grimes get_mountlist(); 3388fae3551SRodney W. Grimes if (debug) 33974853402SPhilippe Charnier warnx("here we go"); 3408fae3551SRodney W. Grimes if (debug == 0) { 3418fae3551SRodney W. Grimes daemon(0, 0); 3428fae3551SRodney W. Grimes signal(SIGINT, SIG_IGN); 3438fae3551SRodney W. Grimes signal(SIGQUIT, SIG_IGN); 3448fae3551SRodney W. Grimes } 34569d65572SIan Dowse signal(SIGHUP, huphandler); 3468360efbdSAlfred Perlstein signal(SIGTERM, terminate); 3478fae3551SRodney W. Grimes { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); 3488fae3551SRodney W. Grimes if (pidfile != NULL) { 3498fae3551SRodney W. Grimes fprintf(pidfile, "%d\n", getpid()); 3508fae3551SRodney W. Grimes fclose(pidfile); 3518fae3551SRodney W. Grimes } 3528fae3551SRodney W. Grimes } 3538360efbdSAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); 3548360efbdSAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); 3558360efbdSAlfred Perlstein udpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 3568360efbdSAlfred Perlstein tcpsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 35795b99739SAlfred Perlstein udpconf = getnetconfigent("udp"); 35895b99739SAlfred Perlstein tcpconf = getnetconfigent("tcp"); 359bcb53b16SMartin Blapp 360bcb53b16SMartin Blapp rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); 361bcb53b16SMartin Blapp 36295b99739SAlfred Perlstein if (!have_v6) 36395b99739SAlfred Perlstein goto skip_v6; 3648360efbdSAlfred Perlstein udp6sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 3658360efbdSAlfred Perlstein tcp6sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); 3668360efbdSAlfred Perlstein /* 3678360efbdSAlfred Perlstein * We're doing host-based access checks here, so don't allow 3688360efbdSAlfred Perlstein * v4-in-v6 to confuse things. The kernel will disable it 3698360efbdSAlfred Perlstein * by default on NFS sockets too. 3708360efbdSAlfred Perlstein */ 3718360efbdSAlfred Perlstein if (udp6sock != -1 && setsockopt(udp6sock, IPPROTO_IPV6, 372fc99a00cSHajimu UMEMOTO IPV6_V6ONLY, &one, sizeof one) < 0) { 3738360efbdSAlfred Perlstein syslog(LOG_ERR, "can't disable v4-in-v6 on UDP socket"); 3748360efbdSAlfred Perlstein exit(1); 3758360efbdSAlfred Perlstein } 3768360efbdSAlfred Perlstein if (tcp6sock != -1 && setsockopt(tcp6sock, IPPROTO_IPV6, 377fc99a00cSHajimu UMEMOTO IPV6_V6ONLY, &one, sizeof one) < 0) { 3787c615cf0SRobert Watson syslog(LOG_ERR, "can't disable v4-in-v6 on TCP socket"); 3798360efbdSAlfred Perlstein exit(1); 3808360efbdSAlfred Perlstein } 3818360efbdSAlfred Perlstein udp6conf = getnetconfigent("udp6"); 3828360efbdSAlfred Perlstein tcp6conf = getnetconfigent("tcp6"); 38395b99739SAlfred Perlstein 38495b99739SAlfred Perlstein skip_v6: 385c6e5e158SGuido van Rooij if (!resvport_only) { 3864a0785aaSPeter Wemm if (sysctlbyname("vfs.nfsrv.nfs_privport", NULL, NULL, 3874a0785aaSPeter Wemm &resvport_only, sizeof(resvport_only)) != 0 && 3884a0785aaSPeter Wemm errno != ENOENT) { 389394da4c1SGuido van Rooij syslog(LOG_ERR, "sysctl: %m"); 390394da4c1SGuido van Rooij exit(1); 391394da4c1SGuido van Rooij } 392c6e5e158SGuido van Rooij } 3938360efbdSAlfred Perlstein if (udpsock != -1 && udpconf != NULL) { 3948360efbdSAlfred Perlstein bindresvport(udpsock, NULL); 3958360efbdSAlfred Perlstein udptransp = svc_dg_create(udpsock, 0, 0); 3968360efbdSAlfred Perlstein if (udptransp != NULL) { 3978360efbdSAlfred Perlstein if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER1, 3988360efbdSAlfred Perlstein mntsrv, udpconf)) 3998360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP RPCMNT_VER1 service"); 4008360efbdSAlfred Perlstein else 4018360efbdSAlfred Perlstein xcreated++; 4028360efbdSAlfred Perlstein if (!force_v2) { 4038360efbdSAlfred Perlstein if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER3, 4048360efbdSAlfred Perlstein mntsrv, udpconf)) 4058360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP RPCMNT_VER3 service"); 4068360efbdSAlfred Perlstein else 4078360efbdSAlfred Perlstein xcreated++; 4088fae3551SRodney W. Grimes } 4098360efbdSAlfred Perlstein } else 4108360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create UDP services"); 4118360efbdSAlfred Perlstein 4128360efbdSAlfred Perlstein } 4138360efbdSAlfred Perlstein if (tcpsock != -1 && tcpconf != NULL) { 4148360efbdSAlfred Perlstein bindresvport(tcpsock, NULL); 4158360efbdSAlfred Perlstein listen(tcpsock, SOMAXCONN); 416bcb53b16SMartin Blapp tcptransp = svc_vc_create(tcpsock, RPC_MAXDATASIZE, RPC_MAXDATASIZE); 4178360efbdSAlfred Perlstein if (tcptransp != NULL) { 4188360efbdSAlfred Perlstein if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER1, 4198360efbdSAlfred Perlstein mntsrv, tcpconf)) 4208360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP RPCMNT_VER1 service"); 4218360efbdSAlfred Perlstein else 4228360efbdSAlfred Perlstein xcreated++; 4238360efbdSAlfred Perlstein if (!force_v2) { 4248360efbdSAlfred Perlstein if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER3, 4258360efbdSAlfred Perlstein mntsrv, tcpconf)) 4268360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP RPCMNT_VER3 service"); 4278360efbdSAlfred Perlstein else 4288360efbdSAlfred Perlstein xcreated++; 4298360efbdSAlfred Perlstein } 4308360efbdSAlfred Perlstein } else 4318360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create TCP service"); 4328360efbdSAlfred Perlstein 4338360efbdSAlfred Perlstein } 43495b99739SAlfred Perlstein if (have_v6 && udp6sock != -1 && udp6conf != NULL) { 4358360efbdSAlfred Perlstein bindresvport(udp6sock, NULL); 4368360efbdSAlfred Perlstein udp6transp = svc_dg_create(udp6sock, 0, 0); 4378360efbdSAlfred Perlstein if (udp6transp != NULL) { 4388360efbdSAlfred Perlstein if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER1, 4398360efbdSAlfred Perlstein mntsrv, udp6conf)) 4408360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER1 service"); 4418360efbdSAlfred Perlstein else 4428360efbdSAlfred Perlstein xcreated++; 4438360efbdSAlfred Perlstein if (!force_v2) { 4448360efbdSAlfred Perlstein if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER3, 4458360efbdSAlfred Perlstein mntsrv, udp6conf)) 4468360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER3 service"); 4478360efbdSAlfred Perlstein else 4488360efbdSAlfred Perlstein xcreated++; 4498360efbdSAlfred Perlstein } 4508360efbdSAlfred Perlstein } else 4518360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create UDP6 service"); 4528360efbdSAlfred Perlstein 4538360efbdSAlfred Perlstein } 45495b99739SAlfred Perlstein if (have_v6 && tcp6sock != -1 && tcp6conf != NULL) { 4558360efbdSAlfred Perlstein bindresvport(tcp6sock, NULL); 4568360efbdSAlfred Perlstein listen(tcp6sock, SOMAXCONN); 457bcb53b16SMartin Blapp tcp6transp = svc_vc_create(tcp6sock, RPC_MAXDATASIZE, RPC_MAXDATASIZE); 4588360efbdSAlfred Perlstein if (tcp6transp != NULL) { 4598360efbdSAlfred Perlstein if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER1, 4608360efbdSAlfred Perlstein mntsrv, tcp6conf)) 4618360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER1 service"); 4628360efbdSAlfred Perlstein else 4638360efbdSAlfred Perlstein xcreated++; 4648360efbdSAlfred Perlstein if (!force_v2) { 4658360efbdSAlfred Perlstein if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER3, 4668360efbdSAlfred Perlstein mntsrv, tcp6conf)) 4678360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER3 service"); 4688360efbdSAlfred Perlstein else 4698360efbdSAlfred Perlstein xcreated++; 4708360efbdSAlfred Perlstein } 4718360efbdSAlfred Perlstein } else 4728360efbdSAlfred Perlstein syslog(LOG_WARNING, "can't create TCP6 service"); 4738360efbdSAlfred Perlstein 4748360efbdSAlfred Perlstein } 4758360efbdSAlfred Perlstein if (xcreated == 0) { 4768360efbdSAlfred Perlstein syslog(LOG_ERR, "could not create any services"); 4772a66cfc5SDoug Rabson exit(1); 4782a66cfc5SDoug Rabson } 47969d65572SIan Dowse 48069d65572SIan Dowse /* Expand svc_run() here so that we can call get_exportlist(). */ 48169d65572SIan Dowse for (;;) { 48269d65572SIan Dowse if (got_sighup) { 48369d65572SIan Dowse get_exportlist(); 48469d65572SIan Dowse got_sighup = 0; 48569d65572SIan Dowse } 48669d65572SIan Dowse readfds = svc_fdset; 48769d65572SIan Dowse switch (select(svc_maxfd + 1, &readfds, NULL, NULL, NULL)) { 48869d65572SIan Dowse case -1: 48969d65572SIan Dowse if (errno == EINTR) 49069d65572SIan Dowse continue; 49169d65572SIan Dowse syslog(LOG_ERR, "mountd died: select: %m"); 49274853402SPhilippe Charnier exit(1); 49369d65572SIan Dowse case 0: 49469d65572SIan Dowse continue; 49569d65572SIan Dowse default: 49669d65572SIan Dowse svc_getreqset(&readfds); 49769d65572SIan Dowse } 49869d65572SIan Dowse } 49974853402SPhilippe Charnier } 50074853402SPhilippe Charnier 50174853402SPhilippe Charnier static void 50274853402SPhilippe Charnier usage() 50374853402SPhilippe Charnier { 50474853402SPhilippe Charnier fprintf(stderr, 50574853402SPhilippe Charnier "usage: mountd [-2] [-d] [-l] [-n] [-r] [export_file]\n"); 5068fae3551SRodney W. Grimes exit(1); 5078fae3551SRodney W. Grimes } 5088fae3551SRodney W. Grimes 5098fae3551SRodney W. Grimes /* 5108fae3551SRodney W. Grimes * The mount rpc service 5118fae3551SRodney W. Grimes */ 5128fae3551SRodney W. Grimes void 5138fae3551SRodney W. Grimes mntsrv(rqstp, transp) 5148fae3551SRodney W. Grimes struct svc_req *rqstp; 5158fae3551SRodney W. Grimes SVCXPRT *transp; 5168fae3551SRodney W. Grimes { 5178fae3551SRodney W. Grimes struct exportlist *ep; 5188fae3551SRodney W. Grimes struct dirlist *dp; 519a62dc406SDoug Rabson struct fhreturn fhr; 5208fae3551SRodney W. Grimes struct stat stb; 5218fae3551SRodney W. Grimes struct statfs fsb; 5228360efbdSAlfred Perlstein struct addrinfo *ai; 5238360efbdSAlfred Perlstein char host[NI_MAXHOST], numerichost[NI_MAXHOST]; 5248360efbdSAlfred Perlstein int lookup_failed = 1; 5258360efbdSAlfred Perlstein struct sockaddr *saddr; 526a62dc406SDoug Rabson u_short sport; 5278fae3551SRodney W. Grimes char rpcpath[RPCMNT_PATHLEN + 1], dirpath[MAXPATHLEN]; 528e90cdb54SGuido van Rooij int bad = 0, defset, hostset; 529a62dc406SDoug Rabson sigset_t sighup_mask; 5308fae3551SRodney W. Grimes 531a62dc406SDoug Rabson sigemptyset(&sighup_mask); 532a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 5338360efbdSAlfred Perlstein saddr = svc_getrpccaller(transp)->buf; 5348360efbdSAlfred Perlstein switch (saddr->sa_family) { 5358360efbdSAlfred Perlstein case AF_INET6: 53601709abfSIan Dowse sport = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port); 5378360efbdSAlfred Perlstein break; 5388360efbdSAlfred Perlstein case AF_INET: 53901709abfSIan Dowse sport = ntohs(((struct sockaddr_in *)saddr)->sin_port); 5408360efbdSAlfred Perlstein break; 5418360efbdSAlfred Perlstein default: 5428360efbdSAlfred Perlstein syslog(LOG_ERR, "request from unknown address family"); 5438360efbdSAlfred Perlstein return; 5448360efbdSAlfred Perlstein } 5458360efbdSAlfred Perlstein lookup_failed = getnameinfo(saddr, saddr->sa_len, host, sizeof host, 5468360efbdSAlfred Perlstein NULL, 0, 0); 5478360efbdSAlfred Perlstein getnameinfo(saddr, saddr->sa_len, numerichost, 5488360efbdSAlfred Perlstein sizeof numerichost, NULL, 0, NI_NUMERICHOST); 5498360efbdSAlfred Perlstein ai = NULL; 5508fae3551SRodney W. Grimes switch (rqstp->rq_proc) { 5518fae3551SRodney W. Grimes case NULLPROC: 552389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) 55374853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 5548fae3551SRodney W. Grimes return; 5558fae3551SRodney W. Grimes case RPCMNT_MOUNT: 556a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 557f51631d7SGuido van Rooij syslog(LOG_NOTICE, 558f51631d7SGuido van Rooij "mount request from %s from unprivileged port", 5598360efbdSAlfred Perlstein numerichost); 5608fae3551SRodney W. Grimes svcerr_weakauth(transp); 5618fae3551SRodney W. Grimes return; 5628fae3551SRodney W. Grimes } 563389b8446SPeter Wemm if (!svc_getargs(transp, (xdrproc_t)xdr_dir, rpcpath)) { 564f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable mount request from %s", 5658360efbdSAlfred Perlstein numerichost); 5668fae3551SRodney W. Grimes svcerr_decode(transp); 5678fae3551SRodney W. Grimes return; 5688fae3551SRodney W. Grimes } 5698fae3551SRodney W. Grimes 5708fae3551SRodney W. Grimes /* 5718fae3551SRodney W. Grimes * Get the real pathname and make sure it is a directory 572a62dc406SDoug Rabson * or a regular file if the -r option was specified 573a62dc406SDoug Rabson * and it exists. 5748fae3551SRodney W. Grimes */ 575cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL || 5768fae3551SRodney W. Grimes stat(dirpath, &stb) < 0 || 577a62dc406SDoug Rabson (!S_ISDIR(stb.st_mode) && 578a62dc406SDoug Rabson (dir_only || !S_ISREG(stb.st_mode))) || 5798fae3551SRodney W. Grimes statfs(dirpath, &fsb) < 0) { 5808fae3551SRodney W. Grimes chdir("/"); /* Just in case realpath doesn't */ 581f51631d7SGuido van Rooij syslog(LOG_NOTICE, 58274853402SPhilippe Charnier "mount request from %s for non existent path %s", 5838360efbdSAlfred Perlstein numerichost, dirpath); 5848fae3551SRodney W. Grimes if (debug) 58574853402SPhilippe Charnier warnx("stat failed on %s", dirpath); 586e90cdb54SGuido van Rooij bad = ENOENT; /* We will send error reply later */ 5878fae3551SRodney W. Grimes } 5888fae3551SRodney W. Grimes 5898fae3551SRodney W. Grimes /* Check in the exports list */ 590a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 5918fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 592a62dc406SDoug Rabson hostset = defset = 0; 593a62dc406SDoug Rabson if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) || 5948fae3551SRodney W. Grimes ((dp = dirp_search(ep->ex_dirl, dirpath)) && 595a62dc406SDoug Rabson chk_host(dp, saddr, &defset, &hostset)) || 5968fae3551SRodney W. Grimes (defset && scan_tree(ep->ex_defdir, saddr) == 0 && 5978fae3551SRodney W. Grimes scan_tree(ep->ex_dirl, saddr) == 0))) { 598e90cdb54SGuido van Rooij if (bad) { 599389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_long, 600e90cdb54SGuido van Rooij (caddr_t)&bad)) 60174853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 602e90cdb54SGuido van Rooij sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 603e90cdb54SGuido van Rooij return; 604e90cdb54SGuido van Rooij } 605a62dc406SDoug Rabson if (hostset & DP_HOSTSET) 606a62dc406SDoug Rabson fhr.fhr_flag = hostset; 607a62dc406SDoug Rabson else 608a62dc406SDoug Rabson fhr.fhr_flag = defset; 609a62dc406SDoug Rabson fhr.fhr_vers = rqstp->rq_vers; 6108fae3551SRodney W. Grimes /* Get the file handle */ 61187564113SPeter Wemm memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t)); 612a62dc406SDoug Rabson if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) { 6138fae3551SRodney W. Grimes bad = errno; 61474853402SPhilippe Charnier syslog(LOG_ERR, "can't get fh for %s", dirpath); 615389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_long, 6168fae3551SRodney W. Grimes (caddr_t)&bad)) 61774853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 618a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6198fae3551SRodney W. Grimes return; 6208fae3551SRodney W. Grimes } 621389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_fhs, 622389b8446SPeter Wemm (caddr_t)&fhr)) 62374853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6248360efbdSAlfred Perlstein if (!lookup_failed) 6258360efbdSAlfred Perlstein add_mlist(host, dirpath); 6268fae3551SRodney W. Grimes else 6278360efbdSAlfred Perlstein add_mlist(numerichost, dirpath); 6288fae3551SRodney W. Grimes if (debug) 62974853402SPhilippe Charnier warnx("mount successful"); 630c903443aSPeter Wemm if (dolog) 631f51631d7SGuido van Rooij syslog(LOG_NOTICE, 632f51631d7SGuido van Rooij "mount request succeeded from %s for %s", 6338360efbdSAlfred Perlstein numerichost, dirpath); 634f51631d7SGuido van Rooij } else { 6358fae3551SRodney W. Grimes bad = EACCES; 636f51631d7SGuido van Rooij syslog(LOG_NOTICE, 637f51631d7SGuido van Rooij "mount request denied from %s for %s", 6388360efbdSAlfred Perlstein numerichost, dirpath); 639f51631d7SGuido van Rooij } 640e90cdb54SGuido van Rooij 641389b8446SPeter Wemm if (bad && !svc_sendreply(transp, (xdrproc_t)xdr_long, 642389b8446SPeter Wemm (caddr_t)&bad)) 64374853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 644a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 6458fae3551SRodney W. Grimes return; 6468fae3551SRodney W. Grimes case RPCMNT_DUMP: 647389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_mlist, (caddr_t)NULL)) 64874853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 649c903443aSPeter Wemm else if (dolog) 650f51631d7SGuido van Rooij syslog(LOG_NOTICE, 651f51631d7SGuido van Rooij "dump request succeeded from %s", 6528360efbdSAlfred Perlstein numerichost); 6538fae3551SRodney W. Grimes return; 6548fae3551SRodney W. Grimes case RPCMNT_UMOUNT: 655a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 656f51631d7SGuido van Rooij syslog(LOG_NOTICE, 657f51631d7SGuido van Rooij "umount request from %s from unprivileged port", 6588360efbdSAlfred Perlstein numerichost); 6598fae3551SRodney W. Grimes svcerr_weakauth(transp); 6608fae3551SRodney W. Grimes return; 6618fae3551SRodney W. Grimes } 662389b8446SPeter Wemm if (!svc_getargs(transp, (xdrproc_t)xdr_dir, rpcpath)) { 663f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable umount request from %s", 6648360efbdSAlfred Perlstein numerichost); 6658fae3551SRodney W. Grimes svcerr_decode(transp); 6668fae3551SRodney W. Grimes return; 6678fae3551SRodney W. Grimes } 668cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL) { 669cb479b11SAlfred Perlstein syslog(LOG_NOTICE, "umount request from %s " 670cb479b11SAlfred Perlstein "for non existent path %s", 6718360efbdSAlfred Perlstein numerichost, dirpath); 672cb479b11SAlfred Perlstein } 673389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_void, (caddr_t)NULL)) 67474853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6758360efbdSAlfred Perlstein if (!lookup_failed) 67601709abfSIan Dowse del_mlist(host, dirpath); 67701709abfSIan Dowse del_mlist(numerichost, dirpath); 678c903443aSPeter Wemm if (dolog) 679f51631d7SGuido van Rooij syslog(LOG_NOTICE, 680f51631d7SGuido van Rooij "umount request succeeded from %s for %s", 6818360efbdSAlfred Perlstein numerichost, dirpath); 6828fae3551SRodney W. Grimes return; 6838fae3551SRodney W. Grimes case RPCMNT_UMNTALL: 684a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 685f51631d7SGuido van Rooij syslog(LOG_NOTICE, 686f51631d7SGuido van Rooij "umountall request from %s from unprivileged port", 6878360efbdSAlfred Perlstein numerichost); 6888fae3551SRodney W. Grimes svcerr_weakauth(transp); 6898fae3551SRodney W. Grimes return; 6908fae3551SRodney W. Grimes } 691389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_void, (caddr_t)NULL)) 69274853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 6938360efbdSAlfred Perlstein if (!lookup_failed) 69401709abfSIan Dowse del_mlist(host, NULL); 69501709abfSIan Dowse del_mlist(numerichost, NULL); 696c903443aSPeter Wemm if (dolog) 697f51631d7SGuido van Rooij syslog(LOG_NOTICE, 698f51631d7SGuido van Rooij "umountall request succeeded from %s", 6998360efbdSAlfred Perlstein numerichost); 7008fae3551SRodney W. Grimes return; 7018fae3551SRodney W. Grimes case RPCMNT_EXPORT: 702389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_explist, (caddr_t)NULL)) 703389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_explist_brief, 704389b8446SPeter Wemm (caddr_t)NULL)) 70574853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 706c903443aSPeter Wemm if (dolog) 707f51631d7SGuido van Rooij syslog(LOG_NOTICE, 708f51631d7SGuido van Rooij "export request succeeded from %s", 7098360efbdSAlfred Perlstein numerichost); 7108fae3551SRodney W. Grimes return; 7118fae3551SRodney W. Grimes default: 7128fae3551SRodney W. Grimes svcerr_noproc(transp); 7138fae3551SRodney W. Grimes return; 7148fae3551SRodney W. Grimes } 7158fae3551SRodney W. Grimes } 7168fae3551SRodney W. Grimes 7178fae3551SRodney W. Grimes /* 7188fae3551SRodney W. Grimes * Xdr conversion for a dirpath string 7198fae3551SRodney W. Grimes */ 7208fae3551SRodney W. Grimes int 7218fae3551SRodney W. Grimes xdr_dir(xdrsp, dirp) 7228fae3551SRodney W. Grimes XDR *xdrsp; 7238fae3551SRodney W. Grimes char *dirp; 7248fae3551SRodney W. Grimes { 7258fae3551SRodney W. Grimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 7268fae3551SRodney W. Grimes } 7278fae3551SRodney W. Grimes 7288fae3551SRodney W. Grimes /* 729a62dc406SDoug Rabson * Xdr routine to generate file handle reply 7308fae3551SRodney W. Grimes */ 7318fae3551SRodney W. Grimes int 732a62dc406SDoug Rabson xdr_fhs(xdrsp, cp) 7338fae3551SRodney W. Grimes XDR *xdrsp; 734a62dc406SDoug Rabson caddr_t cp; 7358fae3551SRodney W. Grimes { 7363d438ad6SDavid E. O'Brien struct fhreturn *fhrp = (struct fhreturn *)cp; 737a62dc406SDoug Rabson u_long ok = 0, len, auth; 7388fae3551SRodney W. Grimes 7398fae3551SRodney W. Grimes if (!xdr_long(xdrsp, &ok)) 7408fae3551SRodney W. Grimes return (0); 741a62dc406SDoug Rabson switch (fhrp->fhr_vers) { 742a62dc406SDoug Rabson case 1: 743a62dc406SDoug Rabson return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH)); 744a62dc406SDoug Rabson case 3: 745a62dc406SDoug Rabson len = NFSX_V3FH; 746a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 747a62dc406SDoug Rabson return (0); 748a62dc406SDoug Rabson if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) 749a62dc406SDoug Rabson return (0); 750a62dc406SDoug Rabson auth = RPCAUTH_UNIX; 751a62dc406SDoug Rabson len = 1; 752a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 753a62dc406SDoug Rabson return (0); 754a62dc406SDoug Rabson return (xdr_long(xdrsp, &auth)); 755a62dc406SDoug Rabson }; 756a62dc406SDoug Rabson return (0); 7578fae3551SRodney W. Grimes } 7588fae3551SRodney W. Grimes 7598fae3551SRodney W. Grimes int 7608fae3551SRodney W. Grimes xdr_mlist(xdrsp, cp) 7618fae3551SRodney W. Grimes XDR *xdrsp; 7628fae3551SRodney W. Grimes caddr_t cp; 7638fae3551SRodney W. Grimes { 7648fae3551SRodney W. Grimes struct mountlist *mlp; 7658fae3551SRodney W. Grimes int true = 1; 7668fae3551SRodney W. Grimes int false = 0; 7678fae3551SRodney W. Grimes char *strp; 7688fae3551SRodney W. Grimes 7698fae3551SRodney W. Grimes mlp = mlhead; 7708fae3551SRodney W. Grimes while (mlp) { 7718fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 7728fae3551SRodney W. Grimes return (0); 7738fae3551SRodney W. Grimes strp = &mlp->ml_host[0]; 7748fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 7758fae3551SRodney W. Grimes return (0); 7768fae3551SRodney W. Grimes strp = &mlp->ml_dirp[0]; 7778fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 7788fae3551SRodney W. Grimes return (0); 7798fae3551SRodney W. Grimes mlp = mlp->ml_next; 7808fae3551SRodney W. Grimes } 7818fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 7828fae3551SRodney W. Grimes return (0); 7838fae3551SRodney W. Grimes return (1); 7848fae3551SRodney W. Grimes } 7858fae3551SRodney W. Grimes 7868fae3551SRodney W. Grimes /* 7878fae3551SRodney W. Grimes * Xdr conversion for export list 7888fae3551SRodney W. Grimes */ 7898fae3551SRodney W. Grimes int 79091acb349SAlfred Perlstein xdr_explist_common(xdrsp, cp, brief) 7918fae3551SRodney W. Grimes XDR *xdrsp; 7928fae3551SRodney W. Grimes caddr_t cp; 79391acb349SAlfred Perlstein int brief; 7948fae3551SRodney W. Grimes { 7958fae3551SRodney W. Grimes struct exportlist *ep; 7968fae3551SRodney W. Grimes int false = 0; 797a62dc406SDoug Rabson int putdef; 798a62dc406SDoug Rabson sigset_t sighup_mask; 7998fae3551SRodney W. Grimes 800a62dc406SDoug Rabson sigemptyset(&sighup_mask); 801a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 802a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 8038fae3551SRodney W. Grimes ep = exphead; 8048fae3551SRodney W. Grimes while (ep) { 8058fae3551SRodney W. Grimes putdef = 0; 80691acb349SAlfred Perlstein if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, 80791acb349SAlfred Perlstein &putdef, brief)) 8088fae3551SRodney W. Grimes goto errout; 8098fae3551SRodney W. Grimes if (ep->ex_defdir && putdef == 0 && 8108fae3551SRodney W. Grimes put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL, 81191acb349SAlfred Perlstein &putdef, brief)) 8128fae3551SRodney W. Grimes goto errout; 8138fae3551SRodney W. Grimes ep = ep->ex_next; 8148fae3551SRodney W. Grimes } 815a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 8168fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 8178fae3551SRodney W. Grimes return (0); 8188fae3551SRodney W. Grimes return (1); 8198fae3551SRodney W. Grimes errout: 820a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 8218fae3551SRodney W. Grimes return (0); 8228fae3551SRodney W. Grimes } 8238fae3551SRodney W. Grimes 8248fae3551SRodney W. Grimes /* 8258fae3551SRodney W. Grimes * Called from xdr_explist() to traverse the tree and export the 8268fae3551SRodney W. Grimes * directory paths. 8278fae3551SRodney W. Grimes */ 8288fae3551SRodney W. Grimes int 82991acb349SAlfred Perlstein put_exlist(dp, xdrsp, adp, putdefp, brief) 8308fae3551SRodney W. Grimes struct dirlist *dp; 8318fae3551SRodney W. Grimes XDR *xdrsp; 8328fae3551SRodney W. Grimes struct dirlist *adp; 8338fae3551SRodney W. Grimes int *putdefp; 83491acb349SAlfred Perlstein int brief; 8358fae3551SRodney W. Grimes { 8368fae3551SRodney W. Grimes struct grouplist *grp; 8378fae3551SRodney W. Grimes struct hostlist *hp; 8388fae3551SRodney W. Grimes int true = 1; 8398fae3551SRodney W. Grimes int false = 0; 8408fae3551SRodney W. Grimes int gotalldir = 0; 8418fae3551SRodney W. Grimes char *strp; 8428fae3551SRodney W. Grimes 8438fae3551SRodney W. Grimes if (dp) { 84491acb349SAlfred Perlstein if (put_exlist(dp->dp_left, xdrsp, adp, putdefp, brief)) 8458fae3551SRodney W. Grimes return (1); 8468fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 8478fae3551SRodney W. Grimes return (1); 8488fae3551SRodney W. Grimes strp = dp->dp_dirp; 8498fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 8508fae3551SRodney W. Grimes return (1); 8518fae3551SRodney W. Grimes if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) { 8528fae3551SRodney W. Grimes gotalldir = 1; 8538fae3551SRodney W. Grimes *putdefp = 1; 8548fae3551SRodney W. Grimes } 85591acb349SAlfred Perlstein if (brief) { 85691acb349SAlfred Perlstein if (!xdr_bool(xdrsp, &true)) 85791acb349SAlfred Perlstein return (1); 85891acb349SAlfred Perlstein strp = "(...)"; 85991acb349SAlfred Perlstein if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 86091acb349SAlfred Perlstein return (1); 86191acb349SAlfred Perlstein } else if ((dp->dp_flag & DP_DEFSET) == 0 && 8628fae3551SRodney W. Grimes (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) { 8638fae3551SRodney W. Grimes hp = dp->dp_hosts; 8648fae3551SRodney W. Grimes while (hp) { 8658fae3551SRodney W. Grimes grp = hp->ht_grp; 8668fae3551SRodney W. Grimes if (grp->gr_type == GT_HOST) { 8678fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 8688fae3551SRodney W. Grimes return (1); 8698360efbdSAlfred Perlstein strp = grp->gr_ptr.gt_addrinfo->ai_canonname; 8708fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, 8718fae3551SRodney W. Grimes RPCMNT_NAMELEN)) 8728fae3551SRodney W. Grimes return (1); 8738fae3551SRodney W. Grimes } else if (grp->gr_type == GT_NET) { 8748fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 8758fae3551SRodney W. Grimes return (1); 8768fae3551SRodney W. Grimes strp = grp->gr_ptr.gt_net.nt_name; 8778fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, 8788fae3551SRodney W. Grimes RPCMNT_NAMELEN)) 8798fae3551SRodney W. Grimes return (1); 8808fae3551SRodney W. Grimes } 8818fae3551SRodney W. Grimes hp = hp->ht_next; 8828fae3551SRodney W. Grimes if (gotalldir && hp == (struct hostlist *)NULL) { 8838fae3551SRodney W. Grimes hp = adp->dp_hosts; 8848fae3551SRodney W. Grimes gotalldir = 0; 8858fae3551SRodney W. Grimes } 8868fae3551SRodney W. Grimes } 8878fae3551SRodney W. Grimes } 8888fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 8898fae3551SRodney W. Grimes return (1); 89091acb349SAlfred Perlstein if (put_exlist(dp->dp_right, xdrsp, adp, putdefp, brief)) 8918fae3551SRodney W. Grimes return (1); 8928fae3551SRodney W. Grimes } 8938fae3551SRodney W. Grimes return (0); 8948fae3551SRodney W. Grimes } 8958fae3551SRodney W. Grimes 89691acb349SAlfred Perlstein int 89791acb349SAlfred Perlstein xdr_explist(xdrsp, cp) 89891acb349SAlfred Perlstein XDR *xdrsp; 89991acb349SAlfred Perlstein caddr_t cp; 90091acb349SAlfred Perlstein { 90191acb349SAlfred Perlstein 90291acb349SAlfred Perlstein return xdr_explist_common(xdrsp, cp, 0); 90391acb349SAlfred Perlstein } 90491acb349SAlfred Perlstein 90591acb349SAlfred Perlstein int 90691acb349SAlfred Perlstein xdr_explist_brief(xdrsp, cp) 90791acb349SAlfred Perlstein XDR *xdrsp; 90891acb349SAlfred Perlstein caddr_t cp; 90991acb349SAlfred Perlstein { 91091acb349SAlfred Perlstein 91191acb349SAlfred Perlstein return xdr_explist_common(xdrsp, cp, 1); 91291acb349SAlfred Perlstein } 91391acb349SAlfred Perlstein 91491ca1a91SIan Dowse char *line; 91591ca1a91SIan Dowse int linesize; 9168fae3551SRodney W. Grimes FILE *exp_file; 9178fae3551SRodney W. Grimes 9188fae3551SRodney W. Grimes /* 9198fae3551SRodney W. Grimes * Get the export list 9208fae3551SRodney W. Grimes */ 9218fae3551SRodney W. Grimes void 9228fae3551SRodney W. Grimes get_exportlist() 9238fae3551SRodney W. Grimes { 9248fae3551SRodney W. Grimes struct exportlist *ep, *ep2; 9258fae3551SRodney W. Grimes struct grouplist *grp, *tgrp; 9268fae3551SRodney W. Grimes struct exportlist **epp; 9278fae3551SRodney W. Grimes struct dirlist *dirhead; 9288fae3551SRodney W. Grimes struct statfs fsb, *fsp; 929c0511d3bSBrian Feldman struct xucred anon; 9308fae3551SRodney W. Grimes char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; 9318fae3551SRodney W. Grimes int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp; 9328fae3551SRodney W. Grimes 933cb479b11SAlfred Perlstein dirp = NULL; 934cb479b11SAlfred Perlstein dirplen = 0; 935cb479b11SAlfred Perlstein 9368fae3551SRodney W. Grimes /* 9378fae3551SRodney W. Grimes * First, get rid of the old list 9388fae3551SRodney W. Grimes */ 9398fae3551SRodney W. Grimes ep = exphead; 9408fae3551SRodney W. Grimes while (ep) { 9418fae3551SRodney W. Grimes ep2 = ep; 9428fae3551SRodney W. Grimes ep = ep->ex_next; 9438fae3551SRodney W. Grimes free_exp(ep2); 9448fae3551SRodney W. Grimes } 9458fae3551SRodney W. Grimes exphead = (struct exportlist *)NULL; 9468fae3551SRodney W. Grimes 9478fae3551SRodney W. Grimes grp = grphead; 9488fae3551SRodney W. Grimes while (grp) { 9498fae3551SRodney W. Grimes tgrp = grp; 9508fae3551SRodney W. Grimes grp = grp->gr_next; 9518fae3551SRodney W. Grimes free_grp(tgrp); 9528fae3551SRodney W. Grimes } 9538fae3551SRodney W. Grimes grphead = (struct grouplist *)NULL; 9548fae3551SRodney W. Grimes 9558fae3551SRodney W. Grimes /* 9568fae3551SRodney W. Grimes * And delete exports that are in the kernel for all local 9578fae3551SRodney W. Grimes * filesystems. 9588fae3551SRodney W. Grimes * XXX: Should know how to handle all local exportable filesystems 95987564113SPeter Wemm * instead of just "ufs". 9608fae3551SRodney W. Grimes */ 9618fae3551SRodney W. Grimes num = getmntinfo(&fsp, MNT_NOWAIT); 9628fae3551SRodney W. Grimes for (i = 0; i < num; i++) { 9638fae3551SRodney W. Grimes union { 9648fae3551SRodney W. Grimes struct ufs_args ua; 9658fae3551SRodney W. Grimes struct iso_args ia; 966a62dc406SDoug Rabson struct msdosfs_args da; 9679300c696SSemen Ustimenko struct ntfs_args na; 968a62dc406SDoug Rabson } targs; 969a62dc406SDoug Rabson 970753d4978SPoul-Henning Kamp if (!strcmp(fsp->f_fstypename, "ufs") || 9714ccd7546SRuslan Ermilov !strcmp(fsp->f_fstypename, "msdosfs") || 9729300c696SSemen Ustimenko !strcmp(fsp->f_fstypename, "ntfs") || 97387564113SPeter Wemm !strcmp(fsp->f_fstypename, "cd9660")) { 974a62dc406SDoug Rabson targs.ua.fspec = NULL; 975a62dc406SDoug Rabson targs.ua.export.ex_flags = MNT_DELEXPORT; 976a62dc406SDoug Rabson if (mount(fsp->f_fstypename, fsp->f_mntonname, 9775f558fa4SIan Dowse fsp->f_flags | MNT_UPDATE, (caddr_t)&targs) < 0 && 9785f558fa4SIan Dowse errno != ENOENT) 9795f558fa4SIan Dowse syslog(LOG_ERR, 9805f558fa4SIan Dowse "can't delete exports for %s: %m", 9818fae3551SRodney W. Grimes fsp->f_mntonname); 9828fae3551SRodney W. Grimes } 9838fae3551SRodney W. Grimes fsp++; 9848fae3551SRodney W. Grimes } 9858fae3551SRodney W. Grimes 9868fae3551SRodney W. Grimes /* 9878fae3551SRodney W. Grimes * Read in the exports file and build the list, calling 9888fae3551SRodney W. Grimes * mount() as we go along to push the export rules into the kernel. 9898fae3551SRodney W. Grimes */ 9908fae3551SRodney W. Grimes if ((exp_file = fopen(exname, "r")) == NULL) { 99174853402SPhilippe Charnier syslog(LOG_ERR, "can't open %s", exname); 9928fae3551SRodney W. Grimes exit(2); 9938fae3551SRodney W. Grimes } 9948fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 9958fae3551SRodney W. Grimes while (get_line()) { 9968fae3551SRodney W. Grimes if (debug) 99774853402SPhilippe Charnier warnx("got line %s", line); 9988fae3551SRodney W. Grimes cp = line; 9998fae3551SRodney W. Grimes nextfield(&cp, &endcp); 10008fae3551SRodney W. Grimes if (*cp == '#') 10018fae3551SRodney W. Grimes goto nextline; 10028fae3551SRodney W. Grimes 10038fae3551SRodney W. Grimes /* 10048fae3551SRodney W. Grimes * Set defaults. 10058fae3551SRodney W. Grimes */ 10068fae3551SRodney W. Grimes has_host = FALSE; 10078fae3551SRodney W. Grimes anon = def_anon; 10088fae3551SRodney W. Grimes exflags = MNT_EXPORTED; 10098fae3551SRodney W. Grimes got_nondir = 0; 10108fae3551SRodney W. Grimes opt_flags = 0; 10118fae3551SRodney W. Grimes ep = (struct exportlist *)NULL; 10128fae3551SRodney W. Grimes 10138fae3551SRodney W. Grimes /* 10148fae3551SRodney W. Grimes * Create new exports list entry 10158fae3551SRodney W. Grimes */ 10168fae3551SRodney W. Grimes len = endcp-cp; 10178fae3551SRodney W. Grimes tgrp = grp = get_grp(); 10188fae3551SRodney W. Grimes while (len > 0) { 10198fae3551SRodney W. Grimes if (len > RPCMNT_NAMELEN) { 10208fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10218fae3551SRodney W. Grimes goto nextline; 10228fae3551SRodney W. Grimes } 10238fae3551SRodney W. Grimes if (*cp == '-') { 10248fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10258fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10268fae3551SRodney W. Grimes goto nextline; 10278fae3551SRodney W. Grimes } 10288fae3551SRodney W. Grimes if (debug) 102974853402SPhilippe Charnier warnx("doing opt %s", cp); 10308fae3551SRodney W. Grimes got_nondir = 1; 10318fae3551SRodney W. Grimes if (do_opt(&cp, &endcp, ep, grp, &has_host, 10328fae3551SRodney W. Grimes &exflags, &anon)) { 10338fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10348fae3551SRodney W. Grimes goto nextline; 10358fae3551SRodney W. Grimes } 10368fae3551SRodney W. Grimes } else if (*cp == '/') { 10378fae3551SRodney W. Grimes savedc = *endcp; 10388fae3551SRodney W. Grimes *endcp = '\0'; 10398fae3551SRodney W. Grimes if (check_dirpath(cp) && 10408fae3551SRodney W. Grimes statfs(cp, &fsb) >= 0) { 10418fae3551SRodney W. Grimes if (got_nondir) { 104274853402SPhilippe Charnier syslog(LOG_ERR, "dirs must be first"); 10438fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10448fae3551SRodney W. Grimes goto nextline; 10458fae3551SRodney W. Grimes } 10468fae3551SRodney W. Grimes if (ep) { 10478fae3551SRodney W. Grimes if (ep->ex_fs.val[0] != fsb.f_fsid.val[0] || 10488fae3551SRodney W. Grimes ep->ex_fs.val[1] != fsb.f_fsid.val[1]) { 10498fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10508fae3551SRodney W. Grimes goto nextline; 10518fae3551SRodney W. Grimes } 10528fae3551SRodney W. Grimes } else { 10538fae3551SRodney W. Grimes /* 10548fae3551SRodney W. Grimes * See if this directory is already 10558fae3551SRodney W. Grimes * in the list. 10568fae3551SRodney W. Grimes */ 10578fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 10588fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10598fae3551SRodney W. Grimes ep = get_exp(); 10608fae3551SRodney W. Grimes ep->ex_fs = fsb.f_fsid; 10618fae3551SRodney W. Grimes ep->ex_fsdir = (char *) 10628fae3551SRodney W. Grimes malloc(strlen(fsb.f_mntonname) + 1); 10638fae3551SRodney W. Grimes if (ep->ex_fsdir) 10648fae3551SRodney W. Grimes strcpy(ep->ex_fsdir, 10658fae3551SRodney W. Grimes fsb.f_mntonname); 10668fae3551SRodney W. Grimes else 10678fae3551SRodney W. Grimes out_of_mem(); 10688fae3551SRodney W. Grimes if (debug) 106974853402SPhilippe Charnier warnx("making new ep fs=0x%x,0x%x", 10708fae3551SRodney W. Grimes fsb.f_fsid.val[0], 10718fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 10728fae3551SRodney W. Grimes } else if (debug) 107374853402SPhilippe Charnier warnx("found ep fs=0x%x,0x%x", 10748fae3551SRodney W. Grimes fsb.f_fsid.val[0], 10758fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 10768fae3551SRodney W. Grimes } 10778fae3551SRodney W. Grimes 10788fae3551SRodney W. Grimes /* 10798fae3551SRodney W. Grimes * Add dirpath to export mount point. 10808fae3551SRodney W. Grimes */ 10818fae3551SRodney W. Grimes dirp = add_expdir(&dirhead, cp, len); 10828fae3551SRodney W. Grimes dirplen = len; 10838fae3551SRodney W. Grimes } else { 10848fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10858fae3551SRodney W. Grimes goto nextline; 10868fae3551SRodney W. Grimes } 10878fae3551SRodney W. Grimes *endcp = savedc; 10888fae3551SRodney W. Grimes } else { 10898fae3551SRodney W. Grimes savedc = *endcp; 10908fae3551SRodney W. Grimes *endcp = '\0'; 10918fae3551SRodney W. Grimes got_nondir = 1; 10928fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 10938fae3551SRodney W. Grimes getexp_err(ep, tgrp); 10948fae3551SRodney W. Grimes goto nextline; 10958fae3551SRodney W. Grimes } 10968fae3551SRodney W. Grimes 10978fae3551SRodney W. Grimes /* 10988fae3551SRodney W. Grimes * Get the host or netgroup. 10998fae3551SRodney W. Grimes */ 11008fae3551SRodney W. Grimes setnetgrent(cp); 11018fae3551SRodney W. Grimes netgrp = getnetgrent(&hst, &usr, &dom); 11028fae3551SRodney W. Grimes do { 11038fae3551SRodney W. Grimes if (has_host) { 11048fae3551SRodney W. Grimes grp->gr_next = get_grp(); 11058fae3551SRodney W. Grimes grp = grp->gr_next; 11068fae3551SRodney W. Grimes } 11078fae3551SRodney W. Grimes if (netgrp) { 11089d70a156SJoerg Wunsch if (hst == 0) { 110974853402SPhilippe Charnier syslog(LOG_ERR, 111074853402SPhilippe Charnier "null hostname in netgroup %s, skipping", cp); 111101d48801SJoerg Wunsch grp->gr_type = GT_IGNORE; 11129d70a156SJoerg Wunsch } else if (get_host(hst, grp, tgrp)) { 111374853402SPhilippe Charnier syslog(LOG_ERR, 111474853402SPhilippe Charnier "bad host %s in netgroup %s, skipping", hst, cp); 1115a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 11168fae3551SRodney W. Grimes } 11178b5a6d67SBill Paul } else if (get_host(cp, grp, tgrp)) { 111874853402SPhilippe Charnier syslog(LOG_ERR, "bad host %s, skipping", cp); 1119a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 11208fae3551SRodney W. Grimes } 11218fae3551SRodney W. Grimes has_host = TRUE; 11228fae3551SRodney W. Grimes } while (netgrp && getnetgrent(&hst, &usr, &dom)); 11238fae3551SRodney W. Grimes endnetgrent(); 11248fae3551SRodney W. Grimes *endcp = savedc; 11258fae3551SRodney W. Grimes } 11268fae3551SRodney W. Grimes cp = endcp; 11278fae3551SRodney W. Grimes nextfield(&cp, &endcp); 11288fae3551SRodney W. Grimes len = endcp - cp; 11298fae3551SRodney W. Grimes } 11308fae3551SRodney W. Grimes if (check_options(dirhead)) { 11318fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11328fae3551SRodney W. Grimes goto nextline; 11338fae3551SRodney W. Grimes } 11348fae3551SRodney W. Grimes if (!has_host) { 11356d359f31SIan Dowse grp->gr_type = GT_DEFAULT; 11368fae3551SRodney W. Grimes if (debug) 113774853402SPhilippe Charnier warnx("adding a default entry"); 11388fae3551SRodney W. Grimes 11398fae3551SRodney W. Grimes /* 11408fae3551SRodney W. Grimes * Don't allow a network export coincide with a list of 11418fae3551SRodney W. Grimes * host(s) on the same line. 11428fae3551SRodney W. Grimes */ 11438fae3551SRodney W. Grimes } else if ((opt_flags & OP_NET) && tgrp->gr_next) { 114460caaee2SIan Dowse syslog(LOG_ERR, "network/host conflict"); 11458fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11468fae3551SRodney W. Grimes goto nextline; 1147a968cfd8SJonathan Lemon 1148a968cfd8SJonathan Lemon /* 1149a968cfd8SJonathan Lemon * If an export list was specified on this line, make sure 1150a968cfd8SJonathan Lemon * that we have at least one valid entry, otherwise skip it. 1151a968cfd8SJonathan Lemon */ 1152a968cfd8SJonathan Lemon } else { 1153a968cfd8SJonathan Lemon grp = tgrp; 1154a968cfd8SJonathan Lemon while (grp && grp->gr_type == GT_IGNORE) 1155a968cfd8SJonathan Lemon grp = grp->gr_next; 1156a968cfd8SJonathan Lemon if (! grp) { 1157a968cfd8SJonathan Lemon getexp_err(ep, tgrp); 1158a968cfd8SJonathan Lemon goto nextline; 1159a968cfd8SJonathan Lemon } 11608fae3551SRodney W. Grimes } 11618fae3551SRodney W. Grimes 11628fae3551SRodney W. Grimes /* 11638fae3551SRodney W. Grimes * Loop through hosts, pushing the exports into the kernel. 11648fae3551SRodney W. Grimes * After loop, tgrp points to the start of the list and 11658fae3551SRodney W. Grimes * grp points to the last entry in the list. 11668fae3551SRodney W. Grimes */ 11678fae3551SRodney W. Grimes grp = tgrp; 11688fae3551SRodney W. Grimes do { 116901709abfSIan Dowse if (do_mount(ep, grp, exflags, &anon, dirp, dirplen, 117001709abfSIan Dowse &fsb)) { 11718fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11728fae3551SRodney W. Grimes goto nextline; 11738fae3551SRodney W. Grimes } 11748fae3551SRodney W. Grimes } while (grp->gr_next && (grp = grp->gr_next)); 11758fae3551SRodney W. Grimes 11768fae3551SRodney W. Grimes /* 11778fae3551SRodney W. Grimes * Success. Update the data structures. 11788fae3551SRodney W. Grimes */ 11798fae3551SRodney W. Grimes if (has_host) { 1180a62dc406SDoug Rabson hang_dirp(dirhead, tgrp, ep, opt_flags); 11818fae3551SRodney W. Grimes grp->gr_next = grphead; 11828fae3551SRodney W. Grimes grphead = tgrp; 11838fae3551SRodney W. Grimes } else { 11848fae3551SRodney W. Grimes hang_dirp(dirhead, (struct grouplist *)NULL, ep, 1185a62dc406SDoug Rabson opt_flags); 11868fae3551SRodney W. Grimes free_grp(grp); 11878fae3551SRodney W. Grimes } 11888fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 11898fae3551SRodney W. Grimes if ((ep->ex_flag & EX_LINKED) == 0) { 11908fae3551SRodney W. Grimes ep2 = exphead; 11918fae3551SRodney W. Grimes epp = &exphead; 11928fae3551SRodney W. Grimes 11938fae3551SRodney W. Grimes /* 11948fae3551SRodney W. Grimes * Insert in the list in alphabetical order. 11958fae3551SRodney W. Grimes */ 11968fae3551SRodney W. Grimes while (ep2 && strcmp(ep2->ex_fsdir, ep->ex_fsdir) < 0) { 11978fae3551SRodney W. Grimes epp = &ep2->ex_next; 11988fae3551SRodney W. Grimes ep2 = ep2->ex_next; 11998fae3551SRodney W. Grimes } 12008fae3551SRodney W. Grimes if (ep2) 12018fae3551SRodney W. Grimes ep->ex_next = ep2; 12028fae3551SRodney W. Grimes *epp = ep; 12038fae3551SRodney W. Grimes ep->ex_flag |= EX_LINKED; 12048fae3551SRodney W. Grimes } 12058fae3551SRodney W. Grimes nextline: 12068fae3551SRodney W. Grimes if (dirhead) { 12078fae3551SRodney W. Grimes free_dir(dirhead); 12088fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 12098fae3551SRodney W. Grimes } 12108fae3551SRodney W. Grimes } 12118fae3551SRodney W. Grimes fclose(exp_file); 12128fae3551SRodney W. Grimes } 12138fae3551SRodney W. Grimes 12148fae3551SRodney W. Grimes /* 12158fae3551SRodney W. Grimes * Allocate an export list element 12168fae3551SRodney W. Grimes */ 12178fae3551SRodney W. Grimes struct exportlist * 12188fae3551SRodney W. Grimes get_exp() 12198fae3551SRodney W. Grimes { 12208fae3551SRodney W. Grimes struct exportlist *ep; 12218fae3551SRodney W. Grimes 12228fae3551SRodney W. Grimes ep = (struct exportlist *)malloc(sizeof (struct exportlist)); 12238fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) 12248fae3551SRodney W. Grimes out_of_mem(); 122587564113SPeter Wemm memset(ep, 0, sizeof(struct exportlist)); 12268fae3551SRodney W. Grimes return (ep); 12278fae3551SRodney W. Grimes } 12288fae3551SRodney W. Grimes 12298fae3551SRodney W. Grimes /* 12308fae3551SRodney W. Grimes * Allocate a group list element 12318fae3551SRodney W. Grimes */ 12328fae3551SRodney W. Grimes struct grouplist * 12338fae3551SRodney W. Grimes get_grp() 12348fae3551SRodney W. Grimes { 12358fae3551SRodney W. Grimes struct grouplist *gp; 12368fae3551SRodney W. Grimes 12378fae3551SRodney W. Grimes gp = (struct grouplist *)malloc(sizeof (struct grouplist)); 12388fae3551SRodney W. Grimes if (gp == (struct grouplist *)NULL) 12398fae3551SRodney W. Grimes out_of_mem(); 124087564113SPeter Wemm memset(gp, 0, sizeof(struct grouplist)); 12418fae3551SRodney W. Grimes return (gp); 12428fae3551SRodney W. Grimes } 12438fae3551SRodney W. Grimes 12448fae3551SRodney W. Grimes /* 12458fae3551SRodney W. Grimes * Clean up upon an error in get_exportlist(). 12468fae3551SRodney W. Grimes */ 12478fae3551SRodney W. Grimes void 12488fae3551SRodney W. Grimes getexp_err(ep, grp) 12498fae3551SRodney W. Grimes struct exportlist *ep; 12508fae3551SRodney W. Grimes struct grouplist *grp; 12518fae3551SRodney W. Grimes { 12528fae3551SRodney W. Grimes struct grouplist *tgrp; 12538fae3551SRodney W. Grimes 1254288fa14aSJoerg Wunsch if (!(opt_flags & OP_QUIET)) 125574853402SPhilippe Charnier syslog(LOG_ERR, "bad exports list line %s", line); 12568fae3551SRodney W. Grimes if (ep && (ep->ex_flag & EX_LINKED) == 0) 12578fae3551SRodney W. Grimes free_exp(ep); 12588fae3551SRodney W. Grimes while (grp) { 12598fae3551SRodney W. Grimes tgrp = grp; 12608fae3551SRodney W. Grimes grp = grp->gr_next; 12618fae3551SRodney W. Grimes free_grp(tgrp); 12628fae3551SRodney W. Grimes } 12638fae3551SRodney W. Grimes } 12648fae3551SRodney W. Grimes 12658fae3551SRodney W. Grimes /* 12668fae3551SRodney W. Grimes * Search the export list for a matching fs. 12678fae3551SRodney W. Grimes */ 12688fae3551SRodney W. Grimes struct exportlist * 12698fae3551SRodney W. Grimes ex_search(fsid) 12708fae3551SRodney W. Grimes fsid_t *fsid; 12718fae3551SRodney W. Grimes { 12728fae3551SRodney W. Grimes struct exportlist *ep; 12738fae3551SRodney W. Grimes 12748fae3551SRodney W. Grimes ep = exphead; 12758fae3551SRodney W. Grimes while (ep) { 12768fae3551SRodney W. Grimes if (ep->ex_fs.val[0] == fsid->val[0] && 12778fae3551SRodney W. Grimes ep->ex_fs.val[1] == fsid->val[1]) 12788fae3551SRodney W. Grimes return (ep); 12798fae3551SRodney W. Grimes ep = ep->ex_next; 12808fae3551SRodney W. Grimes } 12818fae3551SRodney W. Grimes return (ep); 12828fae3551SRodney W. Grimes } 12838fae3551SRodney W. Grimes 12848fae3551SRodney W. Grimes /* 12858fae3551SRodney W. Grimes * Add a directory path to the list. 12868fae3551SRodney W. Grimes */ 12878fae3551SRodney W. Grimes char * 12888fae3551SRodney W. Grimes add_expdir(dpp, cp, len) 12898fae3551SRodney W. Grimes struct dirlist **dpp; 12908fae3551SRodney W. Grimes char *cp; 12918fae3551SRodney W. Grimes int len; 12928fae3551SRodney W. Grimes { 12938fae3551SRodney W. Grimes struct dirlist *dp; 12948fae3551SRodney W. Grimes 12958fae3551SRodney W. Grimes dp = (struct dirlist *)malloc(sizeof (struct dirlist) + len); 129674853402SPhilippe Charnier if (dp == (struct dirlist *)NULL) 129774853402SPhilippe Charnier out_of_mem(); 12988fae3551SRodney W. Grimes dp->dp_left = *dpp; 12998fae3551SRodney W. Grimes dp->dp_right = (struct dirlist *)NULL; 13008fae3551SRodney W. Grimes dp->dp_flag = 0; 13018fae3551SRodney W. Grimes dp->dp_hosts = (struct hostlist *)NULL; 13028fae3551SRodney W. Grimes strcpy(dp->dp_dirp, cp); 13038fae3551SRodney W. Grimes *dpp = dp; 13048fae3551SRodney W. Grimes return (dp->dp_dirp); 13058fae3551SRodney W. Grimes } 13068fae3551SRodney W. Grimes 13078fae3551SRodney W. Grimes /* 13088fae3551SRodney W. Grimes * Hang the dir list element off the dirpath binary tree as required 13098fae3551SRodney W. Grimes * and update the entry for host. 13108fae3551SRodney W. Grimes */ 13118fae3551SRodney W. Grimes void 1312a62dc406SDoug Rabson hang_dirp(dp, grp, ep, flags) 13138fae3551SRodney W. Grimes struct dirlist *dp; 13148fae3551SRodney W. Grimes struct grouplist *grp; 13158fae3551SRodney W. Grimes struct exportlist *ep; 1316a62dc406SDoug Rabson int flags; 13178fae3551SRodney W. Grimes { 13188fae3551SRodney W. Grimes struct hostlist *hp; 13198fae3551SRodney W. Grimes struct dirlist *dp2; 13208fae3551SRodney W. Grimes 1321a62dc406SDoug Rabson if (flags & OP_ALLDIRS) { 13228fae3551SRodney W. Grimes if (ep->ex_defdir) 13238fae3551SRodney W. Grimes free((caddr_t)dp); 13248fae3551SRodney W. Grimes else 13258fae3551SRodney W. Grimes ep->ex_defdir = dp; 1326a62dc406SDoug Rabson if (grp == (struct grouplist *)NULL) { 13278fae3551SRodney W. Grimes ep->ex_defdir->dp_flag |= DP_DEFSET; 1328a62dc406SDoug Rabson } else while (grp) { 13298fae3551SRodney W. Grimes hp = get_ht(); 13308fae3551SRodney W. Grimes hp->ht_grp = grp; 13318fae3551SRodney W. Grimes hp->ht_next = ep->ex_defdir->dp_hosts; 13328fae3551SRodney W. Grimes ep->ex_defdir->dp_hosts = hp; 13338fae3551SRodney W. Grimes grp = grp->gr_next; 13348fae3551SRodney W. Grimes } 13358fae3551SRodney W. Grimes } else { 13368fae3551SRodney W. Grimes 13378fae3551SRodney W. Grimes /* 133874853402SPhilippe Charnier * Loop through the directories adding them to the tree. 13398fae3551SRodney W. Grimes */ 13408fae3551SRodney W. Grimes while (dp) { 13418fae3551SRodney W. Grimes dp2 = dp->dp_left; 1342a62dc406SDoug Rabson add_dlist(&ep->ex_dirl, dp, grp, flags); 13438fae3551SRodney W. Grimes dp = dp2; 13448fae3551SRodney W. Grimes } 13458fae3551SRodney W. Grimes } 13468fae3551SRodney W. Grimes } 13478fae3551SRodney W. Grimes 13488fae3551SRodney W. Grimes /* 13498fae3551SRodney W. Grimes * Traverse the binary tree either updating a node that is already there 13508fae3551SRodney W. Grimes * for the new directory or adding the new node. 13518fae3551SRodney W. Grimes */ 13528fae3551SRodney W. Grimes void 1353a62dc406SDoug Rabson add_dlist(dpp, newdp, grp, flags) 13548fae3551SRodney W. Grimes struct dirlist **dpp; 13558fae3551SRodney W. Grimes struct dirlist *newdp; 13568fae3551SRodney W. Grimes struct grouplist *grp; 1357a62dc406SDoug Rabson int flags; 13588fae3551SRodney W. Grimes { 13598fae3551SRodney W. Grimes struct dirlist *dp; 13608fae3551SRodney W. Grimes struct hostlist *hp; 13618fae3551SRodney W. Grimes int cmp; 13628fae3551SRodney W. Grimes 13638fae3551SRodney W. Grimes dp = *dpp; 13648fae3551SRodney W. Grimes if (dp) { 13658fae3551SRodney W. Grimes cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); 13668fae3551SRodney W. Grimes if (cmp > 0) { 1367a62dc406SDoug Rabson add_dlist(&dp->dp_left, newdp, grp, flags); 13688fae3551SRodney W. Grimes return; 13698fae3551SRodney W. Grimes } else if (cmp < 0) { 1370a62dc406SDoug Rabson add_dlist(&dp->dp_right, newdp, grp, flags); 13718fae3551SRodney W. Grimes return; 13728fae3551SRodney W. Grimes } else 13738fae3551SRodney W. Grimes free((caddr_t)newdp); 13748fae3551SRodney W. Grimes } else { 13758fae3551SRodney W. Grimes dp = newdp; 13768fae3551SRodney W. Grimes dp->dp_left = (struct dirlist *)NULL; 13778fae3551SRodney W. Grimes *dpp = dp; 13788fae3551SRodney W. Grimes } 13798fae3551SRodney W. Grimes if (grp) { 13808fae3551SRodney W. Grimes 13818fae3551SRodney W. Grimes /* 13828fae3551SRodney W. Grimes * Hang all of the host(s) off of the directory point. 13838fae3551SRodney W. Grimes */ 13848fae3551SRodney W. Grimes do { 13858fae3551SRodney W. Grimes hp = get_ht(); 13868fae3551SRodney W. Grimes hp->ht_grp = grp; 13878fae3551SRodney W. Grimes hp->ht_next = dp->dp_hosts; 13888fae3551SRodney W. Grimes dp->dp_hosts = hp; 13898fae3551SRodney W. Grimes grp = grp->gr_next; 13908fae3551SRodney W. Grimes } while (grp); 1391a62dc406SDoug Rabson } else { 13928fae3551SRodney W. Grimes dp->dp_flag |= DP_DEFSET; 1393a62dc406SDoug Rabson } 13948fae3551SRodney W. Grimes } 13958fae3551SRodney W. Grimes 13968fae3551SRodney W. Grimes /* 13978fae3551SRodney W. Grimes * Search for a dirpath on the export point. 13988fae3551SRodney W. Grimes */ 13998fae3551SRodney W. Grimes struct dirlist * 14008360efbdSAlfred Perlstein dirp_search(dp, dirp) 14018fae3551SRodney W. Grimes struct dirlist *dp; 14028360efbdSAlfred Perlstein char *dirp; 14038fae3551SRodney W. Grimes { 14048fae3551SRodney W. Grimes int cmp; 14058fae3551SRodney W. Grimes 14068fae3551SRodney W. Grimes if (dp) { 14078360efbdSAlfred Perlstein cmp = strcmp(dp->dp_dirp, dirp); 14088fae3551SRodney W. Grimes if (cmp > 0) 14098360efbdSAlfred Perlstein return (dirp_search(dp->dp_left, dirp)); 14108fae3551SRodney W. Grimes else if (cmp < 0) 14118360efbdSAlfred Perlstein return (dirp_search(dp->dp_right, dirp)); 14128fae3551SRodney W. Grimes else 14138fae3551SRodney W. Grimes return (dp); 14148fae3551SRodney W. Grimes } 14158fae3551SRodney W. Grimes return (dp); 14168fae3551SRodney W. Grimes } 14178fae3551SRodney W. Grimes 14188fae3551SRodney W. Grimes /* 14198fae3551SRodney W. Grimes * Scan for a host match in a directory tree. 14208fae3551SRodney W. Grimes */ 14218fae3551SRodney W. Grimes int 1422a62dc406SDoug Rabson chk_host(dp, saddr, defsetp, hostsetp) 14238fae3551SRodney W. Grimes struct dirlist *dp; 14248360efbdSAlfred Perlstein struct sockaddr *saddr; 14258fae3551SRodney W. Grimes int *defsetp; 1426a62dc406SDoug Rabson int *hostsetp; 14278fae3551SRodney W. Grimes { 14288fae3551SRodney W. Grimes struct hostlist *hp; 14298fae3551SRodney W. Grimes struct grouplist *grp; 14308360efbdSAlfred Perlstein struct addrinfo *ai; 14318fae3551SRodney W. Grimes 14328fae3551SRodney W. Grimes if (dp) { 14338fae3551SRodney W. Grimes if (dp->dp_flag & DP_DEFSET) 1434a62dc406SDoug Rabson *defsetp = dp->dp_flag; 14358fae3551SRodney W. Grimes hp = dp->dp_hosts; 14368fae3551SRodney W. Grimes while (hp) { 14378fae3551SRodney W. Grimes grp = hp->ht_grp; 14388fae3551SRodney W. Grimes switch (grp->gr_type) { 14398fae3551SRodney W. Grimes case GT_HOST: 14408360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 14418360efbdSAlfred Perlstein for (; ai; ai = ai->ai_next) { 144260caaee2SIan Dowse if (!sacmp(ai->ai_addr, saddr, NULL)) { 14438360efbdSAlfred Perlstein *hostsetp = 14448360efbdSAlfred Perlstein (hp->ht_flag | DP_HOSTSET); 14458fae3551SRodney W. Grimes return (1); 1446a62dc406SDoug Rabson } 14478fae3551SRodney W. Grimes } 14488fae3551SRodney W. Grimes break; 14498fae3551SRodney W. Grimes case GT_NET: 145060caaee2SIan Dowse if (!sacmp(saddr, (struct sockaddr *) 145160caaee2SIan Dowse &grp->gr_ptr.gt_net.nt_net, 145260caaee2SIan Dowse (struct sockaddr *) 145360caaee2SIan Dowse &grp->gr_ptr.gt_net.nt_mask)) { 1454a62dc406SDoug Rabson *hostsetp = (hp->ht_flag | DP_HOSTSET); 14558fae3551SRodney W. Grimes return (1); 1456a62dc406SDoug Rabson } 14578fae3551SRodney W. Grimes break; 145860caaee2SIan Dowse } 14598fae3551SRodney W. Grimes hp = hp->ht_next; 14608fae3551SRodney W. Grimes } 14618fae3551SRodney W. Grimes } 14628fae3551SRodney W. Grimes return (0); 14638fae3551SRodney W. Grimes } 14648fae3551SRodney W. Grimes 14658fae3551SRodney W. Grimes /* 14668fae3551SRodney W. Grimes * Scan tree for a host that matches the address. 14678fae3551SRodney W. Grimes */ 14688fae3551SRodney W. Grimes int 14698fae3551SRodney W. Grimes scan_tree(dp, saddr) 14708fae3551SRodney W. Grimes struct dirlist *dp; 14718360efbdSAlfred Perlstein struct sockaddr *saddr; 14728fae3551SRodney W. Grimes { 1473a62dc406SDoug Rabson int defset, hostset; 14748fae3551SRodney W. Grimes 14758fae3551SRodney W. Grimes if (dp) { 14768fae3551SRodney W. Grimes if (scan_tree(dp->dp_left, saddr)) 14778fae3551SRodney W. Grimes return (1); 1478a62dc406SDoug Rabson if (chk_host(dp, saddr, &defset, &hostset)) 14798fae3551SRodney W. Grimes return (1); 14808fae3551SRodney W. Grimes if (scan_tree(dp->dp_right, saddr)) 14818fae3551SRodney W. Grimes return (1); 14828fae3551SRodney W. Grimes } 14838fae3551SRodney W. Grimes return (0); 14848fae3551SRodney W. Grimes } 14858fae3551SRodney W. Grimes 14868fae3551SRodney W. Grimes /* 14878fae3551SRodney W. Grimes * Traverse the dirlist tree and free it up. 14888fae3551SRodney W. Grimes */ 14898fae3551SRodney W. Grimes void 14908fae3551SRodney W. Grimes free_dir(dp) 14918fae3551SRodney W. Grimes struct dirlist *dp; 14928fae3551SRodney W. Grimes { 14938fae3551SRodney W. Grimes 14948fae3551SRodney W. Grimes if (dp) { 14958fae3551SRodney W. Grimes free_dir(dp->dp_left); 14968fae3551SRodney W. Grimes free_dir(dp->dp_right); 14978fae3551SRodney W. Grimes free_host(dp->dp_hosts); 14988fae3551SRodney W. Grimes free((caddr_t)dp); 14998fae3551SRodney W. Grimes } 15008fae3551SRodney W. Grimes } 15018fae3551SRodney W. Grimes 15028fae3551SRodney W. Grimes /* 15038fae3551SRodney W. Grimes * Parse the option string and update fields. 15048fae3551SRodney W. Grimes * Option arguments may either be -<option>=<value> or 15058fae3551SRodney W. Grimes * -<option> <value> 15068fae3551SRodney W. Grimes */ 15078fae3551SRodney W. Grimes int 15088fae3551SRodney W. Grimes do_opt(cpp, endcpp, ep, grp, has_hostp, exflagsp, cr) 15098fae3551SRodney W. Grimes char **cpp, **endcpp; 15108fae3551SRodney W. Grimes struct exportlist *ep; 15118fae3551SRodney W. Grimes struct grouplist *grp; 15128fae3551SRodney W. Grimes int *has_hostp; 15138fae3551SRodney W. Grimes int *exflagsp; 1514c0511d3bSBrian Feldman struct xucred *cr; 15158fae3551SRodney W. Grimes { 15168fae3551SRodney W. Grimes char *cpoptarg, *cpoptend; 15178fae3551SRodney W. Grimes char *cp, *endcp, *cpopt, savedc, savedc2; 15188fae3551SRodney W. Grimes int allflag, usedarg; 15198fae3551SRodney W. Grimes 1520cb479b11SAlfred Perlstein savedc2 = '\0'; 15218fae3551SRodney W. Grimes cpopt = *cpp; 15228fae3551SRodney W. Grimes cpopt++; 15238fae3551SRodney W. Grimes cp = *endcpp; 15248fae3551SRodney W. Grimes savedc = *cp; 15258fae3551SRodney W. Grimes *cp = '\0'; 15268fae3551SRodney W. Grimes while (cpopt && *cpopt) { 15278fae3551SRodney W. Grimes allflag = 1; 15288fae3551SRodney W. Grimes usedarg = -2; 152974853402SPhilippe Charnier if ((cpoptend = strchr(cpopt, ','))) { 15308fae3551SRodney W. Grimes *cpoptend++ = '\0'; 153174853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 15328fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 15338fae3551SRodney W. Grimes } else { 153474853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 15358fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 15368fae3551SRodney W. Grimes else { 15378fae3551SRodney W. Grimes *cp = savedc; 15388fae3551SRodney W. Grimes nextfield(&cp, &endcp); 15398fae3551SRodney W. Grimes **endcpp = '\0'; 15408fae3551SRodney W. Grimes if (endcp > cp && *cp != '-') { 15418fae3551SRodney W. Grimes cpoptarg = cp; 15428fae3551SRodney W. Grimes savedc2 = *endcp; 15438fae3551SRodney W. Grimes *endcp = '\0'; 15448fae3551SRodney W. Grimes usedarg = 0; 15458fae3551SRodney W. Grimes } 15468fae3551SRodney W. Grimes } 15478fae3551SRodney W. Grimes } 15488fae3551SRodney W. Grimes if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 15498fae3551SRodney W. Grimes *exflagsp |= MNT_EXRDONLY; 15508fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "maproot") || 15518fae3551SRodney W. Grimes !(allflag = strcmp(cpopt, "mapall")) || 15528fae3551SRodney W. Grimes !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) { 15538fae3551SRodney W. Grimes usedarg++; 15548fae3551SRodney W. Grimes parsecred(cpoptarg, cr); 15558fae3551SRodney W. Grimes if (allflag == 0) { 15568fae3551SRodney W. Grimes *exflagsp |= MNT_EXPORTANON; 15578fae3551SRodney W. Grimes opt_flags |= OP_MAPALL; 15588fae3551SRodney W. Grimes } else 15598fae3551SRodney W. Grimes opt_flags |= OP_MAPROOT; 15608fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "mask") || 15618fae3551SRodney W. Grimes !strcmp(cpopt, "m"))) { 15628fae3551SRodney W. Grimes if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { 156374853402SPhilippe Charnier syslog(LOG_ERR, "bad mask: %s", cpoptarg); 15648fae3551SRodney W. Grimes return (1); 15658fae3551SRodney W. Grimes } 15668fae3551SRodney W. Grimes usedarg++; 15678fae3551SRodney W. Grimes opt_flags |= OP_MASK; 15688fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "network") || 15698fae3551SRodney W. Grimes !strcmp(cpopt, "n"))) { 15708360efbdSAlfred Perlstein if (strchr(cpoptarg, '/') != NULL) { 15718360efbdSAlfred Perlstein if (debug) 15728360efbdSAlfred Perlstein fprintf(stderr, "setting OP_MASKLEN\n"); 15738360efbdSAlfred Perlstein opt_flags |= OP_MASKLEN; 15748360efbdSAlfred Perlstein } 15758fae3551SRodney W. Grimes if (grp->gr_type != GT_NULL) { 157674853402SPhilippe Charnier syslog(LOG_ERR, "network/host conflict"); 15778fae3551SRodney W. Grimes return (1); 15788fae3551SRodney W. Grimes } else if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 0)) { 157974853402SPhilippe Charnier syslog(LOG_ERR, "bad net: %s", cpoptarg); 15808fae3551SRodney W. Grimes return (1); 15818fae3551SRodney W. Grimes } 15828fae3551SRodney W. Grimes grp->gr_type = GT_NET; 15838fae3551SRodney W. Grimes *has_hostp = 1; 15848fae3551SRodney W. Grimes usedarg++; 15858fae3551SRodney W. Grimes opt_flags |= OP_NET; 15868fae3551SRodney W. Grimes } else if (!strcmp(cpopt, "alldirs")) { 15878fae3551SRodney W. Grimes opt_flags |= OP_ALLDIRS; 1588cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "public")) { 1589cb3923e0SDoug Rabson *exflagsp |= MNT_EXPUBLIC; 1590cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "webnfs")) { 1591cb3923e0SDoug Rabson *exflagsp |= (MNT_EXPUBLIC|MNT_EXRDONLY|MNT_EXPORTANON); 1592cb3923e0SDoug Rabson opt_flags |= OP_MAPALL; 1593cb3923e0SDoug Rabson } else if (cpoptarg && !strcmp(cpopt, "index")) { 1594cb3923e0SDoug Rabson ep->ex_indexfile = strdup(cpoptarg); 1595288fa14aSJoerg Wunsch } else if (!strcmp(cpopt, "quiet")) { 1596288fa14aSJoerg Wunsch opt_flags |= OP_QUIET; 15978fae3551SRodney W. Grimes } else { 159874853402SPhilippe Charnier syslog(LOG_ERR, "bad opt %s", cpopt); 15998fae3551SRodney W. Grimes return (1); 16008fae3551SRodney W. Grimes } 16018fae3551SRodney W. Grimes if (usedarg >= 0) { 16028fae3551SRodney W. Grimes *endcp = savedc2; 16038fae3551SRodney W. Grimes **endcpp = savedc; 16048fae3551SRodney W. Grimes if (usedarg > 0) { 16058fae3551SRodney W. Grimes *cpp = cp; 16068fae3551SRodney W. Grimes *endcpp = endcp; 16078fae3551SRodney W. Grimes } 16088fae3551SRodney W. Grimes return (0); 16098fae3551SRodney W. Grimes } 16108fae3551SRodney W. Grimes cpopt = cpoptend; 16118fae3551SRodney W. Grimes } 16128fae3551SRodney W. Grimes **endcpp = savedc; 16138fae3551SRodney W. Grimes return (0); 16148fae3551SRodney W. Grimes } 16158fae3551SRodney W. Grimes 16168fae3551SRodney W. Grimes /* 16178fae3551SRodney W. Grimes * Translate a character string to the corresponding list of network 16188fae3551SRodney W. Grimes * addresses for a hostname. 16198fae3551SRodney W. Grimes */ 16208fae3551SRodney W. Grimes int 16218b5a6d67SBill Paul get_host(cp, grp, tgrp) 16228fae3551SRodney W. Grimes char *cp; 16238fae3551SRodney W. Grimes struct grouplist *grp; 16248b5a6d67SBill Paul struct grouplist *tgrp; 16258fae3551SRodney W. Grimes { 16268b5a6d67SBill Paul struct grouplist *checkgrp; 162701709abfSIan Dowse struct addrinfo *ai, *tai, hints; 16288360efbdSAlfred Perlstein int ecode; 16298360efbdSAlfred Perlstein char host[NI_MAXHOST]; 16308fae3551SRodney W. Grimes 16318360efbdSAlfred Perlstein if (grp->gr_type != GT_NULL) { 16328360efbdSAlfred Perlstein syslog(LOG_ERR, "Bad netgroup type for ip host %s", cp); 16338fae3551SRodney W. Grimes return (1); 16348fae3551SRodney W. Grimes } 16358360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 16368360efbdSAlfred Perlstein hints.ai_flags = AI_CANONNAME; 16378360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_UDP; 16388360efbdSAlfred Perlstein ecode = getaddrinfo(cp, NULL, &hints, &ai); 16398360efbdSAlfred Perlstein if (ecode != 0) { 164001709abfSIan Dowse syslog(LOG_ERR,"can't get address info for host %s", cp); 16418360efbdSAlfred Perlstein return 1; 16428fae3551SRodney W. Grimes } 16438360efbdSAlfred Perlstein grp->gr_ptr.gt_addrinfo = ai; 16448360efbdSAlfred Perlstein while (ai != NULL) { 16458360efbdSAlfred Perlstein if (ai->ai_canonname == NULL) { 16468360efbdSAlfred Perlstein if (getnameinfo(ai->ai_addr, ai->ai_addrlen, host, 16478360efbdSAlfred Perlstein sizeof host, NULL, 0, ninumeric) != 0) 16488360efbdSAlfred Perlstein strlcpy(host, "?", sizeof(host)); 16498360efbdSAlfred Perlstein ai->ai_canonname = strdup(host); 16508360efbdSAlfred Perlstein ai->ai_flags |= AI_CANONNAME; 16516d359f31SIan Dowse } 16528fae3551SRodney W. Grimes if (debug) 165301709abfSIan Dowse fprintf(stderr, "got host %s\n", ai->ai_canonname); 165401709abfSIan Dowse /* 165501709abfSIan Dowse * Sanity check: make sure we don't already have an entry 165601709abfSIan Dowse * for this host in the grouplist. 165701709abfSIan Dowse */ 165801709abfSIan Dowse for (checkgrp = tgrp; checkgrp != NULL; 165901709abfSIan Dowse checkgrp = checkgrp->gr_next) { 166001709abfSIan Dowse if (checkgrp->gr_type != GT_HOST) 166101709abfSIan Dowse continue; 166201709abfSIan Dowse for (tai = checkgrp->gr_ptr.gt_addrinfo; tai != NULL; 166301709abfSIan Dowse tai = tai->ai_next) { 166460caaee2SIan Dowse if (sacmp(tai->ai_addr, ai->ai_addr, NULL) != 0) 166501709abfSIan Dowse continue; 166601709abfSIan Dowse if (debug) 166701709abfSIan Dowse fprintf(stderr, 166801709abfSIan Dowse "ignoring duplicate host %s\n", 166901709abfSIan Dowse ai->ai_canonname); 167001709abfSIan Dowse grp->gr_type = GT_IGNORE; 167101709abfSIan Dowse return (0); 167201709abfSIan Dowse } 167301709abfSIan Dowse } 16748360efbdSAlfred Perlstein ai = ai->ai_next; 16758360efbdSAlfred Perlstein } 167601709abfSIan Dowse grp->gr_type = GT_HOST; 16778fae3551SRodney W. Grimes return (0); 16788fae3551SRodney W. Grimes } 16798fae3551SRodney W. Grimes 16808fae3551SRodney W. Grimes /* 16818fae3551SRodney W. Grimes * Free up an exports list component 16828fae3551SRodney W. Grimes */ 16838fae3551SRodney W. Grimes void 16848fae3551SRodney W. Grimes free_exp(ep) 16858fae3551SRodney W. Grimes struct exportlist *ep; 16868fae3551SRodney W. Grimes { 16878fae3551SRodney W. Grimes 16888fae3551SRodney W. Grimes if (ep->ex_defdir) { 16898fae3551SRodney W. Grimes free_host(ep->ex_defdir->dp_hosts); 16908fae3551SRodney W. Grimes free((caddr_t)ep->ex_defdir); 16918fae3551SRodney W. Grimes } 16928fae3551SRodney W. Grimes if (ep->ex_fsdir) 16938fae3551SRodney W. Grimes free(ep->ex_fsdir); 1694cb3923e0SDoug Rabson if (ep->ex_indexfile) 1695cb3923e0SDoug Rabson free(ep->ex_indexfile); 16968fae3551SRodney W. Grimes free_dir(ep->ex_dirl); 16978fae3551SRodney W. Grimes free((caddr_t)ep); 16988fae3551SRodney W. Grimes } 16998fae3551SRodney W. Grimes 17008fae3551SRodney W. Grimes /* 17018fae3551SRodney W. Grimes * Free hosts. 17028fae3551SRodney W. Grimes */ 17038fae3551SRodney W. Grimes void 17048fae3551SRodney W. Grimes free_host(hp) 17058fae3551SRodney W. Grimes struct hostlist *hp; 17068fae3551SRodney W. Grimes { 17078fae3551SRodney W. Grimes struct hostlist *hp2; 17088fae3551SRodney W. Grimes 17098fae3551SRodney W. Grimes while (hp) { 17108fae3551SRodney W. Grimes hp2 = hp; 17118fae3551SRodney W. Grimes hp = hp->ht_next; 17128fae3551SRodney W. Grimes free((caddr_t)hp2); 17138fae3551SRodney W. Grimes } 17148fae3551SRodney W. Grimes } 17158fae3551SRodney W. Grimes 17168fae3551SRodney W. Grimes struct hostlist * 17178fae3551SRodney W. Grimes get_ht() 17188fae3551SRodney W. Grimes { 17198fae3551SRodney W. Grimes struct hostlist *hp; 17208fae3551SRodney W. Grimes 17218fae3551SRodney W. Grimes hp = (struct hostlist *)malloc(sizeof (struct hostlist)); 17228fae3551SRodney W. Grimes if (hp == (struct hostlist *)NULL) 17238fae3551SRodney W. Grimes out_of_mem(); 17248fae3551SRodney W. Grimes hp->ht_next = (struct hostlist *)NULL; 1725a62dc406SDoug Rabson hp->ht_flag = 0; 17268fae3551SRodney W. Grimes return (hp); 17278fae3551SRodney W. Grimes } 17288fae3551SRodney W. Grimes 17298fae3551SRodney W. Grimes /* 17308fae3551SRodney W. Grimes * Out of memory, fatal 17318fae3551SRodney W. Grimes */ 17328fae3551SRodney W. Grimes void 17338fae3551SRodney W. Grimes out_of_mem() 17348fae3551SRodney W. Grimes { 17358fae3551SRodney W. Grimes 173674853402SPhilippe Charnier syslog(LOG_ERR, "out of memory"); 17378fae3551SRodney W. Grimes exit(2); 17388fae3551SRodney W. Grimes } 17398fae3551SRodney W. Grimes 17408fae3551SRodney W. Grimes /* 17418fae3551SRodney W. Grimes * Do the mount syscall with the update flag to push the export info into 17428fae3551SRodney W. Grimes * the kernel. 17438fae3551SRodney W. Grimes */ 17448fae3551SRodney W. Grimes int 17458fae3551SRodney W. Grimes do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb) 17468fae3551SRodney W. Grimes struct exportlist *ep; 17478fae3551SRodney W. Grimes struct grouplist *grp; 17488fae3551SRodney W. Grimes int exflags; 1749c0511d3bSBrian Feldman struct xucred *anoncrp; 17508fae3551SRodney W. Grimes char *dirp; 17518fae3551SRodney W. Grimes int dirplen; 17528fae3551SRodney W. Grimes struct statfs *fsb; 17538fae3551SRodney W. Grimes { 1754f93caef2SIan Dowse struct statfs fsb1; 17558360efbdSAlfred Perlstein struct addrinfo *ai; 175660caaee2SIan Dowse struct export_args *eap; 17578360efbdSAlfred Perlstein char *cp = NULL; 17588fae3551SRodney W. Grimes int done; 17598fae3551SRodney W. Grimes char savedc = '\0'; 17608fae3551SRodney W. Grimes union { 17618fae3551SRodney W. Grimes struct ufs_args ua; 17628fae3551SRodney W. Grimes struct iso_args ia; 1763a62dc406SDoug Rabson struct msdosfs_args da; 17649300c696SSemen Ustimenko struct ntfs_args na; 17658fae3551SRodney W. Grimes } args; 17668fae3551SRodney W. Grimes 176760caaee2SIan Dowse bzero(&args, sizeof args); 176860caaee2SIan Dowse /* XXX, we assume that all xx_args look like ufs_args. */ 17698fae3551SRodney W. Grimes args.ua.fspec = 0; 177060caaee2SIan Dowse eap = &args.ua.export; 177160caaee2SIan Dowse 177260caaee2SIan Dowse eap->ex_flags = exflags; 177360caaee2SIan Dowse eap->ex_anon = *anoncrp; 177460caaee2SIan Dowse eap->ex_indexfile = ep->ex_indexfile; 17756d359f31SIan Dowse if (grp->gr_type == GT_HOST) 17768360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 17776d359f31SIan Dowse else 17786d359f31SIan Dowse ai = NULL; 17798fae3551SRodney W. Grimes done = FALSE; 17808fae3551SRodney W. Grimes while (!done) { 17818fae3551SRodney W. Grimes switch (grp->gr_type) { 17828fae3551SRodney W. Grimes case GT_HOST: 17836d359f31SIan Dowse if (ai->ai_addr->sa_family == AF_INET6 && have_v6 == 0) 17848360efbdSAlfred Perlstein goto skip; 178560caaee2SIan Dowse eap->ex_addr = ai->ai_addr; 178660caaee2SIan Dowse eap->ex_addrlen = ai->ai_addrlen; 178760caaee2SIan Dowse eap->ex_masklen = 0; 17888fae3551SRodney W. Grimes break; 17898fae3551SRodney W. Grimes case GT_NET: 179060caaee2SIan Dowse if (grp->gr_ptr.gt_net.nt_net.ss_family == AF_INET6 && 17918360efbdSAlfred Perlstein have_v6 == 0) 17928360efbdSAlfred Perlstein goto skip; 179360caaee2SIan Dowse eap->ex_addr = 179460caaee2SIan Dowse (struct sockaddr *)&grp->gr_ptr.gt_net.nt_net; 179560caaee2SIan Dowse eap->ex_addrlen = args.ua.export.ex_addr->sa_len; 179660caaee2SIan Dowse eap->ex_mask = 179760caaee2SIan Dowse (struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask; 179860caaee2SIan Dowse eap->ex_masklen = args.ua.export.ex_mask->sa_len; 17998fae3551SRodney W. Grimes break; 18006d359f31SIan Dowse case GT_DEFAULT: 180160caaee2SIan Dowse eap->ex_addr = NULL; 180260caaee2SIan Dowse eap->ex_addrlen = 0; 180360caaee2SIan Dowse eap->ex_mask = NULL; 180460caaee2SIan Dowse eap->ex_masklen = 0; 18056d359f31SIan Dowse break; 18068b5a6d67SBill Paul case GT_IGNORE: 18078b5a6d67SBill Paul return(0); 18088b5a6d67SBill Paul break; 18098fae3551SRodney W. Grimes default: 181074853402SPhilippe Charnier syslog(LOG_ERR, "bad grouptype"); 18118fae3551SRodney W. Grimes if (cp) 18128fae3551SRodney W. Grimes *cp = savedc; 18138fae3551SRodney W. Grimes return (1); 18148fae3551SRodney W. Grimes }; 18158fae3551SRodney W. Grimes 18168fae3551SRodney W. Grimes /* 18178fae3551SRodney W. Grimes * XXX: 18188fae3551SRodney W. Grimes * Maybe I should just use the fsb->f_mntonname path instead 18198fae3551SRodney W. Grimes * of looping back up the dirp to the mount point?? 18208fae3551SRodney W. Grimes * Also, needs to know how to export all types of local 182187564113SPeter Wemm * exportable filesystems and not just "ufs". 18228fae3551SRodney W. Grimes */ 1823a62dc406SDoug Rabson while (mount(fsb->f_fstypename, dirp, 18248fae3551SRodney W. Grimes fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) { 18258fae3551SRodney W. Grimes if (cp) 18268fae3551SRodney W. Grimes *cp-- = savedc; 18278fae3551SRodney W. Grimes else 18288fae3551SRodney W. Grimes cp = dirp + dirplen - 1; 1829288fa14aSJoerg Wunsch if (opt_flags & OP_QUIET) 1830288fa14aSJoerg Wunsch return (1); 18318fae3551SRodney W. Grimes if (errno == EPERM) { 183201709abfSIan Dowse if (debug) 183301709abfSIan Dowse warnx("can't change attributes for %s", 183401709abfSIan Dowse dirp); 18358fae3551SRodney W. Grimes syslog(LOG_ERR, 183674853402SPhilippe Charnier "can't change attributes for %s", dirp); 18378fae3551SRodney W. Grimes return (1); 18388fae3551SRodney W. Grimes } 18398fae3551SRodney W. Grimes if (opt_flags & OP_ALLDIRS) { 1840288fa14aSJoerg Wunsch if (errno == EINVAL) 1841288fa14aSJoerg Wunsch syslog(LOG_ERR, 1842288fa14aSJoerg Wunsch "-alldirs requested but %s is not a filesystem mountpoint", 1843288fa14aSJoerg Wunsch dirp); 1844288fa14aSJoerg Wunsch else 1845288fa14aSJoerg Wunsch syslog(LOG_ERR, 1846288fa14aSJoerg Wunsch "could not remount %s: %m", 18473980ac4fSGarrett Wollman dirp); 18488fae3551SRodney W. Grimes return (1); 18498fae3551SRodney W. Grimes } 18508fae3551SRodney W. Grimes /* back up over the last component */ 18518fae3551SRodney W. Grimes while (*cp == '/' && cp > dirp) 18528fae3551SRodney W. Grimes cp--; 18538fae3551SRodney W. Grimes while (*(cp - 1) != '/' && cp > dirp) 18548fae3551SRodney W. Grimes cp--; 18558fae3551SRodney W. Grimes if (cp == dirp) { 18568fae3551SRodney W. Grimes if (debug) 185774853402SPhilippe Charnier warnx("mnt unsucc"); 185874853402SPhilippe Charnier syslog(LOG_ERR, "can't export %s", dirp); 18598fae3551SRodney W. Grimes return (1); 18608fae3551SRodney W. Grimes } 18618fae3551SRodney W. Grimes savedc = *cp; 18628fae3551SRodney W. Grimes *cp = '\0'; 1863f93caef2SIan Dowse /* Check that we're still on the same filesystem. */ 1864f93caef2SIan Dowse if (statfs(dirp, &fsb1) != 0 || bcmp(&fsb1.f_fsid, 1865f93caef2SIan Dowse &fsb->f_fsid, sizeof(fsb1.f_fsid)) != 0) { 1866f93caef2SIan Dowse *cp = savedc; 1867f93caef2SIan Dowse syslog(LOG_ERR, "can't export %s", dirp); 1868f93caef2SIan Dowse return (1); 1869f93caef2SIan Dowse } 18708fae3551SRodney W. Grimes } 18718360efbdSAlfred Perlstein skip: 18726d359f31SIan Dowse if (ai != NULL) 18738360efbdSAlfred Perlstein ai = ai->ai_next; 18748360efbdSAlfred Perlstein if (ai == NULL) 18758fae3551SRodney W. Grimes done = TRUE; 18768fae3551SRodney W. Grimes } 18778fae3551SRodney W. Grimes if (cp) 18788fae3551SRodney W. Grimes *cp = savedc; 18798fae3551SRodney W. Grimes return (0); 18808fae3551SRodney W. Grimes } 18818fae3551SRodney W. Grimes 18828fae3551SRodney W. Grimes /* 18838fae3551SRodney W. Grimes * Translate a net address. 188460caaee2SIan Dowse * 188560caaee2SIan Dowse * If `maskflg' is nonzero, then `cp' is a netmask, not a network address. 18868fae3551SRodney W. Grimes */ 18878fae3551SRodney W. Grimes int 18888fae3551SRodney W. Grimes get_net(cp, net, maskflg) 18898fae3551SRodney W. Grimes char *cp; 18908fae3551SRodney W. Grimes struct netmsk *net; 18918fae3551SRodney W. Grimes int maskflg; 18928fae3551SRodney W. Grimes { 1893931c04f1SIan Dowse struct netent *np = NULL; 18948360efbdSAlfred Perlstein char *name, *p, *prefp; 189560caaee2SIan Dowse struct sockaddr_in sin; 1896931c04f1SIan Dowse struct sockaddr *sa = NULL; 18978360efbdSAlfred Perlstein struct addrinfo hints, *ai = NULL; 18988360efbdSAlfred Perlstein char netname[NI_MAXHOST]; 18998360efbdSAlfred Perlstein long preflen; 19008fae3551SRodney W. Grimes 190101709abfSIan Dowse p = prefp = NULL; 19028360efbdSAlfred Perlstein if ((opt_flags & OP_MASKLEN) && !maskflg) { 19038360efbdSAlfred Perlstein p = strchr(cp, '/'); 19048360efbdSAlfred Perlstein *p = '\0'; 19058360efbdSAlfred Perlstein prefp = p + 1; 19068360efbdSAlfred Perlstein } 19078360efbdSAlfred Perlstein 1908931c04f1SIan Dowse /* 1909931c04f1SIan Dowse * Check for a numeric address first. We wish to avoid 1910931c04f1SIan Dowse * possible DNS lookups in getnetbyname(). 1911931c04f1SIan Dowse */ 1912931c04f1SIan Dowse if (isxdigit(*cp) || *cp == ':') { 19138360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 191460caaee2SIan Dowse /* Ensure the mask and the network have the same family. */ 191560caaee2SIan Dowse if (maskflg && (opt_flags & OP_NET)) 191660caaee2SIan Dowse hints.ai_family = net->nt_net.ss_family; 191760caaee2SIan Dowse else if (!maskflg && (opt_flags & OP_HAVEMASK)) 191860caaee2SIan Dowse hints.ai_family = net->nt_mask.ss_family; 191960caaee2SIan Dowse else 19208360efbdSAlfred Perlstein hints.ai_family = AF_UNSPEC; 19218360efbdSAlfred Perlstein hints.ai_flags = AI_NUMERICHOST; 1922931c04f1SIan Dowse if (getaddrinfo(cp, NULL, &hints, &ai) == 0) 1923931c04f1SIan Dowse sa = ai->ai_addr; 1924931c04f1SIan Dowse if (sa != NULL && ai->ai_family == AF_INET) { 19258fae3551SRodney W. Grimes /* 192660caaee2SIan Dowse * The address in `cp' is really a network address, so 192760caaee2SIan Dowse * use inet_network() to re-interpret this correctly. 192860caaee2SIan Dowse * e.g. "127.1" means 127.1.0.0, not 127.0.0.1. 19298fae3551SRodney W. Grimes */ 193060caaee2SIan Dowse bzero(&sin, sizeof sin); 19318360efbdSAlfred Perlstein sin.sin_family = AF_INET; 19328360efbdSAlfred Perlstein sin.sin_len = sizeof sin; 19338360efbdSAlfred Perlstein sin.sin_addr = inet_makeaddr(inet_network(cp), 0); 19348360efbdSAlfred Perlstein if (debug) 193560caaee2SIan Dowse fprintf(stderr, "get_net: v4 addr %s\n", 193660caaee2SIan Dowse inet_ntoa(sin.sin_addr)); 19378360efbdSAlfred Perlstein sa = (struct sockaddr *)&sin; 1938931c04f1SIan Dowse } 1939931c04f1SIan Dowse } 1940931c04f1SIan Dowse if (sa == NULL && (np = getnetbyname(cp)) != NULL) { 1941931c04f1SIan Dowse bzero(&sin, sizeof sin); 1942931c04f1SIan Dowse sin.sin_family = AF_INET; 1943931c04f1SIan Dowse sin.sin_len = sizeof sin; 1944931c04f1SIan Dowse sin.sin_addr = inet_makeaddr(np->n_net, 0); 1945931c04f1SIan Dowse sa = (struct sockaddr *)&sin; 1946931c04f1SIan Dowse } 1947931c04f1SIan Dowse if (sa == NULL) 19488360efbdSAlfred Perlstein goto fail; 19498360efbdSAlfred Perlstein 195060caaee2SIan Dowse if (maskflg) { 195160caaee2SIan Dowse /* The specified sockaddr is a mask. */ 195260caaee2SIan Dowse if (checkmask(sa) != 0) 19538360efbdSAlfred Perlstein goto fail; 195460caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 195560caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 195660caaee2SIan Dowse } else { 195760caaee2SIan Dowse /* The specified sockaddr is a network address. */ 195860caaee2SIan Dowse bcopy(sa, &net->nt_net, sa->sa_len); 19590f4b7baaSPaul Traina 196060caaee2SIan Dowse /* Get a network name for the export list. */ 196160caaee2SIan Dowse if (np) { 196260caaee2SIan Dowse name = np->n_name; 196360caaee2SIan Dowse } else if (getnameinfo(sa, sa->sa_len, netname, sizeof netname, 196460caaee2SIan Dowse NULL, 0, ninumeric) == 0) { 196560caaee2SIan Dowse name = netname; 196660caaee2SIan Dowse } else { 196760caaee2SIan Dowse goto fail; 196860caaee2SIan Dowse } 196960caaee2SIan Dowse if ((net->nt_name = strdup(name)) == NULL) 197060caaee2SIan Dowse out_of_mem(); 197160caaee2SIan Dowse 197260caaee2SIan Dowse /* 197360caaee2SIan Dowse * Extract a mask from either a "/<masklen>" suffix, or 197460caaee2SIan Dowse * from the class of an IPv4 address. 197560caaee2SIan Dowse */ 19768360efbdSAlfred Perlstein if (opt_flags & OP_MASKLEN) { 19778360efbdSAlfred Perlstein preflen = strtol(prefp, NULL, 10); 197860caaee2SIan Dowse if (preflen < 0L || preflen == LONG_MAX) 19798360efbdSAlfred Perlstein goto fail; 198060caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 198160caaee2SIan Dowse if (makemask(&net->nt_mask, (int)preflen) != 0) 198260caaee2SIan Dowse goto fail; 198360caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 19848360efbdSAlfred Perlstein *p = '/'; 198560caaee2SIan Dowse } else if (sa->sa_family == AF_INET && 198660caaee2SIan Dowse (opt_flags & OP_MASK) == 0) { 198760caaee2SIan Dowse in_addr_t addr; 19888360efbdSAlfred Perlstein 198960caaee2SIan Dowse addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; 199060caaee2SIan Dowse if (IN_CLASSA(addr)) 199160caaee2SIan Dowse preflen = 8; 199260caaee2SIan Dowse else if (IN_CLASSB(addr)) 199360caaee2SIan Dowse preflen = 16; 199460caaee2SIan Dowse else if (IN_CLASSC(addr)) 199560caaee2SIan Dowse preflen = 24; 199660caaee2SIan Dowse else if (IN_CLASSD(addr)) 199760caaee2SIan Dowse preflen = 28; 19988360efbdSAlfred Perlstein else 199960caaee2SIan Dowse preflen = 32; /* XXX */ 200060caaee2SIan Dowse 200160caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 200260caaee2SIan Dowse makemask(&net->nt_mask, (int)preflen); 200360caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 200460caaee2SIan Dowse } 20058360efbdSAlfred Perlstein } 20068360efbdSAlfred Perlstein 20078360efbdSAlfred Perlstein if (ai) 20088360efbdSAlfred Perlstein freeaddrinfo(ai); 20098360efbdSAlfred Perlstein return 0; 20108360efbdSAlfred Perlstein 20118360efbdSAlfred Perlstein fail: 20128360efbdSAlfred Perlstein if (ai) 20138360efbdSAlfred Perlstein freeaddrinfo(ai); 20148360efbdSAlfred Perlstein return 1; 20158fae3551SRodney W. Grimes } 20168fae3551SRodney W. Grimes 20178fae3551SRodney W. Grimes /* 20188fae3551SRodney W. Grimes * Parse out the next white space separated field 20198fae3551SRodney W. Grimes */ 20208fae3551SRodney W. Grimes void 20218fae3551SRodney W. Grimes nextfield(cp, endcp) 20228fae3551SRodney W. Grimes char **cp; 20238fae3551SRodney W. Grimes char **endcp; 20248fae3551SRodney W. Grimes { 20258fae3551SRodney W. Grimes char *p; 20268fae3551SRodney W. Grimes 20278fae3551SRodney W. Grimes p = *cp; 20288fae3551SRodney W. Grimes while (*p == ' ' || *p == '\t') 20298fae3551SRodney W. Grimes p++; 20308fae3551SRodney W. Grimes if (*p == '\n' || *p == '\0') 20318fae3551SRodney W. Grimes *cp = *endcp = p; 20328fae3551SRodney W. Grimes else { 20338fae3551SRodney W. Grimes *cp = p++; 20348fae3551SRodney W. Grimes while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 20358fae3551SRodney W. Grimes p++; 20368fae3551SRodney W. Grimes *endcp = p; 20378fae3551SRodney W. Grimes } 20388fae3551SRodney W. Grimes } 20398fae3551SRodney W. Grimes 20408fae3551SRodney W. Grimes /* 20418fae3551SRodney W. Grimes * Get an exports file line. Skip over blank lines and handle line 20428fae3551SRodney W. Grimes * continuations. 20438fae3551SRodney W. Grimes */ 20448fae3551SRodney W. Grimes int 20458fae3551SRodney W. Grimes get_line() 20468fae3551SRodney W. Grimes { 20478fae3551SRodney W. Grimes char *p, *cp; 204891ca1a91SIan Dowse size_t len; 20498fae3551SRodney W. Grimes int totlen, cont_line; 20508fae3551SRodney W. Grimes 20518fae3551SRodney W. Grimes /* 20528fae3551SRodney W. Grimes * Loop around ignoring blank lines and getting all continuation lines. 20538fae3551SRodney W. Grimes */ 20548fae3551SRodney W. Grimes p = line; 20558fae3551SRodney W. Grimes totlen = 0; 20568fae3551SRodney W. Grimes do { 205791ca1a91SIan Dowse if ((p = fgetln(exp_file, &len)) == NULL) 20588fae3551SRodney W. Grimes return (0); 20598fae3551SRodney W. Grimes cp = p + len - 1; 20608fae3551SRodney W. Grimes cont_line = 0; 20618fae3551SRodney W. Grimes while (cp >= p && 20628fae3551SRodney W. Grimes (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '\\')) { 20638fae3551SRodney W. Grimes if (*cp == '\\') 20648fae3551SRodney W. Grimes cont_line = 1; 20658fae3551SRodney W. Grimes cp--; 20668fae3551SRodney W. Grimes len--; 20678fae3551SRodney W. Grimes } 2068376f8390SDima Dorfman if (cont_line) { 2069376f8390SDima Dorfman *++cp = ' '; 2070376f8390SDima Dorfman len++; 2071376f8390SDima Dorfman } 207291ca1a91SIan Dowse if (linesize < len + totlen + 1) { 207391ca1a91SIan Dowse linesize = len + totlen + 1; 207491ca1a91SIan Dowse line = realloc(line, linesize); 207591ca1a91SIan Dowse if (line == NULL) 207691ca1a91SIan Dowse out_of_mem(); 207791ca1a91SIan Dowse } 207891ca1a91SIan Dowse memcpy(line + totlen, p, len); 20798fae3551SRodney W. Grimes totlen += len; 208091ca1a91SIan Dowse line[totlen] = '\0'; 20818fae3551SRodney W. Grimes } while (totlen == 0 || cont_line); 20828fae3551SRodney W. Grimes return (1); 20838fae3551SRodney W. Grimes } 20848fae3551SRodney W. Grimes 20858fae3551SRodney W. Grimes /* 20868fae3551SRodney W. Grimes * Parse a description of a credential. 20878fae3551SRodney W. Grimes */ 20888fae3551SRodney W. Grimes void 20898fae3551SRodney W. Grimes parsecred(namelist, cr) 20908fae3551SRodney W. Grimes char *namelist; 2091c0511d3bSBrian Feldman struct xucred *cr; 20928fae3551SRodney W. Grimes { 20938fae3551SRodney W. Grimes char *name; 20948fae3551SRodney W. Grimes int cnt; 20958fae3551SRodney W. Grimes char *names; 20968fae3551SRodney W. Grimes struct passwd *pw; 20978fae3551SRodney W. Grimes struct group *gr; 20988fae3551SRodney W. Grimes int ngroups, groups[NGROUPS + 1]; 20998fae3551SRodney W. Grimes 210076183f34SDima Dorfman cr->cr_version = XUCRED_VERSION; 21018fae3551SRodney W. Grimes /* 210274853402SPhilippe Charnier * Set up the unprivileged user. 21038fae3551SRodney W. Grimes */ 21048fae3551SRodney W. Grimes cr->cr_uid = -2; 21058fae3551SRodney W. Grimes cr->cr_groups[0] = -2; 21068fae3551SRodney W. Grimes cr->cr_ngroups = 1; 21078fae3551SRodney W. Grimes /* 21088fae3551SRodney W. Grimes * Get the user's password table entry. 21098fae3551SRodney W. Grimes */ 21108fae3551SRodney W. Grimes names = strsep(&namelist, " \t\n"); 21118fae3551SRodney W. Grimes name = strsep(&names, ":"); 21128fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') 21138fae3551SRodney W. Grimes pw = getpwuid(atoi(name)); 21148fae3551SRodney W. Grimes else 21158fae3551SRodney W. Grimes pw = getpwnam(name); 21168fae3551SRodney W. Grimes /* 21178fae3551SRodney W. Grimes * Credentials specified as those of a user. 21188fae3551SRodney W. Grimes */ 21198fae3551SRodney W. Grimes if (names == NULL) { 21208fae3551SRodney W. Grimes if (pw == NULL) { 212174853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 21228fae3551SRodney W. Grimes return; 21238fae3551SRodney W. Grimes } 21248fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 21258fae3551SRodney W. Grimes ngroups = NGROUPS + 1; 21268fae3551SRodney W. Grimes if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) 212774853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 21288fae3551SRodney W. Grimes /* 21298fae3551SRodney W. Grimes * Convert from int's to gid_t's and compress out duplicate 21308fae3551SRodney W. Grimes */ 21318fae3551SRodney W. Grimes cr->cr_ngroups = ngroups - 1; 21328fae3551SRodney W. Grimes cr->cr_groups[0] = groups[0]; 21338fae3551SRodney W. Grimes for (cnt = 2; cnt < ngroups; cnt++) 21348fae3551SRodney W. Grimes cr->cr_groups[cnt - 1] = groups[cnt]; 21358fae3551SRodney W. Grimes return; 21368fae3551SRodney W. Grimes } 21378fae3551SRodney W. Grimes /* 21388fae3551SRodney W. Grimes * Explicit credential specified as a colon separated list: 21398fae3551SRodney W. Grimes * uid:gid:gid:... 21408fae3551SRodney W. Grimes */ 21418fae3551SRodney W. Grimes if (pw != NULL) 21428fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 21438fae3551SRodney W. Grimes else if (isdigit(*name) || *name == '-') 21448fae3551SRodney W. Grimes cr->cr_uid = atoi(name); 21458fae3551SRodney W. Grimes else { 214674853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 21478fae3551SRodney W. Grimes return; 21488fae3551SRodney W. Grimes } 21498fae3551SRodney W. Grimes cr->cr_ngroups = 0; 21508fae3551SRodney W. Grimes while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { 21518fae3551SRodney W. Grimes name = strsep(&names, ":"); 21528fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') { 21538fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = atoi(name); 21548fae3551SRodney W. Grimes } else { 21558fae3551SRodney W. Grimes if ((gr = getgrnam(name)) == NULL) { 215674853402SPhilippe Charnier syslog(LOG_ERR, "unknown group: %s", name); 21578fae3551SRodney W. Grimes continue; 21588fae3551SRodney W. Grimes } 21598fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; 21608fae3551SRodney W. Grimes } 21618fae3551SRodney W. Grimes } 21628fae3551SRodney W. Grimes if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) 216374853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 21648fae3551SRodney W. Grimes } 21658fae3551SRodney W. Grimes 21668fae3551SRodney W. Grimes #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 21678fae3551SRodney W. Grimes /* 21688fae3551SRodney W. Grimes * Routines that maintain the remote mounttab 21698fae3551SRodney W. Grimes */ 21708fae3551SRodney W. Grimes void 21718fae3551SRodney W. Grimes get_mountlist() 21728fae3551SRodney W. Grimes { 21738fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 217487564113SPeter Wemm char *host, *dirp, *cp; 21758fae3551SRodney W. Grimes char str[STRSIZ]; 21768fae3551SRodney W. Grimes FILE *mlfile; 21778fae3551SRodney W. Grimes 21788fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) { 217939539916SBill Fumerola if (errno == ENOENT) 218039539916SBill Fumerola return; 218139539916SBill Fumerola else { 218274853402SPhilippe Charnier syslog(LOG_ERR, "can't open %s", _PATH_RMOUNTLIST); 21838fae3551SRodney W. Grimes return; 21848fae3551SRodney W. Grimes } 218539539916SBill Fumerola } 21868fae3551SRodney W. Grimes mlpp = &mlhead; 21878fae3551SRodney W. Grimes while (fgets(str, STRSIZ, mlfile) != NULL) { 218887564113SPeter Wemm cp = str; 218987564113SPeter Wemm host = strsep(&cp, " \t\n"); 219087564113SPeter Wemm dirp = strsep(&cp, " \t\n"); 219187564113SPeter Wemm if (host == NULL || dirp == NULL) 21928fae3551SRodney W. Grimes continue; 21938fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 219474853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 219574853402SPhilippe Charnier out_of_mem(); 219687564113SPeter Wemm strncpy(mlp->ml_host, host, RPCMNT_NAMELEN); 219787564113SPeter Wemm mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 219887564113SPeter Wemm strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 219987564113SPeter Wemm mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 22008fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 22018fae3551SRodney W. Grimes *mlpp = mlp; 22028fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 22038fae3551SRodney W. Grimes } 22048fae3551SRodney W. Grimes fclose(mlfile); 22058fae3551SRodney W. Grimes } 22068fae3551SRodney W. Grimes 220701709abfSIan Dowse void 220801709abfSIan Dowse del_mlist(char *hostp, char *dirp) 22098fae3551SRodney W. Grimes { 22108fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 22118fae3551SRodney W. Grimes struct mountlist *mlp2; 22128fae3551SRodney W. Grimes FILE *mlfile; 22138fae3551SRodney W. Grimes int fnd = 0; 22148fae3551SRodney W. Grimes 22158fae3551SRodney W. Grimes mlpp = &mlhead; 22168fae3551SRodney W. Grimes mlp = mlhead; 22178fae3551SRodney W. Grimes while (mlp) { 22188fae3551SRodney W. Grimes if (!strcmp(mlp->ml_host, hostp) && 22198fae3551SRodney W. Grimes (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 22208fae3551SRodney W. Grimes fnd = 1; 22218fae3551SRodney W. Grimes mlp2 = mlp; 22228fae3551SRodney W. Grimes *mlpp = mlp = mlp->ml_next; 22238fae3551SRodney W. Grimes free((caddr_t)mlp2); 22248fae3551SRodney W. Grimes } else { 22258fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 22268fae3551SRodney W. Grimes mlp = mlp->ml_next; 22278fae3551SRodney W. Grimes } 22288fae3551SRodney W. Grimes } 22298fae3551SRodney W. Grimes if (fnd) { 22308fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 223174853402SPhilippe Charnier syslog(LOG_ERR,"can't update %s", _PATH_RMOUNTLIST); 22328fae3551SRodney W. Grimes return; 22338fae3551SRodney W. Grimes } 22348fae3551SRodney W. Grimes mlp = mlhead; 22358fae3551SRodney W. Grimes while (mlp) { 22368fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 22378fae3551SRodney W. Grimes mlp = mlp->ml_next; 22388fae3551SRodney W. Grimes } 22398fae3551SRodney W. Grimes fclose(mlfile); 22408fae3551SRodney W. Grimes } 22418fae3551SRodney W. Grimes } 22428fae3551SRodney W. Grimes 22438fae3551SRodney W. Grimes void 22448fae3551SRodney W. Grimes add_mlist(hostp, dirp) 22458fae3551SRodney W. Grimes char *hostp, *dirp; 22468fae3551SRodney W. Grimes { 22478fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 22488fae3551SRodney W. Grimes FILE *mlfile; 22498fae3551SRodney W. Grimes 22508fae3551SRodney W. Grimes mlpp = &mlhead; 22518fae3551SRodney W. Grimes mlp = mlhead; 22528fae3551SRodney W. Grimes while (mlp) { 22538fae3551SRodney W. Grimes if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 22548fae3551SRodney W. Grimes return; 22558fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 22568fae3551SRodney W. Grimes mlp = mlp->ml_next; 22578fae3551SRodney W. Grimes } 22588fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 225974853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 226074853402SPhilippe Charnier out_of_mem(); 22618fae3551SRodney W. Grimes strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 22628fae3551SRodney W. Grimes mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 22638fae3551SRodney W. Grimes strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 22648fae3551SRodney W. Grimes mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 22658fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 22668fae3551SRodney W. Grimes *mlpp = mlp; 22678fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 226874853402SPhilippe Charnier syslog(LOG_ERR, "can't update %s", _PATH_RMOUNTLIST); 22698fae3551SRodney W. Grimes return; 22708fae3551SRodney W. Grimes } 22718fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 22728fae3551SRodney W. Grimes fclose(mlfile); 22738fae3551SRodney W. Grimes } 22748fae3551SRodney W. Grimes 22758fae3551SRodney W. Grimes /* 22768fae3551SRodney W. Grimes * Free up a group list. 22778fae3551SRodney W. Grimes */ 22788fae3551SRodney W. Grimes void 22798fae3551SRodney W. Grimes free_grp(grp) 22808fae3551SRodney W. Grimes struct grouplist *grp; 22818fae3551SRodney W. Grimes { 22828fae3551SRodney W. Grimes if (grp->gr_type == GT_HOST) { 22838360efbdSAlfred Perlstein if (grp->gr_ptr.gt_addrinfo != NULL) 22848360efbdSAlfred Perlstein freeaddrinfo(grp->gr_ptr.gt_addrinfo); 22858fae3551SRodney W. Grimes } else if (grp->gr_type == GT_NET) { 22868fae3551SRodney W. Grimes if (grp->gr_ptr.gt_net.nt_name) 22878fae3551SRodney W. Grimes free(grp->gr_ptr.gt_net.nt_name); 22888fae3551SRodney W. Grimes } 22898fae3551SRodney W. Grimes free((caddr_t)grp); 22908fae3551SRodney W. Grimes } 22918fae3551SRodney W. Grimes 22928fae3551SRodney W. Grimes #ifdef DEBUG 22938fae3551SRodney W. Grimes void 22948fae3551SRodney W. Grimes SYSLOG(int pri, const char *fmt, ...) 22958fae3551SRodney W. Grimes { 22968fae3551SRodney W. Grimes va_list ap; 22978fae3551SRodney W. Grimes 22988fae3551SRodney W. Grimes va_start(ap, fmt); 22998fae3551SRodney W. Grimes vfprintf(stderr, fmt, ap); 23008fae3551SRodney W. Grimes va_end(ap); 23018fae3551SRodney W. Grimes } 23028fae3551SRodney W. Grimes #endif /* DEBUG */ 23038fae3551SRodney W. Grimes 23048fae3551SRodney W. Grimes /* 23058fae3551SRodney W. Grimes * Check options for consistency. 23068fae3551SRodney W. Grimes */ 23078fae3551SRodney W. Grimes int 23088fae3551SRodney W. Grimes check_options(dp) 23098fae3551SRodney W. Grimes struct dirlist *dp; 23108fae3551SRodney W. Grimes { 23118fae3551SRodney W. Grimes 23128fae3551SRodney W. Grimes if (dp == (struct dirlist *)NULL) 23138fae3551SRodney W. Grimes return (1); 231491196234SPeter Wemm if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL)) { 231591196234SPeter Wemm syslog(LOG_ERR, "-mapall and -maproot mutually exclusive"); 23168fae3551SRodney W. Grimes return (1); 23178fae3551SRodney W. Grimes } 23188fae3551SRodney W. Grimes if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { 231960caaee2SIan Dowse syslog(LOG_ERR, "-mask requires -network"); 232060caaee2SIan Dowse return (1); 232160caaee2SIan Dowse } 232260caaee2SIan Dowse if ((opt_flags & OP_NET) && (opt_flags & OP_HAVEMASK) == 0) { 232360caaee2SIan Dowse syslog(LOG_ERR, "-network requires mask specification"); 232460caaee2SIan Dowse return (1); 232560caaee2SIan Dowse } 232660caaee2SIan Dowse if ((opt_flags & OP_MASK) && (opt_flags & OP_MASKLEN)) { 232760caaee2SIan Dowse syslog(LOG_ERR, "-mask and /masklen are mutually exclusive"); 23288fae3551SRodney W. Grimes return (1); 23298fae3551SRodney W. Grimes } 23308fae3551SRodney W. Grimes if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { 23316436fcb9SAlexander Langer syslog(LOG_ERR, "-alldirs has multiple directories"); 23328fae3551SRodney W. Grimes return (1); 23338fae3551SRodney W. Grimes } 23348fae3551SRodney W. Grimes return (0); 23358fae3551SRodney W. Grimes } 23368fae3551SRodney W. Grimes 23378fae3551SRodney W. Grimes /* 23388fae3551SRodney W. Grimes * Check an absolute directory path for any symbolic links. Return true 23398fae3551SRodney W. Grimes */ 23408fae3551SRodney W. Grimes int 23418fae3551SRodney W. Grimes check_dirpath(dirp) 23428fae3551SRodney W. Grimes char *dirp; 23438fae3551SRodney W. Grimes { 23448fae3551SRodney W. Grimes char *cp; 23458fae3551SRodney W. Grimes int ret = 1; 23468fae3551SRodney W. Grimes struct stat sb; 23478fae3551SRodney W. Grimes 23488fae3551SRodney W. Grimes cp = dirp + 1; 23498fae3551SRodney W. Grimes while (*cp && ret) { 23508fae3551SRodney W. Grimes if (*cp == '/') { 23518fae3551SRodney W. Grimes *cp = '\0'; 2352a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 23538fae3551SRodney W. Grimes ret = 0; 23548fae3551SRodney W. Grimes *cp = '/'; 23558fae3551SRodney W. Grimes } 23568fae3551SRodney W. Grimes cp++; 23578fae3551SRodney W. Grimes } 2358a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 23598fae3551SRodney W. Grimes ret = 0; 23608fae3551SRodney W. Grimes return (ret); 23618fae3551SRodney W. Grimes } 2362a62dc406SDoug Rabson 236360caaee2SIan Dowse /* 236460caaee2SIan Dowse * Make a netmask according to the specified prefix length. The ss_family 236560caaee2SIan Dowse * and other non-address fields must be initialised before calling this. 236660caaee2SIan Dowse */ 236760caaee2SIan Dowse int 236860caaee2SIan Dowse makemask(struct sockaddr_storage *ssp, int bitlen) 23698360efbdSAlfred Perlstein { 237060caaee2SIan Dowse u_char *p; 237160caaee2SIan Dowse int bits, i, len; 23728360efbdSAlfred Perlstein 237360caaee2SIan Dowse if ((p = sa_rawaddr((struct sockaddr *)ssp, &len)) == NULL) 237460caaee2SIan Dowse return (-1); 237589fdc4e1SMike Barcroft if (bitlen > len * CHAR_BIT) 237660caaee2SIan Dowse return (-1); 23778360efbdSAlfred Perlstein 237860caaee2SIan Dowse for (i = 0; i < len; i++) { 237989fdc4e1SMike Barcroft bits = (bitlen > CHAR_BIT) ? CHAR_BIT : bitlen; 238060caaee2SIan Dowse *p++ = (1 << bits) - 1; 238160caaee2SIan Dowse bitlen -= bits; 23828360efbdSAlfred Perlstein } 23838360efbdSAlfred Perlstein return 0; 23848360efbdSAlfred Perlstein } 23858360efbdSAlfred Perlstein 238660caaee2SIan Dowse /* 238760caaee2SIan Dowse * Check that the sockaddr is a valid netmask. Returns 0 if the mask 238860caaee2SIan Dowse * is acceptable (i.e. of the form 1...10....0). 238960caaee2SIan Dowse */ 239060caaee2SIan Dowse int 239160caaee2SIan Dowse checkmask(struct sockaddr *sa) 23928360efbdSAlfred Perlstein { 239360caaee2SIan Dowse u_char *mask; 239460caaee2SIan Dowse int i, len; 239560caaee2SIan Dowse 239660caaee2SIan Dowse if ((mask = sa_rawaddr(sa, &len)) == NULL) 239760caaee2SIan Dowse return (-1); 239860caaee2SIan Dowse 239960caaee2SIan Dowse for (i = 0; i < len; i++) 240060caaee2SIan Dowse if (mask[i] != 0xff) 240160caaee2SIan Dowse break; 240260caaee2SIan Dowse if (i < len) { 240360caaee2SIan Dowse if (~mask[i] & (u_char)(~mask[i] + 1)) 240460caaee2SIan Dowse return (-1); 240560caaee2SIan Dowse i++; 240660caaee2SIan Dowse } 240760caaee2SIan Dowse for (; i < len; i++) 240860caaee2SIan Dowse if (mask[i] != 0) 240960caaee2SIan Dowse return (-1); 241060caaee2SIan Dowse return (0); 241160caaee2SIan Dowse } 241260caaee2SIan Dowse 241360caaee2SIan Dowse /* 241460caaee2SIan Dowse * Compare two sockaddrs according to a specified mask. Return zero if 241560caaee2SIan Dowse * `sa1' matches `sa2' when filtered by the netmask in `samask'. 241660caaee2SIan Dowse * If samask is NULL, perform a full comparision. 241760caaee2SIan Dowse */ 241860caaee2SIan Dowse int 241960caaee2SIan Dowse sacmp(struct sockaddr *sa1, struct sockaddr *sa2, struct sockaddr *samask) 242060caaee2SIan Dowse { 242160caaee2SIan Dowse unsigned char *p1, *p2, *mask; 242260caaee2SIan Dowse int len, i; 242360caaee2SIan Dowse 242460caaee2SIan Dowse if (sa1->sa_family != sa2->sa_family || 242560caaee2SIan Dowse (p1 = sa_rawaddr(sa1, &len)) == NULL || 242660caaee2SIan Dowse (p2 = sa_rawaddr(sa2, NULL)) == NULL) 242760caaee2SIan Dowse return (1); 242860caaee2SIan Dowse 242960caaee2SIan Dowse switch (sa1->sa_family) { 243060caaee2SIan Dowse case AF_INET6: 243160caaee2SIan Dowse if (((struct sockaddr_in6 *)sa1)->sin6_scope_id != 243260caaee2SIan Dowse ((struct sockaddr_in6 *)sa2)->sin6_scope_id) 243360caaee2SIan Dowse return (1); 243460caaee2SIan Dowse break; 243560caaee2SIan Dowse } 243660caaee2SIan Dowse 243760caaee2SIan Dowse /* Simple binary comparison if no mask specified. */ 243860caaee2SIan Dowse if (samask == NULL) 243960caaee2SIan Dowse return (memcmp(p1, p2, len)); 244060caaee2SIan Dowse 244160caaee2SIan Dowse /* Set up the mask, and do a mask-based comparison. */ 244260caaee2SIan Dowse if (sa1->sa_family != samask->sa_family || 244360caaee2SIan Dowse (mask = sa_rawaddr(samask, NULL)) == NULL) 244460caaee2SIan Dowse return (1); 244560caaee2SIan Dowse 244660caaee2SIan Dowse for (i = 0; i < len; i++) 244760caaee2SIan Dowse if ((p1[i] & mask[i]) != (p2[i] & mask[i])) 244860caaee2SIan Dowse return (1); 244960caaee2SIan Dowse return (0); 245060caaee2SIan Dowse } 245160caaee2SIan Dowse 245260caaee2SIan Dowse /* 245360caaee2SIan Dowse * Return a pointer to the part of the sockaddr that contains the 245460caaee2SIan Dowse * raw address, and set *nbytes to its length in bytes. Returns 245560caaee2SIan Dowse * NULL if the address family is unknown. 245660caaee2SIan Dowse */ 245760caaee2SIan Dowse void * 245860caaee2SIan Dowse sa_rawaddr(struct sockaddr *sa, int *nbytes) { 245960caaee2SIan Dowse void *p; 246060caaee2SIan Dowse int len; 24618360efbdSAlfred Perlstein 24628360efbdSAlfred Perlstein switch (sa->sa_family) { 24638360efbdSAlfred Perlstein case AF_INET: 246460caaee2SIan Dowse len = sizeof(((struct sockaddr_in *)sa)->sin_addr); 246560caaee2SIan Dowse p = &((struct sockaddr_in *)sa)->sin_addr; 24668360efbdSAlfred Perlstein break; 24678360efbdSAlfred Perlstein case AF_INET6: 246860caaee2SIan Dowse len = sizeof(((struct sockaddr_in6 *)sa)->sin6_addr); 246960caaee2SIan Dowse p = &((struct sockaddr_in6 *)sa)->sin6_addr; 24708360efbdSAlfred Perlstein break; 24718360efbdSAlfred Perlstein default: 247260caaee2SIan Dowse p = NULL; 247360caaee2SIan Dowse len = 0; 24748360efbdSAlfred Perlstein } 24758360efbdSAlfred Perlstein 247660caaee2SIan Dowse if (nbytes != NULL) 247760caaee2SIan Dowse *nbytes = len; 247860caaee2SIan Dowse return (p); 24798360efbdSAlfred Perlstein } 24808360efbdSAlfred Perlstein 248169d65572SIan Dowse void 248269d65572SIan Dowse huphandler(int sig) 248369d65572SIan Dowse { 248469d65572SIan Dowse got_sighup = 1; 248569d65572SIan Dowse } 248669d65572SIan Dowse 24878360efbdSAlfred Perlstein void terminate(sig) 24888360efbdSAlfred Perlstein int sig; 24898360efbdSAlfred Perlstein { 24908360efbdSAlfred Perlstein close(mountdlockfd); 24918360efbdSAlfred Perlstein unlink(MOUNTDLOCK); 24927b98a1d6SAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); 24937b98a1d6SAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); 24948360efbdSAlfred Perlstein exit (0); 24958360efbdSAlfred Perlstein } 2496