]> git.saurik.com Git - apple/network_cmds.git/blob - nfsd.tproj/nfsd.c
network_cmds-76.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 20
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", 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", 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 syslog(LOG_ERR, "can't bind udp addr");
378 exit(1);
379 }
380 if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
381 !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
382 syslog(LOG_ERR, "can't register with udp portmap");
383 exit(1);
384 }
385 nfsdargs.sock = sock;
386 nfsdargs.name = NULL;
387 nfsdargs.namelen = 0;
388 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
389 syslog(LOG_ERR, "can't Add UDP socket");
390 exit(1);
391 }
392 (void)close(sock);
393 }
394
395 #ifdef ISO
396 /* If we are serving cltp, set up the socket. */
397 if (cltpflag) {
398 if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
399 syslog(LOG_ERR, "can't create cltp socket");
400 exit(1);
401 }
402 memset(&isoaddr, 0, sizeof(isoaddr));
403 isoaddr.siso_family = AF_ISO;
404 isoaddr.siso_tlen = 2;
405 cp = TSEL(&isoaddr);
406 *cp++ = (NFS_PORT >> 8);
407 *cp = (NFS_PORT & 0xff);
408 isoaddr.siso_len = sizeof(isoaddr);
409 if (bind(sock,
410 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
411 syslog(LOG_ERR, "can't bind cltp addr");
412 exit(1);
413 }
414 #ifdef notyet
415 /*
416 * XXX
417 * Someday this should probably use "rpcbind", the son of
418 * portmap.
419 */
420 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
421 syslog(LOG_ERR, "can't register with udp portmap");
422 exit(1);
423 }
424 #endif /* notyet */
425 nfsdargs.sock = sock;
426 nfsdargs.name = NULL;
427 nfsdargs.namelen = 0;
428 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
429 syslog(LOG_ERR, "can't add UDP socket");
430 exit(1);
431 }
432 close(sock);
433 }
434 #endif /* ISO */
435
436 /* Now set up the master server socket waiting for tcp connections. */
437 on = 1;
438 FD_ZERO(&sockbits);
439 connect_type_cnt = 0;
440 if (tcpflag) {
441 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
442 syslog(LOG_ERR, "can't create tcp socket");
443 exit(1);
444 }
445 if (setsockopt(tcpsock,
446 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
447 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
448 inetaddr.sin_family = AF_INET;
449 inetaddr.sin_addr.s_addr = INADDR_ANY;
450 inetaddr.sin_port = htons(NFS_PORT);
451 inetaddr.sin_len = sizeof(inetaddr);
452 if (bind(tcpsock,
453 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
454 syslog(LOG_ERR, "can't bind tcp addr");
455 exit(1);
456 }
457 if (listen(tcpsock, 5) < 0) {
458 syslog(LOG_ERR, "listen failed");
459 exit(1);
460 }
461 if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
462 !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
463 syslog(LOG_ERR, "can't register tcp with portmap");
464 exit(1);
465 }
466 FD_SET(tcpsock, &sockbits);
467 maxsock = tcpsock;
468 connect_type_cnt++;
469 }
470
471 #ifdef notyet
472 /* Now set up the master server socket waiting for tp4 connections. */
473 if (tp4flag) {
474 if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
475 syslog(LOG_ERR, "can't create tp4 socket");
476 exit(1);
477 }
478 if (setsockopt(tp4sock,
479 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
480 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
481 memset(&isoaddr, 0, sizeof(isoaddr));
482 isoaddr.siso_family = AF_ISO;
483 isoaddr.siso_tlen = 2;
484 cp = TSEL(&isoaddr);
485 *cp++ = (NFS_PORT >> 8);
486 *cp = (NFS_PORT & 0xff);
487 isoaddr.siso_len = sizeof(isoaddr);
488 if (bind(tp4sock,
489 (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) {
490 syslog(LOG_ERR, "can't bind tp4 addr");
491 exit(1);
492 }
493 if (listen(tp4sock, 5) < 0) {
494 syslog(LOG_ERR, "listen failed");
495 exit(1);
496 }
497 /*
498 * XXX
499 * Someday this should probably use "rpcbind", the son of
500 * portmap.
501 */
502 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
503 syslog(LOG_ERR, "can't register tcp with portmap");
504 exit(1);
505 }
506 FD_SET(tp4sock, &sockbits);
507 maxsock = tp4sock;
508 connect_type_cnt++;
509 }
510
511 /* Now set up the master server socket waiting for tpip connections. */
512 if (tpipflag) {
513 if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
514 syslog(LOG_ERR, "can't create tpip socket");
515 exit(1);
516 }
517 if (setsockopt(tpipsock,
518 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
519 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
520 inetaddr.sin_family = AF_INET;
521 inetaddr.sin_addr.s_addr = INADDR_ANY;
522 inetaddr.sin_port = htons(NFS_PORT);
523 inetaddr.sin_len = sizeof(inetaddr);
524 if (bind(tpipsock,
525 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
526 syslog(LOG_ERR, "can't bind tcp addr");
527 exit(1);
528 }
529 if (listen(tpipsock, 5) < 0) {
530 syslog(LOG_ERR, "listen failed");
531 exit(1);
532 }
533 /*
534 * XXX
535 * Someday this should probably use "rpcbind", the son of
536 * portmap.
537 */
538 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
539 syslog(LOG_ERR, "can't register tcp with portmap");
540 exit(1);
541 }
542 FD_SET(tpipsock, &sockbits);
543 maxsock = tpipsock;
544 connect_type_cnt++;
545 }
546 #endif /* notyet */
547
548 if (connect_type_cnt == 0)
549 exit(0);
550
551 setproctitle("master");
552
553 /*
554 * Loop forever accepting connections and passing the sockets
555 * into the kernel for the mounts.
556 */
557 for (;;) {
558 ready = sockbits;
559 if (connect_type_cnt > 1) {
560 if (select(maxsock + 1,
561 &ready, NULL, NULL, NULL) < 1) {
562 syslog(LOG_ERR, "select failed: %m");
563 exit(1);
564 }
565 }
566 if (tcpflag && FD_ISSET(tcpsock, &ready)) {
567 len = sizeof(inetpeer);
568 if ((msgsock = accept(tcpsock,
569 (struct sockaddr *)&inetpeer, &len)) < 0) {
570 syslog(LOG_ERR, "accept failed: %m");
571 exit(1);
572 }
573 memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
574 if (setsockopt(msgsock, SOL_SOCKET,
575 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
576 syslog(LOG_ERR,
577 "setsockopt SO_KEEPALIVE: %m");
578 nfsdargs.sock = msgsock;
579 nfsdargs.name = (caddr_t)&inetpeer;
580 nfsdargs.namelen = sizeof(inetpeer);
581 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
582 (void)close(msgsock);
583 }
584 #ifdef notyet
585 if (tp4flag && FD_ISSET(tp4sock, &ready)) {
586 len = sizeof(isopeer);
587 if ((msgsock = accept(tp4sock,
588 (struct sockaddr *)&isopeer, &len)) < 0) {
589 syslog(LOG_ERR, "accept failed: %m");
590 exit(1);
591 }
592 if (setsockopt(msgsock, SOL_SOCKET,
593 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
594 syslog(LOG_ERR,
595 "setsockopt SO_KEEPALIVE: %m");
596 nfsdargs.sock = msgsock;
597 nfsdargs.name = (caddr_t)&isopeer;
598 nfsdargs.namelen = len;
599 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
600 (void)close(msgsock);
601 }
602 if (tpipflag && FD_ISSET(tpipsock, &ready)) {
603 len = sizeof(inetpeer);
604 if ((msgsock = accept(tpipsock,
605 (struct sockaddr *)&inetpeer, &len)) < 0) {
606 syslog(LOG_ERR, "Accept failed: %m");
607 exit(1);
608 }
609 if (setsockopt(msgsock, SOL_SOCKET,
610 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
611 syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
612 nfsdargs.sock = msgsock;
613 nfsdargs.name = (caddr_t)&inetpeer;
614 nfsdargs.namelen = len;
615 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
616 (void)close(msgsock);
617 }
618 #endif /* notyet */
619 }
620 }
621
622 void
623 usage()
624 {
625 (void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
626 exit(1);
627 }
628
629 void
630 nonfs(signo)
631 int signo;
632 {
633 syslog(LOG_ERR, "missing system call: NFS not available.");
634 }
635
636 void
637 reapchild(signo)
638 int signo;
639 {
640
641 while (wait3(NULL, WNOHANG, NULL) > 0);
642 }
643
644 void
645 setproctitle(a)
646 char *a;
647 {
648 register char *cp;
649 char buf[80];
650
651 cp = Argv[0];
652 (void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
653 (void)strncpy(cp, buf, LastArg - cp);
654 cp += strlen(cp);
655 while (cp < LastArg)
656 *cp++ = '\0';
657 }