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