]> git.saurik.com Git - apple/network_cmds.git/blob - nfsd.tproj/nfsd.c
network_cmds-245.17.tar.gz
[apple/network_cmds.git] / nfsd.tproj / nfsd.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Copyright (c) 1989, 1993, 1994
26 * The Regents of the University of California. All rights reserved.
27 *
28 * This code is derived from software contributed to Berkeley by
29 * Rick Macklem at The University of Guelph.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 */
59
60
61 #include <sys/param.h>
62 #include <sys/syslog.h>
63 #include <sys/ioctl.h>
64 #include <sys/stat.h>
65 #include <sys/wait.h>
66 #include <sys/uio.h>
67 #include <sys/ucred.h>
68 #include <sys/mount.h>
69 #include <sys/socket.h>
70 #include <sys/socketvar.h>
71
72 #include <rpc/rpc.h>
73 #include <rpc/pmap_clnt.h>
74 #include <rpc/pmap_prot.h>
75
76 #ifdef ISO
77 #include <netiso/iso.h>
78 #endif
79 #include <nfs/rpcv2.h>
80 #include <nfs/nfsproto.h>
81 #include <nfs/nfs.h>
82
83 #ifdef NFSKERB
84 #include <kerberosIV/des.h>
85 #include <kerberosIV/krb.h>
86 #endif
87
88 #include <err.h>
89 #include <errno.h>
90 #include <fcntl.h>
91 #include <grp.h>
92 #include <pwd.h>
93 #include <signal.h>
94 #include <stdio.h>
95 #include <stdlib.h>
96 #include <strings.h>
97 #include <unistd.h>
98
99 /* Global defs */
100 #ifdef DEBUG
101 #define syslog(e, s) fprintf(stderr,(s))
102 int debug = 1;
103 #else
104 int debug = 0;
105 #endif
106
107 struct nfsd_srvargs nsd;
108 char **Argv = NULL; /* pointer to argument vector */
109 char *LastArg = NULL; /* end of argv */
110
111 #ifdef NFSKERB
112 char lnam[ANAME_SZ];
113 KTEXT_ST kt;
114 AUTH_DAT kauth;
115 char inst[INST_SZ];
116 struct nfsrpc_fullblock kin, kout;
117 struct nfsrpc_fullverf kverf;
118 NFSKERBKEY_T kivec;
119 struct timeval ktv;
120 NFSKERBKEYSCHED_T kerb_keysched;
121 #endif
122
123 void nonfs __P((int));
124 void reapchild __P((int));
125 void setproctitle __P((char *));
126 void usage __P((void));
127
128 /*
129 * Nfs server daemon mostly just a user context for nfssvc()
130 *
131 * 1 - do file descriptor and signal cleanup
132 * 2 - fork the nfsd(s)
133 * 3 - create server socket(s)
134 * 4 - register socket with portmap
135 *
136 * For connectionless protocols, just pass the socket into the kernel via.
137 * nfssvc().
138 * For connection based sockets, loop doing accepts. When you get a new
139 * socket from accept, pass the msgsock into the kernel via. nfssvc().
140 * The arguments are:
141 * -c - support iso cltp clients
142 * -r - reregister with portmapper
143 * -t - support tcp nfs clients
144 * -u - support udp nfs clients
145 * followed by "n" which is the number of nfsds' to fork off
146 */
147 int
148 main(argc, argv, envp)
149 int argc;
150 char *argv[], *envp[];
151 {
152 extern int optind;
153 struct group *grp;
154 struct nfsd_args nfsdargs;
155 struct passwd *pwd;
156 struct ucred *cr;
157 struct sockaddr_in inetaddr, inetpeer;
158 #ifdef ISO
159 struct sockaddr_iso isoaddr, isopeer;
160 #endif
161 struct timeval ktv;
162 fd_set ready, sockbits;
163 int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
164 int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
165 int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag;
166 char *cp, **cpp;
167
168 /* Save start and extent of argv for setproctitle. */
169 Argv = argv;
170 if (envp == 0 || *envp == 0)
171 envp = argv;
172 while (*envp)
173 envp++;
174 LastArg = envp[-1] + strlen(envp[-1]);
175
176 #define MAXNFSDCNT 64
177 #define DEFNFSDCNT 4
178 nfsdcnt = DEFNFSDCNT;
179 cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
180 tpipflag = udpflag = 0;
181 #ifdef ISO
182 #define GETOPT "cn:rtu"
183 #define USAGE "[-crtu] [-n num_servers]"
184 #else
185 #define GETOPT "n:rtu"
186 #define USAGE "[-rtu] [-n num_servers]"
187 #endif
188 while ((ch = getopt(argc, argv, GETOPT)) != EOF)
189 switch (ch) {
190 case 'n':
191 nfsdcnt = atoi(optarg);
192 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
193 warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
194 nfsdcnt = DEFNFSDCNT;
195 }
196 break;
197 case 'r':
198 reregister = 1;
199 break;
200 case 't':
201 tcpflag = 1;
202 break;
203 case 'u':
204 udpflag = 1;
205 break;
206 #ifdef ISO
207 case 'c':
208 cltpflag = 1;
209 break;
210 #ifdef notyet
211 case 'i':
212 tp4cnt = 1;
213 break;
214 case 'p':
215 tpipcnt = 1;
216 break;
217 #endif /* notyet */
218 #endif /* ISO */
219 default:
220 case '?':
221 usage();
222 };
223 argv += optind;
224 argc -= optind;
225
226 /*
227 * XXX
228 * Backward compatibility, trailing number is the count of daemons.
229 */
230 if (argc > 1)
231 usage();
232 if (argc == 1) {
233 nfsdcnt = atoi(argv[0]);
234 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
235 warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
236 nfsdcnt = DEFNFSDCNT;
237 }
238 }
239
240 if (debug == 0) {
241 daemon(0, 0);
242 (void)signal(SIGHUP, SIG_IGN);
243 (void)signal(SIGINT, SIG_IGN);
244 (void)signal(SIGQUIT, SIG_IGN);
245 (void)signal(SIGSYS, nonfs);
246 (void)signal(SIGTERM, SIG_IGN);
247 }
248 (void)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 (void)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 if (udpflag) {
367 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
368 syslog(LOG_ERR, "can't create udp socket");
369 exit(1);
370 }
371 inetaddr.sin_family = AF_INET;
372 inetaddr.sin_addr.s_addr = INADDR_ANY;
373 inetaddr.sin_port = htons(NFS_PORT);
374 inetaddr.sin_len = sizeof(inetaddr);
375 if (bind(sock,
376 (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
377 /* socket may still be lingering from previous incarnation */
378 /* wait a few seconds and try again */
379 sleep(6);
380 if (bind(sock,
381 (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
382 syslog(LOG_ERR, "can't bind udp addr");
383 exit(1);
384 }
385 }
386 if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
387 !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
388 syslog(LOG_ERR, "can't register with udp portmap");
389 exit(1);
390 }
391 nfsdargs.sock = sock;
392 nfsdargs.name = NULL;
393 nfsdargs.namelen = 0;
394 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
395 syslog(LOG_ERR, "can't Add UDP socket");
396 exit(1);
397 }
398 (void)close(sock);
399 }
400
401 #ifdef ISO
402 /* If we are serving cltp, set up the socket. */
403 if (cltpflag) {
404 if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
405 syslog(LOG_ERR, "can't create cltp socket");
406 exit(1);
407 }
408 memset(&isoaddr, 0, sizeof(isoaddr));
409 isoaddr.siso_family = AF_ISO;
410 isoaddr.siso_tlen = 2;
411 cp = TSEL(&isoaddr);
412 *cp++ = (NFS_PORT >> 8);
413 *cp = (NFS_PORT & 0xff);
414 isoaddr.siso_len = sizeof(isoaddr);
415 if (bind(sock,
416 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
417 syslog(LOG_ERR, "can't bind cltp addr");
418 exit(1);
419 }
420 #ifdef notyet
421 /*
422 * XXX
423 * Someday this should probably use "rpcbind", the son of
424 * portmap.
425 */
426 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
427 syslog(LOG_ERR, "can't register with udp portmap");
428 exit(1);
429 }
430 #endif /* notyet */
431 nfsdargs.sock = sock;
432 nfsdargs.name = NULL;
433 nfsdargs.namelen = 0;
434 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
435 syslog(LOG_ERR, "can't add UDP socket");
436 exit(1);
437 }
438 close(sock);
439 }
440 #endif /* ISO */
441
442 /* Now set up the master server socket waiting for tcp connections. */
443 on = 1;
444 FD_ZERO(&sockbits);
445 connect_type_cnt = 0;
446 if (tcpflag) {
447 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
448 syslog(LOG_ERR, "can't create tcp socket");
449 exit(1);
450 }
451 if (setsockopt(tcpsock,
452 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
453 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
454 inetaddr.sin_family = AF_INET;
455 inetaddr.sin_addr.s_addr = INADDR_ANY;
456 inetaddr.sin_port = htons(NFS_PORT);
457 inetaddr.sin_len = sizeof(inetaddr);
458 if (bind(tcpsock,
459 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
460 syslog(LOG_ERR, "can't bind tcp addr");
461 exit(1);
462 }
463 if (listen(tcpsock, 5) < 0) {
464 syslog(LOG_ERR, "listen failed");
465 exit(1);
466 }
467 if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
468 !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
469 syslog(LOG_ERR, "can't register tcp with portmap");
470 exit(1);
471 }
472 FD_SET(tcpsock, &sockbits);
473 maxsock = tcpsock;
474 connect_type_cnt++;
475 }
476
477 #ifdef notyet
478 /* Now set up the master server socket waiting for tp4 connections. */
479 if (tp4flag) {
480 if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
481 syslog(LOG_ERR, "can't create tp4 socket");
482 exit(1);
483 }
484 if (setsockopt(tp4sock,
485 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
486 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
487 memset(&isoaddr, 0, sizeof(isoaddr));
488 isoaddr.siso_family = AF_ISO;
489 isoaddr.siso_tlen = 2;
490 cp = TSEL(&isoaddr);
491 *cp++ = (NFS_PORT >> 8);
492 *cp = (NFS_PORT & 0xff);
493 isoaddr.siso_len = sizeof(isoaddr);
494 if (bind(tp4sock,
495 (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) {
496 syslog(LOG_ERR, "can't bind tp4 addr");
497 exit(1);
498 }
499 if (listen(tp4sock, 5) < 0) {
500 syslog(LOG_ERR, "listen failed");
501 exit(1);
502 }
503 /*
504 * XXX
505 * Someday this should probably use "rpcbind", the son of
506 * portmap.
507 */
508 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
509 syslog(LOG_ERR, "can't register tcp with portmap");
510 exit(1);
511 }
512 FD_SET(tp4sock, &sockbits);
513 maxsock = tp4sock;
514 connect_type_cnt++;
515 }
516
517 /* Now set up the master server socket waiting for tpip connections. */
518 if (tpipflag) {
519 if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
520 syslog(LOG_ERR, "can't create tpip socket");
521 exit(1);
522 }
523 if (setsockopt(tpipsock,
524 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
525 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
526 inetaddr.sin_family = AF_INET;
527 inetaddr.sin_addr.s_addr = INADDR_ANY;
528 inetaddr.sin_port = htons(NFS_PORT);
529 inetaddr.sin_len = sizeof(inetaddr);
530 if (bind(tpipsock,
531 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
532 syslog(LOG_ERR, "can't bind tcp addr");
533 exit(1);
534 }
535 if (listen(tpipsock, 5) < 0) {
536 syslog(LOG_ERR, "listen failed");
537 exit(1);
538 }
539 /*
540 * XXX
541 * Someday this should probably use "rpcbind", the son of
542 * portmap.
543 */
544 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
545 syslog(LOG_ERR, "can't register tcp with portmap");
546 exit(1);
547 }
548 FD_SET(tpipsock, &sockbits);
549 maxsock = tpipsock;
550 connect_type_cnt++;
551 }
552 #endif /* notyet */
553
554 if (connect_type_cnt == 0)
555 exit(0);
556
557 setproctitle("master");
558
559 /*
560 * Loop forever accepting connections and passing the sockets
561 * into the kernel for the mounts.
562 */
563 for (;;) {
564 ready = sockbits;
565 if (connect_type_cnt > 1) {
566 if (select(maxsock + 1,
567 &ready, NULL, NULL, NULL) < 1) {
568 syslog(LOG_ERR, "select failed: %m");
569 exit(1);
570 }
571 }
572 if (tcpflag && FD_ISSET(tcpsock, &ready)) {
573 len = sizeof(inetpeer);
574 if ((msgsock = accept(tcpsock,
575 (struct sockaddr *)&inetpeer, &len)) < 0) {
576 syslog(LOG_ERR, "accept failed: %m");
577 exit(1);
578 }
579 memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
580 if (setsockopt(msgsock, SOL_SOCKET,
581 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
582 syslog(LOG_ERR,
583 "setsockopt SO_KEEPALIVE: %m");
584 nfsdargs.sock = msgsock;
585 nfsdargs.name = (caddr_t)&inetpeer;
586 nfsdargs.namelen = sizeof(inetpeer);
587 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
588 (void)close(msgsock);
589 }
590 #ifdef notyet
591 if (tp4flag && FD_ISSET(tp4sock, &ready)) {
592 len = sizeof(isopeer);
593 if ((msgsock = accept(tp4sock,
594 (struct sockaddr *)&isopeer, &len)) < 0) {
595 syslog(LOG_ERR, "accept failed: %m");
596 exit(1);
597 }
598 if (setsockopt(msgsock, SOL_SOCKET,
599 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
600 syslog(LOG_ERR,
601 "setsockopt SO_KEEPALIVE: %m");
602 nfsdargs.sock = msgsock;
603 nfsdargs.name = (caddr_t)&isopeer;
604 nfsdargs.namelen = len;
605 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
606 (void)close(msgsock);
607 }
608 if (tpipflag && FD_ISSET(tpipsock, &ready)) {
609 len = sizeof(inetpeer);
610 if ((msgsock = accept(tpipsock,
611 (struct sockaddr *)&inetpeer, &len)) < 0) {
612 syslog(LOG_ERR, "Accept failed: %m");
613 exit(1);
614 }
615 if (setsockopt(msgsock, SOL_SOCKET,
616 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
617 syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
618 nfsdargs.sock = msgsock;
619 nfsdargs.name = (caddr_t)&inetpeer;
620 nfsdargs.namelen = len;
621 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
622 (void)close(msgsock);
623 }
624 #endif /* notyet */
625 }
626 }
627
628 void
629 usage()
630 {
631 (void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
632 exit(1);
633 }
634
635 void
636 nonfs(signo)
637 int signo;
638 {
639 syslog(LOG_ERR, "missing system call: NFS not available.");
640 }
641
642 void
643 reapchild(signo)
644 int signo;
645 {
646
647 while (wait3(NULL, WNOHANG, NULL) > 0);
648 }
649
650 void
651 setproctitle(a)
652 char *a;
653 {
654 register char *cp;
655 char buf[80];
656
657 cp = Argv[0];
658 (void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
659 (void)strncpy(cp, buf, LastArg - cp);
660 cp += strlen(cp);
661 while (cp < LastArg)
662 *cp++ = '\0';
663 }