xref: /minix3/tests/fs/nfs/nfsservice/nfsd.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: nfsd.c,v 1.5 2015/08/21 14:19:10 christos Exp $	*/
211be35a1SLionel Sambuc 
311be35a1SLionel Sambuc /*
411be35a1SLionel Sambuc  * Copyright (c) 1989, 1993, 1994
511be35a1SLionel Sambuc  *	The Regents of the University of California.  All rights reserved.
611be35a1SLionel Sambuc  *
711be35a1SLionel Sambuc  * This code is derived from software contributed to Berkeley by
811be35a1SLionel Sambuc  * Rick Macklem at The University of Guelph.
911be35a1SLionel Sambuc  *
1011be35a1SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
1111be35a1SLionel Sambuc  * modification, are permitted provided that the following conditions
1211be35a1SLionel Sambuc  * are met:
1311be35a1SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
1411be35a1SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
1511be35a1SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
1611be35a1SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
1711be35a1SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
1811be35a1SLionel Sambuc  * 3. Neither the name of the University nor the names of its contributors
1911be35a1SLionel Sambuc  *    may be used to endorse or promote products derived from this software
2011be35a1SLionel Sambuc  *    without specific prior written permission.
2111be35a1SLionel Sambuc  *
2211be35a1SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2311be35a1SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2411be35a1SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2511be35a1SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2611be35a1SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2711be35a1SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2811be35a1SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2911be35a1SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3011be35a1SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3111be35a1SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3211be35a1SLionel Sambuc  * SUCH DAMAGE.
3311be35a1SLionel Sambuc  */
3411be35a1SLionel Sambuc 
3511be35a1SLionel Sambuc #include <sys/cdefs.h>
3611be35a1SLionel Sambuc #ifndef lint
3711be35a1SLionel Sambuc __COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\
3811be35a1SLionel Sambuc  The Regents of the University of California.  All rights reserved.");
3911be35a1SLionel Sambuc #endif /* not lint */
4011be35a1SLionel Sambuc 
4111be35a1SLionel Sambuc #ifndef lint
4211be35a1SLionel Sambuc #if 0
4311be35a1SLionel Sambuc static char sccsid[] = "@(#)nfsd.c	8.9 (Berkeley) 3/29/95";
4411be35a1SLionel Sambuc #else
45*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: nfsd.c,v 1.5 2015/08/21 14:19:10 christos Exp $");
4611be35a1SLionel Sambuc #endif
4711be35a1SLionel Sambuc #endif /* not lint */
4811be35a1SLionel Sambuc 
4911be35a1SLionel Sambuc #include <sys/param.h>
5011be35a1SLionel Sambuc #include <sys/ioctl.h>
5111be35a1SLionel Sambuc #include <sys/stat.h>
5211be35a1SLionel Sambuc #include <sys/wait.h>
5311be35a1SLionel Sambuc #include <sys/uio.h>
5411be35a1SLionel Sambuc #include <sys/ucred.h>
5511be35a1SLionel Sambuc #include <sys/mount.h>
5611be35a1SLionel Sambuc #include <sys/socket.h>
5711be35a1SLionel Sambuc #include <sys/socketvar.h>
5811be35a1SLionel Sambuc #include <poll.h>
5911be35a1SLionel Sambuc 
6011be35a1SLionel Sambuc #include <rpc/rpc.h>
6111be35a1SLionel Sambuc #include <rpc/pmap_clnt.h>
6211be35a1SLionel Sambuc #include <rpc/pmap_prot.h>
6311be35a1SLionel Sambuc 
6411be35a1SLionel Sambuc #include <nfs/rpcv2.h>
6511be35a1SLionel Sambuc #include <nfs/nfsproto.h>
6611be35a1SLionel Sambuc #include <nfs/nfs.h>
6711be35a1SLionel Sambuc 
6811be35a1SLionel Sambuc #include <err.h>
6911be35a1SLionel Sambuc #include <errno.h>
7011be35a1SLionel Sambuc #include <fcntl.h>
7111be35a1SLionel Sambuc #include <grp.h>
7211be35a1SLionel Sambuc #include <pwd.h>
7311be35a1SLionel Sambuc #include <pthread.h>
7411be35a1SLionel Sambuc #include <signal.h>
7511be35a1SLionel Sambuc #include <stdio.h>
7611be35a1SLionel Sambuc #include <stdlib.h>
7711be35a1SLionel Sambuc #include <string.h>
7811be35a1SLionel Sambuc #include <syslog.h>
7911be35a1SLionel Sambuc #include <unistd.h>
8011be35a1SLionel Sambuc #include <netdb.h>
8111be35a1SLionel Sambuc 
8211be35a1SLionel Sambuc #include <rump/rump.h>
8311be35a1SLionel Sambuc #include <rump/rump_syscalls.h>
8411be35a1SLionel Sambuc 
8511be35a1SLionel Sambuc /* Global defs */
8611be35a1SLionel Sambuc #ifdef DEBUG
8711be35a1SLionel Sambuc #define	syslog(e, s, args...)						\
8811be35a1SLionel Sambuc do {									\
8911be35a1SLionel Sambuc     fprintf(stderr,(s), ## args); 					\
9011be35a1SLionel Sambuc     fprintf(stderr, "\n");						\
9111be35a1SLionel Sambuc } while (/*CONSTCOND*/0)
9211be35a1SLionel Sambuc int	debug = 1;
9311be35a1SLionel Sambuc #else
9411be35a1SLionel Sambuc int	debug = 0;
9511be35a1SLionel Sambuc #endif
9611be35a1SLionel Sambuc 
97*0a6a1f1dSLionel Sambuc void	nonfs(int);
98*0a6a1f1dSLionel Sambuc void	usage(void);
9911be35a1SLionel Sambuc 
10011be35a1SLionel Sambuc static void *
child(void * arg)10111be35a1SLionel Sambuc child(void *arg)
10211be35a1SLionel Sambuc {
10311be35a1SLionel Sambuc 	struct	nfsd_srvargs nsd;
10411be35a1SLionel Sambuc 	int nfssvc_flag;
10511be35a1SLionel Sambuc 
10611be35a1SLionel Sambuc 	nfssvc_flag = NFSSVC_NFSD;
10711be35a1SLionel Sambuc 	memset(&nsd, 0, sizeof(nsd));
10811be35a1SLionel Sambuc 	while (rump_sys_nfssvc(nfssvc_flag, &nsd) < 0) {
10911be35a1SLionel Sambuc 		if (errno != ENEEDAUTH) {
110*0a6a1f1dSLionel Sambuc 			syslog(LOG_ERR, "nfssvc (%s)", strerror(errno));
11111be35a1SLionel Sambuc 			exit(1);
11211be35a1SLionel Sambuc 		}
11311be35a1SLionel Sambuc 		nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
11411be35a1SLionel Sambuc 	}
11511be35a1SLionel Sambuc 
11611be35a1SLionel Sambuc 	return NULL;
11711be35a1SLionel Sambuc }
11811be35a1SLionel Sambuc 
11911be35a1SLionel Sambuc /*
12011be35a1SLionel Sambuc  * Nfs server daemon mostly just a user context for nfssvc()
12111be35a1SLionel Sambuc  *
12211be35a1SLionel Sambuc  * 1 - do file descriptor and signal cleanup
12311be35a1SLionel Sambuc  * 2 - create the nfsd thread(s)
12411be35a1SLionel Sambuc  * 3 - create server socket(s)
12511be35a1SLionel Sambuc  * 4 - register socket with portmap
12611be35a1SLionel Sambuc  *
12711be35a1SLionel Sambuc  * For connectionless protocols, just pass the socket into the kernel via
12811be35a1SLionel Sambuc  * nfssvc().
12911be35a1SLionel Sambuc  * For connection based sockets, loop doing accepts. When you get a new
13011be35a1SLionel Sambuc  * socket from accept, pass the msgsock into the kernel via nfssvc().
13111be35a1SLionel Sambuc  * The arguments are:
13211be35a1SLionel Sambuc  *	-c - support iso cltp clients
13311be35a1SLionel Sambuc  *	-r - reregister with portmapper
13411be35a1SLionel Sambuc  *	-t - support tcp nfs clients
13511be35a1SLionel Sambuc  *	-u - support udp nfs clients
13611be35a1SLionel Sambuc  * followed by "n" which is the number of nfsd threads to create
13711be35a1SLionel Sambuc  */
13811be35a1SLionel Sambuc int nfsd_main(int, char**);
13911be35a1SLionel Sambuc int
nfsd_main(argc,argv)14011be35a1SLionel Sambuc nfsd_main(argc, argv)
14111be35a1SLionel Sambuc 	int argc;
14211be35a1SLionel Sambuc 	char *argv[];
14311be35a1SLionel Sambuc {
14411be35a1SLionel Sambuc 	struct nfsd_args nfsdargs;
14511be35a1SLionel Sambuc 	struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
14611be35a1SLionel Sambuc 	struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
14711be35a1SLionel Sambuc 	struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
14811be35a1SLionel Sambuc 	struct sockaddr_in inetpeer;
14911be35a1SLionel Sambuc 	struct pollfd set[4];
15011be35a1SLionel Sambuc 	socklen_t len;
15184d9c625SLionel Sambuc 	int ch, connect_type_cnt, i, msgsock;
15211be35a1SLionel Sambuc 	int nfsdcnt, on = 1, reregister, sock, tcpflag, tcpsock;
15311be35a1SLionel Sambuc 	int tcp6sock, ip6flag;
15484d9c625SLionel Sambuc 	int tp4cnt, tp4flag, tpipcnt, udpflag, ecode, s;
15511be35a1SLionel Sambuc 
15611be35a1SLionel Sambuc #define	DEFNFSDCNT	 4
15711be35a1SLionel Sambuc 	nfsdcnt = DEFNFSDCNT;
15884d9c625SLionel Sambuc 	reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
15984d9c625SLionel Sambuc 	udpflag = ip6flag = 0;
16011be35a1SLionel Sambuc 	nconf_udp = nconf_tcp = nconf_udp6 = nconf_tcp6 = NULL;
16111be35a1SLionel Sambuc 	tcpsock = tcp6sock = -1;
16211be35a1SLionel Sambuc #define	GETOPT	"6n:rtu"
16311be35a1SLionel Sambuc #define	USAGE	"[-rtu] [-n num_servers]"
16411be35a1SLionel Sambuc 	while ((ch = getopt(argc, argv, GETOPT)) != -1) {
16511be35a1SLionel Sambuc 		switch (ch) {
16611be35a1SLionel Sambuc 		case '6':
16711be35a1SLionel Sambuc 			ip6flag = 1;
16811be35a1SLionel Sambuc 			s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
16911be35a1SLionel Sambuc 			if (s < 0 && (errno == EPROTONOSUPPORT ||
17011be35a1SLionel Sambuc 			    errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
17111be35a1SLionel Sambuc 				ip6flag = 0;
17211be35a1SLionel Sambuc 			else
17311be35a1SLionel Sambuc 				close(s);
17411be35a1SLionel Sambuc 			break;
17511be35a1SLionel Sambuc 		case 'n':
17611be35a1SLionel Sambuc 			nfsdcnt = atoi(optarg);
17711be35a1SLionel Sambuc 			if (nfsdcnt < 1) {
17811be35a1SLionel Sambuc 				warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
17911be35a1SLionel Sambuc 				nfsdcnt = DEFNFSDCNT;
18011be35a1SLionel Sambuc 			}
18111be35a1SLionel Sambuc 			break;
18211be35a1SLionel Sambuc 		case 'r':
18311be35a1SLionel Sambuc 			reregister = 1;
18411be35a1SLionel Sambuc 			break;
18511be35a1SLionel Sambuc 		case 't':
18611be35a1SLionel Sambuc 			tcpflag = 1;
18711be35a1SLionel Sambuc 			break;
18811be35a1SLionel Sambuc 		case 'u':
18911be35a1SLionel Sambuc 			udpflag = 1;
19011be35a1SLionel Sambuc 			break;
19111be35a1SLionel Sambuc 		default:
19211be35a1SLionel Sambuc 		case '?':
19311be35a1SLionel Sambuc 			usage();
19411be35a1SLionel Sambuc 		};
19511be35a1SLionel Sambuc 	}
19611be35a1SLionel Sambuc 	argv += optind;
19711be35a1SLionel Sambuc 	argc -= optind;
19811be35a1SLionel Sambuc 
19911be35a1SLionel Sambuc 	/*
20011be35a1SLionel Sambuc 	 * XXX
20111be35a1SLionel Sambuc 	 * Backward compatibility, trailing number is the count of daemons.
20211be35a1SLionel Sambuc 	 */
20311be35a1SLionel Sambuc 	if (argc > 1)
20411be35a1SLionel Sambuc 		usage();
20511be35a1SLionel Sambuc 	if (argc == 1) {
20611be35a1SLionel Sambuc 		nfsdcnt = atoi(argv[0]);
20711be35a1SLionel Sambuc 		if (nfsdcnt < 1) {
20811be35a1SLionel Sambuc 			warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
20911be35a1SLionel Sambuc 			nfsdcnt = DEFNFSDCNT;
21011be35a1SLionel Sambuc 		}
21111be35a1SLionel Sambuc 	}
21211be35a1SLionel Sambuc 
21311be35a1SLionel Sambuc 	/*
21411be35a1SLionel Sambuc 	 * If none of TCP or UDP are specified, default to UDP only.
21511be35a1SLionel Sambuc 	 */
21611be35a1SLionel Sambuc 	if (tcpflag == 0 && udpflag == 0)
21711be35a1SLionel Sambuc 		udpflag = 1;
21811be35a1SLionel Sambuc 
21911be35a1SLionel Sambuc 	if (debug == 0) {
22011be35a1SLionel Sambuc 		fprintf(stderr, "non-debug not supported here\n");
22111be35a1SLionel Sambuc 		exit(1);
22211be35a1SLionel Sambuc 
22311be35a1SLionel Sambuc #ifdef not_the_debug_man
22411be35a1SLionel Sambuc 		daemon(0, 0);
22511be35a1SLionel Sambuc 		(void)signal(SIGHUP, SIG_IGN);
22611be35a1SLionel Sambuc 		(void)signal(SIGINT, SIG_IGN);
22711be35a1SLionel Sambuc 		(void)signal(SIGQUIT, SIG_IGN);
22811be35a1SLionel Sambuc 		(void)signal(SIGSYS, nonfs);
22911be35a1SLionel Sambuc #endif
23011be35a1SLionel Sambuc 	}
23111be35a1SLionel Sambuc 
23211be35a1SLionel Sambuc 	if (udpflag) {
23311be35a1SLionel Sambuc 		memset(&hints, 0, sizeof hints);
23411be35a1SLionel Sambuc 		hints.ai_flags = AI_PASSIVE;
23511be35a1SLionel Sambuc 		hints.ai_family = PF_INET;
23611be35a1SLionel Sambuc 		hints.ai_socktype = SOCK_DGRAM;
23711be35a1SLionel Sambuc 		hints.ai_protocol = IPPROTO_UDP;
23811be35a1SLionel Sambuc 
23911be35a1SLionel Sambuc 		ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
24011be35a1SLionel Sambuc 		if (ecode != 0) {
24111be35a1SLionel Sambuc 			syslog(LOG_ERR, "getaddrinfo udp: %s",
24211be35a1SLionel Sambuc 			    gai_strerror(ecode));
24311be35a1SLionel Sambuc 			exit(1);
24411be35a1SLionel Sambuc 		}
24511be35a1SLionel Sambuc 
24611be35a1SLionel Sambuc 		nconf_udp = getnetconfigent("udp");
24711be35a1SLionel Sambuc 
24811be35a1SLionel Sambuc 		if (nconf_udp == NULL)
24911be35a1SLionel Sambuc 			err(1, "getnetconfigent udp failed");
25011be35a1SLionel Sambuc 
25111be35a1SLionel Sambuc 		nb_udp.buf = ai_udp->ai_addr;
25211be35a1SLionel Sambuc 		nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
25311be35a1SLionel Sambuc 		if (reregister)
25411be35a1SLionel Sambuc 			if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp))
25511be35a1SLionel Sambuc 				err(1, "rpcb_set udp failed");
25611be35a1SLionel Sambuc 	}
25711be35a1SLionel Sambuc 
25811be35a1SLionel Sambuc 	if (tcpflag) {
25911be35a1SLionel Sambuc 		memset(&hints, 0, sizeof hints);
26011be35a1SLionel Sambuc 		hints.ai_flags = AI_PASSIVE;
26111be35a1SLionel Sambuc 		hints.ai_family = PF_INET;
26211be35a1SLionel Sambuc 		hints.ai_socktype = SOCK_STREAM;
26311be35a1SLionel Sambuc 		hints.ai_protocol = IPPROTO_TCP;
26411be35a1SLionel Sambuc 
26511be35a1SLionel Sambuc 		ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
26611be35a1SLionel Sambuc 		if (ecode != 0) {
26711be35a1SLionel Sambuc 			syslog(LOG_ERR, "getaddrinfo tcp: %s",
26811be35a1SLionel Sambuc 			    gai_strerror(ecode));
26911be35a1SLionel Sambuc 			exit(1);
27011be35a1SLionel Sambuc 		}
27111be35a1SLionel Sambuc 
27211be35a1SLionel Sambuc 		nconf_tcp = getnetconfigent("tcp");
27311be35a1SLionel Sambuc 
27411be35a1SLionel Sambuc 		if (nconf_tcp == NULL)
27511be35a1SLionel Sambuc 			err(1, "getnetconfigent tcp failed");
27611be35a1SLionel Sambuc 
27711be35a1SLionel Sambuc 		nb_tcp.buf = ai_tcp->ai_addr;
27811be35a1SLionel Sambuc 		nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
27911be35a1SLionel Sambuc 		if (reregister)
28011be35a1SLionel Sambuc 			if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp))
28111be35a1SLionel Sambuc 				err(1, "rpcb_set tcp failed");
28211be35a1SLionel Sambuc 	}
28311be35a1SLionel Sambuc 
28411be35a1SLionel Sambuc 	if (udpflag && ip6flag) {
28511be35a1SLionel Sambuc 		memset(&hints, 0, sizeof hints);
28611be35a1SLionel Sambuc 		hints.ai_flags = AI_PASSIVE;
28711be35a1SLionel Sambuc 		hints.ai_family = PF_INET6;
28811be35a1SLionel Sambuc 		hints.ai_socktype = SOCK_DGRAM;
28911be35a1SLionel Sambuc 		hints.ai_protocol = IPPROTO_UDP;
29011be35a1SLionel Sambuc 
29111be35a1SLionel Sambuc 		ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
29211be35a1SLionel Sambuc 		if (ecode != 0) {
29311be35a1SLionel Sambuc 			syslog(LOG_ERR, "getaddrinfo udp: %s",
29411be35a1SLionel Sambuc 			    gai_strerror(ecode));
29511be35a1SLionel Sambuc 			exit(1);
29611be35a1SLionel Sambuc 		}
29711be35a1SLionel Sambuc 
29811be35a1SLionel Sambuc 		nconf_udp6 = getnetconfigent("udp6");
29911be35a1SLionel Sambuc 
30011be35a1SLionel Sambuc 		if (nconf_udp6 == NULL)
30111be35a1SLionel Sambuc 			err(1, "getnetconfigent udp6 failed");
30211be35a1SLionel Sambuc 
30311be35a1SLionel Sambuc 		nb_udp6.buf = ai_udp6->ai_addr;
30411be35a1SLionel Sambuc 		nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
30511be35a1SLionel Sambuc 		if (reregister)
30611be35a1SLionel Sambuc 			if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6))
30711be35a1SLionel Sambuc 				err(1, "rpcb_set udp6 failed");
30811be35a1SLionel Sambuc 	}
30911be35a1SLionel Sambuc 
31011be35a1SLionel Sambuc 	if (tcpflag && ip6flag) {
31111be35a1SLionel Sambuc 		memset(&hints, 0, sizeof hints);
31211be35a1SLionel Sambuc 		hints.ai_flags = AI_PASSIVE;
31311be35a1SLionel Sambuc 		hints.ai_family = PF_INET6;
31411be35a1SLionel Sambuc 		hints.ai_socktype = SOCK_STREAM;
31511be35a1SLionel Sambuc 		hints.ai_protocol = IPPROTO_TCP;
31611be35a1SLionel Sambuc 
31711be35a1SLionel Sambuc 		ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
31811be35a1SLionel Sambuc 		if (ecode != 0) {
31911be35a1SLionel Sambuc 			syslog(LOG_ERR, "getaddrinfo tcp: %s",
32011be35a1SLionel Sambuc 			    gai_strerror(ecode));
32111be35a1SLionel Sambuc 			exit(1);
32211be35a1SLionel Sambuc 		}
32311be35a1SLionel Sambuc 
32411be35a1SLionel Sambuc 		nconf_tcp6 = getnetconfigent("tcp6");
32511be35a1SLionel Sambuc 
32611be35a1SLionel Sambuc 		if (nconf_tcp6 == NULL)
32711be35a1SLionel Sambuc 			err(1, "getnetconfigent tcp6 failed");
32811be35a1SLionel Sambuc 
32911be35a1SLionel Sambuc 		nb_tcp6.buf = ai_tcp6->ai_addr;
33011be35a1SLionel Sambuc 		nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
33111be35a1SLionel Sambuc 		if (reregister)
33211be35a1SLionel Sambuc 			if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6))
33311be35a1SLionel Sambuc 				err(1, "rpcb_set tcp6 failed");
33411be35a1SLionel Sambuc 	}
33511be35a1SLionel Sambuc 
33611be35a1SLionel Sambuc 	openlog("nfsd", LOG_PID, LOG_DAEMON);
33711be35a1SLionel Sambuc 
33811be35a1SLionel Sambuc 	for (i = 0; i < nfsdcnt; i++) {
33911be35a1SLionel Sambuc 		pthread_t t;
34011be35a1SLionel Sambuc 		pthread_create(&t, NULL, child, NULL);
34111be35a1SLionel Sambuc 	}
34211be35a1SLionel Sambuc 
34311be35a1SLionel Sambuc 	/* If we are serving udp, set up the socket. */
34411be35a1SLionel Sambuc 	if (udpflag) {
34511be35a1SLionel Sambuc 		if ((sock = rump_sys_socket(ai_udp->ai_family, ai_udp->ai_socktype,
34611be35a1SLionel Sambuc 		    ai_udp->ai_protocol)) < 0) {
34711be35a1SLionel Sambuc 			syslog(LOG_ERR, "can't create udp socket");
34811be35a1SLionel Sambuc 			exit(1);
34911be35a1SLionel Sambuc 		}
35011be35a1SLionel Sambuc 		if (bind(sock, ai_udp->ai_addr, ai_udp->ai_addrlen) < 0) {
35111be35a1SLionel Sambuc 			syslog(LOG_ERR, "can't bind udp addr");
35211be35a1SLionel Sambuc 			exit(1);
35311be35a1SLionel Sambuc 		}
35411be35a1SLionel Sambuc 		if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp) ||
35511be35a1SLionel Sambuc 		    !rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)) {
35611be35a1SLionel Sambuc 			syslog(LOG_ERR, "can't register with udp portmap");
35711be35a1SLionel Sambuc 			exit(1);
35811be35a1SLionel Sambuc 		}
35911be35a1SLionel Sambuc 		nfsdargs.sock = sock;
36011be35a1SLionel Sambuc 		nfsdargs.name = NULL;
36111be35a1SLionel Sambuc 		nfsdargs.namelen = 0;
36211be35a1SLionel Sambuc 		if (rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
36311be35a1SLionel Sambuc 			syslog(LOG_ERR, "can't add UDP socket");
36411be35a1SLionel Sambuc 			exit(1);
36511be35a1SLionel Sambuc 		}
36611be35a1SLionel Sambuc 		(void)rump_sys_close(sock);
36711be35a1SLionel Sambuc 	}
36811be35a1SLionel Sambuc 
36911be35a1SLionel Sambuc 	if (udpflag &&ip6flag) {
37011be35a1SLionel Sambuc 		if ((sock = rump_sys_socket(ai_udp6->ai_family, ai_udp6->ai_socktype,
37111be35a1SLionel Sambuc 		    ai_udp6->ai_protocol)) < 0) {
37211be35a1SLionel Sambuc 			syslog(LOG_ERR, "can't create udp socket");
37311be35a1SLionel Sambuc 			exit(1);
37411be35a1SLionel Sambuc 		}
37511be35a1SLionel Sambuc 		if (rump_sys_setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
37611be35a1SLionel Sambuc 		    &on, sizeof on) < 0) {
37711be35a1SLionel Sambuc 			syslog(LOG_ERR, "can't set v6-only binding for udp6 "
378*0a6a1f1dSLionel Sambuc 			    "socket (%s)", strerror(errno));
37911be35a1SLionel Sambuc 			exit(1);
38011be35a1SLionel Sambuc 		}
38111be35a1SLionel Sambuc 		if (rump_sys_bind(sock, ai_udp6->ai_addr, ai_udp6->ai_addrlen) < 0) {
382*0a6a1f1dSLionel Sambuc 			syslog(LOG_ERR, "can't bind udp addr (%s)",
383*0a6a1f1dSLionel Sambuc 			    strerror(errno));
38411be35a1SLionel Sambuc 			exit(1);
38511be35a1SLionel Sambuc 		}
38611be35a1SLionel Sambuc 		if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6) ||
38711be35a1SLionel Sambuc 		    !rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)) {
38811be35a1SLionel Sambuc 			syslog(LOG_ERR, "can't register with udp portmap");
38911be35a1SLionel Sambuc 			exit(1);
39011be35a1SLionel Sambuc 		}
39111be35a1SLionel Sambuc 		nfsdargs.sock = sock;
39211be35a1SLionel Sambuc 		nfsdargs.name = NULL;
39311be35a1SLionel Sambuc 		nfsdargs.namelen = 0;
39411be35a1SLionel Sambuc 		if (rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
395*0a6a1f1dSLionel Sambuc 			syslog(LOG_ERR, "can't add UDP6 socket (%s)",
396*0a6a1f1dSLionel Sambuc 			    strerror(errno));
39711be35a1SLionel Sambuc 			exit(1);
39811be35a1SLionel Sambuc 		}
39911be35a1SLionel Sambuc 		(void)rump_sys_close(sock);
40011be35a1SLionel Sambuc 	}
40111be35a1SLionel Sambuc 
40211be35a1SLionel Sambuc 	/* Now set up the master server socket waiting for tcp connections. */
40311be35a1SLionel Sambuc 	on = 1;
40411be35a1SLionel Sambuc 	connect_type_cnt = 0;
40511be35a1SLionel Sambuc 	if (tcpflag) {
40611be35a1SLionel Sambuc 		if ((tcpsock = rump_sys_socket(ai_tcp->ai_family, ai_tcp->ai_socktype,
40711be35a1SLionel Sambuc 		    ai_tcp->ai_protocol)) < 0) {
40811be35a1SLionel Sambuc 			syslog(LOG_ERR, "can't create tcp socket");
40911be35a1SLionel Sambuc 			exit(1);
41011be35a1SLionel Sambuc 		}
41111be35a1SLionel Sambuc 		if (setsockopt(tcpsock,
41211be35a1SLionel Sambuc 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
413*0a6a1f1dSLionel Sambuc 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR (%s)",
414*0a6a1f1dSLionel Sambuc 			    strerror(errno));
41511be35a1SLionel Sambuc 		if (bind(tcpsock, ai_tcp->ai_addr, ai_tcp->ai_addrlen) < 0) {
41611be35a1SLionel Sambuc 			syslog(LOG_ERR, "can't bind tcp addr");
41711be35a1SLionel Sambuc 			exit(1);
41811be35a1SLionel Sambuc 		}
41911be35a1SLionel Sambuc 		if (rump_sys_listen(tcpsock, 5) < 0) {
42011be35a1SLionel Sambuc 			syslog(LOG_ERR, "listen failed");
42111be35a1SLionel Sambuc 			exit(1);
42211be35a1SLionel Sambuc 		}
42311be35a1SLionel Sambuc 		if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp) ||
42411be35a1SLionel Sambuc 		    !rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)) {
42511be35a1SLionel Sambuc 			syslog(LOG_ERR, "can't register tcp with rpcbind");
42611be35a1SLionel Sambuc 			exit(1);
42711be35a1SLionel Sambuc 		}
42811be35a1SLionel Sambuc 		set[0].fd = tcpsock;
42911be35a1SLionel Sambuc 		set[0].events = POLLIN;
43011be35a1SLionel Sambuc 		connect_type_cnt++;
43111be35a1SLionel Sambuc 	} else
43211be35a1SLionel Sambuc 		set[0].fd = -1;
43311be35a1SLionel Sambuc 
43411be35a1SLionel Sambuc 	if (tcpflag && ip6flag) {
43511be35a1SLionel Sambuc 		if ((tcp6sock = socket(ai_tcp6->ai_family, ai_tcp6->ai_socktype,
43611be35a1SLionel Sambuc 		    ai_tcp6->ai_protocol)) < 0) {
437*0a6a1f1dSLionel Sambuc 			syslog(LOG_ERR, "can't create tcp socket (%s)",
438*0a6a1f1dSLionel Sambuc 			    strerror(errno));
43911be35a1SLionel Sambuc 			exit(1);
44011be35a1SLionel Sambuc 		}
44111be35a1SLionel Sambuc 		if (setsockopt(tcp6sock,
44211be35a1SLionel Sambuc 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
443*0a6a1f1dSLionel Sambuc 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR (%s)",
444*0a6a1f1dSLionel Sambuc 			    strerror(errno));
44511be35a1SLionel Sambuc 		if (setsockopt(tcp6sock, IPPROTO_IPV6, IPV6_V6ONLY,
44611be35a1SLionel Sambuc 		    &on, sizeof on) < 0) {
44711be35a1SLionel Sambuc 			syslog(LOG_ERR, "can't set v6-only binding for tcp6 "
448*0a6a1f1dSLionel Sambuc 			    "socket (%s)", strerror(errno));
44911be35a1SLionel Sambuc 			exit(1);
45011be35a1SLionel Sambuc 		}
45111be35a1SLionel Sambuc 		if (bind(tcp6sock, ai_tcp6->ai_addr, ai_tcp6->ai_addrlen) < 0) {
452*0a6a1f1dSLionel Sambuc 			syslog(LOG_ERR, "can't bind tcp6 addr (%s)",
453*0a6a1f1dSLionel Sambuc 			    strerror(errno));
45411be35a1SLionel Sambuc 			exit(1);
45511be35a1SLionel Sambuc 		}
45611be35a1SLionel Sambuc 		if (listen(tcp6sock, 5) < 0) {
457*0a6a1f1dSLionel Sambuc 			syslog(LOG_ERR, "listen failed (%s)", strerror(errno));
45811be35a1SLionel Sambuc 			exit(1);
45911be35a1SLionel Sambuc 		}
46011be35a1SLionel Sambuc 		if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6) ||
46111be35a1SLionel Sambuc 		    !rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)) {
46211be35a1SLionel Sambuc 			syslog(LOG_ERR, "can't register tcp6 with rpcbind");
46311be35a1SLionel Sambuc 			exit(1);
46411be35a1SLionel Sambuc 		}
46511be35a1SLionel Sambuc 		set[1].fd = tcp6sock;
46611be35a1SLionel Sambuc 		set[1].events = POLLIN;
46711be35a1SLionel Sambuc 		connect_type_cnt++;
46811be35a1SLionel Sambuc 	} else
46911be35a1SLionel Sambuc 		set[1].fd = -1;
47011be35a1SLionel Sambuc 
47111be35a1SLionel Sambuc 	set[2].fd = -1;
47211be35a1SLionel Sambuc 	set[3].fd = -1;
47311be35a1SLionel Sambuc 
47411be35a1SLionel Sambuc 	if (connect_type_cnt == 0) {
47511be35a1SLionel Sambuc 		pause();
47611be35a1SLionel Sambuc 		exit(0);
47711be35a1SLionel Sambuc 	}
47811be35a1SLionel Sambuc 
47911be35a1SLionel Sambuc 	/*
48011be35a1SLionel Sambuc 	 * Loop forever accepting connections and passing the sockets
48111be35a1SLionel Sambuc 	 * into the kernel for the mounts.
48211be35a1SLionel Sambuc 	 */
48311be35a1SLionel Sambuc 	for (;;) {
48411be35a1SLionel Sambuc 		if (rump_sys_poll(set, 4, INFTIM) < 1) {
485*0a6a1f1dSLionel Sambuc 			syslog(LOG_ERR, "poll failed (%s)", strerror(errno));
48611be35a1SLionel Sambuc 			exit(1);
48711be35a1SLionel Sambuc 		}
48811be35a1SLionel Sambuc 
48911be35a1SLionel Sambuc 		len = sizeof(inetpeer);
49011be35a1SLionel Sambuc 		if ((msgsock = accept(tcpsock,
49111be35a1SLionel Sambuc 		    (struct sockaddr *)&inetpeer, &len)) < 0) {
492*0a6a1f1dSLionel Sambuc 			syslog(LOG_ERR, "accept failed (%s)",
493*0a6a1f1dSLionel Sambuc 			    strerror(errno));
49411be35a1SLionel Sambuc 			exit(1);
49511be35a1SLionel Sambuc 		}
49611be35a1SLionel Sambuc 		memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
49711be35a1SLionel Sambuc 		if (setsockopt(msgsock, SOL_SOCKET,
49811be35a1SLionel Sambuc 		    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
499*0a6a1f1dSLionel Sambuc 			syslog(LOG_ERR, "setsockopt SO_KEEPALIVE (%s)",
500*0a6a1f1dSLionel Sambuc 			    strerror(errno));
50111be35a1SLionel Sambuc 		nfsdargs.sock = msgsock;
50211be35a1SLionel Sambuc 		nfsdargs.name = (caddr_t)&inetpeer;
50311be35a1SLionel Sambuc 		nfsdargs.namelen = sizeof(inetpeer);
50411be35a1SLionel Sambuc 		rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
50511be35a1SLionel Sambuc 		(void)rump_sys_close(msgsock);
50611be35a1SLionel Sambuc 
50711be35a1SLionel Sambuc #ifdef notyet
508*0a6a1f1dSLionel Sambuc 		int error = 0;
50911be35a1SLionel Sambuc 		if (set[1].revents & POLLIN) {
51011be35a1SLionel Sambuc 			len = sizeof(inet6peer);
51111be35a1SLionel Sambuc 			if ((msgsock = rump_sys_accept(tcp6sock,
51211be35a1SLionel Sambuc 			    (struct sockaddr *)&inet6peer, &len, &error)) < 0) {
513*0a6a1f1dSLionel Sambuc 				syslog(LOG_ERR, "accept failed (%s)",
514*0a6a1f1dSLionel Sambuc 					strerror(error));
51511be35a1SLionel Sambuc 				exit(1);
51611be35a1SLionel Sambuc 			}
51711be35a1SLionel Sambuc 			if (rump_sys_setsockopt(msgsock, SOL_SOCKET,
51811be35a1SLionel Sambuc 			    SO_KEEPALIVE, (char *)&on, sizeof(on), &error) < 0)
51911be35a1SLionel Sambuc 				syslog(LOG_ERR,
520*0a6a1f1dSLionel Sambuc 				    "setsockopt SO_KEEPALIVE (%s)",
521*0a6a1f1dSLionel Sambuc 					strerror(error));
52211be35a1SLionel Sambuc 			nfsdargs.sock = msgsock;
52311be35a1SLionel Sambuc 			nfsdargs.name = (caddr_t)&inet6peer;
52411be35a1SLionel Sambuc 			nfsdargs.namelen = sizeof(inet6peer);
52511be35a1SLionel Sambuc 			rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs, &error);
52611be35a1SLionel Sambuc 			(void)rump_sys_close(msgsock, &error);
52711be35a1SLionel Sambuc 		}
52811be35a1SLionel Sambuc 
52911be35a1SLionel Sambuc 		if (set[2].revents & POLLIN) {
53011be35a1SLionel Sambuc 			len = sizeof(isopeer);
53111be35a1SLionel Sambuc 			if ((msgsock = rump_sys_accept(tp4sock,
53211be35a1SLionel Sambuc 			    (struct sockaddr *)&isopeer, &len, &error)) < 0) {
533*0a6a1f1dSLionel Sambuc 				syslog(LOG_ERR, "accept failed (%s)",
534*0a6a1f1dSLionel Sambuc 				    strerror(error));
53511be35a1SLionel Sambuc 				exit(1);
53611be35a1SLionel Sambuc 			}
53711be35a1SLionel Sambuc 			if (rump_sys_setsockopt(msgsock, SOL_SOCKET,
53811be35a1SLionel Sambuc 			    SO_KEEPALIVE, (char *)&on, sizeof(on), &error) < 0)
539*0a6a1f1dSLionel Sambuc 				syslog(LOG_ERR, "setsockopt SO_KEEPALIVE (%s)",
540*0a6a1f1dSLionel Sambuc 				    strerror(error));
54111be35a1SLionel Sambuc 			nfsdargs.sock = msgsock;
54211be35a1SLionel Sambuc 			nfsdargs.name = (caddr_t)&isopeer;
54311be35a1SLionel Sambuc 			nfsdargs.namelen = len;
54411be35a1SLionel Sambuc 			rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs, &error);
54511be35a1SLionel Sambuc 			(void)rump_sys_close(msgsock, &error);
54611be35a1SLionel Sambuc 		}
54711be35a1SLionel Sambuc 
54811be35a1SLionel Sambuc 		if (set[3].revents & POLLIN) {
54911be35a1SLionel Sambuc 			len = sizeof(inetpeer);
55011be35a1SLionel Sambuc 			if ((msgsock = rump_sys_accept(tpipsock,
55111be35a1SLionel Sambuc 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
552*0a6a1f1dSLionel Sambuc 				syslog(LOG_ERR, "accept failed (%s)",
553*0a6a1f1dSLionel Sambuc 				    strerror(errno));
55411be35a1SLionel Sambuc 				exit(1);
55511be35a1SLionel Sambuc 			}
55611be35a1SLionel Sambuc 			if (setsockopt(msgsock, SOL_SOCKET,
55711be35a1SLionel Sambuc 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
558*0a6a1f1dSLionel Sambuc 				syslog(LOG_ERR, "setsockopt SO_KEEPALIVE (%s)",
559*0a6a1f1dSLionel Sambuc 				    strerror(errno));
56011be35a1SLionel Sambuc 			nfsdargs.sock = msgsock;
56111be35a1SLionel Sambuc 			nfsdargs.name = (caddr_t)&inetpeer;
56211be35a1SLionel Sambuc 			nfsdargs.namelen = len;
56311be35a1SLionel Sambuc 			rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
56411be35a1SLionel Sambuc 			(void)rump_sys_close(msgsock);
56511be35a1SLionel Sambuc 		}
56611be35a1SLionel Sambuc #endif /* notyet */
56711be35a1SLionel Sambuc 	}
56811be35a1SLionel Sambuc }
56911be35a1SLionel Sambuc 
57011be35a1SLionel Sambuc void
usage()57111be35a1SLionel Sambuc usage()
57211be35a1SLionel Sambuc {
57311be35a1SLionel Sambuc 	(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
57411be35a1SLionel Sambuc 	exit(1);
57511be35a1SLionel Sambuc }
57611be35a1SLionel Sambuc 
57711be35a1SLionel Sambuc void
nonfs(signo)57811be35a1SLionel Sambuc nonfs(signo)
57911be35a1SLionel Sambuc 	int signo;
58011be35a1SLionel Sambuc {
58111be35a1SLionel Sambuc 	syslog(LOG_ERR, "missing system call: NFS not available.");
58211be35a1SLionel Sambuc }
583