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