nfsd.c revision 1.46 1 /* $NetBSD: nfsd.c,v 1.46 2006/03/23 15:37:02 dogcow Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Rick Macklem at The University of Guelph.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 #ifndef lint
37 __COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\n\
38 The Regents of the University of California. All rights reserved.\n");
39 #endif /* not lint */
40
41 #ifndef lint
42 #if 0
43 static char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95";
44 #else
45 __RCSID("$NetBSD: nfsd.c,v 1.46 2006/03/23 15:37:02 dogcow Exp $");
46 #endif
47 #endif /* not lint */
48
49 #include <sys/param.h>
50 #include <sys/ioctl.h>
51 #include <sys/stat.h>
52 #include <sys/wait.h>
53 #include <sys/uio.h>
54 #include <sys/ucred.h>
55 #include <sys/mount.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
58 #include <poll.h>
59
60 #include <rpc/rpc.h>
61 #include <rpc/pmap_clnt.h>
62 #include <rpc/pmap_prot.h>
63
64 #ifdef ISO
65 #include <netiso/iso.h>
66 #endif
67 #include <nfs/rpcv2.h>
68 #include <nfs/nfsproto.h>
69 #include <nfs/nfs.h>
70
71 #include <err.h>
72 #include <errno.h>
73 #include <fcntl.h>
74 #include <grp.h>
75 #include <pwd.h>
76 #include <signal.h>
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <string.h>
80 #include <syslog.h>
81 #include <unistd.h>
82 #include <netdb.h>
83
84 /* Global defs */
85 #ifdef DEBUG
86 #define syslog(e, s) fprintf(stderr,(s))
87 int debug = 1;
88 #else
89 int debug = 0;
90 #endif
91
92 struct nfsd_srvargs nsd;
93
94 int main __P((int, char **));
95 void nonfs __P((int));
96 void reapchild __P((int));
97 void usage __P((void));
98
99 /*
100 * Nfs server daemon mostly just a user context for nfssvc()
101 *
102 * 1 - do file descriptor and signal cleanup
103 * 2 - fork the nfsd(s)
104 * 3 - create server socket(s)
105 * 4 - register socket with portmap
106 *
107 * For connectionless protocols, just pass the socket into the kernel via
108 * nfssvc().
109 * For connection based sockets, loop doing accepts. When you get a new
110 * socket from accept, pass the msgsock into the kernel via nfssvc().
111 * The arguments are:
112 * -c - support iso cltp clients
113 * -r - reregister with portmapper
114 * -t - support tcp nfs clients
115 * -u - support udp nfs clients
116 * followed by "n" which is the number of nfsds' to fork off
117 */
118 int
119 main(argc, argv)
120 int argc;
121 char *argv[];
122 {
123 struct nfsd_args nfsdargs;
124 struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
125 struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
126 struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
127 struct sockaddr_in inetpeer;
128 struct sockaddr_in6 inet6peer;
129 #ifdef ISO
130 struct sockaddr_iso isoaddr, isopeer;
131 #endif
132 struct pollfd set[4];
133 int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
134 int nfsdcnt, nfssvc_flag, on = 1, reregister, sock, tcpflag, tcpsock;
135 int tcp6sock, ip6flag;
136 int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag, ecode, s;
137
138 #define MAXNFSDCNT 1024
139 #define DEFNFSDCNT 4
140 nfsdcnt = DEFNFSDCNT;
141 cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
142 tpipflag = udpflag = ip6flag = 0;
143 nconf_udp = nconf_tcp = nconf_udp6 = nconf_tcp6 = NULL;
144 maxsock = 0;
145 tcpsock = tcp6sock = -1;
146 #ifdef ISO
147 #define GETOPT "6cn:rtu"
148 #define USAGE "[-crtu] [-n num_servers]"
149 #else
150 #define GETOPT "6n:rtu"
151 #define USAGE "[-rtu] [-n num_servers]"
152 #endif
153 while ((ch = getopt(argc, argv, GETOPT)) != -1) {
154 switch (ch) {
155 case '6':
156 ip6flag = 1;
157 s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
158 if (s < 0 && (errno == EPROTONOSUPPORT ||
159 errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
160 ip6flag = 0;
161 else
162 close(s);
163 break;
164 case 'n':
165 nfsdcnt = atoi(optarg);
166 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
167 warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
168 nfsdcnt = DEFNFSDCNT;
169 }
170 break;
171 case 'r':
172 reregister = 1;
173 break;
174 case 't':
175 tcpflag = 1;
176 break;
177 case 'u':
178 udpflag = 1;
179 break;
180 #ifdef ISO
181 case 'c':
182 cltpflag = 1;
183 break;
184 #ifdef notyet
185 case 'i':
186 tp4cnt = 1;
187 break;
188 case 'p':
189 tpipcnt = 1;
190 break;
191 #endif /* notyet */
192 #endif /* ISO */
193 default:
194 case '?':
195 usage();
196 };
197 }
198 argv += optind;
199 argc -= optind;
200
201 /*
202 * XXX
203 * Backward compatibility, trailing number is the count of daemons.
204 */
205 if (argc > 1)
206 usage();
207 if (argc == 1) {
208 nfsdcnt = atoi(argv[0]);
209 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
210 warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
211 nfsdcnt = DEFNFSDCNT;
212 }
213 }
214
215 /*
216 * If none of TCP or UDP are specified, default to UDP only.
217 */
218 if (tcpflag == 0 && udpflag == 0)
219 udpflag = 1;
220
221 if (debug == 0) {
222 daemon(0, 0);
223 (void)signal(SIGHUP, SIG_IGN);
224 (void)signal(SIGINT, SIG_IGN);
225 (void)signal(SIGQUIT, SIG_IGN);
226 (void)signal(SIGSYS, nonfs);
227 }
228 (void)signal(SIGCHLD, reapchild);
229
230 if (udpflag) {
231 memset(&hints, 0, sizeof hints);
232 hints.ai_flags = AI_PASSIVE;
233 hints.ai_family = PF_INET;
234 hints.ai_socktype = SOCK_DGRAM;
235 hints.ai_protocol = IPPROTO_UDP;
236
237 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
238 if (ecode != 0) {
239 syslog(LOG_ERR, "getaddrinfo udp: %s",
240 gai_strerror(ecode));
241 exit(1);
242 }
243
244 nconf_udp = getnetconfigent("udp");
245
246 if (nconf_udp == NULL)
247 err(1, "getnetconfigent udp failed");
248
249 nb_udp.buf = ai_udp->ai_addr;
250 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
251 if (reregister)
252 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp))
253 err(1, "rpcb_set udp failed");
254 }
255
256 if (tcpflag) {
257 memset(&hints, 0, sizeof hints);
258 hints.ai_flags = AI_PASSIVE;
259 hints.ai_family = PF_INET;
260 hints.ai_socktype = SOCK_STREAM;
261 hints.ai_protocol = IPPROTO_TCP;
262
263 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
264 if (ecode != 0) {
265 syslog(LOG_ERR, "getaddrinfo udp: %s",
266 gai_strerror(ecode));
267 exit(1);
268 }
269
270 nconf_tcp = getnetconfigent("tcp");
271
272 if (nconf_tcp == NULL)
273 err(1, "getnetconfigent tcp failed");
274
275 nb_tcp.buf = ai_tcp->ai_addr;
276 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
277 if (reregister)
278 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp))
279 err(1, "rpcb_set tcp failed");
280 }
281
282 if (udpflag && ip6flag) {
283 memset(&hints, 0, sizeof hints);
284 hints.ai_flags = AI_PASSIVE;
285 hints.ai_family = PF_INET6;
286 hints.ai_socktype = SOCK_DGRAM;
287 hints.ai_protocol = IPPROTO_UDP;
288
289 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
290 if (ecode != 0) {
291 syslog(LOG_ERR, "getaddrinfo udp: %s",
292 gai_strerror(ecode));
293 exit(1);
294 }
295
296 nconf_udp6 = getnetconfigent("udp6");
297
298 if (nconf_udp6 == NULL)
299 err(1, "getnetconfigent udp6 failed");
300
301 nb_udp6.buf = ai_udp6->ai_addr;
302 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
303 if (reregister)
304 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6))
305 err(1, "rpcb_set udp6 failed");
306 }
307
308 if (tcpflag && ip6flag) {
309 memset(&hints, 0, sizeof hints);
310 hints.ai_flags = AI_PASSIVE;
311 hints.ai_family = PF_INET6;
312 hints.ai_socktype = SOCK_STREAM;
313 hints.ai_protocol = IPPROTO_TCP;
314
315 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
316 if (ecode != 0) {
317 syslog(LOG_ERR, "getaddrinfo udp: %s",
318 gai_strerror(ecode));
319 exit(1);
320 }
321
322 nconf_tcp6 = getnetconfigent("tcp6");
323
324 if (nconf_tcp6 == NULL)
325 err(1, "getnetconfigent tcp6 failed");
326
327 nb_tcp6.buf = ai_tcp6->ai_addr;
328 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
329 if (reregister)
330 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6))
331 err(1, "rpcb_set tcp6 failed");
332 }
333
334 openlog("nfsd", LOG_PID, LOG_DAEMON);
335
336 for (i = 0; i < nfsdcnt; i++) {
337 switch (fork()) {
338 case -1:
339 syslog(LOG_ERR, "fork: %m");
340 exit (1);
341 case 0:
342 break;
343 default:
344 continue;
345 }
346
347 setproctitle("server");
348 nfssvc_flag = NFSSVC_NFSD;
349 nsd.nsd_nfsd = NULL;
350 while (nfssvc(nfssvc_flag, &nsd) < 0) {
351 if (errno != ENEEDAUTH) {
352 syslog(LOG_ERR, "nfssvc: %m");
353 exit(1);
354 }
355 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
356 }
357 exit(0);
358 }
359
360 /* If we are serving udp, set up the socket. */
361 if (udpflag) {
362 if ((sock = socket(ai_udp->ai_family, ai_udp->ai_socktype,
363 ai_udp->ai_protocol)) < 0) {
364 syslog(LOG_ERR, "can't create udp socket");
365 exit(1);
366 }
367 if (bind(sock, ai_udp->ai_addr, ai_udp->ai_addrlen) < 0) {
368 syslog(LOG_ERR, "can't bind udp addr");
369 exit(1);
370 }
371 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp) ||
372 !rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)) {
373 syslog(LOG_ERR, "can't register with udp portmap");
374 exit(1);
375 }
376 nfsdargs.sock = sock;
377 nfsdargs.name = NULL;
378 nfsdargs.namelen = 0;
379 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
380 syslog(LOG_ERR, "can't add UDP socket");
381 exit(1);
382 }
383 (void)close(sock);
384 }
385
386 if (udpflag &&ip6flag) {
387 if ((sock = socket(ai_udp6->ai_family, ai_udp6->ai_socktype,
388 ai_udp6->ai_protocol)) < 0) {
389 syslog(LOG_ERR, "can't create udp socket");
390 exit(1);
391 }
392 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
393 &on, sizeof on) < 0) {
394 syslog(LOG_ERR, "can't set v6-only binding for udp6 "
395 "socket: %m");
396 exit(1);
397 }
398 if (bind(sock, ai_udp6->ai_addr, ai_udp6->ai_addrlen) < 0) {
399 syslog(LOG_ERR, "can't bind udp addr");
400 exit(1);
401 }
402 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6) ||
403 !rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)) {
404 syslog(LOG_ERR, "can't register with udp portmap");
405 exit(1);
406 }
407 nfsdargs.sock = sock;
408 nfsdargs.name = NULL;
409 nfsdargs.namelen = 0;
410 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
411 syslog(LOG_ERR, "can't add UDP6 socket");
412 exit(1);
413 }
414 (void)close(sock);
415 }
416
417 #ifdef ISO
418 /* If we are serving cltp, set up the socket. */
419 if (cltpflag) {
420 if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
421 syslog(LOG_ERR, "can't create cltp socket");
422 exit(1);
423 }
424 memset(&isoaddr, 0, sizeof(isoaddr));
425 isoaddr.siso_family = AF_ISO;
426 isoaddr.siso_tlen = 2;
427 cp = TSEL(&isoaddr);
428 *cp++ = (NFS_PORT >> 8);
429 *cp = (NFS_PORT & 0xff);
430 isoaddr.siso_len = sizeof(isoaddr);
431 if (bind(sock,
432 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
433 syslog(LOG_ERR, "can't bind cltp addr");
434 exit(1);
435 }
436 #ifdef notyet
437 /*
438 * XXX
439 * Someday this should probably use "rpcbind", the son of
440 * portmap.
441 */
442 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
443 syslog(LOG_ERR, "can't register with udp portmap");
444 exit(1);
445 }
446 #endif /* notyet */
447 nfsdargs.sock = sock;
448 nfsdargs.name = NULL;
449 nfsdargs.namelen = 0;
450 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
451 syslog(LOG_ERR, "can't add UDP socket");
452 exit(1);
453 }
454 close(sock);
455 }
456 #endif /* ISO */
457
458 /* Now set up the master server socket waiting for tcp connections. */
459 on = 1;
460 connect_type_cnt = 0;
461 if (tcpflag) {
462 if ((tcpsock = socket(ai_tcp->ai_family, ai_tcp->ai_socktype,
463 ai_tcp->ai_protocol)) < 0) {
464 syslog(LOG_ERR, "can't create tcp socket");
465 exit(1);
466 }
467 if (setsockopt(tcpsock,
468 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
469 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
470 if (bind(tcpsock, ai_tcp->ai_addr, ai_tcp->ai_addrlen) < 0) {
471 syslog(LOG_ERR, "can't bind tcp addr");
472 exit(1);
473 }
474 if (listen(tcpsock, 5) < 0) {
475 syslog(LOG_ERR, "listen failed");
476 exit(1);
477 }
478 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp) ||
479 !rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)) {
480 syslog(LOG_ERR, "can't register tcp with rpcbind");
481 exit(1);
482 }
483 set[0].fd = tcpsock;
484 set[0].events = POLLIN;
485 connect_type_cnt++;
486 } else
487 set[0].fd = -1;
488
489 if (tcpflag && ip6flag) {
490 if ((tcp6sock = socket(ai_tcp6->ai_family, ai_tcp6->ai_socktype,
491 ai_tcp6->ai_protocol)) < 0) {
492 syslog(LOG_ERR, "can't create tcp socket");
493 exit(1);
494 }
495 if (setsockopt(tcp6sock,
496 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
497 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
498 if (setsockopt(tcp6sock, IPPROTO_IPV6, IPV6_V6ONLY,
499 &on, sizeof on) < 0) {
500 syslog(LOG_ERR, "can't set v6-only binding for tcp6 "
501 "socket: %m");
502 exit(1);
503 }
504 if (bind(tcp6sock, ai_tcp6->ai_addr, ai_tcp6->ai_addrlen) < 0) {
505 syslog(LOG_ERR, "can't bind tcp6 addr");
506 exit(1);
507 }
508 if (listen(tcp6sock, 5) < 0) {
509 syslog(LOG_ERR, "listen failed");
510 exit(1);
511 }
512 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6) ||
513 !rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)) {
514 syslog(LOG_ERR, "can't register tcp6 with rpcbind");
515 exit(1);
516 }
517 set[1].fd = tcp6sock;
518 set[1].events = POLLIN;
519 connect_type_cnt++;
520 } else
521 set[1].fd = -1;
522
523 #ifdef notyet
524 /* Now set up the master server socket waiting for tp4 connections. */
525 if (tp4flag) {
526 if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
527 syslog(LOG_ERR, "can't create tp4 socket");
528 exit(1);
529 }
530 if (setsockopt(tp4sock,
531 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
532 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
533 memset(&isoaddr, 0, sizeof(isoaddr));
534 isoaddr.siso_family = AF_ISO;
535 isoaddr.siso_tlen = 2;
536 cp = TSEL(&isoaddr);
537 *cp++ = (NFS_PORT >> 8);
538 *cp = (NFS_PORT & 0xff);
539 isoaddr.siso_len = sizeof(isoaddr);
540 if (bind(tp4sock,
541 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
542 syslog(LOG_ERR, "can't bind tp4 addr");
543 exit(1);
544 }
545 if (listen(tp4sock, 5) < 0) {
546 syslog(LOG_ERR, "listen failed");
547 exit(1);
548 }
549 /*
550 * XXX
551 * Someday this should probably use "rpcbind", the son of
552 * portmap.
553 */
554 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
555 syslog(LOG_ERR, "can't register tcp with portmap");
556 exit(1);
557 }
558 set[2].fd = tp4sock;
559 set[2].events = POLLIN;
560 connect_type_cnt++;
561 } else
562 set[2].fd = -1;
563
564 /* Now set up the master server socket waiting for tpip connections. */
565 if (tpipflag) {
566 if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
567 syslog(LOG_ERR, "can't create tpip socket");
568 exit(1);
569 }
570 if (setsockopt(tpipsock,
571 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
572 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
573 inetaddr.sin_family = AF_INET;
574 inetaddr.sin_addr.s_addr = INADDR_ANY;
575 inetaddr.sin_port = htons(NFS_PORT);
576 inetaddr.sin_len = sizeof(inetaddr);
577 memset(inetaddr.sin_zero, 0, sizeof(inetaddr.sin_zero));
578 if (bind(tpipsock,
579 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
580 syslog(LOG_ERR, "can't bind tcp addr");
581 exit(1);
582 }
583 if (listen(tpipsock, 5) < 0) {
584 syslog(LOG_ERR, "listen failed");
585 exit(1);
586 }
587 /*
588 * XXX
589 * Someday this should probably use "rpcbind", the son of
590 * portmap.
591 */
592 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
593 syslog(LOG_ERR, "can't register tcp with portmap");
594 exit(1);
595 }
596 set[3].fd = tpipsock;
597 set[3].events = POLLIN;
598 connect_type_cnt++;
599 } else
600 set[3].fd = -1;
601 #else
602 set[2].fd = -1;
603 set[3].fd = -1;
604 #endif /* notyet */
605
606 if (connect_type_cnt == 0)
607 exit(0);
608
609 setproctitle("master");
610
611 /*
612 * Loop forever accepting connections and passing the sockets
613 * into the kernel for the mounts.
614 */
615 for (;;) {
616 if (poll(set, 4, INFTIM) < 1) {
617 syslog(LOG_ERR, "select failed: %m");
618 exit(1);
619 }
620
621 if (set[0].revents & POLLIN) {
622 len = sizeof(inetpeer);
623 if ((msgsock = accept(tcpsock,
624 (struct sockaddr *)&inetpeer, &len)) < 0) {
625 syslog(LOG_ERR, "accept failed: %m");
626 exit(1);
627 }
628 memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
629 if (setsockopt(msgsock, SOL_SOCKET,
630 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
631 syslog(LOG_ERR,
632 "setsockopt SO_KEEPALIVE: %m");
633 nfsdargs.sock = msgsock;
634 nfsdargs.name = (caddr_t)&inetpeer;
635 nfsdargs.namelen = sizeof(inetpeer);
636 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
637 (void)close(msgsock);
638 }
639
640 if (set[1].revents & POLLIN) {
641 len = sizeof(inet6peer);
642 if ((msgsock = accept(tcp6sock,
643 (struct sockaddr *)&inet6peer, &len)) < 0) {
644 syslog(LOG_ERR, "accept failed: %m");
645 exit(1);
646 }
647 if (setsockopt(msgsock, SOL_SOCKET,
648 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
649 syslog(LOG_ERR,
650 "setsockopt SO_KEEPALIVE: %m");
651 nfsdargs.sock = msgsock;
652 nfsdargs.name = (caddr_t)&inet6peer;
653 nfsdargs.namelen = sizeof(inet6peer);
654 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
655 (void)close(msgsock);
656 }
657
658 #ifdef notyet
659 if (set[2].revents & POLLIN) {
660 len = sizeof(isopeer);
661 if ((msgsock = accept(tp4sock,
662 (struct sockaddr *)&isopeer, &len)) < 0) {
663 syslog(LOG_ERR, "accept failed: %m");
664 exit(1);
665 }
666 if (setsockopt(msgsock, SOL_SOCKET,
667 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
668 syslog(LOG_ERR,
669 "setsockopt SO_KEEPALIVE: %m");
670 nfsdargs.sock = msgsock;
671 nfsdargs.name = (caddr_t)&isopeer;
672 nfsdargs.namelen = len;
673 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
674 (void)close(msgsock);
675 }
676
677 if (set[3].revents & POLLIN) {
678 len = sizeof(inetpeer);
679 if ((msgsock = accept(tpipsock,
680 (struct sockaddr *)&inetpeer, &len)) < 0) {
681 syslog(LOG_ERR, "accept failed: %m");
682 exit(1);
683 }
684 if (setsockopt(msgsock, SOL_SOCKET,
685 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
686 syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
687 nfsdargs.sock = msgsock;
688 nfsdargs.name = (caddr_t)&inetpeer;
689 nfsdargs.namelen = len;
690 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
691 (void)close(msgsock);
692 }
693 #endif /* notyet */
694 }
695 }
696
697 void
698 usage()
699 {
700 (void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
701 exit(1);
702 }
703
704 void
705 nonfs(signo)
706 int signo;
707 {
708 syslog(LOG_ERR, "missing system call: NFS not available.");
709 }
710
711 void
712 reapchild(signo)
713 int signo;
714 {
715 while (wait3(NULL, WNOHANG, NULL) > 0);
716 }
717