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