Home | History | Annotate | Line # | Download | only in nfsd
nfsd.c revision 1.45
      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