xref: /dragonfly/sbin/nfsd/nfsd.c (revision 984263bc)
1 /*
2  * Copyright (c) 1989, 1993, 1994
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #ifndef lint
38 static const char copyright[] =
39 "@(#) Copyright (c) 1989, 1993, 1994\n\
40 	The Regents of the University of California.  All rights reserved.\n";
41 #endif not lint
42 
43 #ifndef lint
44 #if 0
45 static char sccsid[] = "@(#)nfsd.c	8.9 (Berkeley) 3/29/95";
46 #endif
47 static const char rcsid[] =
48   "$FreeBSD: src/sbin/nfsd/nfsd.c,v 1.15.2.1 2000/09/16 22:52:23 brian Exp $";
49 #endif not lint
50 
51 #include <sys/param.h>
52 #include <sys/syslog.h>
53 #include <sys/wait.h>
54 #include <sys/mount.h>
55 
56 #include <rpc/rpc.h>
57 #include <rpc/pmap_clnt.h>
58 
59 #include <netdb.h>
60 #include <arpa/inet.h>
61 #ifdef ISO
62 #include <netiso/iso.h>
63 #endif
64 #include <nfs/rpcv2.h>
65 #include <nfs/nfsproto.h>
66 #include <nfs/nfs.h>
67 
68 #ifdef NFSKERB
69 #include <kerberosIV/des.h>
70 #include <kerberosIV/krb.h>
71 #endif
72 
73 #include <err.h>
74 #include <errno.h>
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <strings.h>
78 #include <unistd.h>
79 
80 /* Global defs */
81 #ifdef DEBUG
82 #define	syslog(e, s)	fprintf(stderr,(s))
83 int	debug = 1;
84 #else
85 int	debug = 0;
86 #endif
87 
88 struct	nfsd_srvargs nsd;
89 #ifdef OLD_SETPROCTITLE
90 char	**Argv = NULL;		/* pointer to argument vector */
91 char	*LastArg = NULL;	/* end of argv */
92 #endif
93 
94 #ifdef NFSKERB
95 char		lnam[ANAME_SZ];
96 KTEXT_ST	kt;
97 AUTH_DAT	kauth;
98 char		inst[INST_SZ];
99 struct nfsrpc_fullblock kin, kout;
100 struct nfsrpc_fullverf kverf;
101 NFSKERBKEY_T	kivec;
102 struct timeval	ktv;
103 NFSKERBKEYSCHED_T kerb_keysched;
104 #endif
105 
106 void	nonfs __P((int));
107 void	reapchild __P((int));
108 void	setbindhost __P((struct sockaddr_in *ia, const char *bindhost));
109 #ifdef OLD_SETPROCTITLE
110 #ifdef __FreeBSD__
111 void	setproctitle __P((char *));
112 #endif
113 #endif
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, envp)
137 	int argc;
138 	char *argv[], *envp[];
139 {
140 	struct nfsd_args nfsdargs;
141 	struct sockaddr_in inetaddr, inetpeer;
142 #ifdef ISO
143 	struct sockaddr_iso isoaddr, isopeer;
144 	char *cp;
145 #endif
146 	fd_set ready, sockbits;
147 	int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
148 	int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
149 	int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag;
150 	int bindhostc = 0, bindanyflag;
151 	char **bindhost = NULL;
152 #ifdef notyet
153 	int tp4sock, tpipsock;
154 #endif
155 #ifdef NFSKERB
156 	struct group *grp;
157 	struct passwd *pwd;
158 	struct ucred *cr;
159 	struct timeval ktv;
160 	char **cpp;
161 #endif
162 #ifdef __FreeBSD__
163 	struct vfsconf vfc;
164 	int error;
165 
166 	error = getvfsbyname("nfs", &vfc);
167 	if (error && vfsisloadable("nfs")) {
168 		if (vfsload("nfs"))
169 			err(1, "vfsload(nfs)");
170 		endvfsent();	/* flush cache */
171 		error = getvfsbyname("nfs", &vfc);
172 	}
173 	if (error)
174 		errx(1, "NFS is not available in the running kernel");
175 #endif
176 
177 #ifdef OLD_SETPROCTITLE
178 	/* Save start and extent of argv for setproctitle. */
179 	Argv = argv;
180 	if (envp == 0 || *envp == 0)
181 		envp = argv;
182 	while (*envp)
183 		envp++;
184 	LastArg = envp[-1] + strlen(envp[-1]);
185 #endif
186 
187 #define	MAXNFSDCNT	20
188 #define	DEFNFSDCNT	 4
189 	nfsdcnt = DEFNFSDCNT;
190 	cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
191 	bindanyflag = tpipflag = udpflag = 0;
192 #ifdef ISO
193 #define	GETOPT	"ach:n:rtu"
194 #define	USAGE	"[-acrtu] [-n num_servers] [-h bindip]"
195 #else
196 #define	GETOPT	"ah:n:rtu"
197 #define	USAGE	"[-artu] [-n num_servers] [-h bindip]"
198 #endif
199 	while ((ch = getopt(argc, argv, GETOPT)) != -1)
200 		switch (ch) {
201 		case 'a':
202 			bindanyflag = 1;
203 			break;
204 		case 'n':
205 			nfsdcnt = atoi(optarg);
206 			if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
207 				warnx("nfsd count %d; reset to %d", nfsdcnt,
208 				    DEFNFSDCNT);
209 				nfsdcnt = DEFNFSDCNT;
210 			}
211 			break;
212 		case 'h':
213 			bindhostc++;
214 			bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
215 			if (bindhost == NULL)
216 				errx(1, "Out of memory");
217 			bindhost[bindhostc-1] = strdup(optarg);
218 			if (bindhost[bindhostc-1] == NULL)
219 				errx(1, "Out of memory");
220 			break;
221 		case 'r':
222 			reregister = 1;
223 			break;
224 		case 't':
225 			tcpflag = 1;
226 			break;
227 		case 'u':
228 			udpflag = 1;
229 			break;
230 #ifdef ISO
231 		case 'c':
232 			cltpflag = 1;
233 			break;
234 #ifdef notyet
235 		case 'i':
236 			tp4cnt = 1;
237 			break;
238 		case 'p':
239 			tpipcnt = 1;
240 			break;
241 #endif /* notyet */
242 #endif /* ISO */
243 		default:
244 		case '?':
245 			usage();
246 		};
247 	if (!tcpflag && !udpflag)
248 		udpflag = 1;
249 	argv += optind;
250 	argc -= optind;
251 
252 	/*
253 	 * XXX
254 	 * Backward compatibility, trailing number is the count of daemons.
255 	 */
256 	if (argc > 1)
257 		usage();
258 	if (argc == 1) {
259 		nfsdcnt = atoi(argv[0]);
260 		if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
261 			warnx("nfsd count %d; reset to %d", nfsdcnt,
262 			    DEFNFSDCNT);
263 			nfsdcnt = DEFNFSDCNT;
264 		}
265 	}
266 
267 	if (bindhostc == 0 || bindanyflag) {
268 		bindhostc++;
269 		bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
270 		if (bindhost == NULL)
271 			errx(1, "Out of memory");
272 		bindhost[bindhostc-1] = strdup("*");
273 		if (bindhost[bindhostc-1] == NULL)
274 			errx(1, "Out of memory");
275 	}
276 
277 	if (debug == 0) {
278 		daemon(0, 0);
279 		(void)signal(SIGHUP, SIG_IGN);
280 		(void)signal(SIGINT, SIG_IGN);
281 		(void)signal(SIGQUIT, SIG_IGN);
282 		(void)signal(SIGSYS, nonfs);
283 		(void)signal(SIGTERM, SIG_IGN);
284 	}
285 	(void)signal(SIGCHLD, reapchild);
286 
287 	if (reregister) {
288 		if (udpflag &&
289 		    (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
290 		     !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)))
291 			err(1, "can't register with portmap for UDP");
292 		if (tcpflag &&
293 		    (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
294 		     !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)))
295 			err(1, "can't register with portmap for TCP");
296 		exit(0);
297 	}
298 	openlog("nfsd:", LOG_PID, LOG_DAEMON);
299 
300 	for (i = 0; i < nfsdcnt; i++) {
301 		switch (fork()) {
302 		case -1:
303 			syslog(LOG_ERR, "fork: %m");
304 			exit (1);
305 		case 0:
306 			break;
307 		default:
308 			continue;
309 		}
310 
311 		setproctitle("server");
312 		nfssvc_flag = NFSSVC_NFSD;
313 		nsd.nsd_nfsd = NULL;
314 #ifdef NFSKERB
315 		if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
316 		    sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
317 		    syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
318 		nsd.nsd_authstr = (u_char *)&kt;
319 		nsd.nsd_authlen = sizeof (kt);
320 		nsd.nsd_verfstr = (u_char *)&kverf;
321 		nsd.nsd_verflen = sizeof (kverf);
322 #endif
323 		while (nfssvc(nfssvc_flag, &nsd) < 0) {
324 			if (errno != ENEEDAUTH) {
325 				syslog(LOG_ERR, "nfssvc: %m");
326 				exit(1);
327 			}
328 			nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
329 #ifdef NFSKERB
330 			/*
331 			 * Get the Kerberos ticket out of the authenticator
332 			 * verify it and convert the principal name to a user
333 			 * name. The user name is then converted to a set of
334 			 * user credentials via the password and group file.
335 			 * Finally, decrypt the timestamp and validate it.
336 			 * For more info see the IETF Draft "Authentication
337 			 * in ONC RPC".
338 			 */
339 			kt.length = ntohl(kt.length);
340 			if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
341 			    kt.length > 0 && kt.length <=
342 			    (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
343 			    kin.w1 = NFS_KERBW1(kt);
344 			    kt.mbz = 0;
345 			    (void)strcpy(inst, "*");
346 			    if (krb_rd_req(&kt, NFS_KERBSRV,
347 				inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK &&
348 				krb_kntoln(&kauth, lnam) == KSUCCESS &&
349 				(pwd = getpwnam(lnam)) != NULL) {
350 				cr = &nsd.nsd_cr;
351 				cr->cr_uid = pwd->pw_uid;
352 				cr->cr_groups[0] = pwd->pw_gid;
353 				cr->cr_ngroups = 1;
354 				setgrent();
355 				while ((grp = getgrent()) != NULL) {
356 					if (grp->gr_gid == cr->cr_groups[0])
357 						continue;
358 					for (cpp = grp->gr_mem;
359 					    *cpp != NULL; ++cpp)
360 						if (!strcmp(*cpp, lnam))
361 							break;
362 					if (*cpp == NULL)
363 						continue;
364 					cr->cr_groups[cr->cr_ngroups++]
365 					    = grp->gr_gid;
366 					if (cr->cr_ngroups == NGROUPS)
367 						break;
368 				}
369 				endgrent();
370 
371 				/*
372 				 * Get the timestamp verifier out of the
373 				 * authenticator and verifier strings.
374 				 */
375 				kin.t1 = kverf.t1;
376 				kin.t2 = kverf.t2;
377 				kin.w2 = kverf.w2;
378 				bzero((caddr_t)kivec, sizeof (kivec));
379 				bcopy((caddr_t)kauth.session,
380 				    (caddr_t)nsd.nsd_key,sizeof(kauth.session));
381 
382 				/*
383 				 * Decrypt the timestamp verifier in CBC mode.
384 				 */
385 				XXX
386 
387 				/*
388 				 * Validate the timestamp verifier, to
389 				 * check that the session key is ok.
390 				 */
391 				nsd.nsd_timestamp.tv_sec = ntohl(kout.t1);
392 				nsd.nsd_timestamp.tv_usec = ntohl(kout.t2);
393 				nsd.nsd_ttl = ntohl(kout.w1);
394 				if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
395 				    nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
396 			}
397 #endif /* NFSKERB */
398 		}
399 		exit(0);
400 	}
401 
402 	/* If we are serving udp, set up the socket. */
403 	for (i = 0; udpflag && i < bindhostc; i++) {
404 		if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
405 			syslog(LOG_ERR, "can't create udp socket");
406 			exit(1);
407 		}
408 		setbindhost(&inetaddr, bindhost[i]);
409 		if (bind(sock,
410 		    (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
411 			syslog(LOG_ERR, "can't bind udp addr %s: %m", bindhost[i]);
412 			exit(1);
413 		}
414 		if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
415 		    !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
416 			syslog(LOG_ERR, "can't register with udp portmap");
417 			exit(1);
418 		}
419 		nfsdargs.sock = sock;
420 		nfsdargs.name = NULL;
421 		nfsdargs.namelen = 0;
422 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
423 			syslog(LOG_ERR, "can't Add UDP socket");
424 			exit(1);
425 		}
426 		(void)close(sock);
427 	}
428 
429 #ifdef ISO
430 	/* If we are serving cltp, set up the socket. */
431 	if (cltpflag) {
432 		if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
433 			syslog(LOG_ERR, "can't create cltp socket");
434 			exit(1);
435 		}
436 		memset(&isoaddr, 0, sizeof(isoaddr));
437 		isoaddr.siso_family = AF_ISO;
438 		isoaddr.siso_tlen = 2;
439 		cp = TSEL(&isoaddr);
440 		*cp++ = (NFS_PORT >> 8);
441 		*cp = (NFS_PORT & 0xff);
442 		isoaddr.siso_len = sizeof(isoaddr);
443 		if (bind(sock,
444 		    (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
445 			syslog(LOG_ERR, "can't bind cltp addr");
446 			exit(1);
447 		}
448 #ifdef notyet
449 		/*
450 		 * XXX
451 		 * Someday this should probably use "rpcbind", the son of
452 		 * portmap.
453 		 */
454 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
455 			syslog(LOG_ERR, "can't register with udp portmap");
456 			exit(1);
457 		}
458 #endif /* notyet */
459 		nfsdargs.sock = sock;
460 		nfsdargs.name = NULL;
461 		nfsdargs.namelen = 0;
462 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
463 			syslog(LOG_ERR, "can't add UDP socket");
464 			exit(1);
465 		}
466 		close(sock);
467 	}
468 #endif /* ISO */
469 
470 	/* Now set up the master server socket waiting for tcp connections. */
471 	on = 1;
472 	FD_ZERO(&sockbits);
473 	connect_type_cnt = 0;
474 	for (i = 0; tcpflag && i < bindhostc; i++) {
475 		if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
476 			syslog(LOG_ERR, "can't create tcp socket");
477 			exit(1);
478 		}
479 		if (setsockopt(tcpsock,
480 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
481 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
482 		setbindhost(&inetaddr, bindhost[i]);
483 		if (bind(tcpsock,
484 		    (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
485 			syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]);
486 			exit(1);
487 		}
488 		if (listen(tcpsock, 5) < 0) {
489 			syslog(LOG_ERR, "listen failed");
490 			exit(1);
491 		}
492 		if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
493 		    !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
494 			syslog(LOG_ERR, "can't register tcp with portmap");
495 			exit(1);
496 		}
497 		FD_SET(tcpsock, &sockbits);
498 		maxsock = tcpsock;
499 		connect_type_cnt++;
500 	}
501 
502 #ifdef notyet
503 	/* Now set up the master server socket waiting for tp4 connections. */
504 	if (tp4flag) {
505 		if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
506 			syslog(LOG_ERR, "can't create tp4 socket");
507 			exit(1);
508 		}
509 		if (setsockopt(tp4sock,
510 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
511 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
512 		memset(&isoaddr, 0, sizeof(isoaddr));
513 		isoaddr.siso_family = AF_ISO;
514 		isoaddr.siso_tlen = 2;
515 		cp = TSEL(&isoaddr);
516 		*cp++ = (NFS_PORT >> 8);
517 		*cp = (NFS_PORT & 0xff);
518 		isoaddr.siso_len = sizeof(isoaddr);
519 		if (bind(tp4sock,
520 		    (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) {
521 			syslog(LOG_ERR, "can't bind tp4 addr");
522 			exit(1);
523 		}
524 		if (listen(tp4sock, 5) < 0) {
525 			syslog(LOG_ERR, "listen failed");
526 			exit(1);
527 		}
528 		/*
529 		 * XXX
530 		 * Someday this should probably use "rpcbind", the son of
531 		 * portmap.
532 		 */
533 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
534 			syslog(LOG_ERR, "can't register tcp with portmap");
535 			exit(1);
536 		}
537 		FD_SET(tp4sock, &sockbits);
538 		maxsock = tp4sock;
539 		connect_type_cnt++;
540 	}
541 
542 	/* Now set up the master server socket waiting for tpip connections. */
543 	for (i = 0; tpipflag && i < bindhostc; i++) {
544 		if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
545 			syslog(LOG_ERR, "can't create tpip socket");
546 			exit(1);
547 		}
548 		if (setsockopt(tpipsock,
549 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
550 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
551 		setbindhost(&inetaddr, bindhost[i]);
552 		if (bind(tpipsock,
553 		    (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
554 			syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]);
555 			exit(1);
556 		}
557 		if (listen(tpipsock, 5) < 0) {
558 			syslog(LOG_ERR, "listen failed");
559 			exit(1);
560 		}
561 		/*
562 		 * XXX
563 		 * Someday this should probably use "rpcbind", the son of
564 		 * portmap.
565 		 */
566 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
567 			syslog(LOG_ERR, "can't register tcp with portmap");
568 			exit(1);
569 		}
570 		FD_SET(tpipsock, &sockbits);
571 		maxsock = tpipsock;
572 		connect_type_cnt++;
573 	}
574 #endif /* notyet */
575 
576 	if (connect_type_cnt == 0)
577 		exit(0);
578 
579 	setproctitle("master");
580 
581 	/*
582 	 * Loop forever accepting connections and passing the sockets
583 	 * into the kernel for the mounts.
584 	 */
585 	for (;;) {
586 		ready = sockbits;
587 		if (connect_type_cnt > 1) {
588 			if (select(maxsock + 1,
589 			    &ready, NULL, NULL, NULL) < 1) {
590 				syslog(LOG_ERR, "select failed: %m");
591 				exit(1);
592 			}
593 		}
594 		if (tcpflag && FD_ISSET(tcpsock, &ready)) {
595 			len = sizeof(inetpeer);
596 			if ((msgsock = accept(tcpsock,
597 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
598 				syslog(LOG_ERR, "accept failed: %m");
599 				exit(1);
600 			}
601 			memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
602 			if (setsockopt(msgsock, SOL_SOCKET,
603 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
604 				syslog(LOG_ERR,
605 				    "setsockopt SO_KEEPALIVE: %m");
606 			nfsdargs.sock = msgsock;
607 			nfsdargs.name = (caddr_t)&inetpeer;
608 			nfsdargs.namelen = sizeof(inetpeer);
609 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
610 			(void)close(msgsock);
611 		}
612 #ifdef notyet
613 		if (tp4flag && FD_ISSET(tp4sock, &ready)) {
614 			len = sizeof(isopeer);
615 			if ((msgsock = accept(tp4sock,
616 			    (struct sockaddr *)&isopeer, &len)) < 0) {
617 				syslog(LOG_ERR, "accept failed: %m");
618 				exit(1);
619 			}
620 			if (setsockopt(msgsock, SOL_SOCKET,
621 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
622 				syslog(LOG_ERR,
623 				    "setsockopt SO_KEEPALIVE: %m");
624 			nfsdargs.sock = msgsock;
625 			nfsdargs.name = (caddr_t)&isopeer;
626 			nfsdargs.namelen = len;
627 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
628 			(void)close(msgsock);
629 		}
630 		if (tpipflag && FD_ISSET(tpipsock, &ready)) {
631 			len = sizeof(inetpeer);
632 			if ((msgsock = accept(tpipsock,
633 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
634 				syslog(LOG_ERR, "accept failed: %m");
635 				exit(1);
636 			}
637 			if (setsockopt(msgsock, SOL_SOCKET,
638 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
639 				syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
640 			nfsdargs.sock = msgsock;
641 			nfsdargs.name = (caddr_t)&inetpeer;
642 			nfsdargs.namelen = len;
643 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
644 			(void)close(msgsock);
645 		}
646 #endif /* notyet */
647 	}
648 }
649 
650 void
651 setbindhost(struct sockaddr_in *ia, const char *bindhost)
652 {
653 	ia->sin_family = AF_INET;
654 	ia->sin_port = htons(NFS_PORT);
655 	ia->sin_len = sizeof(*ia);
656 	if (bindhost == NULL || strcmp(bindhost,"*") == 0) {
657 		ia->sin_addr.s_addr = INADDR_ANY;
658 	} else {
659 		if (inet_aton(bindhost, &ia->sin_addr) == 0) {
660 			struct hostent *he;
661 
662 			he = gethostbyname2(bindhost, ia->sin_family);
663 			if (he == NULL) {
664 				syslog(LOG_ERR, "gethostbyname of %s failed", bindhost);
665 				exit(1);
666 			}
667 			bcopy(he->h_addr, &ia->sin_addr, he->h_length);
668 		}
669 	}
670 }
671 
672 void
673 usage()
674 {
675 	(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
676 	exit(1);
677 }
678 
679 void
680 nonfs(signo)
681 	int signo;
682 {
683 	syslog(LOG_ERR, "missing system call: NFS not available");
684 }
685 
686 void
687 reapchild(signo)
688 	int signo;
689 {
690 
691 	while (wait3(NULL, WNOHANG, NULL) > 0);
692 }
693 
694 #ifdef OLD_SETPROCTITLE
695 #ifdef __FreeBSD__
696 void
697 setproctitle(a)
698 	char *a;
699 {
700 	register char *cp;
701 	char buf[80];
702 
703 	cp = Argv[0];
704 	(void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
705 	(void)strncpy(cp, buf, LastArg - cp);
706 	cp += strlen(cp);
707 	while (cp < LastArg)
708 		*cp++ = '\0';
709 	Argv[1] = NULL;
710 }
711 #endif	/* __FreeBSD__ */
712 #endif
713