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