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, 5) < 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, 5) < 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");