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