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