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 * 4. Neither the name of the University nor the names of its contributors 178fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 188fae3551SRodney W. Grimes * without specific prior written permission. 198fae3551SRodney W. Grimes * 208fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 218fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 228fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 238fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 248fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 258fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 268fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 278fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 288fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 298fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 308fae3551SRodney W. Grimes * SUCH DAMAGE. 318fae3551SRodney W. Grimes */ 328fae3551SRodney W. Grimes 338fae3551SRodney W. Grimes #ifndef lint 3474853402SPhilippe Charnier static const char copyright[] = 358fae3551SRodney W. Grimes "@(#) Copyright (c) 1989, 1993\n\ 368fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 37d599144dSGarrett Wollman #endif /*not lint*/ 388fae3551SRodney W. Grimes 3974853402SPhilippe Charnier #if 0 4075201fa4SPhilippe Charnier #ifndef lint 4174853402SPhilippe Charnier static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; 42d599144dSGarrett Wollman #endif /*not lint*/ 4375201fa4SPhilippe Charnier #endif 4475201fa4SPhilippe Charnier 4575201fa4SPhilippe Charnier #include <sys/cdefs.h> 4675201fa4SPhilippe Charnier __FBSDID("$FreeBSD$"); 478fae3551SRodney W. Grimes 488fae3551SRodney W. Grimes #include <sys/param.h> 498fae3551SRodney W. Grimes #include <sys/mount.h> 508360efbdSAlfred Perlstein #include <sys/fcntl.h> 518fae3551SRodney W. Grimes #include <sys/stat.h> 528fae3551SRodney W. Grimes #include <sys/syslog.h> 53394da4c1SGuido van Rooij #include <sys/sysctl.h> 5491ca1a91SIan Dowse #include <sys/linker.h> 5591ca1a91SIan Dowse #include <sys/module.h> 568fae3551SRodney W. Grimes 578fae3551SRodney W. Grimes #include <rpc/rpc.h> 58bcb53b16SMartin Blapp #include <rpc/rpc_com.h> 598fae3551SRodney W. Grimes #include <rpc/pmap_clnt.h> 608360efbdSAlfred Perlstein #include <rpc/pmap_prot.h> 618360efbdSAlfred Perlstein #include <rpcsvc/mount.h> 628fae3551SRodney W. Grimes #include <nfs/rpcv2.h> 63a62dc406SDoug Rabson #include <nfs/nfsproto.h> 6491196234SPeter Wemm #include <nfsserver/nfs.h> 658fae3551SRodney W. Grimes 668fae3551SRodney W. Grimes #include <arpa/inet.h> 678fae3551SRodney W. Grimes 688fae3551SRodney W. Grimes #include <ctype.h> 6974853402SPhilippe Charnier #include <err.h> 708fae3551SRodney W. Grimes #include <errno.h> 718fae3551SRodney W. Grimes #include <grp.h> 72a032b226SPawel Jakub Dawidek #include <libutil.h> 7389fdc4e1SMike Barcroft #include <limits.h> 748fae3551SRodney W. Grimes #include <netdb.h> 758fae3551SRodney W. Grimes #include <pwd.h> 768fae3551SRodney W. Grimes #include <signal.h> 778fae3551SRodney W. Grimes #include <stdio.h> 788fae3551SRodney W. Grimes #include <stdlib.h> 798fae3551SRodney W. Grimes #include <string.h> 808fae3551SRodney W. Grimes #include <unistd.h> 818fae3551SRodney W. Grimes #include "pathnames.h" 826a09faf2SCraig Rodrigues #include "mntopts.h" 838fae3551SRodney W. Grimes 848fae3551SRodney W. Grimes #ifdef DEBUG 858fae3551SRodney W. Grimes #include <stdarg.h> 868fae3551SRodney W. Grimes #endif 878fae3551SRodney W. Grimes 888fae3551SRodney W. Grimes /* 898fae3551SRodney W. Grimes * Structures for keeping the mount list and export list 908fae3551SRodney W. Grimes */ 918fae3551SRodney W. Grimes struct mountlist { 928fae3551SRodney W. Grimes struct mountlist *ml_next; 938fae3551SRodney W. Grimes char ml_host[RPCMNT_NAMELEN+1]; 948fae3551SRodney W. Grimes char ml_dirp[RPCMNT_PATHLEN+1]; 958fae3551SRodney W. Grimes }; 968fae3551SRodney W. Grimes 978fae3551SRodney W. Grimes struct dirlist { 988fae3551SRodney W. Grimes struct dirlist *dp_left; 998fae3551SRodney W. Grimes struct dirlist *dp_right; 1008fae3551SRodney W. Grimes int dp_flag; 1018fae3551SRodney W. Grimes struct hostlist *dp_hosts; /* List of hosts this dir exported to */ 1028fae3551SRodney W. Grimes char dp_dirp[1]; /* Actually malloc'd to size of dir */ 1038fae3551SRodney W. Grimes }; 1048fae3551SRodney W. Grimes /* dp_flag bits */ 1058fae3551SRodney W. Grimes #define DP_DEFSET 0x1 106a62dc406SDoug Rabson #define DP_HOSTSET 0x2 1078fae3551SRodney W. Grimes 1088fae3551SRodney W. Grimes struct exportlist { 1098fae3551SRodney W. Grimes struct exportlist *ex_next; 1108fae3551SRodney W. Grimes struct dirlist *ex_dirl; 1118fae3551SRodney W. Grimes struct dirlist *ex_defdir; 1128fae3551SRodney W. Grimes int ex_flag; 1138fae3551SRodney W. Grimes fsid_t ex_fs; 1148fae3551SRodney W. Grimes char *ex_fsdir; 115cb3923e0SDoug Rabson char *ex_indexfile; 1168fae3551SRodney W. Grimes }; 1178fae3551SRodney W. Grimes /* ex_flag bits */ 1188fae3551SRodney W. Grimes #define EX_LINKED 0x1 1198fae3551SRodney W. Grimes 1208fae3551SRodney W. Grimes struct netmsk { 1218360efbdSAlfred Perlstein struct sockaddr_storage nt_net; 12260caaee2SIan Dowse struct sockaddr_storage nt_mask; 1238fae3551SRodney W. Grimes char *nt_name; 1248fae3551SRodney W. Grimes }; 1258fae3551SRodney W. Grimes 1268fae3551SRodney W. Grimes union grouptypes { 1278360efbdSAlfred Perlstein struct addrinfo *gt_addrinfo; 1288fae3551SRodney W. Grimes struct netmsk gt_net; 1298fae3551SRodney W. Grimes }; 1308fae3551SRodney W. Grimes 1318fae3551SRodney W. Grimes struct grouplist { 1328fae3551SRodney W. Grimes int gr_type; 1338fae3551SRodney W. Grimes union grouptypes gr_ptr; 1348fae3551SRodney W. Grimes struct grouplist *gr_next; 1358fae3551SRodney W. Grimes }; 1368fae3551SRodney W. Grimes /* Group types */ 1378fae3551SRodney W. Grimes #define GT_NULL 0x0 1388fae3551SRodney W. Grimes #define GT_HOST 0x1 1398fae3551SRodney W. Grimes #define GT_NET 0x2 1406d359f31SIan Dowse #define GT_DEFAULT 0x3 1418b5a6d67SBill Paul #define GT_IGNORE 0x5 1428fae3551SRodney W. Grimes 1438fae3551SRodney W. Grimes struct hostlist { 144a62dc406SDoug Rabson int ht_flag; /* Uses DP_xx bits */ 1458fae3551SRodney W. Grimes struct grouplist *ht_grp; 1468fae3551SRodney W. Grimes struct hostlist *ht_next; 1478fae3551SRodney W. Grimes }; 1488fae3551SRodney W. Grimes 149a62dc406SDoug Rabson struct fhreturn { 150a62dc406SDoug Rabson int fhr_flag; 151a62dc406SDoug Rabson int fhr_vers; 152a62dc406SDoug Rabson nfsfh_t fhr_fh; 153a62dc406SDoug Rabson }; 154a62dc406SDoug Rabson 1558fae3551SRodney W. Grimes /* Global defs */ 15685429990SWarner Losh char *add_expdir(struct dirlist **, char *, int); 15785429990SWarner Losh void add_dlist(struct dirlist **, struct dirlist *, 15885429990SWarner Losh struct grouplist *, int); 15985429990SWarner Losh void add_mlist(char *, char *); 16085429990SWarner Losh int check_dirpath(char *); 16185429990SWarner Losh int check_options(struct dirlist *); 16260caaee2SIan Dowse int checkmask(struct sockaddr *sa); 16385429990SWarner Losh int chk_host(struct dirlist *, struct sockaddr *, int *, int *); 164d11e3645SMatteo Riondato void create_service(struct netconfig *nconf); 16501709abfSIan Dowse void del_mlist(char *hostp, char *dirp); 16685429990SWarner Losh struct dirlist *dirp_search(struct dirlist *, char *); 16785429990SWarner Losh int do_mount(struct exportlist *, struct grouplist *, int, 16885429990SWarner Losh struct xucred *, char *, int, struct statfs *); 16985429990SWarner Losh int do_opt(char **, char **, struct exportlist *, struct grouplist *, 17085429990SWarner Losh int *, int *, struct xucred *); 17185429990SWarner Losh struct exportlist *ex_search(fsid_t *); 17285429990SWarner Losh struct exportlist *get_exp(void); 17385429990SWarner Losh void free_dir(struct dirlist *); 17485429990SWarner Losh void free_exp(struct exportlist *); 17585429990SWarner Losh void free_grp(struct grouplist *); 17685429990SWarner Losh void free_host(struct hostlist *); 17785429990SWarner Losh void get_exportlist(void); 17885429990SWarner Losh int get_host(char *, struct grouplist *, struct grouplist *); 17985429990SWarner Losh struct hostlist *get_ht(void); 18085429990SWarner Losh int get_line(void); 18185429990SWarner Losh void get_mountlist(void); 18285429990SWarner Losh int get_net(char *, struct netmsk *, int); 18385429990SWarner Losh void getexp_err(struct exportlist *, struct grouplist *); 18485429990SWarner Losh struct grouplist *get_grp(void); 18585429990SWarner Losh void hang_dirp(struct dirlist *, struct grouplist *, 18685429990SWarner Losh struct exportlist *, int); 18769d65572SIan Dowse void huphandler(int sig); 18860caaee2SIan Dowse int makemask(struct sockaddr_storage *ssp, int bitlen); 18985429990SWarner Losh void mntsrv(struct svc_req *, SVCXPRT *); 19085429990SWarner Losh void nextfield(char **, char **); 19185429990SWarner Losh void out_of_mem(void); 19285429990SWarner Losh void parsecred(char *, struct xucred *); 19391acb349SAlfred Perlstein int put_exlist(struct dirlist *, XDR *, struct dirlist *, int *, int); 19460caaee2SIan Dowse void *sa_rawaddr(struct sockaddr *sa, int *nbytes); 19560caaee2SIan Dowse int sacmp(struct sockaddr *sa1, struct sockaddr *sa2, 19660caaee2SIan Dowse struct sockaddr *samask); 19785429990SWarner Losh int scan_tree(struct dirlist *, struct sockaddr *); 19885429990SWarner Losh static void usage(void); 19985429990SWarner Losh int xdr_dir(XDR *, char *); 20085429990SWarner Losh int xdr_explist(XDR *, caddr_t); 20191acb349SAlfred Perlstein int xdr_explist_brief(XDR *, caddr_t); 20285429990SWarner Losh int xdr_fhs(XDR *, caddr_t); 20385429990SWarner Losh int xdr_mlist(XDR *, caddr_t); 20485429990SWarner Losh void terminate(int); 2058fae3551SRodney W. Grimes 2068fae3551SRodney W. Grimes struct exportlist *exphead; 2078fae3551SRodney W. Grimes struct mountlist *mlhead; 2088fae3551SRodney W. Grimes struct grouplist *grphead; 20996968c22SPawel Jakub Dawidek char *exnames_default[2] = { _PATH_EXPORTS, NULL }; 21096968c22SPawel Jakub Dawidek char **exnames; 211d11e3645SMatteo Riondato char **hosts = NULL; 212c0511d3bSBrian Feldman struct xucred def_anon = { 21376183f34SDima Dorfman XUCRED_VERSION, 2148fae3551SRodney W. Grimes (uid_t)-2, 2158fae3551SRodney W. Grimes 1, 216c0511d3bSBrian Feldman { (gid_t)-2 }, 217c0511d3bSBrian Feldman NULL 2188fae3551SRodney W. Grimes }; 2192a66cfc5SDoug Rabson int force_v2 = 0; 220a62dc406SDoug Rabson int resvport_only = 1; 221d11e3645SMatteo Riondato int nhosts = 0; 222a62dc406SDoug Rabson int dir_only = 1; 223c903443aSPeter Wemm int dolog = 0; 22469d65572SIan Dowse int got_sighup = 0; 225d11e3645SMatteo Riondato int xcreated = 0; 226d11e3645SMatteo Riondato 227d11e3645SMatteo Riondato char *svcport_str = NULL; 2288360efbdSAlfred Perlstein 2298fae3551SRodney W. Grimes int opt_flags; 2308360efbdSAlfred Perlstein static int have_v6 = 1; 2318360efbdSAlfred Perlstein 232a032b226SPawel Jakub Dawidek struct pidfh *pfh = NULL; 23360caaee2SIan Dowse /* Bits for opt_flags above */ 2348fae3551SRodney W. Grimes #define OP_MAPROOT 0x01 2358fae3551SRodney W. Grimes #define OP_MAPALL 0x02 23691196234SPeter Wemm /* 0x4 free */ 2378fae3551SRodney W. Grimes #define OP_MASK 0x08 2388fae3551SRodney W. Grimes #define OP_NET 0x10 2398fae3551SRodney W. Grimes #define OP_ALLDIRS 0x40 24060caaee2SIan Dowse #define OP_HAVEMASK 0x80 /* A mask was specified or inferred. */ 241288fa14aSJoerg Wunsch #define OP_QUIET 0x100 2428360efbdSAlfred Perlstein #define OP_MASKLEN 0x200 2438fae3551SRodney W. Grimes 2448fae3551SRodney W. Grimes #ifdef DEBUG 2458fae3551SRodney W. Grimes int debug = 1; 24685429990SWarner Losh void SYSLOG(int, const char *, ...) __printflike(2, 3); 2478fae3551SRodney W. Grimes #define syslog SYSLOG 2488fae3551SRodney W. Grimes #else 2498fae3551SRodney W. Grimes int debug = 0; 2508fae3551SRodney W. Grimes #endif 2518fae3551SRodney W. Grimes 2528fae3551SRodney W. Grimes /* 2538fae3551SRodney W. Grimes * Mountd server for NFS mount protocol as described in: 2548fae3551SRodney W. Grimes * NFS: Network File System Protocol Specification, RFC1094, Appendix A 2558fae3551SRodney W. Grimes * The optional arguments are the exports file name 2568fae3551SRodney W. Grimes * default: _PATH_EXPORTS 2578fae3551SRodney W. Grimes * and "-n" to allow nonroot mount. 2588fae3551SRodney W. Grimes */ 2598fae3551SRodney W. Grimes int 2608fae3551SRodney W. Grimes main(argc, argv) 2618fae3551SRodney W. Grimes int argc; 2628fae3551SRodney W. Grimes char **argv; 2638fae3551SRodney W. Grimes { 26469d65572SIan Dowse fd_set readfds; 265d11e3645SMatteo Riondato struct netconfig *nconf; 266d11e3645SMatteo Riondato char *endptr, **hosts_bak; 267d11e3645SMatteo Riondato void *nc_handle; 268a032b226SPawel Jakub Dawidek pid_t otherpid; 269d11e3645SMatteo Riondato in_port_t svcport; 270d11e3645SMatteo Riondato int c, k, s; 271bcb53b16SMartin Blapp int maxrec = RPC_MAXDATASIZE; 2728360efbdSAlfred Perlstein 27301709abfSIan Dowse /* Check that another mountd isn't already running. */ 2748b28aef2SPawel Jakub Dawidek pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid); 275a032b226SPawel Jakub Dawidek if (pfh == NULL) { 276a032b226SPawel Jakub Dawidek if (errno == EEXIST) 277a032b226SPawel Jakub Dawidek errx(1, "mountd already running, pid: %d.", otherpid); 278a032b226SPawel Jakub Dawidek warn("cannot open or create pidfile"); 279a032b226SPawel Jakub Dawidek } 2808360efbdSAlfred Perlstein 2818360efbdSAlfred Perlstein s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 2828360efbdSAlfred Perlstein if (s < 0) 2838360efbdSAlfred Perlstein have_v6 = 0; 2848360efbdSAlfred Perlstein else 2858360efbdSAlfred Perlstein close(s); 2864a0785aaSPeter Wemm if (modfind("nfsserver") < 0) { 2874a0785aaSPeter Wemm /* Not present in kernel, try loading it */ 2884a0785aaSPeter Wemm if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0) 2894a0785aaSPeter Wemm errx(1, "NFS server is not available or loadable"); 290d599144dSGarrett Wollman } 2918fae3551SRodney W. Grimes 292d11e3645SMatteo Riondato while ((c = getopt(argc, argv, "2dh:lnp:r")) != -1) 2938fae3551SRodney W. Grimes switch (c) { 2942a66cfc5SDoug Rabson case '2': 2952a66cfc5SDoug Rabson force_v2 = 1; 2962a66cfc5SDoug Rabson break; 297a62dc406SDoug Rabson case 'n': 298a62dc406SDoug Rabson resvport_only = 0; 299a62dc406SDoug Rabson break; 300a62dc406SDoug Rabson case 'r': 301a62dc406SDoug Rabson dir_only = 0; 302a62dc406SDoug Rabson break; 3036444ef3bSPoul-Henning Kamp case 'd': 3046444ef3bSPoul-Henning Kamp debug = debug ? 0 : 1; 3056444ef3bSPoul-Henning Kamp break; 306f51631d7SGuido van Rooij case 'l': 307c903443aSPeter Wemm dolog = 1; 308f51631d7SGuido van Rooij break; 309c203da27SBruce M Simpson case 'p': 310c203da27SBruce M Simpson endptr = NULL; 311c203da27SBruce M Simpson svcport = (in_port_t)strtoul(optarg, &endptr, 10); 312c203da27SBruce M Simpson if (endptr == NULL || *endptr != '\0' || 313c203da27SBruce M Simpson svcport == 0 || svcport >= IPPORT_MAX) 314c203da27SBruce M Simpson usage(); 315d11e3645SMatteo Riondato svcport_str = strdup(optarg); 316d11e3645SMatteo Riondato break; 317d11e3645SMatteo Riondato case 'h': 318d11e3645SMatteo Riondato ++nhosts; 319d11e3645SMatteo Riondato hosts_bak = hosts; 320d11e3645SMatteo Riondato hosts_bak = realloc(hosts, nhosts * sizeof(char *)); 321d11e3645SMatteo Riondato if (hosts_bak == NULL) { 322d11e3645SMatteo Riondato if (hosts != NULL) { 323d11e3645SMatteo Riondato for (k = 0; k < nhosts; k++) 324d11e3645SMatteo Riondato free(hosts[k]); 325d11e3645SMatteo Riondato free(hosts); 326d11e3645SMatteo Riondato out_of_mem(); 327d11e3645SMatteo Riondato } 328d11e3645SMatteo Riondato } 329d11e3645SMatteo Riondato hosts = hosts_bak; 330d11e3645SMatteo Riondato hosts[nhosts - 1] = strdup(optarg); 331d11e3645SMatteo Riondato if (hosts[nhosts - 1] == NULL) { 332d11e3645SMatteo Riondato for (k = 0; k < (nhosts - 1); k++) 333d11e3645SMatteo Riondato free(hosts[k]); 334d11e3645SMatteo Riondato free(hosts); 335d11e3645SMatteo Riondato out_of_mem(); 336d11e3645SMatteo Riondato } 337c203da27SBruce M Simpson break; 3388fae3551SRodney W. Grimes default: 33974853402SPhilippe Charnier usage(); 3408fae3551SRodney W. Grimes }; 3418fae3551SRodney W. Grimes argc -= optind; 3428fae3551SRodney W. Grimes argv += optind; 3438fae3551SRodney W. Grimes grphead = (struct grouplist *)NULL; 3448fae3551SRodney W. Grimes exphead = (struct exportlist *)NULL; 3458fae3551SRodney W. Grimes mlhead = (struct mountlist *)NULL; 34696968c22SPawel Jakub Dawidek if (argc > 0) 34796968c22SPawel Jakub Dawidek exnames = argv; 34896968c22SPawel Jakub Dawidek else 34996968c22SPawel Jakub Dawidek exnames = exnames_default; 3508fae3551SRodney W. Grimes openlog("mountd", LOG_PID, LOG_DAEMON); 3518fae3551SRodney W. Grimes if (debug) 35274853402SPhilippe Charnier warnx("getting export list"); 3538fae3551SRodney W. Grimes get_exportlist(); 3548fae3551SRodney W. Grimes if (debug) 35574853402SPhilippe Charnier warnx("getting mount list"); 3568fae3551SRodney W. Grimes get_mountlist(); 3578fae3551SRodney W. Grimes if (debug) 35874853402SPhilippe Charnier warnx("here we go"); 3598fae3551SRodney W. Grimes if (debug == 0) { 3608fae3551SRodney W. Grimes daemon(0, 0); 3618fae3551SRodney W. Grimes signal(SIGINT, SIG_IGN); 3628fae3551SRodney W. Grimes signal(SIGQUIT, SIG_IGN); 3638fae3551SRodney W. Grimes } 36469d65572SIan Dowse signal(SIGHUP, huphandler); 3658360efbdSAlfred Perlstein signal(SIGTERM, terminate); 36609fc9dc6SCraig Rodrigues signal(SIGPIPE, SIG_IGN); 367a032b226SPawel Jakub Dawidek 368a032b226SPawel Jakub Dawidek pidfile_write(pfh); 369a032b226SPawel Jakub Dawidek 3708360efbdSAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); 3718360efbdSAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); 372bcb53b16SMartin Blapp rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); 373bcb53b16SMartin Blapp 374c6e5e158SGuido van Rooij if (!resvport_only) { 3754a0785aaSPeter Wemm if (sysctlbyname("vfs.nfsrv.nfs_privport", NULL, NULL, 3764a0785aaSPeter Wemm &resvport_only, sizeof(resvport_only)) != 0 && 3774a0785aaSPeter Wemm errno != ENOENT) { 378394da4c1SGuido van Rooij syslog(LOG_ERR, "sysctl: %m"); 379394da4c1SGuido van Rooij exit(1); 380394da4c1SGuido van Rooij } 381c6e5e158SGuido van Rooij } 382c203da27SBruce M Simpson 383d11e3645SMatteo Riondato /* 384d11e3645SMatteo Riondato * If no hosts were specified, add a wildcard entry to bind to 385d11e3645SMatteo Riondato * INADDR_ANY. Otherwise make sure 127.0.0.1 and ::1 are added to the 386d11e3645SMatteo Riondato * list. 387d11e3645SMatteo Riondato */ 388d11e3645SMatteo Riondato if (nhosts == 0) { 389d11e3645SMatteo Riondato hosts = malloc(sizeof(char**)); 390d11e3645SMatteo Riondato if (hosts == NULL) 391d11e3645SMatteo Riondato out_of_mem(); 392d11e3645SMatteo Riondato hosts[0] = "*"; 393d11e3645SMatteo Riondato nhosts = 1; 394d11e3645SMatteo Riondato } else { 395d11e3645SMatteo Riondato hosts_bak = hosts; 396d11e3645SMatteo Riondato if (have_v6) { 397d11e3645SMatteo Riondato hosts_bak = realloc(hosts, (nhosts + 2) * 398d11e3645SMatteo Riondato sizeof(char *)); 399d11e3645SMatteo Riondato if (hosts_bak == NULL) { 400d11e3645SMatteo Riondato for (k = 0; k < nhosts; k++) 401d11e3645SMatteo Riondato free(hosts[k]); 402d11e3645SMatteo Riondato free(hosts); 403d11e3645SMatteo Riondato out_of_mem(); 404c203da27SBruce M Simpson } else 405d11e3645SMatteo Riondato hosts = hosts_bak; 406d11e3645SMatteo Riondato nhosts += 2; 407d11e3645SMatteo Riondato hosts[nhosts - 2] = "::1"; 408d11e3645SMatteo Riondato } else { 409d11e3645SMatteo Riondato hosts_bak = realloc(hosts, (nhosts + 1) * sizeof(char *)); 410d11e3645SMatteo Riondato if (hosts_bak == NULL) { 411d11e3645SMatteo Riondato for (k = 0; k < nhosts; k++) 412d11e3645SMatteo Riondato free(hosts[k]); 413d11e3645SMatteo Riondato free(hosts); 414d11e3645SMatteo Riondato out_of_mem(); 415d11e3645SMatteo Riondato } else { 416d11e3645SMatteo Riondato nhosts += 1; 417d11e3645SMatteo Riondato hosts = hosts_bak; 4188fae3551SRodney W. Grimes } 419d11e3645SMatteo Riondato } 4208360efbdSAlfred Perlstein 421d11e3645SMatteo Riondato hosts[nhosts - 1] = "127.0.0.1"; 4228360efbdSAlfred Perlstein } 4238360efbdSAlfred Perlstein 424d11e3645SMatteo Riondato nc_handle = setnetconfig(); 425d11e3645SMatteo Riondato while ((nconf = getnetconfig(nc_handle))) { 426d11e3645SMatteo Riondato if (nconf->nc_flag & NC_VISIBLE) { 427d11e3645SMatteo Riondato if (have_v6 == 0 && strcmp(nconf->nc_protofmly, 428d11e3645SMatteo Riondato "inet6") == 0) { 429d11e3645SMatteo Riondato /* DO NOTHING */ 430c203da27SBruce M Simpson } else 431d11e3645SMatteo Riondato create_service(nconf); 4328360efbdSAlfred Perlstein } 433d11e3645SMatteo Riondato } 434d11e3645SMatteo Riondato endnetconfig(nc_handle); 4358360efbdSAlfred Perlstein 4368360efbdSAlfred Perlstein if (xcreated == 0) { 4378360efbdSAlfred Perlstein syslog(LOG_ERR, "could not create any services"); 4382a66cfc5SDoug Rabson exit(1); 4392a66cfc5SDoug Rabson } 44069d65572SIan Dowse 44169d65572SIan Dowse /* Expand svc_run() here so that we can call get_exportlist(). */ 44269d65572SIan Dowse for (;;) { 44369d65572SIan Dowse if (got_sighup) { 44469d65572SIan Dowse get_exportlist(); 44569d65572SIan Dowse got_sighup = 0; 44669d65572SIan Dowse } 44769d65572SIan Dowse readfds = svc_fdset; 44869d65572SIan Dowse switch (select(svc_maxfd + 1, &readfds, NULL, NULL, NULL)) { 44969d65572SIan Dowse case -1: 45069d65572SIan Dowse if (errno == EINTR) 45169d65572SIan Dowse continue; 45269d65572SIan Dowse syslog(LOG_ERR, "mountd died: select: %m"); 45374853402SPhilippe Charnier exit(1); 45469d65572SIan Dowse case 0: 45569d65572SIan Dowse continue; 45669d65572SIan Dowse default: 45769d65572SIan Dowse svc_getreqset(&readfds); 45869d65572SIan Dowse } 45969d65572SIan Dowse } 46074853402SPhilippe Charnier } 46174853402SPhilippe Charnier 462d11e3645SMatteo Riondato /* 463d11e3645SMatteo Riondato * This routine creates and binds sockets on the appropriate 464d11e3645SMatteo Riondato * addresses. It gets called one time for each transport and 465d11e3645SMatteo Riondato * registrates the service with rpcbind on that trasport. 466d11e3645SMatteo Riondato */ 467d11e3645SMatteo Riondato void 468d11e3645SMatteo Riondato create_service(struct netconfig *nconf) 469d11e3645SMatteo Riondato { 470d11e3645SMatteo Riondato struct addrinfo hints, *res = NULL; 471d11e3645SMatteo Riondato struct sockaddr_in *sin; 472d11e3645SMatteo Riondato struct sockaddr_in6 *sin6; 473d11e3645SMatteo Riondato struct __rpc_sockinfo si; 474d11e3645SMatteo Riondato struct netbuf servaddr; 475d11e3645SMatteo Riondato SVCXPRT *transp = NULL; 476d11e3645SMatteo Riondato int aicode; 477d11e3645SMatteo Riondato int fd; 478d11e3645SMatteo Riondato int nhostsbak; 479d11e3645SMatteo Riondato int one = 1; 480d11e3645SMatteo Riondato int r; 481d11e3645SMatteo Riondato int registered = 0; 482d11e3645SMatteo Riondato u_int32_t host_addr[4]; /* IPv4 or IPv6 */ 483d11e3645SMatteo Riondato 484d11e3645SMatteo Riondato if ((nconf->nc_semantics != NC_TPI_CLTS) && 485d11e3645SMatteo Riondato (nconf->nc_semantics != NC_TPI_COTS) && 486d11e3645SMatteo Riondato (nconf->nc_semantics != NC_TPI_COTS_ORD)) 487d11e3645SMatteo Riondato return; /* not my type */ 488d11e3645SMatteo Riondato 489d11e3645SMatteo Riondato /* 490d11e3645SMatteo Riondato * XXX - using RPC library internal functions. 491d11e3645SMatteo Riondato */ 492d11e3645SMatteo Riondato if (!__rpc_nconf2sockinfo(nconf, &si)) { 493d11e3645SMatteo Riondato syslog(LOG_ERR, "cannot get information for %s", 494d11e3645SMatteo Riondato nconf->nc_netid); 495d11e3645SMatteo Riondato return; 496d11e3645SMatteo Riondato } 497d11e3645SMatteo Riondato 498d11e3645SMatteo Riondato /* Get mountd's address on this transport */ 499d11e3645SMatteo Riondato memset(&hints, 0, sizeof hints); 500d11e3645SMatteo Riondato hints.ai_flags = AI_PASSIVE; 501d11e3645SMatteo Riondato hints.ai_family = si.si_af; 502d11e3645SMatteo Riondato hints.ai_socktype = si.si_socktype; 503d11e3645SMatteo Riondato hints.ai_protocol = si.si_proto; 504d11e3645SMatteo Riondato 505d11e3645SMatteo Riondato /* 506d11e3645SMatteo Riondato * Bind to specific IPs if asked to 507d11e3645SMatteo Riondato */ 508d11e3645SMatteo Riondato nhostsbak = nhosts; 509d11e3645SMatteo Riondato while (nhostsbak > 0) { 510d11e3645SMatteo Riondato --nhostsbak; 511d11e3645SMatteo Riondato /* 512d11e3645SMatteo Riondato * XXX - using RPC library internal functions. 513d11e3645SMatteo Riondato */ 514d11e3645SMatteo Riondato if ((fd = __rpc_nconf2fd(nconf)) < 0) { 515d11e3645SMatteo Riondato int non_fatal = 0; 516d11e3645SMatteo Riondato if (errno == EPROTONOSUPPORT && 517d11e3645SMatteo Riondato nconf->nc_semantics != NC_TPI_CLTS) 518d11e3645SMatteo Riondato non_fatal = 1; 519d11e3645SMatteo Riondato 520d11e3645SMatteo Riondato syslog(non_fatal ? LOG_DEBUG : LOG_ERR, 521d11e3645SMatteo Riondato "cannot create socket for %s", nconf->nc_netid); 522d11e3645SMatteo Riondato return; 523d11e3645SMatteo Riondato } 524d11e3645SMatteo Riondato 525d11e3645SMatteo Riondato switch (hints.ai_family) { 526d11e3645SMatteo Riondato case AF_INET: 527d11e3645SMatteo Riondato if (inet_pton(AF_INET, hosts[nhostsbak], 528d11e3645SMatteo Riondato host_addr) == 1) { 529d11e3645SMatteo Riondato hints.ai_flags &= AI_NUMERICHOST; 530d11e3645SMatteo Riondato } else { 531d11e3645SMatteo Riondato /* 532d11e3645SMatteo Riondato * Skip if we have an AF_INET6 address. 533d11e3645SMatteo Riondato */ 534d11e3645SMatteo Riondato if (inet_pton(AF_INET6, hosts[nhostsbak], 535d11e3645SMatteo Riondato host_addr) == 1) { 536d11e3645SMatteo Riondato close(fd); 537d11e3645SMatteo Riondato continue; 538d11e3645SMatteo Riondato } 539d11e3645SMatteo Riondato } 540d11e3645SMatteo Riondato break; 541d11e3645SMatteo Riondato case AF_INET6: 542d11e3645SMatteo Riondato if (inet_pton(AF_INET6, hosts[nhostsbak], 543d11e3645SMatteo Riondato host_addr) == 1) { 544d11e3645SMatteo Riondato hints.ai_flags &= AI_NUMERICHOST; 545d11e3645SMatteo Riondato } else { 546d11e3645SMatteo Riondato /* 547d11e3645SMatteo Riondato * Skip if we have an AF_INET address. 548d11e3645SMatteo Riondato */ 549d11e3645SMatteo Riondato if (inet_pton(AF_INET, hosts[nhostsbak], 550d11e3645SMatteo Riondato host_addr) == 1) { 551d11e3645SMatteo Riondato close(fd); 552d11e3645SMatteo Riondato continue; 553d11e3645SMatteo Riondato } 554d11e3645SMatteo Riondato } 555d11e3645SMatteo Riondato 556d11e3645SMatteo Riondato /* 557d11e3645SMatteo Riondato * We're doing host-based access checks here, so don't 558d11e3645SMatteo Riondato * allow v4-in-v6 to confuse things. The kernel will 559d11e3645SMatteo Riondato * disable it by default on NFS sockets too. 560d11e3645SMatteo Riondato */ 561d11e3645SMatteo Riondato if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, 562d11e3645SMatteo Riondato sizeof one) < 0) { 563d11e3645SMatteo Riondato syslog(LOG_ERR, 564d11e3645SMatteo Riondato "can't disable v4-in-v6 on IPv6 socket"); 565d11e3645SMatteo Riondato exit(1); 566d11e3645SMatteo Riondato } 567d11e3645SMatteo Riondato break; 568d11e3645SMatteo Riondato default: 569d11e3645SMatteo Riondato break; 570d11e3645SMatteo Riondato } 571d11e3645SMatteo Riondato 572d11e3645SMatteo Riondato /* 573d11e3645SMatteo Riondato * If no hosts were specified, just bind to INADDR_ANY 574d11e3645SMatteo Riondato */ 575d11e3645SMatteo Riondato if (strcmp("*", hosts[nhostsbak]) == 0) { 576d11e3645SMatteo Riondato if (svcport_str == NULL) { 577d11e3645SMatteo Riondato res = malloc(sizeof(struct addrinfo)); 578d11e3645SMatteo Riondato if (res == NULL) 579d11e3645SMatteo Riondato out_of_mem(); 580d11e3645SMatteo Riondato res->ai_flags = hints.ai_flags; 581d11e3645SMatteo Riondato res->ai_family = hints.ai_family; 582d11e3645SMatteo Riondato res->ai_protocol = hints.ai_protocol; 583d11e3645SMatteo Riondato switch (res->ai_family) { 584d11e3645SMatteo Riondato case AF_INET: 585d11e3645SMatteo Riondato sin = malloc(sizeof(struct sockaddr_in)); 586d11e3645SMatteo Riondato if (sin == NULL) 587d11e3645SMatteo Riondato out_of_mem(); 588d11e3645SMatteo Riondato sin->sin_family = AF_INET; 589d11e3645SMatteo Riondato sin->sin_port = htons(0); 590d11e3645SMatteo Riondato sin->sin_addr.s_addr = htonl(INADDR_ANY); 591d11e3645SMatteo Riondato res->ai_addr = (struct sockaddr*) sin; 592d11e3645SMatteo Riondato res->ai_addrlen = (socklen_t) 593d11e3645SMatteo Riondato sizeof(res->ai_addr); 594d11e3645SMatteo Riondato break; 595d11e3645SMatteo Riondato case AF_INET6: 596d11e3645SMatteo Riondato sin6 = malloc(sizeof(struct sockaddr_in6)); 597d11e3645SMatteo Riondato if (res->ai_addr == NULL) 598d11e3645SMatteo Riondato out_of_mem(); 599d11e3645SMatteo Riondato sin6->sin6_family = AF_INET6; 600d11e3645SMatteo Riondato sin6->sin6_port = htons(0); 601d11e3645SMatteo Riondato sin6->sin6_addr = in6addr_any; 602d11e3645SMatteo Riondato res->ai_addr = (struct sockaddr*) sin6; 603d11e3645SMatteo Riondato res->ai_addrlen = (socklen_t) 604d11e3645SMatteo Riondato sizeof(res->ai_addr); 605d11e3645SMatteo Riondato break; 606d11e3645SMatteo Riondato default: 607d11e3645SMatteo Riondato break; 608d11e3645SMatteo Riondato } 609d11e3645SMatteo Riondato } else { 610d11e3645SMatteo Riondato if ((aicode = getaddrinfo(NULL, svcport_str, 611d11e3645SMatteo Riondato &hints, &res)) != 0) { 612d11e3645SMatteo Riondato syslog(LOG_ERR, 613d11e3645SMatteo Riondato "cannot get local address for %s: %s", 614d11e3645SMatteo Riondato nconf->nc_netid, 615d11e3645SMatteo Riondato gai_strerror(aicode)); 616d11e3645SMatteo Riondato continue; 617d11e3645SMatteo Riondato } 618d11e3645SMatteo Riondato } 619d11e3645SMatteo Riondato } else { 620d11e3645SMatteo Riondato if ((aicode = getaddrinfo(hosts[nhostsbak], svcport_str, 621d11e3645SMatteo Riondato &hints, &res)) != 0) { 622d11e3645SMatteo Riondato syslog(LOG_ERR, 623d11e3645SMatteo Riondato "cannot get local address for %s: %s", 624d11e3645SMatteo Riondato nconf->nc_netid, gai_strerror(aicode)); 625d11e3645SMatteo Riondato continue; 626d11e3645SMatteo Riondato } 627d11e3645SMatteo Riondato } 628d11e3645SMatteo Riondato 629d11e3645SMatteo Riondato r = bindresvport_sa(fd, res->ai_addr); 630d11e3645SMatteo Riondato if (r != 0) { 631d11e3645SMatteo Riondato syslog(LOG_ERR, "bindresvport_sa: %m"); 632d11e3645SMatteo Riondato exit(1); 633d11e3645SMatteo Riondato } 634d11e3645SMatteo Riondato 635d11e3645SMatteo Riondato if (nconf->nc_semantics != NC_TPI_CLTS) 636d11e3645SMatteo Riondato listen(fd, SOMAXCONN); 637d11e3645SMatteo Riondato 638d11e3645SMatteo Riondato if (nconf->nc_semantics == NC_TPI_CLTS ) 639d11e3645SMatteo Riondato transp = svc_dg_create(fd, 0, 0); 640d11e3645SMatteo Riondato else 641d11e3645SMatteo Riondato transp = svc_vc_create(fd, RPC_MAXDATASIZE, 642d11e3645SMatteo Riondato RPC_MAXDATASIZE); 643d11e3645SMatteo Riondato 644d11e3645SMatteo Riondato if (transp != (SVCXPRT *) NULL) { 645d11e3645SMatteo Riondato if (!svc_reg(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv, 646d11e3645SMatteo Riondato NULL)) 647d11e3645SMatteo Riondato syslog(LOG_ERR, 648d11e3645SMatteo Riondato "can't register %s RPCMNT_VER1 service", 649d11e3645SMatteo Riondato nconf->nc_netid); 650d11e3645SMatteo Riondato if (!force_v2) { 651d11e3645SMatteo Riondato if (!svc_reg(transp, RPCPROG_MNT, RPCMNT_VER3, 652d11e3645SMatteo Riondato mntsrv, NULL)) 653d11e3645SMatteo Riondato syslog(LOG_ERR, 654d11e3645SMatteo Riondato "can't register %s RPCMNT_VER3 service", 655d11e3645SMatteo Riondato nconf->nc_netid); 656d11e3645SMatteo Riondato } 657d11e3645SMatteo Riondato } else 658d11e3645SMatteo Riondato syslog(LOG_WARNING, "can't create %s services", 659d11e3645SMatteo Riondato nconf->nc_netid); 660d11e3645SMatteo Riondato 661d11e3645SMatteo Riondato if (registered == 0) { 662d11e3645SMatteo Riondato registered = 1; 663d11e3645SMatteo Riondato memset(&hints, 0, sizeof hints); 664d11e3645SMatteo Riondato hints.ai_flags = AI_PASSIVE; 665d11e3645SMatteo Riondato hints.ai_family = si.si_af; 666d11e3645SMatteo Riondato hints.ai_socktype = si.si_socktype; 667d11e3645SMatteo Riondato hints.ai_protocol = si.si_proto; 668d11e3645SMatteo Riondato 669d11e3645SMatteo Riondato if (svcport_str == NULL) { 670d11e3645SMatteo Riondato svcport_str = malloc(NI_MAXSERV * sizeof(char)); 671d11e3645SMatteo Riondato if (svcport_str == NULL) 672d11e3645SMatteo Riondato out_of_mem(); 673d11e3645SMatteo Riondato 674d11e3645SMatteo Riondato if (getnameinfo(res->ai_addr, 675d11e3645SMatteo Riondato res->ai_addr->sa_len, NULL, NI_MAXHOST, 676d11e3645SMatteo Riondato svcport_str, NI_MAXSERV * sizeof(char), 677d11e3645SMatteo Riondato NI_NUMERICHOST | NI_NUMERICSERV)) 678d11e3645SMatteo Riondato errx(1, "Cannot get port number"); 679d11e3645SMatteo Riondato } 680d11e3645SMatteo Riondato 681d11e3645SMatteo Riondato if((aicode = getaddrinfo(NULL, svcport_str, &hints, 682d11e3645SMatteo Riondato &res)) != 0) { 683d11e3645SMatteo Riondato syslog(LOG_ERR, "cannot get local address: %s", 684d11e3645SMatteo Riondato gai_strerror(aicode)); 685d11e3645SMatteo Riondato exit(1); 686d11e3645SMatteo Riondato } 687d11e3645SMatteo Riondato 688d11e3645SMatteo Riondato servaddr.buf = malloc(res->ai_addrlen); 689d11e3645SMatteo Riondato memcpy(servaddr.buf, res->ai_addr, res->ai_addrlen); 690d11e3645SMatteo Riondato servaddr.len = res->ai_addrlen; 691d11e3645SMatteo Riondato 692d11e3645SMatteo Riondato rpcb_set(RPCPROG_MNT, RPCMNT_VER1, nconf, &servaddr); 693d11e3645SMatteo Riondato rpcb_set(RPCPROG_MNT, RPCMNT_VER3, nconf, &servaddr); 694d11e3645SMatteo Riondato 695d11e3645SMatteo Riondato xcreated++; 696d11e3645SMatteo Riondato freeaddrinfo(res); 697d11e3645SMatteo Riondato } 698d11e3645SMatteo Riondato } /* end while */ 699d11e3645SMatteo Riondato } 700d11e3645SMatteo Riondato 70174853402SPhilippe Charnier static void 70274853402SPhilippe Charnier usage() 70374853402SPhilippe Charnier { 70474853402SPhilippe Charnier fprintf(stderr, 705c203da27SBruce M Simpson "usage: mountd [-2] [-d] [-l] [-n] [-p <port>] [-r] " 706d11e3645SMatteo Riondato "[-h <bindip>] [export_file ...]\n"); 7078fae3551SRodney W. Grimes exit(1); 7088fae3551SRodney W. Grimes } 7098fae3551SRodney W. Grimes 7108fae3551SRodney W. Grimes /* 7118fae3551SRodney W. Grimes * The mount rpc service 7128fae3551SRodney W. Grimes */ 7138fae3551SRodney W. Grimes void 7148fae3551SRodney W. Grimes mntsrv(rqstp, transp) 7158fae3551SRodney W. Grimes struct svc_req *rqstp; 7168fae3551SRodney W. Grimes SVCXPRT *transp; 7178fae3551SRodney W. Grimes { 7188fae3551SRodney W. Grimes struct exportlist *ep; 7198fae3551SRodney W. Grimes struct dirlist *dp; 720a62dc406SDoug Rabson struct fhreturn fhr; 7218fae3551SRodney W. Grimes struct stat stb; 7228fae3551SRodney W. Grimes struct statfs fsb; 7238360efbdSAlfred Perlstein char host[NI_MAXHOST], numerichost[NI_MAXHOST]; 7248360efbdSAlfred Perlstein int lookup_failed = 1; 7258360efbdSAlfred Perlstein struct sockaddr *saddr; 726a62dc406SDoug Rabson u_short sport; 7278fae3551SRodney W. Grimes char rpcpath[RPCMNT_PATHLEN + 1], dirpath[MAXPATHLEN]; 728e90cdb54SGuido van Rooij int bad = 0, defset, hostset; 729a62dc406SDoug Rabson sigset_t sighup_mask; 7308fae3551SRodney W. Grimes 731a62dc406SDoug Rabson sigemptyset(&sighup_mask); 732a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 7338360efbdSAlfred Perlstein saddr = svc_getrpccaller(transp)->buf; 7348360efbdSAlfred Perlstein switch (saddr->sa_family) { 7358360efbdSAlfred Perlstein case AF_INET6: 73601709abfSIan Dowse sport = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port); 7378360efbdSAlfred Perlstein break; 7388360efbdSAlfred Perlstein case AF_INET: 73901709abfSIan Dowse sport = ntohs(((struct sockaddr_in *)saddr)->sin_port); 7408360efbdSAlfred Perlstein break; 7418360efbdSAlfred Perlstein default: 7428360efbdSAlfred Perlstein syslog(LOG_ERR, "request from unknown address family"); 7438360efbdSAlfred Perlstein return; 7448360efbdSAlfred Perlstein } 7458360efbdSAlfred Perlstein lookup_failed = getnameinfo(saddr, saddr->sa_len, host, sizeof host, 7468360efbdSAlfred Perlstein NULL, 0, 0); 7478360efbdSAlfred Perlstein getnameinfo(saddr, saddr->sa_len, numerichost, 7488360efbdSAlfred Perlstein sizeof numerichost, NULL, 0, NI_NUMERICHOST); 7498fae3551SRodney W. Grimes switch (rqstp->rq_proc) { 7508fae3551SRodney W. Grimes case NULLPROC: 751389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) 75274853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 7538fae3551SRodney W. Grimes return; 7548fae3551SRodney W. Grimes case RPCMNT_MOUNT: 755a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 756f51631d7SGuido van Rooij syslog(LOG_NOTICE, 757f51631d7SGuido van Rooij "mount request from %s from unprivileged port", 7588360efbdSAlfred Perlstein numerichost); 7598fae3551SRodney W. Grimes svcerr_weakauth(transp); 7608fae3551SRodney W. Grimes return; 7618fae3551SRodney W. Grimes } 762389b8446SPeter Wemm if (!svc_getargs(transp, (xdrproc_t)xdr_dir, rpcpath)) { 763f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable mount request from %s", 7648360efbdSAlfred Perlstein numerichost); 7658fae3551SRodney W. Grimes svcerr_decode(transp); 7668fae3551SRodney W. Grimes return; 7678fae3551SRodney W. Grimes } 7688fae3551SRodney W. Grimes 7698fae3551SRodney W. Grimes /* 7708fae3551SRodney W. Grimes * Get the real pathname and make sure it is a directory 771a62dc406SDoug Rabson * or a regular file if the -r option was specified 772a62dc406SDoug Rabson * and it exists. 7738fae3551SRodney W. Grimes */ 774cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL || 7758fae3551SRodney W. Grimes stat(dirpath, &stb) < 0 || 776a62dc406SDoug Rabson (!S_ISDIR(stb.st_mode) && 777a62dc406SDoug Rabson (dir_only || !S_ISREG(stb.st_mode))) || 7788fae3551SRodney W. Grimes statfs(dirpath, &fsb) < 0) { 7798fae3551SRodney W. Grimes chdir("/"); /* Just in case realpath doesn't */ 780f51631d7SGuido van Rooij syslog(LOG_NOTICE, 78174853402SPhilippe Charnier "mount request from %s for non existent path %s", 7828360efbdSAlfred Perlstein numerichost, dirpath); 7838fae3551SRodney W. Grimes if (debug) 78474853402SPhilippe Charnier warnx("stat failed on %s", dirpath); 785e90cdb54SGuido van Rooij bad = ENOENT; /* We will send error reply later */ 7868fae3551SRodney W. Grimes } 7878fae3551SRodney W. Grimes 7888fae3551SRodney W. Grimes /* Check in the exports list */ 789a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 7908fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 791a62dc406SDoug Rabson hostset = defset = 0; 792a62dc406SDoug Rabson if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) || 7938fae3551SRodney W. Grimes ((dp = dirp_search(ep->ex_dirl, dirpath)) && 794a62dc406SDoug Rabson chk_host(dp, saddr, &defset, &hostset)) || 7958fae3551SRodney W. Grimes (defset && scan_tree(ep->ex_defdir, saddr) == 0 && 7968fae3551SRodney W. Grimes scan_tree(ep->ex_dirl, saddr) == 0))) { 797e90cdb54SGuido van Rooij if (bad) { 798389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_long, 799e90cdb54SGuido van Rooij (caddr_t)&bad)) 80074853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 801e90cdb54SGuido van Rooij sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 802e90cdb54SGuido van Rooij return; 803e90cdb54SGuido van Rooij } 804a62dc406SDoug Rabson if (hostset & DP_HOSTSET) 805a62dc406SDoug Rabson fhr.fhr_flag = hostset; 806a62dc406SDoug Rabson else 807a62dc406SDoug Rabson fhr.fhr_flag = defset; 808a62dc406SDoug Rabson fhr.fhr_vers = rqstp->rq_vers; 8098fae3551SRodney W. Grimes /* Get the file handle */ 81087564113SPeter Wemm memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t)); 811a62dc406SDoug Rabson if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) { 8128fae3551SRodney W. Grimes bad = errno; 81374853402SPhilippe Charnier syslog(LOG_ERR, "can't get fh for %s", dirpath); 814389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_long, 8158fae3551SRodney W. Grimes (caddr_t)&bad)) 81674853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 817a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 8188fae3551SRodney W. Grimes return; 8198fae3551SRodney W. Grimes } 820389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_fhs, 821389b8446SPeter Wemm (caddr_t)&fhr)) 82274853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 8238360efbdSAlfred Perlstein if (!lookup_failed) 8248360efbdSAlfred Perlstein add_mlist(host, dirpath); 8258fae3551SRodney W. Grimes else 8268360efbdSAlfred Perlstein add_mlist(numerichost, dirpath); 8278fae3551SRodney W. Grimes if (debug) 82874853402SPhilippe Charnier warnx("mount successful"); 829c903443aSPeter Wemm if (dolog) 830f51631d7SGuido van Rooij syslog(LOG_NOTICE, 831f51631d7SGuido van Rooij "mount request succeeded from %s for %s", 8328360efbdSAlfred Perlstein numerichost, dirpath); 833f51631d7SGuido van Rooij } else { 8348fae3551SRodney W. Grimes bad = EACCES; 835f51631d7SGuido van Rooij syslog(LOG_NOTICE, 836f51631d7SGuido van Rooij "mount request denied from %s for %s", 8378360efbdSAlfred Perlstein numerichost, dirpath); 838f51631d7SGuido van Rooij } 839e90cdb54SGuido van Rooij 840389b8446SPeter Wemm if (bad && !svc_sendreply(transp, (xdrproc_t)xdr_long, 841389b8446SPeter Wemm (caddr_t)&bad)) 84274853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 843a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 8448fae3551SRodney W. Grimes return; 8458fae3551SRodney W. Grimes case RPCMNT_DUMP: 846389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_mlist, (caddr_t)NULL)) 84774853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 848c903443aSPeter Wemm else if (dolog) 849f51631d7SGuido van Rooij syslog(LOG_NOTICE, 850f51631d7SGuido van Rooij "dump request succeeded from %s", 8518360efbdSAlfred Perlstein numerichost); 8528fae3551SRodney W. Grimes return; 8538fae3551SRodney W. Grimes case RPCMNT_UMOUNT: 854a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 855f51631d7SGuido van Rooij syslog(LOG_NOTICE, 856f51631d7SGuido van Rooij "umount request from %s from unprivileged port", 8578360efbdSAlfred Perlstein numerichost); 8588fae3551SRodney W. Grimes svcerr_weakauth(transp); 8598fae3551SRodney W. Grimes return; 8608fae3551SRodney W. Grimes } 861389b8446SPeter Wemm if (!svc_getargs(transp, (xdrproc_t)xdr_dir, rpcpath)) { 862f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable umount request from %s", 8638360efbdSAlfred Perlstein numerichost); 8648fae3551SRodney W. Grimes svcerr_decode(transp); 8658fae3551SRodney W. Grimes return; 8668fae3551SRodney W. Grimes } 867cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL) { 868cb479b11SAlfred Perlstein syslog(LOG_NOTICE, "umount request from %s " 869cb479b11SAlfred Perlstein "for non existent path %s", 8708360efbdSAlfred Perlstein numerichost, dirpath); 871cb479b11SAlfred Perlstein } 872389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_void, (caddr_t)NULL)) 87374853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 8748360efbdSAlfred Perlstein if (!lookup_failed) 87501709abfSIan Dowse del_mlist(host, dirpath); 87601709abfSIan Dowse del_mlist(numerichost, dirpath); 877c903443aSPeter Wemm if (dolog) 878f51631d7SGuido van Rooij syslog(LOG_NOTICE, 879f51631d7SGuido van Rooij "umount request succeeded from %s for %s", 8808360efbdSAlfred Perlstein numerichost, dirpath); 8818fae3551SRodney W. Grimes return; 8828fae3551SRodney W. Grimes case RPCMNT_UMNTALL: 883a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 884f51631d7SGuido van Rooij syslog(LOG_NOTICE, 885f51631d7SGuido van Rooij "umountall request from %s from unprivileged port", 8868360efbdSAlfred Perlstein numerichost); 8878fae3551SRodney W. Grimes svcerr_weakauth(transp); 8888fae3551SRodney W. Grimes return; 8898fae3551SRodney W. Grimes } 890389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_void, (caddr_t)NULL)) 89174853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 8928360efbdSAlfred Perlstein if (!lookup_failed) 89301709abfSIan Dowse del_mlist(host, NULL); 89401709abfSIan Dowse del_mlist(numerichost, NULL); 895c903443aSPeter Wemm if (dolog) 896f51631d7SGuido van Rooij syslog(LOG_NOTICE, 897f51631d7SGuido van Rooij "umountall request succeeded from %s", 8988360efbdSAlfred Perlstein numerichost); 8998fae3551SRodney W. Grimes return; 9008fae3551SRodney W. Grimes case RPCMNT_EXPORT: 901389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_explist, (caddr_t)NULL)) 902389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_explist_brief, 903389b8446SPeter Wemm (caddr_t)NULL)) 90474853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 905c903443aSPeter Wemm if (dolog) 906f51631d7SGuido van Rooij syslog(LOG_NOTICE, 907f51631d7SGuido van Rooij "export request succeeded from %s", 9088360efbdSAlfred Perlstein numerichost); 9098fae3551SRodney W. Grimes return; 9108fae3551SRodney W. Grimes default: 9118fae3551SRodney W. Grimes svcerr_noproc(transp); 9128fae3551SRodney W. Grimes return; 9138fae3551SRodney W. Grimes } 9148fae3551SRodney W. Grimes } 9158fae3551SRodney W. Grimes 9168fae3551SRodney W. Grimes /* 9178fae3551SRodney W. Grimes * Xdr conversion for a dirpath string 9188fae3551SRodney W. Grimes */ 9198fae3551SRodney W. Grimes int 9208fae3551SRodney W. Grimes xdr_dir(xdrsp, dirp) 9218fae3551SRodney W. Grimes XDR *xdrsp; 9228fae3551SRodney W. Grimes char *dirp; 9238fae3551SRodney W. Grimes { 9248fae3551SRodney W. Grimes return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 9258fae3551SRodney W. Grimes } 9268fae3551SRodney W. Grimes 9278fae3551SRodney W. Grimes /* 928a62dc406SDoug Rabson * Xdr routine to generate file handle reply 9298fae3551SRodney W. Grimes */ 9308fae3551SRodney W. Grimes int 931a62dc406SDoug Rabson xdr_fhs(xdrsp, cp) 9328fae3551SRodney W. Grimes XDR *xdrsp; 933a62dc406SDoug Rabson caddr_t cp; 9348fae3551SRodney W. Grimes { 9353d438ad6SDavid E. O'Brien struct fhreturn *fhrp = (struct fhreturn *)cp; 936a62dc406SDoug Rabson u_long ok = 0, len, auth; 9378fae3551SRodney W. Grimes 9388fae3551SRodney W. Grimes if (!xdr_long(xdrsp, &ok)) 9398fae3551SRodney W. Grimes return (0); 940a62dc406SDoug Rabson switch (fhrp->fhr_vers) { 941a62dc406SDoug Rabson case 1: 942a62dc406SDoug Rabson return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH)); 943a62dc406SDoug Rabson case 3: 944a62dc406SDoug Rabson len = NFSX_V3FH; 945a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 946a62dc406SDoug Rabson return (0); 947a62dc406SDoug Rabson if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) 948a62dc406SDoug Rabson return (0); 949a62dc406SDoug Rabson auth = RPCAUTH_UNIX; 950a62dc406SDoug Rabson len = 1; 951a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 952a62dc406SDoug Rabson return (0); 953a62dc406SDoug Rabson return (xdr_long(xdrsp, &auth)); 954a62dc406SDoug Rabson }; 955a62dc406SDoug Rabson return (0); 9568fae3551SRodney W. Grimes } 9578fae3551SRodney W. Grimes 9588fae3551SRodney W. Grimes int 9598fae3551SRodney W. Grimes xdr_mlist(xdrsp, cp) 9608fae3551SRodney W. Grimes XDR *xdrsp; 9618fae3551SRodney W. Grimes caddr_t cp; 9628fae3551SRodney W. Grimes { 9638fae3551SRodney W. Grimes struct mountlist *mlp; 9648fae3551SRodney W. Grimes int true = 1; 9658fae3551SRodney W. Grimes int false = 0; 9668fae3551SRodney W. Grimes char *strp; 9678fae3551SRodney W. Grimes 9688fae3551SRodney W. Grimes mlp = mlhead; 9698fae3551SRodney W. Grimes while (mlp) { 9708fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 9718fae3551SRodney W. Grimes return (0); 9728fae3551SRodney W. Grimes strp = &mlp->ml_host[0]; 9738fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 9748fae3551SRodney W. Grimes return (0); 9758fae3551SRodney W. Grimes strp = &mlp->ml_dirp[0]; 9768fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 9778fae3551SRodney W. Grimes return (0); 9788fae3551SRodney W. Grimes mlp = mlp->ml_next; 9798fae3551SRodney W. Grimes } 9808fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 9818fae3551SRodney W. Grimes return (0); 9828fae3551SRodney W. Grimes return (1); 9838fae3551SRodney W. Grimes } 9848fae3551SRodney W. Grimes 9858fae3551SRodney W. Grimes /* 9868fae3551SRodney W. Grimes * Xdr conversion for export list 9878fae3551SRodney W. Grimes */ 9888fae3551SRodney W. Grimes int 98991acb349SAlfred Perlstein xdr_explist_common(xdrsp, cp, brief) 9908fae3551SRodney W. Grimes XDR *xdrsp; 9918fae3551SRodney W. Grimes caddr_t cp; 99291acb349SAlfred Perlstein int brief; 9938fae3551SRodney W. Grimes { 9948fae3551SRodney W. Grimes struct exportlist *ep; 9958fae3551SRodney W. Grimes int false = 0; 996a62dc406SDoug Rabson int putdef; 997a62dc406SDoug Rabson sigset_t sighup_mask; 9988fae3551SRodney W. Grimes 999a62dc406SDoug Rabson sigemptyset(&sighup_mask); 1000a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 1001a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 10028fae3551SRodney W. Grimes ep = exphead; 10038fae3551SRodney W. Grimes while (ep) { 10048fae3551SRodney W. Grimes putdef = 0; 100591acb349SAlfred Perlstein if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, 100691acb349SAlfred Perlstein &putdef, brief)) 10078fae3551SRodney W. Grimes goto errout; 10088fae3551SRodney W. Grimes if (ep->ex_defdir && putdef == 0 && 10098fae3551SRodney W. Grimes put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL, 101091acb349SAlfred Perlstein &putdef, brief)) 10118fae3551SRodney W. Grimes goto errout; 10128fae3551SRodney W. Grimes ep = ep->ex_next; 10138fae3551SRodney W. Grimes } 1014a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 10158fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 10168fae3551SRodney W. Grimes return (0); 10178fae3551SRodney W. Grimes return (1); 10188fae3551SRodney W. Grimes errout: 1019a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 10208fae3551SRodney W. Grimes return (0); 10218fae3551SRodney W. Grimes } 10228fae3551SRodney W. Grimes 10238fae3551SRodney W. Grimes /* 10248fae3551SRodney W. Grimes * Called from xdr_explist() to traverse the tree and export the 10258fae3551SRodney W. Grimes * directory paths. 10268fae3551SRodney W. Grimes */ 10278fae3551SRodney W. Grimes int 102891acb349SAlfred Perlstein put_exlist(dp, xdrsp, adp, putdefp, brief) 10298fae3551SRodney W. Grimes struct dirlist *dp; 10308fae3551SRodney W. Grimes XDR *xdrsp; 10318fae3551SRodney W. Grimes struct dirlist *adp; 10328fae3551SRodney W. Grimes int *putdefp; 103391acb349SAlfred Perlstein int brief; 10348fae3551SRodney W. Grimes { 10358fae3551SRodney W. Grimes struct grouplist *grp; 10368fae3551SRodney W. Grimes struct hostlist *hp; 10378fae3551SRodney W. Grimes int true = 1; 10388fae3551SRodney W. Grimes int false = 0; 10398fae3551SRodney W. Grimes int gotalldir = 0; 10408fae3551SRodney W. Grimes char *strp; 10418fae3551SRodney W. Grimes 10428fae3551SRodney W. Grimes if (dp) { 104391acb349SAlfred Perlstein if (put_exlist(dp->dp_left, xdrsp, adp, putdefp, brief)) 10448fae3551SRodney W. Grimes return (1); 10458fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 10468fae3551SRodney W. Grimes return (1); 10478fae3551SRodney W. Grimes strp = dp->dp_dirp; 10488fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 10498fae3551SRodney W. Grimes return (1); 10508fae3551SRodney W. Grimes if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) { 10518fae3551SRodney W. Grimes gotalldir = 1; 10528fae3551SRodney W. Grimes *putdefp = 1; 10538fae3551SRodney W. Grimes } 105491acb349SAlfred Perlstein if (brief) { 105591acb349SAlfred Perlstein if (!xdr_bool(xdrsp, &true)) 105691acb349SAlfred Perlstein return (1); 105791acb349SAlfred Perlstein strp = "(...)"; 105891acb349SAlfred Perlstein if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 105991acb349SAlfred Perlstein return (1); 106091acb349SAlfred Perlstein } else if ((dp->dp_flag & DP_DEFSET) == 0 && 10618fae3551SRodney W. Grimes (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) { 10628fae3551SRodney W. Grimes hp = dp->dp_hosts; 10638fae3551SRodney W. Grimes while (hp) { 10648fae3551SRodney W. Grimes grp = hp->ht_grp; 10658fae3551SRodney W. Grimes if (grp->gr_type == GT_HOST) { 10668fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 10678fae3551SRodney W. Grimes return (1); 10688360efbdSAlfred Perlstein strp = grp->gr_ptr.gt_addrinfo->ai_canonname; 10698fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, 10708fae3551SRodney W. Grimes RPCMNT_NAMELEN)) 10718fae3551SRodney W. Grimes return (1); 10728fae3551SRodney W. Grimes } else if (grp->gr_type == GT_NET) { 10738fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 10748fae3551SRodney W. Grimes return (1); 10758fae3551SRodney W. Grimes strp = grp->gr_ptr.gt_net.nt_name; 10768fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, 10778fae3551SRodney W. Grimes RPCMNT_NAMELEN)) 10788fae3551SRodney W. Grimes return (1); 10798fae3551SRodney W. Grimes } 10808fae3551SRodney W. Grimes hp = hp->ht_next; 10818fae3551SRodney W. Grimes if (gotalldir && hp == (struct hostlist *)NULL) { 10828fae3551SRodney W. Grimes hp = adp->dp_hosts; 10838fae3551SRodney W. Grimes gotalldir = 0; 10848fae3551SRodney W. Grimes } 10858fae3551SRodney W. Grimes } 10868fae3551SRodney W. Grimes } 10878fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 10888fae3551SRodney W. Grimes return (1); 108991acb349SAlfred Perlstein if (put_exlist(dp->dp_right, xdrsp, adp, putdefp, brief)) 10908fae3551SRodney W. Grimes return (1); 10918fae3551SRodney W. Grimes } 10928fae3551SRodney W. Grimes return (0); 10938fae3551SRodney W. Grimes } 10948fae3551SRodney W. Grimes 109591acb349SAlfred Perlstein int 109691acb349SAlfred Perlstein xdr_explist(xdrsp, cp) 109791acb349SAlfred Perlstein XDR *xdrsp; 109891acb349SAlfred Perlstein caddr_t cp; 109991acb349SAlfred Perlstein { 110091acb349SAlfred Perlstein 110191acb349SAlfred Perlstein return xdr_explist_common(xdrsp, cp, 0); 110291acb349SAlfred Perlstein } 110391acb349SAlfred Perlstein 110491acb349SAlfred Perlstein int 110591acb349SAlfred Perlstein xdr_explist_brief(xdrsp, cp) 110691acb349SAlfred Perlstein XDR *xdrsp; 110791acb349SAlfred Perlstein caddr_t cp; 110891acb349SAlfred Perlstein { 110991acb349SAlfred Perlstein 111091acb349SAlfred Perlstein return xdr_explist_common(xdrsp, cp, 1); 111191acb349SAlfred Perlstein } 111291acb349SAlfred Perlstein 111391ca1a91SIan Dowse char *line; 111491ca1a91SIan Dowse int linesize; 11158fae3551SRodney W. Grimes FILE *exp_file; 11168fae3551SRodney W. Grimes 11178fae3551SRodney W. Grimes /* 111896968c22SPawel Jakub Dawidek * Get the export list from one, currently open file 11198fae3551SRodney W. Grimes */ 112096968c22SPawel Jakub Dawidek static void 112196968c22SPawel Jakub Dawidek get_exportlist_one() 11228fae3551SRodney W. Grimes { 11238fae3551SRodney W. Grimes struct exportlist *ep, *ep2; 11248fae3551SRodney W. Grimes struct grouplist *grp, *tgrp; 11258fae3551SRodney W. Grimes struct exportlist **epp; 11268fae3551SRodney W. Grimes struct dirlist *dirhead; 112796968c22SPawel Jakub Dawidek struct statfs fsb; 1128c0511d3bSBrian Feldman struct xucred anon; 11298fae3551SRodney W. Grimes char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; 113096968c22SPawel Jakub Dawidek int len, has_host, exflags, got_nondir, dirplen, netgrp; 11318fae3551SRodney W. Grimes 11328fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 11338fae3551SRodney W. Grimes while (get_line()) { 11348fae3551SRodney W. Grimes if (debug) 113574853402SPhilippe Charnier warnx("got line %s", line); 11368fae3551SRodney W. Grimes cp = line; 11378fae3551SRodney W. Grimes nextfield(&cp, &endcp); 11388fae3551SRodney W. Grimes if (*cp == '#') 11398fae3551SRodney W. Grimes goto nextline; 11408fae3551SRodney W. Grimes 11418fae3551SRodney W. Grimes /* 11428fae3551SRodney W. Grimes * Set defaults. 11438fae3551SRodney W. Grimes */ 11448fae3551SRodney W. Grimes has_host = FALSE; 11458fae3551SRodney W. Grimes anon = def_anon; 11468fae3551SRodney W. Grimes exflags = MNT_EXPORTED; 11478fae3551SRodney W. Grimes got_nondir = 0; 11488fae3551SRodney W. Grimes opt_flags = 0; 11498fae3551SRodney W. Grimes ep = (struct exportlist *)NULL; 11508fae3551SRodney W. Grimes 11518fae3551SRodney W. Grimes /* 11528fae3551SRodney W. Grimes * Create new exports list entry 11538fae3551SRodney W. Grimes */ 11548fae3551SRodney W. Grimes len = endcp-cp; 11558fae3551SRodney W. Grimes tgrp = grp = get_grp(); 11568fae3551SRodney W. Grimes while (len > 0) { 11578fae3551SRodney W. Grimes if (len > RPCMNT_NAMELEN) { 11588fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11598fae3551SRodney W. Grimes goto nextline; 11608fae3551SRodney W. Grimes } 11618fae3551SRodney W. Grimes if (*cp == '-') { 11628fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 11638fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11648fae3551SRodney W. Grimes goto nextline; 11658fae3551SRodney W. Grimes } 11668fae3551SRodney W. Grimes if (debug) 116774853402SPhilippe Charnier warnx("doing opt %s", cp); 11688fae3551SRodney W. Grimes got_nondir = 1; 11698fae3551SRodney W. Grimes if (do_opt(&cp, &endcp, ep, grp, &has_host, 11708fae3551SRodney W. Grimes &exflags, &anon)) { 11718fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11728fae3551SRodney W. Grimes goto nextline; 11738fae3551SRodney W. Grimes } 11748fae3551SRodney W. Grimes } else if (*cp == '/') { 11758fae3551SRodney W. Grimes savedc = *endcp; 11768fae3551SRodney W. Grimes *endcp = '\0'; 11778fae3551SRodney W. Grimes if (check_dirpath(cp) && 11788fae3551SRodney W. Grimes statfs(cp, &fsb) >= 0) { 11798fae3551SRodney W. Grimes if (got_nondir) { 118074853402SPhilippe Charnier syslog(LOG_ERR, "dirs must be first"); 11818fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11828fae3551SRodney W. Grimes goto nextline; 11838fae3551SRodney W. Grimes } 11848fae3551SRodney W. Grimes if (ep) { 11858fae3551SRodney W. Grimes if (ep->ex_fs.val[0] != fsb.f_fsid.val[0] || 11868fae3551SRodney W. Grimes ep->ex_fs.val[1] != fsb.f_fsid.val[1]) { 11878fae3551SRodney W. Grimes getexp_err(ep, tgrp); 11888fae3551SRodney W. Grimes goto nextline; 11898fae3551SRodney W. Grimes } 11908fae3551SRodney W. Grimes } else { 11918fae3551SRodney W. Grimes /* 11928fae3551SRodney W. Grimes * See if this directory is already 11938fae3551SRodney W. Grimes * in the list. 11948fae3551SRodney W. Grimes */ 11958fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 11968fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 11978fae3551SRodney W. Grimes ep = get_exp(); 11988fae3551SRodney W. Grimes ep->ex_fs = fsb.f_fsid; 11998fae3551SRodney W. Grimes ep->ex_fsdir = (char *) 12008fae3551SRodney W. Grimes malloc(strlen(fsb.f_mntonname) + 1); 12018fae3551SRodney W. Grimes if (ep->ex_fsdir) 12028fae3551SRodney W. Grimes strcpy(ep->ex_fsdir, 12038fae3551SRodney W. Grimes fsb.f_mntonname); 12048fae3551SRodney W. Grimes else 12058fae3551SRodney W. Grimes out_of_mem(); 12068fae3551SRodney W. Grimes if (debug) 120774853402SPhilippe Charnier warnx("making new ep fs=0x%x,0x%x", 12088fae3551SRodney W. Grimes fsb.f_fsid.val[0], 12098fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 12108fae3551SRodney W. Grimes } else if (debug) 121174853402SPhilippe Charnier warnx("found ep fs=0x%x,0x%x", 12128fae3551SRodney W. Grimes fsb.f_fsid.val[0], 12138fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 12148fae3551SRodney W. Grimes } 12158fae3551SRodney W. Grimes 12168fae3551SRodney W. Grimes /* 12178fae3551SRodney W. Grimes * Add dirpath to export mount point. 12188fae3551SRodney W. Grimes */ 12198fae3551SRodney W. Grimes dirp = add_expdir(&dirhead, cp, len); 12208fae3551SRodney W. Grimes dirplen = len; 12218fae3551SRodney W. Grimes } else { 12228fae3551SRodney W. Grimes getexp_err(ep, tgrp); 12238fae3551SRodney W. Grimes goto nextline; 12248fae3551SRodney W. Grimes } 12258fae3551SRodney W. Grimes *endcp = savedc; 12268fae3551SRodney W. Grimes } else { 12278fae3551SRodney W. Grimes savedc = *endcp; 12288fae3551SRodney W. Grimes *endcp = '\0'; 12298fae3551SRodney W. Grimes got_nondir = 1; 12308fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 12318fae3551SRodney W. Grimes getexp_err(ep, tgrp); 12328fae3551SRodney W. Grimes goto nextline; 12338fae3551SRodney W. Grimes } 12348fae3551SRodney W. Grimes 12358fae3551SRodney W. Grimes /* 12368fae3551SRodney W. Grimes * Get the host or netgroup. 12378fae3551SRodney W. Grimes */ 12388fae3551SRodney W. Grimes setnetgrent(cp); 12398fae3551SRodney W. Grimes netgrp = getnetgrent(&hst, &usr, &dom); 12408fae3551SRodney W. Grimes do { 12418fae3551SRodney W. Grimes if (has_host) { 12428fae3551SRodney W. Grimes grp->gr_next = get_grp(); 12438fae3551SRodney W. Grimes grp = grp->gr_next; 12448fae3551SRodney W. Grimes } 12458fae3551SRodney W. Grimes if (netgrp) { 12469d70a156SJoerg Wunsch if (hst == 0) { 124774853402SPhilippe Charnier syslog(LOG_ERR, 124874853402SPhilippe Charnier "null hostname in netgroup %s, skipping", cp); 124901d48801SJoerg Wunsch grp->gr_type = GT_IGNORE; 12509d70a156SJoerg Wunsch } else if (get_host(hst, grp, tgrp)) { 125174853402SPhilippe Charnier syslog(LOG_ERR, 125274853402SPhilippe Charnier "bad host %s in netgroup %s, skipping", hst, cp); 1253a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 12548fae3551SRodney W. Grimes } 12558b5a6d67SBill Paul } else if (get_host(cp, grp, tgrp)) { 125674853402SPhilippe Charnier syslog(LOG_ERR, "bad host %s, skipping", cp); 1257a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 12588fae3551SRodney W. Grimes } 12598fae3551SRodney W. Grimes has_host = TRUE; 12608fae3551SRodney W. Grimes } while (netgrp && getnetgrent(&hst, &usr, &dom)); 12618fae3551SRodney W. Grimes endnetgrent(); 12628fae3551SRodney W. Grimes *endcp = savedc; 12638fae3551SRodney W. Grimes } 12648fae3551SRodney W. Grimes cp = endcp; 12658fae3551SRodney W. Grimes nextfield(&cp, &endcp); 12668fae3551SRodney W. Grimes len = endcp - cp; 12678fae3551SRodney W. Grimes } 12688fae3551SRodney W. Grimes if (check_options(dirhead)) { 12698fae3551SRodney W. Grimes getexp_err(ep, tgrp); 12708fae3551SRodney W. Grimes goto nextline; 12718fae3551SRodney W. Grimes } 12728fae3551SRodney W. Grimes if (!has_host) { 12736d359f31SIan Dowse grp->gr_type = GT_DEFAULT; 12748fae3551SRodney W. Grimes if (debug) 127574853402SPhilippe Charnier warnx("adding a default entry"); 12768fae3551SRodney W. Grimes 12778fae3551SRodney W. Grimes /* 12788fae3551SRodney W. Grimes * Don't allow a network export coincide with a list of 12798fae3551SRodney W. Grimes * host(s) on the same line. 12808fae3551SRodney W. Grimes */ 12818fae3551SRodney W. Grimes } else if ((opt_flags & OP_NET) && tgrp->gr_next) { 128260caaee2SIan Dowse syslog(LOG_ERR, "network/host conflict"); 12838fae3551SRodney W. Grimes getexp_err(ep, tgrp); 12848fae3551SRodney W. Grimes goto nextline; 1285a968cfd8SJonathan Lemon 1286a968cfd8SJonathan Lemon /* 1287a968cfd8SJonathan Lemon * If an export list was specified on this line, make sure 1288a968cfd8SJonathan Lemon * that we have at least one valid entry, otherwise skip it. 1289a968cfd8SJonathan Lemon */ 1290a968cfd8SJonathan Lemon } else { 1291a968cfd8SJonathan Lemon grp = tgrp; 1292a968cfd8SJonathan Lemon while (grp && grp->gr_type == GT_IGNORE) 1293a968cfd8SJonathan Lemon grp = grp->gr_next; 1294a968cfd8SJonathan Lemon if (! grp) { 1295a968cfd8SJonathan Lemon getexp_err(ep, tgrp); 1296a968cfd8SJonathan Lemon goto nextline; 1297a968cfd8SJonathan Lemon } 12988fae3551SRodney W. Grimes } 12998fae3551SRodney W. Grimes 13008fae3551SRodney W. Grimes /* 13018fae3551SRodney W. Grimes * Loop through hosts, pushing the exports into the kernel. 13028fae3551SRodney W. Grimes * After loop, tgrp points to the start of the list and 13038fae3551SRodney W. Grimes * grp points to the last entry in the list. 13048fae3551SRodney W. Grimes */ 13058fae3551SRodney W. Grimes grp = tgrp; 13068fae3551SRodney W. Grimes do { 130701709abfSIan Dowse if (do_mount(ep, grp, exflags, &anon, dirp, dirplen, 130801709abfSIan Dowse &fsb)) { 13098fae3551SRodney W. Grimes getexp_err(ep, tgrp); 13108fae3551SRodney W. Grimes goto nextline; 13118fae3551SRodney W. Grimes } 13128fae3551SRodney W. Grimes } while (grp->gr_next && (grp = grp->gr_next)); 13138fae3551SRodney W. Grimes 13148fae3551SRodney W. Grimes /* 13158fae3551SRodney W. Grimes * Success. Update the data structures. 13168fae3551SRodney W. Grimes */ 13178fae3551SRodney W. Grimes if (has_host) { 1318a62dc406SDoug Rabson hang_dirp(dirhead, tgrp, ep, opt_flags); 13198fae3551SRodney W. Grimes grp->gr_next = grphead; 13208fae3551SRodney W. Grimes grphead = tgrp; 13218fae3551SRodney W. Grimes } else { 13228fae3551SRodney W. Grimes hang_dirp(dirhead, (struct grouplist *)NULL, ep, 1323a62dc406SDoug Rabson opt_flags); 13248fae3551SRodney W. Grimes free_grp(grp); 13258fae3551SRodney W. Grimes } 13268fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 13278fae3551SRodney W. Grimes if ((ep->ex_flag & EX_LINKED) == 0) { 13288fae3551SRodney W. Grimes ep2 = exphead; 13298fae3551SRodney W. Grimes epp = &exphead; 13308fae3551SRodney W. Grimes 13318fae3551SRodney W. Grimes /* 13328fae3551SRodney W. Grimes * Insert in the list in alphabetical order. 13338fae3551SRodney W. Grimes */ 13348fae3551SRodney W. Grimes while (ep2 && strcmp(ep2->ex_fsdir, ep->ex_fsdir) < 0) { 13358fae3551SRodney W. Grimes epp = &ep2->ex_next; 13368fae3551SRodney W. Grimes ep2 = ep2->ex_next; 13378fae3551SRodney W. Grimes } 13388fae3551SRodney W. Grimes if (ep2) 13398fae3551SRodney W. Grimes ep->ex_next = ep2; 13408fae3551SRodney W. Grimes *epp = ep; 13418fae3551SRodney W. Grimes ep->ex_flag |= EX_LINKED; 13428fae3551SRodney W. Grimes } 13438fae3551SRodney W. Grimes nextline: 13448fae3551SRodney W. Grimes if (dirhead) { 13458fae3551SRodney W. Grimes free_dir(dirhead); 13468fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 13478fae3551SRodney W. Grimes } 13488fae3551SRodney W. Grimes } 134996968c22SPawel Jakub Dawidek } 135096968c22SPawel Jakub Dawidek 135196968c22SPawel Jakub Dawidek /* 135296968c22SPawel Jakub Dawidek * Get the export list from all specified files 135396968c22SPawel Jakub Dawidek */ 135496968c22SPawel Jakub Dawidek void 135596968c22SPawel Jakub Dawidek get_exportlist() 135696968c22SPawel Jakub Dawidek { 135796968c22SPawel Jakub Dawidek struct exportlist *ep, *ep2; 135896968c22SPawel Jakub Dawidek struct grouplist *grp, *tgrp; 135996968c22SPawel Jakub Dawidek struct export_args export; 136096968c22SPawel Jakub Dawidek struct iovec *iov; 136196968c22SPawel Jakub Dawidek struct statfs *fsp, *mntbufp; 136296968c22SPawel Jakub Dawidek struct xvfsconf vfc; 136396968c22SPawel Jakub Dawidek char *dirp; 136496968c22SPawel Jakub Dawidek char errmsg[255]; 136596968c22SPawel Jakub Dawidek int dirplen, num, i; 136696968c22SPawel Jakub Dawidek int iovlen; 13676c90092bSPawel Jakub Dawidek int done; 136896968c22SPawel Jakub Dawidek 136996968c22SPawel Jakub Dawidek bzero(&export, sizeof(export)); 137096968c22SPawel Jakub Dawidek export.ex_flags = MNT_DELEXPORT; 137196968c22SPawel Jakub Dawidek dirp = NULL; 137296968c22SPawel Jakub Dawidek dirplen = 0; 137396968c22SPawel Jakub Dawidek iov = NULL; 137496968c22SPawel Jakub Dawidek iovlen = 0; 137596968c22SPawel Jakub Dawidek bzero(errmsg, sizeof(errmsg)); 137696968c22SPawel Jakub Dawidek 137796968c22SPawel Jakub Dawidek /* 137896968c22SPawel Jakub Dawidek * First, get rid of the old list 137996968c22SPawel Jakub Dawidek */ 138096968c22SPawel Jakub Dawidek ep = exphead; 138196968c22SPawel Jakub Dawidek while (ep) { 138296968c22SPawel Jakub Dawidek ep2 = ep; 138396968c22SPawel Jakub Dawidek ep = ep->ex_next; 138496968c22SPawel Jakub Dawidek free_exp(ep2); 138596968c22SPawel Jakub Dawidek } 138696968c22SPawel Jakub Dawidek exphead = (struct exportlist *)NULL; 138796968c22SPawel Jakub Dawidek 138896968c22SPawel Jakub Dawidek grp = grphead; 138996968c22SPawel Jakub Dawidek while (grp) { 139096968c22SPawel Jakub Dawidek tgrp = grp; 139196968c22SPawel Jakub Dawidek grp = grp->gr_next; 139296968c22SPawel Jakub Dawidek free_grp(tgrp); 139396968c22SPawel Jakub Dawidek } 139496968c22SPawel Jakub Dawidek grphead = (struct grouplist *)NULL; 139596968c22SPawel Jakub Dawidek 139696968c22SPawel Jakub Dawidek /* 139796968c22SPawel Jakub Dawidek * And delete exports that are in the kernel for all local 139896968c22SPawel Jakub Dawidek * filesystems. 139996968c22SPawel Jakub Dawidek * XXX: Should know how to handle all local exportable filesystems. 140096968c22SPawel Jakub Dawidek */ 140196968c22SPawel Jakub Dawidek num = getmntinfo(&mntbufp, MNT_NOWAIT); 140296968c22SPawel Jakub Dawidek 140396968c22SPawel Jakub Dawidek if (num > 0) { 140496968c22SPawel Jakub Dawidek build_iovec(&iov, &iovlen, "fstype", NULL, 0); 140596968c22SPawel Jakub Dawidek build_iovec(&iov, &iovlen, "fspath", NULL, 0); 140696968c22SPawel Jakub Dawidek build_iovec(&iov, &iovlen, "from", NULL, 0); 140796968c22SPawel Jakub Dawidek build_iovec(&iov, &iovlen, "update", NULL, 0); 140896968c22SPawel Jakub Dawidek build_iovec(&iov, &iovlen, "export", &export, sizeof(export)); 140996968c22SPawel Jakub Dawidek build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); 141096968c22SPawel Jakub Dawidek } 141196968c22SPawel Jakub Dawidek 141296968c22SPawel Jakub Dawidek for (i = 0; i < num; i++) { 141396968c22SPawel Jakub Dawidek fsp = &mntbufp[i]; 141496968c22SPawel Jakub Dawidek if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) { 141596968c22SPawel Jakub Dawidek syslog(LOG_ERR, "getvfsbyname() failed for %s", 141696968c22SPawel Jakub Dawidek fsp->f_fstypename); 141796968c22SPawel Jakub Dawidek continue; 141896968c22SPawel Jakub Dawidek } 141996968c22SPawel Jakub Dawidek 142096968c22SPawel Jakub Dawidek /* 142196968c22SPawel Jakub Dawidek * Do not delete export for network filesystem by 142296968c22SPawel Jakub Dawidek * passing "export" arg to nmount(). 142396968c22SPawel Jakub Dawidek * It only makes sense to do this for local filesystems. 142496968c22SPawel Jakub Dawidek */ 142596968c22SPawel Jakub Dawidek if (vfc.vfc_flags & VFCF_NETWORK) 142696968c22SPawel Jakub Dawidek continue; 142796968c22SPawel Jakub Dawidek 142896968c22SPawel Jakub Dawidek iov[1].iov_base = fsp->f_fstypename; 142996968c22SPawel Jakub Dawidek iov[1].iov_len = strlen(fsp->f_fstypename) + 1; 143096968c22SPawel Jakub Dawidek iov[3].iov_base = fsp->f_mntonname; 143196968c22SPawel Jakub Dawidek iov[3].iov_len = strlen(fsp->f_mntonname) + 1; 143296968c22SPawel Jakub Dawidek iov[5].iov_base = fsp->f_mntfromname; 143396968c22SPawel Jakub Dawidek iov[5].iov_len = strlen(fsp->f_mntfromname) + 1; 143496968c22SPawel Jakub Dawidek 143596968c22SPawel Jakub Dawidek /* 143696968c22SPawel Jakub Dawidek * Kick out MNT_ROOTFS. It should not be passed from 143796968c22SPawel Jakub Dawidek * userland to kernel. It should only be used 143896968c22SPawel Jakub Dawidek * internally in the kernel. 143996968c22SPawel Jakub Dawidek */ 144096968c22SPawel Jakub Dawidek if (fsp->f_flags & MNT_ROOTFS) { 144196968c22SPawel Jakub Dawidek fsp->f_flags &= ~MNT_ROOTFS; 144296968c22SPawel Jakub Dawidek } 144396968c22SPawel Jakub Dawidek 144496968c22SPawel Jakub Dawidek if (nmount(iov, iovlen, fsp->f_flags) < 0 && 144596968c22SPawel Jakub Dawidek errno != ENOENT && errno != ENOTSUP) { 144696968c22SPawel Jakub Dawidek syslog(LOG_ERR, 144796968c22SPawel Jakub Dawidek "can't delete exports for %s: %m %s", 144896968c22SPawel Jakub Dawidek fsp->f_mntonname, errmsg); 144996968c22SPawel Jakub Dawidek } 145096968c22SPawel Jakub Dawidek } 145196968c22SPawel Jakub Dawidek 145296968c22SPawel Jakub Dawidek if (iov != NULL) { 145396968c22SPawel Jakub Dawidek /* Free strings allocated by strdup() in getmntopts.c */ 145496968c22SPawel Jakub Dawidek free(iov[0].iov_base); /* fstype */ 145596968c22SPawel Jakub Dawidek free(iov[2].iov_base); /* fspath */ 145696968c22SPawel Jakub Dawidek free(iov[4].iov_base); /* from */ 145796968c22SPawel Jakub Dawidek free(iov[6].iov_base); /* update */ 145896968c22SPawel Jakub Dawidek free(iov[8].iov_base); /* export */ 145996968c22SPawel Jakub Dawidek free(iov[10].iov_base); /* errmsg */ 146096968c22SPawel Jakub Dawidek 146196968c22SPawel Jakub Dawidek /* free iov, allocated by realloc() */ 146296968c22SPawel Jakub Dawidek free(iov); 146396968c22SPawel Jakub Dawidek iovlen = 0; 146496968c22SPawel Jakub Dawidek } 146596968c22SPawel Jakub Dawidek 146696968c22SPawel Jakub Dawidek /* 146796968c22SPawel Jakub Dawidek * Read in the exports file and build the list, calling 146896968c22SPawel Jakub Dawidek * nmount() as we go along to push the export rules into the kernel. 146996968c22SPawel Jakub Dawidek */ 14706c90092bSPawel Jakub Dawidek done = 0; 147196968c22SPawel Jakub Dawidek for (i = 0; exnames[i] != NULL; i++) { 147296968c22SPawel Jakub Dawidek if (debug) 147396968c22SPawel Jakub Dawidek warnx("reading exports from %s", exnames[i]); 147496968c22SPawel Jakub Dawidek if ((exp_file = fopen(exnames[i], "r")) == NULL) { 14756c90092bSPawel Jakub Dawidek syslog(LOG_WARNING, "can't open %s", exnames[i]); 14766c90092bSPawel Jakub Dawidek continue; 147796968c22SPawel Jakub Dawidek } 147896968c22SPawel Jakub Dawidek get_exportlist_one(); 14798fae3551SRodney W. Grimes fclose(exp_file); 14806c90092bSPawel Jakub Dawidek done++; 14816c90092bSPawel Jakub Dawidek } 14826c90092bSPawel Jakub Dawidek if (done == 0) { 14836c90092bSPawel Jakub Dawidek syslog(LOG_ERR, "can't open any exports file"); 14846c90092bSPawel Jakub Dawidek exit(2); 14858fae3551SRodney W. Grimes } 148696968c22SPawel Jakub Dawidek } 14878fae3551SRodney W. Grimes 14888fae3551SRodney W. Grimes /* 14898fae3551SRodney W. Grimes * Allocate an export list element 14908fae3551SRodney W. Grimes */ 14918fae3551SRodney W. Grimes struct exportlist * 14928fae3551SRodney W. Grimes get_exp() 14938fae3551SRodney W. Grimes { 14948fae3551SRodney W. Grimes struct exportlist *ep; 14958fae3551SRodney W. Grimes 14968fae3551SRodney W. Grimes ep = (struct exportlist *)malloc(sizeof (struct exportlist)); 14978fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) 14988fae3551SRodney W. Grimes out_of_mem(); 149987564113SPeter Wemm memset(ep, 0, sizeof(struct exportlist)); 15008fae3551SRodney W. Grimes return (ep); 15018fae3551SRodney W. Grimes } 15028fae3551SRodney W. Grimes 15038fae3551SRodney W. Grimes /* 15048fae3551SRodney W. Grimes * Allocate a group list element 15058fae3551SRodney W. Grimes */ 15068fae3551SRodney W. Grimes struct grouplist * 15078fae3551SRodney W. Grimes get_grp() 15088fae3551SRodney W. Grimes { 15098fae3551SRodney W. Grimes struct grouplist *gp; 15108fae3551SRodney W. Grimes 15118fae3551SRodney W. Grimes gp = (struct grouplist *)malloc(sizeof (struct grouplist)); 15128fae3551SRodney W. Grimes if (gp == (struct grouplist *)NULL) 15138fae3551SRodney W. Grimes out_of_mem(); 151487564113SPeter Wemm memset(gp, 0, sizeof(struct grouplist)); 15158fae3551SRodney W. Grimes return (gp); 15168fae3551SRodney W. Grimes } 15178fae3551SRodney W. Grimes 15188fae3551SRodney W. Grimes /* 15198fae3551SRodney W. Grimes * Clean up upon an error in get_exportlist(). 15208fae3551SRodney W. Grimes */ 15218fae3551SRodney W. Grimes void 15228fae3551SRodney W. Grimes getexp_err(ep, grp) 15238fae3551SRodney W. Grimes struct exportlist *ep; 15248fae3551SRodney W. Grimes struct grouplist *grp; 15258fae3551SRodney W. Grimes { 15268fae3551SRodney W. Grimes struct grouplist *tgrp; 15278fae3551SRodney W. Grimes 1528288fa14aSJoerg Wunsch if (!(opt_flags & OP_QUIET)) 152974853402SPhilippe Charnier syslog(LOG_ERR, "bad exports list line %s", line); 15308fae3551SRodney W. Grimes if (ep && (ep->ex_flag & EX_LINKED) == 0) 15318fae3551SRodney W. Grimes free_exp(ep); 15328fae3551SRodney W. Grimes while (grp) { 15338fae3551SRodney W. Grimes tgrp = grp; 15348fae3551SRodney W. Grimes grp = grp->gr_next; 15358fae3551SRodney W. Grimes free_grp(tgrp); 15368fae3551SRodney W. Grimes } 15378fae3551SRodney W. Grimes } 15388fae3551SRodney W. Grimes 15398fae3551SRodney W. Grimes /* 15408fae3551SRodney W. Grimes * Search the export list for a matching fs. 15418fae3551SRodney W. Grimes */ 15428fae3551SRodney W. Grimes struct exportlist * 15438fae3551SRodney W. Grimes ex_search(fsid) 15448fae3551SRodney W. Grimes fsid_t *fsid; 15458fae3551SRodney W. Grimes { 15468fae3551SRodney W. Grimes struct exportlist *ep; 15478fae3551SRodney W. Grimes 15488fae3551SRodney W. Grimes ep = exphead; 15498fae3551SRodney W. Grimes while (ep) { 15508fae3551SRodney W. Grimes if (ep->ex_fs.val[0] == fsid->val[0] && 15518fae3551SRodney W. Grimes ep->ex_fs.val[1] == fsid->val[1]) 15528fae3551SRodney W. Grimes return (ep); 15538fae3551SRodney W. Grimes ep = ep->ex_next; 15548fae3551SRodney W. Grimes } 15558fae3551SRodney W. Grimes return (ep); 15568fae3551SRodney W. Grimes } 15578fae3551SRodney W. Grimes 15588fae3551SRodney W. Grimes /* 15598fae3551SRodney W. Grimes * Add a directory path to the list. 15608fae3551SRodney W. Grimes */ 15618fae3551SRodney W. Grimes char * 15628fae3551SRodney W. Grimes add_expdir(dpp, cp, len) 15638fae3551SRodney W. Grimes struct dirlist **dpp; 15648fae3551SRodney W. Grimes char *cp; 15658fae3551SRodney W. Grimes int len; 15668fae3551SRodney W. Grimes { 15678fae3551SRodney W. Grimes struct dirlist *dp; 15688fae3551SRodney W. Grimes 15698fae3551SRodney W. Grimes dp = (struct dirlist *)malloc(sizeof (struct dirlist) + len); 157074853402SPhilippe Charnier if (dp == (struct dirlist *)NULL) 157174853402SPhilippe Charnier out_of_mem(); 15728fae3551SRodney W. Grimes dp->dp_left = *dpp; 15738fae3551SRodney W. Grimes dp->dp_right = (struct dirlist *)NULL; 15748fae3551SRodney W. Grimes dp->dp_flag = 0; 15758fae3551SRodney W. Grimes dp->dp_hosts = (struct hostlist *)NULL; 15768fae3551SRodney W. Grimes strcpy(dp->dp_dirp, cp); 15778fae3551SRodney W. Grimes *dpp = dp; 15788fae3551SRodney W. Grimes return (dp->dp_dirp); 15798fae3551SRodney W. Grimes } 15808fae3551SRodney W. Grimes 15818fae3551SRodney W. Grimes /* 15828fae3551SRodney W. Grimes * Hang the dir list element off the dirpath binary tree as required 15838fae3551SRodney W. Grimes * and update the entry for host. 15848fae3551SRodney W. Grimes */ 15858fae3551SRodney W. Grimes void 1586a62dc406SDoug Rabson hang_dirp(dp, grp, ep, flags) 15878fae3551SRodney W. Grimes struct dirlist *dp; 15888fae3551SRodney W. Grimes struct grouplist *grp; 15898fae3551SRodney W. Grimes struct exportlist *ep; 1590a62dc406SDoug Rabson int flags; 15918fae3551SRodney W. Grimes { 15928fae3551SRodney W. Grimes struct hostlist *hp; 15938fae3551SRodney W. Grimes struct dirlist *dp2; 15948fae3551SRodney W. Grimes 1595a62dc406SDoug Rabson if (flags & OP_ALLDIRS) { 15968fae3551SRodney W. Grimes if (ep->ex_defdir) 15978fae3551SRodney W. Grimes free((caddr_t)dp); 15988fae3551SRodney W. Grimes else 15998fae3551SRodney W. Grimes ep->ex_defdir = dp; 1600a62dc406SDoug Rabson if (grp == (struct grouplist *)NULL) { 16018fae3551SRodney W. Grimes ep->ex_defdir->dp_flag |= DP_DEFSET; 1602a62dc406SDoug Rabson } else while (grp) { 16038fae3551SRodney W. Grimes hp = get_ht(); 16048fae3551SRodney W. Grimes hp->ht_grp = grp; 16058fae3551SRodney W. Grimes hp->ht_next = ep->ex_defdir->dp_hosts; 16068fae3551SRodney W. Grimes ep->ex_defdir->dp_hosts = hp; 16078fae3551SRodney W. Grimes grp = grp->gr_next; 16088fae3551SRodney W. Grimes } 16098fae3551SRodney W. Grimes } else { 16108fae3551SRodney W. Grimes 16118fae3551SRodney W. Grimes /* 161274853402SPhilippe Charnier * Loop through the directories adding them to the tree. 16138fae3551SRodney W. Grimes */ 16148fae3551SRodney W. Grimes while (dp) { 16158fae3551SRodney W. Grimes dp2 = dp->dp_left; 1616a62dc406SDoug Rabson add_dlist(&ep->ex_dirl, dp, grp, flags); 16178fae3551SRodney W. Grimes dp = dp2; 16188fae3551SRodney W. Grimes } 16198fae3551SRodney W. Grimes } 16208fae3551SRodney W. Grimes } 16218fae3551SRodney W. Grimes 16228fae3551SRodney W. Grimes /* 16238fae3551SRodney W. Grimes * Traverse the binary tree either updating a node that is already there 16248fae3551SRodney W. Grimes * for the new directory or adding the new node. 16258fae3551SRodney W. Grimes */ 16268fae3551SRodney W. Grimes void 1627a62dc406SDoug Rabson add_dlist(dpp, newdp, grp, flags) 16288fae3551SRodney W. Grimes struct dirlist **dpp; 16298fae3551SRodney W. Grimes struct dirlist *newdp; 16308fae3551SRodney W. Grimes struct grouplist *grp; 1631a62dc406SDoug Rabson int flags; 16328fae3551SRodney W. Grimes { 16338fae3551SRodney W. Grimes struct dirlist *dp; 16348fae3551SRodney W. Grimes struct hostlist *hp; 16358fae3551SRodney W. Grimes int cmp; 16368fae3551SRodney W. Grimes 16378fae3551SRodney W. Grimes dp = *dpp; 16388fae3551SRodney W. Grimes if (dp) { 16398fae3551SRodney W. Grimes cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); 16408fae3551SRodney W. Grimes if (cmp > 0) { 1641a62dc406SDoug Rabson add_dlist(&dp->dp_left, newdp, grp, flags); 16428fae3551SRodney W. Grimes return; 16438fae3551SRodney W. Grimes } else if (cmp < 0) { 1644a62dc406SDoug Rabson add_dlist(&dp->dp_right, newdp, grp, flags); 16458fae3551SRodney W. Grimes return; 16468fae3551SRodney W. Grimes } else 16478fae3551SRodney W. Grimes free((caddr_t)newdp); 16488fae3551SRodney W. Grimes } else { 16498fae3551SRodney W. Grimes dp = newdp; 16508fae3551SRodney W. Grimes dp->dp_left = (struct dirlist *)NULL; 16518fae3551SRodney W. Grimes *dpp = dp; 16528fae3551SRodney W. Grimes } 16538fae3551SRodney W. Grimes if (grp) { 16548fae3551SRodney W. Grimes 16558fae3551SRodney W. Grimes /* 16568fae3551SRodney W. Grimes * Hang all of the host(s) off of the directory point. 16578fae3551SRodney W. Grimes */ 16588fae3551SRodney W. Grimes do { 16598fae3551SRodney W. Grimes hp = get_ht(); 16608fae3551SRodney W. Grimes hp->ht_grp = grp; 16618fae3551SRodney W. Grimes hp->ht_next = dp->dp_hosts; 16628fae3551SRodney W. Grimes dp->dp_hosts = hp; 16638fae3551SRodney W. Grimes grp = grp->gr_next; 16648fae3551SRodney W. Grimes } while (grp); 1665a62dc406SDoug Rabson } else { 16668fae3551SRodney W. Grimes dp->dp_flag |= DP_DEFSET; 1667a62dc406SDoug Rabson } 16688fae3551SRodney W. Grimes } 16698fae3551SRodney W. Grimes 16708fae3551SRodney W. Grimes /* 16718fae3551SRodney W. Grimes * Search for a dirpath on the export point. 16728fae3551SRodney W. Grimes */ 16738fae3551SRodney W. Grimes struct dirlist * 16748360efbdSAlfred Perlstein dirp_search(dp, dirp) 16758fae3551SRodney W. Grimes struct dirlist *dp; 16768360efbdSAlfred Perlstein char *dirp; 16778fae3551SRodney W. Grimes { 16788fae3551SRodney W. Grimes int cmp; 16798fae3551SRodney W. Grimes 16808fae3551SRodney W. Grimes if (dp) { 16818360efbdSAlfred Perlstein cmp = strcmp(dp->dp_dirp, dirp); 16828fae3551SRodney W. Grimes if (cmp > 0) 16838360efbdSAlfred Perlstein return (dirp_search(dp->dp_left, dirp)); 16848fae3551SRodney W. Grimes else if (cmp < 0) 16858360efbdSAlfred Perlstein return (dirp_search(dp->dp_right, dirp)); 16868fae3551SRodney W. Grimes else 16878fae3551SRodney W. Grimes return (dp); 16888fae3551SRodney W. Grimes } 16898fae3551SRodney W. Grimes return (dp); 16908fae3551SRodney W. Grimes } 16918fae3551SRodney W. Grimes 16928fae3551SRodney W. Grimes /* 16938fae3551SRodney W. Grimes * Scan for a host match in a directory tree. 16948fae3551SRodney W. Grimes */ 16958fae3551SRodney W. Grimes int 1696a62dc406SDoug Rabson chk_host(dp, saddr, defsetp, hostsetp) 16978fae3551SRodney W. Grimes struct dirlist *dp; 16988360efbdSAlfred Perlstein struct sockaddr *saddr; 16998fae3551SRodney W. Grimes int *defsetp; 1700a62dc406SDoug Rabson int *hostsetp; 17018fae3551SRodney W. Grimes { 17028fae3551SRodney W. Grimes struct hostlist *hp; 17038fae3551SRodney W. Grimes struct grouplist *grp; 17048360efbdSAlfred Perlstein struct addrinfo *ai; 17058fae3551SRodney W. Grimes 17068fae3551SRodney W. Grimes if (dp) { 17078fae3551SRodney W. Grimes if (dp->dp_flag & DP_DEFSET) 1708a62dc406SDoug Rabson *defsetp = dp->dp_flag; 17098fae3551SRodney W. Grimes hp = dp->dp_hosts; 17108fae3551SRodney W. Grimes while (hp) { 17118fae3551SRodney W. Grimes grp = hp->ht_grp; 17128fae3551SRodney W. Grimes switch (grp->gr_type) { 17138fae3551SRodney W. Grimes case GT_HOST: 17148360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 17158360efbdSAlfred Perlstein for (; ai; ai = ai->ai_next) { 171660caaee2SIan Dowse if (!sacmp(ai->ai_addr, saddr, NULL)) { 17178360efbdSAlfred Perlstein *hostsetp = 17188360efbdSAlfred Perlstein (hp->ht_flag | DP_HOSTSET); 17198fae3551SRodney W. Grimes return (1); 1720a62dc406SDoug Rabson } 17218fae3551SRodney W. Grimes } 17228fae3551SRodney W. Grimes break; 17238fae3551SRodney W. Grimes case GT_NET: 172460caaee2SIan Dowse if (!sacmp(saddr, (struct sockaddr *) 172560caaee2SIan Dowse &grp->gr_ptr.gt_net.nt_net, 172660caaee2SIan Dowse (struct sockaddr *) 172760caaee2SIan Dowse &grp->gr_ptr.gt_net.nt_mask)) { 1728a62dc406SDoug Rabson *hostsetp = (hp->ht_flag | DP_HOSTSET); 17298fae3551SRodney W. Grimes return (1); 1730a62dc406SDoug Rabson } 17318fae3551SRodney W. Grimes break; 173260caaee2SIan Dowse } 17338fae3551SRodney W. Grimes hp = hp->ht_next; 17348fae3551SRodney W. Grimes } 17358fae3551SRodney W. Grimes } 17368fae3551SRodney W. Grimes return (0); 17378fae3551SRodney W. Grimes } 17388fae3551SRodney W. Grimes 17398fae3551SRodney W. Grimes /* 17408fae3551SRodney W. Grimes * Scan tree for a host that matches the address. 17418fae3551SRodney W. Grimes */ 17428fae3551SRodney W. Grimes int 17438fae3551SRodney W. Grimes scan_tree(dp, saddr) 17448fae3551SRodney W. Grimes struct dirlist *dp; 17458360efbdSAlfred Perlstein struct sockaddr *saddr; 17468fae3551SRodney W. Grimes { 1747a62dc406SDoug Rabson int defset, hostset; 17488fae3551SRodney W. Grimes 17498fae3551SRodney W. Grimes if (dp) { 17508fae3551SRodney W. Grimes if (scan_tree(dp->dp_left, saddr)) 17518fae3551SRodney W. Grimes return (1); 1752a62dc406SDoug Rabson if (chk_host(dp, saddr, &defset, &hostset)) 17538fae3551SRodney W. Grimes return (1); 17548fae3551SRodney W. Grimes if (scan_tree(dp->dp_right, saddr)) 17558fae3551SRodney W. Grimes return (1); 17568fae3551SRodney W. Grimes } 17578fae3551SRodney W. Grimes return (0); 17588fae3551SRodney W. Grimes } 17598fae3551SRodney W. Grimes 17608fae3551SRodney W. Grimes /* 17618fae3551SRodney W. Grimes * Traverse the dirlist tree and free it up. 17628fae3551SRodney W. Grimes */ 17638fae3551SRodney W. Grimes void 17648fae3551SRodney W. Grimes free_dir(dp) 17658fae3551SRodney W. Grimes struct dirlist *dp; 17668fae3551SRodney W. Grimes { 17678fae3551SRodney W. Grimes 17688fae3551SRodney W. Grimes if (dp) { 17698fae3551SRodney W. Grimes free_dir(dp->dp_left); 17708fae3551SRodney W. Grimes free_dir(dp->dp_right); 17718fae3551SRodney W. Grimes free_host(dp->dp_hosts); 17728fae3551SRodney W. Grimes free((caddr_t)dp); 17738fae3551SRodney W. Grimes } 17748fae3551SRodney W. Grimes } 17758fae3551SRodney W. Grimes 17768fae3551SRodney W. Grimes /* 17778fae3551SRodney W. Grimes * Parse the option string and update fields. 17788fae3551SRodney W. Grimes * Option arguments may either be -<option>=<value> or 17798fae3551SRodney W. Grimes * -<option> <value> 17808fae3551SRodney W. Grimes */ 17818fae3551SRodney W. Grimes int 17828fae3551SRodney W. Grimes do_opt(cpp, endcpp, ep, grp, has_hostp, exflagsp, cr) 17838fae3551SRodney W. Grimes char **cpp, **endcpp; 17848fae3551SRodney W. Grimes struct exportlist *ep; 17858fae3551SRodney W. Grimes struct grouplist *grp; 17868fae3551SRodney W. Grimes int *has_hostp; 17878fae3551SRodney W. Grimes int *exflagsp; 1788c0511d3bSBrian Feldman struct xucred *cr; 17898fae3551SRodney W. Grimes { 17908fae3551SRodney W. Grimes char *cpoptarg, *cpoptend; 17918fae3551SRodney W. Grimes char *cp, *endcp, *cpopt, savedc, savedc2; 17928fae3551SRodney W. Grimes int allflag, usedarg; 17938fae3551SRodney W. Grimes 1794cb479b11SAlfred Perlstein savedc2 = '\0'; 17958fae3551SRodney W. Grimes cpopt = *cpp; 17968fae3551SRodney W. Grimes cpopt++; 17978fae3551SRodney W. Grimes cp = *endcpp; 17988fae3551SRodney W. Grimes savedc = *cp; 17998fae3551SRodney W. Grimes *cp = '\0'; 18008fae3551SRodney W. Grimes while (cpopt && *cpopt) { 18018fae3551SRodney W. Grimes allflag = 1; 18028fae3551SRodney W. Grimes usedarg = -2; 180374853402SPhilippe Charnier if ((cpoptend = strchr(cpopt, ','))) { 18048fae3551SRodney W. Grimes *cpoptend++ = '\0'; 180574853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 18068fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 18078fae3551SRodney W. Grimes } else { 180874853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 18098fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 18108fae3551SRodney W. Grimes else { 18118fae3551SRodney W. Grimes *cp = savedc; 18128fae3551SRodney W. Grimes nextfield(&cp, &endcp); 18138fae3551SRodney W. Grimes **endcpp = '\0'; 18148fae3551SRodney W. Grimes if (endcp > cp && *cp != '-') { 18158fae3551SRodney W. Grimes cpoptarg = cp; 18168fae3551SRodney W. Grimes savedc2 = *endcp; 18178fae3551SRodney W. Grimes *endcp = '\0'; 18188fae3551SRodney W. Grimes usedarg = 0; 18198fae3551SRodney W. Grimes } 18208fae3551SRodney W. Grimes } 18218fae3551SRodney W. Grimes } 18228fae3551SRodney W. Grimes if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 18238fae3551SRodney W. Grimes *exflagsp |= MNT_EXRDONLY; 18248fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "maproot") || 18258fae3551SRodney W. Grimes !(allflag = strcmp(cpopt, "mapall")) || 18268fae3551SRodney W. Grimes !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) { 18278fae3551SRodney W. Grimes usedarg++; 18288fae3551SRodney W. Grimes parsecred(cpoptarg, cr); 18298fae3551SRodney W. Grimes if (allflag == 0) { 18308fae3551SRodney W. Grimes *exflagsp |= MNT_EXPORTANON; 18318fae3551SRodney W. Grimes opt_flags |= OP_MAPALL; 18328fae3551SRodney W. Grimes } else 18338fae3551SRodney W. Grimes opt_flags |= OP_MAPROOT; 18348fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "mask") || 18358fae3551SRodney W. Grimes !strcmp(cpopt, "m"))) { 18368fae3551SRodney W. Grimes if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { 183774853402SPhilippe Charnier syslog(LOG_ERR, "bad mask: %s", cpoptarg); 18388fae3551SRodney W. Grimes return (1); 18398fae3551SRodney W. Grimes } 18408fae3551SRodney W. Grimes usedarg++; 18418fae3551SRodney W. Grimes opt_flags |= OP_MASK; 18428fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "network") || 18438fae3551SRodney W. Grimes !strcmp(cpopt, "n"))) { 18448360efbdSAlfred Perlstein if (strchr(cpoptarg, '/') != NULL) { 18458360efbdSAlfred Perlstein if (debug) 18468360efbdSAlfred Perlstein fprintf(stderr, "setting OP_MASKLEN\n"); 18478360efbdSAlfred Perlstein opt_flags |= OP_MASKLEN; 18488360efbdSAlfred Perlstein } 18498fae3551SRodney W. Grimes if (grp->gr_type != GT_NULL) { 185074853402SPhilippe Charnier syslog(LOG_ERR, "network/host conflict"); 18518fae3551SRodney W. Grimes return (1); 18528fae3551SRodney W. Grimes } else if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 0)) { 185374853402SPhilippe Charnier syslog(LOG_ERR, "bad net: %s", cpoptarg); 18548fae3551SRodney W. Grimes return (1); 18558fae3551SRodney W. Grimes } 18568fae3551SRodney W. Grimes grp->gr_type = GT_NET; 18578fae3551SRodney W. Grimes *has_hostp = 1; 18588fae3551SRodney W. Grimes usedarg++; 18598fae3551SRodney W. Grimes opt_flags |= OP_NET; 18608fae3551SRodney W. Grimes } else if (!strcmp(cpopt, "alldirs")) { 18618fae3551SRodney W. Grimes opt_flags |= OP_ALLDIRS; 1862cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "public")) { 1863cb3923e0SDoug Rabson *exflagsp |= MNT_EXPUBLIC; 1864cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "webnfs")) { 1865cb3923e0SDoug Rabson *exflagsp |= (MNT_EXPUBLIC|MNT_EXRDONLY|MNT_EXPORTANON); 1866cb3923e0SDoug Rabson opt_flags |= OP_MAPALL; 1867cb3923e0SDoug Rabson } else if (cpoptarg && !strcmp(cpopt, "index")) { 1868cb3923e0SDoug Rabson ep->ex_indexfile = strdup(cpoptarg); 1869288fa14aSJoerg Wunsch } else if (!strcmp(cpopt, "quiet")) { 1870288fa14aSJoerg Wunsch opt_flags |= OP_QUIET; 18718fae3551SRodney W. Grimes } else { 187274853402SPhilippe Charnier syslog(LOG_ERR, "bad opt %s", cpopt); 18738fae3551SRodney W. Grimes return (1); 18748fae3551SRodney W. Grimes } 18758fae3551SRodney W. Grimes if (usedarg >= 0) { 18768fae3551SRodney W. Grimes *endcp = savedc2; 18778fae3551SRodney W. Grimes **endcpp = savedc; 18788fae3551SRodney W. Grimes if (usedarg > 0) { 18798fae3551SRodney W. Grimes *cpp = cp; 18808fae3551SRodney W. Grimes *endcpp = endcp; 18818fae3551SRodney W. Grimes } 18828fae3551SRodney W. Grimes return (0); 18838fae3551SRodney W. Grimes } 18848fae3551SRodney W. Grimes cpopt = cpoptend; 18858fae3551SRodney W. Grimes } 18868fae3551SRodney W. Grimes **endcpp = savedc; 18878fae3551SRodney W. Grimes return (0); 18888fae3551SRodney W. Grimes } 18898fae3551SRodney W. Grimes 18908fae3551SRodney W. Grimes /* 18918fae3551SRodney W. Grimes * Translate a character string to the corresponding list of network 18928fae3551SRodney W. Grimes * addresses for a hostname. 18938fae3551SRodney W. Grimes */ 18948fae3551SRodney W. Grimes int 18958b5a6d67SBill Paul get_host(cp, grp, tgrp) 18968fae3551SRodney W. Grimes char *cp; 18978fae3551SRodney W. Grimes struct grouplist *grp; 18988b5a6d67SBill Paul struct grouplist *tgrp; 18998fae3551SRodney W. Grimes { 19008b5a6d67SBill Paul struct grouplist *checkgrp; 190101709abfSIan Dowse struct addrinfo *ai, *tai, hints; 19028360efbdSAlfred Perlstein int ecode; 19038360efbdSAlfred Perlstein char host[NI_MAXHOST]; 19048fae3551SRodney W. Grimes 19058360efbdSAlfred Perlstein if (grp->gr_type != GT_NULL) { 19068360efbdSAlfred Perlstein syslog(LOG_ERR, "Bad netgroup type for ip host %s", cp); 19078fae3551SRodney W. Grimes return (1); 19088fae3551SRodney W. Grimes } 19098360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 19108360efbdSAlfred Perlstein hints.ai_flags = AI_CANONNAME; 19118360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_UDP; 19128360efbdSAlfred Perlstein ecode = getaddrinfo(cp, NULL, &hints, &ai); 19138360efbdSAlfred Perlstein if (ecode != 0) { 191401709abfSIan Dowse syslog(LOG_ERR,"can't get address info for host %s", cp); 19158360efbdSAlfred Perlstein return 1; 19168fae3551SRodney W. Grimes } 19178360efbdSAlfred Perlstein grp->gr_ptr.gt_addrinfo = ai; 19188360efbdSAlfred Perlstein while (ai != NULL) { 19198360efbdSAlfred Perlstein if (ai->ai_canonname == NULL) { 19208360efbdSAlfred Perlstein if (getnameinfo(ai->ai_addr, ai->ai_addrlen, host, 19214f101318SHajimu UMEMOTO sizeof host, NULL, 0, NI_NUMERICHOST) != 0) 19228360efbdSAlfred Perlstein strlcpy(host, "?", sizeof(host)); 19238360efbdSAlfred Perlstein ai->ai_canonname = strdup(host); 19248360efbdSAlfred Perlstein ai->ai_flags |= AI_CANONNAME; 19256d359f31SIan Dowse } 19268fae3551SRodney W. Grimes if (debug) 192701709abfSIan Dowse fprintf(stderr, "got host %s\n", ai->ai_canonname); 192801709abfSIan Dowse /* 192901709abfSIan Dowse * Sanity check: make sure we don't already have an entry 193001709abfSIan Dowse * for this host in the grouplist. 193101709abfSIan Dowse */ 193201709abfSIan Dowse for (checkgrp = tgrp; checkgrp != NULL; 193301709abfSIan Dowse checkgrp = checkgrp->gr_next) { 193401709abfSIan Dowse if (checkgrp->gr_type != GT_HOST) 193501709abfSIan Dowse continue; 193601709abfSIan Dowse for (tai = checkgrp->gr_ptr.gt_addrinfo; tai != NULL; 193701709abfSIan Dowse tai = tai->ai_next) { 193860caaee2SIan Dowse if (sacmp(tai->ai_addr, ai->ai_addr, NULL) != 0) 193901709abfSIan Dowse continue; 194001709abfSIan Dowse if (debug) 194101709abfSIan Dowse fprintf(stderr, 194201709abfSIan Dowse "ignoring duplicate host %s\n", 194301709abfSIan Dowse ai->ai_canonname); 194401709abfSIan Dowse grp->gr_type = GT_IGNORE; 194501709abfSIan Dowse return (0); 194601709abfSIan Dowse } 194701709abfSIan Dowse } 19488360efbdSAlfred Perlstein ai = ai->ai_next; 19498360efbdSAlfred Perlstein } 195001709abfSIan Dowse grp->gr_type = GT_HOST; 19518fae3551SRodney W. Grimes return (0); 19528fae3551SRodney W. Grimes } 19538fae3551SRodney W. Grimes 19548fae3551SRodney W. Grimes /* 19558fae3551SRodney W. Grimes * Free up an exports list component 19568fae3551SRodney W. Grimes */ 19578fae3551SRodney W. Grimes void 19588fae3551SRodney W. Grimes free_exp(ep) 19598fae3551SRodney W. Grimes struct exportlist *ep; 19608fae3551SRodney W. Grimes { 19618fae3551SRodney W. Grimes 19628fae3551SRodney W. Grimes if (ep->ex_defdir) { 19638fae3551SRodney W. Grimes free_host(ep->ex_defdir->dp_hosts); 19648fae3551SRodney W. Grimes free((caddr_t)ep->ex_defdir); 19658fae3551SRodney W. Grimes } 19668fae3551SRodney W. Grimes if (ep->ex_fsdir) 19678fae3551SRodney W. Grimes free(ep->ex_fsdir); 1968cb3923e0SDoug Rabson if (ep->ex_indexfile) 1969cb3923e0SDoug Rabson free(ep->ex_indexfile); 19708fae3551SRodney W. Grimes free_dir(ep->ex_dirl); 19718fae3551SRodney W. Grimes free((caddr_t)ep); 19728fae3551SRodney W. Grimes } 19738fae3551SRodney W. Grimes 19748fae3551SRodney W. Grimes /* 19758fae3551SRodney W. Grimes * Free hosts. 19768fae3551SRodney W. Grimes */ 19778fae3551SRodney W. Grimes void 19788fae3551SRodney W. Grimes free_host(hp) 19798fae3551SRodney W. Grimes struct hostlist *hp; 19808fae3551SRodney W. Grimes { 19818fae3551SRodney W. Grimes struct hostlist *hp2; 19828fae3551SRodney W. Grimes 19838fae3551SRodney W. Grimes while (hp) { 19848fae3551SRodney W. Grimes hp2 = hp; 19858fae3551SRodney W. Grimes hp = hp->ht_next; 19868fae3551SRodney W. Grimes free((caddr_t)hp2); 19878fae3551SRodney W. Grimes } 19888fae3551SRodney W. Grimes } 19898fae3551SRodney W. Grimes 19908fae3551SRodney W. Grimes struct hostlist * 19918fae3551SRodney W. Grimes get_ht() 19928fae3551SRodney W. Grimes { 19938fae3551SRodney W. Grimes struct hostlist *hp; 19948fae3551SRodney W. Grimes 19958fae3551SRodney W. Grimes hp = (struct hostlist *)malloc(sizeof (struct hostlist)); 19968fae3551SRodney W. Grimes if (hp == (struct hostlist *)NULL) 19978fae3551SRodney W. Grimes out_of_mem(); 19988fae3551SRodney W. Grimes hp->ht_next = (struct hostlist *)NULL; 1999a62dc406SDoug Rabson hp->ht_flag = 0; 20008fae3551SRodney W. Grimes return (hp); 20018fae3551SRodney W. Grimes } 20028fae3551SRodney W. Grimes 20038fae3551SRodney W. Grimes /* 20048fae3551SRodney W. Grimes * Out of memory, fatal 20058fae3551SRodney W. Grimes */ 20068fae3551SRodney W. Grimes void 20078fae3551SRodney W. Grimes out_of_mem() 20088fae3551SRodney W. Grimes { 20098fae3551SRodney W. Grimes 201074853402SPhilippe Charnier syslog(LOG_ERR, "out of memory"); 20118fae3551SRodney W. Grimes exit(2); 20128fae3551SRodney W. Grimes } 20138fae3551SRodney W. Grimes 20148fae3551SRodney W. Grimes /* 20156a09faf2SCraig Rodrigues * Do the nmount() syscall with the update flag to push the export info into 20168fae3551SRodney W. Grimes * the kernel. 20178fae3551SRodney W. Grimes */ 20188fae3551SRodney W. Grimes int 20196a09faf2SCraig Rodrigues do_mount(struct exportlist *ep, struct grouplist *grp, int exflags, 20206a09faf2SCraig Rodrigues struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb) 20218fae3551SRodney W. Grimes { 2022f93caef2SIan Dowse struct statfs fsb1; 20238360efbdSAlfred Perlstein struct addrinfo *ai; 20246a09faf2SCraig Rodrigues struct export_args eap; 20256a09faf2SCraig Rodrigues char errmsg[255]; 20266a09faf2SCraig Rodrigues char *cp; 20278fae3551SRodney W. Grimes int done; 20286a09faf2SCraig Rodrigues char savedc; 20296a09faf2SCraig Rodrigues struct iovec *iov; 20306a09faf2SCraig Rodrigues int iovlen; 20316a09faf2SCraig Rodrigues int ret; 20328fae3551SRodney W. Grimes 20336a09faf2SCraig Rodrigues cp = NULL; 20346a09faf2SCraig Rodrigues savedc = '\0'; 20356a09faf2SCraig Rodrigues iov = NULL; 20366a09faf2SCraig Rodrigues iovlen = 0; 20376a09faf2SCraig Rodrigues ret = 0; 203860caaee2SIan Dowse 20396a09faf2SCraig Rodrigues bzero(&eap, sizeof(eap)); 20406a09faf2SCraig Rodrigues bzero(errmsg, sizeof(errmsg)); 20416a09faf2SCraig Rodrigues eap.ex_flags = exflags; 20426a09faf2SCraig Rodrigues eap.ex_anon = *anoncrp; 20436a09faf2SCraig Rodrigues eap.ex_indexfile = ep->ex_indexfile; 20446d359f31SIan Dowse if (grp->gr_type == GT_HOST) 20458360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 20466d359f31SIan Dowse else 20476d359f31SIan Dowse ai = NULL; 20488fae3551SRodney W. Grimes done = FALSE; 20496a09faf2SCraig Rodrigues 20506a09faf2SCraig Rodrigues build_iovec(&iov, &iovlen, "fstype", NULL, 0); 20516a09faf2SCraig Rodrigues build_iovec(&iov, &iovlen, "fspath", NULL, 0); 20526a09faf2SCraig Rodrigues build_iovec(&iov, &iovlen, "from", NULL, 0); 20536a09faf2SCraig Rodrigues build_iovec(&iov, &iovlen, "update", NULL, 0); 20546a09faf2SCraig Rodrigues build_iovec(&iov, &iovlen, "export", &eap, sizeof(eap)); 20556a09faf2SCraig Rodrigues build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); 20566a09faf2SCraig Rodrigues 20578fae3551SRodney W. Grimes while (!done) { 20588fae3551SRodney W. Grimes switch (grp->gr_type) { 20598fae3551SRodney W. Grimes case GT_HOST: 20606d359f31SIan Dowse if (ai->ai_addr->sa_family == AF_INET6 && have_v6 == 0) 20618360efbdSAlfred Perlstein goto skip; 20626a09faf2SCraig Rodrigues eap.ex_addr = ai->ai_addr; 20636a09faf2SCraig Rodrigues eap.ex_addrlen = ai->ai_addrlen; 20646a09faf2SCraig Rodrigues eap.ex_masklen = 0; 20658fae3551SRodney W. Grimes break; 20668fae3551SRodney W. Grimes case GT_NET: 206760caaee2SIan Dowse if (grp->gr_ptr.gt_net.nt_net.ss_family == AF_INET6 && 20688360efbdSAlfred Perlstein have_v6 == 0) 20698360efbdSAlfred Perlstein goto skip; 20706a09faf2SCraig Rodrigues eap.ex_addr = 207160caaee2SIan Dowse (struct sockaddr *)&grp->gr_ptr.gt_net.nt_net; 20726a09faf2SCraig Rodrigues eap.ex_addrlen = 20736a09faf2SCraig Rodrigues ((struct sockaddr *)&grp->gr_ptr.gt_net.nt_net)->sa_len; 20746a09faf2SCraig Rodrigues eap.ex_mask = 207560caaee2SIan Dowse (struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask; 20766a09faf2SCraig Rodrigues eap.ex_masklen = ((struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask)->sa_len; 20778fae3551SRodney W. Grimes break; 20786d359f31SIan Dowse case GT_DEFAULT: 20796a09faf2SCraig Rodrigues eap.ex_addr = NULL; 20806a09faf2SCraig Rodrigues eap.ex_addrlen = 0; 20816a09faf2SCraig Rodrigues eap.ex_mask = NULL; 20826a09faf2SCraig Rodrigues eap.ex_masklen = 0; 20836d359f31SIan Dowse break; 20848b5a6d67SBill Paul case GT_IGNORE: 20856a09faf2SCraig Rodrigues ret = 0; 20866a09faf2SCraig Rodrigues goto error_exit; 20878b5a6d67SBill Paul break; 20888fae3551SRodney W. Grimes default: 208974853402SPhilippe Charnier syslog(LOG_ERR, "bad grouptype"); 20908fae3551SRodney W. Grimes if (cp) 20918fae3551SRodney W. Grimes *cp = savedc; 20926a09faf2SCraig Rodrigues ret = 1; 20936a09faf2SCraig Rodrigues goto error_exit; 20948fae3551SRodney W. Grimes }; 20958fae3551SRodney W. Grimes 20968fae3551SRodney W. Grimes /* 20978fae3551SRodney W. Grimes * XXX: 20988fae3551SRodney W. Grimes * Maybe I should just use the fsb->f_mntonname path instead 20998fae3551SRodney W. Grimes * of looping back up the dirp to the mount point?? 21008fae3551SRodney W. Grimes * Also, needs to know how to export all types of local 210187564113SPeter Wemm * exportable filesystems and not just "ufs". 21028fae3551SRodney W. Grimes */ 21036a09faf2SCraig Rodrigues iov[1].iov_base = fsb->f_fstypename; /* "fstype" */ 21046a09faf2SCraig Rodrigues iov[1].iov_len = strlen(fsb->f_fstypename) + 1; 21056a09faf2SCraig Rodrigues iov[3].iov_base = fsb->f_mntonname; /* "fspath" */ 21066a09faf2SCraig Rodrigues iov[3].iov_len = strlen(fsb->f_mntonname) + 1; 21076a09faf2SCraig Rodrigues iov[5].iov_base = fsb->f_mntfromname; /* "from" */ 21086a09faf2SCraig Rodrigues iov[5].iov_len = strlen(fsb->f_mntfromname) + 1; 21096a09faf2SCraig Rodrigues 2110300a6ee8SRink Springer /* 2111300a6ee8SRink Springer * Remount the filesystem, but chop off the MNT_ROOTFS flag 2112300a6ee8SRink Springer * as it is used internally (and will result in an error if 2113300a6ee8SRink Springer * specified) 2114300a6ee8SRink Springer */ 2115300a6ee8SRink Springer while (nmount(iov, iovlen, fsb->f_flags & ~MNT_ROOTFS) < 0) { 21168fae3551SRodney W. Grimes if (cp) 21178fae3551SRodney W. Grimes *cp-- = savedc; 21188fae3551SRodney W. Grimes else 21198fae3551SRodney W. Grimes cp = dirp + dirplen - 1; 21206a09faf2SCraig Rodrigues if (opt_flags & OP_QUIET) { 21216a09faf2SCraig Rodrigues ret = 1; 21226a09faf2SCraig Rodrigues goto error_exit; 21236a09faf2SCraig Rodrigues } 21248fae3551SRodney W. Grimes if (errno == EPERM) { 212501709abfSIan Dowse if (debug) 212601709abfSIan Dowse warnx("can't change attributes for %s", 212701709abfSIan Dowse dirp); 21288fae3551SRodney W. Grimes syslog(LOG_ERR, 212974853402SPhilippe Charnier "can't change attributes for %s", dirp); 21306a09faf2SCraig Rodrigues ret = 1; 21316a09faf2SCraig Rodrigues goto error_exit; 21328fae3551SRodney W. Grimes } 21338fae3551SRodney W. Grimes if (opt_flags & OP_ALLDIRS) { 2134288fa14aSJoerg Wunsch if (errno == EINVAL) 2135288fa14aSJoerg Wunsch syslog(LOG_ERR, 2136288fa14aSJoerg Wunsch "-alldirs requested but %s is not a filesystem mountpoint", 2137288fa14aSJoerg Wunsch dirp); 2138288fa14aSJoerg Wunsch else 2139288fa14aSJoerg Wunsch syslog(LOG_ERR, 2140288fa14aSJoerg Wunsch "could not remount %s: %m", 21413980ac4fSGarrett Wollman dirp); 21426a09faf2SCraig Rodrigues ret = 1; 21436a09faf2SCraig Rodrigues goto error_exit; 21448fae3551SRodney W. Grimes } 21458fae3551SRodney W. Grimes /* back up over the last component */ 21468fae3551SRodney W. Grimes while (*cp == '/' && cp > dirp) 21478fae3551SRodney W. Grimes cp--; 21488fae3551SRodney W. Grimes while (*(cp - 1) != '/' && cp > dirp) 21498fae3551SRodney W. Grimes cp--; 21508fae3551SRodney W. Grimes if (cp == dirp) { 21518fae3551SRodney W. Grimes if (debug) 215274853402SPhilippe Charnier warnx("mnt unsucc"); 215337518a88SCraig Rodrigues syslog(LOG_ERR, "can't export %s %s", dirp, 215437518a88SCraig Rodrigues errmsg); 21556a09faf2SCraig Rodrigues ret = 1; 21566a09faf2SCraig Rodrigues goto error_exit; 21578fae3551SRodney W. Grimes } 21588fae3551SRodney W. Grimes savedc = *cp; 21598fae3551SRodney W. Grimes *cp = '\0'; 2160f93caef2SIan Dowse /* Check that we're still on the same filesystem. */ 2161f93caef2SIan Dowse if (statfs(dirp, &fsb1) != 0 || bcmp(&fsb1.f_fsid, 2162f93caef2SIan Dowse &fsb->f_fsid, sizeof(fsb1.f_fsid)) != 0) { 2163f93caef2SIan Dowse *cp = savedc; 216437518a88SCraig Rodrigues syslog(LOG_ERR, "can't export %s %s", dirp, 216537518a88SCraig Rodrigues errmsg); 21666a09faf2SCraig Rodrigues ret = 1; 21676a09faf2SCraig Rodrigues goto error_exit; 2168f93caef2SIan Dowse } 21698fae3551SRodney W. Grimes } 21708360efbdSAlfred Perlstein skip: 21716d359f31SIan Dowse if (ai != NULL) 21728360efbdSAlfred Perlstein ai = ai->ai_next; 21738360efbdSAlfred Perlstein if (ai == NULL) 21748fae3551SRodney W. Grimes done = TRUE; 21758fae3551SRodney W. Grimes } 21768fae3551SRodney W. Grimes if (cp) 21778fae3551SRodney W. Grimes *cp = savedc; 21786a09faf2SCraig Rodrigues error_exit: 21796a09faf2SCraig Rodrigues /* free strings allocated by strdup() in getmntopts.c */ 21806a09faf2SCraig Rodrigues if (iov != NULL) { 21816a09faf2SCraig Rodrigues free(iov[0].iov_base); /* fstype */ 21826a09faf2SCraig Rodrigues free(iov[2].iov_base); /* fspath */ 21836a09faf2SCraig Rodrigues free(iov[4].iov_base); /* from */ 21846a09faf2SCraig Rodrigues free(iov[6].iov_base); /* update */ 21856a09faf2SCraig Rodrigues free(iov[8].iov_base); /* export */ 21866a09faf2SCraig Rodrigues free(iov[10].iov_base); /* errmsg */ 21876a09faf2SCraig Rodrigues 21886a09faf2SCraig Rodrigues /* free iov, allocated by realloc() */ 21896a09faf2SCraig Rodrigues free(iov); 21906a09faf2SCraig Rodrigues } 21916a09faf2SCraig Rodrigues return (ret); 21928fae3551SRodney W. Grimes } 21938fae3551SRodney W. Grimes 21948fae3551SRodney W. Grimes /* 21958fae3551SRodney W. Grimes * Translate a net address. 219660caaee2SIan Dowse * 219760caaee2SIan Dowse * If `maskflg' is nonzero, then `cp' is a netmask, not a network address. 21988fae3551SRodney W. Grimes */ 21998fae3551SRodney W. Grimes int 22008fae3551SRodney W. Grimes get_net(cp, net, maskflg) 22018fae3551SRodney W. Grimes char *cp; 22028fae3551SRodney W. Grimes struct netmsk *net; 22038fae3551SRodney W. Grimes int maskflg; 22048fae3551SRodney W. Grimes { 2205931c04f1SIan Dowse struct netent *np = NULL; 22068360efbdSAlfred Perlstein char *name, *p, *prefp; 220760caaee2SIan Dowse struct sockaddr_in sin; 2208931c04f1SIan Dowse struct sockaddr *sa = NULL; 22098360efbdSAlfred Perlstein struct addrinfo hints, *ai = NULL; 22108360efbdSAlfred Perlstein char netname[NI_MAXHOST]; 22118360efbdSAlfred Perlstein long preflen; 22128fae3551SRodney W. Grimes 221301709abfSIan Dowse p = prefp = NULL; 22148360efbdSAlfred Perlstein if ((opt_flags & OP_MASKLEN) && !maskflg) { 22158360efbdSAlfred Perlstein p = strchr(cp, '/'); 22168360efbdSAlfred Perlstein *p = '\0'; 22178360efbdSAlfred Perlstein prefp = p + 1; 22188360efbdSAlfred Perlstein } 22198360efbdSAlfred Perlstein 2220931c04f1SIan Dowse /* 2221931c04f1SIan Dowse * Check for a numeric address first. We wish to avoid 2222931c04f1SIan Dowse * possible DNS lookups in getnetbyname(). 2223931c04f1SIan Dowse */ 2224931c04f1SIan Dowse if (isxdigit(*cp) || *cp == ':') { 22258360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 222660caaee2SIan Dowse /* Ensure the mask and the network have the same family. */ 222760caaee2SIan Dowse if (maskflg && (opt_flags & OP_NET)) 222860caaee2SIan Dowse hints.ai_family = net->nt_net.ss_family; 222960caaee2SIan Dowse else if (!maskflg && (opt_flags & OP_HAVEMASK)) 223060caaee2SIan Dowse hints.ai_family = net->nt_mask.ss_family; 223160caaee2SIan Dowse else 22328360efbdSAlfred Perlstein hints.ai_family = AF_UNSPEC; 22338360efbdSAlfred Perlstein hints.ai_flags = AI_NUMERICHOST; 2234931c04f1SIan Dowse if (getaddrinfo(cp, NULL, &hints, &ai) == 0) 2235931c04f1SIan Dowse sa = ai->ai_addr; 2236931c04f1SIan Dowse if (sa != NULL && ai->ai_family == AF_INET) { 22378fae3551SRodney W. Grimes /* 223860caaee2SIan Dowse * The address in `cp' is really a network address, so 223960caaee2SIan Dowse * use inet_network() to re-interpret this correctly. 224060caaee2SIan Dowse * e.g. "127.1" means 127.1.0.0, not 127.0.0.1. 22418fae3551SRodney W. Grimes */ 224260caaee2SIan Dowse bzero(&sin, sizeof sin); 22438360efbdSAlfred Perlstein sin.sin_family = AF_INET; 22448360efbdSAlfred Perlstein sin.sin_len = sizeof sin; 22458360efbdSAlfred Perlstein sin.sin_addr = inet_makeaddr(inet_network(cp), 0); 22468360efbdSAlfred Perlstein if (debug) 224760caaee2SIan Dowse fprintf(stderr, "get_net: v4 addr %s\n", 224860caaee2SIan Dowse inet_ntoa(sin.sin_addr)); 22498360efbdSAlfred Perlstein sa = (struct sockaddr *)&sin; 2250931c04f1SIan Dowse } 2251931c04f1SIan Dowse } 2252931c04f1SIan Dowse if (sa == NULL && (np = getnetbyname(cp)) != NULL) { 2253931c04f1SIan Dowse bzero(&sin, sizeof sin); 2254931c04f1SIan Dowse sin.sin_family = AF_INET; 2255931c04f1SIan Dowse sin.sin_len = sizeof sin; 2256931c04f1SIan Dowse sin.sin_addr = inet_makeaddr(np->n_net, 0); 2257931c04f1SIan Dowse sa = (struct sockaddr *)&sin; 2258931c04f1SIan Dowse } 2259931c04f1SIan Dowse if (sa == NULL) 22608360efbdSAlfred Perlstein goto fail; 22618360efbdSAlfred Perlstein 226260caaee2SIan Dowse if (maskflg) { 226360caaee2SIan Dowse /* The specified sockaddr is a mask. */ 226460caaee2SIan Dowse if (checkmask(sa) != 0) 22658360efbdSAlfred Perlstein goto fail; 226660caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 226760caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 226860caaee2SIan Dowse } else { 226960caaee2SIan Dowse /* The specified sockaddr is a network address. */ 227060caaee2SIan Dowse bcopy(sa, &net->nt_net, sa->sa_len); 22710f4b7baaSPaul Traina 227260caaee2SIan Dowse /* Get a network name for the export list. */ 227360caaee2SIan Dowse if (np) { 227460caaee2SIan Dowse name = np->n_name; 227560caaee2SIan Dowse } else if (getnameinfo(sa, sa->sa_len, netname, sizeof netname, 22764f101318SHajimu UMEMOTO NULL, 0, NI_NUMERICHOST) == 0) { 227760caaee2SIan Dowse name = netname; 227860caaee2SIan Dowse } else { 227960caaee2SIan Dowse goto fail; 228060caaee2SIan Dowse } 228160caaee2SIan Dowse if ((net->nt_name = strdup(name)) == NULL) 228260caaee2SIan Dowse out_of_mem(); 228360caaee2SIan Dowse 228460caaee2SIan Dowse /* 228560caaee2SIan Dowse * Extract a mask from either a "/<masklen>" suffix, or 228660caaee2SIan Dowse * from the class of an IPv4 address. 228760caaee2SIan Dowse */ 22888360efbdSAlfred Perlstein if (opt_flags & OP_MASKLEN) { 22898360efbdSAlfred Perlstein preflen = strtol(prefp, NULL, 10); 229060caaee2SIan Dowse if (preflen < 0L || preflen == LONG_MAX) 22918360efbdSAlfred Perlstein goto fail; 229260caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 229360caaee2SIan Dowse if (makemask(&net->nt_mask, (int)preflen) != 0) 229460caaee2SIan Dowse goto fail; 229560caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 22968360efbdSAlfred Perlstein *p = '/'; 229760caaee2SIan Dowse } else if (sa->sa_family == AF_INET && 229860caaee2SIan Dowse (opt_flags & OP_MASK) == 0) { 229960caaee2SIan Dowse in_addr_t addr; 23008360efbdSAlfred Perlstein 230160caaee2SIan Dowse addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; 230260caaee2SIan Dowse if (IN_CLASSA(addr)) 230360caaee2SIan Dowse preflen = 8; 230460caaee2SIan Dowse else if (IN_CLASSB(addr)) 230560caaee2SIan Dowse preflen = 16; 230660caaee2SIan Dowse else if (IN_CLASSC(addr)) 230760caaee2SIan Dowse preflen = 24; 230860caaee2SIan Dowse else if (IN_CLASSD(addr)) 230960caaee2SIan Dowse preflen = 28; 23108360efbdSAlfred Perlstein else 231160caaee2SIan Dowse preflen = 32; /* XXX */ 231260caaee2SIan Dowse 231360caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 231460caaee2SIan Dowse makemask(&net->nt_mask, (int)preflen); 231560caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 231660caaee2SIan Dowse } 23178360efbdSAlfred Perlstein } 23188360efbdSAlfred Perlstein 23198360efbdSAlfred Perlstein if (ai) 23208360efbdSAlfred Perlstein freeaddrinfo(ai); 23218360efbdSAlfred Perlstein return 0; 23228360efbdSAlfred Perlstein 23238360efbdSAlfred Perlstein fail: 23248360efbdSAlfred Perlstein if (ai) 23258360efbdSAlfred Perlstein freeaddrinfo(ai); 23268360efbdSAlfred Perlstein return 1; 23278fae3551SRodney W. Grimes } 23288fae3551SRodney W. Grimes 23298fae3551SRodney W. Grimes /* 23308fae3551SRodney W. Grimes * Parse out the next white space separated field 23318fae3551SRodney W. Grimes */ 23328fae3551SRodney W. Grimes void 23338fae3551SRodney W. Grimes nextfield(cp, endcp) 23348fae3551SRodney W. Grimes char **cp; 23358fae3551SRodney W. Grimes char **endcp; 23368fae3551SRodney W. Grimes { 23378fae3551SRodney W. Grimes char *p; 23388fae3551SRodney W. Grimes 23398fae3551SRodney W. Grimes p = *cp; 23408fae3551SRodney W. Grimes while (*p == ' ' || *p == '\t') 23418fae3551SRodney W. Grimes p++; 23428fae3551SRodney W. Grimes if (*p == '\n' || *p == '\0') 23438fae3551SRodney W. Grimes *cp = *endcp = p; 23448fae3551SRodney W. Grimes else { 23458fae3551SRodney W. Grimes *cp = p++; 23468fae3551SRodney W. Grimes while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 23478fae3551SRodney W. Grimes p++; 23488fae3551SRodney W. Grimes *endcp = p; 23498fae3551SRodney W. Grimes } 23508fae3551SRodney W. Grimes } 23518fae3551SRodney W. Grimes 23528fae3551SRodney W. Grimes /* 23538fae3551SRodney W. Grimes * Get an exports file line. Skip over blank lines and handle line 23548fae3551SRodney W. Grimes * continuations. 23558fae3551SRodney W. Grimes */ 23568fae3551SRodney W. Grimes int 23578fae3551SRodney W. Grimes get_line() 23588fae3551SRodney W. Grimes { 23598fae3551SRodney W. Grimes char *p, *cp; 236091ca1a91SIan Dowse size_t len; 23618fae3551SRodney W. Grimes int totlen, cont_line; 23628fae3551SRodney W. Grimes 23638fae3551SRodney W. Grimes /* 23648fae3551SRodney W. Grimes * Loop around ignoring blank lines and getting all continuation lines. 23658fae3551SRodney W. Grimes */ 23668fae3551SRodney W. Grimes p = line; 23678fae3551SRodney W. Grimes totlen = 0; 23688fae3551SRodney W. Grimes do { 236991ca1a91SIan Dowse if ((p = fgetln(exp_file, &len)) == NULL) 23708fae3551SRodney W. Grimes return (0); 23718fae3551SRodney W. Grimes cp = p + len - 1; 23728fae3551SRodney W. Grimes cont_line = 0; 23738fae3551SRodney W. Grimes while (cp >= p && 23748fae3551SRodney W. Grimes (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '\\')) { 23758fae3551SRodney W. Grimes if (*cp == '\\') 23768fae3551SRodney W. Grimes cont_line = 1; 23778fae3551SRodney W. Grimes cp--; 23788fae3551SRodney W. Grimes len--; 23798fae3551SRodney W. Grimes } 2380376f8390SDima Dorfman if (cont_line) { 2381376f8390SDima Dorfman *++cp = ' '; 2382376f8390SDima Dorfman len++; 2383376f8390SDima Dorfman } 238491ca1a91SIan Dowse if (linesize < len + totlen + 1) { 238591ca1a91SIan Dowse linesize = len + totlen + 1; 238691ca1a91SIan Dowse line = realloc(line, linesize); 238791ca1a91SIan Dowse if (line == NULL) 238891ca1a91SIan Dowse out_of_mem(); 238991ca1a91SIan Dowse } 239091ca1a91SIan Dowse memcpy(line + totlen, p, len); 23918fae3551SRodney W. Grimes totlen += len; 239291ca1a91SIan Dowse line[totlen] = '\0'; 23938fae3551SRodney W. Grimes } while (totlen == 0 || cont_line); 23948fae3551SRodney W. Grimes return (1); 23958fae3551SRodney W. Grimes } 23968fae3551SRodney W. Grimes 23978fae3551SRodney W. Grimes /* 23988fae3551SRodney W. Grimes * Parse a description of a credential. 23998fae3551SRodney W. Grimes */ 24008fae3551SRodney W. Grimes void 24018fae3551SRodney W. Grimes parsecred(namelist, cr) 24028fae3551SRodney W. Grimes char *namelist; 2403c0511d3bSBrian Feldman struct xucred *cr; 24048fae3551SRodney W. Grimes { 24058fae3551SRodney W. Grimes char *name; 24068fae3551SRodney W. Grimes int cnt; 24078fae3551SRodney W. Grimes char *names; 24088fae3551SRodney W. Grimes struct passwd *pw; 24098fae3551SRodney W. Grimes struct group *gr; 2410950cc395SStefan Farfeleder gid_t groups[NGROUPS + 1]; 2411950cc395SStefan Farfeleder int ngroups; 24128fae3551SRodney W. Grimes 241376183f34SDima Dorfman cr->cr_version = XUCRED_VERSION; 24148fae3551SRodney W. Grimes /* 241574853402SPhilippe Charnier * Set up the unprivileged user. 24168fae3551SRodney W. Grimes */ 24178fae3551SRodney W. Grimes cr->cr_uid = -2; 24188fae3551SRodney W. Grimes cr->cr_groups[0] = -2; 24198fae3551SRodney W. Grimes cr->cr_ngroups = 1; 24208fae3551SRodney W. Grimes /* 24218fae3551SRodney W. Grimes * Get the user's password table entry. 24228fae3551SRodney W. Grimes */ 24238fae3551SRodney W. Grimes names = strsep(&namelist, " \t\n"); 24248fae3551SRodney W. Grimes name = strsep(&names, ":"); 24258fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') 24268fae3551SRodney W. Grimes pw = getpwuid(atoi(name)); 24278fae3551SRodney W. Grimes else 24288fae3551SRodney W. Grimes pw = getpwnam(name); 24298fae3551SRodney W. Grimes /* 24308fae3551SRodney W. Grimes * Credentials specified as those of a user. 24318fae3551SRodney W. Grimes */ 24328fae3551SRodney W. Grimes if (names == NULL) { 24338fae3551SRodney W. Grimes if (pw == NULL) { 243474853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 24358fae3551SRodney W. Grimes return; 24368fae3551SRodney W. Grimes } 24378fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 24388fae3551SRodney W. Grimes ngroups = NGROUPS + 1; 24398fae3551SRodney W. Grimes if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) 244074853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 24418fae3551SRodney W. Grimes /* 2442950cc395SStefan Farfeleder * Compress out duplicate. 24438fae3551SRodney W. Grimes */ 24448fae3551SRodney W. Grimes cr->cr_ngroups = ngroups - 1; 24458fae3551SRodney W. Grimes cr->cr_groups[0] = groups[0]; 24468fae3551SRodney W. Grimes for (cnt = 2; cnt < ngroups; cnt++) 24478fae3551SRodney W. Grimes cr->cr_groups[cnt - 1] = groups[cnt]; 24488fae3551SRodney W. Grimes return; 24498fae3551SRodney W. Grimes } 24508fae3551SRodney W. Grimes /* 24518fae3551SRodney W. Grimes * Explicit credential specified as a colon separated list: 24528fae3551SRodney W. Grimes * uid:gid:gid:... 24538fae3551SRodney W. Grimes */ 24548fae3551SRodney W. Grimes if (pw != NULL) 24558fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 24568fae3551SRodney W. Grimes else if (isdigit(*name) || *name == '-') 24578fae3551SRodney W. Grimes cr->cr_uid = atoi(name); 24588fae3551SRodney W. Grimes else { 245974853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 24608fae3551SRodney W. Grimes return; 24618fae3551SRodney W. Grimes } 24628fae3551SRodney W. Grimes cr->cr_ngroups = 0; 24638fae3551SRodney W. Grimes while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { 24648fae3551SRodney W. Grimes name = strsep(&names, ":"); 24658fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') { 24668fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = atoi(name); 24678fae3551SRodney W. Grimes } else { 24688fae3551SRodney W. Grimes if ((gr = getgrnam(name)) == NULL) { 246974853402SPhilippe Charnier syslog(LOG_ERR, "unknown group: %s", name); 24708fae3551SRodney W. Grimes continue; 24718fae3551SRodney W. Grimes } 24728fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; 24738fae3551SRodney W. Grimes } 24748fae3551SRodney W. Grimes } 24758fae3551SRodney W. Grimes if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) 247674853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 24778fae3551SRodney W. Grimes } 24788fae3551SRodney W. Grimes 24798fae3551SRodney W. Grimes #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 24808fae3551SRodney W. Grimes /* 24818fae3551SRodney W. Grimes * Routines that maintain the remote mounttab 24828fae3551SRodney W. Grimes */ 24838fae3551SRodney W. Grimes void 24848fae3551SRodney W. Grimes get_mountlist() 24858fae3551SRodney W. Grimes { 24868fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 248787564113SPeter Wemm char *host, *dirp, *cp; 24888fae3551SRodney W. Grimes char str[STRSIZ]; 24898fae3551SRodney W. Grimes FILE *mlfile; 24908fae3551SRodney W. Grimes 24918fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) { 249239539916SBill Fumerola if (errno == ENOENT) 249339539916SBill Fumerola return; 249439539916SBill Fumerola else { 249574853402SPhilippe Charnier syslog(LOG_ERR, "can't open %s", _PATH_RMOUNTLIST); 24968fae3551SRodney W. Grimes return; 24978fae3551SRodney W. Grimes } 249839539916SBill Fumerola } 24998fae3551SRodney W. Grimes mlpp = &mlhead; 25008fae3551SRodney W. Grimes while (fgets(str, STRSIZ, mlfile) != NULL) { 250187564113SPeter Wemm cp = str; 250287564113SPeter Wemm host = strsep(&cp, " \t\n"); 250387564113SPeter Wemm dirp = strsep(&cp, " \t\n"); 250487564113SPeter Wemm if (host == NULL || dirp == NULL) 25058fae3551SRodney W. Grimes continue; 25068fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 250774853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 250874853402SPhilippe Charnier out_of_mem(); 250987564113SPeter Wemm strncpy(mlp->ml_host, host, RPCMNT_NAMELEN); 251087564113SPeter Wemm mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 251187564113SPeter Wemm strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 251287564113SPeter Wemm mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 25138fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 25148fae3551SRodney W. Grimes *mlpp = mlp; 25158fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 25168fae3551SRodney W. Grimes } 25178fae3551SRodney W. Grimes fclose(mlfile); 25188fae3551SRodney W. Grimes } 25198fae3551SRodney W. Grimes 252001709abfSIan Dowse void 252101709abfSIan Dowse del_mlist(char *hostp, char *dirp) 25228fae3551SRodney W. Grimes { 25238fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 25248fae3551SRodney W. Grimes struct mountlist *mlp2; 25258fae3551SRodney W. Grimes FILE *mlfile; 25268fae3551SRodney W. Grimes int fnd = 0; 25278fae3551SRodney W. Grimes 25288fae3551SRodney W. Grimes mlpp = &mlhead; 25298fae3551SRodney W. Grimes mlp = mlhead; 25308fae3551SRodney W. Grimes while (mlp) { 25318fae3551SRodney W. Grimes if (!strcmp(mlp->ml_host, hostp) && 25328fae3551SRodney W. Grimes (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 25338fae3551SRodney W. Grimes fnd = 1; 25348fae3551SRodney W. Grimes mlp2 = mlp; 25358fae3551SRodney W. Grimes *mlpp = mlp = mlp->ml_next; 25368fae3551SRodney W. Grimes free((caddr_t)mlp2); 25378fae3551SRodney W. Grimes } else { 25388fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 25398fae3551SRodney W. Grimes mlp = mlp->ml_next; 25408fae3551SRodney W. Grimes } 25418fae3551SRodney W. Grimes } 25428fae3551SRodney W. Grimes if (fnd) { 25438fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 254474853402SPhilippe Charnier syslog(LOG_ERR,"can't update %s", _PATH_RMOUNTLIST); 25458fae3551SRodney W. Grimes return; 25468fae3551SRodney W. Grimes } 25478fae3551SRodney W. Grimes mlp = mlhead; 25488fae3551SRodney W. Grimes while (mlp) { 25498fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 25508fae3551SRodney W. Grimes mlp = mlp->ml_next; 25518fae3551SRodney W. Grimes } 25528fae3551SRodney W. Grimes fclose(mlfile); 25538fae3551SRodney W. Grimes } 25548fae3551SRodney W. Grimes } 25558fae3551SRodney W. Grimes 25568fae3551SRodney W. Grimes void 25578fae3551SRodney W. Grimes add_mlist(hostp, dirp) 25588fae3551SRodney W. Grimes char *hostp, *dirp; 25598fae3551SRodney W. Grimes { 25608fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 25618fae3551SRodney W. Grimes FILE *mlfile; 25628fae3551SRodney W. Grimes 25638fae3551SRodney W. Grimes mlpp = &mlhead; 25648fae3551SRodney W. Grimes mlp = mlhead; 25658fae3551SRodney W. Grimes while (mlp) { 25668fae3551SRodney W. Grimes if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 25678fae3551SRodney W. Grimes return; 25688fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 25698fae3551SRodney W. Grimes mlp = mlp->ml_next; 25708fae3551SRodney W. Grimes } 25718fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 257274853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 257374853402SPhilippe Charnier out_of_mem(); 25748fae3551SRodney W. Grimes strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 25758fae3551SRodney W. Grimes mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 25768fae3551SRodney W. Grimes strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 25778fae3551SRodney W. Grimes mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 25788fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 25798fae3551SRodney W. Grimes *mlpp = mlp; 25808fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 258174853402SPhilippe Charnier syslog(LOG_ERR, "can't update %s", _PATH_RMOUNTLIST); 25828fae3551SRodney W. Grimes return; 25838fae3551SRodney W. Grimes } 25848fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 25858fae3551SRodney W. Grimes fclose(mlfile); 25868fae3551SRodney W. Grimes } 25878fae3551SRodney W. Grimes 25888fae3551SRodney W. Grimes /* 25898fae3551SRodney W. Grimes * Free up a group list. 25908fae3551SRodney W. Grimes */ 25918fae3551SRodney W. Grimes void 25928fae3551SRodney W. Grimes free_grp(grp) 25938fae3551SRodney W. Grimes struct grouplist *grp; 25948fae3551SRodney W. Grimes { 25958fae3551SRodney W. Grimes if (grp->gr_type == GT_HOST) { 25968360efbdSAlfred Perlstein if (grp->gr_ptr.gt_addrinfo != NULL) 25978360efbdSAlfred Perlstein freeaddrinfo(grp->gr_ptr.gt_addrinfo); 25988fae3551SRodney W. Grimes } else if (grp->gr_type == GT_NET) { 25998fae3551SRodney W. Grimes if (grp->gr_ptr.gt_net.nt_name) 26008fae3551SRodney W. Grimes free(grp->gr_ptr.gt_net.nt_name); 26018fae3551SRodney W. Grimes } 26028fae3551SRodney W. Grimes free((caddr_t)grp); 26038fae3551SRodney W. Grimes } 26048fae3551SRodney W. Grimes 26058fae3551SRodney W. Grimes #ifdef DEBUG 26068fae3551SRodney W. Grimes void 26078fae3551SRodney W. Grimes SYSLOG(int pri, const char *fmt, ...) 26088fae3551SRodney W. Grimes { 26098fae3551SRodney W. Grimes va_list ap; 26108fae3551SRodney W. Grimes 26118fae3551SRodney W. Grimes va_start(ap, fmt); 26128fae3551SRodney W. Grimes vfprintf(stderr, fmt, ap); 26138fae3551SRodney W. Grimes va_end(ap); 26148fae3551SRodney W. Grimes } 26158fae3551SRodney W. Grimes #endif /* DEBUG */ 26168fae3551SRodney W. Grimes 26178fae3551SRodney W. Grimes /* 26188fae3551SRodney W. Grimes * Check options for consistency. 26198fae3551SRodney W. Grimes */ 26208fae3551SRodney W. Grimes int 26218fae3551SRodney W. Grimes check_options(dp) 26228fae3551SRodney W. Grimes struct dirlist *dp; 26238fae3551SRodney W. Grimes { 26248fae3551SRodney W. Grimes 26258fae3551SRodney W. Grimes if (dp == (struct dirlist *)NULL) 26268fae3551SRodney W. Grimes return (1); 262791196234SPeter Wemm if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL)) { 262891196234SPeter Wemm syslog(LOG_ERR, "-mapall and -maproot mutually exclusive"); 26298fae3551SRodney W. Grimes return (1); 26308fae3551SRodney W. Grimes } 26318fae3551SRodney W. Grimes if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { 263260caaee2SIan Dowse syslog(LOG_ERR, "-mask requires -network"); 263360caaee2SIan Dowse return (1); 263460caaee2SIan Dowse } 263560caaee2SIan Dowse if ((opt_flags & OP_NET) && (opt_flags & OP_HAVEMASK) == 0) { 263660caaee2SIan Dowse syslog(LOG_ERR, "-network requires mask specification"); 263760caaee2SIan Dowse return (1); 263860caaee2SIan Dowse } 263960caaee2SIan Dowse if ((opt_flags & OP_MASK) && (opt_flags & OP_MASKLEN)) { 264060caaee2SIan Dowse syslog(LOG_ERR, "-mask and /masklen are mutually exclusive"); 26418fae3551SRodney W. Grimes return (1); 26428fae3551SRodney W. Grimes } 26438fae3551SRodney W. Grimes if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { 26446436fcb9SAlexander Langer syslog(LOG_ERR, "-alldirs has multiple directories"); 26458fae3551SRodney W. Grimes return (1); 26468fae3551SRodney W. Grimes } 26478fae3551SRodney W. Grimes return (0); 26488fae3551SRodney W. Grimes } 26498fae3551SRodney W. Grimes 26508fae3551SRodney W. Grimes /* 26518fae3551SRodney W. Grimes * Check an absolute directory path for any symbolic links. Return true 26528fae3551SRodney W. Grimes */ 26538fae3551SRodney W. Grimes int 26548fae3551SRodney W. Grimes check_dirpath(dirp) 26558fae3551SRodney W. Grimes char *dirp; 26568fae3551SRodney W. Grimes { 26578fae3551SRodney W. Grimes char *cp; 26588fae3551SRodney W. Grimes int ret = 1; 26598fae3551SRodney W. Grimes struct stat sb; 26608fae3551SRodney W. Grimes 26618fae3551SRodney W. Grimes cp = dirp + 1; 26628fae3551SRodney W. Grimes while (*cp && ret) { 26638fae3551SRodney W. Grimes if (*cp == '/') { 26648fae3551SRodney W. Grimes *cp = '\0'; 2665a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 26668fae3551SRodney W. Grimes ret = 0; 26678fae3551SRodney W. Grimes *cp = '/'; 26688fae3551SRodney W. Grimes } 26698fae3551SRodney W. Grimes cp++; 26708fae3551SRodney W. Grimes } 2671a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 26728fae3551SRodney W. Grimes ret = 0; 26738fae3551SRodney W. Grimes return (ret); 26748fae3551SRodney W. Grimes } 2675a62dc406SDoug Rabson 267660caaee2SIan Dowse /* 267760caaee2SIan Dowse * Make a netmask according to the specified prefix length. The ss_family 267860caaee2SIan Dowse * and other non-address fields must be initialised before calling this. 267960caaee2SIan Dowse */ 268060caaee2SIan Dowse int 268160caaee2SIan Dowse makemask(struct sockaddr_storage *ssp, int bitlen) 26828360efbdSAlfred Perlstein { 268360caaee2SIan Dowse u_char *p; 268460caaee2SIan Dowse int bits, i, len; 26858360efbdSAlfred Perlstein 268660caaee2SIan Dowse if ((p = sa_rawaddr((struct sockaddr *)ssp, &len)) == NULL) 268760caaee2SIan Dowse return (-1); 268889fdc4e1SMike Barcroft if (bitlen > len * CHAR_BIT) 268960caaee2SIan Dowse return (-1); 26908360efbdSAlfred Perlstein 269160caaee2SIan Dowse for (i = 0; i < len; i++) { 269289fdc4e1SMike Barcroft bits = (bitlen > CHAR_BIT) ? CHAR_BIT : bitlen; 269360caaee2SIan Dowse *p++ = (1 << bits) - 1; 269460caaee2SIan Dowse bitlen -= bits; 26958360efbdSAlfred Perlstein } 26968360efbdSAlfred Perlstein return 0; 26978360efbdSAlfred Perlstein } 26988360efbdSAlfred Perlstein 269960caaee2SIan Dowse /* 270060caaee2SIan Dowse * Check that the sockaddr is a valid netmask. Returns 0 if the mask 270160caaee2SIan Dowse * is acceptable (i.e. of the form 1...10....0). 270260caaee2SIan Dowse */ 270360caaee2SIan Dowse int 270460caaee2SIan Dowse checkmask(struct sockaddr *sa) 27058360efbdSAlfred Perlstein { 270660caaee2SIan Dowse u_char *mask; 270760caaee2SIan Dowse int i, len; 270860caaee2SIan Dowse 270960caaee2SIan Dowse if ((mask = sa_rawaddr(sa, &len)) == NULL) 271060caaee2SIan Dowse return (-1); 271160caaee2SIan Dowse 271260caaee2SIan Dowse for (i = 0; i < len; i++) 271360caaee2SIan Dowse if (mask[i] != 0xff) 271460caaee2SIan Dowse break; 271560caaee2SIan Dowse if (i < len) { 271660caaee2SIan Dowse if (~mask[i] & (u_char)(~mask[i] + 1)) 271760caaee2SIan Dowse return (-1); 271860caaee2SIan Dowse i++; 271960caaee2SIan Dowse } 272060caaee2SIan Dowse for (; i < len; i++) 272160caaee2SIan Dowse if (mask[i] != 0) 272260caaee2SIan Dowse return (-1); 272360caaee2SIan Dowse return (0); 272460caaee2SIan Dowse } 272560caaee2SIan Dowse 272660caaee2SIan Dowse /* 272760caaee2SIan Dowse * Compare two sockaddrs according to a specified mask. Return zero if 272860caaee2SIan Dowse * `sa1' matches `sa2' when filtered by the netmask in `samask'. 272960caaee2SIan Dowse * If samask is NULL, perform a full comparision. 273060caaee2SIan Dowse */ 273160caaee2SIan Dowse int 273260caaee2SIan Dowse sacmp(struct sockaddr *sa1, struct sockaddr *sa2, struct sockaddr *samask) 273360caaee2SIan Dowse { 273460caaee2SIan Dowse unsigned char *p1, *p2, *mask; 273560caaee2SIan Dowse int len, i; 273660caaee2SIan Dowse 273760caaee2SIan Dowse if (sa1->sa_family != sa2->sa_family || 273860caaee2SIan Dowse (p1 = sa_rawaddr(sa1, &len)) == NULL || 273960caaee2SIan Dowse (p2 = sa_rawaddr(sa2, NULL)) == NULL) 274060caaee2SIan Dowse return (1); 274160caaee2SIan Dowse 274260caaee2SIan Dowse switch (sa1->sa_family) { 274360caaee2SIan Dowse case AF_INET6: 274460caaee2SIan Dowse if (((struct sockaddr_in6 *)sa1)->sin6_scope_id != 274560caaee2SIan Dowse ((struct sockaddr_in6 *)sa2)->sin6_scope_id) 274660caaee2SIan Dowse return (1); 274760caaee2SIan Dowse break; 274860caaee2SIan Dowse } 274960caaee2SIan Dowse 275060caaee2SIan Dowse /* Simple binary comparison if no mask specified. */ 275160caaee2SIan Dowse if (samask == NULL) 275260caaee2SIan Dowse return (memcmp(p1, p2, len)); 275360caaee2SIan Dowse 275460caaee2SIan Dowse /* Set up the mask, and do a mask-based comparison. */ 275560caaee2SIan Dowse if (sa1->sa_family != samask->sa_family || 275660caaee2SIan Dowse (mask = sa_rawaddr(samask, NULL)) == NULL) 275760caaee2SIan Dowse return (1); 275860caaee2SIan Dowse 275960caaee2SIan Dowse for (i = 0; i < len; i++) 276060caaee2SIan Dowse if ((p1[i] & mask[i]) != (p2[i] & mask[i])) 276160caaee2SIan Dowse return (1); 276260caaee2SIan Dowse return (0); 276360caaee2SIan Dowse } 276460caaee2SIan Dowse 276560caaee2SIan Dowse /* 276660caaee2SIan Dowse * Return a pointer to the part of the sockaddr that contains the 276760caaee2SIan Dowse * raw address, and set *nbytes to its length in bytes. Returns 276860caaee2SIan Dowse * NULL if the address family is unknown. 276960caaee2SIan Dowse */ 277060caaee2SIan Dowse void * 277160caaee2SIan Dowse sa_rawaddr(struct sockaddr *sa, int *nbytes) { 277260caaee2SIan Dowse void *p; 277360caaee2SIan Dowse int len; 27748360efbdSAlfred Perlstein 27758360efbdSAlfred Perlstein switch (sa->sa_family) { 27768360efbdSAlfred Perlstein case AF_INET: 277760caaee2SIan Dowse len = sizeof(((struct sockaddr_in *)sa)->sin_addr); 277860caaee2SIan Dowse p = &((struct sockaddr_in *)sa)->sin_addr; 27798360efbdSAlfred Perlstein break; 27808360efbdSAlfred Perlstein case AF_INET6: 278160caaee2SIan Dowse len = sizeof(((struct sockaddr_in6 *)sa)->sin6_addr); 278260caaee2SIan Dowse p = &((struct sockaddr_in6 *)sa)->sin6_addr; 27838360efbdSAlfred Perlstein break; 27848360efbdSAlfred Perlstein default: 278560caaee2SIan Dowse p = NULL; 278660caaee2SIan Dowse len = 0; 27878360efbdSAlfred Perlstein } 27888360efbdSAlfred Perlstein 278960caaee2SIan Dowse if (nbytes != NULL) 279060caaee2SIan Dowse *nbytes = len; 279160caaee2SIan Dowse return (p); 27928360efbdSAlfred Perlstein } 27938360efbdSAlfred Perlstein 279469d65572SIan Dowse void 279569d65572SIan Dowse huphandler(int sig) 279669d65572SIan Dowse { 279769d65572SIan Dowse got_sighup = 1; 279869d65572SIan Dowse } 279969d65572SIan Dowse 28008360efbdSAlfred Perlstein void terminate(sig) 28018360efbdSAlfred Perlstein int sig; 28028360efbdSAlfred Perlstein { 2803a032b226SPawel Jakub Dawidek pidfile_remove(pfh); 28047b98a1d6SAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); 28057b98a1d6SAlfred Perlstein rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); 28068360efbdSAlfred Perlstein exit (0); 28078360efbdSAlfred Perlstein } 2808