Merge from vendor branch NTPD:
[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.6 2004/02/04 17:40:00 joerg 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(int);
93 void    reapchild(int);
94 void    setbindhost(struct sockaddr_in *ia, const char *bindhost);
95 #ifdef OLD_SETPROCTITLE
96 #ifdef __FreeBSD__
97 void    setproctitle(char *);
98 #endif
99 #endif
100 void    usage(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 = -1, msgsock;
132         int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock = -1;
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