nfsd.c revision 1.50 1 /* $NetBSD: nfsd.c,v 1.50 2007/07/10 13:52:51 yamt 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.50 2007/07/10 13:52:51 yamt 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 <pthread.h>
77 #include <signal.h>
78 #include <stdio.h>
79 #include <stdlib.h>
80 #include <string.h>
81 #include <syslog.h>
82 #include <unistd.h>
83 #include <netdb.h>
84
85 /* Global defs */
86 #ifdef DEBUG
87 #define syslog(e, s) fprintf(stderr,(s))
88 int debug = 1;
89 #else
90 int debug = 0;
91 #endif
92
93 int main __P((int, char **));
94 void nonfs __P((int));
95 void reapchild __P((int));
96 void usage __P((void));
97
98 static void *
99 child(void *dummy)
100 {
101 struct nfsd_srvargs nsd;
102 int nfssvc_flag;
103
104 nfssvc_flag = NFSSVC_NFSD;
105 memset(&nsd, 0, sizeof(nsd));
106 while (nfssvc(nfssvc_flag, &nsd) < 0) {
107 if (errno != ENEEDAUTH) {
108 syslog(LOG_ERR, "nfssvc: %m");
109 exit(1);
110 }
111 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
112 }
113
114 return NULL;
115 }
116
117 /*
118 * Nfs server daemon mostly just a user context for nfssvc()
119 *
120 * 1 - do file descriptor and signal cleanup
121 * 2 - create the nfsd thread(s)
122 * 3 - create server socket(s)
123 * 4 - register socket with portmap
124 *
125 * For connectionless protocols, just pass the socket into the kernel via
126 * nfssvc().
127 * For connection based sockets, loop doing accepts. When you get a new
128 * socket from accept, pass the msgsock into the kernel via nfssvc().
129 * The arguments are:
130 * -c - support iso cltp clients
131 * -r - reregister with portmapper
132 * -t - support tcp nfs clients
133 * -u - support udp nfs clients
134 * followed by "n" which is the number of nfsd threads to create
135 */
136 int
137 main(argc, argv)
138 int argc;
139 char *argv[];
140 {
141 struct nfsd_args nfsdargs;
142 struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
143 struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
144 struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
145 struct sockaddr_in inetpeer;
146 struct sockaddr_in6 inet6peer;
147 #ifdef ISO
148 struct sockaddr_iso isoaddr, isopeer;
149 #endif
150 struct pollfd set[4];
151 socklen_t len;
152 int ch, cltpflag, connect_type_cnt, i, maxsock, msgsock;
153 int nfsdcnt, on = 1, reregister, sock, tcpflag, tcpsock;
154 int tcp6sock, ip6flag;
155 int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag, ecode, s;
156
157 #define MAXNFSDCNT 1024
158 #define DEFNFSDCNT 4
159 nfsdcnt = DEFNFSDCNT;
160 cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
161 tpipflag = udpflag = ip6flag = 0;
162 nconf_udp = nconf_tcp = nconf_udp6 = nconf_tcp6 = NULL;
163 maxsock = 0;
164 tcpsock = tcp6sock = -1;
165 #ifdef ISO
166 #define GETOPT "6cn:rtu"
167 #define USAGE "[-crtu] [-n num_servers]"
168 #else
169 #define GETOPT "6n:rtu"
170 #define USAGE "[-rtu] [-n num_servers]"
171 #endif
172 while ((ch = getopt(argc, argv, GETOPT)) != -1) {
173 switch (ch) {
174 case '6':
175 ip6flag = 1;
176 s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
177 if (s < 0 && (errno == EPROTONOSUPPORT ||
178 errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
179 ip6flag = 0;
180 else
181 close(s);
182 break;
183 case 'n':
184 nfsdcnt = atoi(optarg);
185 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
186 warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
187 nfsdcnt = DEFNFSDCNT;
188 }
189 break;
190 case 'r':
191 reregister = 1;
192 break;
193 case 't':
194 tcpflag = 1;
195 break;
196 case 'u':
197 udpflag = 1;
198 break;
199 #ifdef ISO
200 case 'c':
201 cltpflag = 1;
202 break;
203 #ifdef notyet
204 case 'i':
205 tp4cnt = 1;
206 break;
207 case 'p':
208 tpipcnt = 1;
209 break;
210 #endif /* notyet */
211 #endif /* ISO */
212 default:
213 case '?':
214 usage();
215 };
216 }
217 argv += optind;
218 argc -= optind;
219
220 /*
221 * XXX
222 * Backward compatibility, trailing number is the count of daemons.
223 */
224 if (argc > 1)
225 usage();
226 if (argc == 1) {
227 nfsdcnt = atoi(argv[0]);
228 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
229 warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
230 nfsdcnt = DEFNFSDCNT;
231 }
232 }
233
234 /*
235 * If none of TCP or UDP are specified, default to UDP only.
236 */
237 if (tcpflag == 0 && udpflag == 0)
238 udpflag = 1;
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 }
247 (void)signal(SIGCHLD, reapchild);
248
249 if (udpflag) {
250 memset(&hints, 0, sizeof hints);
251 hints.ai_flags = AI_PASSIVE;
252 hints.ai_family = PF_INET;
253 hints.ai_socktype = SOCK_DGRAM;
254 hints.ai_protocol = IPPROTO_UDP;
255
256 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
257 if (ecode != 0) {
258 syslog(LOG_ERR, "getaddrinfo udp: %s",
259 gai_strerror(ecode));
260 exit(1);
261 }
262
263 nconf_udp = getnetconfigent("udp");
264
265 if (nconf_udp == NULL)
266 err(1, "getnetconfigent udp failed");
267
268 nb_udp.buf = ai_udp->ai_addr;
269 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
270 if (reregister)
271 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp))
272 err(1, "rpcb_set udp failed");
273 }
274
275 if (tcpflag) {
276 memset(&hints, 0, sizeof hints);
277 hints.ai_flags = AI_PASSIVE;
278 hints.ai_family = PF_INET;
279 hints.ai_socktype = SOCK_STREAM;
280 hints.ai_protocol = IPPROTO_TCP;
281
282 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
283 if (ecode != 0) {
284 syslog(LOG_ERR, "getaddrinfo tcp: %s",
285 gai_strerror(ecode));
286 exit(1);
287 }
288
289 nconf_tcp = getnetconfigent("tcp");
290
291 if (nconf_tcp == NULL)
292 err(1, "getnetconfigent tcp failed");
293
294 nb_tcp.buf = ai_tcp->ai_addr;
295 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
296 if (reregister)
297 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp))
298 err(1, "rpcb_set tcp failed");
299 }
300
301 if (udpflag && ip6flag) {
302 memset(&hints, 0, sizeof hints);
303 hints.ai_flags = AI_PASSIVE;
304 hints.ai_family = PF_INET6;
305 hints.ai_socktype = SOCK_DGRAM;
306 hints.ai_protocol = IPPROTO_UDP;
307
308 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
309 if (ecode != 0) {
310 syslog(LOG_ERR, "getaddrinfo udp: %s",
311 gai_strerror(ecode));
312 exit(1);
313 }
314
315 nconf_udp6 = getnetconfigent("udp6");
316
317 if (nconf_udp6 == NULL)
318 err(1, "getnetconfigent udp6 failed");
319
320 nb_udp6.buf = ai_udp6->ai_addr;
321 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
322 if (reregister)
323 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6))
324 err(1, "rpcb_set udp6 failed");
325 }
326
327 if (tcpflag && ip6flag) {
328 memset(&hints, 0, sizeof hints);
329 hints.ai_flags = AI_PASSIVE;
330 hints.ai_family = PF_INET6;
331 hints.ai_socktype = SOCK_STREAM;
332 hints.ai_protocol = IPPROTO_TCP;
333
334 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
335 if (ecode != 0) {
336 syslog(LOG_ERR, "getaddrinfo tcp: %s",
337 gai_strerror(ecode));
338 exit(1);
339 }
340
341 nconf_tcp6 = getnetconfigent("tcp6");
342
343 if (nconf_tcp6 == NULL)
344 err(1, "getnetconfigent tcp6 failed");
345
346 nb_tcp6.buf = ai_tcp6->ai_addr;
347 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
348 if (reregister)
349 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6))
350 err(1, "rpcb_set tcp6 failed");
351 }
352
353 openlog("nfsd", LOG_PID, LOG_DAEMON);
354
355 for (i = 0; i < nfsdcnt; i++) {
356 pthread_t t;
357 int error;
358
359 error = pthread_create(&t, NULL, child, NULL);
360 if (error) {
361 errno = error;
362 syslog(LOG_ERR, "pthread_create: %m");
363 exit (1);
364 }
365 }
366
367 /* If we are serving udp, set up the socket. */
368 if (udpflag) {
369 if ((sock = socket(ai_udp->ai_family, ai_udp->ai_socktype,
370 ai_udp->ai_protocol)) < 0) {
371 syslog(LOG_ERR, "can't create udp socket");
372 exit(1);
373 }
374 if (bind(sock, ai_udp->ai_addr, ai_udp->ai_addrlen) < 0) {
375 syslog(LOG_ERR, "can't bind udp addr");
376 exit(1);
377 }
378 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp) ||
379 !rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)) {
380 syslog(LOG_ERR, "can't register with udp portmap");
381 exit(1);
382 }
383 nfsdargs.sock = sock;
384 nfsdargs.name = NULL;
385 nfsdargs.namelen = 0;
386 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
387 syslog(LOG_ERR, "can't add UDP socket");
388 exit(1);
389 }
390 (void)close(sock);
391 }
392
393 if (udpflag &&ip6flag) {
394 if ((sock = socket(ai_udp6->ai_family, ai_udp6->ai_socktype,
395 ai_udp6->ai_protocol)) < 0) {
396 syslog(LOG_ERR, "can't create udp socket");
397 exit(1);
398 }
399 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
400 &on, sizeof on) < 0) {
401 syslog(LOG_ERR, "can't set v6-only binding for udp6 "
402 "socket: %m");
403 exit(1);
404 }
405 if (bind(sock, ai_udp6->ai_addr, ai_udp6->ai_addrlen) < 0) {
406 syslog(LOG_ERR, "can't bind udp addr");
407 exit(1);
408 }
409 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6) ||
410 !rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)) {
411 syslog(LOG_ERR, "can't register with udp portmap");
412 exit(1);
413 }
414 nfsdargs.sock = sock;
415 nfsdargs.name = NULL;
416 nfsdargs.namelen = 0;
417 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
418 syslog(LOG_ERR, "can't add UDP6 socket");
419 exit(1);
420 }
421 (void)close(sock);
422 }
423
424 #ifdef ISO
425 /* If we are serving cltp, set up the socket. */
426 if (cltpflag) {
427 if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
428 syslog(LOG_ERR, "can't create cltp socket");
429 exit(1);
430 }
431 memset(&isoaddr, 0, sizeof(isoaddr));
432 isoaddr.siso_family = AF_ISO;
433 isoaddr.siso_tlen = 2;
434 cp = TSEL(&isoaddr);
435 *cp++ = (NFS_PORT >> 8);
436 *cp = (NFS_PORT & 0xff);
437 isoaddr.siso_len = sizeof(isoaddr);
438 if (bind(sock,
439 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
440 syslog(LOG_ERR, "can't bind cltp addr");
441 exit(1);
442 }
443 #ifdef notyet
444 /*
445 * XXX
446 * Someday this should probably use "rpcbind", the son of
447 * portmap.
448 */
449 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
450 syslog(LOG_ERR, "can't register with udp portmap");
451 exit(1);
452 }
453 #endif /* notyet */
454 nfsdargs.sock = sock;
455 nfsdargs.name = NULL;
456 nfsdargs.namelen = 0;
457 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
458 syslog(LOG_ERR, "can't add UDP socket");
459 exit(1);
460 }
461 close(sock);
462 }
463 #endif /* ISO */
464
465 /* Now set up the master server socket waiting for tcp connections. */
466 on = 1;
467 connect_type_cnt = 0;
468 if (tcpflag) {
469 if ((tcpsock = socket(ai_tcp->ai_family, ai_tcp->ai_socktype,
470 ai_tcp->ai_protocol)) < 0) {
471 syslog(LOG_ERR, "can't create tcp socket");
472 exit(1);
473 }
474 if (setsockopt(tcpsock,
475 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
476 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
477 if (bind(tcpsock, ai_tcp->ai_addr, ai_tcp->ai_addrlen) < 0) {
478 syslog(LOG_ERR, "can't bind tcp addr");
479 exit(1);
480 }
481 if (listen(tcpsock, 5) < 0) {
482 syslog(LOG_ERR, "listen failed");
483 exit(1);
484 }
485 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp) ||
486 !rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)) {
487 syslog(LOG_ERR, "can't register tcp with rpcbind");
488 exit(1);
489 }
490 set[0].fd = tcpsock;
491 set[0].events = POLLIN;
492 connect_type_cnt++;
493 } else
494 set[0].fd = -1;
495
496 if (tcpflag && ip6flag) {
497 if ((tcp6sock = socket(ai_tcp6->ai_family, ai_tcp6->ai_socktype,
498 ai_tcp6->ai_protocol)) < 0) {
499 syslog(LOG_ERR, "can't create tcp socket");
500 exit(1);
501 }
502 if (setsockopt(tcp6sock,
503 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
504 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
505 if (setsockopt(tcp6sock, IPPROTO_IPV6, IPV6_V6ONLY,
506 &on, sizeof on) < 0) {
507 syslog(LOG_ERR, "can't set v6-only binding for tcp6 "
508 "socket: %m");
509 exit(1);
510 }
511 if (bind(tcp6sock, ai_tcp6->ai_addr, ai_tcp6->ai_addrlen) < 0) {
512 syslog(LOG_ERR, "can't bind tcp6 addr");
513 exit(1);
514 }
515 if (listen(tcp6sock, 5) < 0) {
516 syslog(LOG_ERR, "listen failed");
517 exit(1);
518 }
519 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6) ||
520 !rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)) {
521 syslog(LOG_ERR, "can't register tcp6 with rpcbind");
522 exit(1);
523 }
524 set[1].fd = tcp6sock;
525 set[1].events = POLLIN;
526 connect_type_cnt++;
527 } else
528 set[1].fd = -1;
529
530 #ifdef notyet
531 /* Now set up the master server socket waiting for tp4 connections. */
532 if (tp4flag) {
533 if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
534 syslog(LOG_ERR, "can't create tp4 socket");
535 exit(1);
536 }
537 if (setsockopt(tp4sock,
538 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
539 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
540 memset(&isoaddr, 0, sizeof(isoaddr));
541 isoaddr.siso_family = AF_ISO;
542 isoaddr.siso_tlen = 2;
543 cp = TSEL(&isoaddr);
544 *cp++ = (NFS_PORT >> 8);
545 *cp = (NFS_PORT & 0xff);
546 isoaddr.siso_len = sizeof(isoaddr);
547 if (bind(tp4sock,
548 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
549 syslog(LOG_ERR, "can't bind tp4 addr");
550 exit(1);
551 }
552 if (listen(tp4sock, 5) < 0) {
553 syslog(LOG_ERR, "listen failed");
554 exit(1);
555 }
556 /*
557 * XXX
558 * Someday this should probably use "rpcbind", the son of
559 * portmap.
560 */
561 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
562 syslog(LOG_ERR, "can't register tcp with portmap");
563 exit(1);
564 }
565 set[2].fd = tp4sock;
566 set[2].events = POLLIN;
567 connect_type_cnt++;
568 } else
569 set[2].fd = -1;
570
571 /* Now set up the master server socket waiting for tpip connections. */
572 if (tpipflag) {
573 if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
574 syslog(LOG_ERR, "can't create tpip socket");
575 exit(1);
576 }
577 if (setsockopt(tpipsock,
578 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
579 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
580 inetaddr.sin_family = AF_INET;
581 inetaddr.sin_addr.s_addr = INADDR_ANY;
582 inetaddr.sin_port = htons(NFS_PORT);
583 inetaddr.sin_len = sizeof(inetaddr);
584 memset(inetaddr.sin_zero, 0, sizeof(inetaddr.sin_zero));
585 if (bind(tpipsock,
586 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
587 syslog(LOG_ERR, "can't bind tcp addr");
588 exit(1);
589 }
590 if (listen(tpipsock, 5) < 0) {
591 syslog(LOG_ERR, "listen failed");
592 exit(1);
593 }
594 /*
595 * XXX
596 * Someday this should probably use "rpcbind", the son of
597 * portmap.
598 */
599 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
600 syslog(LOG_ERR, "can't register tcp with portmap");
601 exit(1);
602 }
603 set[3].fd = tpipsock;
604 set[3].events = POLLIN;
605 connect_type_cnt++;
606 } else
607 set[3].fd = -1;
608 #else
609 set[2].fd = -1;
610 set[3].fd = -1;
611 #endif /* notyet */
612
613 if (connect_type_cnt == 0)
614 exit(0);
615
616 setproctitle("master");
617
618 /*
619 * Loop forever accepting connections and passing the sockets
620 * into the kernel for the mounts.
621 */
622 for (;;) {
623 if (poll(set, 4, INFTIM) < 1) {
624 syslog(LOG_ERR, "poll failed: %m");
625 exit(1);
626 }
627
628 if (set[0].revents & POLLIN) {
629 len = sizeof(inetpeer);
630 if ((msgsock = accept(tcpsock,
631 (struct sockaddr *)&inetpeer, &len)) < 0) {
632 syslog(LOG_ERR, "accept failed: %m");
633 exit(1);
634 }
635 memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
636 if (setsockopt(msgsock, SOL_SOCKET,
637 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
638 syslog(LOG_ERR,
639 "setsockopt SO_KEEPALIVE: %m");
640 nfsdargs.sock = msgsock;
641 nfsdargs.name = (caddr_t)&inetpeer;
642 nfsdargs.namelen = sizeof(inetpeer);
643 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
644 (void)close(msgsock);
645 }
646
647 if (set[1].revents & POLLIN) {
648 len = sizeof(inet6peer);
649 if ((msgsock = accept(tcp6sock,
650 (struct sockaddr *)&inet6peer, &len)) < 0) {
651 syslog(LOG_ERR, "accept failed: %m");
652 exit(1);
653 }
654 if (setsockopt(msgsock, SOL_SOCKET,
655 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
656 syslog(LOG_ERR,
657 "setsockopt SO_KEEPALIVE: %m");
658 nfsdargs.sock = msgsock;
659 nfsdargs.name = (caddr_t)&inet6peer;
660 nfsdargs.namelen = sizeof(inet6peer);
661 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
662 (void)close(msgsock);
663 }
664
665 #ifdef notyet
666 if (set[2].revents & POLLIN) {
667 len = sizeof(isopeer);
668 if ((msgsock = accept(tp4sock,
669 (struct sockaddr *)&isopeer, &len)) < 0) {
670 syslog(LOG_ERR, "accept failed: %m");
671 exit(1);
672 }
673 if (setsockopt(msgsock, SOL_SOCKET,
674 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
675 syslog(LOG_ERR,
676 "setsockopt SO_KEEPALIVE: %m");
677 nfsdargs.sock = msgsock;
678 nfsdargs.name = (caddr_t)&isopeer;
679 nfsdargs.namelen = len;
680 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
681 (void)close(msgsock);
682 }
683
684 if (set[3].revents & POLLIN) {
685 len = sizeof(inetpeer);
686 if ((msgsock = accept(tpipsock,
687 (struct sockaddr *)&inetpeer, &len)) < 0) {
688 syslog(LOG_ERR, "accept failed: %m");
689 exit(1);
690 }
691 if (setsockopt(msgsock, SOL_SOCKET,
692 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
693 syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
694 nfsdargs.sock = msgsock;
695 nfsdargs.name = (caddr_t)&inetpeer;
696 nfsdargs.namelen = len;
697 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
698 (void)close(msgsock);
699 }
700 #endif /* notyet */
701 }
702 }
703
704 void
705 usage()
706 {
707 (void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
708 exit(1);
709 }
710
711 void
712 nonfs(signo)
713 int signo;
714 {
715 syslog(LOG_ERR, "missing system call: NFS not available.");
716 }
717
718 void
719 reapchild(signo)
720 int signo;
721 {
722 while (wait3(NULL, WNOHANG, NULL) > 0);
723 }
724