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> 498360efbdSAlfred Perlstein #include <sys/fcntl.h> 5091ca1a91SIan Dowse #include <sys/linker.h> 5191ca1a91SIan Dowse #include <sys/module.h> 52bcc1d071SRick Macklem #include <sys/mount.h> 53bcc1d071SRick Macklem #include <sys/stat.h> 54bcc1d071SRick Macklem #include <sys/sysctl.h> 55bcc1d071SRick Macklem #include <sys/syslog.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> 62a62dc406SDoug Rabson #include <nfs/nfsproto.h> 63bcc1d071SRick Macklem #include <nfs/nfssvc.h> 6491196234SPeter Wemm #include <nfsserver/nfs.h> 658fae3551SRodney W. Grimes 66bcc1d071SRick Macklem #include <fs/nfs/nfsport.h> 67bcc1d071SRick Macklem 688fae3551SRodney W. Grimes #include <arpa/inet.h> 698fae3551SRodney W. Grimes 708fae3551SRodney W. Grimes #include <ctype.h> 7174853402SPhilippe Charnier #include <err.h> 728fae3551SRodney W. Grimes #include <errno.h> 738fae3551SRodney W. Grimes #include <grp.h> 74a032b226SPawel Jakub Dawidek #include <libutil.h> 7589fdc4e1SMike Barcroft #include <limits.h> 768fae3551SRodney W. Grimes #include <netdb.h> 778fae3551SRodney W. Grimes #include <pwd.h> 788fae3551SRodney W. Grimes #include <signal.h> 798fae3551SRodney W. Grimes #include <stdio.h> 808fae3551SRodney W. Grimes #include <stdlib.h> 818fae3551SRodney W. Grimes #include <string.h> 828fae3551SRodney W. Grimes #include <unistd.h> 838fae3551SRodney W. Grimes #include "pathnames.h" 846a09faf2SCraig Rodrigues #include "mntopts.h" 858fae3551SRodney W. Grimes 868fae3551SRodney W. Grimes #ifdef DEBUG 878fae3551SRodney W. Grimes #include <stdarg.h> 888fae3551SRodney W. Grimes #endif 898fae3551SRodney W. Grimes 908fae3551SRodney W. Grimes /* 918fae3551SRodney W. Grimes * Structures for keeping the mount list and export list 928fae3551SRodney W. Grimes */ 938fae3551SRodney W. Grimes struct mountlist { 948fae3551SRodney W. Grimes struct mountlist *ml_next; 950775314bSDoug Rabson char ml_host[MNTNAMLEN+1]; 960775314bSDoug Rabson char ml_dirp[MNTPATHLEN+1]; 978fae3551SRodney W. Grimes }; 988fae3551SRodney W. Grimes 998fae3551SRodney W. Grimes struct dirlist { 1008fae3551SRodney W. Grimes struct dirlist *dp_left; 1018fae3551SRodney W. Grimes struct dirlist *dp_right; 1028fae3551SRodney W. Grimes int dp_flag; 1038fae3551SRodney W. Grimes struct hostlist *dp_hosts; /* List of hosts this dir exported to */ 1048fae3551SRodney W. Grimes char dp_dirp[1]; /* Actually malloc'd to size of dir */ 1058fae3551SRodney W. Grimes }; 1068fae3551SRodney W. Grimes /* dp_flag bits */ 1078fae3551SRodney W. Grimes #define DP_DEFSET 0x1 108a62dc406SDoug Rabson #define DP_HOSTSET 0x2 1098fae3551SRodney W. Grimes 1108fae3551SRodney W. Grimes struct exportlist { 1118fae3551SRodney W. Grimes struct exportlist *ex_next; 1128fae3551SRodney W. Grimes struct dirlist *ex_dirl; 1138fae3551SRodney W. Grimes struct dirlist *ex_defdir; 1148fae3551SRodney W. Grimes int ex_flag; 1158fae3551SRodney W. Grimes fsid_t ex_fs; 1168fae3551SRodney W. Grimes char *ex_fsdir; 117cb3923e0SDoug Rabson char *ex_indexfile; 118a9148abdSDoug Rabson int ex_numsecflavors; 119a9148abdSDoug Rabson int ex_secflavors[MAXSECFLAVORS]; 120*c3f86a25SRick Macklem int ex_defnumsecflavors; 121*c3f86a25SRick Macklem int ex_defsecflavors[MAXSECFLAVORS]; 1228fae3551SRodney W. Grimes }; 1238fae3551SRodney W. Grimes /* ex_flag bits */ 1248fae3551SRodney W. Grimes #define EX_LINKED 0x1 1258fae3551SRodney W. Grimes 1268fae3551SRodney W. Grimes struct netmsk { 1278360efbdSAlfred Perlstein struct sockaddr_storage nt_net; 12860caaee2SIan Dowse struct sockaddr_storage nt_mask; 1298fae3551SRodney W. Grimes char *nt_name; 1308fae3551SRodney W. Grimes }; 1318fae3551SRodney W. Grimes 1328fae3551SRodney W. Grimes union grouptypes { 1338360efbdSAlfred Perlstein struct addrinfo *gt_addrinfo; 1348fae3551SRodney W. Grimes struct netmsk gt_net; 1358fae3551SRodney W. Grimes }; 1368fae3551SRodney W. Grimes 1378fae3551SRodney W. Grimes struct grouplist { 1388fae3551SRodney W. Grimes int gr_type; 1398fae3551SRodney W. Grimes union grouptypes gr_ptr; 1408fae3551SRodney W. Grimes struct grouplist *gr_next; 141*c3f86a25SRick Macklem int gr_numsecflavors; 142*c3f86a25SRick Macklem int gr_secflavors[MAXSECFLAVORS]; 1438fae3551SRodney W. Grimes }; 1448fae3551SRodney W. Grimes /* Group types */ 1458fae3551SRodney W. Grimes #define GT_NULL 0x0 1468fae3551SRodney W. Grimes #define GT_HOST 0x1 1478fae3551SRodney W. Grimes #define GT_NET 0x2 1486d359f31SIan Dowse #define GT_DEFAULT 0x3 1498b5a6d67SBill Paul #define GT_IGNORE 0x5 1508fae3551SRodney W. Grimes 1518fae3551SRodney W. Grimes struct hostlist { 152a62dc406SDoug Rabson int ht_flag; /* Uses DP_xx bits */ 1538fae3551SRodney W. Grimes struct grouplist *ht_grp; 1548fae3551SRodney W. Grimes struct hostlist *ht_next; 1558fae3551SRodney W. Grimes }; 1568fae3551SRodney W. Grimes 157a62dc406SDoug Rabson struct fhreturn { 158a62dc406SDoug Rabson int fhr_flag; 159a62dc406SDoug Rabson int fhr_vers; 160a62dc406SDoug Rabson nfsfh_t fhr_fh; 161a9148abdSDoug Rabson int fhr_numsecflavors; 162a9148abdSDoug Rabson int *fhr_secflavors; 163a62dc406SDoug Rabson }; 164a62dc406SDoug Rabson 1658fb6ad5dSRick Macklem #define GETPORT_MAXTRY 20 /* Max tries to get a port # */ 1668fb6ad5dSRick Macklem 1678fae3551SRodney W. Grimes /* Global defs */ 16885429990SWarner Losh char *add_expdir(struct dirlist **, char *, int); 16985429990SWarner Losh void add_dlist(struct dirlist **, struct dirlist *, 170*c3f86a25SRick Macklem struct grouplist *, int, struct exportlist *); 17185429990SWarner Losh void add_mlist(char *, char *); 17285429990SWarner Losh int check_dirpath(char *); 17385429990SWarner Losh int check_options(struct dirlist *); 17460caaee2SIan Dowse int checkmask(struct sockaddr *sa); 175*c3f86a25SRick Macklem int chk_host(struct dirlist *, struct sockaddr *, int *, int *, int *, 176*c3f86a25SRick Macklem int **); 1778fb6ad5dSRick Macklem static int create_service(struct netconfig *nconf); 1788fb6ad5dSRick Macklem static void complete_service(struct netconfig *nconf, char *port_str); 1798fb6ad5dSRick Macklem static void clearout_service(void); 18001709abfSIan Dowse void del_mlist(char *hostp, char *dirp); 18185429990SWarner Losh struct dirlist *dirp_search(struct dirlist *, char *); 18285429990SWarner Losh int do_mount(struct exportlist *, struct grouplist *, int, 18385429990SWarner Losh struct xucred *, char *, int, struct statfs *); 18485429990SWarner Losh int do_opt(char **, char **, struct exportlist *, struct grouplist *, 18585429990SWarner Losh int *, int *, struct xucred *); 18685429990SWarner Losh struct exportlist *ex_search(fsid_t *); 18785429990SWarner Losh struct exportlist *get_exp(void); 18885429990SWarner Losh void free_dir(struct dirlist *); 18985429990SWarner Losh void free_exp(struct exportlist *); 19085429990SWarner Losh void free_grp(struct grouplist *); 19185429990SWarner Losh void free_host(struct hostlist *); 19285429990SWarner Losh void get_exportlist(void); 19385429990SWarner Losh int get_host(char *, struct grouplist *, struct grouplist *); 19485429990SWarner Losh struct hostlist *get_ht(void); 19585429990SWarner Losh int get_line(void); 19685429990SWarner Losh void get_mountlist(void); 19785429990SWarner Losh int get_net(char *, struct netmsk *, int); 19885429990SWarner Losh void getexp_err(struct exportlist *, struct grouplist *); 19985429990SWarner Losh struct grouplist *get_grp(void); 20085429990SWarner Losh void hang_dirp(struct dirlist *, struct grouplist *, 20185429990SWarner Losh struct exportlist *, int); 20269d65572SIan Dowse void huphandler(int sig); 20360caaee2SIan Dowse int makemask(struct sockaddr_storage *ssp, int bitlen); 20485429990SWarner Losh void mntsrv(struct svc_req *, SVCXPRT *); 20585429990SWarner Losh void nextfield(char **, char **); 20685429990SWarner Losh void out_of_mem(void); 20785429990SWarner Losh void parsecred(char *, struct xucred *); 208a7a7d96cSPhilippe Charnier int parsesec(char *, struct exportlist *); 20991acb349SAlfred Perlstein int put_exlist(struct dirlist *, XDR *, struct dirlist *, int *, int); 21060caaee2SIan Dowse void *sa_rawaddr(struct sockaddr *sa, int *nbytes); 21160caaee2SIan Dowse int sacmp(struct sockaddr *sa1, struct sockaddr *sa2, 21260caaee2SIan Dowse struct sockaddr *samask); 21385429990SWarner Losh int scan_tree(struct dirlist *, struct sockaddr *); 21485429990SWarner Losh static void usage(void); 21585429990SWarner Losh int xdr_dir(XDR *, char *); 21685429990SWarner Losh int xdr_explist(XDR *, caddr_t); 21791acb349SAlfred Perlstein int xdr_explist_brief(XDR *, caddr_t); 218a7a7d96cSPhilippe Charnier int xdr_explist_common(XDR *, caddr_t, int); 21985429990SWarner Losh int xdr_fhs(XDR *, caddr_t); 22085429990SWarner Losh int xdr_mlist(XDR *, caddr_t); 22185429990SWarner Losh void terminate(int); 2228fae3551SRodney W. Grimes 2238fae3551SRodney W. Grimes struct exportlist *exphead; 2248fae3551SRodney W. Grimes struct mountlist *mlhead; 2258fae3551SRodney W. Grimes struct grouplist *grphead; 22696968c22SPawel Jakub Dawidek char *exnames_default[2] = { _PATH_EXPORTS, NULL }; 22796968c22SPawel Jakub Dawidek char **exnames; 228d11e3645SMatteo Riondato char **hosts = NULL; 229c0511d3bSBrian Feldman struct xucred def_anon = { 23076183f34SDima Dorfman XUCRED_VERSION, 2318fae3551SRodney W. Grimes (uid_t)-2, 2328fae3551SRodney W. Grimes 1, 233c0511d3bSBrian Feldman { (gid_t)-2 }, 234c0511d3bSBrian Feldman NULL 2358fae3551SRodney W. Grimes }; 2362a66cfc5SDoug Rabson int force_v2 = 0; 237a62dc406SDoug Rabson int resvport_only = 1; 238d11e3645SMatteo Riondato int nhosts = 0; 239a62dc406SDoug Rabson int dir_only = 1; 240c903443aSPeter Wemm int dolog = 0; 24169d65572SIan Dowse int got_sighup = 0; 242d11e3645SMatteo Riondato int xcreated = 0; 243d11e3645SMatteo Riondato 244d11e3645SMatteo Riondato char *svcport_str = NULL; 2458fb6ad5dSRick Macklem static int mallocd_svcport = 0; 2468fb6ad5dSRick Macklem static int *sock_fd; 2478fb6ad5dSRick Macklem static int sock_fdcnt; 2488fb6ad5dSRick Macklem static int sock_fdpos; 2498360efbdSAlfred Perlstein 2508fae3551SRodney W. Grimes int opt_flags; 2518360efbdSAlfred Perlstein static int have_v6 = 1; 2528360efbdSAlfred Perlstein 253bcc1d071SRick Macklem int v4root_phase = 0; 254bcc1d071SRick Macklem char v4root_dirpath[PATH_MAX + 1]; 2552a85df8cSRick Macklem int run_v4server = 1; 256bcc1d071SRick Macklem int has_publicfh = 0; 257bcc1d071SRick Macklem 258a032b226SPawel Jakub Dawidek struct pidfh *pfh = NULL; 25960caaee2SIan Dowse /* Bits for opt_flags above */ 2608fae3551SRodney W. Grimes #define OP_MAPROOT 0x01 2618fae3551SRodney W. Grimes #define OP_MAPALL 0x02 26291196234SPeter Wemm /* 0x4 free */ 2638fae3551SRodney W. Grimes #define OP_MASK 0x08 2648fae3551SRodney W. Grimes #define OP_NET 0x10 2658fae3551SRodney W. Grimes #define OP_ALLDIRS 0x40 26660caaee2SIan Dowse #define OP_HAVEMASK 0x80 /* A mask was specified or inferred. */ 267288fa14aSJoerg Wunsch #define OP_QUIET 0x100 2688360efbdSAlfred Perlstein #define OP_MASKLEN 0x200 269a9148abdSDoug Rabson #define OP_SEC 0x400 2708fae3551SRodney W. Grimes 2718fae3551SRodney W. Grimes #ifdef DEBUG 2728fae3551SRodney W. Grimes int debug = 1; 27385429990SWarner Losh void SYSLOG(int, const char *, ...) __printflike(2, 3); 2748fae3551SRodney W. Grimes #define syslog SYSLOG 2758fae3551SRodney W. Grimes #else 2768fae3551SRodney W. Grimes int debug = 0; 2778fae3551SRodney W. Grimes #endif 2788fae3551SRodney W. Grimes 2798fae3551SRodney W. Grimes /* 2808fae3551SRodney W. Grimes * Mountd server for NFS mount protocol as described in: 2818fae3551SRodney W. Grimes * NFS: Network File System Protocol Specification, RFC1094, Appendix A 2828fae3551SRodney W. Grimes * The optional arguments are the exports file name 2838fae3551SRodney W. Grimes * default: _PATH_EXPORTS 2848fae3551SRodney W. Grimes * and "-n" to allow nonroot mount. 2858fae3551SRodney W. Grimes */ 2868fae3551SRodney W. Grimes int 287a7a7d96cSPhilippe Charnier main(int argc, char **argv) 2888fae3551SRodney W. Grimes { 28969d65572SIan Dowse fd_set readfds; 290d11e3645SMatteo Riondato struct netconfig *nconf; 291d11e3645SMatteo Riondato char *endptr, **hosts_bak; 292d11e3645SMatteo Riondato void *nc_handle; 293a032b226SPawel Jakub Dawidek pid_t otherpid; 294d11e3645SMatteo Riondato in_port_t svcport; 295d11e3645SMatteo Riondato int c, k, s; 296bcb53b16SMartin Blapp int maxrec = RPC_MAXDATASIZE; 2978fb6ad5dSRick Macklem int attempt_cnt, port_len, port_pos, ret; 2988fb6ad5dSRick Macklem char **port_list; 2998360efbdSAlfred Perlstein 30001709abfSIan Dowse /* Check that another mountd isn't already running. */ 3018b28aef2SPawel Jakub Dawidek pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid); 302a032b226SPawel Jakub Dawidek if (pfh == NULL) { 303a032b226SPawel Jakub Dawidek if (errno == EEXIST) 304a032b226SPawel Jakub Dawidek errx(1, "mountd already running, pid: %d.", otherpid); 305a032b226SPawel Jakub Dawidek warn("cannot open or create pidfile"); 306a032b226SPawel Jakub Dawidek } 3078360efbdSAlfred Perlstein 3088360efbdSAlfred Perlstein s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 3098360efbdSAlfred Perlstein if (s < 0) 3108360efbdSAlfred Perlstein have_v6 = 0; 3118360efbdSAlfred Perlstein else 3128360efbdSAlfred Perlstein close(s); 3138fae3551SRodney W. Grimes 3142a85df8cSRick Macklem while ((c = getopt(argc, argv, "2deh:lnop:r")) != -1) 3158fae3551SRodney W. Grimes switch (c) { 3162a66cfc5SDoug Rabson case '2': 3172a66cfc5SDoug Rabson force_v2 = 1; 3182a66cfc5SDoug Rabson break; 3192179ae1eSRick Macklem case 'e': 3202a85df8cSRick Macklem /* now a no-op, since this is the default */ 321bcc1d071SRick Macklem break; 322a62dc406SDoug Rabson case 'n': 323a62dc406SDoug Rabson resvport_only = 0; 324a62dc406SDoug Rabson break; 325a62dc406SDoug Rabson case 'r': 326a62dc406SDoug Rabson dir_only = 0; 327a62dc406SDoug Rabson break; 3286444ef3bSPoul-Henning Kamp case 'd': 3296444ef3bSPoul-Henning Kamp debug = debug ? 0 : 1; 3306444ef3bSPoul-Henning Kamp break; 331f51631d7SGuido van Rooij case 'l': 332c903443aSPeter Wemm dolog = 1; 333f51631d7SGuido van Rooij break; 3342a85df8cSRick Macklem case 'o': 3352a85df8cSRick Macklem run_v4server = 0; 3362a85df8cSRick Macklem break; 337c203da27SBruce M Simpson case 'p': 338c203da27SBruce M Simpson endptr = NULL; 339c203da27SBruce M Simpson svcport = (in_port_t)strtoul(optarg, &endptr, 10); 340c203da27SBruce M Simpson if (endptr == NULL || *endptr != '\0' || 341c203da27SBruce M Simpson svcport == 0 || svcport >= IPPORT_MAX) 342c203da27SBruce M Simpson usage(); 343d11e3645SMatteo Riondato svcport_str = strdup(optarg); 344d11e3645SMatteo Riondato break; 345d11e3645SMatteo Riondato case 'h': 346d11e3645SMatteo Riondato ++nhosts; 347d11e3645SMatteo Riondato hosts_bak = hosts; 348d11e3645SMatteo Riondato hosts_bak = realloc(hosts, nhosts * sizeof(char *)); 349d11e3645SMatteo Riondato if (hosts_bak == NULL) { 350d11e3645SMatteo Riondato if (hosts != NULL) { 351d11e3645SMatteo Riondato for (k = 0; k < nhosts; k++) 352d11e3645SMatteo Riondato free(hosts[k]); 353d11e3645SMatteo Riondato free(hosts); 354d11e3645SMatteo Riondato out_of_mem(); 355d11e3645SMatteo Riondato } 356d11e3645SMatteo Riondato } 357d11e3645SMatteo Riondato hosts = hosts_bak; 358d11e3645SMatteo Riondato hosts[nhosts - 1] = strdup(optarg); 359d11e3645SMatteo Riondato if (hosts[nhosts - 1] == NULL) { 360d11e3645SMatteo Riondato for (k = 0; k < (nhosts - 1); k++) 361d11e3645SMatteo Riondato free(hosts[k]); 362d11e3645SMatteo Riondato free(hosts); 363d11e3645SMatteo Riondato out_of_mem(); 364d11e3645SMatteo Riondato } 365c203da27SBruce M Simpson break; 3668fae3551SRodney W. Grimes default: 36774853402SPhilippe Charnier usage(); 3688fae3551SRodney W. Grimes }; 369bcc1d071SRick Macklem 370bcc1d071SRick Macklem /* 3712a85df8cSRick Macklem * Unless the "-o" option was specified, try and run "nfsd". 3722a85df8cSRick Macklem * If "-o" was specified, try and run "nfsserver". 373bcc1d071SRick Macklem */ 374bcc1d071SRick Macklem if (run_v4server > 0) { 375bcc1d071SRick Macklem if (modfind("nfsd") < 0) { 376bcc1d071SRick Macklem /* Not present in kernel, try loading it */ 377bcc1d071SRick Macklem if (kldload("nfsd") < 0 || modfind("nfsd") < 0) 378bcc1d071SRick Macklem errx(1, "NFS server is not available"); 379bcc1d071SRick Macklem } 380bcc1d071SRick Macklem } else if (modfind("nfsserver") < 0) { 381bcc1d071SRick Macklem /* Not present in kernel, try loading it */ 382bcc1d071SRick Macklem if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0) 383bcc1d071SRick Macklem errx(1, "NFS server is not available"); 384bcc1d071SRick Macklem } 385bcc1d071SRick Macklem 3868fae3551SRodney W. Grimes argc -= optind; 3878fae3551SRodney W. Grimes argv += optind; 3888fae3551SRodney W. Grimes grphead = (struct grouplist *)NULL; 3898fae3551SRodney W. Grimes exphead = (struct exportlist *)NULL; 3908fae3551SRodney W. Grimes mlhead = (struct mountlist *)NULL; 39196968c22SPawel Jakub Dawidek if (argc > 0) 39296968c22SPawel Jakub Dawidek exnames = argv; 39396968c22SPawel Jakub Dawidek else 39496968c22SPawel Jakub Dawidek exnames = exnames_default; 3958fae3551SRodney W. Grimes openlog("mountd", LOG_PID, LOG_DAEMON); 3968fae3551SRodney W. Grimes if (debug) 39774853402SPhilippe Charnier warnx("getting export list"); 3988fae3551SRodney W. Grimes get_exportlist(); 3998fae3551SRodney W. Grimes if (debug) 40074853402SPhilippe Charnier warnx("getting mount list"); 4018fae3551SRodney W. Grimes get_mountlist(); 4028fae3551SRodney W. Grimes if (debug) 40374853402SPhilippe Charnier warnx("here we go"); 4048fae3551SRodney W. Grimes if (debug == 0) { 4058fae3551SRodney W. Grimes daemon(0, 0); 4068fae3551SRodney W. Grimes signal(SIGINT, SIG_IGN); 4078fae3551SRodney W. Grimes signal(SIGQUIT, SIG_IGN); 4088fae3551SRodney W. Grimes } 40969d65572SIan Dowse signal(SIGHUP, huphandler); 4108360efbdSAlfred Perlstein signal(SIGTERM, terminate); 41109fc9dc6SCraig Rodrigues signal(SIGPIPE, SIG_IGN); 412a032b226SPawel Jakub Dawidek 413a032b226SPawel Jakub Dawidek pidfile_write(pfh); 414a032b226SPawel Jakub Dawidek 4150775314bSDoug Rabson rpcb_unset(MOUNTPROG, MOUNTVERS, NULL); 4160775314bSDoug Rabson rpcb_unset(MOUNTPROG, MOUNTVERS3, NULL); 417bcb53b16SMartin Blapp rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); 418bcb53b16SMartin Blapp 419c6e5e158SGuido van Rooij if (!resvport_only) { 4204a0785aaSPeter Wemm if (sysctlbyname("vfs.nfsrv.nfs_privport", NULL, NULL, 4214a0785aaSPeter Wemm &resvport_only, sizeof(resvport_only)) != 0 && 4224a0785aaSPeter Wemm errno != ENOENT) { 423394da4c1SGuido van Rooij syslog(LOG_ERR, "sysctl: %m"); 424394da4c1SGuido van Rooij exit(1); 425394da4c1SGuido van Rooij } 426c6e5e158SGuido van Rooij } 427c203da27SBruce M Simpson 428d11e3645SMatteo Riondato /* 429d11e3645SMatteo Riondato * If no hosts were specified, add a wildcard entry to bind to 430d11e3645SMatteo Riondato * INADDR_ANY. Otherwise make sure 127.0.0.1 and ::1 are added to the 431d11e3645SMatteo Riondato * list. 432d11e3645SMatteo Riondato */ 433d11e3645SMatteo Riondato if (nhosts == 0) { 434d11e3645SMatteo Riondato hosts = malloc(sizeof(char**)); 435d11e3645SMatteo Riondato if (hosts == NULL) 436d11e3645SMatteo Riondato out_of_mem(); 437d11e3645SMatteo Riondato hosts[0] = "*"; 438d11e3645SMatteo Riondato nhosts = 1; 439d11e3645SMatteo Riondato } else { 440d11e3645SMatteo Riondato hosts_bak = hosts; 441d11e3645SMatteo Riondato if (have_v6) { 442d11e3645SMatteo Riondato hosts_bak = realloc(hosts, (nhosts + 2) * 443d11e3645SMatteo Riondato sizeof(char *)); 444d11e3645SMatteo Riondato if (hosts_bak == NULL) { 445d11e3645SMatteo Riondato for (k = 0; k < nhosts; k++) 446d11e3645SMatteo Riondato free(hosts[k]); 447d11e3645SMatteo Riondato free(hosts); 448d11e3645SMatteo Riondato out_of_mem(); 449c203da27SBruce M Simpson } else 450d11e3645SMatteo Riondato hosts = hosts_bak; 451d11e3645SMatteo Riondato nhosts += 2; 452d11e3645SMatteo Riondato hosts[nhosts - 2] = "::1"; 453d11e3645SMatteo Riondato } else { 454d11e3645SMatteo Riondato hosts_bak = realloc(hosts, (nhosts + 1) * sizeof(char *)); 455d11e3645SMatteo Riondato if (hosts_bak == NULL) { 456d11e3645SMatteo Riondato for (k = 0; k < nhosts; k++) 457d11e3645SMatteo Riondato free(hosts[k]); 458d11e3645SMatteo Riondato free(hosts); 459d11e3645SMatteo Riondato out_of_mem(); 460d11e3645SMatteo Riondato } else { 461d11e3645SMatteo Riondato nhosts += 1; 462d11e3645SMatteo Riondato hosts = hosts_bak; 4638fae3551SRodney W. Grimes } 464d11e3645SMatteo Riondato } 4658360efbdSAlfred Perlstein 466d11e3645SMatteo Riondato hosts[nhosts - 1] = "127.0.0.1"; 4678360efbdSAlfred Perlstein } 4688360efbdSAlfred Perlstein 4698fb6ad5dSRick Macklem attempt_cnt = 1; 4708fb6ad5dSRick Macklem sock_fdcnt = 0; 4718fb6ad5dSRick Macklem sock_fd = NULL; 4728fb6ad5dSRick Macklem port_list = NULL; 4738fb6ad5dSRick Macklem port_len = 0; 474d11e3645SMatteo Riondato nc_handle = setnetconfig(); 475d11e3645SMatteo Riondato while ((nconf = getnetconfig(nc_handle))) { 476d11e3645SMatteo Riondato if (nconf->nc_flag & NC_VISIBLE) { 477d11e3645SMatteo Riondato if (have_v6 == 0 && strcmp(nconf->nc_protofmly, 478d11e3645SMatteo Riondato "inet6") == 0) { 479d11e3645SMatteo Riondato /* DO NOTHING */ 4808fb6ad5dSRick Macklem } else { 4818fb6ad5dSRick Macklem ret = create_service(nconf); 4828fb6ad5dSRick Macklem if (ret == 1) 4838fb6ad5dSRick Macklem /* Ignore this call */ 4848fb6ad5dSRick Macklem continue; 4858fb6ad5dSRick Macklem if (ret < 0) { 4868fb6ad5dSRick Macklem /* 4878fb6ad5dSRick Macklem * Failed to bind port, so close off 4888fb6ad5dSRick Macklem * all sockets created and try again 4898fb6ad5dSRick Macklem * if the port# was dynamically 4908fb6ad5dSRick Macklem * assigned via bind(2). 4918fb6ad5dSRick Macklem */ 4928fb6ad5dSRick Macklem clearout_service(); 4938fb6ad5dSRick Macklem if (mallocd_svcport != 0 && 4948fb6ad5dSRick Macklem attempt_cnt < GETPORT_MAXTRY) { 4958fb6ad5dSRick Macklem free(svcport_str); 4968fb6ad5dSRick Macklem svcport_str = NULL; 4978fb6ad5dSRick Macklem mallocd_svcport = 0; 4988fb6ad5dSRick Macklem } else { 4998fb6ad5dSRick Macklem errno = EADDRINUSE; 5008fb6ad5dSRick Macklem syslog(LOG_ERR, 5018fb6ad5dSRick Macklem "bindresvport_sa: %m"); 5028fb6ad5dSRick Macklem exit(1); 5038fb6ad5dSRick Macklem } 5048fb6ad5dSRick Macklem 5058fb6ad5dSRick Macklem /* Start over at the first service. */ 5068fb6ad5dSRick Macklem free(sock_fd); 5078fb6ad5dSRick Macklem sock_fdcnt = 0; 5088fb6ad5dSRick Macklem sock_fd = NULL; 5098fb6ad5dSRick Macklem nc_handle = setnetconfig(); 5108fb6ad5dSRick Macklem attempt_cnt++; 5118fb6ad5dSRick Macklem } else if (mallocd_svcport != 0 && 5128fb6ad5dSRick Macklem attempt_cnt == GETPORT_MAXTRY) { 5138fb6ad5dSRick Macklem /* 5148fb6ad5dSRick Macklem * For the last attempt, allow 5158fb6ad5dSRick Macklem * different port #s for each nconf 5168fb6ad5dSRick Macklem * by saving the svcport_str and 5178fb6ad5dSRick Macklem * setting it back to NULL. 5188fb6ad5dSRick Macklem */ 5198fb6ad5dSRick Macklem port_list = realloc(port_list, 5208fb6ad5dSRick Macklem (port_len + 1) * sizeof(char *)); 5218fb6ad5dSRick Macklem if (port_list == NULL) 5228fb6ad5dSRick Macklem out_of_mem(); 5238fb6ad5dSRick Macklem port_list[port_len++] = svcport_str; 5248fb6ad5dSRick Macklem svcport_str = NULL; 5258fb6ad5dSRick Macklem mallocd_svcport = 0; 5268fb6ad5dSRick Macklem } 5278fb6ad5dSRick Macklem } 5288fb6ad5dSRick Macklem } 5298fb6ad5dSRick Macklem } 5308fb6ad5dSRick Macklem 5318fb6ad5dSRick Macklem /* 5328fb6ad5dSRick Macklem * Successfully bound the ports, so call complete_service() to 5338fb6ad5dSRick Macklem * do the rest of the setup on the service(s). 5348fb6ad5dSRick Macklem */ 5358fb6ad5dSRick Macklem sock_fdpos = 0; 5368fb6ad5dSRick Macklem port_pos = 0; 5378fb6ad5dSRick Macklem nc_handle = setnetconfig(); 5388fb6ad5dSRick Macklem while ((nconf = getnetconfig(nc_handle))) { 5398fb6ad5dSRick Macklem if (nconf->nc_flag & NC_VISIBLE) { 5408fb6ad5dSRick Macklem if (have_v6 == 0 && strcmp(nconf->nc_protofmly, 5418fb6ad5dSRick Macklem "inet6") == 0) { 5428fb6ad5dSRick Macklem /* DO NOTHING */ 5438fb6ad5dSRick Macklem } else if (port_list != NULL) { 5448fb6ad5dSRick Macklem if (port_pos >= port_len) { 5458fb6ad5dSRick Macklem syslog(LOG_ERR, "too many port#s"); 5468fb6ad5dSRick Macklem exit(1); 5478fb6ad5dSRick Macklem } 5488fb6ad5dSRick Macklem complete_service(nconf, port_list[port_pos++]); 549c203da27SBruce M Simpson } else 5508fb6ad5dSRick Macklem complete_service(nconf, svcport_str); 5518360efbdSAlfred Perlstein } 552d11e3645SMatteo Riondato } 553d11e3645SMatteo Riondato endnetconfig(nc_handle); 5548fb6ad5dSRick Macklem free(sock_fd); 5558fb6ad5dSRick Macklem if (port_list != NULL) { 5568fb6ad5dSRick Macklem for (port_pos = 0; port_pos < port_len; port_pos++) 5578fb6ad5dSRick Macklem free(port_list[port_pos]); 5588fb6ad5dSRick Macklem free(port_list); 5598fb6ad5dSRick Macklem } 5608360efbdSAlfred Perlstein 5618360efbdSAlfred Perlstein if (xcreated == 0) { 5628360efbdSAlfred Perlstein syslog(LOG_ERR, "could not create any services"); 5632a66cfc5SDoug Rabson exit(1); 5642a66cfc5SDoug Rabson } 56569d65572SIan Dowse 56669d65572SIan Dowse /* Expand svc_run() here so that we can call get_exportlist(). */ 56769d65572SIan Dowse for (;;) { 56869d65572SIan Dowse if (got_sighup) { 56969d65572SIan Dowse get_exportlist(); 57069d65572SIan Dowse got_sighup = 0; 57169d65572SIan Dowse } 57269d65572SIan Dowse readfds = svc_fdset; 57369d65572SIan Dowse switch (select(svc_maxfd + 1, &readfds, NULL, NULL, NULL)) { 57469d65572SIan Dowse case -1: 57569d65572SIan Dowse if (errno == EINTR) 57669d65572SIan Dowse continue; 57769d65572SIan Dowse syslog(LOG_ERR, "mountd died: select: %m"); 57874853402SPhilippe Charnier exit(1); 57969d65572SIan Dowse case 0: 58069d65572SIan Dowse continue; 58169d65572SIan Dowse default: 58269d65572SIan Dowse svc_getreqset(&readfds); 58369d65572SIan Dowse } 58469d65572SIan Dowse } 58574853402SPhilippe Charnier } 58674853402SPhilippe Charnier 587d11e3645SMatteo Riondato /* 588d11e3645SMatteo Riondato * This routine creates and binds sockets on the appropriate 5898fb6ad5dSRick Macklem * addresses. It gets called one time for each transport. 5908fb6ad5dSRick Macklem * It returns 0 upon success, 1 for ingore the call and -1 to indicate 5918fb6ad5dSRick Macklem * bind failed with EADDRINUSE. 5928fb6ad5dSRick Macklem * Any file descriptors that have been created are stored in sock_fd and 5938fb6ad5dSRick Macklem * the total count of them is maintained in sock_fdcnt. 594d11e3645SMatteo Riondato */ 5958fb6ad5dSRick Macklem static int 596d11e3645SMatteo Riondato create_service(struct netconfig *nconf) 597d11e3645SMatteo Riondato { 598d11e3645SMatteo Riondato struct addrinfo hints, *res = NULL; 599d11e3645SMatteo Riondato struct sockaddr_in *sin; 600d11e3645SMatteo Riondato struct sockaddr_in6 *sin6; 601d11e3645SMatteo Riondato struct __rpc_sockinfo si; 602d11e3645SMatteo Riondato int aicode; 603d11e3645SMatteo Riondato int fd; 604d11e3645SMatteo Riondato int nhostsbak; 605d11e3645SMatteo Riondato int one = 1; 606d11e3645SMatteo Riondato int r; 607d11e3645SMatteo Riondato u_int32_t host_addr[4]; /* IPv4 or IPv6 */ 6088fb6ad5dSRick Macklem int mallocd_res; 609d11e3645SMatteo Riondato 610d11e3645SMatteo Riondato if ((nconf->nc_semantics != NC_TPI_CLTS) && 611d11e3645SMatteo Riondato (nconf->nc_semantics != NC_TPI_COTS) && 612d11e3645SMatteo Riondato (nconf->nc_semantics != NC_TPI_COTS_ORD)) 6138fb6ad5dSRick Macklem return (1); /* not my type */ 614d11e3645SMatteo Riondato 615d11e3645SMatteo Riondato /* 616d11e3645SMatteo Riondato * XXX - using RPC library internal functions. 617d11e3645SMatteo Riondato */ 618d11e3645SMatteo Riondato if (!__rpc_nconf2sockinfo(nconf, &si)) { 619d11e3645SMatteo Riondato syslog(LOG_ERR, "cannot get information for %s", 620d11e3645SMatteo Riondato nconf->nc_netid); 6218fb6ad5dSRick Macklem return (1); 622d11e3645SMatteo Riondato } 623d11e3645SMatteo Riondato 624d11e3645SMatteo Riondato /* Get mountd's address on this transport */ 625d11e3645SMatteo Riondato memset(&hints, 0, sizeof hints); 626d11e3645SMatteo Riondato hints.ai_flags = AI_PASSIVE; 627d11e3645SMatteo Riondato hints.ai_family = si.si_af; 628d11e3645SMatteo Riondato hints.ai_socktype = si.si_socktype; 629d11e3645SMatteo Riondato hints.ai_protocol = si.si_proto; 630d11e3645SMatteo Riondato 631d11e3645SMatteo Riondato /* 632d11e3645SMatteo Riondato * Bind to specific IPs if asked to 633d11e3645SMatteo Riondato */ 634d11e3645SMatteo Riondato nhostsbak = nhosts; 635d11e3645SMatteo Riondato while (nhostsbak > 0) { 636d11e3645SMatteo Riondato --nhostsbak; 6378fb6ad5dSRick Macklem sock_fd = realloc(sock_fd, (sock_fdcnt + 1) * sizeof(int)); 6388fb6ad5dSRick Macklem if (sock_fd == NULL) 6398fb6ad5dSRick Macklem out_of_mem(); 6408fb6ad5dSRick Macklem sock_fd[sock_fdcnt++] = -1; /* Set invalid for now. */ 6418fb6ad5dSRick Macklem mallocd_res = 0; 6428fb6ad5dSRick Macklem 643d11e3645SMatteo Riondato /* 644d11e3645SMatteo Riondato * XXX - using RPC library internal functions. 645d11e3645SMatteo Riondato */ 646d11e3645SMatteo Riondato if ((fd = __rpc_nconf2fd(nconf)) < 0) { 647d11e3645SMatteo Riondato int non_fatal = 0; 648d11e3645SMatteo Riondato if (errno == EPROTONOSUPPORT && 649d11e3645SMatteo Riondato nconf->nc_semantics != NC_TPI_CLTS) 650d11e3645SMatteo Riondato non_fatal = 1; 651d11e3645SMatteo Riondato 652d11e3645SMatteo Riondato syslog(non_fatal ? LOG_DEBUG : LOG_ERR, 653d11e3645SMatteo Riondato "cannot create socket for %s", nconf->nc_netid); 6548fb6ad5dSRick Macklem if (non_fatal != 0) 6558fb6ad5dSRick Macklem continue; 6568fb6ad5dSRick Macklem exit(1); 657d11e3645SMatteo Riondato } 658d11e3645SMatteo Riondato 659d11e3645SMatteo Riondato switch (hints.ai_family) { 660d11e3645SMatteo Riondato case AF_INET: 661d11e3645SMatteo Riondato if (inet_pton(AF_INET, hosts[nhostsbak], 662d11e3645SMatteo Riondato host_addr) == 1) { 6638fb6ad5dSRick Macklem hints.ai_flags |= AI_NUMERICHOST; 664d11e3645SMatteo Riondato } else { 665d11e3645SMatteo Riondato /* 666d11e3645SMatteo Riondato * Skip if we have an AF_INET6 address. 667d11e3645SMatteo Riondato */ 668d11e3645SMatteo Riondato if (inet_pton(AF_INET6, hosts[nhostsbak], 669d11e3645SMatteo Riondato host_addr) == 1) { 670d11e3645SMatteo Riondato close(fd); 671d11e3645SMatteo Riondato continue; 672d11e3645SMatteo Riondato } 673d11e3645SMatteo Riondato } 674d11e3645SMatteo Riondato break; 675d11e3645SMatteo Riondato case AF_INET6: 676d11e3645SMatteo Riondato if (inet_pton(AF_INET6, hosts[nhostsbak], 677d11e3645SMatteo Riondato host_addr) == 1) { 6788fb6ad5dSRick Macklem hints.ai_flags |= AI_NUMERICHOST; 679d11e3645SMatteo Riondato } else { 680d11e3645SMatteo Riondato /* 681d11e3645SMatteo Riondato * Skip if we have an AF_INET address. 682d11e3645SMatteo Riondato */ 683d11e3645SMatteo Riondato if (inet_pton(AF_INET, hosts[nhostsbak], 684d11e3645SMatteo Riondato host_addr) == 1) { 685d11e3645SMatteo Riondato close(fd); 686d11e3645SMatteo Riondato continue; 687d11e3645SMatteo Riondato } 688d11e3645SMatteo Riondato } 689d11e3645SMatteo Riondato 690d11e3645SMatteo Riondato /* 691d11e3645SMatteo Riondato * We're doing host-based access checks here, so don't 692d11e3645SMatteo Riondato * allow v4-in-v6 to confuse things. The kernel will 693d11e3645SMatteo Riondato * disable it by default on NFS sockets too. 694d11e3645SMatteo Riondato */ 695d11e3645SMatteo Riondato if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, 696d11e3645SMatteo Riondato sizeof one) < 0) { 697d11e3645SMatteo Riondato syslog(LOG_ERR, 698d11e3645SMatteo Riondato "can't disable v4-in-v6 on IPv6 socket"); 699d11e3645SMatteo Riondato exit(1); 700d11e3645SMatteo Riondato } 701d11e3645SMatteo Riondato break; 702d11e3645SMatteo Riondato default: 703d11e3645SMatteo Riondato break; 704d11e3645SMatteo Riondato } 705d11e3645SMatteo Riondato 706d11e3645SMatteo Riondato /* 707d11e3645SMatteo Riondato * If no hosts were specified, just bind to INADDR_ANY 708d11e3645SMatteo Riondato */ 709d11e3645SMatteo Riondato if (strcmp("*", hosts[nhostsbak]) == 0) { 710d11e3645SMatteo Riondato if (svcport_str == NULL) { 711d11e3645SMatteo Riondato res = malloc(sizeof(struct addrinfo)); 712d11e3645SMatteo Riondato if (res == NULL) 713d11e3645SMatteo Riondato out_of_mem(); 7148fb6ad5dSRick Macklem mallocd_res = 1; 715d11e3645SMatteo Riondato res->ai_flags = hints.ai_flags; 716d11e3645SMatteo Riondato res->ai_family = hints.ai_family; 717d11e3645SMatteo Riondato res->ai_protocol = hints.ai_protocol; 718d11e3645SMatteo Riondato switch (res->ai_family) { 719d11e3645SMatteo Riondato case AF_INET: 720d11e3645SMatteo Riondato sin = malloc(sizeof(struct sockaddr_in)); 721d11e3645SMatteo Riondato if (sin == NULL) 722d11e3645SMatteo Riondato out_of_mem(); 723d11e3645SMatteo Riondato sin->sin_family = AF_INET; 724d11e3645SMatteo Riondato sin->sin_port = htons(0); 725d11e3645SMatteo Riondato sin->sin_addr.s_addr = htonl(INADDR_ANY); 726d11e3645SMatteo Riondato res->ai_addr = (struct sockaddr*) sin; 727d11e3645SMatteo Riondato res->ai_addrlen = (socklen_t) 7288fb6ad5dSRick Macklem sizeof(struct sockaddr_in); 729d11e3645SMatteo Riondato break; 730d11e3645SMatteo Riondato case AF_INET6: 731d11e3645SMatteo Riondato sin6 = malloc(sizeof(struct sockaddr_in6)); 73289ca9145SSimon L. B. Nielsen if (sin6 == NULL) 733d11e3645SMatteo Riondato out_of_mem(); 734d11e3645SMatteo Riondato sin6->sin6_family = AF_INET6; 735d11e3645SMatteo Riondato sin6->sin6_port = htons(0); 736d11e3645SMatteo Riondato sin6->sin6_addr = in6addr_any; 737d11e3645SMatteo Riondato res->ai_addr = (struct sockaddr*) sin6; 738d11e3645SMatteo Riondato res->ai_addrlen = (socklen_t) 7398fb6ad5dSRick Macklem sizeof(struct sockaddr_in6); 740d11e3645SMatteo Riondato break; 741d11e3645SMatteo Riondato default: 7428fb6ad5dSRick Macklem syslog(LOG_ERR, "bad addr fam %d", 7438fb6ad5dSRick Macklem res->ai_family); 7448fb6ad5dSRick Macklem exit(1); 745d11e3645SMatteo Riondato } 746d11e3645SMatteo Riondato } else { 747d11e3645SMatteo Riondato if ((aicode = getaddrinfo(NULL, svcport_str, 748d11e3645SMatteo Riondato &hints, &res)) != 0) { 749d11e3645SMatteo Riondato syslog(LOG_ERR, 750d11e3645SMatteo Riondato "cannot get local address for %s: %s", 751d11e3645SMatteo Riondato nconf->nc_netid, 752d11e3645SMatteo Riondato gai_strerror(aicode)); 7538fb6ad5dSRick Macklem close(fd); 754d11e3645SMatteo Riondato continue; 755d11e3645SMatteo Riondato } 756d11e3645SMatteo Riondato } 757d11e3645SMatteo Riondato } else { 758d11e3645SMatteo Riondato if ((aicode = getaddrinfo(hosts[nhostsbak], svcport_str, 759d11e3645SMatteo Riondato &hints, &res)) != 0) { 760d11e3645SMatteo Riondato syslog(LOG_ERR, 761d11e3645SMatteo Riondato "cannot get local address for %s: %s", 762d11e3645SMatteo Riondato nconf->nc_netid, gai_strerror(aicode)); 7638fb6ad5dSRick Macklem close(fd); 764d11e3645SMatteo Riondato continue; 765d11e3645SMatteo Riondato } 766d11e3645SMatteo Riondato } 767d11e3645SMatteo Riondato 7688fb6ad5dSRick Macklem /* Store the fd. */ 7698fb6ad5dSRick Macklem sock_fd[sock_fdcnt - 1] = fd; 7708fb6ad5dSRick Macklem 7718fb6ad5dSRick Macklem /* Now, attempt the bind. */ 772d11e3645SMatteo Riondato r = bindresvport_sa(fd, res->ai_addr); 773d11e3645SMatteo Riondato if (r != 0) { 7748fb6ad5dSRick Macklem if (errno == EADDRINUSE && mallocd_svcport != 0) { 7758fb6ad5dSRick Macklem if (mallocd_res != 0) { 7768fb6ad5dSRick Macklem free(res->ai_addr); 7778fb6ad5dSRick Macklem free(res); 7788fb6ad5dSRick Macklem } else 7798fb6ad5dSRick Macklem freeaddrinfo(res); 7808fb6ad5dSRick Macklem return (-1); 7818fb6ad5dSRick Macklem } 782d11e3645SMatteo Riondato syslog(LOG_ERR, "bindresvport_sa: %m"); 783d11e3645SMatteo Riondato exit(1); 784d11e3645SMatteo Riondato } 785d11e3645SMatteo Riondato 7868fb6ad5dSRick Macklem if (svcport_str == NULL) { 7878fb6ad5dSRick Macklem svcport_str = malloc(NI_MAXSERV * sizeof(char)); 7888fb6ad5dSRick Macklem if (svcport_str == NULL) 7898fb6ad5dSRick Macklem out_of_mem(); 7908fb6ad5dSRick Macklem mallocd_svcport = 1; 7918fb6ad5dSRick Macklem 7928fb6ad5dSRick Macklem if (getnameinfo(res->ai_addr, 7938fb6ad5dSRick Macklem res->ai_addr->sa_len, NULL, NI_MAXHOST, 7948fb6ad5dSRick Macklem svcport_str, NI_MAXSERV * sizeof(char), 7958fb6ad5dSRick Macklem NI_NUMERICHOST | NI_NUMERICSERV)) 7968fb6ad5dSRick Macklem errx(1, "Cannot get port number"); 7978fb6ad5dSRick Macklem } 7988fb6ad5dSRick Macklem if (mallocd_res != 0) { 7998fb6ad5dSRick Macklem free(res->ai_addr); 8008fb6ad5dSRick Macklem free(res); 8018fb6ad5dSRick Macklem } else 8028fb6ad5dSRick Macklem freeaddrinfo(res); 8038fb6ad5dSRick Macklem res = NULL; 8048fb6ad5dSRick Macklem } 8058fb6ad5dSRick Macklem return (0); 8068fb6ad5dSRick Macklem } 8078fb6ad5dSRick Macklem 8088fb6ad5dSRick Macklem /* 8098fb6ad5dSRick Macklem * Called after all the create_service() calls have succeeded, to complete 8108fb6ad5dSRick Macklem * the setup and registration. 8118fb6ad5dSRick Macklem */ 8128fb6ad5dSRick Macklem static void 8138fb6ad5dSRick Macklem complete_service(struct netconfig *nconf, char *port_str) 8148fb6ad5dSRick Macklem { 8158fb6ad5dSRick Macklem struct addrinfo hints, *res = NULL; 8168fb6ad5dSRick Macklem struct __rpc_sockinfo si; 8178fb6ad5dSRick Macklem struct netbuf servaddr; 8188fb6ad5dSRick Macklem SVCXPRT *transp = NULL; 8198fb6ad5dSRick Macklem int aicode, fd, nhostsbak; 8208fb6ad5dSRick Macklem int registered = 0; 8218fb6ad5dSRick Macklem 8228fb6ad5dSRick Macklem if ((nconf->nc_semantics != NC_TPI_CLTS) && 8238fb6ad5dSRick Macklem (nconf->nc_semantics != NC_TPI_COTS) && 8248fb6ad5dSRick Macklem (nconf->nc_semantics != NC_TPI_COTS_ORD)) 8258fb6ad5dSRick Macklem return; /* not my type */ 8268fb6ad5dSRick Macklem 8278fb6ad5dSRick Macklem /* 8288fb6ad5dSRick Macklem * XXX - using RPC library internal functions. 8298fb6ad5dSRick Macklem */ 8308fb6ad5dSRick Macklem if (!__rpc_nconf2sockinfo(nconf, &si)) { 8318fb6ad5dSRick Macklem syslog(LOG_ERR, "cannot get information for %s", 8328fb6ad5dSRick Macklem nconf->nc_netid); 8338fb6ad5dSRick Macklem return; 8348fb6ad5dSRick Macklem } 8358fb6ad5dSRick Macklem 8368fb6ad5dSRick Macklem nhostsbak = nhosts; 8378fb6ad5dSRick Macklem while (nhostsbak > 0) { 8388fb6ad5dSRick Macklem --nhostsbak; 8398fb6ad5dSRick Macklem if (sock_fdpos >= sock_fdcnt) { 8408fb6ad5dSRick Macklem /* Should never happen. */ 8418fb6ad5dSRick Macklem syslog(LOG_ERR, "Ran out of socket fd's"); 8428fb6ad5dSRick Macklem return; 8438fb6ad5dSRick Macklem } 8448fb6ad5dSRick Macklem fd = sock_fd[sock_fdpos++]; 8458fb6ad5dSRick Macklem if (fd < 0) 8468fb6ad5dSRick Macklem continue; 8478fb6ad5dSRick Macklem 848d11e3645SMatteo Riondato if (nconf->nc_semantics != NC_TPI_CLTS) 849d11e3645SMatteo Riondato listen(fd, SOMAXCONN); 850d11e3645SMatteo Riondato 851d11e3645SMatteo Riondato if (nconf->nc_semantics == NC_TPI_CLTS ) 852d11e3645SMatteo Riondato transp = svc_dg_create(fd, 0, 0); 853d11e3645SMatteo Riondato else 854d11e3645SMatteo Riondato transp = svc_vc_create(fd, RPC_MAXDATASIZE, 855d11e3645SMatteo Riondato RPC_MAXDATASIZE); 856d11e3645SMatteo Riondato 857d11e3645SMatteo Riondato if (transp != (SVCXPRT *) NULL) { 8580775314bSDoug Rabson if (!svc_reg(transp, MOUNTPROG, MOUNTVERS, mntsrv, 859d11e3645SMatteo Riondato NULL)) 860d11e3645SMatteo Riondato syslog(LOG_ERR, 8610775314bSDoug Rabson "can't register %s MOUNTVERS service", 862d11e3645SMatteo Riondato nconf->nc_netid); 863d11e3645SMatteo Riondato if (!force_v2) { 8640775314bSDoug Rabson if (!svc_reg(transp, MOUNTPROG, MOUNTVERS3, 865d11e3645SMatteo Riondato mntsrv, NULL)) 866d11e3645SMatteo Riondato syslog(LOG_ERR, 8670775314bSDoug Rabson "can't register %s MOUNTVERS3 service", 868d11e3645SMatteo Riondato nconf->nc_netid); 869d11e3645SMatteo Riondato } 870d11e3645SMatteo Riondato } else 871d11e3645SMatteo Riondato syslog(LOG_WARNING, "can't create %s services", 872d11e3645SMatteo Riondato nconf->nc_netid); 873d11e3645SMatteo Riondato 874d11e3645SMatteo Riondato if (registered == 0) { 875d11e3645SMatteo Riondato registered = 1; 876d11e3645SMatteo Riondato memset(&hints, 0, sizeof hints); 877d11e3645SMatteo Riondato hints.ai_flags = AI_PASSIVE; 878d11e3645SMatteo Riondato hints.ai_family = si.si_af; 879d11e3645SMatteo Riondato hints.ai_socktype = si.si_socktype; 880d11e3645SMatteo Riondato hints.ai_protocol = si.si_proto; 881d11e3645SMatteo Riondato 8828fb6ad5dSRick Macklem if ((aicode = getaddrinfo(NULL, port_str, &hints, 883d11e3645SMatteo Riondato &res)) != 0) { 884d11e3645SMatteo Riondato syslog(LOG_ERR, "cannot get local address: %s", 885d11e3645SMatteo Riondato gai_strerror(aicode)); 886d11e3645SMatteo Riondato exit(1); 887d11e3645SMatteo Riondato } 888d11e3645SMatteo Riondato 889d11e3645SMatteo Riondato servaddr.buf = malloc(res->ai_addrlen); 890d11e3645SMatteo Riondato memcpy(servaddr.buf, res->ai_addr, res->ai_addrlen); 891d11e3645SMatteo Riondato servaddr.len = res->ai_addrlen; 892d11e3645SMatteo Riondato 8930775314bSDoug Rabson rpcb_set(MOUNTPROG, MOUNTVERS, nconf, &servaddr); 8940775314bSDoug Rabson rpcb_set(MOUNTPROG, MOUNTVERS3, nconf, &servaddr); 895d11e3645SMatteo Riondato 896d11e3645SMatteo Riondato xcreated++; 897d11e3645SMatteo Riondato freeaddrinfo(res); 898d11e3645SMatteo Riondato } 899d11e3645SMatteo Riondato } /* end while */ 900d11e3645SMatteo Riondato } 901d11e3645SMatteo Riondato 9028fb6ad5dSRick Macklem /* 9038fb6ad5dSRick Macklem * Clear out sockets after a failure to bind one of them, so that the 9048fb6ad5dSRick Macklem * cycle of socket creation/binding can start anew. 9058fb6ad5dSRick Macklem */ 9068fb6ad5dSRick Macklem static void 9078fb6ad5dSRick Macklem clearout_service(void) 9088fb6ad5dSRick Macklem { 9098fb6ad5dSRick Macklem int i; 9108fb6ad5dSRick Macklem 9118fb6ad5dSRick Macklem for (i = 0; i < sock_fdcnt; i++) { 9128fb6ad5dSRick Macklem if (sock_fd[i] >= 0) { 9138fb6ad5dSRick Macklem shutdown(sock_fd[i], SHUT_RDWR); 9148fb6ad5dSRick Macklem close(sock_fd[i]); 9158fb6ad5dSRick Macklem } 9168fb6ad5dSRick Macklem } 9178fb6ad5dSRick Macklem } 9188fb6ad5dSRick Macklem 91974853402SPhilippe Charnier static void 920a7a7d96cSPhilippe Charnier usage(void) 92174853402SPhilippe Charnier { 92274853402SPhilippe Charnier fprintf(stderr, 9232179ae1eSRick Macklem "usage: mountd [-2] [-d] [-e] [-l] [-n] [-p <port>] [-r] " 924d11e3645SMatteo Riondato "[-h <bindip>] [export_file ...]\n"); 9258fae3551SRodney W. Grimes exit(1); 9268fae3551SRodney W. Grimes } 9278fae3551SRodney W. Grimes 9288fae3551SRodney W. Grimes /* 9298fae3551SRodney W. Grimes * The mount rpc service 9308fae3551SRodney W. Grimes */ 9318fae3551SRodney W. Grimes void 932a7a7d96cSPhilippe Charnier mntsrv(struct svc_req *rqstp, SVCXPRT *transp) 9338fae3551SRodney W. Grimes { 9348fae3551SRodney W. Grimes struct exportlist *ep; 9358fae3551SRodney W. Grimes struct dirlist *dp; 936a62dc406SDoug Rabson struct fhreturn fhr; 9378fae3551SRodney W. Grimes struct stat stb; 9388fae3551SRodney W. Grimes struct statfs fsb; 9398360efbdSAlfred Perlstein char host[NI_MAXHOST], numerichost[NI_MAXHOST]; 9408360efbdSAlfred Perlstein int lookup_failed = 1; 9418360efbdSAlfred Perlstein struct sockaddr *saddr; 942a62dc406SDoug Rabson u_short sport; 9430775314bSDoug Rabson char rpcpath[MNTPATHLEN + 1], dirpath[MAXPATHLEN]; 944e90cdb54SGuido van Rooij int bad = 0, defset, hostset; 945a62dc406SDoug Rabson sigset_t sighup_mask; 946*c3f86a25SRick Macklem int numsecflavors, *secflavorsp; 9478fae3551SRodney W. Grimes 948a62dc406SDoug Rabson sigemptyset(&sighup_mask); 949a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 9508360efbdSAlfred Perlstein saddr = svc_getrpccaller(transp)->buf; 9518360efbdSAlfred Perlstein switch (saddr->sa_family) { 9528360efbdSAlfred Perlstein case AF_INET6: 95301709abfSIan Dowse sport = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port); 9548360efbdSAlfred Perlstein break; 9558360efbdSAlfred Perlstein case AF_INET: 95601709abfSIan Dowse sport = ntohs(((struct sockaddr_in *)saddr)->sin_port); 9578360efbdSAlfred Perlstein break; 9588360efbdSAlfred Perlstein default: 9598360efbdSAlfred Perlstein syslog(LOG_ERR, "request from unknown address family"); 9608360efbdSAlfred Perlstein return; 9618360efbdSAlfred Perlstein } 9628360efbdSAlfred Perlstein lookup_failed = getnameinfo(saddr, saddr->sa_len, host, sizeof host, 9638360efbdSAlfred Perlstein NULL, 0, 0); 9648360efbdSAlfred Perlstein getnameinfo(saddr, saddr->sa_len, numerichost, 9658360efbdSAlfred Perlstein sizeof numerichost, NULL, 0, NI_NUMERICHOST); 9668fae3551SRodney W. Grimes switch (rqstp->rq_proc) { 9678fae3551SRodney W. Grimes case NULLPROC: 968389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) 96974853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 9708fae3551SRodney W. Grimes return; 9710775314bSDoug Rabson case MOUNTPROC_MNT: 972a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 973f51631d7SGuido van Rooij syslog(LOG_NOTICE, 974f51631d7SGuido van Rooij "mount request from %s from unprivileged port", 9758360efbdSAlfred Perlstein numerichost); 9768fae3551SRodney W. Grimes svcerr_weakauth(transp); 9778fae3551SRodney W. Grimes return; 9788fae3551SRodney W. Grimes } 979389b8446SPeter Wemm if (!svc_getargs(transp, (xdrproc_t)xdr_dir, rpcpath)) { 980f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable mount request from %s", 9818360efbdSAlfred Perlstein numerichost); 9828fae3551SRodney W. Grimes svcerr_decode(transp); 9838fae3551SRodney W. Grimes return; 9848fae3551SRodney W. Grimes } 9858fae3551SRodney W. Grimes 9868fae3551SRodney W. Grimes /* 9878fae3551SRodney W. Grimes * Get the real pathname and make sure it is a directory 988a62dc406SDoug Rabson * or a regular file if the -r option was specified 989a62dc406SDoug Rabson * and it exists. 9908fae3551SRodney W. Grimes */ 991cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL || 9928fae3551SRodney W. Grimes stat(dirpath, &stb) < 0 || 993a62dc406SDoug Rabson (!S_ISDIR(stb.st_mode) && 994a62dc406SDoug Rabson (dir_only || !S_ISREG(stb.st_mode))) || 9958fae3551SRodney W. Grimes statfs(dirpath, &fsb) < 0) { 9968fae3551SRodney W. Grimes chdir("/"); /* Just in case realpath doesn't */ 997f51631d7SGuido van Rooij syslog(LOG_NOTICE, 99874853402SPhilippe Charnier "mount request from %s for non existent path %s", 9998360efbdSAlfred Perlstein numerichost, dirpath); 10008fae3551SRodney W. Grimes if (debug) 100174853402SPhilippe Charnier warnx("stat failed on %s", dirpath); 1002e90cdb54SGuido van Rooij bad = ENOENT; /* We will send error reply later */ 10038fae3551SRodney W. Grimes } 10048fae3551SRodney W. Grimes 10058fae3551SRodney W. Grimes /* Check in the exports list */ 1006a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 10078fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 1008a62dc406SDoug Rabson hostset = defset = 0; 1009*c3f86a25SRick Macklem if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset, 1010*c3f86a25SRick Macklem &numsecflavors, &secflavorsp) || 10118fae3551SRodney W. Grimes ((dp = dirp_search(ep->ex_dirl, dirpath)) && 1012*c3f86a25SRick Macklem chk_host(dp, saddr, &defset, &hostset, &numsecflavors, 1013*c3f86a25SRick Macklem &secflavorsp)) || 10148fae3551SRodney W. Grimes (defset && scan_tree(ep->ex_defdir, saddr) == 0 && 10158fae3551SRodney W. Grimes scan_tree(ep->ex_dirl, saddr) == 0))) { 1016e90cdb54SGuido van Rooij if (bad) { 1017389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_long, 1018e90cdb54SGuido van Rooij (caddr_t)&bad)) 101974853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 1020e90cdb54SGuido van Rooij sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 1021e90cdb54SGuido van Rooij return; 1022e90cdb54SGuido van Rooij } 1023*c3f86a25SRick Macklem if (hostset & DP_HOSTSET) { 1024a62dc406SDoug Rabson fhr.fhr_flag = hostset; 1025*c3f86a25SRick Macklem fhr.fhr_numsecflavors = numsecflavors; 1026*c3f86a25SRick Macklem fhr.fhr_secflavors = secflavorsp; 1027*c3f86a25SRick Macklem } else { 1028a62dc406SDoug Rabson fhr.fhr_flag = defset; 1029*c3f86a25SRick Macklem fhr.fhr_numsecflavors = ep->ex_defnumsecflavors; 1030*c3f86a25SRick Macklem fhr.fhr_secflavors = ep->ex_defsecflavors; 1031*c3f86a25SRick Macklem } 1032a62dc406SDoug Rabson fhr.fhr_vers = rqstp->rq_vers; 10338fae3551SRodney W. Grimes /* Get the file handle */ 103487564113SPeter Wemm memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t)); 1035a62dc406SDoug Rabson if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) { 10368fae3551SRodney W. Grimes bad = errno; 103774853402SPhilippe Charnier syslog(LOG_ERR, "can't get fh for %s", dirpath); 1038389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_long, 10398fae3551SRodney W. Grimes (caddr_t)&bad)) 104074853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 1041a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 10428fae3551SRodney W. Grimes return; 10438fae3551SRodney W. Grimes } 1044389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_fhs, 1045389b8446SPeter Wemm (caddr_t)&fhr)) 104674853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 10478360efbdSAlfred Perlstein if (!lookup_failed) 10488360efbdSAlfred Perlstein add_mlist(host, dirpath); 10498fae3551SRodney W. Grimes else 10508360efbdSAlfred Perlstein add_mlist(numerichost, dirpath); 10518fae3551SRodney W. Grimes if (debug) 105274853402SPhilippe Charnier warnx("mount successful"); 1053c903443aSPeter Wemm if (dolog) 1054f51631d7SGuido van Rooij syslog(LOG_NOTICE, 1055f51631d7SGuido van Rooij "mount request succeeded from %s for %s", 10568360efbdSAlfred Perlstein numerichost, dirpath); 1057f51631d7SGuido van Rooij } else { 10588fae3551SRodney W. Grimes bad = EACCES; 1059f51631d7SGuido van Rooij syslog(LOG_NOTICE, 1060f51631d7SGuido van Rooij "mount request denied from %s for %s", 10618360efbdSAlfred Perlstein numerichost, dirpath); 1062f51631d7SGuido van Rooij } 1063e90cdb54SGuido van Rooij 1064389b8446SPeter Wemm if (bad && !svc_sendreply(transp, (xdrproc_t)xdr_long, 1065389b8446SPeter Wemm (caddr_t)&bad)) 106674853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 1067a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 10688fae3551SRodney W. Grimes return; 10690775314bSDoug Rabson case MOUNTPROC_DUMP: 1070389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_mlist, (caddr_t)NULL)) 107174853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 1072c903443aSPeter Wemm else if (dolog) 1073f51631d7SGuido van Rooij syslog(LOG_NOTICE, 1074f51631d7SGuido van Rooij "dump request succeeded from %s", 10758360efbdSAlfred Perlstein numerichost); 10768fae3551SRodney W. Grimes return; 10770775314bSDoug Rabson case MOUNTPROC_UMNT: 1078a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 1079f51631d7SGuido van Rooij syslog(LOG_NOTICE, 1080f51631d7SGuido van Rooij "umount request from %s from unprivileged port", 10818360efbdSAlfred Perlstein numerichost); 10828fae3551SRodney W. Grimes svcerr_weakauth(transp); 10838fae3551SRodney W. Grimes return; 10848fae3551SRodney W. Grimes } 1085389b8446SPeter Wemm if (!svc_getargs(transp, (xdrproc_t)xdr_dir, rpcpath)) { 1086f51631d7SGuido van Rooij syslog(LOG_NOTICE, "undecodable umount request from %s", 10878360efbdSAlfred Perlstein numerichost); 10888fae3551SRodney W. Grimes svcerr_decode(transp); 10898fae3551SRodney W. Grimes return; 10908fae3551SRodney W. Grimes } 1091cb479b11SAlfred Perlstein if (realpath(rpcpath, dirpath) == NULL) { 1092cb479b11SAlfred Perlstein syslog(LOG_NOTICE, "umount request from %s " 1093cb479b11SAlfred Perlstein "for non existent path %s", 10948360efbdSAlfred Perlstein numerichost, dirpath); 1095cb479b11SAlfred Perlstein } 1096389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_void, (caddr_t)NULL)) 109774853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 10988360efbdSAlfred Perlstein if (!lookup_failed) 109901709abfSIan Dowse del_mlist(host, dirpath); 110001709abfSIan Dowse del_mlist(numerichost, dirpath); 1101c903443aSPeter Wemm if (dolog) 1102f51631d7SGuido van Rooij syslog(LOG_NOTICE, 1103f51631d7SGuido van Rooij "umount request succeeded from %s for %s", 11048360efbdSAlfred Perlstein numerichost, dirpath); 11058fae3551SRodney W. Grimes return; 11060775314bSDoug Rabson case MOUNTPROC_UMNTALL: 1107a62dc406SDoug Rabson if (sport >= IPPORT_RESERVED && resvport_only) { 1108f51631d7SGuido van Rooij syslog(LOG_NOTICE, 1109f51631d7SGuido van Rooij "umountall request from %s from unprivileged port", 11108360efbdSAlfred Perlstein numerichost); 11118fae3551SRodney W. Grimes svcerr_weakauth(transp); 11128fae3551SRodney W. Grimes return; 11138fae3551SRodney W. Grimes } 1114389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_void, (caddr_t)NULL)) 111574853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 11168360efbdSAlfred Perlstein if (!lookup_failed) 111701709abfSIan Dowse del_mlist(host, NULL); 111801709abfSIan Dowse del_mlist(numerichost, NULL); 1119c903443aSPeter Wemm if (dolog) 1120f51631d7SGuido van Rooij syslog(LOG_NOTICE, 1121f51631d7SGuido van Rooij "umountall request succeeded from %s", 11228360efbdSAlfred Perlstein numerichost); 11238fae3551SRodney W. Grimes return; 11240775314bSDoug Rabson case MOUNTPROC_EXPORT: 1125389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_explist, (caddr_t)NULL)) 1126389b8446SPeter Wemm if (!svc_sendreply(transp, (xdrproc_t)xdr_explist_brief, 1127389b8446SPeter Wemm (caddr_t)NULL)) 112874853402SPhilippe Charnier syslog(LOG_ERR, "can't send reply"); 1129c903443aSPeter Wemm if (dolog) 1130f51631d7SGuido van Rooij syslog(LOG_NOTICE, 1131f51631d7SGuido van Rooij "export request succeeded from %s", 11328360efbdSAlfred Perlstein numerichost); 11338fae3551SRodney W. Grimes return; 11348fae3551SRodney W. Grimes default: 11358fae3551SRodney W. Grimes svcerr_noproc(transp); 11368fae3551SRodney W. Grimes return; 11378fae3551SRodney W. Grimes } 11388fae3551SRodney W. Grimes } 11398fae3551SRodney W. Grimes 11408fae3551SRodney W. Grimes /* 11418fae3551SRodney W. Grimes * Xdr conversion for a dirpath string 11428fae3551SRodney W. Grimes */ 11438fae3551SRodney W. Grimes int 1144a7a7d96cSPhilippe Charnier xdr_dir(XDR *xdrsp, char *dirp) 11458fae3551SRodney W. Grimes { 11460775314bSDoug Rabson return (xdr_string(xdrsp, &dirp, MNTPATHLEN)); 11478fae3551SRodney W. Grimes } 11488fae3551SRodney W. Grimes 11498fae3551SRodney W. Grimes /* 1150a62dc406SDoug Rabson * Xdr routine to generate file handle reply 11518fae3551SRodney W. Grimes */ 11528fae3551SRodney W. Grimes int 1153a7a7d96cSPhilippe Charnier xdr_fhs(XDR *xdrsp, caddr_t cp) 11548fae3551SRodney W. Grimes { 11553d438ad6SDavid E. O'Brien struct fhreturn *fhrp = (struct fhreturn *)cp; 1156a62dc406SDoug Rabson u_long ok = 0, len, auth; 1157a9148abdSDoug Rabson int i; 11588fae3551SRodney W. Grimes 11598fae3551SRodney W. Grimes if (!xdr_long(xdrsp, &ok)) 11608fae3551SRodney W. Grimes return (0); 1161a62dc406SDoug Rabson switch (fhrp->fhr_vers) { 1162a62dc406SDoug Rabson case 1: 1163a62dc406SDoug Rabson return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH)); 1164a62dc406SDoug Rabson case 3: 1165a62dc406SDoug Rabson len = NFSX_V3FH; 1166a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 1167a62dc406SDoug Rabson return (0); 1168a62dc406SDoug Rabson if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) 1169a62dc406SDoug Rabson return (0); 1170a9148abdSDoug Rabson if (fhrp->fhr_numsecflavors) { 1171a9148abdSDoug Rabson if (!xdr_int(xdrsp, &fhrp->fhr_numsecflavors)) 1172a9148abdSDoug Rabson return (0); 1173a9148abdSDoug Rabson for (i = 0; i < fhrp->fhr_numsecflavors; i++) 1174a9148abdSDoug Rabson if (!xdr_int(xdrsp, &fhrp->fhr_secflavors[i])) 1175a9148abdSDoug Rabson return (0); 1176a9148abdSDoug Rabson return (1); 1177a9148abdSDoug Rabson } else { 1178a9148abdSDoug Rabson auth = AUTH_SYS; 1179a62dc406SDoug Rabson len = 1; 1180a62dc406SDoug Rabson if (!xdr_long(xdrsp, &len)) 1181a62dc406SDoug Rabson return (0); 1182a62dc406SDoug Rabson return (xdr_long(xdrsp, &auth)); 1183a9148abdSDoug Rabson } 1184a62dc406SDoug Rabson }; 1185a62dc406SDoug Rabson return (0); 11868fae3551SRodney W. Grimes } 11878fae3551SRodney W. Grimes 11888fae3551SRodney W. Grimes int 1189a7a7d96cSPhilippe Charnier xdr_mlist(XDR *xdrsp, caddr_t cp __unused) 11908fae3551SRodney W. Grimes { 11918fae3551SRodney W. Grimes struct mountlist *mlp; 11928fae3551SRodney W. Grimes int true = 1; 11938fae3551SRodney W. Grimes int false = 0; 11948fae3551SRodney W. Grimes char *strp; 11958fae3551SRodney W. Grimes 11968fae3551SRodney W. Grimes mlp = mlhead; 11978fae3551SRodney W. Grimes while (mlp) { 11988fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 11998fae3551SRodney W. Grimes return (0); 12008fae3551SRodney W. Grimes strp = &mlp->ml_host[0]; 12010775314bSDoug Rabson if (!xdr_string(xdrsp, &strp, MNTNAMLEN)) 12028fae3551SRodney W. Grimes return (0); 12038fae3551SRodney W. Grimes strp = &mlp->ml_dirp[0]; 12040775314bSDoug Rabson if (!xdr_string(xdrsp, &strp, MNTPATHLEN)) 12058fae3551SRodney W. Grimes return (0); 12068fae3551SRodney W. Grimes mlp = mlp->ml_next; 12078fae3551SRodney W. Grimes } 12088fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 12098fae3551SRodney W. Grimes return (0); 12108fae3551SRodney W. Grimes return (1); 12118fae3551SRodney W. Grimes } 12128fae3551SRodney W. Grimes 12138fae3551SRodney W. Grimes /* 12148fae3551SRodney W. Grimes * Xdr conversion for export list 12158fae3551SRodney W. Grimes */ 12168fae3551SRodney W. Grimes int 1217a7a7d96cSPhilippe Charnier xdr_explist_common(XDR *xdrsp, caddr_t cp __unused, int brief) 12188fae3551SRodney W. Grimes { 12198fae3551SRodney W. Grimes struct exportlist *ep; 12208fae3551SRodney W. Grimes int false = 0; 1221a62dc406SDoug Rabson int putdef; 1222a62dc406SDoug Rabson sigset_t sighup_mask; 12238fae3551SRodney W. Grimes 1224a62dc406SDoug Rabson sigemptyset(&sighup_mask); 1225a62dc406SDoug Rabson sigaddset(&sighup_mask, SIGHUP); 1226a62dc406SDoug Rabson sigprocmask(SIG_BLOCK, &sighup_mask, NULL); 12278fae3551SRodney W. Grimes ep = exphead; 12288fae3551SRodney W. Grimes while (ep) { 12298fae3551SRodney W. Grimes putdef = 0; 123091acb349SAlfred Perlstein if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, 123191acb349SAlfred Perlstein &putdef, brief)) 12328fae3551SRodney W. Grimes goto errout; 12338fae3551SRodney W. Grimes if (ep->ex_defdir && putdef == 0 && 12348fae3551SRodney W. Grimes put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL, 123591acb349SAlfred Perlstein &putdef, brief)) 12368fae3551SRodney W. Grimes goto errout; 12378fae3551SRodney W. Grimes ep = ep->ex_next; 12388fae3551SRodney W. Grimes } 1239a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 12408fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 12418fae3551SRodney W. Grimes return (0); 12428fae3551SRodney W. Grimes return (1); 12438fae3551SRodney W. Grimes errout: 1244a62dc406SDoug Rabson sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); 12458fae3551SRodney W. Grimes return (0); 12468fae3551SRodney W. Grimes } 12478fae3551SRodney W. Grimes 12488fae3551SRodney W. Grimes /* 12498fae3551SRodney W. Grimes * Called from xdr_explist() to traverse the tree and export the 12508fae3551SRodney W. Grimes * directory paths. 12518fae3551SRodney W. Grimes */ 12528fae3551SRodney W. Grimes int 1253a7a7d96cSPhilippe Charnier put_exlist(struct dirlist *dp, XDR *xdrsp, struct dirlist *adp, int *putdefp, 1254a7a7d96cSPhilippe Charnier int brief) 12558fae3551SRodney W. Grimes { 12568fae3551SRodney W. Grimes struct grouplist *grp; 12578fae3551SRodney W. Grimes struct hostlist *hp; 12588fae3551SRodney W. Grimes int true = 1; 12598fae3551SRodney W. Grimes int false = 0; 12608fae3551SRodney W. Grimes int gotalldir = 0; 12618fae3551SRodney W. Grimes char *strp; 12628fae3551SRodney W. Grimes 12638fae3551SRodney W. Grimes if (dp) { 126491acb349SAlfred Perlstein if (put_exlist(dp->dp_left, xdrsp, adp, putdefp, brief)) 12658fae3551SRodney W. Grimes return (1); 12668fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 12678fae3551SRodney W. Grimes return (1); 12688fae3551SRodney W. Grimes strp = dp->dp_dirp; 12690775314bSDoug Rabson if (!xdr_string(xdrsp, &strp, MNTPATHLEN)) 12708fae3551SRodney W. Grimes return (1); 12718fae3551SRodney W. Grimes if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) { 12728fae3551SRodney W. Grimes gotalldir = 1; 12738fae3551SRodney W. Grimes *putdefp = 1; 12748fae3551SRodney W. Grimes } 127591acb349SAlfred Perlstein if (brief) { 127691acb349SAlfred Perlstein if (!xdr_bool(xdrsp, &true)) 127791acb349SAlfred Perlstein return (1); 127891acb349SAlfred Perlstein strp = "(...)"; 12790775314bSDoug Rabson if (!xdr_string(xdrsp, &strp, MNTPATHLEN)) 128091acb349SAlfred Perlstein return (1); 128191acb349SAlfred Perlstein } else if ((dp->dp_flag & DP_DEFSET) == 0 && 12828fae3551SRodney W. Grimes (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) { 12838fae3551SRodney W. Grimes hp = dp->dp_hosts; 12848fae3551SRodney W. Grimes while (hp) { 12858fae3551SRodney W. Grimes grp = hp->ht_grp; 12868fae3551SRodney W. Grimes if (grp->gr_type == GT_HOST) { 12878fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 12888fae3551SRodney W. Grimes return (1); 12898360efbdSAlfred Perlstein strp = grp->gr_ptr.gt_addrinfo->ai_canonname; 12908fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, 12910775314bSDoug Rabson MNTNAMLEN)) 12928fae3551SRodney W. Grimes return (1); 12938fae3551SRodney W. Grimes } else if (grp->gr_type == GT_NET) { 12948fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &true)) 12958fae3551SRodney W. Grimes return (1); 12968fae3551SRodney W. Grimes strp = grp->gr_ptr.gt_net.nt_name; 12978fae3551SRodney W. Grimes if (!xdr_string(xdrsp, &strp, 12980775314bSDoug Rabson MNTNAMLEN)) 12998fae3551SRodney W. Grimes return (1); 13008fae3551SRodney W. Grimes } 13018fae3551SRodney W. Grimes hp = hp->ht_next; 13028fae3551SRodney W. Grimes if (gotalldir && hp == (struct hostlist *)NULL) { 13038fae3551SRodney W. Grimes hp = adp->dp_hosts; 13048fae3551SRodney W. Grimes gotalldir = 0; 13058fae3551SRodney W. Grimes } 13068fae3551SRodney W. Grimes } 13078fae3551SRodney W. Grimes } 13088fae3551SRodney W. Grimes if (!xdr_bool(xdrsp, &false)) 13098fae3551SRodney W. Grimes return (1); 131091acb349SAlfred Perlstein if (put_exlist(dp->dp_right, xdrsp, adp, putdefp, brief)) 13118fae3551SRodney W. Grimes return (1); 13128fae3551SRodney W. Grimes } 13138fae3551SRodney W. Grimes return (0); 13148fae3551SRodney W. Grimes } 13158fae3551SRodney W. Grimes 131691acb349SAlfred Perlstein int 1317a7a7d96cSPhilippe Charnier xdr_explist(XDR *xdrsp, caddr_t cp) 131891acb349SAlfred Perlstein { 131991acb349SAlfred Perlstein 132091acb349SAlfred Perlstein return xdr_explist_common(xdrsp, cp, 0); 132191acb349SAlfred Perlstein } 132291acb349SAlfred Perlstein 132391acb349SAlfred Perlstein int 1324a7a7d96cSPhilippe Charnier xdr_explist_brief(XDR *xdrsp, caddr_t cp) 132591acb349SAlfred Perlstein { 132691acb349SAlfred Perlstein 132791acb349SAlfred Perlstein return xdr_explist_common(xdrsp, cp, 1); 132891acb349SAlfred Perlstein } 132991acb349SAlfred Perlstein 133091ca1a91SIan Dowse char *line; 133191ca1a91SIan Dowse int linesize; 13328fae3551SRodney W. Grimes FILE *exp_file; 13338fae3551SRodney W. Grimes 13348fae3551SRodney W. Grimes /* 133596968c22SPawel Jakub Dawidek * Get the export list from one, currently open file 13368fae3551SRodney W. Grimes */ 133796968c22SPawel Jakub Dawidek static void 1338a7a7d96cSPhilippe Charnier get_exportlist_one(void) 13398fae3551SRodney W. Grimes { 13408fae3551SRodney W. Grimes struct exportlist *ep, *ep2; 13418fae3551SRodney W. Grimes struct grouplist *grp, *tgrp; 13428fae3551SRodney W. Grimes struct exportlist **epp; 13438fae3551SRodney W. Grimes struct dirlist *dirhead; 134496968c22SPawel Jakub Dawidek struct statfs fsb; 1345c0511d3bSBrian Feldman struct xucred anon; 13468fae3551SRodney W. Grimes char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; 134796968c22SPawel Jakub Dawidek int len, has_host, exflags, got_nondir, dirplen, netgrp; 13488fae3551SRodney W. Grimes 1349bcc1d071SRick Macklem v4root_phase = 0; 13508fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 13518fae3551SRodney W. Grimes while (get_line()) { 13528fae3551SRodney W. Grimes if (debug) 135374853402SPhilippe Charnier warnx("got line %s", line); 13548fae3551SRodney W. Grimes cp = line; 13558fae3551SRodney W. Grimes nextfield(&cp, &endcp); 13568fae3551SRodney W. Grimes if (*cp == '#') 13578fae3551SRodney W. Grimes goto nextline; 13588fae3551SRodney W. Grimes 13598fae3551SRodney W. Grimes /* 13608fae3551SRodney W. Grimes * Set defaults. 13618fae3551SRodney W. Grimes */ 13628fae3551SRodney W. Grimes has_host = FALSE; 13638fae3551SRodney W. Grimes anon = def_anon; 13648fae3551SRodney W. Grimes exflags = MNT_EXPORTED; 13658fae3551SRodney W. Grimes got_nondir = 0; 13668fae3551SRodney W. Grimes opt_flags = 0; 13678fae3551SRodney W. Grimes ep = (struct exportlist *)NULL; 1368bcc1d071SRick Macklem dirp = NULL; 1369bcc1d071SRick Macklem 1370bcc1d071SRick Macklem /* 1371bcc1d071SRick Macklem * Handle the V4 root dir. 1372bcc1d071SRick Macklem */ 1373bcc1d071SRick Macklem if (*cp == 'V' && *(cp + 1) == '4' && *(cp + 2) == ':') { 1374bcc1d071SRick Macklem /* 1375bcc1d071SRick Macklem * V4: just indicates that it is the v4 root point, 1376bcc1d071SRick Macklem * so skip over that and set v4root_phase. 1377bcc1d071SRick Macklem */ 1378bcc1d071SRick Macklem if (v4root_phase > 0) { 1379bcc1d071SRick Macklem syslog(LOG_ERR, "V4:duplicate line, ignored"); 1380bcc1d071SRick Macklem goto nextline; 1381bcc1d071SRick Macklem } 1382bcc1d071SRick Macklem v4root_phase = 1; 1383bcc1d071SRick Macklem cp += 3; 1384bcc1d071SRick Macklem nextfield(&cp, &endcp); 1385bcc1d071SRick Macklem } 13868fae3551SRodney W. Grimes 13878fae3551SRodney W. Grimes /* 13888fae3551SRodney W. Grimes * Create new exports list entry 13898fae3551SRodney W. Grimes */ 13908fae3551SRodney W. Grimes len = endcp-cp; 13918fae3551SRodney W. Grimes tgrp = grp = get_grp(); 13928fae3551SRodney W. Grimes while (len > 0) { 13930775314bSDoug Rabson if (len > MNTNAMLEN) { 13948fae3551SRodney W. Grimes getexp_err(ep, tgrp); 13958fae3551SRodney W. Grimes goto nextline; 13968fae3551SRodney W. Grimes } 13978fae3551SRodney W. Grimes if (*cp == '-') { 13988fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 13998fae3551SRodney W. Grimes getexp_err(ep, tgrp); 14008fae3551SRodney W. Grimes goto nextline; 14018fae3551SRodney W. Grimes } 14028fae3551SRodney W. Grimes if (debug) 140374853402SPhilippe Charnier warnx("doing opt %s", cp); 14048fae3551SRodney W. Grimes got_nondir = 1; 14058fae3551SRodney W. Grimes if (do_opt(&cp, &endcp, ep, grp, &has_host, 14068fae3551SRodney W. Grimes &exflags, &anon)) { 14078fae3551SRodney W. Grimes getexp_err(ep, tgrp); 14088fae3551SRodney W. Grimes goto nextline; 14098fae3551SRodney W. Grimes } 14108fae3551SRodney W. Grimes } else if (*cp == '/') { 14118fae3551SRodney W. Grimes savedc = *endcp; 14128fae3551SRodney W. Grimes *endcp = '\0'; 1413bcc1d071SRick Macklem if (v4root_phase > 1) { 1414bcc1d071SRick Macklem if (dirp != NULL) { 1415bcc1d071SRick Macklem syslog(LOG_ERR, "Multiple V4 dirs"); 1416bcc1d071SRick Macklem getexp_err(ep, tgrp); 1417bcc1d071SRick Macklem goto nextline; 1418bcc1d071SRick Macklem } 1419bcc1d071SRick Macklem } 14208fae3551SRodney W. Grimes if (check_dirpath(cp) && 14218fae3551SRodney W. Grimes statfs(cp, &fsb) >= 0) { 14228fae3551SRodney W. Grimes if (got_nondir) { 142374853402SPhilippe Charnier syslog(LOG_ERR, "dirs must be first"); 14248fae3551SRodney W. Grimes getexp_err(ep, tgrp); 14258fae3551SRodney W. Grimes goto nextline; 14268fae3551SRodney W. Grimes } 1427bcc1d071SRick Macklem if (v4root_phase == 1) { 1428bcc1d071SRick Macklem if (dirp != NULL) { 1429bcc1d071SRick Macklem syslog(LOG_ERR, "Multiple V4 dirs"); 1430bcc1d071SRick Macklem getexp_err(ep, tgrp); 1431bcc1d071SRick Macklem goto nextline; 1432bcc1d071SRick Macklem } 1433bcc1d071SRick Macklem if (strlen(v4root_dirpath) == 0) { 1434bcc1d071SRick Macklem strlcpy(v4root_dirpath, cp, 1435bcc1d071SRick Macklem sizeof (v4root_dirpath)); 1436bcc1d071SRick Macklem } else if (strcmp(v4root_dirpath, cp) 1437bcc1d071SRick Macklem != 0) { 1438bcc1d071SRick Macklem syslog(LOG_ERR, 1439bcc1d071SRick Macklem "different V4 dirpath %s", cp); 1440bcc1d071SRick Macklem getexp_err(ep, tgrp); 1441bcc1d071SRick Macklem goto nextline; 1442bcc1d071SRick Macklem } 1443bcc1d071SRick Macklem dirp = cp; 1444bcc1d071SRick Macklem v4root_phase = 2; 1445bcc1d071SRick Macklem got_nondir = 1; 1446bcc1d071SRick Macklem ep = get_exp(); 1447bcc1d071SRick Macklem } else { 14488fae3551SRodney W. Grimes if (ep) { 1449bcc1d071SRick Macklem if (ep->ex_fs.val[0] != 1450bcc1d071SRick Macklem fsb.f_fsid.val[0] || 1451bcc1d071SRick Macklem ep->ex_fs.val[1] != 1452bcc1d071SRick Macklem fsb.f_fsid.val[1]) { 14538fae3551SRodney W. Grimes getexp_err(ep, tgrp); 14548fae3551SRodney W. Grimes goto nextline; 14558fae3551SRodney W. Grimes } 14568fae3551SRodney W. Grimes } else { 14578fae3551SRodney W. Grimes /* 14588fae3551SRodney W. Grimes * See if this directory is already 14598fae3551SRodney W. Grimes * in the list. 14608fae3551SRodney W. Grimes */ 14618fae3551SRodney W. Grimes ep = ex_search(&fsb.f_fsid); 14628fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 14638fae3551SRodney W. Grimes ep = get_exp(); 14648fae3551SRodney W. Grimes ep->ex_fs = fsb.f_fsid; 1465bcc1d071SRick Macklem ep->ex_fsdir = (char *)malloc 1466bcc1d071SRick Macklem (strlen(fsb.f_mntonname) + 1); 14678fae3551SRodney W. Grimes if (ep->ex_fsdir) 14688fae3551SRodney W. Grimes strcpy(ep->ex_fsdir, 14698fae3551SRodney W. Grimes fsb.f_mntonname); 14708fae3551SRodney W. Grimes else 14718fae3551SRodney W. Grimes out_of_mem(); 14728fae3551SRodney W. Grimes if (debug) 1473bcc1d071SRick Macklem warnx( 1474bcc1d071SRick Macklem "making new ep fs=0x%x,0x%x", 14758fae3551SRodney W. Grimes fsb.f_fsid.val[0], 14768fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 14778fae3551SRodney W. Grimes } else if (debug) 147874853402SPhilippe Charnier warnx("found ep fs=0x%x,0x%x", 14798fae3551SRodney W. Grimes fsb.f_fsid.val[0], 14808fae3551SRodney W. Grimes fsb.f_fsid.val[1]); 14818fae3551SRodney W. Grimes } 14828fae3551SRodney W. Grimes 14838fae3551SRodney W. Grimes /* 14848fae3551SRodney W. Grimes * Add dirpath to export mount point. 14858fae3551SRodney W. Grimes */ 14868fae3551SRodney W. Grimes dirp = add_expdir(&dirhead, cp, len); 14878fae3551SRodney W. Grimes dirplen = len; 1488bcc1d071SRick Macklem } 14898fae3551SRodney W. Grimes } else { 14908fae3551SRodney W. Grimes getexp_err(ep, tgrp); 14918fae3551SRodney W. Grimes goto nextline; 14928fae3551SRodney W. Grimes } 14938fae3551SRodney W. Grimes *endcp = savedc; 14948fae3551SRodney W. Grimes } else { 14958fae3551SRodney W. Grimes savedc = *endcp; 14968fae3551SRodney W. Grimes *endcp = '\0'; 14978fae3551SRodney W. Grimes got_nondir = 1; 14988fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) { 14998fae3551SRodney W. Grimes getexp_err(ep, tgrp); 15008fae3551SRodney W. Grimes goto nextline; 15018fae3551SRodney W. Grimes } 15028fae3551SRodney W. Grimes 15038fae3551SRodney W. Grimes /* 15048fae3551SRodney W. Grimes * Get the host or netgroup. 15058fae3551SRodney W. Grimes */ 15068fae3551SRodney W. Grimes setnetgrent(cp); 15078fae3551SRodney W. Grimes netgrp = getnetgrent(&hst, &usr, &dom); 15088fae3551SRodney W. Grimes do { 15098fae3551SRodney W. Grimes if (has_host) { 15108fae3551SRodney W. Grimes grp->gr_next = get_grp(); 15118fae3551SRodney W. Grimes grp = grp->gr_next; 15128fae3551SRodney W. Grimes } 15138fae3551SRodney W. Grimes if (netgrp) { 15149d70a156SJoerg Wunsch if (hst == 0) { 151574853402SPhilippe Charnier syslog(LOG_ERR, 151674853402SPhilippe Charnier "null hostname in netgroup %s, skipping", cp); 151701d48801SJoerg Wunsch grp->gr_type = GT_IGNORE; 15189d70a156SJoerg Wunsch } else if (get_host(hst, grp, tgrp)) { 151974853402SPhilippe Charnier syslog(LOG_ERR, 152074853402SPhilippe Charnier "bad host %s in netgroup %s, skipping", hst, cp); 1521a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 15228fae3551SRodney W. Grimes } 15238b5a6d67SBill Paul } else if (get_host(cp, grp, tgrp)) { 152474853402SPhilippe Charnier syslog(LOG_ERR, "bad host %s, skipping", cp); 1525a968cfd8SJonathan Lemon grp->gr_type = GT_IGNORE; 15268fae3551SRodney W. Grimes } 15278fae3551SRodney W. Grimes has_host = TRUE; 15288fae3551SRodney W. Grimes } while (netgrp && getnetgrent(&hst, &usr, &dom)); 15298fae3551SRodney W. Grimes endnetgrent(); 15308fae3551SRodney W. Grimes *endcp = savedc; 15318fae3551SRodney W. Grimes } 15328fae3551SRodney W. Grimes cp = endcp; 15338fae3551SRodney W. Grimes nextfield(&cp, &endcp); 15348fae3551SRodney W. Grimes len = endcp - cp; 15358fae3551SRodney W. Grimes } 15368fae3551SRodney W. Grimes if (check_options(dirhead)) { 15378fae3551SRodney W. Grimes getexp_err(ep, tgrp); 15388fae3551SRodney W. Grimes goto nextline; 15398fae3551SRodney W. Grimes } 15408fae3551SRodney W. Grimes if (!has_host) { 15416d359f31SIan Dowse grp->gr_type = GT_DEFAULT; 15428fae3551SRodney W. Grimes if (debug) 154374853402SPhilippe Charnier warnx("adding a default entry"); 15448fae3551SRodney W. Grimes 15458fae3551SRodney W. Grimes /* 15468fae3551SRodney W. Grimes * Don't allow a network export coincide with a list of 15478fae3551SRodney W. Grimes * host(s) on the same line. 15488fae3551SRodney W. Grimes */ 15498fae3551SRodney W. Grimes } else if ((opt_flags & OP_NET) && tgrp->gr_next) { 155060caaee2SIan Dowse syslog(LOG_ERR, "network/host conflict"); 15518fae3551SRodney W. Grimes getexp_err(ep, tgrp); 15528fae3551SRodney W. Grimes goto nextline; 1553a968cfd8SJonathan Lemon 1554a968cfd8SJonathan Lemon /* 1555a968cfd8SJonathan Lemon * If an export list was specified on this line, make sure 1556a968cfd8SJonathan Lemon * that we have at least one valid entry, otherwise skip it. 1557a968cfd8SJonathan Lemon */ 1558a968cfd8SJonathan Lemon } else { 1559a968cfd8SJonathan Lemon grp = tgrp; 1560a968cfd8SJonathan Lemon while (grp && grp->gr_type == GT_IGNORE) 1561a968cfd8SJonathan Lemon grp = grp->gr_next; 1562a968cfd8SJonathan Lemon if (! grp) { 1563a968cfd8SJonathan Lemon getexp_err(ep, tgrp); 1564a968cfd8SJonathan Lemon goto nextline; 1565a968cfd8SJonathan Lemon } 15668fae3551SRodney W. Grimes } 15678fae3551SRodney W. Grimes 1568bcc1d071SRick Macklem if (v4root_phase == 1) { 1569bcc1d071SRick Macklem syslog(LOG_ERR, "V4:root, no dirp, ignored"); 1570bcc1d071SRick Macklem getexp_err(ep, tgrp); 1571bcc1d071SRick Macklem goto nextline; 1572bcc1d071SRick Macklem } 1573bcc1d071SRick Macklem 15748fae3551SRodney W. Grimes /* 15758fae3551SRodney W. Grimes * Loop through hosts, pushing the exports into the kernel. 15768fae3551SRodney W. Grimes * After loop, tgrp points to the start of the list and 15778fae3551SRodney W. Grimes * grp points to the last entry in the list. 15788fae3551SRodney W. Grimes */ 15798fae3551SRodney W. Grimes grp = tgrp; 15808fae3551SRodney W. Grimes do { 158101709abfSIan Dowse if (do_mount(ep, grp, exflags, &anon, dirp, dirplen, 158201709abfSIan Dowse &fsb)) { 15838fae3551SRodney W. Grimes getexp_err(ep, tgrp); 15848fae3551SRodney W. Grimes goto nextline; 15858fae3551SRodney W. Grimes } 15868fae3551SRodney W. Grimes } while (grp->gr_next && (grp = grp->gr_next)); 15878fae3551SRodney W. Grimes 15888fae3551SRodney W. Grimes /* 1589bcc1d071SRick Macklem * For V4: don't enter in mount lists. 1590bcc1d071SRick Macklem */ 159173f4ccbdSRick Macklem if (v4root_phase > 0 && v4root_phase <= 2) { 159273f4ccbdSRick Macklem /* 159373f4ccbdSRick Macklem * Since these structures aren't used by mountd, 159473f4ccbdSRick Macklem * free them up now. 159573f4ccbdSRick Macklem */ 159673f4ccbdSRick Macklem if (ep != NULL) 159773f4ccbdSRick Macklem free_exp(ep); 159873f4ccbdSRick Macklem while (tgrp != NULL) { 159973f4ccbdSRick Macklem grp = tgrp; 160073f4ccbdSRick Macklem tgrp = tgrp->gr_next; 160173f4ccbdSRick Macklem free_grp(grp); 160273f4ccbdSRick Macklem } 1603bcc1d071SRick Macklem goto nextline; 160473f4ccbdSRick Macklem } 1605bcc1d071SRick Macklem 1606bcc1d071SRick Macklem /* 16078fae3551SRodney W. Grimes * Success. Update the data structures. 16088fae3551SRodney W. Grimes */ 16098fae3551SRodney W. Grimes if (has_host) { 1610a62dc406SDoug Rabson hang_dirp(dirhead, tgrp, ep, opt_flags); 16118fae3551SRodney W. Grimes grp->gr_next = grphead; 16128fae3551SRodney W. Grimes grphead = tgrp; 16138fae3551SRodney W. Grimes } else { 16148fae3551SRodney W. Grimes hang_dirp(dirhead, (struct grouplist *)NULL, ep, 1615a62dc406SDoug Rabson opt_flags); 16168fae3551SRodney W. Grimes free_grp(grp); 16178fae3551SRodney W. Grimes } 16188fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 16198fae3551SRodney W. Grimes if ((ep->ex_flag & EX_LINKED) == 0) { 16208fae3551SRodney W. Grimes ep2 = exphead; 16218fae3551SRodney W. Grimes epp = &exphead; 16228fae3551SRodney W. Grimes 16238fae3551SRodney W. Grimes /* 16248fae3551SRodney W. Grimes * Insert in the list in alphabetical order. 16258fae3551SRodney W. Grimes */ 16268fae3551SRodney W. Grimes while (ep2 && strcmp(ep2->ex_fsdir, ep->ex_fsdir) < 0) { 16278fae3551SRodney W. Grimes epp = &ep2->ex_next; 16288fae3551SRodney W. Grimes ep2 = ep2->ex_next; 16298fae3551SRodney W. Grimes } 16308fae3551SRodney W. Grimes if (ep2) 16318fae3551SRodney W. Grimes ep->ex_next = ep2; 16328fae3551SRodney W. Grimes *epp = ep; 16338fae3551SRodney W. Grimes ep->ex_flag |= EX_LINKED; 16348fae3551SRodney W. Grimes } 16358fae3551SRodney W. Grimes nextline: 1636bcc1d071SRick Macklem v4root_phase = 0; 16378fae3551SRodney W. Grimes if (dirhead) { 16388fae3551SRodney W. Grimes free_dir(dirhead); 16398fae3551SRodney W. Grimes dirhead = (struct dirlist *)NULL; 16408fae3551SRodney W. Grimes } 16418fae3551SRodney W. Grimes } 164296968c22SPawel Jakub Dawidek } 164396968c22SPawel Jakub Dawidek 164496968c22SPawel Jakub Dawidek /* 164596968c22SPawel Jakub Dawidek * Get the export list from all specified files 164696968c22SPawel Jakub Dawidek */ 164796968c22SPawel Jakub Dawidek void 1648a7a7d96cSPhilippe Charnier get_exportlist(void) 164996968c22SPawel Jakub Dawidek { 165096968c22SPawel Jakub Dawidek struct exportlist *ep, *ep2; 165196968c22SPawel Jakub Dawidek struct grouplist *grp, *tgrp; 165296968c22SPawel Jakub Dawidek struct export_args export; 165396968c22SPawel Jakub Dawidek struct iovec *iov; 165496968c22SPawel Jakub Dawidek struct statfs *fsp, *mntbufp; 165596968c22SPawel Jakub Dawidek struct xvfsconf vfc; 165696968c22SPawel Jakub Dawidek char errmsg[255]; 1657e0bcf086SEitan Adler int num, i; 165896968c22SPawel Jakub Dawidek int iovlen; 16596c90092bSPawel Jakub Dawidek int done; 1660bcc1d071SRick Macklem struct nfsex_args eargs; 166196968c22SPawel Jakub Dawidek 1662bcc1d071SRick Macklem v4root_dirpath[0] = '\0'; 166396968c22SPawel Jakub Dawidek bzero(&export, sizeof(export)); 166496968c22SPawel Jakub Dawidek export.ex_flags = MNT_DELEXPORT; 166596968c22SPawel Jakub Dawidek iov = NULL; 166696968c22SPawel Jakub Dawidek iovlen = 0; 166796968c22SPawel Jakub Dawidek bzero(errmsg, sizeof(errmsg)); 166896968c22SPawel Jakub Dawidek 166996968c22SPawel Jakub Dawidek /* 167096968c22SPawel Jakub Dawidek * First, get rid of the old list 167196968c22SPawel Jakub Dawidek */ 167296968c22SPawel Jakub Dawidek ep = exphead; 167396968c22SPawel Jakub Dawidek while (ep) { 167496968c22SPawel Jakub Dawidek ep2 = ep; 167596968c22SPawel Jakub Dawidek ep = ep->ex_next; 167696968c22SPawel Jakub Dawidek free_exp(ep2); 167796968c22SPawel Jakub Dawidek } 167896968c22SPawel Jakub Dawidek exphead = (struct exportlist *)NULL; 167996968c22SPawel Jakub Dawidek 168096968c22SPawel Jakub Dawidek grp = grphead; 168196968c22SPawel Jakub Dawidek while (grp) { 168296968c22SPawel Jakub Dawidek tgrp = grp; 168396968c22SPawel Jakub Dawidek grp = grp->gr_next; 168496968c22SPawel Jakub Dawidek free_grp(tgrp); 168596968c22SPawel Jakub Dawidek } 168696968c22SPawel Jakub Dawidek grphead = (struct grouplist *)NULL; 168796968c22SPawel Jakub Dawidek 168896968c22SPawel Jakub Dawidek /* 1689bcc1d071SRick Macklem * and the old V4 root dir. 1690bcc1d071SRick Macklem */ 1691bcc1d071SRick Macklem bzero(&eargs, sizeof (eargs)); 1692bcc1d071SRick Macklem eargs.export.ex_flags = MNT_DELEXPORT; 1693bcc1d071SRick Macklem if (run_v4server > 0 && 1694bcc1d071SRick Macklem nfssvc(NFSSVC_V4ROOTEXPORT, (caddr_t)&eargs) < 0 && 1695bcc1d071SRick Macklem errno != ENOENT) 1696bcc1d071SRick Macklem syslog(LOG_ERR, "Can't delete exports for V4:"); 1697bcc1d071SRick Macklem 1698bcc1d071SRick Macklem /* 1699bcc1d071SRick Macklem * and clear flag that notes if a public fh has been exported. 1700bcc1d071SRick Macklem */ 1701bcc1d071SRick Macklem has_publicfh = 0; 1702bcc1d071SRick Macklem 1703bcc1d071SRick Macklem /* 170496968c22SPawel Jakub Dawidek * And delete exports that are in the kernel for all local 170596968c22SPawel Jakub Dawidek * filesystems. 170696968c22SPawel Jakub Dawidek * XXX: Should know how to handle all local exportable filesystems. 170796968c22SPawel Jakub Dawidek */ 170896968c22SPawel Jakub Dawidek num = getmntinfo(&mntbufp, MNT_NOWAIT); 170996968c22SPawel Jakub Dawidek 171096968c22SPawel Jakub Dawidek if (num > 0) { 171196968c22SPawel Jakub Dawidek build_iovec(&iov, &iovlen, "fstype", NULL, 0); 171296968c22SPawel Jakub Dawidek build_iovec(&iov, &iovlen, "fspath", NULL, 0); 171396968c22SPawel Jakub Dawidek build_iovec(&iov, &iovlen, "from", NULL, 0); 171496968c22SPawel Jakub Dawidek build_iovec(&iov, &iovlen, "update", NULL, 0); 171596968c22SPawel Jakub Dawidek build_iovec(&iov, &iovlen, "export", &export, sizeof(export)); 171696968c22SPawel Jakub Dawidek build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); 171796968c22SPawel Jakub Dawidek } 171896968c22SPawel Jakub Dawidek 171996968c22SPawel Jakub Dawidek for (i = 0; i < num; i++) { 172096968c22SPawel Jakub Dawidek fsp = &mntbufp[i]; 172196968c22SPawel Jakub Dawidek if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) { 172296968c22SPawel Jakub Dawidek syslog(LOG_ERR, "getvfsbyname() failed for %s", 172396968c22SPawel Jakub Dawidek fsp->f_fstypename); 172496968c22SPawel Jakub Dawidek continue; 172596968c22SPawel Jakub Dawidek } 172696968c22SPawel Jakub Dawidek 172796968c22SPawel Jakub Dawidek /* 172896968c22SPawel Jakub Dawidek * Do not delete export for network filesystem by 172996968c22SPawel Jakub Dawidek * passing "export" arg to nmount(). 173096968c22SPawel Jakub Dawidek * It only makes sense to do this for local filesystems. 173196968c22SPawel Jakub Dawidek */ 173296968c22SPawel Jakub Dawidek if (vfc.vfc_flags & VFCF_NETWORK) 173396968c22SPawel Jakub Dawidek continue; 173496968c22SPawel Jakub Dawidek 173596968c22SPawel Jakub Dawidek iov[1].iov_base = fsp->f_fstypename; 173696968c22SPawel Jakub Dawidek iov[1].iov_len = strlen(fsp->f_fstypename) + 1; 173796968c22SPawel Jakub Dawidek iov[3].iov_base = fsp->f_mntonname; 173896968c22SPawel Jakub Dawidek iov[3].iov_len = strlen(fsp->f_mntonname) + 1; 173996968c22SPawel Jakub Dawidek iov[5].iov_base = fsp->f_mntfromname; 174096968c22SPawel Jakub Dawidek iov[5].iov_len = strlen(fsp->f_mntfromname) + 1; 174196968c22SPawel Jakub Dawidek 174296968c22SPawel Jakub Dawidek if (nmount(iov, iovlen, fsp->f_flags) < 0 && 174396968c22SPawel Jakub Dawidek errno != ENOENT && errno != ENOTSUP) { 174496968c22SPawel Jakub Dawidek syslog(LOG_ERR, 174596968c22SPawel Jakub Dawidek "can't delete exports for %s: %m %s", 174696968c22SPawel Jakub Dawidek fsp->f_mntonname, errmsg); 174796968c22SPawel Jakub Dawidek } 174896968c22SPawel Jakub Dawidek } 174996968c22SPawel Jakub Dawidek 175096968c22SPawel Jakub Dawidek if (iov != NULL) { 175196968c22SPawel Jakub Dawidek /* Free strings allocated by strdup() in getmntopts.c */ 175296968c22SPawel Jakub Dawidek free(iov[0].iov_base); /* fstype */ 175396968c22SPawel Jakub Dawidek free(iov[2].iov_base); /* fspath */ 175496968c22SPawel Jakub Dawidek free(iov[4].iov_base); /* from */ 175596968c22SPawel Jakub Dawidek free(iov[6].iov_base); /* update */ 175696968c22SPawel Jakub Dawidek free(iov[8].iov_base); /* export */ 175796968c22SPawel Jakub Dawidek free(iov[10].iov_base); /* errmsg */ 175896968c22SPawel Jakub Dawidek 175996968c22SPawel Jakub Dawidek /* free iov, allocated by realloc() */ 176096968c22SPawel Jakub Dawidek free(iov); 176196968c22SPawel Jakub Dawidek iovlen = 0; 176296968c22SPawel Jakub Dawidek } 176396968c22SPawel Jakub Dawidek 176496968c22SPawel Jakub Dawidek /* 176596968c22SPawel Jakub Dawidek * Read in the exports file and build the list, calling 176696968c22SPawel Jakub Dawidek * nmount() as we go along to push the export rules into the kernel. 176796968c22SPawel Jakub Dawidek */ 17686c90092bSPawel Jakub Dawidek done = 0; 176996968c22SPawel Jakub Dawidek for (i = 0; exnames[i] != NULL; i++) { 177096968c22SPawel Jakub Dawidek if (debug) 177196968c22SPawel Jakub Dawidek warnx("reading exports from %s", exnames[i]); 177296968c22SPawel Jakub Dawidek if ((exp_file = fopen(exnames[i], "r")) == NULL) { 17736c90092bSPawel Jakub Dawidek syslog(LOG_WARNING, "can't open %s", exnames[i]); 17746c90092bSPawel Jakub Dawidek continue; 177596968c22SPawel Jakub Dawidek } 177696968c22SPawel Jakub Dawidek get_exportlist_one(); 17778fae3551SRodney W. Grimes fclose(exp_file); 17786c90092bSPawel Jakub Dawidek done++; 17796c90092bSPawel Jakub Dawidek } 17806c90092bSPawel Jakub Dawidek if (done == 0) { 17816c90092bSPawel Jakub Dawidek syslog(LOG_ERR, "can't open any exports file"); 17826c90092bSPawel Jakub Dawidek exit(2); 17838fae3551SRodney W. Grimes } 1784bcc1d071SRick Macklem 1785bcc1d071SRick Macklem /* 1786bcc1d071SRick Macklem * If there was no public fh, clear any previous one set. 1787bcc1d071SRick Macklem */ 1788bcc1d071SRick Macklem if (run_v4server > 0 && has_publicfh == 0) 1789bcc1d071SRick Macklem (void) nfssvc(NFSSVC_NOPUBLICFH, NULL); 179096968c22SPawel Jakub Dawidek } 17918fae3551SRodney W. Grimes 17928fae3551SRodney W. Grimes /* 17938fae3551SRodney W. Grimes * Allocate an export list element 17948fae3551SRodney W. Grimes */ 17958fae3551SRodney W. Grimes struct exportlist * 1796a7a7d96cSPhilippe Charnier get_exp(void) 17978fae3551SRodney W. Grimes { 17988fae3551SRodney W. Grimes struct exportlist *ep; 17998fae3551SRodney W. Grimes 180053750151SXin LI ep = (struct exportlist *)calloc(1, sizeof (struct exportlist)); 18018fae3551SRodney W. Grimes if (ep == (struct exportlist *)NULL) 18028fae3551SRodney W. Grimes out_of_mem(); 18038fae3551SRodney W. Grimes return (ep); 18048fae3551SRodney W. Grimes } 18058fae3551SRodney W. Grimes 18068fae3551SRodney W. Grimes /* 18078fae3551SRodney W. Grimes * Allocate a group list element 18088fae3551SRodney W. Grimes */ 18098fae3551SRodney W. Grimes struct grouplist * 1810a7a7d96cSPhilippe Charnier get_grp(void) 18118fae3551SRodney W. Grimes { 18128fae3551SRodney W. Grimes struct grouplist *gp; 18138fae3551SRodney W. Grimes 181453750151SXin LI gp = (struct grouplist *)calloc(1, sizeof (struct grouplist)); 18158fae3551SRodney W. Grimes if (gp == (struct grouplist *)NULL) 18168fae3551SRodney W. Grimes out_of_mem(); 18178fae3551SRodney W. Grimes return (gp); 18188fae3551SRodney W. Grimes } 18198fae3551SRodney W. Grimes 18208fae3551SRodney W. Grimes /* 18218fae3551SRodney W. Grimes * Clean up upon an error in get_exportlist(). 18228fae3551SRodney W. Grimes */ 18238fae3551SRodney W. Grimes void 1824a7a7d96cSPhilippe Charnier getexp_err(struct exportlist *ep, struct grouplist *grp) 18258fae3551SRodney W. Grimes { 18268fae3551SRodney W. Grimes struct grouplist *tgrp; 18278fae3551SRodney W. Grimes 1828288fa14aSJoerg Wunsch if (!(opt_flags & OP_QUIET)) 182974853402SPhilippe Charnier syslog(LOG_ERR, "bad exports list line %s", line); 18308fae3551SRodney W. Grimes if (ep && (ep->ex_flag & EX_LINKED) == 0) 18318fae3551SRodney W. Grimes free_exp(ep); 18328fae3551SRodney W. Grimes while (grp) { 18338fae3551SRodney W. Grimes tgrp = grp; 18348fae3551SRodney W. Grimes grp = grp->gr_next; 18358fae3551SRodney W. Grimes free_grp(tgrp); 18368fae3551SRodney W. Grimes } 18378fae3551SRodney W. Grimes } 18388fae3551SRodney W. Grimes 18398fae3551SRodney W. Grimes /* 18408fae3551SRodney W. Grimes * Search the export list for a matching fs. 18418fae3551SRodney W. Grimes */ 18428fae3551SRodney W. Grimes struct exportlist * 1843a7a7d96cSPhilippe Charnier ex_search(fsid_t *fsid) 18448fae3551SRodney W. Grimes { 18458fae3551SRodney W. Grimes struct exportlist *ep; 18468fae3551SRodney W. Grimes 18478fae3551SRodney W. Grimes ep = exphead; 18488fae3551SRodney W. Grimes while (ep) { 18498fae3551SRodney W. Grimes if (ep->ex_fs.val[0] == fsid->val[0] && 18508fae3551SRodney W. Grimes ep->ex_fs.val[1] == fsid->val[1]) 18518fae3551SRodney W. Grimes return (ep); 18528fae3551SRodney W. Grimes ep = ep->ex_next; 18538fae3551SRodney W. Grimes } 18548fae3551SRodney W. Grimes return (ep); 18558fae3551SRodney W. Grimes } 18568fae3551SRodney W. Grimes 18578fae3551SRodney W. Grimes /* 18588fae3551SRodney W. Grimes * Add a directory path to the list. 18598fae3551SRodney W. Grimes */ 18608fae3551SRodney W. Grimes char * 1861a7a7d96cSPhilippe Charnier add_expdir(struct dirlist **dpp, char *cp, int len) 18628fae3551SRodney W. Grimes { 18638fae3551SRodney W. Grimes struct dirlist *dp; 18648fae3551SRodney W. Grimes 18658fae3551SRodney W. Grimes dp = (struct dirlist *)malloc(sizeof (struct dirlist) + len); 186674853402SPhilippe Charnier if (dp == (struct dirlist *)NULL) 186774853402SPhilippe Charnier out_of_mem(); 18688fae3551SRodney W. Grimes dp->dp_left = *dpp; 18698fae3551SRodney W. Grimes dp->dp_right = (struct dirlist *)NULL; 18708fae3551SRodney W. Grimes dp->dp_flag = 0; 18718fae3551SRodney W. Grimes dp->dp_hosts = (struct hostlist *)NULL; 18728fae3551SRodney W. Grimes strcpy(dp->dp_dirp, cp); 18738fae3551SRodney W. Grimes *dpp = dp; 18748fae3551SRodney W. Grimes return (dp->dp_dirp); 18758fae3551SRodney W. Grimes } 18768fae3551SRodney W. Grimes 18778fae3551SRodney W. Grimes /* 18788fae3551SRodney W. Grimes * Hang the dir list element off the dirpath binary tree as required 18798fae3551SRodney W. Grimes * and update the entry for host. 18808fae3551SRodney W. Grimes */ 18818fae3551SRodney W. Grimes void 1882a7a7d96cSPhilippe Charnier hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep, 1883a7a7d96cSPhilippe Charnier int flags) 18848fae3551SRodney W. Grimes { 18858fae3551SRodney W. Grimes struct hostlist *hp; 18868fae3551SRodney W. Grimes struct dirlist *dp2; 18878fae3551SRodney W. Grimes 1888a62dc406SDoug Rabson if (flags & OP_ALLDIRS) { 18898fae3551SRodney W. Grimes if (ep->ex_defdir) 18908fae3551SRodney W. Grimes free((caddr_t)dp); 18918fae3551SRodney W. Grimes else 18928fae3551SRodney W. Grimes ep->ex_defdir = dp; 1893a62dc406SDoug Rabson if (grp == (struct grouplist *)NULL) { 18948fae3551SRodney W. Grimes ep->ex_defdir->dp_flag |= DP_DEFSET; 1895*c3f86a25SRick Macklem /* Save the default security flavors list. */ 1896*c3f86a25SRick Macklem ep->ex_defnumsecflavors = ep->ex_numsecflavors; 1897*c3f86a25SRick Macklem if (ep->ex_numsecflavors > 0) 1898*c3f86a25SRick Macklem memcpy(ep->ex_defsecflavors, ep->ex_secflavors, 1899*c3f86a25SRick Macklem sizeof(ep->ex_secflavors)); 1900a62dc406SDoug Rabson } else while (grp) { 19018fae3551SRodney W. Grimes hp = get_ht(); 19028fae3551SRodney W. Grimes hp->ht_grp = grp; 19038fae3551SRodney W. Grimes hp->ht_next = ep->ex_defdir->dp_hosts; 19048fae3551SRodney W. Grimes ep->ex_defdir->dp_hosts = hp; 1905*c3f86a25SRick Macklem /* Save the security flavors list for this host set. */ 1906*c3f86a25SRick Macklem grp->gr_numsecflavors = ep->ex_numsecflavors; 1907*c3f86a25SRick Macklem if (ep->ex_numsecflavors > 0) 1908*c3f86a25SRick Macklem memcpy(grp->gr_secflavors, ep->ex_secflavors, 1909*c3f86a25SRick Macklem sizeof(ep->ex_secflavors)); 19108fae3551SRodney W. Grimes grp = grp->gr_next; 19118fae3551SRodney W. Grimes } 19128fae3551SRodney W. Grimes } else { 19138fae3551SRodney W. Grimes 19148fae3551SRodney W. Grimes /* 191574853402SPhilippe Charnier * Loop through the directories adding them to the tree. 19168fae3551SRodney W. Grimes */ 19178fae3551SRodney W. Grimes while (dp) { 19188fae3551SRodney W. Grimes dp2 = dp->dp_left; 1919*c3f86a25SRick Macklem add_dlist(&ep->ex_dirl, dp, grp, flags, ep); 19208fae3551SRodney W. Grimes dp = dp2; 19218fae3551SRodney W. Grimes } 19228fae3551SRodney W. Grimes } 19238fae3551SRodney W. Grimes } 19248fae3551SRodney W. Grimes 19258fae3551SRodney W. Grimes /* 19268fae3551SRodney W. Grimes * Traverse the binary tree either updating a node that is already there 19278fae3551SRodney W. Grimes * for the new directory or adding the new node. 19288fae3551SRodney W. Grimes */ 19298fae3551SRodney W. Grimes void 1930a7a7d96cSPhilippe Charnier add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp, 1931*c3f86a25SRick Macklem int flags, struct exportlist *ep) 19328fae3551SRodney W. Grimes { 19338fae3551SRodney W. Grimes struct dirlist *dp; 19348fae3551SRodney W. Grimes struct hostlist *hp; 19358fae3551SRodney W. Grimes int cmp; 19368fae3551SRodney W. Grimes 19378fae3551SRodney W. Grimes dp = *dpp; 19388fae3551SRodney W. Grimes if (dp) { 19398fae3551SRodney W. Grimes cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); 19408fae3551SRodney W. Grimes if (cmp > 0) { 1941*c3f86a25SRick Macklem add_dlist(&dp->dp_left, newdp, grp, flags, ep); 19428fae3551SRodney W. Grimes return; 19438fae3551SRodney W. Grimes } else if (cmp < 0) { 1944*c3f86a25SRick Macklem add_dlist(&dp->dp_right, newdp, grp, flags, ep); 19458fae3551SRodney W. Grimes return; 19468fae3551SRodney W. Grimes } else 19478fae3551SRodney W. Grimes free((caddr_t)newdp); 19488fae3551SRodney W. Grimes } else { 19498fae3551SRodney W. Grimes dp = newdp; 19508fae3551SRodney W. Grimes dp->dp_left = (struct dirlist *)NULL; 19518fae3551SRodney W. Grimes *dpp = dp; 19528fae3551SRodney W. Grimes } 19538fae3551SRodney W. Grimes if (grp) { 19548fae3551SRodney W. Grimes 19558fae3551SRodney W. Grimes /* 19568fae3551SRodney W. Grimes * Hang all of the host(s) off of the directory point. 19578fae3551SRodney W. Grimes */ 19588fae3551SRodney W. Grimes do { 19598fae3551SRodney W. Grimes hp = get_ht(); 19608fae3551SRodney W. Grimes hp->ht_grp = grp; 19618fae3551SRodney W. Grimes hp->ht_next = dp->dp_hosts; 19628fae3551SRodney W. Grimes dp->dp_hosts = hp; 1963*c3f86a25SRick Macklem /* Save the security flavors list for this host set. */ 1964*c3f86a25SRick Macklem grp->gr_numsecflavors = ep->ex_numsecflavors; 1965*c3f86a25SRick Macklem if (ep->ex_numsecflavors > 0) 1966*c3f86a25SRick Macklem memcpy(grp->gr_secflavors, ep->ex_secflavors, 1967*c3f86a25SRick Macklem sizeof(ep->ex_secflavors)); 19688fae3551SRodney W. Grimes grp = grp->gr_next; 19698fae3551SRodney W. Grimes } while (grp); 1970a62dc406SDoug Rabson } else { 19718fae3551SRodney W. Grimes dp->dp_flag |= DP_DEFSET; 1972*c3f86a25SRick Macklem /* Save the default security flavors list. */ 1973*c3f86a25SRick Macklem ep->ex_defnumsecflavors = ep->ex_numsecflavors; 1974*c3f86a25SRick Macklem if (ep->ex_numsecflavors > 0) 1975*c3f86a25SRick Macklem memcpy(ep->ex_defsecflavors, ep->ex_secflavors, 1976*c3f86a25SRick Macklem sizeof(ep->ex_secflavors)); 1977a62dc406SDoug Rabson } 19788fae3551SRodney W. Grimes } 19798fae3551SRodney W. Grimes 19808fae3551SRodney W. Grimes /* 19818fae3551SRodney W. Grimes * Search for a dirpath on the export point. 19828fae3551SRodney W. Grimes */ 19838fae3551SRodney W. Grimes struct dirlist * 1984a7a7d96cSPhilippe Charnier dirp_search(struct dirlist *dp, char *dirp) 19858fae3551SRodney W. Grimes { 19868fae3551SRodney W. Grimes int cmp; 19878fae3551SRodney W. Grimes 19888fae3551SRodney W. Grimes if (dp) { 19898360efbdSAlfred Perlstein cmp = strcmp(dp->dp_dirp, dirp); 19908fae3551SRodney W. Grimes if (cmp > 0) 19918360efbdSAlfred Perlstein return (dirp_search(dp->dp_left, dirp)); 19928fae3551SRodney W. Grimes else if (cmp < 0) 19938360efbdSAlfred Perlstein return (dirp_search(dp->dp_right, dirp)); 19948fae3551SRodney W. Grimes else 19958fae3551SRodney W. Grimes return (dp); 19968fae3551SRodney W. Grimes } 19978fae3551SRodney W. Grimes return (dp); 19988fae3551SRodney W. Grimes } 19998fae3551SRodney W. Grimes 20008fae3551SRodney W. Grimes /* 20018fae3551SRodney W. Grimes * Scan for a host match in a directory tree. 20028fae3551SRodney W. Grimes */ 20038fae3551SRodney W. Grimes int 2004a7a7d96cSPhilippe Charnier chk_host(struct dirlist *dp, struct sockaddr *saddr, int *defsetp, 2005*c3f86a25SRick Macklem int *hostsetp, int *numsecflavors, int **secflavorsp) 20068fae3551SRodney W. Grimes { 20078fae3551SRodney W. Grimes struct hostlist *hp; 20088fae3551SRodney W. Grimes struct grouplist *grp; 20098360efbdSAlfred Perlstein struct addrinfo *ai; 20108fae3551SRodney W. Grimes 20118fae3551SRodney W. Grimes if (dp) { 20128fae3551SRodney W. Grimes if (dp->dp_flag & DP_DEFSET) 2013a62dc406SDoug Rabson *defsetp = dp->dp_flag; 20148fae3551SRodney W. Grimes hp = dp->dp_hosts; 20158fae3551SRodney W. Grimes while (hp) { 20168fae3551SRodney W. Grimes grp = hp->ht_grp; 20178fae3551SRodney W. Grimes switch (grp->gr_type) { 20188fae3551SRodney W. Grimes case GT_HOST: 20198360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 20208360efbdSAlfred Perlstein for (; ai; ai = ai->ai_next) { 202160caaee2SIan Dowse if (!sacmp(ai->ai_addr, saddr, NULL)) { 20228360efbdSAlfred Perlstein *hostsetp = 20238360efbdSAlfred Perlstein (hp->ht_flag | DP_HOSTSET); 2024*c3f86a25SRick Macklem if (numsecflavors != NULL) { 2025*c3f86a25SRick Macklem *numsecflavors = 2026*c3f86a25SRick Macklem grp->gr_numsecflavors; 2027*c3f86a25SRick Macklem *secflavorsp = 2028*c3f86a25SRick Macklem grp->gr_secflavors; 2029*c3f86a25SRick Macklem } 20308fae3551SRodney W. Grimes return (1); 2031a62dc406SDoug Rabson } 20328fae3551SRodney W. Grimes } 20338fae3551SRodney W. Grimes break; 20348fae3551SRodney W. Grimes case GT_NET: 203560caaee2SIan Dowse if (!sacmp(saddr, (struct sockaddr *) 203660caaee2SIan Dowse &grp->gr_ptr.gt_net.nt_net, 203760caaee2SIan Dowse (struct sockaddr *) 203860caaee2SIan Dowse &grp->gr_ptr.gt_net.nt_mask)) { 2039a62dc406SDoug Rabson *hostsetp = (hp->ht_flag | DP_HOSTSET); 2040*c3f86a25SRick Macklem if (numsecflavors != NULL) { 2041*c3f86a25SRick Macklem *numsecflavors = 2042*c3f86a25SRick Macklem grp->gr_numsecflavors; 2043*c3f86a25SRick Macklem *secflavorsp = 2044*c3f86a25SRick Macklem grp->gr_secflavors; 2045*c3f86a25SRick Macklem } 20468fae3551SRodney W. Grimes return (1); 2047a62dc406SDoug Rabson } 20488fae3551SRodney W. Grimes break; 204960caaee2SIan Dowse } 20508fae3551SRodney W. Grimes hp = hp->ht_next; 20518fae3551SRodney W. Grimes } 20528fae3551SRodney W. Grimes } 20538fae3551SRodney W. Grimes return (0); 20548fae3551SRodney W. Grimes } 20558fae3551SRodney W. Grimes 20568fae3551SRodney W. Grimes /* 20578fae3551SRodney W. Grimes * Scan tree for a host that matches the address. 20588fae3551SRodney W. Grimes */ 20598fae3551SRodney W. Grimes int 2060a7a7d96cSPhilippe Charnier scan_tree(struct dirlist *dp, struct sockaddr *saddr) 20618fae3551SRodney W. Grimes { 2062a62dc406SDoug Rabson int defset, hostset; 20638fae3551SRodney W. Grimes 20648fae3551SRodney W. Grimes if (dp) { 20658fae3551SRodney W. Grimes if (scan_tree(dp->dp_left, saddr)) 20668fae3551SRodney W. Grimes return (1); 2067*c3f86a25SRick Macklem if (chk_host(dp, saddr, &defset, &hostset, NULL, NULL)) 20688fae3551SRodney W. Grimes return (1); 20698fae3551SRodney W. Grimes if (scan_tree(dp->dp_right, saddr)) 20708fae3551SRodney W. Grimes return (1); 20718fae3551SRodney W. Grimes } 20728fae3551SRodney W. Grimes return (0); 20738fae3551SRodney W. Grimes } 20748fae3551SRodney W. Grimes 20758fae3551SRodney W. Grimes /* 20768fae3551SRodney W. Grimes * Traverse the dirlist tree and free it up. 20778fae3551SRodney W. Grimes */ 20788fae3551SRodney W. Grimes void 2079a7a7d96cSPhilippe Charnier free_dir(struct dirlist *dp) 20808fae3551SRodney W. Grimes { 20818fae3551SRodney W. Grimes 20828fae3551SRodney W. Grimes if (dp) { 20838fae3551SRodney W. Grimes free_dir(dp->dp_left); 20848fae3551SRodney W. Grimes free_dir(dp->dp_right); 20858fae3551SRodney W. Grimes free_host(dp->dp_hosts); 20868fae3551SRodney W. Grimes free((caddr_t)dp); 20878fae3551SRodney W. Grimes } 20888fae3551SRodney W. Grimes } 20898fae3551SRodney W. Grimes 20908fae3551SRodney W. Grimes /* 2091a9148abdSDoug Rabson * Parse a colon separated list of security flavors 2092a9148abdSDoug Rabson */ 2093a9148abdSDoug Rabson int 2094a7a7d96cSPhilippe Charnier parsesec(char *seclist, struct exportlist *ep) 2095a9148abdSDoug Rabson { 2096a9148abdSDoug Rabson char *cp, savedc; 2097a9148abdSDoug Rabson int flavor; 2098a9148abdSDoug Rabson 2099a9148abdSDoug Rabson ep->ex_numsecflavors = 0; 2100a9148abdSDoug Rabson for (;;) { 2101a9148abdSDoug Rabson cp = strchr(seclist, ':'); 2102a9148abdSDoug Rabson if (cp) { 2103a9148abdSDoug Rabson savedc = *cp; 2104a9148abdSDoug Rabson *cp = '\0'; 2105a9148abdSDoug Rabson } 2106a9148abdSDoug Rabson 2107a9148abdSDoug Rabson if (!strcmp(seclist, "sys")) 2108a9148abdSDoug Rabson flavor = AUTH_SYS; 2109a9148abdSDoug Rabson else if (!strcmp(seclist, "krb5")) 2110a9148abdSDoug Rabson flavor = RPCSEC_GSS_KRB5; 2111a9148abdSDoug Rabson else if (!strcmp(seclist, "krb5i")) 2112a9148abdSDoug Rabson flavor = RPCSEC_GSS_KRB5I; 2113a9148abdSDoug Rabson else if (!strcmp(seclist, "krb5p")) 2114a9148abdSDoug Rabson flavor = RPCSEC_GSS_KRB5P; 2115a9148abdSDoug Rabson else { 2116a9148abdSDoug Rabson if (cp) 2117a9148abdSDoug Rabson *cp = savedc; 2118a9148abdSDoug Rabson syslog(LOG_ERR, "bad sec flavor: %s", seclist); 2119a9148abdSDoug Rabson return (1); 2120a9148abdSDoug Rabson } 2121a9148abdSDoug Rabson if (ep->ex_numsecflavors == MAXSECFLAVORS) { 2122a9148abdSDoug Rabson if (cp) 2123a9148abdSDoug Rabson *cp = savedc; 2124a9148abdSDoug Rabson syslog(LOG_ERR, "too many sec flavors: %s", seclist); 2125a9148abdSDoug Rabson return (1); 2126a9148abdSDoug Rabson } 2127a9148abdSDoug Rabson ep->ex_secflavors[ep->ex_numsecflavors] = flavor; 2128a9148abdSDoug Rabson ep->ex_numsecflavors++; 2129a9148abdSDoug Rabson if (cp) { 2130a9148abdSDoug Rabson *cp = savedc; 2131a9148abdSDoug Rabson seclist = cp + 1; 2132a9148abdSDoug Rabson } else { 2133a9148abdSDoug Rabson break; 2134a9148abdSDoug Rabson } 2135a9148abdSDoug Rabson } 2136a9148abdSDoug Rabson return (0); 2137a9148abdSDoug Rabson } 2138a9148abdSDoug Rabson 2139a9148abdSDoug Rabson /* 21408fae3551SRodney W. Grimes * Parse the option string and update fields. 21418fae3551SRodney W. Grimes * Option arguments may either be -<option>=<value> or 21428fae3551SRodney W. Grimes * -<option> <value> 21438fae3551SRodney W. Grimes */ 21448fae3551SRodney W. Grimes int 2145a7a7d96cSPhilippe Charnier do_opt(char **cpp, char **endcpp, struct exportlist *ep, struct grouplist *grp, 2146a7a7d96cSPhilippe Charnier int *has_hostp, int *exflagsp, struct xucred *cr) 21478fae3551SRodney W. Grimes { 21488fae3551SRodney W. Grimes char *cpoptarg, *cpoptend; 21498fae3551SRodney W. Grimes char *cp, *endcp, *cpopt, savedc, savedc2; 21508fae3551SRodney W. Grimes int allflag, usedarg; 21518fae3551SRodney W. Grimes 2152cb479b11SAlfred Perlstein savedc2 = '\0'; 21538fae3551SRodney W. Grimes cpopt = *cpp; 21548fae3551SRodney W. Grimes cpopt++; 21558fae3551SRodney W. Grimes cp = *endcpp; 21568fae3551SRodney W. Grimes savedc = *cp; 21578fae3551SRodney W. Grimes *cp = '\0'; 21588fae3551SRodney W. Grimes while (cpopt && *cpopt) { 21598fae3551SRodney W. Grimes allflag = 1; 21608fae3551SRodney W. Grimes usedarg = -2; 216174853402SPhilippe Charnier if ((cpoptend = strchr(cpopt, ','))) { 21628fae3551SRodney W. Grimes *cpoptend++ = '\0'; 216374853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 21648fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 21658fae3551SRodney W. Grimes } else { 216674853402SPhilippe Charnier if ((cpoptarg = strchr(cpopt, '='))) 21678fae3551SRodney W. Grimes *cpoptarg++ = '\0'; 21688fae3551SRodney W. Grimes else { 21698fae3551SRodney W. Grimes *cp = savedc; 21708fae3551SRodney W. Grimes nextfield(&cp, &endcp); 21718fae3551SRodney W. Grimes **endcpp = '\0'; 21728fae3551SRodney W. Grimes if (endcp > cp && *cp != '-') { 21738fae3551SRodney W. Grimes cpoptarg = cp; 21748fae3551SRodney W. Grimes savedc2 = *endcp; 21758fae3551SRodney W. Grimes *endcp = '\0'; 21768fae3551SRodney W. Grimes usedarg = 0; 21778fae3551SRodney W. Grimes } 21788fae3551SRodney W. Grimes } 21798fae3551SRodney W. Grimes } 21808fae3551SRodney W. Grimes if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 21818fae3551SRodney W. Grimes *exflagsp |= MNT_EXRDONLY; 21828fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "maproot") || 21838fae3551SRodney W. Grimes !(allflag = strcmp(cpopt, "mapall")) || 21848fae3551SRodney W. Grimes !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) { 21858fae3551SRodney W. Grimes usedarg++; 21868fae3551SRodney W. Grimes parsecred(cpoptarg, cr); 21878fae3551SRodney W. Grimes if (allflag == 0) { 21888fae3551SRodney W. Grimes *exflagsp |= MNT_EXPORTANON; 21898fae3551SRodney W. Grimes opt_flags |= OP_MAPALL; 21908fae3551SRodney W. Grimes } else 21918fae3551SRodney W. Grimes opt_flags |= OP_MAPROOT; 21928fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "mask") || 21938fae3551SRodney W. Grimes !strcmp(cpopt, "m"))) { 21948fae3551SRodney W. Grimes if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { 219574853402SPhilippe Charnier syslog(LOG_ERR, "bad mask: %s", cpoptarg); 21968fae3551SRodney W. Grimes return (1); 21978fae3551SRodney W. Grimes } 21988fae3551SRodney W. Grimes usedarg++; 21998fae3551SRodney W. Grimes opt_flags |= OP_MASK; 22008fae3551SRodney W. Grimes } else if (cpoptarg && (!strcmp(cpopt, "network") || 22018fae3551SRodney W. Grimes !strcmp(cpopt, "n"))) { 22028360efbdSAlfred Perlstein if (strchr(cpoptarg, '/') != NULL) { 22038360efbdSAlfred Perlstein if (debug) 22048360efbdSAlfred Perlstein fprintf(stderr, "setting OP_MASKLEN\n"); 22058360efbdSAlfred Perlstein opt_flags |= OP_MASKLEN; 22068360efbdSAlfred Perlstein } 22078fae3551SRodney W. Grimes if (grp->gr_type != GT_NULL) { 220874853402SPhilippe Charnier syslog(LOG_ERR, "network/host conflict"); 22098fae3551SRodney W. Grimes return (1); 22108fae3551SRodney W. Grimes } else if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 0)) { 221174853402SPhilippe Charnier syslog(LOG_ERR, "bad net: %s", cpoptarg); 22128fae3551SRodney W. Grimes return (1); 22138fae3551SRodney W. Grimes } 22148fae3551SRodney W. Grimes grp->gr_type = GT_NET; 22158fae3551SRodney W. Grimes *has_hostp = 1; 22168fae3551SRodney W. Grimes usedarg++; 22178fae3551SRodney W. Grimes opt_flags |= OP_NET; 22188fae3551SRodney W. Grimes } else if (!strcmp(cpopt, "alldirs")) { 22198fae3551SRodney W. Grimes opt_flags |= OP_ALLDIRS; 2220cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "public")) { 2221cb3923e0SDoug Rabson *exflagsp |= MNT_EXPUBLIC; 2222cb3923e0SDoug Rabson } else if (!strcmp(cpopt, "webnfs")) { 2223cb3923e0SDoug Rabson *exflagsp |= (MNT_EXPUBLIC|MNT_EXRDONLY|MNT_EXPORTANON); 2224cb3923e0SDoug Rabson opt_flags |= OP_MAPALL; 2225cb3923e0SDoug Rabson } else if (cpoptarg && !strcmp(cpopt, "index")) { 2226cb3923e0SDoug Rabson ep->ex_indexfile = strdup(cpoptarg); 2227288fa14aSJoerg Wunsch } else if (!strcmp(cpopt, "quiet")) { 2228288fa14aSJoerg Wunsch opt_flags |= OP_QUIET; 2229a9148abdSDoug Rabson } else if (!strcmp(cpopt, "sec")) { 2230a9148abdSDoug Rabson if (parsesec(cpoptarg, ep)) 2231a9148abdSDoug Rabson return (1); 2232a9148abdSDoug Rabson opt_flags |= OP_SEC; 2233a9148abdSDoug Rabson usedarg++; 22348fae3551SRodney W. Grimes } else { 223574853402SPhilippe Charnier syslog(LOG_ERR, "bad opt %s", cpopt); 22368fae3551SRodney W. Grimes return (1); 22378fae3551SRodney W. Grimes } 22388fae3551SRodney W. Grimes if (usedarg >= 0) { 22398fae3551SRodney W. Grimes *endcp = savedc2; 22408fae3551SRodney W. Grimes **endcpp = savedc; 22418fae3551SRodney W. Grimes if (usedarg > 0) { 22428fae3551SRodney W. Grimes *cpp = cp; 22438fae3551SRodney W. Grimes *endcpp = endcp; 22448fae3551SRodney W. Grimes } 22458fae3551SRodney W. Grimes return (0); 22468fae3551SRodney W. Grimes } 22478fae3551SRodney W. Grimes cpopt = cpoptend; 22488fae3551SRodney W. Grimes } 22498fae3551SRodney W. Grimes **endcpp = savedc; 22508fae3551SRodney W. Grimes return (0); 22518fae3551SRodney W. Grimes } 22528fae3551SRodney W. Grimes 22538fae3551SRodney W. Grimes /* 22548fae3551SRodney W. Grimes * Translate a character string to the corresponding list of network 22558fae3551SRodney W. Grimes * addresses for a hostname. 22568fae3551SRodney W. Grimes */ 22578fae3551SRodney W. Grimes int 2258a7a7d96cSPhilippe Charnier get_host(char *cp, struct grouplist *grp, struct grouplist *tgrp) 22598fae3551SRodney W. Grimes { 22608b5a6d67SBill Paul struct grouplist *checkgrp; 226101709abfSIan Dowse struct addrinfo *ai, *tai, hints; 22628360efbdSAlfred Perlstein int ecode; 22638360efbdSAlfred Perlstein char host[NI_MAXHOST]; 22648fae3551SRodney W. Grimes 22658360efbdSAlfred Perlstein if (grp->gr_type != GT_NULL) { 22668360efbdSAlfred Perlstein syslog(LOG_ERR, "Bad netgroup type for ip host %s", cp); 22678fae3551SRodney W. Grimes return (1); 22688fae3551SRodney W. Grimes } 22698360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 22708360efbdSAlfred Perlstein hints.ai_flags = AI_CANONNAME; 22718360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_UDP; 22728360efbdSAlfred Perlstein ecode = getaddrinfo(cp, NULL, &hints, &ai); 22738360efbdSAlfred Perlstein if (ecode != 0) { 227401709abfSIan Dowse syslog(LOG_ERR,"can't get address info for host %s", cp); 22758360efbdSAlfred Perlstein return 1; 22768fae3551SRodney W. Grimes } 22778360efbdSAlfred Perlstein grp->gr_ptr.gt_addrinfo = ai; 22788360efbdSAlfred Perlstein while (ai != NULL) { 22798360efbdSAlfred Perlstein if (ai->ai_canonname == NULL) { 22808360efbdSAlfred Perlstein if (getnameinfo(ai->ai_addr, ai->ai_addrlen, host, 22814f101318SHajimu UMEMOTO sizeof host, NULL, 0, NI_NUMERICHOST) != 0) 22828360efbdSAlfred Perlstein strlcpy(host, "?", sizeof(host)); 22838360efbdSAlfred Perlstein ai->ai_canonname = strdup(host); 22848360efbdSAlfred Perlstein ai->ai_flags |= AI_CANONNAME; 22856d359f31SIan Dowse } 22868fae3551SRodney W. Grimes if (debug) 228701709abfSIan Dowse fprintf(stderr, "got host %s\n", ai->ai_canonname); 228801709abfSIan Dowse /* 228901709abfSIan Dowse * Sanity check: make sure we don't already have an entry 229001709abfSIan Dowse * for this host in the grouplist. 229101709abfSIan Dowse */ 229201709abfSIan Dowse for (checkgrp = tgrp; checkgrp != NULL; 229301709abfSIan Dowse checkgrp = checkgrp->gr_next) { 229401709abfSIan Dowse if (checkgrp->gr_type != GT_HOST) 229501709abfSIan Dowse continue; 229601709abfSIan Dowse for (tai = checkgrp->gr_ptr.gt_addrinfo; tai != NULL; 229701709abfSIan Dowse tai = tai->ai_next) { 229860caaee2SIan Dowse if (sacmp(tai->ai_addr, ai->ai_addr, NULL) != 0) 229901709abfSIan Dowse continue; 230001709abfSIan Dowse if (debug) 230101709abfSIan Dowse fprintf(stderr, 230201709abfSIan Dowse "ignoring duplicate host %s\n", 230301709abfSIan Dowse ai->ai_canonname); 230401709abfSIan Dowse grp->gr_type = GT_IGNORE; 230501709abfSIan Dowse return (0); 230601709abfSIan Dowse } 230701709abfSIan Dowse } 23088360efbdSAlfred Perlstein ai = ai->ai_next; 23098360efbdSAlfred Perlstein } 231001709abfSIan Dowse grp->gr_type = GT_HOST; 23118fae3551SRodney W. Grimes return (0); 23128fae3551SRodney W. Grimes } 23138fae3551SRodney W. Grimes 23148fae3551SRodney W. Grimes /* 23158fae3551SRodney W. Grimes * Free up an exports list component 23168fae3551SRodney W. Grimes */ 23178fae3551SRodney W. Grimes void 2318a7a7d96cSPhilippe Charnier free_exp(struct exportlist *ep) 23198fae3551SRodney W. Grimes { 23208fae3551SRodney W. Grimes 23218fae3551SRodney W. Grimes if (ep->ex_defdir) { 23228fae3551SRodney W. Grimes free_host(ep->ex_defdir->dp_hosts); 23238fae3551SRodney W. Grimes free((caddr_t)ep->ex_defdir); 23248fae3551SRodney W. Grimes } 23258fae3551SRodney W. Grimes if (ep->ex_fsdir) 23268fae3551SRodney W. Grimes free(ep->ex_fsdir); 2327cb3923e0SDoug Rabson if (ep->ex_indexfile) 2328cb3923e0SDoug Rabson free(ep->ex_indexfile); 23298fae3551SRodney W. Grimes free_dir(ep->ex_dirl); 23308fae3551SRodney W. Grimes free((caddr_t)ep); 23318fae3551SRodney W. Grimes } 23328fae3551SRodney W. Grimes 23338fae3551SRodney W. Grimes /* 23348fae3551SRodney W. Grimes * Free hosts. 23358fae3551SRodney W. Grimes */ 23368fae3551SRodney W. Grimes void 2337a7a7d96cSPhilippe Charnier free_host(struct hostlist *hp) 23388fae3551SRodney W. Grimes { 23398fae3551SRodney W. Grimes struct hostlist *hp2; 23408fae3551SRodney W. Grimes 23418fae3551SRodney W. Grimes while (hp) { 23428fae3551SRodney W. Grimes hp2 = hp; 23438fae3551SRodney W. Grimes hp = hp->ht_next; 23448fae3551SRodney W. Grimes free((caddr_t)hp2); 23458fae3551SRodney W. Grimes } 23468fae3551SRodney W. Grimes } 23478fae3551SRodney W. Grimes 23488fae3551SRodney W. Grimes struct hostlist * 2349a7a7d96cSPhilippe Charnier get_ht(void) 23508fae3551SRodney W. Grimes { 23518fae3551SRodney W. Grimes struct hostlist *hp; 23528fae3551SRodney W. Grimes 23538fae3551SRodney W. Grimes hp = (struct hostlist *)malloc(sizeof (struct hostlist)); 23548fae3551SRodney W. Grimes if (hp == (struct hostlist *)NULL) 23558fae3551SRodney W. Grimes out_of_mem(); 23568fae3551SRodney W. Grimes hp->ht_next = (struct hostlist *)NULL; 2357a62dc406SDoug Rabson hp->ht_flag = 0; 23588fae3551SRodney W. Grimes return (hp); 23598fae3551SRodney W. Grimes } 23608fae3551SRodney W. Grimes 23618fae3551SRodney W. Grimes /* 23628fae3551SRodney W. Grimes * Out of memory, fatal 23638fae3551SRodney W. Grimes */ 23648fae3551SRodney W. Grimes void 2365a7a7d96cSPhilippe Charnier out_of_mem(void) 23668fae3551SRodney W. Grimes { 23678fae3551SRodney W. Grimes 236874853402SPhilippe Charnier syslog(LOG_ERR, "out of memory"); 23698fae3551SRodney W. Grimes exit(2); 23708fae3551SRodney W. Grimes } 23718fae3551SRodney W. Grimes 23728fae3551SRodney W. Grimes /* 23736a09faf2SCraig Rodrigues * Do the nmount() syscall with the update flag to push the export info into 23748fae3551SRodney W. Grimes * the kernel. 23758fae3551SRodney W. Grimes */ 23768fae3551SRodney W. Grimes int 23776a09faf2SCraig Rodrigues do_mount(struct exportlist *ep, struct grouplist *grp, int exflags, 23786a09faf2SCraig Rodrigues struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb) 23798fae3551SRodney W. Grimes { 2380f93caef2SIan Dowse struct statfs fsb1; 23818360efbdSAlfred Perlstein struct addrinfo *ai; 2382bcc1d071SRick Macklem struct export_args ea, *eap; 23836a09faf2SCraig Rodrigues char errmsg[255]; 23846a09faf2SCraig Rodrigues char *cp; 23858fae3551SRodney W. Grimes int done; 23866a09faf2SCraig Rodrigues char savedc; 23876a09faf2SCraig Rodrigues struct iovec *iov; 2388a9148abdSDoug Rabson int i, iovlen; 23896a09faf2SCraig Rodrigues int ret; 2390bcc1d071SRick Macklem struct nfsex_args nfsea; 2391bcc1d071SRick Macklem 2392bcc1d071SRick Macklem if (run_v4server > 0) 2393bcc1d071SRick Macklem eap = &nfsea.export; 2394bcc1d071SRick Macklem else 2395bcc1d071SRick Macklem eap = &ea; 23968fae3551SRodney W. Grimes 23976a09faf2SCraig Rodrigues cp = NULL; 23986a09faf2SCraig Rodrigues savedc = '\0'; 23996a09faf2SCraig Rodrigues iov = NULL; 24006a09faf2SCraig Rodrigues iovlen = 0; 24016a09faf2SCraig Rodrigues ret = 0; 240260caaee2SIan Dowse 2403bcc1d071SRick Macklem bzero(eap, sizeof (struct export_args)); 24046a09faf2SCraig Rodrigues bzero(errmsg, sizeof(errmsg)); 2405bcc1d071SRick Macklem eap->ex_flags = exflags; 2406bcc1d071SRick Macklem eap->ex_anon = *anoncrp; 2407bcc1d071SRick Macklem eap->ex_indexfile = ep->ex_indexfile; 24086d359f31SIan Dowse if (grp->gr_type == GT_HOST) 24098360efbdSAlfred Perlstein ai = grp->gr_ptr.gt_addrinfo; 24106d359f31SIan Dowse else 24116d359f31SIan Dowse ai = NULL; 2412bcc1d071SRick Macklem eap->ex_numsecflavors = ep->ex_numsecflavors; 2413bcc1d071SRick Macklem for (i = 0; i < eap->ex_numsecflavors; i++) 2414bcc1d071SRick Macklem eap->ex_secflavors[i] = ep->ex_secflavors[i]; 2415bcc1d071SRick Macklem if (eap->ex_numsecflavors == 0) { 2416bcc1d071SRick Macklem eap->ex_numsecflavors = 1; 2417bcc1d071SRick Macklem eap->ex_secflavors[0] = AUTH_SYS; 2418a9148abdSDoug Rabson } 24198fae3551SRodney W. Grimes done = FALSE; 24206a09faf2SCraig Rodrigues 2421bcc1d071SRick Macklem if (v4root_phase == 0) { 24226a09faf2SCraig Rodrigues build_iovec(&iov, &iovlen, "fstype", NULL, 0); 24236a09faf2SCraig Rodrigues build_iovec(&iov, &iovlen, "fspath", NULL, 0); 24246a09faf2SCraig Rodrigues build_iovec(&iov, &iovlen, "from", NULL, 0); 24256a09faf2SCraig Rodrigues build_iovec(&iov, &iovlen, "update", NULL, 0); 2426bcc1d071SRick Macklem build_iovec(&iov, &iovlen, "export", eap, 2427bcc1d071SRick Macklem sizeof (struct export_args)); 24286a09faf2SCraig Rodrigues build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); 2429bcc1d071SRick Macklem } 24306a09faf2SCraig Rodrigues 24318fae3551SRodney W. Grimes while (!done) { 24328fae3551SRodney W. Grimes switch (grp->gr_type) { 24338fae3551SRodney W. Grimes case GT_HOST: 24346d359f31SIan Dowse if (ai->ai_addr->sa_family == AF_INET6 && have_v6 == 0) 24358360efbdSAlfred Perlstein goto skip; 2436bcc1d071SRick Macklem eap->ex_addr = ai->ai_addr; 2437bcc1d071SRick Macklem eap->ex_addrlen = ai->ai_addrlen; 2438bcc1d071SRick Macklem eap->ex_masklen = 0; 24398fae3551SRodney W. Grimes break; 24408fae3551SRodney W. Grimes case GT_NET: 244160caaee2SIan Dowse if (grp->gr_ptr.gt_net.nt_net.ss_family == AF_INET6 && 24428360efbdSAlfred Perlstein have_v6 == 0) 24438360efbdSAlfred Perlstein goto skip; 2444bcc1d071SRick Macklem eap->ex_addr = 244560caaee2SIan Dowse (struct sockaddr *)&grp->gr_ptr.gt_net.nt_net; 2446bcc1d071SRick Macklem eap->ex_addrlen = 24476a09faf2SCraig Rodrigues ((struct sockaddr *)&grp->gr_ptr.gt_net.nt_net)->sa_len; 2448bcc1d071SRick Macklem eap->ex_mask = 244960caaee2SIan Dowse (struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask; 2450bcc1d071SRick Macklem eap->ex_masklen = ((struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask)->sa_len; 24518fae3551SRodney W. Grimes break; 24526d359f31SIan Dowse case GT_DEFAULT: 2453bcc1d071SRick Macklem eap->ex_addr = NULL; 2454bcc1d071SRick Macklem eap->ex_addrlen = 0; 2455bcc1d071SRick Macklem eap->ex_mask = NULL; 2456bcc1d071SRick Macklem eap->ex_masklen = 0; 24576d359f31SIan Dowse break; 24588b5a6d67SBill Paul case GT_IGNORE: 24596a09faf2SCraig Rodrigues ret = 0; 24606a09faf2SCraig Rodrigues goto error_exit; 24618b5a6d67SBill Paul break; 24628fae3551SRodney W. Grimes default: 246374853402SPhilippe Charnier syslog(LOG_ERR, "bad grouptype"); 24648fae3551SRodney W. Grimes if (cp) 24658fae3551SRodney W. Grimes *cp = savedc; 24666a09faf2SCraig Rodrigues ret = 1; 24676a09faf2SCraig Rodrigues goto error_exit; 24688fae3551SRodney W. Grimes }; 24698fae3551SRodney W. Grimes 24708fae3551SRodney W. Grimes /* 2471bcc1d071SRick Macklem * For V4:, use the nfssvc() syscall, instead of mount(). 2472bcc1d071SRick Macklem */ 2473bcc1d071SRick Macklem if (v4root_phase == 2) { 2474bcc1d071SRick Macklem nfsea.fspec = v4root_dirpath; 2475bcc1d071SRick Macklem if (run_v4server > 0 && 2476bcc1d071SRick Macklem nfssvc(NFSSVC_V4ROOTEXPORT, (caddr_t)&nfsea) < 0) { 2477bcc1d071SRick Macklem syslog(LOG_ERR, "Exporting V4: failed"); 2478bcc1d071SRick Macklem return (2); 2479bcc1d071SRick Macklem } 2480bcc1d071SRick Macklem } else { 2481bcc1d071SRick Macklem /* 24828fae3551SRodney W. Grimes * XXX: 2483bcc1d071SRick Macklem * Maybe I should just use the fsb->f_mntonname path 2484bcc1d071SRick Macklem * instead of looping back up the dirp to the mount 2485bcc1d071SRick Macklem * point?? 24868fae3551SRodney W. Grimes * Also, needs to know how to export all types of local 248787564113SPeter Wemm * exportable filesystems and not just "ufs". 24888fae3551SRodney W. Grimes */ 24896a09faf2SCraig Rodrigues iov[1].iov_base = fsb->f_fstypename; /* "fstype" */ 24906a09faf2SCraig Rodrigues iov[1].iov_len = strlen(fsb->f_fstypename) + 1; 24916a09faf2SCraig Rodrigues iov[3].iov_base = fsb->f_mntonname; /* "fspath" */ 24926a09faf2SCraig Rodrigues iov[3].iov_len = strlen(fsb->f_mntonname) + 1; 24936a09faf2SCraig Rodrigues iov[5].iov_base = fsb->f_mntfromname; /* "from" */ 24946a09faf2SCraig Rodrigues iov[5].iov_len = strlen(fsb->f_mntfromname) + 1; 24956a09faf2SCraig Rodrigues 249655dd1327SCraig Rodrigues while (nmount(iov, iovlen, fsb->f_flags) < 0) { 24978fae3551SRodney W. Grimes if (cp) 24988fae3551SRodney W. Grimes *cp-- = savedc; 24998fae3551SRodney W. Grimes else 25008fae3551SRodney W. Grimes cp = dirp + dirplen - 1; 25016a09faf2SCraig Rodrigues if (opt_flags & OP_QUIET) { 25026a09faf2SCraig Rodrigues ret = 1; 25036a09faf2SCraig Rodrigues goto error_exit; 25046a09faf2SCraig Rodrigues } 25058fae3551SRodney W. Grimes if (errno == EPERM) { 250601709abfSIan Dowse if (debug) 250777909162SXin LI warnx("can't change attributes for %s: %s", 250877909162SXin LI dirp, errmsg); 25098fae3551SRodney W. Grimes syslog(LOG_ERR, 251077909162SXin LI "can't change attributes for %s: %s", 251177909162SXin LI dirp, errmsg); 25126a09faf2SCraig Rodrigues ret = 1; 25136a09faf2SCraig Rodrigues goto error_exit; 25148fae3551SRodney W. Grimes } 25158fae3551SRodney W. Grimes if (opt_flags & OP_ALLDIRS) { 2516288fa14aSJoerg Wunsch if (errno == EINVAL) 2517288fa14aSJoerg Wunsch syslog(LOG_ERR, 2518288fa14aSJoerg Wunsch "-alldirs requested but %s is not a filesystem mountpoint", 2519288fa14aSJoerg Wunsch dirp); 2520288fa14aSJoerg Wunsch else 2521288fa14aSJoerg Wunsch syslog(LOG_ERR, 2522288fa14aSJoerg Wunsch "could not remount %s: %m", 25233980ac4fSGarrett Wollman dirp); 25246a09faf2SCraig Rodrigues ret = 1; 25256a09faf2SCraig Rodrigues goto error_exit; 25268fae3551SRodney W. Grimes } 25278fae3551SRodney W. Grimes /* back up over the last component */ 25288fae3551SRodney W. Grimes while (*cp == '/' && cp > dirp) 25298fae3551SRodney W. Grimes cp--; 25308fae3551SRodney W. Grimes while (*(cp - 1) != '/' && cp > dirp) 25318fae3551SRodney W. Grimes cp--; 25328fae3551SRodney W. Grimes if (cp == dirp) { 25338fae3551SRodney W. Grimes if (debug) 253474853402SPhilippe Charnier warnx("mnt unsucc"); 2535bcc1d071SRick Macklem syslog(LOG_ERR, "can't export %s %s", 2536bcc1d071SRick Macklem dirp, errmsg); 25376a09faf2SCraig Rodrigues ret = 1; 25386a09faf2SCraig Rodrigues goto error_exit; 25398fae3551SRodney W. Grimes } 25408fae3551SRodney W. Grimes savedc = *cp; 25418fae3551SRodney W. Grimes *cp = '\0'; 2542bcc1d071SRick Macklem /* 2543bcc1d071SRick Macklem * Check that we're still on the same 2544bcc1d071SRick Macklem * filesystem. 2545bcc1d071SRick Macklem */ 2546bcc1d071SRick Macklem if (statfs(dirp, &fsb1) != 0 || 2547bcc1d071SRick Macklem bcmp(&fsb1.f_fsid, &fsb->f_fsid, 2548bcc1d071SRick Macklem sizeof (fsb1.f_fsid)) != 0) { 2549f93caef2SIan Dowse *cp = savedc; 2550bcc1d071SRick Macklem syslog(LOG_ERR, 2551bcc1d071SRick Macklem "can't export %s %s", dirp, 255237518a88SCraig Rodrigues errmsg); 25536a09faf2SCraig Rodrigues ret = 1; 25546a09faf2SCraig Rodrigues goto error_exit; 2555f93caef2SIan Dowse } 25568fae3551SRodney W. Grimes } 2557bcc1d071SRick Macklem } 2558bcc1d071SRick Macklem 2559bcc1d071SRick Macklem /* 2560bcc1d071SRick Macklem * For the experimental server: 2561bcc1d071SRick Macklem * If this is the public directory, get the file handle 2562bcc1d071SRick Macklem * and load it into the kernel via the nfssvc() syscall. 2563bcc1d071SRick Macklem */ 2564bcc1d071SRick Macklem if (run_v4server > 0 && (exflags & MNT_EXPUBLIC) != 0) { 2565bcc1d071SRick Macklem fhandle_t fh; 2566bcc1d071SRick Macklem char *public_name; 2567bcc1d071SRick Macklem 2568bcc1d071SRick Macklem if (eap->ex_indexfile != NULL) 2569bcc1d071SRick Macklem public_name = eap->ex_indexfile; 2570bcc1d071SRick Macklem else 2571bcc1d071SRick Macklem public_name = dirp; 2572bcc1d071SRick Macklem if (getfh(public_name, &fh) < 0) 2573bcc1d071SRick Macklem syslog(LOG_ERR, 2574bcc1d071SRick Macklem "Can't get public fh for %s", public_name); 2575bcc1d071SRick Macklem else if (nfssvc(NFSSVC_PUBLICFH, (caddr_t)&fh) < 0) 2576bcc1d071SRick Macklem syslog(LOG_ERR, 2577bcc1d071SRick Macklem "Can't set public fh for %s", public_name); 2578bcc1d071SRick Macklem else 2579bcc1d071SRick Macklem has_publicfh = 1; 2580bcc1d071SRick Macklem } 25818360efbdSAlfred Perlstein skip: 25826d359f31SIan Dowse if (ai != NULL) 25838360efbdSAlfred Perlstein ai = ai->ai_next; 25848360efbdSAlfred Perlstein if (ai == NULL) 25858fae3551SRodney W. Grimes done = TRUE; 25868fae3551SRodney W. Grimes } 25878fae3551SRodney W. Grimes if (cp) 25888fae3551SRodney W. Grimes *cp = savedc; 25896a09faf2SCraig Rodrigues error_exit: 25906a09faf2SCraig Rodrigues /* free strings allocated by strdup() in getmntopts.c */ 25916a09faf2SCraig Rodrigues if (iov != NULL) { 25926a09faf2SCraig Rodrigues free(iov[0].iov_base); /* fstype */ 25936a09faf2SCraig Rodrigues free(iov[2].iov_base); /* fspath */ 25946a09faf2SCraig Rodrigues free(iov[4].iov_base); /* from */ 25956a09faf2SCraig Rodrigues free(iov[6].iov_base); /* update */ 25966a09faf2SCraig Rodrigues free(iov[8].iov_base); /* export */ 25976a09faf2SCraig Rodrigues free(iov[10].iov_base); /* errmsg */ 25986a09faf2SCraig Rodrigues 25996a09faf2SCraig Rodrigues /* free iov, allocated by realloc() */ 26006a09faf2SCraig Rodrigues free(iov); 26016a09faf2SCraig Rodrigues } 26026a09faf2SCraig Rodrigues return (ret); 26038fae3551SRodney W. Grimes } 26048fae3551SRodney W. Grimes 26058fae3551SRodney W. Grimes /* 26068fae3551SRodney W. Grimes * Translate a net address. 260760caaee2SIan Dowse * 260860caaee2SIan Dowse * If `maskflg' is nonzero, then `cp' is a netmask, not a network address. 26098fae3551SRodney W. Grimes */ 26108fae3551SRodney W. Grimes int 2611a7a7d96cSPhilippe Charnier get_net(char *cp, struct netmsk *net, int maskflg) 26128fae3551SRodney W. Grimes { 2613931c04f1SIan Dowse struct netent *np = NULL; 26148360efbdSAlfred Perlstein char *name, *p, *prefp; 261560caaee2SIan Dowse struct sockaddr_in sin; 2616931c04f1SIan Dowse struct sockaddr *sa = NULL; 26178360efbdSAlfred Perlstein struct addrinfo hints, *ai = NULL; 26188360efbdSAlfred Perlstein char netname[NI_MAXHOST]; 26198360efbdSAlfred Perlstein long preflen; 26208fae3551SRodney W. Grimes 262101709abfSIan Dowse p = prefp = NULL; 26228360efbdSAlfred Perlstein if ((opt_flags & OP_MASKLEN) && !maskflg) { 26238360efbdSAlfred Perlstein p = strchr(cp, '/'); 26248360efbdSAlfred Perlstein *p = '\0'; 26258360efbdSAlfred Perlstein prefp = p + 1; 26268360efbdSAlfred Perlstein } 26278360efbdSAlfred Perlstein 2628931c04f1SIan Dowse /* 2629931c04f1SIan Dowse * Check for a numeric address first. We wish to avoid 2630931c04f1SIan Dowse * possible DNS lookups in getnetbyname(). 2631931c04f1SIan Dowse */ 2632931c04f1SIan Dowse if (isxdigit(*cp) || *cp == ':') { 26338360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 263460caaee2SIan Dowse /* Ensure the mask and the network have the same family. */ 263560caaee2SIan Dowse if (maskflg && (opt_flags & OP_NET)) 263660caaee2SIan Dowse hints.ai_family = net->nt_net.ss_family; 263760caaee2SIan Dowse else if (!maskflg && (opt_flags & OP_HAVEMASK)) 263860caaee2SIan Dowse hints.ai_family = net->nt_mask.ss_family; 263960caaee2SIan Dowse else 26408360efbdSAlfred Perlstein hints.ai_family = AF_UNSPEC; 26418360efbdSAlfred Perlstein hints.ai_flags = AI_NUMERICHOST; 2642931c04f1SIan Dowse if (getaddrinfo(cp, NULL, &hints, &ai) == 0) 2643931c04f1SIan Dowse sa = ai->ai_addr; 2644931c04f1SIan Dowse if (sa != NULL && ai->ai_family == AF_INET) { 26458fae3551SRodney W. Grimes /* 264660caaee2SIan Dowse * The address in `cp' is really a network address, so 264760caaee2SIan Dowse * use inet_network() to re-interpret this correctly. 264860caaee2SIan Dowse * e.g. "127.1" means 127.1.0.0, not 127.0.0.1. 26498fae3551SRodney W. Grimes */ 265060caaee2SIan Dowse bzero(&sin, sizeof sin); 26518360efbdSAlfred Perlstein sin.sin_family = AF_INET; 26528360efbdSAlfred Perlstein sin.sin_len = sizeof sin; 26538360efbdSAlfred Perlstein sin.sin_addr = inet_makeaddr(inet_network(cp), 0); 26548360efbdSAlfred Perlstein if (debug) 265560caaee2SIan Dowse fprintf(stderr, "get_net: v4 addr %s\n", 265660caaee2SIan Dowse inet_ntoa(sin.sin_addr)); 26578360efbdSAlfred Perlstein sa = (struct sockaddr *)&sin; 2658931c04f1SIan Dowse } 2659931c04f1SIan Dowse } 2660931c04f1SIan Dowse if (sa == NULL && (np = getnetbyname(cp)) != NULL) { 2661931c04f1SIan Dowse bzero(&sin, sizeof sin); 2662931c04f1SIan Dowse sin.sin_family = AF_INET; 2663931c04f1SIan Dowse sin.sin_len = sizeof sin; 2664931c04f1SIan Dowse sin.sin_addr = inet_makeaddr(np->n_net, 0); 2665931c04f1SIan Dowse sa = (struct sockaddr *)&sin; 2666931c04f1SIan Dowse } 2667931c04f1SIan Dowse if (sa == NULL) 26688360efbdSAlfred Perlstein goto fail; 26698360efbdSAlfred Perlstein 267060caaee2SIan Dowse if (maskflg) { 267160caaee2SIan Dowse /* The specified sockaddr is a mask. */ 267260caaee2SIan Dowse if (checkmask(sa) != 0) 26738360efbdSAlfred Perlstein goto fail; 267460caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 267560caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 267660caaee2SIan Dowse } else { 267760caaee2SIan Dowse /* The specified sockaddr is a network address. */ 267860caaee2SIan Dowse bcopy(sa, &net->nt_net, sa->sa_len); 26790f4b7baaSPaul Traina 268060caaee2SIan Dowse /* Get a network name for the export list. */ 268160caaee2SIan Dowse if (np) { 268260caaee2SIan Dowse name = np->n_name; 268360caaee2SIan Dowse } else if (getnameinfo(sa, sa->sa_len, netname, sizeof netname, 26844f101318SHajimu UMEMOTO NULL, 0, NI_NUMERICHOST) == 0) { 268560caaee2SIan Dowse name = netname; 268660caaee2SIan Dowse } else { 268760caaee2SIan Dowse goto fail; 268860caaee2SIan Dowse } 268960caaee2SIan Dowse if ((net->nt_name = strdup(name)) == NULL) 269060caaee2SIan Dowse out_of_mem(); 269160caaee2SIan Dowse 269260caaee2SIan Dowse /* 269360caaee2SIan Dowse * Extract a mask from either a "/<masklen>" suffix, or 269460caaee2SIan Dowse * from the class of an IPv4 address. 269560caaee2SIan Dowse */ 26968360efbdSAlfred Perlstein if (opt_flags & OP_MASKLEN) { 26978360efbdSAlfred Perlstein preflen = strtol(prefp, NULL, 10); 269860caaee2SIan Dowse if (preflen < 0L || preflen == LONG_MAX) 26998360efbdSAlfred Perlstein goto fail; 270060caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 270160caaee2SIan Dowse if (makemask(&net->nt_mask, (int)preflen) != 0) 270260caaee2SIan Dowse goto fail; 270360caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 27048360efbdSAlfred Perlstein *p = '/'; 270560caaee2SIan Dowse } else if (sa->sa_family == AF_INET && 270660caaee2SIan Dowse (opt_flags & OP_MASK) == 0) { 270760caaee2SIan Dowse in_addr_t addr; 27088360efbdSAlfred Perlstein 270960caaee2SIan Dowse addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; 271060caaee2SIan Dowse if (IN_CLASSA(addr)) 271160caaee2SIan Dowse preflen = 8; 271260caaee2SIan Dowse else if (IN_CLASSB(addr)) 271360caaee2SIan Dowse preflen = 16; 271460caaee2SIan Dowse else if (IN_CLASSC(addr)) 271560caaee2SIan Dowse preflen = 24; 271660caaee2SIan Dowse else if (IN_CLASSD(addr)) 271760caaee2SIan Dowse preflen = 28; 27188360efbdSAlfred Perlstein else 271960caaee2SIan Dowse preflen = 32; /* XXX */ 272060caaee2SIan Dowse 272160caaee2SIan Dowse bcopy(sa, &net->nt_mask, sa->sa_len); 272260caaee2SIan Dowse makemask(&net->nt_mask, (int)preflen); 272360caaee2SIan Dowse opt_flags |= OP_HAVEMASK; 272460caaee2SIan Dowse } 27258360efbdSAlfred Perlstein } 27268360efbdSAlfred Perlstein 27278360efbdSAlfred Perlstein if (ai) 27288360efbdSAlfred Perlstein freeaddrinfo(ai); 27298360efbdSAlfred Perlstein return 0; 27308360efbdSAlfred Perlstein 27318360efbdSAlfred Perlstein fail: 27328360efbdSAlfred Perlstein if (ai) 27338360efbdSAlfred Perlstein freeaddrinfo(ai); 27348360efbdSAlfred Perlstein return 1; 27358fae3551SRodney W. Grimes } 27368fae3551SRodney W. Grimes 27378fae3551SRodney W. Grimes /* 27388fae3551SRodney W. Grimes * Parse out the next white space separated field 27398fae3551SRodney W. Grimes */ 27408fae3551SRodney W. Grimes void 2741a7a7d96cSPhilippe Charnier nextfield(char **cp, char **endcp) 27428fae3551SRodney W. Grimes { 27438fae3551SRodney W. Grimes char *p; 27448fae3551SRodney W. Grimes 27458fae3551SRodney W. Grimes p = *cp; 27468fae3551SRodney W. Grimes while (*p == ' ' || *p == '\t') 27478fae3551SRodney W. Grimes p++; 27488fae3551SRodney W. Grimes if (*p == '\n' || *p == '\0') 27498fae3551SRodney W. Grimes *cp = *endcp = p; 27508fae3551SRodney W. Grimes else { 27518fae3551SRodney W. Grimes *cp = p++; 27528fae3551SRodney W. Grimes while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 27538fae3551SRodney W. Grimes p++; 27548fae3551SRodney W. Grimes *endcp = p; 27558fae3551SRodney W. Grimes } 27568fae3551SRodney W. Grimes } 27578fae3551SRodney W. Grimes 27588fae3551SRodney W. Grimes /* 27598fae3551SRodney W. Grimes * Get an exports file line. Skip over blank lines and handle line 27608fae3551SRodney W. Grimes * continuations. 27618fae3551SRodney W. Grimes */ 27628fae3551SRodney W. Grimes int 2763a7a7d96cSPhilippe Charnier get_line(void) 27648fae3551SRodney W. Grimes { 27658fae3551SRodney W. Grimes char *p, *cp; 276691ca1a91SIan Dowse size_t len; 27678fae3551SRodney W. Grimes int totlen, cont_line; 27688fae3551SRodney W. Grimes 27698fae3551SRodney W. Grimes /* 27708fae3551SRodney W. Grimes * Loop around ignoring blank lines and getting all continuation lines. 27718fae3551SRodney W. Grimes */ 27728fae3551SRodney W. Grimes p = line; 27738fae3551SRodney W. Grimes totlen = 0; 27748fae3551SRodney W. Grimes do { 277591ca1a91SIan Dowse if ((p = fgetln(exp_file, &len)) == NULL) 27768fae3551SRodney W. Grimes return (0); 27778fae3551SRodney W. Grimes cp = p + len - 1; 27788fae3551SRodney W. Grimes cont_line = 0; 27798fae3551SRodney W. Grimes while (cp >= p && 27808fae3551SRodney W. Grimes (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '\\')) { 27818fae3551SRodney W. Grimes if (*cp == '\\') 27828fae3551SRodney W. Grimes cont_line = 1; 27838fae3551SRodney W. Grimes cp--; 27848fae3551SRodney W. Grimes len--; 27858fae3551SRodney W. Grimes } 2786376f8390SDima Dorfman if (cont_line) { 2787376f8390SDima Dorfman *++cp = ' '; 2788376f8390SDima Dorfman len++; 2789376f8390SDima Dorfman } 279091ca1a91SIan Dowse if (linesize < len + totlen + 1) { 279191ca1a91SIan Dowse linesize = len + totlen + 1; 279291ca1a91SIan Dowse line = realloc(line, linesize); 279391ca1a91SIan Dowse if (line == NULL) 279491ca1a91SIan Dowse out_of_mem(); 279591ca1a91SIan Dowse } 279691ca1a91SIan Dowse memcpy(line + totlen, p, len); 27978fae3551SRodney W. Grimes totlen += len; 279891ca1a91SIan Dowse line[totlen] = '\0'; 27998fae3551SRodney W. Grimes } while (totlen == 0 || cont_line); 28008fae3551SRodney W. Grimes return (1); 28018fae3551SRodney W. Grimes } 28028fae3551SRodney W. Grimes 28038fae3551SRodney W. Grimes /* 28048fae3551SRodney W. Grimes * Parse a description of a credential. 28058fae3551SRodney W. Grimes */ 28068fae3551SRodney W. Grimes void 2807a7a7d96cSPhilippe Charnier parsecred(char *namelist, struct xucred *cr) 28088fae3551SRodney W. Grimes { 28098fae3551SRodney W. Grimes char *name; 28108fae3551SRodney W. Grimes int cnt; 28118fae3551SRodney W. Grimes char *names; 28128fae3551SRodney W. Grimes struct passwd *pw; 28138fae3551SRodney W. Grimes struct group *gr; 2814838d9858SBrooks Davis gid_t groups[XU_NGROUPS + 1]; 2815950cc395SStefan Farfeleder int ngroups; 28168fae3551SRodney W. Grimes 281776183f34SDima Dorfman cr->cr_version = XUCRED_VERSION; 28188fae3551SRodney W. Grimes /* 281974853402SPhilippe Charnier * Set up the unprivileged user. 28208fae3551SRodney W. Grimes */ 28218fae3551SRodney W. Grimes cr->cr_uid = -2; 28228fae3551SRodney W. Grimes cr->cr_groups[0] = -2; 28238fae3551SRodney W. Grimes cr->cr_ngroups = 1; 28248fae3551SRodney W. Grimes /* 28258fae3551SRodney W. Grimes * Get the user's password table entry. 28268fae3551SRodney W. Grimes */ 28278fae3551SRodney W. Grimes names = strsep(&namelist, " \t\n"); 28288fae3551SRodney W. Grimes name = strsep(&names, ":"); 28298fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') 28308fae3551SRodney W. Grimes pw = getpwuid(atoi(name)); 28318fae3551SRodney W. Grimes else 28328fae3551SRodney W. Grimes pw = getpwnam(name); 28338fae3551SRodney W. Grimes /* 28348fae3551SRodney W. Grimes * Credentials specified as those of a user. 28358fae3551SRodney W. Grimes */ 28368fae3551SRodney W. Grimes if (names == NULL) { 28378fae3551SRodney W. Grimes if (pw == NULL) { 283874853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 28398fae3551SRodney W. Grimes return; 28408fae3551SRodney W. Grimes } 28418fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 2842838d9858SBrooks Davis ngroups = XU_NGROUPS + 1; 28438fae3551SRodney W. Grimes if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) 284474853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 28458fae3551SRodney W. Grimes /* 2846950cc395SStefan Farfeleder * Compress out duplicate. 28478fae3551SRodney W. Grimes */ 28488fae3551SRodney W. Grimes cr->cr_ngroups = ngroups - 1; 28498fae3551SRodney W. Grimes cr->cr_groups[0] = groups[0]; 28508fae3551SRodney W. Grimes for (cnt = 2; cnt < ngroups; cnt++) 28518fae3551SRodney W. Grimes cr->cr_groups[cnt - 1] = groups[cnt]; 28528fae3551SRodney W. Grimes return; 28538fae3551SRodney W. Grimes } 28548fae3551SRodney W. Grimes /* 28558fae3551SRodney W. Grimes * Explicit credential specified as a colon separated list: 28568fae3551SRodney W. Grimes * uid:gid:gid:... 28578fae3551SRodney W. Grimes */ 28588fae3551SRodney W. Grimes if (pw != NULL) 28598fae3551SRodney W. Grimes cr->cr_uid = pw->pw_uid; 28608fae3551SRodney W. Grimes else if (isdigit(*name) || *name == '-') 28618fae3551SRodney W. Grimes cr->cr_uid = atoi(name); 28628fae3551SRodney W. Grimes else { 286374853402SPhilippe Charnier syslog(LOG_ERR, "unknown user: %s", name); 28648fae3551SRodney W. Grimes return; 28658fae3551SRodney W. Grimes } 28668fae3551SRodney W. Grimes cr->cr_ngroups = 0; 2867838d9858SBrooks Davis while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) { 28688fae3551SRodney W. Grimes name = strsep(&names, ":"); 28698fae3551SRodney W. Grimes if (isdigit(*name) || *name == '-') { 28708fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = atoi(name); 28718fae3551SRodney W. Grimes } else { 28728fae3551SRodney W. Grimes if ((gr = getgrnam(name)) == NULL) { 287374853402SPhilippe Charnier syslog(LOG_ERR, "unknown group: %s", name); 28748fae3551SRodney W. Grimes continue; 28758fae3551SRodney W. Grimes } 28768fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; 28778fae3551SRodney W. Grimes } 28788fae3551SRodney W. Grimes } 2879838d9858SBrooks Davis if (names != NULL && *names != '\0' && cr->cr_ngroups == XU_NGROUPS) 288074853402SPhilippe Charnier syslog(LOG_ERR, "too many groups"); 28818fae3551SRodney W. Grimes } 28828fae3551SRodney W. Grimes 28830775314bSDoug Rabson #define STRSIZ (MNTNAMLEN+MNTPATHLEN+50) 28848fae3551SRodney W. Grimes /* 28858fae3551SRodney W. Grimes * Routines that maintain the remote mounttab 28868fae3551SRodney W. Grimes */ 28878fae3551SRodney W. Grimes void 2888a7a7d96cSPhilippe Charnier get_mountlist(void) 28898fae3551SRodney W. Grimes { 28908fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 289187564113SPeter Wemm char *host, *dirp, *cp; 28928fae3551SRodney W. Grimes char str[STRSIZ]; 28938fae3551SRodney W. Grimes FILE *mlfile; 28948fae3551SRodney W. Grimes 28958fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) { 289639539916SBill Fumerola if (errno == ENOENT) 289739539916SBill Fumerola return; 289839539916SBill Fumerola else { 289974853402SPhilippe Charnier syslog(LOG_ERR, "can't open %s", _PATH_RMOUNTLIST); 29008fae3551SRodney W. Grimes return; 29018fae3551SRodney W. Grimes } 290239539916SBill Fumerola } 29038fae3551SRodney W. Grimes mlpp = &mlhead; 29048fae3551SRodney W. Grimes while (fgets(str, STRSIZ, mlfile) != NULL) { 290587564113SPeter Wemm cp = str; 290687564113SPeter Wemm host = strsep(&cp, " \t\n"); 290787564113SPeter Wemm dirp = strsep(&cp, " \t\n"); 290887564113SPeter Wemm if (host == NULL || dirp == NULL) 29098fae3551SRodney W. Grimes continue; 29108fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 291174853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 291274853402SPhilippe Charnier out_of_mem(); 29130775314bSDoug Rabson strncpy(mlp->ml_host, host, MNTNAMLEN); 29140775314bSDoug Rabson mlp->ml_host[MNTNAMLEN] = '\0'; 29150775314bSDoug Rabson strncpy(mlp->ml_dirp, dirp, MNTPATHLEN); 29160775314bSDoug Rabson mlp->ml_dirp[MNTPATHLEN] = '\0'; 29178fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 29188fae3551SRodney W. Grimes *mlpp = mlp; 29198fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 29208fae3551SRodney W. Grimes } 29218fae3551SRodney W. Grimes fclose(mlfile); 29228fae3551SRodney W. Grimes } 29238fae3551SRodney W. Grimes 292401709abfSIan Dowse void 292501709abfSIan Dowse del_mlist(char *hostp, char *dirp) 29268fae3551SRodney W. Grimes { 29278fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 29288fae3551SRodney W. Grimes struct mountlist *mlp2; 29298fae3551SRodney W. Grimes FILE *mlfile; 29308fae3551SRodney W. Grimes int fnd = 0; 29318fae3551SRodney W. Grimes 29328fae3551SRodney W. Grimes mlpp = &mlhead; 29338fae3551SRodney W. Grimes mlp = mlhead; 29348fae3551SRodney W. Grimes while (mlp) { 29358fae3551SRodney W. Grimes if (!strcmp(mlp->ml_host, hostp) && 29368fae3551SRodney W. Grimes (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 29378fae3551SRodney W. Grimes fnd = 1; 29388fae3551SRodney W. Grimes mlp2 = mlp; 29398fae3551SRodney W. Grimes *mlpp = mlp = mlp->ml_next; 29408fae3551SRodney W. Grimes free((caddr_t)mlp2); 29418fae3551SRodney W. Grimes } else { 29428fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 29438fae3551SRodney W. Grimes mlp = mlp->ml_next; 29448fae3551SRodney W. Grimes } 29458fae3551SRodney W. Grimes } 29468fae3551SRodney W. Grimes if (fnd) { 29478fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 294874853402SPhilippe Charnier syslog(LOG_ERR,"can't update %s", _PATH_RMOUNTLIST); 29498fae3551SRodney W. Grimes return; 29508fae3551SRodney W. Grimes } 29518fae3551SRodney W. Grimes mlp = mlhead; 29528fae3551SRodney W. Grimes while (mlp) { 29538fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 29548fae3551SRodney W. Grimes mlp = mlp->ml_next; 29558fae3551SRodney W. Grimes } 29568fae3551SRodney W. Grimes fclose(mlfile); 29578fae3551SRodney W. Grimes } 29588fae3551SRodney W. Grimes } 29598fae3551SRodney W. Grimes 29608fae3551SRodney W. Grimes void 2961a7a7d96cSPhilippe Charnier add_mlist(char *hostp, char *dirp) 29628fae3551SRodney W. Grimes { 29638fae3551SRodney W. Grimes struct mountlist *mlp, **mlpp; 29648fae3551SRodney W. Grimes FILE *mlfile; 29658fae3551SRodney W. Grimes 29668fae3551SRodney W. Grimes mlpp = &mlhead; 29678fae3551SRodney W. Grimes mlp = mlhead; 29688fae3551SRodney W. Grimes while (mlp) { 29698fae3551SRodney W. Grimes if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 29708fae3551SRodney W. Grimes return; 29718fae3551SRodney W. Grimes mlpp = &mlp->ml_next; 29728fae3551SRodney W. Grimes mlp = mlp->ml_next; 29738fae3551SRodney W. Grimes } 29748fae3551SRodney W. Grimes mlp = (struct mountlist *)malloc(sizeof (*mlp)); 297574853402SPhilippe Charnier if (mlp == (struct mountlist *)NULL) 297674853402SPhilippe Charnier out_of_mem(); 29770775314bSDoug Rabson strncpy(mlp->ml_host, hostp, MNTNAMLEN); 29780775314bSDoug Rabson mlp->ml_host[MNTNAMLEN] = '\0'; 29790775314bSDoug Rabson strncpy(mlp->ml_dirp, dirp, MNTPATHLEN); 29800775314bSDoug Rabson mlp->ml_dirp[MNTPATHLEN] = '\0'; 29818fae3551SRodney W. Grimes mlp->ml_next = (struct mountlist *)NULL; 29828fae3551SRodney W. Grimes *mlpp = mlp; 29838fae3551SRodney W. Grimes if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 298474853402SPhilippe Charnier syslog(LOG_ERR, "can't update %s", _PATH_RMOUNTLIST); 29858fae3551SRodney W. Grimes return; 29868fae3551SRodney W. Grimes } 29878fae3551SRodney W. Grimes fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 29888fae3551SRodney W. Grimes fclose(mlfile); 29898fae3551SRodney W. Grimes } 29908fae3551SRodney W. Grimes 29918fae3551SRodney W. Grimes /* 29928fae3551SRodney W. Grimes * Free up a group list. 29938fae3551SRodney W. Grimes */ 29948fae3551SRodney W. Grimes void 2995a7a7d96cSPhilippe Charnier free_grp(struct grouplist *grp) 29968fae3551SRodney W. Grimes { 29978fae3551SRodney W. Grimes if (grp->gr_type == GT_HOST) { 29988360efbdSAlfred Perlstein if (grp->gr_ptr.gt_addrinfo != NULL) 29998360efbdSAlfred Perlstein freeaddrinfo(grp->gr_ptr.gt_addrinfo); 30008fae3551SRodney W. Grimes } else if (grp->gr_type == GT_NET) { 30018fae3551SRodney W. Grimes if (grp->gr_ptr.gt_net.nt_name) 30028fae3551SRodney W. Grimes free(grp->gr_ptr.gt_net.nt_name); 30038fae3551SRodney W. Grimes } 30048fae3551SRodney W. Grimes free((caddr_t)grp); 30058fae3551SRodney W. Grimes } 30068fae3551SRodney W. Grimes 30078fae3551SRodney W. Grimes #ifdef DEBUG 30088fae3551SRodney W. Grimes void 30098fae3551SRodney W. Grimes SYSLOG(int pri, const char *fmt, ...) 30108fae3551SRodney W. Grimes { 30118fae3551SRodney W. Grimes va_list ap; 30128fae3551SRodney W. Grimes 30138fae3551SRodney W. Grimes va_start(ap, fmt); 30148fae3551SRodney W. Grimes vfprintf(stderr, fmt, ap); 30158fae3551SRodney W. Grimes va_end(ap); 30168fae3551SRodney W. Grimes } 30178fae3551SRodney W. Grimes #endif /* DEBUG */ 30188fae3551SRodney W. Grimes 30198fae3551SRodney W. Grimes /* 30208fae3551SRodney W. Grimes * Check options for consistency. 30218fae3551SRodney W. Grimes */ 30228fae3551SRodney W. Grimes int 3023a7a7d96cSPhilippe Charnier check_options(struct dirlist *dp) 30248fae3551SRodney W. Grimes { 30258fae3551SRodney W. Grimes 3026bcc1d071SRick Macklem if (v4root_phase == 0 && dp == NULL) 30278fae3551SRodney W. Grimes return (1); 302891196234SPeter Wemm if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL)) { 302991196234SPeter Wemm syslog(LOG_ERR, "-mapall and -maproot mutually exclusive"); 30308fae3551SRodney W. Grimes return (1); 30318fae3551SRodney W. Grimes } 30328fae3551SRodney W. Grimes if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { 303360caaee2SIan Dowse syslog(LOG_ERR, "-mask requires -network"); 303460caaee2SIan Dowse return (1); 303560caaee2SIan Dowse } 303660caaee2SIan Dowse if ((opt_flags & OP_NET) && (opt_flags & OP_HAVEMASK) == 0) { 303760caaee2SIan Dowse syslog(LOG_ERR, "-network requires mask specification"); 303860caaee2SIan Dowse return (1); 303960caaee2SIan Dowse } 304060caaee2SIan Dowse if ((opt_flags & OP_MASK) && (opt_flags & OP_MASKLEN)) { 304160caaee2SIan Dowse syslog(LOG_ERR, "-mask and /masklen are mutually exclusive"); 30428fae3551SRodney W. Grimes return (1); 30438fae3551SRodney W. Grimes } 3044bcc1d071SRick Macklem if (v4root_phase > 0 && 3045bcc1d071SRick Macklem (opt_flags & 3046bcc1d071SRick Macklem ~(OP_SEC | OP_MASK | OP_NET | OP_HAVEMASK | OP_MASKLEN)) != 0) { 3047bcc1d071SRick Macklem syslog(LOG_ERR,"only -sec,-net,-mask options allowed on V4:"); 3048bcc1d071SRick Macklem return (1); 3049bcc1d071SRick Macklem } 305056cfc5edSRick Macklem if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { 305156cfc5edSRick Macklem syslog(LOG_ERR, "-alldirs has multiple directories"); 305256cfc5edSRick Macklem return (1); 305356cfc5edSRick Macklem } 30548fae3551SRodney W. Grimes return (0); 30558fae3551SRodney W. Grimes } 30568fae3551SRodney W. Grimes 30578fae3551SRodney W. Grimes /* 30588fae3551SRodney W. Grimes * Check an absolute directory path for any symbolic links. Return true 30598fae3551SRodney W. Grimes */ 30608fae3551SRodney W. Grimes int 3061a7a7d96cSPhilippe Charnier check_dirpath(char *dirp) 30628fae3551SRodney W. Grimes { 30638fae3551SRodney W. Grimes char *cp; 30648fae3551SRodney W. Grimes int ret = 1; 30658fae3551SRodney W. Grimes struct stat sb; 30668fae3551SRodney W. Grimes 30678fae3551SRodney W. Grimes cp = dirp + 1; 30688fae3551SRodney W. Grimes while (*cp && ret) { 30698fae3551SRodney W. Grimes if (*cp == '/') { 30708fae3551SRodney W. Grimes *cp = '\0'; 3071a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 30728fae3551SRodney W. Grimes ret = 0; 30738fae3551SRodney W. Grimes *cp = '/'; 30748fae3551SRodney W. Grimes } 30758fae3551SRodney W. Grimes cp++; 30768fae3551SRodney W. Grimes } 3077a62dc406SDoug Rabson if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 30788fae3551SRodney W. Grimes ret = 0; 30798fae3551SRodney W. Grimes return (ret); 30808fae3551SRodney W. Grimes } 3081a62dc406SDoug Rabson 308260caaee2SIan Dowse /* 308360caaee2SIan Dowse * Make a netmask according to the specified prefix length. The ss_family 308460caaee2SIan Dowse * and other non-address fields must be initialised before calling this. 308560caaee2SIan Dowse */ 308660caaee2SIan Dowse int 308760caaee2SIan Dowse makemask(struct sockaddr_storage *ssp, int bitlen) 30888360efbdSAlfred Perlstein { 308960caaee2SIan Dowse u_char *p; 309060caaee2SIan Dowse int bits, i, len; 30918360efbdSAlfred Perlstein 309260caaee2SIan Dowse if ((p = sa_rawaddr((struct sockaddr *)ssp, &len)) == NULL) 309360caaee2SIan Dowse return (-1); 309489fdc4e1SMike Barcroft if (bitlen > len * CHAR_BIT) 309560caaee2SIan Dowse return (-1); 30968360efbdSAlfred Perlstein 309760caaee2SIan Dowse for (i = 0; i < len; i++) { 309889fdc4e1SMike Barcroft bits = (bitlen > CHAR_BIT) ? CHAR_BIT : bitlen; 309958202d89SRuslan Ermilov *p++ = (u_char)~0 << (CHAR_BIT - bits); 310060caaee2SIan Dowse bitlen -= bits; 31018360efbdSAlfred Perlstein } 31028360efbdSAlfred Perlstein return 0; 31038360efbdSAlfred Perlstein } 31048360efbdSAlfred Perlstein 310560caaee2SIan Dowse /* 310660caaee2SIan Dowse * Check that the sockaddr is a valid netmask. Returns 0 if the mask 310760caaee2SIan Dowse * is acceptable (i.e. of the form 1...10....0). 310860caaee2SIan Dowse */ 310960caaee2SIan Dowse int 311060caaee2SIan Dowse checkmask(struct sockaddr *sa) 31118360efbdSAlfred Perlstein { 311260caaee2SIan Dowse u_char *mask; 311360caaee2SIan Dowse int i, len; 311460caaee2SIan Dowse 311560caaee2SIan Dowse if ((mask = sa_rawaddr(sa, &len)) == NULL) 311660caaee2SIan Dowse return (-1); 311760caaee2SIan Dowse 311860caaee2SIan Dowse for (i = 0; i < len; i++) 311960caaee2SIan Dowse if (mask[i] != 0xff) 312060caaee2SIan Dowse break; 312160caaee2SIan Dowse if (i < len) { 312260caaee2SIan Dowse if (~mask[i] & (u_char)(~mask[i] + 1)) 312360caaee2SIan Dowse return (-1); 312460caaee2SIan Dowse i++; 312560caaee2SIan Dowse } 312660caaee2SIan Dowse for (; i < len; i++) 312760caaee2SIan Dowse if (mask[i] != 0) 312860caaee2SIan Dowse return (-1); 312960caaee2SIan Dowse return (0); 313060caaee2SIan Dowse } 313160caaee2SIan Dowse 313260caaee2SIan Dowse /* 313360caaee2SIan Dowse * Compare two sockaddrs according to a specified mask. Return zero if 313460caaee2SIan Dowse * `sa1' matches `sa2' when filtered by the netmask in `samask'. 31353df5ecacSUlrich Spörlein * If samask is NULL, perform a full comparison. 313660caaee2SIan Dowse */ 313760caaee2SIan Dowse int 313860caaee2SIan Dowse sacmp(struct sockaddr *sa1, struct sockaddr *sa2, struct sockaddr *samask) 313960caaee2SIan Dowse { 314060caaee2SIan Dowse unsigned char *p1, *p2, *mask; 314160caaee2SIan Dowse int len, i; 314260caaee2SIan Dowse 314360caaee2SIan Dowse if (sa1->sa_family != sa2->sa_family || 314460caaee2SIan Dowse (p1 = sa_rawaddr(sa1, &len)) == NULL || 314560caaee2SIan Dowse (p2 = sa_rawaddr(sa2, NULL)) == NULL) 314660caaee2SIan Dowse return (1); 314760caaee2SIan Dowse 314860caaee2SIan Dowse switch (sa1->sa_family) { 314960caaee2SIan Dowse case AF_INET6: 315060caaee2SIan Dowse if (((struct sockaddr_in6 *)sa1)->sin6_scope_id != 315160caaee2SIan Dowse ((struct sockaddr_in6 *)sa2)->sin6_scope_id) 315260caaee2SIan Dowse return (1); 315360caaee2SIan Dowse break; 315460caaee2SIan Dowse } 315560caaee2SIan Dowse 315660caaee2SIan Dowse /* Simple binary comparison if no mask specified. */ 315760caaee2SIan Dowse if (samask == NULL) 315860caaee2SIan Dowse return (memcmp(p1, p2, len)); 315960caaee2SIan Dowse 316060caaee2SIan Dowse /* Set up the mask, and do a mask-based comparison. */ 316160caaee2SIan Dowse if (sa1->sa_family != samask->sa_family || 316260caaee2SIan Dowse (mask = sa_rawaddr(samask, NULL)) == NULL) 316360caaee2SIan Dowse return (1); 316460caaee2SIan Dowse 316560caaee2SIan Dowse for (i = 0; i < len; i++) 316660caaee2SIan Dowse if ((p1[i] & mask[i]) != (p2[i] & mask[i])) 316760caaee2SIan Dowse return (1); 316860caaee2SIan Dowse return (0); 316960caaee2SIan Dowse } 317060caaee2SIan Dowse 317160caaee2SIan Dowse /* 317260caaee2SIan Dowse * Return a pointer to the part of the sockaddr that contains the 317360caaee2SIan Dowse * raw address, and set *nbytes to its length in bytes. Returns 317460caaee2SIan Dowse * NULL if the address family is unknown. 317560caaee2SIan Dowse */ 317660caaee2SIan Dowse void * 317760caaee2SIan Dowse sa_rawaddr(struct sockaddr *sa, int *nbytes) { 317860caaee2SIan Dowse void *p; 317960caaee2SIan Dowse int len; 31808360efbdSAlfred Perlstein 31818360efbdSAlfred Perlstein switch (sa->sa_family) { 31828360efbdSAlfred Perlstein case AF_INET: 318360caaee2SIan Dowse len = sizeof(((struct sockaddr_in *)sa)->sin_addr); 318460caaee2SIan Dowse p = &((struct sockaddr_in *)sa)->sin_addr; 31858360efbdSAlfred Perlstein break; 31868360efbdSAlfred Perlstein case AF_INET6: 318760caaee2SIan Dowse len = sizeof(((struct sockaddr_in6 *)sa)->sin6_addr); 318860caaee2SIan Dowse p = &((struct sockaddr_in6 *)sa)->sin6_addr; 31898360efbdSAlfred Perlstein break; 31908360efbdSAlfred Perlstein default: 319160caaee2SIan Dowse p = NULL; 319260caaee2SIan Dowse len = 0; 31938360efbdSAlfred Perlstein } 31948360efbdSAlfred Perlstein 319560caaee2SIan Dowse if (nbytes != NULL) 319660caaee2SIan Dowse *nbytes = len; 319760caaee2SIan Dowse return (p); 31988360efbdSAlfred Perlstein } 31998360efbdSAlfred Perlstein 320069d65572SIan Dowse void 3201a7a7d96cSPhilippe Charnier huphandler(int sig __unused) 320269d65572SIan Dowse { 320369d65572SIan Dowse got_sighup = 1; 320469d65572SIan Dowse } 320569d65572SIan Dowse 3206a7a7d96cSPhilippe Charnier void terminate(int sig __unused) 32078360efbdSAlfred Perlstein { 3208a032b226SPawel Jakub Dawidek pidfile_remove(pfh); 32090775314bSDoug Rabson rpcb_unset(MOUNTPROG, MOUNTVERS, NULL); 32100775314bSDoug Rabson rpcb_unset(MOUNTPROG, MOUNTVERS3, NULL); 32118360efbdSAlfred Perlstein exit (0); 32128360efbdSAlfred Perlstein } 3213bcc1d071SRick Macklem 3214