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
34 static const char copyright[] =
35 "@(#) Copyright (c) 1989, 1993, 1994\n\
36 The Regents of the University of California. All rights reserved.\n";
41 static char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95";
43 static const char rcsid[] =
47 #include <sys/param.h>
48 #include <sys/syslog.h>
50 #include <sys/mount.h>
51 #include <sys/linker.h>
52 #include <sys/module.h>
55 #include <rpc/pmap_clnt.h>
58 #include <arpa/inet.h>
59 #include <nfs/rpcv2.h>
60 #include <nfs/nfsproto.h>
61 #include <nfsserver/nfs.h>
74 #define syslog(e, s...) fprintf(stderr,s)
80 #define MAXNFSDCNT 256
82 pid_t children[MAXNFSDCNT]; /* PIDs of children */
83 int nfsdcnt; /* number of children */
86 void child_cleanup(int);
87 void killchildren(void);
91 int setbindhost(struct addrinfo **ia, const char *bindhost,
92 struct addrinfo hints);
93 void start_server(int);
94 void unregistration(void);
98 * Nfs server daemon mostly just a user context for nfssvc()
100 * 1 - do file descriptor and signal cleanup
101 * 2 - fork the nfsd(s)
102 * 3 - create server socket(s)
103 * 4 - register socket with rpcbind
105 * For connectionless protocols, just pass the socket into the kernel via.
107 * For connection based sockets, loop doing accepts. When you get a new
108 * socket from accept, pass the msgsock into the kernel via. nfssvc().
110 * -r - reregister with rpcbind
111 * -d - unregister with rpcbind
112 * -t - support tcp nfs clients
113 * -u - support udp nfs clients
114 * followed by "n" which is the number of nfsds' to fork off
117 main(int argc, char **argv)
119 struct nfsd_args nfsdargs;
120 struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
121 struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
122 struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
123 struct sockaddr_in inetpeer;
124 struct sockaddr_in6 inet6peer;
125 fd_set ready, sockbits;
126 fd_set v4bits, v6bits;
127 int ch, connect_type_cnt, i, maxsock, msgsock;
129 int on = 1, unregister, reregister, sock;
130 int tcp6sock, ip6flag, tcpflag, tcpsock;
131 int udpflag, ecode, s, srvcnt;
132 int bindhostc, bindanyflag, rpcbreg, rpcbregcnt;
133 char **bindhost = NULL;
136 if (modfind("nfsserver") < 0) {
137 /* Not present in kernel, try loading it */
138 if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0)
139 errx(1, "NFS server is not available");
142 nfsdcnt = DEFNFSDCNT;
143 unregister = reregister = tcpflag = maxsock = 0;
144 bindanyflag = udpflag = connect_type_cnt = bindhostc = 0;
145 #define GETOPT "ah:n:rdtu"
146 #define USAGE "[-ardtu] [-n num_servers] [-h bindip]"
147 while ((ch = getopt(argc, argv, GETOPT)) != -1)
153 nfsdcnt = atoi(optarg);
154 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
155 warnx("nfsd count %d; reset to %d", nfsdcnt,
157 nfsdcnt = DEFNFSDCNT;
162 bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
163 if (bindhost == NULL)
164 errx(1, "Out of memory");
165 bindhost[bindhostc-1] = strdup(optarg);
166 if (bindhost[bindhostc-1] == NULL)
167 errx(1, "Out of memory");
185 if (!tcpflag && !udpflag)
192 * Backward compatibility, trailing number is the count of daemons.
197 nfsdcnt = atoi(argv[0]);
198 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
199 warnx("nfsd count %d; reset to %d", nfsdcnt,
201 nfsdcnt = DEFNFSDCNT;
206 s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
208 if (errno != EPROTONOSUPPORT)
211 } else if (getnetconfigent("udp6") == NULL ||
212 getnetconfigent("tcp6") == NULL) {
218 if (bindhostc == 0 || bindanyflag) {
220 bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
221 if (bindhost == NULL)
222 errx(1, "Out of memory");
223 bindhost[bindhostc-1] = strdup("*");
224 if (bindhost[bindhostc-1] == NULL)
225 errx(1, "Out of memory");
234 memset(&hints, 0, sizeof hints);
235 hints.ai_flags = AI_PASSIVE;
236 hints.ai_family = AF_INET;
237 hints.ai_socktype = SOCK_DGRAM;
238 hints.ai_protocol = IPPROTO_UDP;
239 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
241 err(1, "getaddrinfo udp: %s", gai_strerror(ecode));
242 nconf_udp = getnetconfigent("udp");
243 if (nconf_udp == NULL)
244 err(1, "getnetconfigent udp failed");
245 nb_udp.buf = ai_udp->ai_addr;
246 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
247 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
248 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
249 err(1, "rpcb_set udp failed");
250 freeaddrinfo(ai_udp);
252 if (udpflag && ip6flag) {
253 memset(&hints, 0, sizeof hints);
254 hints.ai_flags = AI_PASSIVE;
255 hints.ai_family = AF_INET6;
256 hints.ai_socktype = SOCK_DGRAM;
257 hints.ai_protocol = IPPROTO_UDP;
258 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
260 err(1, "getaddrinfo udp6: %s", gai_strerror(ecode));
261 nconf_udp6 = getnetconfigent("udp6");
262 if (nconf_udp6 == NULL)
263 err(1, "getnetconfigent udp6 failed");
264 nb_udp6.buf = ai_udp6->ai_addr;
265 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
266 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
267 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
268 err(1, "rpcb_set udp6 failed");
269 freeaddrinfo(ai_udp6);
272 memset(&hints, 0, sizeof hints);
273 hints.ai_flags = AI_PASSIVE;
274 hints.ai_family = AF_INET;
275 hints.ai_socktype = SOCK_STREAM;
276 hints.ai_protocol = IPPROTO_TCP;
277 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
279 err(1, "getaddrinfo tcp: %s", gai_strerror(ecode));
280 nconf_tcp = getnetconfigent("tcp");
281 if (nconf_tcp == NULL)
282 err(1, "getnetconfigent tcp failed");
283 nb_tcp.buf = ai_tcp->ai_addr;
284 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
285 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) ||
286 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)))
287 err(1, "rpcb_set tcp failed");
288 freeaddrinfo(ai_tcp);
290 if (tcpflag && ip6flag) {
291 memset(&hints, 0, sizeof hints);
292 hints.ai_flags = AI_PASSIVE;
293 hints.ai_family = AF_INET6;
294 hints.ai_socktype = SOCK_STREAM;
295 hints.ai_protocol = IPPROTO_TCP;
296 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
298 err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode));
299 nconf_tcp6 = getnetconfigent("tcp6");
300 if (nconf_tcp6 == NULL)
301 err(1, "getnetconfigent tcp6 failed");
302 nb_tcp6.buf = ai_tcp6->ai_addr;
303 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
304 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
305 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
306 err(1, "rpcb_set tcp6 failed");
307 freeaddrinfo(ai_tcp6);
313 (void)signal(SIGHUP, SIG_IGN);
314 (void)signal(SIGINT, SIG_IGN);
316 * nfsd sits in the kernel most of the time. It needs
317 * to ignore SIGTERM/SIGQUIT in order to stay alive as long
318 * as possible during a shutdown, otherwise loopback
319 * mounts will not be able to unmount.
321 (void)signal(SIGTERM, SIG_IGN);
322 (void)signal(SIGQUIT, SIG_IGN);
324 (void)signal(SIGSYS, nonfs);
325 (void)signal(SIGCHLD, reapchild);
327 openlog("nfsd", LOG_PID, LOG_DAEMON);
329 /* If we use UDP only, we start the last server below. */
330 srvcnt = tcpflag ? nfsdcnt : nfsdcnt - 1;
331 for (i = 0; i < srvcnt; i++) {
332 switch ((pid = fork())) {
334 syslog(LOG_ERR, "fork: %m");
342 (void)signal(SIGUSR1, child_cleanup);
343 setproctitle("server");
348 (void)signal(SIGUSR1, cleanup);
354 /* Set up the socket for udp and rpcb register it. */
357 for (i = 0; i < bindhostc; i++) {
358 memset(&hints, 0, sizeof hints);
359 hints.ai_flags = AI_PASSIVE;
360 hints.ai_family = AF_INET;
361 hints.ai_socktype = SOCK_DGRAM;
362 hints.ai_protocol = IPPROTO_UDP;
363 if (setbindhost(&ai_udp, bindhost[i], hints) == 0) {
366 if ((sock = socket(ai_udp->ai_family,
368 ai_udp->ai_protocol)) < 0) {
370 "can't create udp socket");
373 if (bind(sock, ai_udp->ai_addr,
374 ai_udp->ai_addrlen) < 0) {
376 "can't bind udp addr %s: %m",
380 freeaddrinfo(ai_udp);
381 nfsdargs.sock = sock;
382 nfsdargs.name = NULL;
383 nfsdargs.namelen = 0;
384 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
385 syslog(LOG_ERR, "can't Add UDP socket");
392 memset(&hints, 0, sizeof hints);
393 hints.ai_flags = AI_PASSIVE;
394 hints.ai_family = AF_INET;
395 hints.ai_socktype = SOCK_DGRAM;
396 hints.ai_protocol = IPPROTO_UDP;
397 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
399 syslog(LOG_ERR, "getaddrinfo udp: %s",
400 gai_strerror(ecode));
403 nconf_udp = getnetconfigent("udp");
404 if (nconf_udp == NULL)
405 err(1, "getnetconfigent udp failed");
406 nb_udp.buf = ai_udp->ai_addr;
407 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
408 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
409 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
410 err(1, "rpcb_set udp failed");
411 freeaddrinfo(ai_udp);
415 /* Set up the socket for udp6 and rpcb register it. */
416 if (udpflag && ip6flag) {
418 for (i = 0; i < bindhostc; i++) {
419 memset(&hints, 0, sizeof hints);
420 hints.ai_flags = AI_PASSIVE;
421 hints.ai_family = AF_INET6;
422 hints.ai_socktype = SOCK_DGRAM;
423 hints.ai_protocol = IPPROTO_UDP;
424 if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) {
427 if ((sock = socket(ai_udp6->ai_family,
428 ai_udp6->ai_socktype,
429 ai_udp6->ai_protocol)) < 0) {
431 "can't create udp6 socket");
434 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
435 &on, sizeof on) < 0) {
437 "can't set v6-only binding for "
441 if (bind(sock, ai_udp6->ai_addr,
442 ai_udp6->ai_addrlen) < 0) {
444 "can't bind udp6 addr %s: %m",
448 freeaddrinfo(ai_udp6);
449 nfsdargs.sock = sock;
450 nfsdargs.name = NULL;
451 nfsdargs.namelen = 0;
452 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
454 "can't add UDP6 socket");
461 memset(&hints, 0, sizeof hints);
462 hints.ai_flags = AI_PASSIVE;
463 hints.ai_family = AF_INET6;
464 hints.ai_socktype = SOCK_DGRAM;
465 hints.ai_protocol = IPPROTO_UDP;
466 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
468 syslog(LOG_ERR, "getaddrinfo udp6: %s",
469 gai_strerror(ecode));
472 nconf_udp6 = getnetconfigent("udp6");
473 if (nconf_udp6 == NULL)
474 err(1, "getnetconfigent udp6 failed");
475 nb_udp6.buf = ai_udp6->ai_addr;
476 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
477 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
478 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
479 err(1, "rpcb_set udp6 failed");
480 freeaddrinfo(ai_udp6);
484 /* Set up the socket for tcp and rpcb register it. */
487 for (i = 0; i < bindhostc; i++) {
488 memset(&hints, 0, sizeof hints);
489 hints.ai_flags = AI_PASSIVE;
490 hints.ai_family = AF_INET;
491 hints.ai_socktype = SOCK_STREAM;
492 hints.ai_protocol = IPPROTO_TCP;
493 if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) {
496 if ((tcpsock = socket(AF_INET, SOCK_STREAM,
499 "can't create tpc socket");
502 if (setsockopt(tcpsock, SOL_SOCKET,
504 (char *)&on, sizeof(on)) < 0)
506 "setsockopt SO_REUSEADDR: %m");
507 if (bind(tcpsock, ai_tcp->ai_addr,
508 ai_tcp->ai_addrlen) < 0) {
510 "can't bind tcp addr %s: %m",
514 if (listen(tcpsock, 5) < 0) {
515 syslog(LOG_ERR, "listen failed");
518 freeaddrinfo(ai_tcp);
519 FD_SET(tcpsock, &sockbits);
520 FD_SET(tcpsock, &v4bits);
526 memset(&hints, 0, sizeof hints);
527 hints.ai_flags = AI_PASSIVE;
528 hints.ai_family = AF_INET;
529 hints.ai_socktype = SOCK_STREAM;
530 hints.ai_protocol = IPPROTO_TCP;
531 ecode = getaddrinfo(NULL, "nfs", &hints,
534 syslog(LOG_ERR, "getaddrinfo tcp: %s",
535 gai_strerror(ecode));
538 nconf_tcp = getnetconfigent("tcp");
539 if (nconf_tcp == NULL)
540 err(1, "getnetconfigent tcp failed");
541 nb_tcp.buf = ai_tcp->ai_addr;
542 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
543 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp,
544 &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3,
545 nconf_tcp, &nb_tcp)))
546 err(1, "rpcb_set tcp failed");
547 freeaddrinfo(ai_tcp);
551 /* Set up the socket for tcp6 and rpcb register it. */
552 if (tcpflag && ip6flag) {
554 for (i = 0; i < bindhostc; i++) {
555 memset(&hints, 0, sizeof hints);
556 hints.ai_flags = AI_PASSIVE;
557 hints.ai_family = AF_INET6;
558 hints.ai_socktype = SOCK_STREAM;
559 hints.ai_protocol = IPPROTO_TCP;
560 if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) {
563 if ((tcp6sock = socket(ai_tcp6->ai_family,
564 ai_tcp6->ai_socktype,
565 ai_tcp6->ai_protocol)) < 0) {
567 "can't create tcp6 socket");
570 if (setsockopt(tcp6sock, SOL_SOCKET,
572 (char *)&on, sizeof(on)) < 0)
574 "setsockopt SO_REUSEADDR: %m");
575 if (setsockopt(tcp6sock, IPPROTO_IPV6,
576 IPV6_V6ONLY, &on, sizeof on) < 0) {
578 "can't set v6-only binding for tcp6 "
582 if (bind(tcp6sock, ai_tcp6->ai_addr,
583 ai_tcp6->ai_addrlen) < 0) {
585 "can't bind tcp6 addr %s: %m",
589 if (listen(tcp6sock, 5) < 0) {
590 syslog(LOG_ERR, "listen failed");
593 freeaddrinfo(ai_tcp6);
594 FD_SET(tcp6sock, &sockbits);
595 FD_SET(tcp6sock, &v6bits);
596 if (maxsock < tcp6sock)
602 memset(&hints, 0, sizeof hints);
603 hints.ai_flags = AI_PASSIVE;
604 hints.ai_family = AF_INET6;
605 hints.ai_socktype = SOCK_STREAM;
606 hints.ai_protocol = IPPROTO_TCP;
607 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
609 syslog(LOG_ERR, "getaddrinfo tcp6: %s",
610 gai_strerror(ecode));
613 nconf_tcp6 = getnetconfigent("tcp6");
614 if (nconf_tcp6 == NULL)
615 err(1, "getnetconfigent tcp6 failed");
616 nb_tcp6.buf = ai_tcp6->ai_addr;
617 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
618 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
619 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
620 err(1, "rpcb_set tcp6 failed");
621 freeaddrinfo(ai_tcp6);
625 if (rpcbregcnt == 0) {
626 syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m");
630 if (tcpflag && connect_type_cnt == 0) {
631 syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m");
635 setproctitle("master");
637 * We always want a master to have a clean way to to shut nfsd down
638 * (with unregistration): if the master is killed, it unregisters and
639 * kills all children. If we run for UDP only (and so do not have to
640 * loop waiting waiting for accept), we instead make the parent
641 * a "server" too. start_server will not return.
647 * Loop forever accepting connections and passing the sockets
648 * into the kernel for the mounts.
652 if (connect_type_cnt > 1) {
653 if (select(maxsock + 1,
654 &ready, NULL, NULL, NULL) < 1) {
655 syslog(LOG_ERR, "select failed: %m");
661 for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) {
662 if (FD_ISSET(tcpsock, &ready)) {
663 if (FD_ISSET(tcpsock, &v4bits)) {
664 len = sizeof(inetpeer);
665 if ((msgsock = accept(tcpsock,
666 (struct sockaddr *)&inetpeer, &len)) < 0) {
667 syslog(LOG_ERR, "accept failed: %m");
668 if (errno == ECONNABORTED ||
673 memset(inetpeer.sin_zero, 0,
674 sizeof(inetpeer.sin_zero));
675 if (setsockopt(msgsock, SOL_SOCKET,
676 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
678 "setsockopt SO_KEEPALIVE: %m");
679 nfsdargs.sock = msgsock;
680 nfsdargs.name = (caddr_t)&inetpeer;
681 nfsdargs.namelen = len;
682 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
683 (void)close(msgsock);
684 } else if (FD_ISSET(tcpsock, &v6bits)) {
685 len = sizeof(inet6peer);
686 if ((msgsock = accept(tcpsock,
687 (struct sockaddr *)&inet6peer,
690 "accept failed: %m");
691 if (errno == ECONNABORTED ||
696 if (setsockopt(msgsock, SOL_SOCKET,
697 SO_KEEPALIVE, (char *)&on,
699 syslog(LOG_ERR, "setsockopt "
701 nfsdargs.sock = msgsock;
702 nfsdargs.name = (caddr_t)&inet6peer;
703 nfsdargs.namelen = len;
704 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
705 (void)close(msgsock);
713 setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints)
716 u_int32_t host_addr[4]; /* IPv4 or IPv6 */
719 if (bindhost == NULL || strcmp("*", bindhost) == 0)
724 if (hostptr != NULL) {
725 switch (hints.ai_family) {
727 if (inet_pton(AF_INET, hostptr, host_addr) == 1) {
728 hints.ai_flags = AI_NUMERICHOST;
730 if (inet_pton(AF_INET6, hostptr,
736 if (inet_pton(AF_INET6, hostptr, host_addr) == 1) {
737 hints.ai_flags = AI_NUMERICHOST;
739 if (inet_pton(AF_INET, hostptr,
749 ecode = getaddrinfo(hostptr, "nfs", &hints, ai);
751 syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost,
752 gai_strerror(ecode));
761 (void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
766 nonfs(__unused int signo)
768 syslog(LOG_ERR, "missing system call: NFS not available");
772 reapchild(__unused int signo)
777 while ((pid = wait3(NULL, WNOHANG, NULL)) > 0) {
778 for (i = 0; i < nfsdcnt; i++)
779 if (pid == children[i])
787 if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) ||
788 (!rpcb_unset(RPCPROG_NFS, 3, NULL)))
789 syslog(LOG_ERR, "rpcb_unset failed");
797 for (i = 0; i < nfsdcnt; i++) {
799 kill(children[i], SIGKILL);
804 * Cleanup master after SIGUSR1.
807 cleanup(__unused int signo)
813 * Cleanup child after SIGUSR1.
816 child_cleanup(__unused int signo)
822 nfsd_exit(int status)
830 start_server(int master)
835 if (nfssvc(NFSSVC_NFSD, NULL) < 0) {
836 syslog(LOG_ERR, "nfssvc: %m");