nfsd.c revision 95861
1/*
2 * Copyright (c) 1989, 1993, 1994
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38static const char copyright[] =
39"@(#) Copyright (c) 1989, 1993, 1994\n\
40	The Regents of the University of California.  All rights reserved.\n";
41#endif /* not lint */
42
43#ifndef lint
44#if 0
45static char sccsid[] = "@(#)nfsd.c	8.9 (Berkeley) 3/29/95";
46#endif
47static const char rcsid[] =
48  "$FreeBSD: head/usr.sbin/nfsd/nfsd.c 95861 2002-05-01 06:49:43Z peter $";
49#endif /* not lint */
50
51#include <sys/param.h>
52#include <sys/syslog.h>
53#include <sys/wait.h>
54#include <sys/mount.h>
55#include <sys/linker.h>
56#include <sys/module.h>
57
58#include <rpc/rpc.h>
59#include <rpc/pmap_clnt.h>
60
61#include <netdb.h>
62#include <arpa/inet.h>
63#include <nfs/rpcv2.h>
64#include <nfs/nfsproto.h>
65#include <nfsserver/nfs.h>
66
67#include <err.h>
68#include <errno.h>
69#include <signal.h>
70#include <stdio.h>
71#include <stdlib.h>
72#include <string.h>
73#include <unistd.h>
74#include <netdb.h>
75
76/* Global defs */
77#ifdef DEBUG
78#define	syslog(e, s...)	fprintf(stderr,s)
79int	debug = 1;
80#else
81int	debug = 0;
82#endif
83
84struct	nfsd_srvargs nsd;
85
86#define	MAXNFSDCNT	20
87#define	DEFNFSDCNT	 4
88pid_t	children[MAXNFSDCNT];	/* PIDs of children */
89int	nfsdcnt;		/* number of children */
90
91void	cleanup(int);
92void	child_cleanup(int);
93void	killchildren(void);
94void	nfsd_exit(int);
95void	nonfs(int);
96void	reapchild(int);
97int	setbindhost(struct addrinfo **ia, const char *bindhost,
98	    struct addrinfo hints);
99void	start_server(int);
100void	unregistration(void);
101void	usage(void);
102
103/*
104 * Nfs server daemon mostly just a user context for nfssvc()
105 *
106 * 1 - do file descriptor and signal cleanup
107 * 2 - fork the nfsd(s)
108 * 3 - create server socket(s)
109 * 4 - register socket with rpcbind
110 *
111 * For connectionless protocols, just pass the socket into the kernel via.
112 * nfssvc().
113 * For connection based sockets, loop doing accepts. When you get a new
114 * socket from accept, pass the msgsock into the kernel via. nfssvc().
115 * The arguments are:
116 *	-r - reregister with rpcbind
117 *	-d - unregister with rpcbind
118 *	-t - support tcp nfs clients
119 *	-u - support udp nfs clients
120 * followed by "n" which is the number of nfsds' to fork off
121 */
122int
123main(argc, argv, envp)
124	int argc;
125	char *argv[], *envp[];
126{
127	struct nfsd_args nfsdargs;
128	struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
129	struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
130	struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
131	struct sockaddr_in inetpeer;
132	struct sockaddr_in6 inet6peer;
133	fd_set ready, sockbits;
134	fd_set v4bits, v6bits;
135	int ch, connect_type_cnt, i, len, maxsock, msgsock;
136	int on = 1, unregister, reregister, sock;
137	int tcp6sock, ip6flag, tcpflag, tcpsock;
138	int udpflag, ecode, s, srvcnt;
139	int bindhostc, bindanyflag, rpcbreg, rpcbregcnt;
140	char **bindhost = NULL;
141	pid_t pid;
142
143	if (modfind("nfsserver") < 0) {
144		/* Not present in kernel, try loading it */
145		if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0)
146			errx(1, "NFS serveris not available");
147	}
148
149	nfsdcnt = DEFNFSDCNT;
150	unregister = reregister = tcpflag = maxsock = 0;
151	bindanyflag = udpflag = connect_type_cnt = bindhostc = 0;
152#define	GETOPT	"ah:n:rdtu"
153#define	USAGE	"[-ardtu] [-n num_servers] [-h bindip]"
154	while ((ch = getopt(argc, argv, GETOPT)) != -1)
155		switch (ch) {
156		case 'a':
157			bindanyflag = 1;
158			break;
159		case 'n':
160			nfsdcnt = atoi(optarg);
161			if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
162				warnx("nfsd count %d; reset to %d", nfsdcnt,
163				    DEFNFSDCNT);
164				nfsdcnt = DEFNFSDCNT;
165			}
166			break;
167		case 'h':
168			bindhostc++;
169			bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
170			if (bindhost == NULL)
171				errx(1, "Out of memory");
172			bindhost[bindhostc-1] = strdup(optarg);
173			if (bindhost[bindhostc-1] == NULL)
174				errx(1, "Out of memory");
175			break;
176		case 'r':
177			reregister = 1;
178			break;
179		case 'd':
180			unregister = 1;
181			break;
182		case 't':
183			tcpflag = 1;
184			break;
185		case 'u':
186			udpflag = 1;
187			break;
188		default:
189		case '?':
190			usage();
191		};
192	if (!tcpflag && !udpflag)
193		udpflag = 1;
194	argv += optind;
195	argc -= optind;
196
197	/*
198	 * XXX
199	 * Backward compatibility, trailing number is the count of daemons.
200	 */
201	if (argc > 1)
202		usage();
203	if (argc == 1) {
204		nfsdcnt = atoi(argv[0]);
205		if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
206			warnx("nfsd count %d; reset to %d", nfsdcnt,
207			    DEFNFSDCNT);
208			nfsdcnt = DEFNFSDCNT;
209		}
210	}
211
212	ip6flag = 1;
213	s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
214	if (s == -1) {
215		if (errno != EPROTONOSUPPORT)
216			err(1, "socket");
217		ip6flag = 0;
218	} else if (getnetconfigent("udp6") == NULL ||
219		getnetconfigent("tcp6") == NULL) {
220		ip6flag = 0;
221	}
222	if (s != -1)
223		close(s);
224
225	if (bindhostc == 0 || bindanyflag) {
226		bindhostc++;
227		bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
228		if (bindhost == NULL)
229			errx(1, "Out of memory");
230		bindhost[bindhostc-1] = strdup("*");
231		if (bindhost[bindhostc-1] == NULL)
232			errx(1, "Out of memory");
233	}
234
235	if (unregister) {
236		unregistration();
237		exit (0);
238	}
239	if (reregister) {
240		if (udpflag) {
241			memset(&hints, 0, sizeof hints);
242			hints.ai_flags = AI_PASSIVE;
243			hints.ai_family = AF_INET;
244			hints.ai_socktype = SOCK_DGRAM;
245			hints.ai_protocol = IPPROTO_UDP;
246			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
247			if (ecode != 0)
248				err(1, "getaddrinfo udp: %s", gai_strerror(ecode));
249			nconf_udp = getnetconfigent("udp");
250			if (nconf_udp == NULL)
251				err(1, "getnetconfigent udp failed");
252			nb_udp.buf = ai_udp->ai_addr;
253			nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
254			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
255			    (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
256				err(1, "rpcb_set udp failed");
257			freeaddrinfo(ai_udp);
258		}
259		if (udpflag && ip6flag) {
260			memset(&hints, 0, sizeof hints);
261			hints.ai_flags = AI_PASSIVE;
262			hints.ai_family = AF_INET6;
263			hints.ai_socktype = SOCK_DGRAM;
264			hints.ai_protocol = IPPROTO_UDP;
265			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
266			if (ecode != 0)
267				err(1, "getaddrinfo udp6: %s", gai_strerror(ecode));
268			nconf_udp6 = getnetconfigent("udp6");
269			if (nconf_udp6 == NULL)
270				err(1, "getnetconfigent udp6 failed");
271			nb_udp6.buf = ai_udp6->ai_addr;
272			nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
273			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
274			    (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
275				err(1, "rpcb_set udp6 failed");
276			freeaddrinfo(ai_udp6);
277		}
278		if (tcpflag) {
279			memset(&hints, 0, sizeof hints);
280			hints.ai_flags = AI_PASSIVE;
281			hints.ai_family = AF_INET;
282			hints.ai_socktype = SOCK_STREAM;
283			hints.ai_protocol = IPPROTO_TCP;
284			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
285			if (ecode != 0)
286				err(1, "getaddrinfo tcp: %s", gai_strerror(ecode));
287			nconf_tcp = getnetconfigent("tcp");
288			if (nconf_tcp == NULL)
289				err(1, "getnetconfigent tcp failed");
290			nb_tcp.buf = ai_tcp->ai_addr;
291			nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
292			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) ||
293			    (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)))
294				err(1, "rpcb_set tcp failed");
295			freeaddrinfo(ai_tcp);
296		}
297		if (tcpflag && ip6flag) {
298			memset(&hints, 0, sizeof hints);
299			hints.ai_flags = AI_PASSIVE;
300			hints.ai_family = AF_INET6;
301			hints.ai_socktype = SOCK_STREAM;
302			hints.ai_protocol = IPPROTO_TCP;
303			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
304			if (ecode != 0)
305				err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode));
306			nconf_tcp6 = getnetconfigent("tcp6");
307			if (nconf_tcp6 == NULL)
308				err(1, "getnetconfigent tcp6 failed");
309			nb_tcp6.buf = ai_tcp6->ai_addr;
310			nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
311			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
312			    (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
313				err(1, "rpcb_set tcp6 failed");
314			freeaddrinfo(ai_tcp6);
315		}
316		exit (0);
317	}
318	if (debug == 0) {
319		daemon(0, 0);
320		(void)signal(SIGHUP, SIG_IGN);
321		(void)signal(SIGINT, SIG_IGN);
322		/*
323		 * nfsd sits in the kernel most of the time.  It needs
324		 * to ignore SIGTERM/SIGQUIT in order to stay alive as long
325		 * as possible during a shutdown, otherwise loopback
326		 * mounts will not be able to unmount.
327		 */
328		(void)signal(SIGTERM, SIG_IGN);
329		(void)signal(SIGQUIT, SIG_IGN);
330	}
331	(void)signal(SIGSYS, nonfs);
332	(void)signal(SIGCHLD, reapchild);
333
334	openlog("nfsd", LOG_PID, LOG_DAEMON);
335
336	/* If we use UDP only, we start the last server below. */
337	srvcnt = tcpflag ? nfsdcnt : nfsdcnt - 1;
338	for (i = 0; i < srvcnt; i++) {
339		switch ((pid = fork())) {
340		case -1:
341			syslog(LOG_ERR, "fork: %m");
342			nfsd_exit(1);
343		case 0:
344			break;
345		default:
346			children[i] = pid;
347			continue;
348		}
349		(void)signal(SIGUSR1, child_cleanup);
350		setproctitle("server");
351
352		start_server(0);
353	}
354
355	(void)signal(SIGUSR1, cleanup);
356	FD_ZERO(&v4bits);
357	FD_ZERO(&v6bits);
358
359	rpcbregcnt = 0;
360	/* Set up the socket for udp and rpcb register it. */
361	if (udpflag) {
362		rpcbreg = 0;
363		for (i = 0; i < bindhostc; i++) {
364			memset(&hints, 0, sizeof hints);
365			hints.ai_flags = AI_PASSIVE;
366			hints.ai_family = AF_INET;
367			hints.ai_socktype = SOCK_DGRAM;
368			hints.ai_protocol = IPPROTO_UDP;
369			if (setbindhost(&ai_udp, bindhost[i], hints) == 0) {
370				rpcbreg = 1;
371				rpcbregcnt++;
372				if ((sock = socket(ai_udp->ai_family,
373				    ai_udp->ai_socktype,
374				    ai_udp->ai_protocol)) < 0) {
375					syslog(LOG_ERR,
376					    "can't create udp socket");
377					nfsd_exit(1);
378				}
379				if (bind(sock, ai_udp->ai_addr,
380				    ai_udp->ai_addrlen) < 0) {
381					syslog(LOG_ERR,
382					    "can't bind udp addr %s: %m",
383					    bindhost[i]);
384					nfsd_exit(1);
385				}
386				freeaddrinfo(ai_udp);
387				nfsdargs.sock = sock;
388				nfsdargs.name = NULL;
389				nfsdargs.namelen = 0;
390				if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
391					syslog(LOG_ERR, "can't Add UDP socket");
392					nfsd_exit(1);
393				}
394				(void)close(sock);
395			}
396		}
397		if (rpcbreg == 1) {
398			memset(&hints, 0, sizeof hints);
399			hints.ai_flags = AI_PASSIVE;
400			hints.ai_family = AF_INET;
401			hints.ai_socktype = SOCK_DGRAM;
402			hints.ai_protocol = IPPROTO_UDP;
403			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
404			if (ecode != 0) {
405				syslog(LOG_ERR, "getaddrinfo udp: %s",
406				   gai_strerror(ecode));
407				nfsd_exit(1);
408			}
409			nconf_udp = getnetconfigent("udp");
410			if (nconf_udp == NULL)
411				err(1, "getnetconfigent udp failed");
412			nb_udp.buf = ai_udp->ai_addr;
413			nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
414			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
415			    (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
416				err(1, "rpcb_set udp failed");
417			freeaddrinfo(ai_udp);
418		}
419	}
420
421	/* Set up the socket for udp6 and rpcb register it. */
422	if (udpflag && ip6flag) {
423		rpcbreg = 0;
424		for (i = 0; i < bindhostc; i++) {
425			memset(&hints, 0, sizeof hints);
426			hints.ai_flags = AI_PASSIVE;
427			hints.ai_family = AF_INET6;
428			hints.ai_socktype = SOCK_DGRAM;
429			hints.ai_protocol = IPPROTO_UDP;
430			if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) {
431				rpcbreg = 1;
432				rpcbregcnt++;
433				if ((sock = socket(ai_udp6->ai_family,
434				    ai_udp6->ai_socktype,
435				    ai_udp6->ai_protocol)) < 0) {
436					syslog(LOG_ERR,
437						"can't create udp6 socket");
438					nfsd_exit(1);
439				}
440				if (setsockopt(sock, IPPROTO_IPV6,
441				    IPV6_BINDV6ONLY,
442				    &on, sizeof on) < 0) {
443					syslog(LOG_ERR,
444					    "can't set v6-only binding for "
445					    "udp6 socket: %m");
446					nfsd_exit(1);
447				}
448				if (bind(sock, ai_udp6->ai_addr,
449				    ai_udp6->ai_addrlen) < 0) {
450					syslog(LOG_ERR,
451					    "can't bind udp6 addr %s: %m",
452					    bindhost[i]);
453					nfsd_exit(1);
454				}
455				freeaddrinfo(ai_udp6);
456				nfsdargs.sock = sock;
457				nfsdargs.name = NULL;
458				nfsdargs.namelen = 0;
459				if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
460					syslog(LOG_ERR,
461					    "can't add UDP6 socket");
462					nfsd_exit(1);
463				}
464				(void)close(sock);
465			}
466		}
467		if (rpcbreg == 1) {
468			memset(&hints, 0, sizeof hints);
469			hints.ai_flags = AI_PASSIVE;
470			hints.ai_family = AF_INET6;
471			hints.ai_socktype = SOCK_DGRAM;
472			hints.ai_protocol = IPPROTO_UDP;
473			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
474			if (ecode != 0) {
475				syslog(LOG_ERR, "getaddrinfo udp6: %s",
476				   gai_strerror(ecode));
477				nfsd_exit(1);
478			}
479			nconf_udp6 = getnetconfigent("udp6");
480			if (nconf_udp6 == NULL)
481				err(1, "getnetconfigent udp6 failed");
482			nb_udp6.buf = ai_udp6->ai_addr;
483			nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
484			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
485			    (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
486				err(1, "rpcb_set udp6 failed");
487			freeaddrinfo(ai_udp6);
488		}
489	}
490
491	/* Set up the socket for tcp and rpcb register it. */
492	if (tcpflag) {
493		rpcbreg = 0;
494		for (i = 0; i < bindhostc; i++) {
495			memset(&hints, 0, sizeof hints);
496			hints.ai_flags = AI_PASSIVE;
497			hints.ai_family = AF_INET;
498			hints.ai_socktype = SOCK_STREAM;
499			hints.ai_protocol = IPPROTO_TCP;
500			if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) {
501				rpcbreg = 1;
502				rpcbregcnt++;
503				if ((tcpsock = socket(AF_INET, SOCK_STREAM,
504				    0)) < 0) {
505					syslog(LOG_ERR,
506					    "can't create tpc socket");
507					nfsd_exit(1);
508				}
509				if (setsockopt(tcpsock, SOL_SOCKET,
510				    SO_REUSEADDR,
511				    (char *)&on, sizeof(on)) < 0)
512					syslog(LOG_ERR,
513					     "setsockopt SO_REUSEADDR: %m");
514				if (bind(tcpsock, ai_tcp->ai_addr,
515				    ai_tcp->ai_addrlen) < 0) {
516					syslog(LOG_ERR,
517					    "can't bind tcp addr %s: %m",
518					    bindhost[i]);
519					nfsd_exit(1);
520				}
521				if (listen(tcpsock, 5) < 0) {
522					syslog(LOG_ERR, "listen failed");
523					nfsd_exit(1);
524				}
525				freeaddrinfo(ai_tcp);
526				FD_SET(tcpsock, &sockbits);
527				FD_SET(tcpsock, &v4bits);
528				maxsock = tcpsock;
529				connect_type_cnt++;
530			}
531		}
532		if (rpcbreg == 1) {
533			memset(&hints, 0, sizeof hints);
534			hints.ai_flags = AI_PASSIVE;
535			hints.ai_family = AF_INET;
536			hints.ai_socktype = SOCK_STREAM;
537			hints.ai_protocol = IPPROTO_TCP;
538			ecode = getaddrinfo(NULL, "nfs", &hints,
539			     &ai_tcp);
540			if (ecode != 0) {
541				syslog(LOG_ERR, "getaddrinfo tcp: %s",
542				   gai_strerror(ecode));
543				nfsd_exit(1);
544			}
545			nconf_tcp = getnetconfigent("tcp");
546			if (nconf_tcp == NULL)
547				err(1, "getnetconfigent tcp failed");
548			nb_tcp.buf = ai_tcp->ai_addr;
549			nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
550			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp,
551			    &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3,
552			    nconf_tcp, &nb_tcp)))
553				err(1, "rpcb_set tcp failed");
554			freeaddrinfo(ai_tcp);
555		}
556	}
557
558	/* Set up the socket for tcp6 and rpcb register it. */
559	if (tcpflag && ip6flag) {
560		rpcbreg = 0;
561		for (i = 0; i < bindhostc; i++) {
562			memset(&hints, 0, sizeof hints);
563			hints.ai_flags = AI_PASSIVE;
564			hints.ai_family = AF_INET6;
565			hints.ai_socktype = SOCK_STREAM;
566			hints.ai_protocol = IPPROTO_TCP;
567			if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) {
568				rpcbreg = 1;
569				rpcbregcnt++;
570				if ((tcp6sock = socket(ai_tcp6->ai_family,
571				    ai_tcp6->ai_socktype,
572				    ai_tcp6->ai_protocol)) < 0) {
573					syslog(LOG_ERR,
574					    "can't create tcp6 socket");
575					nfsd_exit(1);
576				}
577				if (setsockopt(tcp6sock, SOL_SOCKET,
578				    SO_REUSEADDR,
579				    (char *)&on, sizeof(on)) < 0)
580					syslog(LOG_ERR,
581					    "setsockopt SO_REUSEADDR: %m");
582				if (setsockopt(tcp6sock, IPPROTO_IPV6,
583				    IPV6_BINDV6ONLY, &on, sizeof on) < 0) {
584					syslog(LOG_ERR,
585					"can't set v6-only binding for tcp6 "
586					    "socket: %m");
587					nfsd_exit(1);
588				}
589				if (bind(tcp6sock, ai_tcp6->ai_addr,
590				    ai_tcp6->ai_addrlen) < 0) {
591					syslog(LOG_ERR,
592					    "can't bind tcp6 addr %s: %m",
593					    bindhost[i]);
594					nfsd_exit(1);
595				}
596				if (listen(tcp6sock, 5) < 0) {
597					syslog(LOG_ERR, "listen failed");
598					nfsd_exit(1);
599				}
600				freeaddrinfo(ai_tcp6);
601				FD_SET(tcp6sock, &sockbits);
602				FD_SET(tcp6sock, &v6bits);
603				if (maxsock < tcp6sock)
604					maxsock = tcp6sock;
605				connect_type_cnt++;
606			}
607		}
608		if (rpcbreg == 1) {
609			memset(&hints, 0, sizeof hints);
610			hints.ai_flags = AI_PASSIVE;
611			hints.ai_family = AF_INET6;
612			hints.ai_socktype = SOCK_STREAM;
613			hints.ai_protocol = IPPROTO_TCP;
614			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
615			if (ecode != 0) {
616				syslog(LOG_ERR, "getaddrinfo tcp6: %s",
617				   gai_strerror(ecode));
618				nfsd_exit(1);
619			}
620			nconf_tcp6 = getnetconfigent("tcp6");
621			if (nconf_tcp6 == NULL)
622				err(1, "getnetconfigent tcp6 failed");
623			nb_tcp6.buf = ai_tcp6->ai_addr;
624			nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
625			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
626			    (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
627				err(1, "rpcb_set tcp6 failed");
628			freeaddrinfo(ai_tcp6);
629		}
630	}
631
632	if (rpcbregcnt == 0) {
633		syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m");
634		nfsd_exit(1);
635	}
636
637	if (tcpflag && connect_type_cnt == 0) {
638		syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m");
639		nfsd_exit(1);
640	}
641
642	setproctitle("master");
643	/*
644	 * We always want a master to have a clean way to to shut nfsd down
645	 * (with unregistration): if the master is killed, it unregisters and
646	 * kills all children. If we run for UDP only (and so do not have to
647	 * loop waiting waiting for accept), we instead make the parent
648	 * a "server" too. start_server will not return.
649	 */
650	if (!tcpflag)
651		start_server(1);
652
653	/*
654	 * Loop forever accepting connections and passing the sockets
655	 * into the kernel for the mounts.
656	 */
657	for (;;) {
658		ready = sockbits;
659		if (connect_type_cnt > 1) {
660			if (select(maxsock + 1,
661			    &ready, NULL, NULL, NULL) < 1) {
662				syslog(LOG_ERR, "select failed: %m");
663				nfsd_exit(1);
664			}
665		}
666		for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) {
667			if (FD_ISSET(tcpsock, &ready)) {
668				if (FD_ISSET(tcpsock, &v4bits)) {
669					len = sizeof(inetpeer);
670					if ((msgsock = accept(tcpsock,
671					    (struct sockaddr *)&inetpeer, &len)) < 0) {
672						syslog(LOG_ERR, "accept failed: %m");
673						nfsd_exit(1);
674					}
675					memset(inetpeer.sin_zero, 0,
676						sizeof(inetpeer.sin_zero));
677					if (setsockopt(msgsock, SOL_SOCKET,
678					    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
679						syslog(LOG_ERR,
680						    "setsockopt SO_KEEPALIVE: %m");
681					nfsdargs.sock = msgsock;
682					nfsdargs.name = (caddr_t)&inetpeer;
683					nfsdargs.namelen = len;
684					nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
685					(void)close(msgsock);
686				} else if (FD_ISSET(tcpsock, &v6bits)) {
687					len = sizeof(inet6peer);
688					if ((msgsock = accept(tcpsock,
689					    (struct sockaddr *)&inet6peer,
690					    &len)) < 0) {
691						syslog(LOG_ERR,
692						     "accept failed: %m");
693						nfsd_exit(1);
694					}
695					if (setsockopt(msgsock, SOL_SOCKET,
696					    SO_KEEPALIVE, (char *)&on,
697					    sizeof(on)) < 0)
698						syslog(LOG_ERR, "setsockopt "
699						    "SO_KEEPALIVE: %m");
700					nfsdargs.sock = msgsock;
701					nfsdargs.name = (caddr_t)&inet6peer;
702					nfsdargs.namelen = len;
703					nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
704					(void)close(msgsock);
705				}
706			}
707		}
708	}
709}
710
711int
712setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints)
713{
714	int ecode;
715	u_int32_t host_addr[4];  /* IPv4 or IPv6 */
716	const char *hostptr;
717
718	if (bindhost == NULL || strcmp("*", bindhost) == 0)
719		hostptr = NULL;
720	else
721		hostptr = bindhost;
722
723	if (hostptr != NULL) {
724		switch (hints.ai_family) {
725		case AF_INET:
726			if (inet_pton(AF_INET, hostptr, host_addr) == 1) {
727				hints.ai_flags = AI_NUMERICHOST;
728			} else {
729				if (inet_pton(AF_INET6, hostptr,
730				    host_addr) == 1)
731					return (1);
732			}
733			break;
734		case AF_INET6:
735			if (inet_pton(AF_INET6, hostptr, host_addr) == 1) {
736				hints.ai_flags = AI_NUMERICHOST;
737			} else {
738				if (inet_pton(AF_INET, hostptr,
739				    host_addr) == 1)
740					return (1);
741			}
742			break;
743		default:
744			break;
745		}
746	}
747
748	ecode = getaddrinfo(hostptr, "nfs", &hints, ai);
749	if (ecode != 0) {
750		syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost,
751		    gai_strerror(ecode));
752		return (1);
753	}
754	return (0);
755}
756
757void
758usage()
759{
760	(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
761	exit(1);
762}
763
764void
765nonfs(signo)
766	int signo;
767{
768	syslog(LOG_ERR, "missing system call: NFS not available");
769}
770
771void
772reapchild(signo)
773	int signo;
774{
775	pid_t pid;
776	int i;
777
778	while ((pid = wait3(NULL, WNOHANG, NULL)) > 0) {
779		for (i = 0; i < nfsdcnt; i++)
780			if (pid == children[i])
781				children[i] = -1;
782	}
783}
784
785void
786unregistration()
787{
788	if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) ||
789	    (!rpcb_unset(RPCPROG_NFS, 3, NULL)))
790		syslog(LOG_ERR, "rpcb_unset failed");
791}
792
793void
794killchildren()
795{
796	int i;
797
798	for (i = 0; i < nfsdcnt; i++) {
799		if (children[i] > 0)
800			kill(children[i], SIGKILL);
801	}
802}
803
804/*
805 * Cleanup master after SIGUSR1.
806 */
807void
808cleanup(signo)
809{
810	nfsd_exit(0);
811}
812
813/*
814 * Cleanup child after SIGUSR1.
815 */
816void
817child_cleanup(signo)
818{
819	exit(0);
820}
821
822void
823nfsd_exit(int status)
824{
825	killchildren();
826	unregistration();
827	exit(status);
828}
829
830void
831start_server(int master)
832{
833	int status;
834
835	status = 0;
836	nsd.nsd_nfsd = NULL;
837	if (nfssvc(NFSSVC_NFSD, &nsd) < 0) {
838		syslog(LOG_ERR, "nfssvc: %m");
839		status = 1;
840	}
841	if (master)
842		nfsd_exit(status);
843	else
844		exit(status);
845}
846