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 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 static const char copyright[] =
39 "@(#) Copyright (c) 1989, 1993, 1994\n\
40 The Regents of the University of California. All rights reserved.\n";
45 static char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95";
47 static const char rcsid[] =
51 #include <sys/param.h>
52 #include <sys/syslog.h>
54 #include <sys/mount.h>
55 #include <sys/linker.h>
56 #include <sys/module.h>
59 #include <rpc/pmap_clnt.h>
62 #include <arpa/inet.h>
63 #include <nfs/rpcv2.h>
64 #include <nfs/nfsproto.h>
65 #include <nfsserver/nfs.h>
78 #define syslog(e, s...) fprintf(stderr,s)
84 struct nfsd_srvargs nsd;
88 pid_t children[MAXNFSDCNT]; /* PIDs of children */
89 int nfsdcnt; /* number of children */
92 void child_cleanup(int);
93 void killchildren(void);
97 int setbindhost(struct addrinfo **ia, const char *bindhost,
98 struct addrinfo hints);
99 void start_server(int);
100 void unregistration(void);
104 * Nfs server daemon mostly just a user context for nfssvc()
106 * 1 - do file descriptor and signal cleanup
107 * 2 - fork the nfsd(s)
108 * 3 - create server socket(s)
109 * 4 - register socket with rpcbind
111 * For connectionless protocols, just pass the socket into the kernel via.
113 * For connection based sockets, loop doing accepts. When you get a new
114 * socket from accept, pass the msgsock into the kernel via. nfssvc().
116 * -r - reregister with rpcbind
117 * -d - unregister with rpcbind
118 * -t - support tcp nfs clients
119 * -u - support udp nfs clients
120 * followed by "n" which is the number of nfsds' to fork off
123 main(argc, argv, envp)
125 char *argv[], *envp[];
127 struct nfsd_args nfsdargs;
128 struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
129 struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
130 struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
131 struct sockaddr_in inetpeer;
132 struct sockaddr_in6 inet6peer;
133 fd_set ready, sockbits;
134 fd_set v4bits, v6bits;
135 int ch, connect_type_cnt, i, len, maxsock, msgsock;
136 int on = 1, unregister, reregister, sock;
137 int tcp6sock, ip6flag, tcpflag, tcpsock;
138 int udpflag, ecode, s, srvcnt;
139 int bindhostc, bindanyflag, rpcbreg, rpcbregcnt;
140 char **bindhost = NULL;
143 if (modfind("nfsserver") < 0) {
144 /* Not present in kernel, try loading it */
145 if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0)
146 errx(1, "NFS server is not available");
149 nfsdcnt = DEFNFSDCNT;
150 unregister = reregister = tcpflag = maxsock = 0;
151 bindanyflag = udpflag = connect_type_cnt = bindhostc = 0;
152 #define GETOPT "ah:n:rdtu"
153 #define USAGE "[-ardtu] [-n num_servers] [-h bindip]"
154 while ((ch = getopt(argc, argv, GETOPT)) != -1)
160 nfsdcnt = atoi(optarg);
161 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
162 warnx("nfsd count %d; reset to %d", nfsdcnt,
164 nfsdcnt = DEFNFSDCNT;
169 bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
170 if (bindhost == NULL)
171 errx(1, "Out of memory");
172 bindhost[bindhostc-1] = strdup(optarg);
173 if (bindhost[bindhostc-1] == NULL)
174 errx(1, "Out of memory");
192 if (!tcpflag && !udpflag)
199 * Backward compatibility, trailing number is the count of daemons.
204 nfsdcnt = atoi(argv[0]);
205 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
206 warnx("nfsd count %d; reset to %d", nfsdcnt,
208 nfsdcnt = DEFNFSDCNT;
213 s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
215 if (errno != EPROTONOSUPPORT)
218 } else if (getnetconfigent("udp6") == NULL ||
219 getnetconfigent("tcp6") == NULL) {
225 if (bindhostc == 0 || bindanyflag) {
227 bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
228 if (bindhost == NULL)
229 errx(1, "Out of memory");
230 bindhost[bindhostc-1] = strdup("*");
231 if (bindhost[bindhostc-1] == NULL)
232 errx(1, "Out of memory");
241 memset(&hints, 0, sizeof hints);
242 hints.ai_flags = AI_PASSIVE;
243 hints.ai_family = AF_INET;
244 hints.ai_socktype = SOCK_DGRAM;
245 hints.ai_protocol = IPPROTO_UDP;
246 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
248 err(1, "getaddrinfo udp: %s", gai_strerror(ecode));
249 nconf_udp = getnetconfigent("udp");
250 if (nconf_udp == NULL)
251 err(1, "getnetconfigent udp failed");
252 nb_udp.buf = ai_udp->ai_addr;
253 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
254 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
255 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
256 err(1, "rpcb_set udp failed");
257 freeaddrinfo(ai_udp);
259 if (udpflag && ip6flag) {
260 memset(&hints, 0, sizeof hints);
261 hints.ai_flags = AI_PASSIVE;
262 hints.ai_family = AF_INET6;
263 hints.ai_socktype = SOCK_DGRAM;
264 hints.ai_protocol = IPPROTO_UDP;
265 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
267 err(1, "getaddrinfo udp6: %s", gai_strerror(ecode));
268 nconf_udp6 = getnetconfigent("udp6");
269 if (nconf_udp6 == NULL)
270 err(1, "getnetconfigent udp6 failed");
271 nb_udp6.buf = ai_udp6->ai_addr;
272 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
273 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
274 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
275 err(1, "rpcb_set udp6 failed");
276 freeaddrinfo(ai_udp6);
279 memset(&hints, 0, sizeof hints);
280 hints.ai_flags = AI_PASSIVE;
281 hints.ai_family = AF_INET;
282 hints.ai_socktype = SOCK_STREAM;
283 hints.ai_protocol = IPPROTO_TCP;
284 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
286 err(1, "getaddrinfo tcp: %s", gai_strerror(ecode));
287 nconf_tcp = getnetconfigent("tcp");
288 if (nconf_tcp == NULL)
289 err(1, "getnetconfigent tcp failed");
290 nb_tcp.buf = ai_tcp->ai_addr;
291 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
292 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) ||
293 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)))
294 err(1, "rpcb_set tcp failed");
295 freeaddrinfo(ai_tcp);
297 if (tcpflag && ip6flag) {
298 memset(&hints, 0, sizeof hints);
299 hints.ai_flags = AI_PASSIVE;
300 hints.ai_family = AF_INET6;
301 hints.ai_socktype = SOCK_STREAM;
302 hints.ai_protocol = IPPROTO_TCP;
303 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
305 err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode));
306 nconf_tcp6 = getnetconfigent("tcp6");
307 if (nconf_tcp6 == NULL)
308 err(1, "getnetconfigent tcp6 failed");
309 nb_tcp6.buf = ai_tcp6->ai_addr;
310 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
311 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
312 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
313 err(1, "rpcb_set tcp6 failed");
314 freeaddrinfo(ai_tcp6);
320 (void)signal(SIGHUP, SIG_IGN);
321 (void)signal(SIGINT, SIG_IGN);
323 * nfsd sits in the kernel most of the time. It needs
324 * to ignore SIGTERM/SIGQUIT in order to stay alive as long
325 * as possible during a shutdown, otherwise loopback
326 * mounts will not be able to unmount.
328 (void)signal(SIGTERM, SIG_IGN);
329 (void)signal(SIGQUIT, SIG_IGN);
331 (void)signal(SIGSYS, nonfs);
332 (void)signal(SIGCHLD, reapchild);
334 openlog("nfsd", LOG_PID, LOG_DAEMON);
336 /* If we use UDP only, we start the last server below. */
337 srvcnt = tcpflag ? nfsdcnt : nfsdcnt - 1;
338 for (i = 0; i < srvcnt; i++) {
339 switch ((pid = fork())) {
341 syslog(LOG_ERR, "fork: %m");
349 (void)signal(SIGUSR1, child_cleanup);
350 setproctitle("server");
355 (void)signal(SIGUSR1, cleanup);
360 /* Set up the socket for udp and rpcb register it. */
363 for (i = 0; i < bindhostc; i++) {
364 memset(&hints, 0, sizeof hints);
365 hints.ai_flags = AI_PASSIVE;
366 hints.ai_family = AF_INET;
367 hints.ai_socktype = SOCK_DGRAM;
368 hints.ai_protocol = IPPROTO_UDP;
369 if (setbindhost(&ai_udp, bindhost[i], hints) == 0) {
372 if ((sock = socket(ai_udp->ai_family,
374 ai_udp->ai_protocol)) < 0) {
376 "can't create udp socket");
379 if (bind(sock, ai_udp->ai_addr,
380 ai_udp->ai_addrlen) < 0) {
382 "can't bind udp addr %s: %m",
386 freeaddrinfo(ai_udp);
387 nfsdargs.sock = sock;
388 nfsdargs.name = NULL;
389 nfsdargs.namelen = 0;
390 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
391 syslog(LOG_ERR, "can't Add UDP socket");
398 memset(&hints, 0, sizeof hints);
399 hints.ai_flags = AI_PASSIVE;
400 hints.ai_family = AF_INET;
401 hints.ai_socktype = SOCK_DGRAM;
402 hints.ai_protocol = IPPROTO_UDP;
403 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
405 syslog(LOG_ERR, "getaddrinfo udp: %s",
406 gai_strerror(ecode));
409 nconf_udp = getnetconfigent("udp");
410 if (nconf_udp == NULL)
411 err(1, "getnetconfigent udp failed");
412 nb_udp.buf = ai_udp->ai_addr;
413 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
414 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
415 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
416 err(1, "rpcb_set udp failed");
417 freeaddrinfo(ai_udp);
421 /* Set up the socket for udp6 and rpcb register it. */
422 if (udpflag && ip6flag) {
424 for (i = 0; i < bindhostc; i++) {
425 memset(&hints, 0, sizeof hints);
426 hints.ai_flags = AI_PASSIVE;
427 hints.ai_family = AF_INET6;
428 hints.ai_socktype = SOCK_DGRAM;
429 hints.ai_protocol = IPPROTO_UDP;
430 if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) {
433 if ((sock = socket(ai_udp6->ai_family,
434 ai_udp6->ai_socktype,
435 ai_udp6->ai_protocol)) < 0) {
437 "can't create udp6 socket");
440 if (setsockopt(sock, IPPROTO_IPV6,
442 &on, sizeof on) < 0) {
444 "can't set v6-only binding for "
448 if (bind(sock, ai_udp6->ai_addr,
449 ai_udp6->ai_addrlen) < 0) {
451 "can't bind udp6 addr %s: %m",
455 freeaddrinfo(ai_udp6);
456 nfsdargs.sock = sock;
457 nfsdargs.name = NULL;
458 nfsdargs.namelen = 0;
459 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
461 "can't add UDP6 socket");
468 memset(&hints, 0, sizeof hints);
469 hints.ai_flags = AI_PASSIVE;
470 hints.ai_family = AF_INET6;
471 hints.ai_socktype = SOCK_DGRAM;
472 hints.ai_protocol = IPPROTO_UDP;
473 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
475 syslog(LOG_ERR, "getaddrinfo udp6: %s",
476 gai_strerror(ecode));
479 nconf_udp6 = getnetconfigent("udp6");
480 if (nconf_udp6 == NULL)
481 err(1, "getnetconfigent udp6 failed");
482 nb_udp6.buf = ai_udp6->ai_addr;
483 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
484 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
485 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
486 err(1, "rpcb_set udp6 failed");
487 freeaddrinfo(ai_udp6);
491 /* Set up the socket for tcp and rpcb register it. */
494 for (i = 0; i < bindhostc; i++) {
495 memset(&hints, 0, sizeof hints);
496 hints.ai_flags = AI_PASSIVE;
497 hints.ai_family = AF_INET;
498 hints.ai_socktype = SOCK_STREAM;
499 hints.ai_protocol = IPPROTO_TCP;
500 if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) {
503 if ((tcpsock = socket(AF_INET, SOCK_STREAM,
506 "can't create tpc socket");
509 if (setsockopt(tcpsock, SOL_SOCKET,
511 (char *)&on, sizeof(on)) < 0)
513 "setsockopt SO_REUSEADDR: %m");
514 if (bind(tcpsock, ai_tcp->ai_addr,
515 ai_tcp->ai_addrlen) < 0) {
517 "can't bind tcp addr %s: %m",
521 if (listen(tcpsock, 5) < 0) {
522 syslog(LOG_ERR, "listen failed");
525 freeaddrinfo(ai_tcp);
526 FD_SET(tcpsock, &sockbits);
527 FD_SET(tcpsock, &v4bits);
533 memset(&hints, 0, sizeof hints);
534 hints.ai_flags = AI_PASSIVE;
535 hints.ai_family = AF_INET;
536 hints.ai_socktype = SOCK_STREAM;
537 hints.ai_protocol = IPPROTO_TCP;
538 ecode = getaddrinfo(NULL, "nfs", &hints,
541 syslog(LOG_ERR, "getaddrinfo tcp: %s",
542 gai_strerror(ecode));
545 nconf_tcp = getnetconfigent("tcp");
546 if (nconf_tcp == NULL)
547 err(1, "getnetconfigent tcp failed");
548 nb_tcp.buf = ai_tcp->ai_addr;
549 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
550 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp,
551 &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3,
552 nconf_tcp, &nb_tcp)))
553 err(1, "rpcb_set tcp failed");
554 freeaddrinfo(ai_tcp);
558 /* Set up the socket for tcp6 and rpcb register it. */
559 if (tcpflag && ip6flag) {
561 for (i = 0; i < bindhostc; i++) {
562 memset(&hints, 0, sizeof hints);
563 hints.ai_flags = AI_PASSIVE;
564 hints.ai_family = AF_INET6;
565 hints.ai_socktype = SOCK_STREAM;
566 hints.ai_protocol = IPPROTO_TCP;
567 if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) {
570 if ((tcp6sock = socket(ai_tcp6->ai_family,
571 ai_tcp6->ai_socktype,
572 ai_tcp6->ai_protocol)) < 0) {
574 "can't create tcp6 socket");
577 if (setsockopt(tcp6sock, SOL_SOCKET,
579 (char *)&on, sizeof(on)) < 0)
581 "setsockopt SO_REUSEADDR: %m");
582 if (setsockopt(tcp6sock, IPPROTO_IPV6,
583 IPV6_BINDV6ONLY, &on, sizeof on) < 0) {
585 "can't set v6-only binding for tcp6 "
589 if (bind(tcp6sock, ai_tcp6->ai_addr,
590 ai_tcp6->ai_addrlen) < 0) {
592 "can't bind tcp6 addr %s: %m",
596 if (listen(tcp6sock, 5) < 0) {
597 syslog(LOG_ERR, "listen failed");
600 freeaddrinfo(ai_tcp6);
601 FD_SET(tcp6sock, &sockbits);
602 FD_SET(tcp6sock, &v6bits);
603 if (maxsock < tcp6sock)
609 memset(&hints, 0, sizeof hints);
610 hints.ai_flags = AI_PASSIVE;
611 hints.ai_family = AF_INET6;
612 hints.ai_socktype = SOCK_STREAM;
613 hints.ai_protocol = IPPROTO_TCP;
614 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
616 syslog(LOG_ERR, "getaddrinfo tcp6: %s",
617 gai_strerror(ecode));
620 nconf_tcp6 = getnetconfigent("tcp6");
621 if (nconf_tcp6 == NULL)
622 err(1, "getnetconfigent tcp6 failed");
623 nb_tcp6.buf = ai_tcp6->ai_addr;
624 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
625 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
626 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
627 err(1, "rpcb_set tcp6 failed");
628 freeaddrinfo(ai_tcp6);
632 if (rpcbregcnt == 0) {
633 syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m");
637 if (tcpflag && connect_type_cnt == 0) {
638 syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m");
642 setproctitle("master");
644 * We always want a master to have a clean way to to shut nfsd down
645 * (with unregistration): if the master is killed, it unregisters and
646 * kills all children. If we run for UDP only (and so do not have to
647 * loop waiting waiting for accept), we instead make the parent
648 * a "server" too. start_server will not return.
654 * Loop forever accepting connections and passing the sockets
655 * into the kernel for the mounts.
659 if (connect_type_cnt > 1) {
660 if (select(maxsock + 1,
661 &ready, NULL, NULL, NULL) < 1) {
662 syslog(LOG_ERR, "select failed: %m");
666 for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) {
667 if (FD_ISSET(tcpsock, &ready)) {
668 if (FD_ISSET(tcpsock, &v4bits)) {
669 len = sizeof(inetpeer);
670 if ((msgsock = accept(tcpsock,
671 (struct sockaddr *)&inetpeer, &len)) < 0) {
672 syslog(LOG_ERR, "accept failed: %m");
675 memset(inetpeer.sin_zero, 0,
676 sizeof(inetpeer.sin_zero));
677 if (setsockopt(msgsock, SOL_SOCKET,
678 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
680 "setsockopt SO_KEEPALIVE: %m");
681 nfsdargs.sock = msgsock;
682 nfsdargs.name = (caddr_t)&inetpeer;
683 nfsdargs.namelen = len;
684 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
685 (void)close(msgsock);
686 } else if (FD_ISSET(tcpsock, &v6bits)) {
687 len = sizeof(inet6peer);
688 if ((msgsock = accept(tcpsock,
689 (struct sockaddr *)&inet6peer,
692 "accept failed: %m");
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);
704 (void)close(msgsock);
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 (void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
768 syslog(LOG_ERR, "missing system call: NFS not available");
778 while ((pid = wait3(NULL, WNOHANG, NULL)) > 0) {
779 for (i = 0; i < nfsdcnt; i++)
780 if (pid == children[i])
788 if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) ||
789 (!rpcb_unset(RPCPROG_NFS, 3, NULL)))
790 syslog(LOG_ERR, "rpcb_unset failed");
798 for (i = 0; i < nfsdcnt; i++) {
800 kill(children[i], SIGKILL);
805 * Cleanup master after SIGUSR1.
814 * Cleanup child after SIGUSR1.
823 nfsd_exit(int status)
831 start_server(int master)
837 if (nfssvc(NFSSVC_NFSD, &nsd) < 0) {
838 syslog(LOG_ERR, "nfssvc: %m");