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