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