]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/netbsd-tests/fs/nfs/nfsservice/nfsd.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / netbsd-tests / fs / nfs / nfsservice / nfsd.c
1 /*      $NetBSD: nfsd.c,v 1.4 2013/10/19 17:45:00 christos 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\
38  The Regents of the University of California.  All rights reserved.");
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.4 2013/10/19 17:45:00 christos 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 #include <nfs/rpcv2.h>
65 #include <nfs/nfsproto.h>
66 #include <nfs/nfs.h>
67
68 #include <err.h>
69 #include <errno.h>
70 #include <fcntl.h>
71 #include <grp.h>
72 #include <pwd.h>
73 #include <pthread.h>
74 #include <signal.h>
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <string.h>
78 #include <syslog.h>
79 #include <unistd.h>
80 #include <netdb.h>
81
82 #include <rump/rump.h>
83 #include <rump/rump_syscalls.h>
84
85 /* Global defs */
86 #ifdef DEBUG
87 #define syslog(e, s, args...)                                           \
88 do {                                                                    \
89     fprintf(stderr,(s), ## args);                                       \
90     fprintf(stderr, "\n");                                              \
91 } while (/*CONSTCOND*/0)
92 int     debug = 1;
93 #else
94 int     debug = 0;
95 #endif
96
97 int     main __P((int, char **));
98 void    nonfs __P((int));
99 void    usage __P((void));
100
101 static void *
102 child(void *arg)
103 {
104         struct  nfsd_srvargs nsd;
105         int nfssvc_flag;
106
107         nfssvc_flag = NFSSVC_NFSD;
108         memset(&nsd, 0, sizeof(nsd));
109         while (rump_sys_nfssvc(nfssvc_flag, &nsd) < 0) {
110                 if (errno != ENEEDAUTH) {
111                         syslog(LOG_ERR, "nfssvc: %m %d", errno);
112                         exit(1);
113                 }
114                 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
115         }
116
117         return NULL;
118 }
119
120 /*
121  * Nfs server daemon mostly just a user context for nfssvc()
122  *
123  * 1 - do file descriptor and signal cleanup
124  * 2 - create the nfsd thread(s)
125  * 3 - create server socket(s)
126  * 4 - register socket with portmap
127  *
128  * For connectionless protocols, just pass the socket into the kernel via
129  * nfssvc().
130  * For connection based sockets, loop doing accepts. When you get a new
131  * socket from accept, pass the msgsock into the kernel via nfssvc().
132  * The arguments are:
133  *      -c - support iso cltp clients
134  *      -r - reregister with portmapper
135  *      -t - support tcp nfs clients
136  *      -u - support udp nfs clients
137  * followed by "n" which is the number of nfsd threads to create
138  */
139 int nfsd_main(int, char**);
140 int
141 nfsd_main(argc, argv)
142         int argc;
143         char *argv[];
144 {
145         struct nfsd_args nfsdargs;
146         struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
147         struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
148         struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
149         struct sockaddr_in inetpeer;
150         struct pollfd set[4];
151         socklen_t len;
152         int ch, connect_type_cnt, i, msgsock;
153         int nfsdcnt, on = 1, reregister, sock, tcpflag, tcpsock;
154         int tcp6sock, ip6flag;
155         int tp4cnt, tp4flag, tpipcnt, udpflag, ecode, s;
156         int error = 0;
157
158 #define DEFNFSDCNT       4
159         nfsdcnt = DEFNFSDCNT;
160         reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
161         udpflag = ip6flag = 0;
162         nconf_udp = nconf_tcp = nconf_udp6 = nconf_tcp6 = NULL;
163         tcpsock = tcp6sock = -1;
164 #define GETOPT  "6n:rtu"
165 #define USAGE   "[-rtu] [-n num_servers]"
166         while ((ch = getopt(argc, argv, GETOPT)) != -1) {
167                 switch (ch) {
168                 case '6':
169                         ip6flag = 1;
170                         s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
171                         if (s < 0 && (errno == EPROTONOSUPPORT ||
172                             errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
173                                 ip6flag = 0;
174                         else
175                                 close(s);
176                         break;
177                 case 'n':
178                         nfsdcnt = atoi(optarg);
179                         if (nfsdcnt < 1) {
180                                 warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
181                                 nfsdcnt = DEFNFSDCNT;
182                         }
183                         break;
184                 case 'r':
185                         reregister = 1;
186                         break;
187                 case 't':
188                         tcpflag = 1;
189                         break;
190                 case 'u':
191                         udpflag = 1;
192                         break;
193                 default:
194                 case '?':
195                         usage();
196                 };
197         }
198         argv += optind;
199         argc -= optind;
200
201         /*
202          * XXX
203          * Backward compatibility, trailing number is the count of daemons.
204          */
205         if (argc > 1)
206                 usage();
207         if (argc == 1) {
208                 nfsdcnt = atoi(argv[0]);
209                 if (nfsdcnt < 1) {
210                         warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
211                         nfsdcnt = DEFNFSDCNT;
212                 }
213         }
214
215         /*
216          * If none of TCP or UDP are specified, default to UDP only.
217          */
218         if (tcpflag == 0 && udpflag == 0)
219                 udpflag = 1;
220
221         if (debug == 0) {
222                 fprintf(stderr, "non-debug not supported here\n");
223                 exit(1);
224
225 #ifdef not_the_debug_man
226                 daemon(0, 0);
227                 (void)signal(SIGHUP, SIG_IGN);
228                 (void)signal(SIGINT, SIG_IGN);
229                 (void)signal(SIGQUIT, SIG_IGN);
230                 (void)signal(SIGSYS, nonfs);
231 #endif
232         }
233
234         if (udpflag) {
235                 memset(&hints, 0, sizeof hints);
236                 hints.ai_flags = AI_PASSIVE;
237                 hints.ai_family = PF_INET;
238                 hints.ai_socktype = SOCK_DGRAM;
239                 hints.ai_protocol = IPPROTO_UDP;
240
241                 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
242                 if (ecode != 0) {
243                         syslog(LOG_ERR, "getaddrinfo udp: %s",
244                             gai_strerror(ecode));
245                         exit(1);
246                 }
247
248                 nconf_udp = getnetconfigent("udp");
249
250                 if (nconf_udp == NULL)
251                         err(1, "getnetconfigent udp failed");
252
253                 nb_udp.buf = ai_udp->ai_addr;
254                 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
255                 if (reregister)
256                         if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp))
257                                 err(1, "rpcb_set udp failed");
258         }
259
260         if (tcpflag) {
261                 memset(&hints, 0, sizeof hints);
262                 hints.ai_flags = AI_PASSIVE;
263                 hints.ai_family = PF_INET;
264                 hints.ai_socktype = SOCK_STREAM;
265                 hints.ai_protocol = IPPROTO_TCP;
266
267                 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
268                 if (ecode != 0) {
269                         syslog(LOG_ERR, "getaddrinfo tcp: %s",
270                             gai_strerror(ecode));
271                         exit(1);
272                 }
273
274                 nconf_tcp = getnetconfigent("tcp");
275
276                 if (nconf_tcp == NULL)
277                         err(1, "getnetconfigent tcp failed");
278
279                 nb_tcp.buf = ai_tcp->ai_addr;
280                 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
281                 if (reregister)
282                         if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp))
283                                 err(1, "rpcb_set tcp failed");
284         }
285
286         if (udpflag && ip6flag) {
287                 memset(&hints, 0, sizeof hints);
288                 hints.ai_flags = AI_PASSIVE;
289                 hints.ai_family = PF_INET6;
290                 hints.ai_socktype = SOCK_DGRAM;
291                 hints.ai_protocol = IPPROTO_UDP;
292
293                 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
294                 if (ecode != 0) {
295                         syslog(LOG_ERR, "getaddrinfo udp: %s",
296                             gai_strerror(ecode));
297                         exit(1);
298                 }
299
300                 nconf_udp6 = getnetconfigent("udp6");
301
302                 if (nconf_udp6 == NULL)
303                         err(1, "getnetconfigent udp6 failed");
304
305                 nb_udp6.buf = ai_udp6->ai_addr;
306                 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
307                 if (reregister)
308                         if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6))
309                                 err(1, "rpcb_set udp6 failed");
310         }
311
312         if (tcpflag && ip6flag) {
313                 memset(&hints, 0, sizeof hints);
314                 hints.ai_flags = AI_PASSIVE;
315                 hints.ai_family = PF_INET6;
316                 hints.ai_socktype = SOCK_STREAM;
317                 hints.ai_protocol = IPPROTO_TCP;
318
319                 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
320                 if (ecode != 0) {
321                         syslog(LOG_ERR, "getaddrinfo tcp: %s",
322                             gai_strerror(ecode));
323                         exit(1);
324                 }
325
326                 nconf_tcp6 = getnetconfigent("tcp6");
327
328                 if (nconf_tcp6 == NULL)
329                         err(1, "getnetconfigent tcp6 failed");
330
331                 nb_tcp6.buf = ai_tcp6->ai_addr;
332                 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
333                 if (reregister)
334                         if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6))
335                                 err(1, "rpcb_set tcp6 failed");
336         }
337
338         openlog("nfsd", LOG_PID, LOG_DAEMON);
339
340         for (i = 0; i < nfsdcnt; i++) {
341                 pthread_t t;
342                 pthread_create(&t, NULL, child, NULL);
343         }
344
345         /* If we are serving udp, set up the socket. */
346         if (udpflag) {
347                 if ((sock = rump_sys_socket(ai_udp->ai_family, ai_udp->ai_socktype,
348                     ai_udp->ai_protocol)) < 0) {
349                         syslog(LOG_ERR, "can't create udp socket");
350                         exit(1);
351                 }
352                 if (bind(sock, ai_udp->ai_addr, ai_udp->ai_addrlen) < 0) {
353                         syslog(LOG_ERR, "can't bind udp addr");
354                         exit(1);
355                 }
356                 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp) ||
357                     !rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)) {
358                         syslog(LOG_ERR, "can't register with udp portmap");
359                         exit(1);
360                 }
361                 nfsdargs.sock = sock;
362                 nfsdargs.name = NULL;
363                 nfsdargs.namelen = 0;
364                 if (rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
365                         syslog(LOG_ERR, "can't add UDP socket");
366                         exit(1);
367                 }
368                 (void)rump_sys_close(sock);
369         }
370
371         if (udpflag &&ip6flag) {
372                 if ((sock = rump_sys_socket(ai_udp6->ai_family, ai_udp6->ai_socktype,
373                     ai_udp6->ai_protocol)) < 0) {
374                         syslog(LOG_ERR, "can't create udp socket");
375                         exit(1);
376                 }
377                 if (rump_sys_setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
378                     &on, sizeof on) < 0) {
379                         syslog(LOG_ERR, "can't set v6-only binding for udp6 "
380                                         "socket: %m");
381                         exit(1);
382                 }
383                 if (rump_sys_bind(sock, ai_udp6->ai_addr, ai_udp6->ai_addrlen) < 0) {
384                         syslog(LOG_ERR, "can't bind udp addr");
385                         exit(1);
386                 }
387                 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6) ||
388                     !rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)) {
389                         syslog(LOG_ERR, "can't register with udp portmap");
390                         exit(1);
391                 }
392                 nfsdargs.sock = sock;
393                 nfsdargs.name = NULL;
394                 nfsdargs.namelen = 0;
395                 if (rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
396                         syslog(LOG_ERR, "can't add UDP6 socket");
397                         exit(1);
398                 }
399                 (void)rump_sys_close(sock);
400         }
401
402         /* Now set up the master server socket waiting for tcp connections. */
403         on = 1;
404         connect_type_cnt = 0;
405         if (tcpflag) {
406                 if ((tcpsock = rump_sys_socket(ai_tcp->ai_family, ai_tcp->ai_socktype,
407                     ai_tcp->ai_protocol)) < 0) {
408                         syslog(LOG_ERR, "can't create tcp socket");
409                         exit(1);
410                 }
411                 if (setsockopt(tcpsock,
412                     SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
413                         syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
414                 if (bind(tcpsock, ai_tcp->ai_addr, ai_tcp->ai_addrlen) < 0) {
415                         syslog(LOG_ERR, "can't bind tcp addr");
416                         exit(1);
417                 }
418                 if (rump_sys_listen(tcpsock, 5) < 0) {
419                         syslog(LOG_ERR, "listen failed");
420                         exit(1);
421                 }
422                 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp) ||
423                     !rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)) {
424                         syslog(LOG_ERR, "can't register tcp with rpcbind");
425                         exit(1);
426                 }
427                 set[0].fd = tcpsock;
428                 set[0].events = POLLIN;
429                 connect_type_cnt++;
430         } else
431                 set[0].fd = -1;
432
433         if (tcpflag && ip6flag) {
434                 if ((tcp6sock = socket(ai_tcp6->ai_family, ai_tcp6->ai_socktype,
435                     ai_tcp6->ai_protocol)) < 0) {
436                         syslog(LOG_ERR, "can't create tcp socket");
437                         exit(1);
438                 }
439                 if (setsockopt(tcp6sock,
440                     SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
441                         syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
442                 if (setsockopt(tcp6sock, IPPROTO_IPV6, IPV6_V6ONLY,
443                     &on, sizeof on) < 0) {
444                         syslog(LOG_ERR, "can't set v6-only binding for tcp6 "
445                                         "socket: %m");
446                         exit(1);
447                 }
448                 if (bind(tcp6sock, ai_tcp6->ai_addr, ai_tcp6->ai_addrlen) < 0) {
449                         syslog(LOG_ERR, "can't bind tcp6 addr");
450                         exit(1);
451                 }
452                 if (listen(tcp6sock, 5) < 0) {
453                         syslog(LOG_ERR, "listen failed");
454                         exit(1);
455                 }
456                 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6) ||
457                     !rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)) {
458                         syslog(LOG_ERR, "can't register tcp6 with rpcbind");
459                         exit(1);
460                 }
461                 set[1].fd = tcp6sock;
462                 set[1].events = POLLIN;
463                 connect_type_cnt++;
464         } else
465                 set[1].fd = -1;
466
467         set[2].fd = -1;
468         set[3].fd = -1;
469
470         if (connect_type_cnt == 0) {
471                 pause();
472                 exit(0);
473         }
474
475         /*
476          * Loop forever accepting connections and passing the sockets
477          * into the kernel for the mounts.
478          */
479         for (;;) {
480                 if (rump_sys_poll(set, 4, INFTIM) < 1) {
481                         syslog(LOG_ERR, "poll failed: %m");
482                         exit(1);
483                 }
484
485                         len = sizeof(inetpeer);
486                         if ((msgsock = accept(tcpsock,
487                             (struct sockaddr *)&inetpeer, &len)) < 0) {
488                                 syslog(LOG_ERR, "accept failed: %d", error);
489                                 exit(1);
490                         }
491                         memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
492                         if (setsockopt(msgsock, SOL_SOCKET,
493                             SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
494                                 syslog(LOG_ERR,
495                                     "setsockopt SO_KEEPALIVE: %m");
496                         nfsdargs.sock = msgsock;
497                         nfsdargs.name = (caddr_t)&inetpeer;
498                         nfsdargs.namelen = sizeof(inetpeer);
499                         rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
500                         (void)rump_sys_close(msgsock);
501
502 #ifdef notyet
503                 if (set[1].revents & POLLIN) {
504                         len = sizeof(inet6peer);
505                         if ((msgsock = rump_sys_accept(tcp6sock,
506                             (struct sockaddr *)&inet6peer, &len, &error)) < 0) {
507                                 syslog(LOG_ERR, "accept failed: %m");
508                                 exit(1);
509                         }
510                         if (rump_sys_setsockopt(msgsock, SOL_SOCKET,
511                             SO_KEEPALIVE, (char *)&on, sizeof(on), &error) < 0)
512                                 syslog(LOG_ERR,
513                                     "setsockopt SO_KEEPALIVE: %m");
514                         nfsdargs.sock = msgsock;
515                         nfsdargs.name = (caddr_t)&inet6peer;
516                         nfsdargs.namelen = sizeof(inet6peer);
517                         rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs, &error);
518                         (void)rump_sys_close(msgsock, &error);
519                 }
520
521                 if (set[2].revents & POLLIN) {
522                         len = sizeof(isopeer);
523                         if ((msgsock = rump_sys_accept(tp4sock,
524                             (struct sockaddr *)&isopeer, &len, &error)) < 0) {
525                                 syslog(LOG_ERR, "accept failed: %m");
526                                 exit(1);
527                         }
528                         if (rump_sys_setsockopt(msgsock, SOL_SOCKET,
529                             SO_KEEPALIVE, (char *)&on, sizeof(on), &error) < 0)
530                                 syslog(LOG_ERR,
531                                     "setsockopt SO_KEEPALIVE: %m");
532                         nfsdargs.sock = msgsock;
533                         nfsdargs.name = (caddr_t)&isopeer;
534                         nfsdargs.namelen = len;
535                         rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs, &error);
536                         (void)rump_sys_close(msgsock, &error);
537                 }
538
539                 if (set[3].revents & POLLIN) {
540                         len = sizeof(inetpeer);
541                         if ((msgsock = rump_sys_accept(tpipsock,
542                             (struct sockaddr *)&inetpeer, &len)) < 0) {
543                                 syslog(LOG_ERR, "accept failed: %m");
544                                 exit(1);
545                         }
546                         if (setsockopt(msgsock, SOL_SOCKET,
547                             SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
548                                 syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
549                         nfsdargs.sock = msgsock;
550                         nfsdargs.name = (caddr_t)&inetpeer;
551                         nfsdargs.namelen = len;
552                         rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
553                         (void)rump_sys_close(msgsock);
554                 }
555 #endif /* notyet */
556         }
557 }
558
559 void
560 usage()
561 {
562         (void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
563         exit(1);
564 }
565
566 void
567 nonfs(signo)
568         int signo;
569 {
570         syslog(LOG_ERR, "missing system call: NFS not available.");
571 }