xref: /netbsd-src/usr.sbin/nfsd/nfsd.c (revision df0caa2637da0538ecdf6b878c4d08e684b43d8f)
1 /*	$NetBSD: nfsd.c,v 1.45 2005/06/02 06:54:02 lukem 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.45 2005/06/02 06:54:02 lukem 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 #ifdef NFSKERB
72 #include <des.h>
73 #include <kerberosIV/krb.h>
74 #endif
75 
76 #include <err.h>
77 #include <errno.h>
78 #include <fcntl.h>
79 #include <grp.h>
80 #include <pwd.h>
81 #include <signal.h>
82 #include <stdio.h>
83 #include <stdlib.h>
84 #include <string.h>
85 #include <syslog.h>
86 #include <unistd.h>
87 #include <netdb.h>
88 
89 /* Global defs */
90 #ifdef DEBUG
91 #define	syslog(e, s)	fprintf(stderr,(s))
92 int	debug = 1;
93 #else
94 int	debug = 0;
95 #endif
96 
97 struct	nfsd_srvargs nsd;
98 
99 #ifdef NFSKERB
100 char		lnam[ANAME_SZ];
101 KTEXT_ST	kt;
102 AUTH_DAT	kauth;
103 char		inst[INST_SZ];
104 struct nfsrpc_fullblock kin, kout;
105 struct nfsrpc_fullverf kverf;
106 NFSKERBKEY_T	kivec;
107 struct timeval	ktv;
108 NFSKERBKEYSCHED_T kerb_keysched;
109 #endif
110 
111 int	main __P((int, char **));
112 void	nonfs __P((int));
113 void	reapchild __P((int));
114 void	usage __P((void));
115 
116 /*
117  * Nfs server daemon mostly just a user context for nfssvc()
118  *
119  * 1 - do file descriptor and signal cleanup
120  * 2 - fork the nfsd(s)
121  * 3 - create server socket(s)
122  * 4 - register socket with portmap
123  *
124  * For connectionless protocols, just pass the socket into the kernel via
125  * nfssvc().
126  * For connection based sockets, loop doing accepts. When you get a new
127  * socket from accept, pass the msgsock into the kernel via nfssvc().
128  * The arguments are:
129  *	-c - support iso cltp clients
130  *	-r - reregister with portmapper
131  *	-t - support tcp nfs clients
132  *	-u - support udp nfs clients
133  * followed by "n" which is the number of nfsds' to fork off
134  */
135 int
136 main(argc, argv)
137 	int argc;
138 	char *argv[];
139 {
140 	struct nfsd_args nfsdargs;
141 	struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
142 	struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
143 	struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
144 	struct sockaddr_in inetpeer;
145 	struct sockaddr_in6 inet6peer;
146 #ifdef ISO
147 	struct sockaddr_iso isoaddr, isopeer;
148 #endif
149 	struct pollfd set[4];
150 	int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
151 	int nfsdcnt, nfssvc_flag, on = 1, reregister, sock, tcpflag, tcpsock;
152 	int tcp6sock, ip6flag;
153 	int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag, ecode, s;
154 #ifdef NFSKERB
155 	struct group *grp;
156 	struct passwd *pwd;
157 	struct ucred *cr;
158 	struct timeval ktv;
159 	int tp4sock, tpipsock;
160 	char *cp, **cpp;
161 #endif
162 
163 #define	MAXNFSDCNT	1024
164 #define	DEFNFSDCNT	 4
165 	nfsdcnt = DEFNFSDCNT;
166 	cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
167 	tpipflag = udpflag = ip6flag = 0;
168 	nconf_udp = nconf_tcp = nconf_udp6 = nconf_tcp6 = NULL;
169 	maxsock = 0;
170 	tcpsock = tcp6sock = -1;
171 #ifdef ISO
172 #define	GETOPT	"6cn:rtu"
173 #define	USAGE	"[-crtu] [-n num_servers]"
174 #else
175 #define	GETOPT	"6n:rtu"
176 #define	USAGE	"[-rtu] [-n num_servers]"
177 #endif
178 	while ((ch = getopt(argc, argv, GETOPT)) != -1) {
179 		switch (ch) {
180 		case '6':
181 			ip6flag = 1;
182 			s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
183 			if (s < 0 && (errno == EPROTONOSUPPORT ||
184 			    errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
185 				ip6flag = 0;
186 			else
187 				close(s);
188 			break;
189 		case 'n':
190 			nfsdcnt = atoi(optarg);
191 			if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
192 				warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
193 				nfsdcnt = DEFNFSDCNT;
194 			}
195 			break;
196 		case 'r':
197 			reregister = 1;
198 			break;
199 		case 't':
200 			tcpflag = 1;
201 			break;
202 		case 'u':
203 			udpflag = 1;
204 			break;
205 #ifdef ISO
206 		case 'c':
207 			cltpflag = 1;
208 			break;
209 #ifdef notyet
210 		case 'i':
211 			tp4cnt = 1;
212 			break;
213 		case 'p':
214 			tpipcnt = 1;
215 			break;
216 #endif /* notyet */
217 #endif /* ISO */
218 		default:
219 		case '?':
220 			usage();
221 		};
222 	}
223 	argv += optind;
224 	argc -= optind;
225 
226 	/*
227 	 * XXX
228 	 * Backward compatibility, trailing number is the count of daemons.
229 	 */
230 	if (argc > 1)
231 		usage();
232 	if (argc == 1) {
233 		nfsdcnt = atoi(argv[0]);
234 		if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
235 			warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
236 			nfsdcnt = DEFNFSDCNT;
237 		}
238 	}
239 
240 	/*
241 	 * If none of TCP or UDP are specified, default to UDP only.
242 	 */
243 	if (tcpflag == 0 && udpflag == 0)
244 		udpflag = 1;
245 
246 	if (debug == 0) {
247 		daemon(0, 0);
248 		(void)signal(SIGHUP, SIG_IGN);
249 		(void)signal(SIGINT, SIG_IGN);
250 		(void)signal(SIGQUIT, SIG_IGN);
251 		(void)signal(SIGSYS, nonfs);
252 	}
253 	(void)signal(SIGCHLD, reapchild);
254 
255 	if (udpflag) {
256 		memset(&hints, 0, sizeof hints);
257 		hints.ai_flags = AI_PASSIVE;
258 		hints.ai_family = PF_INET;
259 		hints.ai_socktype = SOCK_DGRAM;
260 		hints.ai_protocol = IPPROTO_UDP;
261 
262 		ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
263 		if (ecode != 0) {
264 			syslog(LOG_ERR, "getaddrinfo udp: %s",
265 			    gai_strerror(ecode));
266 			exit(1);
267 		}
268 
269 		nconf_udp = getnetconfigent("udp");
270 
271 		if (nconf_udp == NULL)
272 			err(1, "getnetconfigent udp failed");
273 
274 		nb_udp.buf = ai_udp->ai_addr;
275 		nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
276 		if (reregister)
277 			if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp))
278 				err(1, "rpcb_set udp failed");
279 	}
280 
281 	if (tcpflag) {
282 		memset(&hints, 0, sizeof hints);
283 		hints.ai_flags = AI_PASSIVE;
284 		hints.ai_family = PF_INET;
285 		hints.ai_socktype = SOCK_STREAM;
286 		hints.ai_protocol = IPPROTO_TCP;
287 
288 		ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
289 		if (ecode != 0) {
290 			syslog(LOG_ERR, "getaddrinfo udp: %s",
291 			    gai_strerror(ecode));
292 			exit(1);
293 		}
294 
295 		nconf_tcp = getnetconfigent("tcp");
296 
297 		if (nconf_tcp == NULL)
298 			err(1, "getnetconfigent tcp failed");
299 
300 		nb_tcp.buf = ai_tcp->ai_addr;
301 		nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
302 		if (reregister)
303 			if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp))
304 				err(1, "rpcb_set tcp failed");
305 	}
306 
307 	if (udpflag && ip6flag) {
308 		memset(&hints, 0, sizeof hints);
309 		hints.ai_flags = AI_PASSIVE;
310 		hints.ai_family = PF_INET6;
311 		hints.ai_socktype = SOCK_DGRAM;
312 		hints.ai_protocol = IPPROTO_UDP;
313 
314 		ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
315 		if (ecode != 0) {
316 			syslog(LOG_ERR, "getaddrinfo udp: %s",
317 			    gai_strerror(ecode));
318 			exit(1);
319 		}
320 
321 		nconf_udp6 = getnetconfigent("udp6");
322 
323 		if (nconf_udp6 == NULL)
324 			err(1, "getnetconfigent udp6 failed");
325 
326 		nb_udp6.buf = ai_udp6->ai_addr;
327 		nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
328 		if (reregister)
329 			if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6))
330 				err(1, "rpcb_set udp6 failed");
331 	}
332 
333 	if (tcpflag && ip6flag) {
334 		memset(&hints, 0, sizeof hints);
335 		hints.ai_flags = AI_PASSIVE;
336 		hints.ai_family = PF_INET6;
337 		hints.ai_socktype = SOCK_STREAM;
338 		hints.ai_protocol = IPPROTO_TCP;
339 
340 		ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
341 		if (ecode != 0) {
342 			syslog(LOG_ERR, "getaddrinfo udp: %s",
343 			    gai_strerror(ecode));
344 			exit(1);
345 		}
346 
347 		nconf_tcp6 = getnetconfigent("tcp6");
348 
349 		if (nconf_tcp6 == NULL)
350 			err(1, "getnetconfigent tcp6 failed");
351 
352 		nb_tcp6.buf = ai_tcp6->ai_addr;
353 		nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
354 		if (reregister)
355 			if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6))
356 				err(1, "rpcb_set tcp6 failed");
357 	}
358 
359 	openlog("nfsd", LOG_PID, LOG_DAEMON);
360 
361 	for (i = 0; i < nfsdcnt; i++) {
362 		switch (fork()) {
363 		case -1:
364 			syslog(LOG_ERR, "fork: %m");
365 			exit (1);
366 		case 0:
367 			break;
368 		default:
369 			continue;
370 		}
371 
372 		setproctitle("server");
373 		nfssvc_flag = NFSSVC_NFSD;
374 		nsd.nsd_nfsd = NULL;
375 #ifdef NFSKERB
376 		if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
377 		    sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
378 			syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
379 		nsd.nsd_authstr = (u_char *)&kt;
380 		nsd.nsd_authlen = sizeof (kt);
381 		nsd.nsd_verfstr = (u_char *)&kverf;
382 		nsd.nsd_verflen = sizeof (kverf);
383 #endif
384 		while (nfssvc(nfssvc_flag, &nsd) < 0) {
385 			if (errno != ENEEDAUTH) {
386 				syslog(LOG_ERR, "nfssvc: %m");
387 				exit(1);
388 			}
389 			nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
390 #ifdef NFSKERB
391 			/*
392 			 * Get the Kerberos ticket out of the authenticator
393 			 * verify it and convert the principal name to a user
394 			 * name. The user name is then converted to a set of
395 			 * user credentials via the password and group file.
396 			 * Finally, decrypt the timestamp and validate it.
397 			 * For more info see the IETF Draft "Authentication
398 			 * in ONC RPC".
399 			 */
400 			kt.length = ntohl(kt.length);
401 			if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
402 			    kt.length > 0 && kt.length <=
403 			    (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
404 				kin.w1 = NFS_KERBW1(kt);
405 				kt.mbz = 0;
406 				(void)strcpy(inst, "*");
407 				if (krb_rd_req(&kt, NFS_KERBSRV,
408 				     inst, nsd.nsd_haddr, &kauth, "") ==
409 				     RD_AP_OK &&
410 				    krb_kntoln(&kauth, lnam) == KSUCCESS &&
411 				    (pwd = getpwnam(lnam)) != NULL) {
412 					cr = &nsd.nsd_cr;
413 					cr->cr_uid = pwd->pw_uid;
414 					cr->cr_groups[0] = pwd->pw_gid;
415 					cr->cr_ngroups = 1;
416 					setgrent();
417 					while ((grp = getgrent()) != NULL) {
418 						if (grp->gr_gid ==
419 						    cr->cr_groups[0])
420 							continue;
421 						for (cpp = grp->gr_mem;
422 						    *cpp != NULL; ++cpp)
423 							if (!strcmp(*cpp, lnam))
424 								break;
425 						if (*cpp == NULL)
426 							continue;
427 						cr->cr_groups[cr->cr_ngroups++]
428 						    = grp->gr_gid;
429 						if (cr->cr_ngroups == NGROUPS)
430 							break;
431 					}
432 					endgrent();
433 
434 					/*
435 					 * Get the timestamp verifier out of
436 					 * the authenticator and verifier
437 					 * strings.
438 					 */
439 					kin.t1 = kverf.t1;
440 					kin.t2 = kverf.t2;
441 					kin.w2 = kverf.w2;
442 					memset((caddr_t)kivec, 0,
443 					    sizeof(kivec));
444 					memmove((caddr_t)nsd.nsd_key,
445 					    (caddr_t)kauth.session,
446 					    sizeof(kauth.session));
447 
448 					/*
449 					 * Decrypt the timestamp verifier
450 					 * in CBC mode.
451 					 */
452 					XXX
453 
454 					/*
455 					 * Validate the timestamp verifier, to
456 					 * check that the session key is ok.
457 					 */
458 					nsd.nsd_timestamp.tv_sec =
459 					    ntohl(kout.t1);
460 					nsd.nsd_timestamp.tv_usec =
461 					    ntohl(kout.t2);
462 					nsd.nsd_ttl = ntohl(kout.w1);
463 					if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
464 					    nfssvc_flag =
465 					        NFSSVC_NFSD | NFSSVC_AUTHIN;
466 				}
467 			}
468 #endif /* NFSKERB */
469 		}
470 		exit(0);
471 	}
472 
473 	/* If we are serving udp, set up the socket. */
474 	if (udpflag) {
475 		if ((sock = socket(ai_udp->ai_family, ai_udp->ai_socktype,
476 		    ai_udp->ai_protocol)) < 0) {
477 			syslog(LOG_ERR, "can't create udp socket");
478 			exit(1);
479 		}
480 		if (bind(sock, ai_udp->ai_addr, ai_udp->ai_addrlen) < 0) {
481 			syslog(LOG_ERR, "can't bind udp addr");
482 			exit(1);
483 		}
484 		if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp) ||
485 		    !rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)) {
486 			syslog(LOG_ERR, "can't register with udp portmap");
487 			exit(1);
488 		}
489 		nfsdargs.sock = sock;
490 		nfsdargs.name = NULL;
491 		nfsdargs.namelen = 0;
492 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
493 			syslog(LOG_ERR, "can't add UDP socket");
494 			exit(1);
495 		}
496 		(void)close(sock);
497 	}
498 
499 	if (udpflag &&ip6flag) {
500 		if ((sock = socket(ai_udp6->ai_family, ai_udp6->ai_socktype,
501 		    ai_udp6->ai_protocol)) < 0) {
502 			syslog(LOG_ERR, "can't create udp socket");
503 			exit(1);
504 		}
505 		if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
506 		    &on, sizeof on) < 0) {
507 			syslog(LOG_ERR, "can't set v6-only binding for udp6 "
508 					"socket: %m");
509 			exit(1);
510 		}
511 		if (bind(sock, ai_udp6->ai_addr, ai_udp6->ai_addrlen) < 0) {
512 			syslog(LOG_ERR, "can't bind udp addr");
513 			exit(1);
514 		}
515 		if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6) ||
516 		    !rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)) {
517 			syslog(LOG_ERR, "can't register with udp portmap");
518 			exit(1);
519 		}
520 		nfsdargs.sock = sock;
521 		nfsdargs.name = NULL;
522 		nfsdargs.namelen = 0;
523 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
524 			syslog(LOG_ERR, "can't add UDP6 socket");
525 			exit(1);
526 		}
527 		(void)close(sock);
528 	}
529 
530 #ifdef ISO
531 	/* If we are serving cltp, set up the socket. */
532 	if (cltpflag) {
533 		if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
534 			syslog(LOG_ERR, "can't create cltp socket");
535 			exit(1);
536 		}
537 		memset(&isoaddr, 0, sizeof(isoaddr));
538 		isoaddr.siso_family = AF_ISO;
539 		isoaddr.siso_tlen = 2;
540 		cp = TSEL(&isoaddr);
541 		*cp++ = (NFS_PORT >> 8);
542 		*cp = (NFS_PORT & 0xff);
543 		isoaddr.siso_len = sizeof(isoaddr);
544 		if (bind(sock,
545 		    (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
546 			syslog(LOG_ERR, "can't bind cltp addr");
547 			exit(1);
548 		}
549 #ifdef notyet
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_UDP, NFS_PORT)) {
556 			syslog(LOG_ERR, "can't register with udp portmap");
557 			exit(1);
558 		}
559 #endif /* notyet */
560 		nfsdargs.sock = sock;
561 		nfsdargs.name = NULL;
562 		nfsdargs.namelen = 0;
563 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
564 			syslog(LOG_ERR, "can't add UDP socket");
565 			exit(1);
566 		}
567 		close(sock);
568 	}
569 #endif /* ISO */
570 
571 	/* Now set up the master server socket waiting for tcp connections. */
572 	on = 1;
573 	connect_type_cnt = 0;
574 	if (tcpflag) {
575 		if ((tcpsock = socket(ai_tcp->ai_family, ai_tcp->ai_socktype,
576 		    ai_tcp->ai_protocol)) < 0) {
577 			syslog(LOG_ERR, "can't create tcp socket");
578 			exit(1);
579 		}
580 		if (setsockopt(tcpsock,
581 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
582 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
583 		if (bind(tcpsock, ai_tcp->ai_addr, ai_tcp->ai_addrlen) < 0) {
584 			syslog(LOG_ERR, "can't bind tcp addr");
585 			exit(1);
586 		}
587 		if (listen(tcpsock, 5) < 0) {
588 			syslog(LOG_ERR, "listen failed");
589 			exit(1);
590 		}
591 		if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp) ||
592 		    !rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)) {
593 			syslog(LOG_ERR, "can't register tcp with rpcbind");
594 			exit(1);
595 		}
596 		set[0].fd = tcpsock;
597 		set[0].events = POLLIN;
598 		connect_type_cnt++;
599 	} else
600 		set[0].fd = -1;
601 
602 	if (tcpflag && ip6flag) {
603 		if ((tcp6sock = socket(ai_tcp6->ai_family, ai_tcp6->ai_socktype,
604 		    ai_tcp6->ai_protocol)) < 0) {
605 			syslog(LOG_ERR, "can't create tcp socket");
606 			exit(1);
607 		}
608 		if (setsockopt(tcp6sock,
609 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
610 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
611 		if (setsockopt(tcp6sock, IPPROTO_IPV6, IPV6_V6ONLY,
612 		    &on, sizeof on) < 0) {
613 			syslog(LOG_ERR, "can't set v6-only binding for tcp6 "
614 					"socket: %m");
615 			exit(1);
616 		}
617 		if (bind(tcp6sock, ai_tcp6->ai_addr, ai_tcp6->ai_addrlen) < 0) {
618 			syslog(LOG_ERR, "can't bind tcp6 addr");
619 			exit(1);
620 		}
621 		if (listen(tcp6sock, 5) < 0) {
622 			syslog(LOG_ERR, "listen failed");
623 			exit(1);
624 		}
625 		if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6) ||
626 		    !rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)) {
627 			syslog(LOG_ERR, "can't register tcp6 with rpcbind");
628 			exit(1);
629 		}
630 		set[1].fd = tcp6sock;
631 		set[1].events = POLLIN;
632 		connect_type_cnt++;
633 	} else
634 		set[1].fd = -1;
635 
636 #ifdef notyet
637 	/* Now set up the master server socket waiting for tp4 connections. */
638 	if (tp4flag) {
639 		if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
640 			syslog(LOG_ERR, "can't create tp4 socket");
641 			exit(1);
642 		}
643 		if (setsockopt(tp4sock,
644 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
645 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
646 		memset(&isoaddr, 0, sizeof(isoaddr));
647 		isoaddr.siso_family = AF_ISO;
648 		isoaddr.siso_tlen = 2;
649 		cp = TSEL(&isoaddr);
650 		*cp++ = (NFS_PORT >> 8);
651 		*cp = (NFS_PORT & 0xff);
652 		isoaddr.siso_len = sizeof(isoaddr);
653 		if (bind(tp4sock,
654 		    (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
655 			syslog(LOG_ERR, "can't bind tp4 addr");
656 			exit(1);
657 		}
658 		if (listen(tp4sock, 5) < 0) {
659 			syslog(LOG_ERR, "listen failed");
660 			exit(1);
661 		}
662 		/*
663 		 * XXX
664 		 * Someday this should probably use "rpcbind", the son of
665 		 * portmap.
666 		 */
667 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
668 			syslog(LOG_ERR, "can't register tcp with portmap");
669 			exit(1);
670 		}
671 		set[2].fd = tp4sock;
672 		set[2].events = POLLIN;
673 		connect_type_cnt++;
674 	} else
675 		set[2].fd = -1;
676 
677 	/* Now set up the master server socket waiting for tpip connections. */
678 	if (tpipflag) {
679 		if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
680 			syslog(LOG_ERR, "can't create tpip socket");
681 			exit(1);
682 		}
683 		if (setsockopt(tpipsock,
684 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
685 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
686 		inetaddr.sin_family = AF_INET;
687 		inetaddr.sin_addr.s_addr = INADDR_ANY;
688 		inetaddr.sin_port = htons(NFS_PORT);
689 		inetaddr.sin_len = sizeof(inetaddr);
690 		memset(inetaddr.sin_zero, 0, sizeof(inetaddr.sin_zero));
691 		if (bind(tpipsock,
692 		    (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
693 			syslog(LOG_ERR, "can't bind tcp addr");
694 			exit(1);
695 		}
696 		if (listen(tpipsock, 5) < 0) {
697 			syslog(LOG_ERR, "listen failed");
698 			exit(1);
699 		}
700 		/*
701 		 * XXX
702 		 * Someday this should probably use "rpcbind", the son of
703 		 * portmap.
704 		 */
705 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
706 			syslog(LOG_ERR, "can't register tcp with portmap");
707 			exit(1);
708 		}
709 		set[3].fd = tpipsock;
710 		set[3].events = POLLIN;
711 		connect_type_cnt++;
712 	} else
713 		set[3].fd = -1;
714 #else
715 	set[2].fd = -1;
716 	set[3].fd = -1;
717 #endif /* notyet */
718 
719 	if (connect_type_cnt == 0)
720 		exit(0);
721 
722 	setproctitle("master");
723 
724 	/*
725 	 * Loop forever accepting connections and passing the sockets
726 	 * into the kernel for the mounts.
727 	 */
728 	for (;;) {
729 		if (poll(set, 4, INFTIM) < 1) {
730 			syslog(LOG_ERR, "select failed: %m");
731 			exit(1);
732 		}
733 
734 		if (set[0].revents & POLLIN) {
735 			len = sizeof(inetpeer);
736 			if ((msgsock = accept(tcpsock,
737 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
738 				syslog(LOG_ERR, "accept failed: %m");
739 				exit(1);
740 			}
741 			memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
742 			if (setsockopt(msgsock, SOL_SOCKET,
743 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
744 				syslog(LOG_ERR,
745 				    "setsockopt SO_KEEPALIVE: %m");
746 			nfsdargs.sock = msgsock;
747 			nfsdargs.name = (caddr_t)&inetpeer;
748 			nfsdargs.namelen = sizeof(inetpeer);
749 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
750 			(void)close(msgsock);
751 		}
752 
753 		if (set[1].revents & POLLIN) {
754 			len = sizeof(inet6peer);
755 			if ((msgsock = accept(tcp6sock,
756 			    (struct sockaddr *)&inet6peer, &len)) < 0) {
757 				syslog(LOG_ERR, "accept failed: %m");
758 				exit(1);
759 			}
760 			if (setsockopt(msgsock, SOL_SOCKET,
761 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
762 				syslog(LOG_ERR,
763 				    "setsockopt SO_KEEPALIVE: %m");
764 			nfsdargs.sock = msgsock;
765 			nfsdargs.name = (caddr_t)&inet6peer;
766 			nfsdargs.namelen = sizeof(inet6peer);
767 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
768 			(void)close(msgsock);
769 		}
770 
771 #ifdef notyet
772 		if (set[2].revents & POLLIN) {
773 			len = sizeof(isopeer);
774 			if ((msgsock = accept(tp4sock,
775 			    (struct sockaddr *)&isopeer, &len)) < 0) {
776 				syslog(LOG_ERR, "accept failed: %m");
777 				exit(1);
778 			}
779 			if (setsockopt(msgsock, SOL_SOCKET,
780 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
781 				syslog(LOG_ERR,
782 				    "setsockopt SO_KEEPALIVE: %m");
783 			nfsdargs.sock = msgsock;
784 			nfsdargs.name = (caddr_t)&isopeer;
785 			nfsdargs.namelen = len;
786 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
787 			(void)close(msgsock);
788 		}
789 
790 		if (set[3].revents & POLLIN) {
791 			len = sizeof(inetpeer);
792 			if ((msgsock = accept(tpipsock,
793 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
794 				syslog(LOG_ERR, "accept failed: %m");
795 				exit(1);
796 			}
797 			if (setsockopt(msgsock, SOL_SOCKET,
798 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
799 				syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
800 			nfsdargs.sock = msgsock;
801 			nfsdargs.name = (caddr_t)&inetpeer;
802 			nfsdargs.namelen = len;
803 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
804 			(void)close(msgsock);
805 		}
806 #endif /* notyet */
807 	}
808 }
809 
810 void
811 usage()
812 {
813 
814 	(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
815 	exit(1);
816 }
817 
818 void
819 nonfs(signo)
820 	int signo;
821 {
822 
823 	syslog(LOG_ERR, "missing system call: NFS not available.");
824 }
825 
826 void
827 reapchild(signo)
828 	int signo;
829 {
830 
831 	while (wait3(NULL, WNOHANG, NULL) > 0);
832 }
833