2 * Copyright (c) 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * @(#) Copyright (c) 1989, 1993, 1994 The Regents of the University of California. All rights reserved.
33 * @(#)nfsd.c 8.9 (Berkeley) 3/29/95
34 * $FreeBSD: src/usr.sbin/nfsd/nfsd.c,v 1.34 2005/12/21 10:12:05 delphij Exp $
35 * $DragonFly: src/sbin/nfsd/nfsd.c,v 1.10 2006/12/27 23:06:29 corecode Exp $
38 #include <sys/param.h>
39 #include <sys/syslog.h>
41 #include <sys/mount.h>
42 #include <sys/linker.h>
43 #include <sys/module.h>
46 #include <rpc/pmap_clnt.h>
49 #include <arpa/inet.h>
50 #include <nfs/rpcv2.h>
51 #include <nfs/nfsproto.h>
65 #define syslog(e, s...) fprintf(stderr,s)
71 struct nfsd_srvargs nsd
;
73 #define MAXNFSDCNT 256
75 pid_t children
[MAXNFSDCNT
]; /* PIDs of children */
76 int nfsdcnt
; /* number of children */
79 void child_cleanup(int);
80 void killchildren(void);
84 int setbindhost(struct addrinfo
**ia
, const char *bindhost
,
85 struct addrinfo hints
);
86 void start_server(int);
87 void unregistration(void);
91 * Nfs server daemon mostly just a user context for nfssvc()
93 * 1 - do file descriptor and signal cleanup
94 * 2 - fork the nfsd(s)
95 * 3 - create server socket(s)
96 * 4 - register socket with rpcbind
98 * For connectionless protocols, just pass the socket into the kernel via.
100 * For connection based sockets, loop doing accepts. When you get a new
101 * socket from accept, pass the msgsock into the kernel via. nfssvc().
103 * -r - reregister with rpcbind
104 * -d - unregister with rpcbind
105 * -t - support tcp nfs clients
106 * -u - support udp nfs clients
107 * followed by "n" which is the number of nfsds' to fork off
110 main(int argc
, char **argv
)
112 struct nfsd_args nfsdargs
;
113 struct addrinfo
*ai_udp
, *ai_tcp
, *ai_udp6
, *ai_tcp6
, hints
;
114 struct netconfig
*nconf_udp
, *nconf_tcp
, *nconf_udp6
, *nconf_tcp6
;
115 struct netbuf nb_udp
, nb_tcp
, nb_udp6
, nb_tcp6
;
116 struct sockaddr_in inetpeer
;
117 struct sockaddr_in6 inet6peer
;
118 fd_set ready
, sockbits
;
119 fd_set v4bits
, v6bits
;
120 int ch
, connect_type_cnt
, i
, maxsock
, msgsock
;
122 int on
= 1, unregister
, reregister
, sock
;
123 int tcp6sock
, ip6flag
, tcpflag
, tcpsock
;
124 int udpflag
, ecode
, s
, srvcnt
;
125 int bindhostc
, bindanyflag
, rpcbreg
, rpcbregcnt
;
126 char **bindhost
= NULL
;
131 error
= getvfsbyname("nfs", &vfc
);
132 if (error
&& vfsisloadable("nfs")) {
134 err(1, "vfsload(nfs)");
135 endvfsent(); /* flush cache */
136 error
= getvfsbyname("nfs", &vfc
);
139 errx(1, "NFS is not available in the running kernel");
141 nfsdcnt
= DEFNFSDCNT
;
142 unregister
= reregister
= tcpflag
= maxsock
= 0;
143 bindanyflag
= udpflag
= connect_type_cnt
= bindhostc
= 0;
144 #define GETOPT "ah:n:rdtu"
145 #define USAGE "[-ardtu] [-n num_servers] [-h bindip]"
146 while ((ch
= getopt(argc
, argv
, GETOPT
)) != -1)
152 nfsdcnt
= atoi(optarg
);
153 if (nfsdcnt
< 1 || nfsdcnt
> MAXNFSDCNT
) {
154 warnx("nfsd count %d; reset to %d", nfsdcnt
,
156 nfsdcnt
= DEFNFSDCNT
;
161 bindhost
= realloc(bindhost
,sizeof(char *)*bindhostc
);
162 if (bindhost
== NULL
)
163 errx(1, "Out of memory");
164 bindhost
[bindhostc
-1] = strdup(optarg
);
165 if (bindhost
[bindhostc
-1] == NULL
)
166 errx(1, "Out of memory");
184 if (!tcpflag
&& !udpflag
)
191 * Backward compatibility, trailing number is the count of daemons.
196 nfsdcnt
= atoi(argv
[0]);
197 if (nfsdcnt
< 1 || nfsdcnt
> MAXNFSDCNT
) {
198 warnx("nfsd count %d; reset to %d", nfsdcnt
,
200 nfsdcnt
= DEFNFSDCNT
;
205 s
= socket(AF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
);
207 if (errno
!= EPROTONOSUPPORT
)
210 } else if (getnetconfigent("udp6") == NULL
||
211 getnetconfigent("tcp6") == NULL
) {
217 if (bindhostc
== 0 || bindanyflag
) {
219 bindhost
= realloc(bindhost
,sizeof(char *)*bindhostc
);
220 if (bindhost
== NULL
)
221 errx(1, "Out of memory");
222 bindhost
[bindhostc
-1] = strdup("*");
223 if (bindhost
[bindhostc
-1] == NULL
)
224 errx(1, "Out of memory");
233 memset(&hints
, 0, sizeof hints
);
234 hints
.ai_flags
= AI_PASSIVE
;
235 hints
.ai_family
= AF_INET
;
236 hints
.ai_socktype
= SOCK_DGRAM
;
237 hints
.ai_protocol
= IPPROTO_UDP
;
238 ecode
= getaddrinfo(NULL
, "nfs", &hints
, &ai_udp
);
240 err(1, "getaddrinfo udp: %s", gai_strerror(ecode
));
241 nconf_udp
= getnetconfigent("udp");
242 if (nconf_udp
== NULL
)
243 err(1, "getnetconfigent udp failed");
244 nb_udp
.buf
= ai_udp
->ai_addr
;
245 nb_udp
.len
= nb_udp
.maxlen
= ai_udp
->ai_addrlen
;
246 if ((!rpcb_set(RPCPROG_NFS
, 2, nconf_udp
, &nb_udp
)) ||
247 (!rpcb_set(RPCPROG_NFS
, 3, nconf_udp
, &nb_udp
)))
248 err(1, "rpcb_set udp failed");
249 freeaddrinfo(ai_udp
);
251 if (udpflag
&& ip6flag
) {
252 memset(&hints
, 0, sizeof hints
);
253 hints
.ai_flags
= AI_PASSIVE
;
254 hints
.ai_family
= AF_INET6
;
255 hints
.ai_socktype
= SOCK_DGRAM
;
256 hints
.ai_protocol
= IPPROTO_UDP
;
257 ecode
= getaddrinfo(NULL
, "nfs", &hints
, &ai_udp6
);
259 err(1, "getaddrinfo udp6: %s", gai_strerror(ecode
));
260 nconf_udp6
= getnetconfigent("udp6");
261 if (nconf_udp6
== NULL
)
262 err(1, "getnetconfigent udp6 failed");
263 nb_udp6
.buf
= ai_udp6
->ai_addr
;
264 nb_udp6
.len
= nb_udp6
.maxlen
= ai_udp6
->ai_addrlen
;
265 if ((!rpcb_set(RPCPROG_NFS
, 2, nconf_udp6
, &nb_udp6
)) ||
266 (!rpcb_set(RPCPROG_NFS
, 3, nconf_udp6
, &nb_udp6
)))
267 err(1, "rpcb_set udp6 failed");
268 freeaddrinfo(ai_udp6
);
271 memset(&hints
, 0, sizeof hints
);
272 hints
.ai_flags
= AI_PASSIVE
;
273 hints
.ai_family
= AF_INET
;
274 hints
.ai_socktype
= SOCK_STREAM
;
275 hints
.ai_protocol
= IPPROTO_TCP
;
276 ecode
= getaddrinfo(NULL
, "nfs", &hints
, &ai_tcp
);
278 err(1, "getaddrinfo tcp: %s", gai_strerror(ecode
));
279 nconf_tcp
= getnetconfigent("tcp");
280 if (nconf_tcp
== NULL
)
281 err(1, "getnetconfigent tcp failed");
282 nb_tcp
.buf
= ai_tcp
->ai_addr
;
283 nb_tcp
.len
= nb_tcp
.maxlen
= ai_tcp
->ai_addrlen
;
284 if ((!rpcb_set(RPCPROG_NFS
, 2, nconf_tcp
, &nb_tcp
)) ||
285 (!rpcb_set(RPCPROG_NFS
, 3, nconf_tcp
, &nb_tcp
)))
286 err(1, "rpcb_set tcp failed");
287 freeaddrinfo(ai_tcp
);
289 if (tcpflag
&& ip6flag
) {
290 memset(&hints
, 0, sizeof hints
);
291 hints
.ai_flags
= AI_PASSIVE
;
292 hints
.ai_family
= AF_INET6
;
293 hints
.ai_socktype
= SOCK_STREAM
;
294 hints
.ai_protocol
= IPPROTO_TCP
;
295 ecode
= getaddrinfo(NULL
, "nfs", &hints
, &ai_tcp6
);
297 err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode
));
298 nconf_tcp6
= getnetconfigent("tcp6");
299 if (nconf_tcp6
== NULL
)
300 err(1, "getnetconfigent tcp6 failed");
301 nb_tcp6
.buf
= ai_tcp6
->ai_addr
;
302 nb_tcp6
.len
= nb_tcp6
.maxlen
= ai_tcp6
->ai_addrlen
;
303 if ((!rpcb_set(RPCPROG_NFS
, 2, nconf_tcp6
, &nb_tcp6
)) ||
304 (!rpcb_set(RPCPROG_NFS
, 3, nconf_tcp6
, &nb_tcp6
)))
305 err(1, "rpcb_set tcp6 failed");
306 freeaddrinfo(ai_tcp6
);
312 signal(SIGHUP
, SIG_IGN
);
313 signal(SIGINT
, SIG_IGN
);
315 * nfsd sits in the kernel most of the time. It needs
316 * to ignore SIGTERM/SIGQUIT in order to stay alive as long
317 * as possible during a shutdown, otherwise loopback
318 * mounts will not be able to unmount.
320 signal(SIGTERM
, SIG_IGN
);
321 signal(SIGQUIT
, SIG_IGN
);
323 signal(SIGSYS
, nonfs
);
324 signal(SIGCHLD
, reapchild
);
326 openlog("nfsd", LOG_PID
, LOG_DAEMON
);
328 /* If we use UDP only, we start the last server below. */
329 srvcnt
= tcpflag
? nfsdcnt
: nfsdcnt
- 1;
330 for (i
= 0; i
< srvcnt
; i
++) {
331 switch ((pid
= fork())) {
333 syslog(LOG_ERR
, "fork: %m");
341 signal(SIGUSR1
, child_cleanup
);
342 setproctitle("server");
347 signal(SIGUSR1
, cleanup
);
353 /* Set up the socket for udp and rpcb register it. */
356 for (i
= 0; i
< bindhostc
; i
++) {
357 memset(&hints
, 0, sizeof hints
);
358 hints
.ai_flags
= AI_PASSIVE
;
359 hints
.ai_family
= AF_INET
;
360 hints
.ai_socktype
= SOCK_DGRAM
;
361 hints
.ai_protocol
= IPPROTO_UDP
;
362 if (setbindhost(&ai_udp
, bindhost
[i
], hints
) == 0) {
365 if ((sock
= socket(ai_udp
->ai_family
,
367 ai_udp
->ai_protocol
)) < 0) {
369 "can't create udp socket");
372 if (bind(sock
, ai_udp
->ai_addr
,
373 ai_udp
->ai_addrlen
) < 0) {
375 "can't bind udp addr %s: %m",
379 freeaddrinfo(ai_udp
);
380 nfsdargs
.sock
= sock
;
381 nfsdargs
.name
= NULL
;
382 nfsdargs
.namelen
= 0;
383 if (nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
) < 0) {
384 syslog(LOG_ERR
, "can't Add UDP socket");
391 memset(&hints
, 0, sizeof hints
);
392 hints
.ai_flags
= AI_PASSIVE
;
393 hints
.ai_family
= AF_INET
;
394 hints
.ai_socktype
= SOCK_DGRAM
;
395 hints
.ai_protocol
= IPPROTO_UDP
;
396 ecode
= getaddrinfo(NULL
, "nfs", &hints
, &ai_udp
);
398 syslog(LOG_ERR
, "getaddrinfo udp: %s",
399 gai_strerror(ecode
));
402 nconf_udp
= getnetconfigent("udp");
403 if (nconf_udp
== NULL
)
404 err(1, "getnetconfigent udp failed");
405 nb_udp
.buf
= ai_udp
->ai_addr
;
406 nb_udp
.len
= nb_udp
.maxlen
= ai_udp
->ai_addrlen
;
407 if ((!rpcb_set(RPCPROG_NFS
, 2, nconf_udp
, &nb_udp
)) ||
408 (!rpcb_set(RPCPROG_NFS
, 3, nconf_udp
, &nb_udp
)))
409 err(1, "rpcb_set udp failed");
410 freeaddrinfo(ai_udp
);
414 /* Set up the socket for udp6 and rpcb register it. */
415 if (udpflag
&& ip6flag
) {
417 for (i
= 0; i
< bindhostc
; i
++) {
418 memset(&hints
, 0, sizeof hints
);
419 hints
.ai_flags
= AI_PASSIVE
;
420 hints
.ai_family
= AF_INET6
;
421 hints
.ai_socktype
= SOCK_DGRAM
;
422 hints
.ai_protocol
= IPPROTO_UDP
;
423 if (setbindhost(&ai_udp6
, bindhost
[i
], hints
) == 0) {
426 if ((sock
= socket(ai_udp6
->ai_family
,
427 ai_udp6
->ai_socktype
,
428 ai_udp6
->ai_protocol
)) < 0) {
430 "can't create udp6 socket");
433 if (setsockopt(sock
, IPPROTO_IPV6
, IPV6_V6ONLY
,
434 &on
, sizeof on
) < 0) {
436 "can't set v6-only binding for "
440 if (bind(sock
, ai_udp6
->ai_addr
,
441 ai_udp6
->ai_addrlen
) < 0) {
443 "can't bind udp6 addr %s: %m",
447 freeaddrinfo(ai_udp6
);
448 nfsdargs
.sock
= sock
;
449 nfsdargs
.name
= NULL
;
450 nfsdargs
.namelen
= 0;
451 if (nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
) < 0) {
453 "can't add UDP6 socket");
460 memset(&hints
, 0, sizeof hints
);
461 hints
.ai_flags
= AI_PASSIVE
;
462 hints
.ai_family
= AF_INET6
;
463 hints
.ai_socktype
= SOCK_DGRAM
;
464 hints
.ai_protocol
= IPPROTO_UDP
;
465 ecode
= getaddrinfo(NULL
, "nfs", &hints
, &ai_udp6
);
467 syslog(LOG_ERR
, "getaddrinfo udp6: %s",
468 gai_strerror(ecode
));
471 nconf_udp6
= getnetconfigent("udp6");
472 if (nconf_udp6
== NULL
)
473 err(1, "getnetconfigent udp6 failed");
474 nb_udp6
.buf
= ai_udp6
->ai_addr
;
475 nb_udp6
.len
= nb_udp6
.maxlen
= ai_udp6
->ai_addrlen
;
476 if ((!rpcb_set(RPCPROG_NFS
, 2, nconf_udp6
, &nb_udp6
)) ||
477 (!rpcb_set(RPCPROG_NFS
, 3, nconf_udp6
, &nb_udp6
)))
478 err(1, "rpcb_set udp6 failed");
479 freeaddrinfo(ai_udp6
);
483 /* Set up the socket for tcp and rpcb register it. */
486 for (i
= 0; i
< bindhostc
; i
++) {
487 memset(&hints
, 0, sizeof hints
);
488 hints
.ai_flags
= AI_PASSIVE
;
489 hints
.ai_family
= AF_INET
;
490 hints
.ai_socktype
= SOCK_STREAM
;
491 hints
.ai_protocol
= IPPROTO_TCP
;
492 if (setbindhost(&ai_tcp
, bindhost
[i
], hints
) == 0) {
495 if ((tcpsock
= socket(AF_INET
, SOCK_STREAM
,
498 "can't create tpc socket");
501 if (setsockopt(tcpsock
, SOL_SOCKET
,
503 (char *)&on
, sizeof(on
)) < 0)
505 "setsockopt SO_REUSEADDR: %m");
506 if (bind(tcpsock
, ai_tcp
->ai_addr
,
507 ai_tcp
->ai_addrlen
) < 0) {
509 "can't bind tcp addr %s: %m",
513 if (listen(tcpsock
, 64) < 0) {
514 syslog(LOG_ERR
, "listen failed");
517 freeaddrinfo(ai_tcp
);
518 FD_SET(tcpsock
, &sockbits
);
519 FD_SET(tcpsock
, &v4bits
);
525 memset(&hints
, 0, sizeof hints
);
526 hints
.ai_flags
= AI_PASSIVE
;
527 hints
.ai_family
= AF_INET
;
528 hints
.ai_socktype
= SOCK_STREAM
;
529 hints
.ai_protocol
= IPPROTO_TCP
;
530 ecode
= getaddrinfo(NULL
, "nfs", &hints
,
533 syslog(LOG_ERR
, "getaddrinfo tcp: %s",
534 gai_strerror(ecode
));
537 nconf_tcp
= getnetconfigent("tcp");
538 if (nconf_tcp
== NULL
)
539 err(1, "getnetconfigent tcp failed");
540 nb_tcp
.buf
= ai_tcp
->ai_addr
;
541 nb_tcp
.len
= nb_tcp
.maxlen
= ai_tcp
->ai_addrlen
;
542 if ((!rpcb_set(RPCPROG_NFS
, 2, nconf_tcp
,
543 &nb_tcp
)) || (!rpcb_set(RPCPROG_NFS
, 3,
544 nconf_tcp
, &nb_tcp
)))
545 err(1, "rpcb_set tcp failed");
546 freeaddrinfo(ai_tcp
);
550 /* Set up the socket for tcp6 and rpcb register it. */
551 if (tcpflag
&& ip6flag
) {
553 for (i
= 0; i
< bindhostc
; i
++) {
554 memset(&hints
, 0, sizeof hints
);
555 hints
.ai_flags
= AI_PASSIVE
;
556 hints
.ai_family
= AF_INET6
;
557 hints
.ai_socktype
= SOCK_STREAM
;
558 hints
.ai_protocol
= IPPROTO_TCP
;
559 if (setbindhost(&ai_tcp6
, bindhost
[i
], hints
) == 0) {
562 if ((tcp6sock
= socket(ai_tcp6
->ai_family
,
563 ai_tcp6
->ai_socktype
,
564 ai_tcp6
->ai_protocol
)) < 0) {
566 "can't create tcp6 socket");
569 if (setsockopt(tcp6sock
, SOL_SOCKET
,
571 (char *)&on
, sizeof(on
)) < 0)
573 "setsockopt SO_REUSEADDR: %m");
574 if (setsockopt(tcp6sock
, IPPROTO_IPV6
,
575 IPV6_V6ONLY
, &on
, sizeof on
) < 0) {
577 "can't set v6-only binding for tcp6 "
581 if (bind(tcp6sock
, ai_tcp6
->ai_addr
,
582 ai_tcp6
->ai_addrlen
) < 0) {
584 "can't bind tcp6 addr %s: %m",
588 if (listen(tcp6sock
, 64) < 0) {
589 syslog(LOG_ERR
, "listen failed");
592 freeaddrinfo(ai_tcp6
);
593 FD_SET(tcp6sock
, &sockbits
);
594 FD_SET(tcp6sock
, &v6bits
);
595 if (maxsock
< tcp6sock
)
601 memset(&hints
, 0, sizeof hints
);
602 hints
.ai_flags
= AI_PASSIVE
;
603 hints
.ai_family
= AF_INET6
;
604 hints
.ai_socktype
= SOCK_STREAM
;
605 hints
.ai_protocol
= IPPROTO_TCP
;
606 ecode
= getaddrinfo(NULL
, "nfs", &hints
, &ai_tcp6
);
608 syslog(LOG_ERR
, "getaddrinfo tcp6: %s",
609 gai_strerror(ecode
));
612 nconf_tcp6
= getnetconfigent("tcp6");
613 if (nconf_tcp6
== NULL
)
614 err(1, "getnetconfigent tcp6 failed");
615 nb_tcp6
.buf
= ai_tcp6
->ai_addr
;
616 nb_tcp6
.len
= nb_tcp6
.maxlen
= ai_tcp6
->ai_addrlen
;
617 if ((!rpcb_set(RPCPROG_NFS
, 2, nconf_tcp6
, &nb_tcp6
)) ||
618 (!rpcb_set(RPCPROG_NFS
, 3, nconf_tcp6
, &nb_tcp6
)))
619 err(1, "rpcb_set tcp6 failed");
620 freeaddrinfo(ai_tcp6
);
624 if (rpcbregcnt
== 0) {
625 syslog(LOG_ERR
, "rpcb_set() failed, nothing to do: %m");
629 if (tcpflag
&& connect_type_cnt
== 0) {
630 syslog(LOG_ERR
, "tcp connects == 0, nothing to do: %m");
634 setproctitle("master");
636 * We always want a master to have a clean way to to shut nfsd down
637 * (with unregistration): if the master is killed, it unregisters and
638 * kills all children. If we run for UDP only (and so do not have to
639 * loop waiting waiting for accept), we instead make the parent
640 * a "server" too. start_server will not return.
646 * Loop forever accepting connections and passing the sockets
647 * into the kernel for the mounts.
651 if (connect_type_cnt
> 1) {
652 if (select(maxsock
+ 1,
653 &ready
, NULL
, NULL
, NULL
) < 1) {
654 syslog(LOG_ERR
, "select failed: %m");
660 for (tcpsock
= 0; tcpsock
<= maxsock
; tcpsock
++) {
661 if (FD_ISSET(tcpsock
, &ready
)) {
662 if (FD_ISSET(tcpsock
, &v4bits
)) {
663 len
= sizeof(inetpeer
);
664 if ((msgsock
= accept(tcpsock
,
665 (struct sockaddr
*)&inetpeer
, &len
)) < 0) {
666 syslog(LOG_ERR
, "accept failed: %m");
667 if (errno
== ECONNABORTED
||
672 memset(inetpeer
.sin_zero
, 0,
673 sizeof(inetpeer
.sin_zero
));
674 if (setsockopt(msgsock
, SOL_SOCKET
,
675 SO_KEEPALIVE
, (char *)&on
, sizeof(on
)) < 0)
677 "setsockopt SO_KEEPALIVE: %m");
678 nfsdargs
.sock
= msgsock
;
679 nfsdargs
.name
= (caddr_t
)&inetpeer
;
680 nfsdargs
.namelen
= len
;
681 nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
);
683 } else if (FD_ISSET(tcpsock
, &v6bits
)) {
684 len
= sizeof(inet6peer
);
685 if ((msgsock
= accept(tcpsock
,
686 (struct sockaddr
*)&inet6peer
,
689 "accept failed: %m");
690 if (errno
== ECONNABORTED
||
695 if (setsockopt(msgsock
, SOL_SOCKET
,
696 SO_KEEPALIVE
, (char *)&on
,
698 syslog(LOG_ERR
, "setsockopt "
700 nfsdargs
.sock
= msgsock
;
701 nfsdargs
.name
= (caddr_t
)&inet6peer
;
702 nfsdargs
.namelen
= len
;
703 nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
);
712 setbindhost(struct addrinfo
**ai
, const char *bindhost
, struct addrinfo hints
)
715 u_int32_t host_addr
[4]; /* IPv4 or IPv6 */
718 if (bindhost
== NULL
|| strcmp("*", bindhost
) == 0)
723 if (hostptr
!= NULL
) {
724 switch (hints
.ai_family
) {
726 if (inet_pton(AF_INET
, hostptr
, host_addr
) == 1) {
727 hints
.ai_flags
= AI_NUMERICHOST
;
729 if (inet_pton(AF_INET6
, hostptr
,
735 if (inet_pton(AF_INET6
, hostptr
, host_addr
) == 1) {
736 hints
.ai_flags
= AI_NUMERICHOST
;
738 if (inet_pton(AF_INET
, hostptr
,
748 ecode
= getaddrinfo(hostptr
, "nfs", &hints
, ai
);
750 syslog(LOG_ERR
, "getaddrinfo %s: %s", bindhost
,
751 gai_strerror(ecode
));
760 fprintf(stderr
, "usage: nfsd %s\n", USAGE
);
765 nonfs(int signo __unused
)
767 syslog(LOG_ERR
, "missing system call: NFS not available");
771 reapchild(int signo __unused
)
776 while ((pid
= wait3(NULL
, WNOHANG
, NULL
)) > 0) {
777 for (i
= 0; i
< nfsdcnt
; i
++)
778 if (pid
== children
[i
])
786 if ((!rpcb_unset(RPCPROG_NFS
, 2, NULL
)) ||
787 (!rpcb_unset(RPCPROG_NFS
, 3, NULL
)))
788 syslog(LOG_ERR
, "rpcb_unset failed");
796 for (i
= 0; i
< nfsdcnt
; i
++) {
798 kill(children
[i
], SIGKILL
);
803 * Cleanup master after SIGUSR1.
806 cleanup(__unused
int signo
)
812 * Cleanup child after SIGUSR1.
815 child_cleanup(__unused
int signo
)
821 nfsd_exit(int status
)
829 start_server(int master
)
835 if (nfssvc(NFSSVC_NFSD
, &nsd
) < 0) {
836 syslog(LOG_ERR
, "nfssvc: %m");