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