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