xref: /freebsd/usr.sbin/nfsd/nfsd.c (revision 3ff369fed2a08f32dda232c10470b949bef9489f)
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
38 static 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
45 static char sccsid[] = "@(#)nfsd.c	8.9 (Berkeley) 3/29/95";
46 #endif
47 static const char rcsid[] =
48   "$FreeBSD$";
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)
79 int	debug = 1;
80 #else
81 int	debug = 0;
82 #endif
83 
84 struct	nfsd_srvargs nsd;
85 
86 #define	MAXNFSDCNT	20
87 #define	DEFNFSDCNT	 4
88 pid_t	children[MAXNFSDCNT];	/* PIDs of children */
89 int	nfsdcnt;		/* number of children */
90 
91 void	cleanup(int);
92 void	child_cleanup(int);
93 void	killchildren(void);
94 void	nfsd_exit(int);
95 void	nonfs(int);
96 void	reapchild(int);
97 int	setbindhost(struct addrinfo **ia, const char *bindhost,
98 	    struct addrinfo hints);
99 void	start_server(int);
100 void	unregistration(void);
101 void	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  */
122 int
123 main(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 server is 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 
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()
759 {
760 	(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
761 	exit(1);
762 }
763 
764 void
765 nonfs(signo)
766 	int signo;
767 {
768 	syslog(LOG_ERR, "missing system call: NFS not available");
769 }
770 
771 void
772 reapchild(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 
785 void
786 unregistration()
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 
793 void
794 killchildren()
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  */
807 void
808 cleanup(signo)
809 {
810 	nfsd_exit(0);
811 }
812 
813 /*
814  * Cleanup child after SIGUSR1.
815  */
816 void
817 child_cleanup(signo)
818 {
819 	exit(0);
820 }
821 
822 void
823 nfsd_exit(int status)
824 {
825 	killchildren();
826 	unregistration();
827 	exit(status);
828 }
829 
830 void
831 start_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