Initial import from FreeBSD RELENG_4:
[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
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