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