xref: /netbsd-src/usr.sbin/nfsd/nfsd.c (revision ce2c90c7c172d95d2402a5b3d96d8f8e6d138a21)
1 /*	$NetBSD: nfsd.c,v 1.49 2006/10/07 17:27:57 elad Exp $	*/
2 
3 /*
4  * Copyright (c) 1989, 1993, 1994
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Rick Macklem at The University of Guelph.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include <sys/cdefs.h>
36 #ifndef lint
37 __COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\n\
38 	The Regents of the University of California.  All rights reserved.\n");
39 #endif /* not lint */
40 
41 #ifndef lint
42 #if 0
43 static char sccsid[] = "@(#)nfsd.c	8.9 (Berkeley) 3/29/95";
44 #else
45 __RCSID("$NetBSD: nfsd.c,v 1.49 2006/10/07 17:27:57 elad Exp $");
46 #endif
47 #endif /* not lint */
48 
49 #include <sys/param.h>
50 #include <sys/ioctl.h>
51 #include <sys/stat.h>
52 #include <sys/wait.h>
53 #include <sys/uio.h>
54 #include <sys/ucred.h>
55 #include <sys/mount.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
58 #include <poll.h>
59 
60 #include <rpc/rpc.h>
61 #include <rpc/pmap_clnt.h>
62 #include <rpc/pmap_prot.h>
63 
64 #ifdef ISO
65 #include <netiso/iso.h>
66 #endif
67 #include <nfs/rpcv2.h>
68 #include <nfs/nfsproto.h>
69 #include <nfs/nfs.h>
70 
71 #include <err.h>
72 #include <errno.h>
73 #include <fcntl.h>
74 #include <grp.h>
75 #include <pwd.h>
76 #include <signal.h>
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <string.h>
80 #include <syslog.h>
81 #include <unistd.h>
82 #include <netdb.h>
83 
84 /* Global defs */
85 #ifdef DEBUG
86 #define	syslog(e, s)	fprintf(stderr,(s))
87 int	debug = 1;
88 #else
89 int	debug = 0;
90 #endif
91 
92 struct	nfsd_srvargs nsd;
93 
94 int	main __P((int, char **));
95 void	nonfs __P((int));
96 void	reapchild __P((int));
97 void	usage __P((void));
98 
99 /*
100  * Nfs server daemon mostly just a user context for nfssvc()
101  *
102  * 1 - do file descriptor and signal cleanup
103  * 2 - fork the nfsd(s)
104  * 3 - create server socket(s)
105  * 4 - register socket with portmap
106  *
107  * For connectionless protocols, just pass the socket into the kernel via
108  * nfssvc().
109  * For connection based sockets, loop doing accepts. When you get a new
110  * socket from accept, pass the msgsock into the kernel via nfssvc().
111  * The arguments are:
112  *	-c - support iso cltp clients
113  *	-r - reregister with portmapper
114  *	-t - support tcp nfs clients
115  *	-u - support udp nfs clients
116  * followed by "n" which is the number of nfsds' to fork off
117  */
118 int
119 main(argc, argv)
120 	int argc;
121 	char *argv[];
122 {
123 	struct nfsd_args nfsdargs;
124 	struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
125 	struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
126 	struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
127 	struct sockaddr_in inetpeer;
128 	struct sockaddr_in6 inet6peer;
129 #ifdef ISO
130 	struct sockaddr_iso isoaddr, isopeer;
131 #endif
132 	struct pollfd set[4];
133 	socklen_t len;
134 	int ch, cltpflag, connect_type_cnt, i, maxsock, msgsock;
135 	int nfsdcnt, nfssvc_flag, on = 1, reregister, sock, tcpflag, tcpsock;
136 	int tcp6sock, ip6flag;
137 	int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag, ecode, s;
138 
139 #define	MAXNFSDCNT	1024
140 #define	DEFNFSDCNT	 4
141 	nfsdcnt = DEFNFSDCNT;
142 	cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
143 	tpipflag = udpflag = ip6flag = 0;
144 	nconf_udp = nconf_tcp = nconf_udp6 = nconf_tcp6 = NULL;
145 	maxsock = 0;
146 	tcpsock = tcp6sock = -1;
147 #ifdef ISO
148 #define	GETOPT	"6cn:rtu"
149 #define	USAGE	"[-crtu] [-n num_servers]"
150 #else
151 #define	GETOPT	"6n:rtu"
152 #define	USAGE	"[-rtu] [-n num_servers]"
153 #endif
154 	while ((ch = getopt(argc, argv, GETOPT)) != -1) {
155 		switch (ch) {
156 		case '6':
157 			ip6flag = 1;
158 			s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
159 			if (s < 0 && (errno == EPROTONOSUPPORT ||
160 			    errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
161 				ip6flag = 0;
162 			else
163 				close(s);
164 			break;
165 		case 'n':
166 			nfsdcnt = atoi(optarg);
167 			if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
168 				warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
169 				nfsdcnt = DEFNFSDCNT;
170 			}
171 			break;
172 		case 'r':
173 			reregister = 1;
174 			break;
175 		case 't':
176 			tcpflag = 1;
177 			break;
178 		case 'u':
179 			udpflag = 1;
180 			break;
181 #ifdef ISO
182 		case 'c':
183 			cltpflag = 1;
184 			break;
185 #ifdef notyet
186 		case 'i':
187 			tp4cnt = 1;
188 			break;
189 		case 'p':
190 			tpipcnt = 1;
191 			break;
192 #endif /* notyet */
193 #endif /* ISO */
194 		default:
195 		case '?':
196 			usage();
197 		};
198 	}
199 	argv += optind;
200 	argc -= optind;
201 
202 	/*
203 	 * XXX
204 	 * Backward compatibility, trailing number is the count of daemons.
205 	 */
206 	if (argc > 1)
207 		usage();
208 	if (argc == 1) {
209 		nfsdcnt = atoi(argv[0]);
210 		if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
211 			warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
212 			nfsdcnt = DEFNFSDCNT;
213 		}
214 	}
215 
216 	/*
217 	 * If none of TCP or UDP are specified, default to UDP only.
218 	 */
219 	if (tcpflag == 0 && udpflag == 0)
220 		udpflag = 1;
221 
222 	if (debug == 0) {
223 		daemon(0, 0);
224 		(void)signal(SIGHUP, SIG_IGN);
225 		(void)signal(SIGINT, SIG_IGN);
226 		(void)signal(SIGQUIT, SIG_IGN);
227 		(void)signal(SIGSYS, nonfs);
228 	}
229 	(void)signal(SIGCHLD, reapchild);
230 
231 	if (udpflag) {
232 		memset(&hints, 0, sizeof hints);
233 		hints.ai_flags = AI_PASSIVE;
234 		hints.ai_family = PF_INET;
235 		hints.ai_socktype = SOCK_DGRAM;
236 		hints.ai_protocol = IPPROTO_UDP;
237 
238 		ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
239 		if (ecode != 0) {
240 			syslog(LOG_ERR, "getaddrinfo udp: %s",
241 			    gai_strerror(ecode));
242 			exit(1);
243 		}
244 
245 		nconf_udp = getnetconfigent("udp");
246 
247 		if (nconf_udp == NULL)
248 			err(1, "getnetconfigent udp failed");
249 
250 		nb_udp.buf = ai_udp->ai_addr;
251 		nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
252 		if (reregister)
253 			if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp))
254 				err(1, "rpcb_set udp failed");
255 	}
256 
257 	if (tcpflag) {
258 		memset(&hints, 0, sizeof hints);
259 		hints.ai_flags = AI_PASSIVE;
260 		hints.ai_family = PF_INET;
261 		hints.ai_socktype = SOCK_STREAM;
262 		hints.ai_protocol = IPPROTO_TCP;
263 
264 		ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
265 		if (ecode != 0) {
266 			syslog(LOG_ERR, "getaddrinfo tcp: %s",
267 			    gai_strerror(ecode));
268 			exit(1);
269 		}
270 
271 		nconf_tcp = getnetconfigent("tcp");
272 
273 		if (nconf_tcp == NULL)
274 			err(1, "getnetconfigent tcp failed");
275 
276 		nb_tcp.buf = ai_tcp->ai_addr;
277 		nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
278 		if (reregister)
279 			if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp))
280 				err(1, "rpcb_set tcp failed");
281 	}
282 
283 	if (udpflag && ip6flag) {
284 		memset(&hints, 0, sizeof hints);
285 		hints.ai_flags = AI_PASSIVE;
286 		hints.ai_family = PF_INET6;
287 		hints.ai_socktype = SOCK_DGRAM;
288 		hints.ai_protocol = IPPROTO_UDP;
289 
290 		ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
291 		if (ecode != 0) {
292 			syslog(LOG_ERR, "getaddrinfo udp: %s",
293 			    gai_strerror(ecode));
294 			exit(1);
295 		}
296 
297 		nconf_udp6 = getnetconfigent("udp6");
298 
299 		if (nconf_udp6 == NULL)
300 			err(1, "getnetconfigent udp6 failed");
301 
302 		nb_udp6.buf = ai_udp6->ai_addr;
303 		nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
304 		if (reregister)
305 			if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6))
306 				err(1, "rpcb_set udp6 failed");
307 	}
308 
309 	if (tcpflag && ip6flag) {
310 		memset(&hints, 0, sizeof hints);
311 		hints.ai_flags = AI_PASSIVE;
312 		hints.ai_family = PF_INET6;
313 		hints.ai_socktype = SOCK_STREAM;
314 		hints.ai_protocol = IPPROTO_TCP;
315 
316 		ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
317 		if (ecode != 0) {
318 			syslog(LOG_ERR, "getaddrinfo tcp: %s",
319 			    gai_strerror(ecode));
320 			exit(1);
321 		}
322 
323 		nconf_tcp6 = getnetconfigent("tcp6");
324 
325 		if (nconf_tcp6 == NULL)
326 			err(1, "getnetconfigent tcp6 failed");
327 
328 		nb_tcp6.buf = ai_tcp6->ai_addr;
329 		nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
330 		if (reregister)
331 			if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6))
332 				err(1, "rpcb_set tcp6 failed");
333 	}
334 
335 	openlog("nfsd", LOG_PID, LOG_DAEMON);
336 
337 	for (i = 0; i < nfsdcnt; i++) {
338 		switch (fork()) {
339 		case -1:
340 			syslog(LOG_ERR, "fork: %m");
341 			exit (1);
342 		case 0:
343 			break;
344 		default:
345 			continue;
346 		}
347 
348 		setproctitle("server");
349 		nfssvc_flag = NFSSVC_NFSD;
350 		nsd.nsd_nfsd = NULL;
351 		while (nfssvc(nfssvc_flag, &nsd) < 0) {
352 			if (errno != ENEEDAUTH) {
353 				syslog(LOG_ERR, "nfssvc: %m");
354 				exit(1);
355 			}
356 			nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
357 		}
358 		exit(0);
359 	}
360 
361 	/* If we are serving udp, set up the socket. */
362 	if (udpflag) {
363 		if ((sock = socket(ai_udp->ai_family, ai_udp->ai_socktype,
364 		    ai_udp->ai_protocol)) < 0) {
365 			syslog(LOG_ERR, "can't create udp socket");
366 			exit(1);
367 		}
368 		if (bind(sock, ai_udp->ai_addr, ai_udp->ai_addrlen) < 0) {
369 			syslog(LOG_ERR, "can't bind udp addr");
370 			exit(1);
371 		}
372 		if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp) ||
373 		    !rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)) {
374 			syslog(LOG_ERR, "can't register with udp portmap");
375 			exit(1);
376 		}
377 		nfsdargs.sock = sock;
378 		nfsdargs.name = NULL;
379 		nfsdargs.namelen = 0;
380 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
381 			syslog(LOG_ERR, "can't add UDP socket");
382 			exit(1);
383 		}
384 		(void)close(sock);
385 	}
386 
387 	if (udpflag &&ip6flag) {
388 		if ((sock = socket(ai_udp6->ai_family, ai_udp6->ai_socktype,
389 		    ai_udp6->ai_protocol)) < 0) {
390 			syslog(LOG_ERR, "can't create udp socket");
391 			exit(1);
392 		}
393 		if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
394 		    &on, sizeof on) < 0) {
395 			syslog(LOG_ERR, "can't set v6-only binding for udp6 "
396 					"socket: %m");
397 			exit(1);
398 		}
399 		if (bind(sock, ai_udp6->ai_addr, ai_udp6->ai_addrlen) < 0) {
400 			syslog(LOG_ERR, "can't bind udp addr");
401 			exit(1);
402 		}
403 		if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6) ||
404 		    !rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)) {
405 			syslog(LOG_ERR, "can't register with udp portmap");
406 			exit(1);
407 		}
408 		nfsdargs.sock = sock;
409 		nfsdargs.name = NULL;
410 		nfsdargs.namelen = 0;
411 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
412 			syslog(LOG_ERR, "can't add UDP6 socket");
413 			exit(1);
414 		}
415 		(void)close(sock);
416 	}
417 
418 #ifdef ISO
419 	/* If we are serving cltp, set up the socket. */
420 	if (cltpflag) {
421 		if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
422 			syslog(LOG_ERR, "can't create cltp socket");
423 			exit(1);
424 		}
425 		memset(&isoaddr, 0, sizeof(isoaddr));
426 		isoaddr.siso_family = AF_ISO;
427 		isoaddr.siso_tlen = 2;
428 		cp = TSEL(&isoaddr);
429 		*cp++ = (NFS_PORT >> 8);
430 		*cp = (NFS_PORT & 0xff);
431 		isoaddr.siso_len = sizeof(isoaddr);
432 		if (bind(sock,
433 		    (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
434 			syslog(LOG_ERR, "can't bind cltp addr");
435 			exit(1);
436 		}
437 #ifdef notyet
438 		/*
439 		 * XXX
440 		 * Someday this should probably use "rpcbind", the son of
441 		 * portmap.
442 		 */
443 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
444 			syslog(LOG_ERR, "can't register with udp portmap");
445 			exit(1);
446 		}
447 #endif /* notyet */
448 		nfsdargs.sock = sock;
449 		nfsdargs.name = NULL;
450 		nfsdargs.namelen = 0;
451 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
452 			syslog(LOG_ERR, "can't add UDP socket");
453 			exit(1);
454 		}
455 		close(sock);
456 	}
457 #endif /* ISO */
458 
459 	/* Now set up the master server socket waiting for tcp connections. */
460 	on = 1;
461 	connect_type_cnt = 0;
462 	if (tcpflag) {
463 		if ((tcpsock = socket(ai_tcp->ai_family, ai_tcp->ai_socktype,
464 		    ai_tcp->ai_protocol)) < 0) {
465 			syslog(LOG_ERR, "can't create tcp socket");
466 			exit(1);
467 		}
468 		if (setsockopt(tcpsock,
469 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
470 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
471 		if (bind(tcpsock, ai_tcp->ai_addr, ai_tcp->ai_addrlen) < 0) {
472 			syslog(LOG_ERR, "can't bind tcp addr");
473 			exit(1);
474 		}
475 		if (listen(tcpsock, 5) < 0) {
476 			syslog(LOG_ERR, "listen failed");
477 			exit(1);
478 		}
479 		if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp) ||
480 		    !rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)) {
481 			syslog(LOG_ERR, "can't register tcp with rpcbind");
482 			exit(1);
483 		}
484 		set[0].fd = tcpsock;
485 		set[0].events = POLLIN;
486 		connect_type_cnt++;
487 	} else
488 		set[0].fd = -1;
489 
490 	if (tcpflag && ip6flag) {
491 		if ((tcp6sock = socket(ai_tcp6->ai_family, ai_tcp6->ai_socktype,
492 		    ai_tcp6->ai_protocol)) < 0) {
493 			syslog(LOG_ERR, "can't create tcp socket");
494 			exit(1);
495 		}
496 		if (setsockopt(tcp6sock,
497 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
498 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
499 		if (setsockopt(tcp6sock, IPPROTO_IPV6, IPV6_V6ONLY,
500 		    &on, sizeof on) < 0) {
501 			syslog(LOG_ERR, "can't set v6-only binding for tcp6 "
502 					"socket: %m");
503 			exit(1);
504 		}
505 		if (bind(tcp6sock, ai_tcp6->ai_addr, ai_tcp6->ai_addrlen) < 0) {
506 			syslog(LOG_ERR, "can't bind tcp6 addr");
507 			exit(1);
508 		}
509 		if (listen(tcp6sock, 5) < 0) {
510 			syslog(LOG_ERR, "listen failed");
511 			exit(1);
512 		}
513 		if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6) ||
514 		    !rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)) {
515 			syslog(LOG_ERR, "can't register tcp6 with rpcbind");
516 			exit(1);
517 		}
518 		set[1].fd = tcp6sock;
519 		set[1].events = POLLIN;
520 		connect_type_cnt++;
521 	} else
522 		set[1].fd = -1;
523 
524 #ifdef notyet
525 	/* Now set up the master server socket waiting for tp4 connections. */
526 	if (tp4flag) {
527 		if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
528 			syslog(LOG_ERR, "can't create tp4 socket");
529 			exit(1);
530 		}
531 		if (setsockopt(tp4sock,
532 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
533 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
534 		memset(&isoaddr, 0, sizeof(isoaddr));
535 		isoaddr.siso_family = AF_ISO;
536 		isoaddr.siso_tlen = 2;
537 		cp = TSEL(&isoaddr);
538 		*cp++ = (NFS_PORT >> 8);
539 		*cp = (NFS_PORT & 0xff);
540 		isoaddr.siso_len = sizeof(isoaddr);
541 		if (bind(tp4sock,
542 		    (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
543 			syslog(LOG_ERR, "can't bind tp4 addr");
544 			exit(1);
545 		}
546 		if (listen(tp4sock, 5) < 0) {
547 			syslog(LOG_ERR, "listen failed");
548 			exit(1);
549 		}
550 		/*
551 		 * XXX
552 		 * Someday this should probably use "rpcbind", the son of
553 		 * portmap.
554 		 */
555 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
556 			syslog(LOG_ERR, "can't register tcp with portmap");
557 			exit(1);
558 		}
559 		set[2].fd = tp4sock;
560 		set[2].events = POLLIN;
561 		connect_type_cnt++;
562 	} else
563 		set[2].fd = -1;
564 
565 	/* Now set up the master server socket waiting for tpip connections. */
566 	if (tpipflag) {
567 		if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
568 			syslog(LOG_ERR, "can't create tpip socket");
569 			exit(1);
570 		}
571 		if (setsockopt(tpipsock,
572 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
573 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
574 		inetaddr.sin_family = AF_INET;
575 		inetaddr.sin_addr.s_addr = INADDR_ANY;
576 		inetaddr.sin_port = htons(NFS_PORT);
577 		inetaddr.sin_len = sizeof(inetaddr);
578 		memset(inetaddr.sin_zero, 0, sizeof(inetaddr.sin_zero));
579 		if (bind(tpipsock,
580 		    (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
581 			syslog(LOG_ERR, "can't bind tcp addr");
582 			exit(1);
583 		}
584 		if (listen(tpipsock, 5) < 0) {
585 			syslog(LOG_ERR, "listen failed");
586 			exit(1);
587 		}
588 		/*
589 		 * XXX
590 		 * Someday this should probably use "rpcbind", the son of
591 		 * portmap.
592 		 */
593 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
594 			syslog(LOG_ERR, "can't register tcp with portmap");
595 			exit(1);
596 		}
597 		set[3].fd = tpipsock;
598 		set[3].events = POLLIN;
599 		connect_type_cnt++;
600 	} else
601 		set[3].fd = -1;
602 #else
603 	set[2].fd = -1;
604 	set[3].fd = -1;
605 #endif /* notyet */
606 
607 	if (connect_type_cnt == 0)
608 		exit(0);
609 
610 	setproctitle("master");
611 
612 	/*
613 	 * Loop forever accepting connections and passing the sockets
614 	 * into the kernel for the mounts.
615 	 */
616 	for (;;) {
617 		if (poll(set, 4, INFTIM) < 1) {
618 			syslog(LOG_ERR, "poll failed: %m");
619 			exit(1);
620 		}
621 
622 		if (set[0].revents & POLLIN) {
623 			len = sizeof(inetpeer);
624 			if ((msgsock = accept(tcpsock,
625 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
626 				syslog(LOG_ERR, "accept failed: %m");
627 				exit(1);
628 			}
629 			memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
630 			if (setsockopt(msgsock, SOL_SOCKET,
631 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
632 				syslog(LOG_ERR,
633 				    "setsockopt SO_KEEPALIVE: %m");
634 			nfsdargs.sock = msgsock;
635 			nfsdargs.name = (caddr_t)&inetpeer;
636 			nfsdargs.namelen = sizeof(inetpeer);
637 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
638 			(void)close(msgsock);
639 		}
640 
641 		if (set[1].revents & POLLIN) {
642 			len = sizeof(inet6peer);
643 			if ((msgsock = accept(tcp6sock,
644 			    (struct sockaddr *)&inet6peer, &len)) < 0) {
645 				syslog(LOG_ERR, "accept failed: %m");
646 				exit(1);
647 			}
648 			if (setsockopt(msgsock, SOL_SOCKET,
649 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
650 				syslog(LOG_ERR,
651 				    "setsockopt SO_KEEPALIVE: %m");
652 			nfsdargs.sock = msgsock;
653 			nfsdargs.name = (caddr_t)&inet6peer;
654 			nfsdargs.namelen = sizeof(inet6peer);
655 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
656 			(void)close(msgsock);
657 		}
658 
659 #ifdef notyet
660 		if (set[2].revents & POLLIN) {
661 			len = sizeof(isopeer);
662 			if ((msgsock = accept(tp4sock,
663 			    (struct sockaddr *)&isopeer, &len)) < 0) {
664 				syslog(LOG_ERR, "accept failed: %m");
665 				exit(1);
666 			}
667 			if (setsockopt(msgsock, SOL_SOCKET,
668 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
669 				syslog(LOG_ERR,
670 				    "setsockopt SO_KEEPALIVE: %m");
671 			nfsdargs.sock = msgsock;
672 			nfsdargs.name = (caddr_t)&isopeer;
673 			nfsdargs.namelen = len;
674 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
675 			(void)close(msgsock);
676 		}
677 
678 		if (set[3].revents & POLLIN) {
679 			len = sizeof(inetpeer);
680 			if ((msgsock = accept(tpipsock,
681 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
682 				syslog(LOG_ERR, "accept failed: %m");
683 				exit(1);
684 			}
685 			if (setsockopt(msgsock, SOL_SOCKET,
686 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
687 				syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
688 			nfsdargs.sock = msgsock;
689 			nfsdargs.name = (caddr_t)&inetpeer;
690 			nfsdargs.namelen = len;
691 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
692 			(void)close(msgsock);
693 		}
694 #endif /* notyet */
695 	}
696 }
697 
698 void
699 usage()
700 {
701 	(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
702 	exit(1);
703 }
704 
705 void
706 nonfs(signo)
707 	int signo;
708 {
709 	syslog(LOG_ERR, "missing system call: NFS not available.");
710 }
711 
712 void
713 reapchild(signo)
714 	int signo;
715 {
716 	while (wait3(NULL, WNOHANG, NULL) > 0);
717 }
718