]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/nfsd/nfsd.c
MFC r340111:
[FreeBSD/FreeBSD.git] / usr.sbin / nfsd / nfsd.c
1 /*
2  * Copyright (c) 1989, 1993, 1994
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
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.
19  *
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
30  * SUCH DAMAGE.
31  */
32
33 #ifndef lint
34 static const char copyright[] =
35 "@(#) Copyright (c) 1989, 1993, 1994\n\
36         The Regents of the University of California.  All rights reserved.\n";
37 #endif /* not lint */
38
39 #ifndef lint
40 #if 0
41 static char sccsid[] = "@(#)nfsd.c      8.9 (Berkeley) 3/29/95";
42 #endif
43 static const char rcsid[] =
44   "$FreeBSD$";
45 #endif /* not lint */
46
47 #include <sys/param.h>
48 #include <sys/syslog.h>
49 #include <sys/wait.h>
50 #include <sys/mount.h>
51 #include <sys/fcntl.h>
52 #include <sys/linker.h>
53 #include <sys/module.h>
54 #include <sys/types.h>
55 #include <sys/stat.h>
56 #include <sys/sysctl.h>
57 #include <sys/ucred.h>
58
59 #include <rpc/rpc.h>
60 #include <rpc/pmap_clnt.h>
61 #include <rpcsvc/nfs_prot.h>
62
63 #include <netdb.h>
64 #include <arpa/inet.h>
65 #include <nfsserver/nfs.h>
66 #include <nfs/nfssvc.h>
67
68 #include <err.h>
69 #include <errno.h>
70 #include <signal.h>
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74 #include <unistd.h>
75 #include <sysexits.h>
76
77 #include <getopt.h>
78
79 static int      debug = 0;
80
81 #define NFSD_STABLERESTART      "/var/db/nfs-stablerestart"
82 #define NFSD_STABLEBACKUP       "/var/db/nfs-stablerestart.bak"
83 #define MAXNFSDCNT      256
84 #define DEFNFSDCNT       4
85 #define NFS_VER2         2
86 #define NFS_VER3         3
87 #define NFS_VER4         4
88 static pid_t children[MAXNFSDCNT]; /* PIDs of children */
89 static int nfsdcnt;             /* number of children */
90 static int nfsdcnt_set;
91 static int minthreads;
92 static int maxthreads;
93 static int nfssvc_nfsd;         /* Set to correct NFSSVC_xxx flag */
94 static int stablefd = -1;       /* Fd for the stable restart file */
95 static int backupfd;            /* Fd for the backup stable restart file */
96 static const char *getopt_shortopts;
97 static const char *getopt_usage;
98
99 static int minthreads_set;
100 static int maxthreads_set;
101
102 static struct option longopts[] = {
103         { "debug", no_argument, &debug, 1 },
104         { "minthreads", required_argument, &minthreads_set, 1 },
105         { "maxthreads", required_argument, &maxthreads_set, 1 },
106         { NULL, 0, NULL, 0}
107 };
108
109 static void     cleanup(int);
110 static void     child_cleanup(int);
111 static void     killchildren(void);
112 static void     nfsd_exit(int);
113 static void     nonfs(int);
114 static void     reapchild(int);
115 static int      setbindhost(struct addrinfo **ia, const char *bindhost,
116                     struct addrinfo hints);
117 static void     start_server(int);
118 static void     unregistration(void);
119 static void     usage(void);
120 static void     open_stable(int *, int *);
121 static void     copy_stable(int, int);
122 static void     backup_stable(int);
123 static void     set_nfsdcnt(int);
124
125 /*
126  * Nfs server daemon mostly just a user context for nfssvc()
127  *
128  * 1 - do file descriptor and signal cleanup
129  * 2 - fork the nfsd(s)
130  * 3 - create server socket(s)
131  * 4 - register socket with rpcbind
132  *
133  * For connectionless protocols, just pass the socket into the kernel via.
134  * nfssvc().
135  * For connection based sockets, loop doing accepts. When you get a new
136  * socket from accept, pass the msgsock into the kernel via. nfssvc().
137  * The arguments are:
138  *      -r - reregister with rpcbind
139  *      -d - unregister with rpcbind
140  *      -t - support tcp nfs clients
141  *      -u - support udp nfs clients
142  *      -e - forces it to run a server that supports nfsv4
143  * followed by "n" which is the number of nfsds' to fork off
144  */
145 int
146 main(int argc, char **argv)
147 {
148         struct nfsd_addsock_args addsockargs;
149         struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
150         struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
151         struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
152         struct sockaddr_storage peer;
153         fd_set ready, sockbits;
154         int ch, connect_type_cnt, i, maxsock, msgsock;
155         socklen_t len;
156         int on = 1, unregister, reregister, sock;
157         int tcp6sock, ip6flag, tcpflag, tcpsock;
158         int udpflag, ecode, error, s;
159         int bindhostc, bindanyflag, rpcbreg, rpcbregcnt;
160         int nfssvc_addsock;
161         int longindex = 0;
162         int nfs_minvers = NFS_VER2;
163         size_t nfs_minvers_size;
164         const char *lopt;
165         char **bindhost = NULL;
166         pid_t pid;
167
168         nfsdcnt = DEFNFSDCNT;
169         unregister = reregister = tcpflag = maxsock = 0;
170         bindanyflag = udpflag = connect_type_cnt = bindhostc = 0;
171         getopt_shortopts = "ah:n:rdtue";
172         getopt_usage =
173             "usage:\n"
174             "  nfsd [-ardtue] [-h bindip]\n"
175             "       [-n numservers] [--minthreads #] [--maxthreads #]\n";
176         while ((ch = getopt_long(argc, argv, getopt_shortopts, longopts,
177                     &longindex)) != -1)
178                 switch (ch) {
179                 case 'a':
180                         bindanyflag = 1;
181                         break;
182                 case 'n':
183                         set_nfsdcnt(atoi(optarg));
184                         break;
185                 case 'h':
186                         bindhostc++;
187                         bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
188                         if (bindhost == NULL) 
189                                 errx(1, "Out of memory");
190                         bindhost[bindhostc-1] = strdup(optarg);
191                         if (bindhost[bindhostc-1] == NULL)
192                                 errx(1, "Out of memory");
193                         break;
194                 case 'r':
195                         reregister = 1;
196                         break;
197                 case 'd':
198                         unregister = 1;
199                         break;
200                 case 't':
201                         tcpflag = 1;
202                         break;
203                 case 'u':
204                         udpflag = 1;
205                         break;
206                 case 'e':
207                         /* now a no-op, since this is the default */
208                         break;
209                 case 0:
210                         lopt = longopts[longindex].name;
211                         if (!strcmp(lopt, "minthreads")) {
212                                 minthreads = atoi(optarg);
213                         } else if (!strcmp(lopt, "maxthreads")) {
214                                 maxthreads = atoi(optarg);
215                         }
216                         break;
217                 default:
218                 case '?':
219                         usage();
220                 }
221         if (!tcpflag && !udpflag)
222                 udpflag = 1;
223         argv += optind;
224         argc -= optind;
225         if (minthreads_set && maxthreads_set && minthreads > maxthreads)
226                 errx(EX_USAGE,
227                     "error: minthreads(%d) can't be greater than "
228                     "maxthreads(%d)", minthreads, maxthreads);
229
230         /*
231          * XXX
232          * Backward compatibility, trailing number is the count of daemons.
233          */
234         if (argc > 1)
235                 usage();
236         if (argc == 1)
237                 set_nfsdcnt(atoi(argv[0]));
238
239         /*
240          * Unless the "-o" option was specified, try and run "nfsd".
241          * If "-o" was specified, try and run "nfsserver".
242          */
243         if (modfind("nfsd") < 0) {
244                 /* Not present in kernel, try loading it */
245                 if (kldload("nfsd") < 0 || modfind("nfsd") < 0)
246                         errx(1, "NFS server is not available");
247         }
248
249         ip6flag = 1;
250         s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
251         if (s == -1) {
252                 if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT)
253                         err(1, "socket");
254                 ip6flag = 0;
255         } else if (getnetconfigent("udp6") == NULL ||
256                 getnetconfigent("tcp6") == NULL) {
257                 ip6flag = 0;
258         }
259         if (s != -1)
260                 close(s);
261
262         if (bindhostc == 0 || bindanyflag) {
263                 bindhostc++;
264                 bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
265                 if (bindhost == NULL) 
266                         errx(1, "Out of memory");
267                 bindhost[bindhostc-1] = strdup("*");
268                 if (bindhost[bindhostc-1] == NULL) 
269                         errx(1, "Out of memory");
270         }
271
272         nfs_minvers_size = sizeof(nfs_minvers);
273         error = sysctlbyname("vfs.nfsd.server_min_nfsvers", &nfs_minvers,
274             &nfs_minvers_size, NULL, 0);
275         if (error != 0 || nfs_minvers < NFS_VER2 || nfs_minvers > NFS_VER4) {
276                 warnx("sysctlbyname(vfs.nfsd.server_min_nfsvers) failed,"
277                     " defaulting to NFSv2");
278                 nfs_minvers = NFS_VER2;
279         }
280
281         if (unregister) {
282                 unregistration();
283                 exit (0);
284         }
285         if (reregister) {
286                 if (udpflag) {
287                         memset(&hints, 0, sizeof hints);
288                         hints.ai_flags = AI_PASSIVE;
289                         hints.ai_family = AF_INET;
290                         hints.ai_socktype = SOCK_DGRAM;
291                         hints.ai_protocol = IPPROTO_UDP;
292                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
293                         if (ecode != 0)
294                                 err(1, "getaddrinfo udp: %s", gai_strerror(ecode));
295                         nconf_udp = getnetconfigent("udp");
296                         if (nconf_udp == NULL)
297                                 err(1, "getnetconfigent udp failed");
298                         nb_udp.buf = ai_udp->ai_addr;
299                         nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
300                         if (nfs_minvers == NFS_VER2)
301                                 if (!rpcb_set(NFS_PROGRAM, 2, nconf_udp,
302                                     &nb_udp))
303                                         err(1, "rpcb_set udp failed");
304                         if (nfs_minvers <= NFS_VER3)
305                                 if (!rpcb_set(NFS_PROGRAM, 3, nconf_udp,
306                                     &nb_udp))
307                                         err(1, "rpcb_set udp failed");
308                         freeaddrinfo(ai_udp);
309                 }
310                 if (udpflag && ip6flag) {
311                         memset(&hints, 0, sizeof hints);
312                         hints.ai_flags = AI_PASSIVE;
313                         hints.ai_family = AF_INET6;
314                         hints.ai_socktype = SOCK_DGRAM;
315                         hints.ai_protocol = IPPROTO_UDP;
316                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
317                         if (ecode != 0)
318                                 err(1, "getaddrinfo udp6: %s", gai_strerror(ecode));
319                         nconf_udp6 = getnetconfigent("udp6");
320                         if (nconf_udp6 == NULL)
321                                 err(1, "getnetconfigent udp6 failed");
322                         nb_udp6.buf = ai_udp6->ai_addr;
323                         nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
324                         if (nfs_minvers == NFS_VER2)
325                                 if (!rpcb_set(NFS_PROGRAM, 2, nconf_udp6,
326                                     &nb_udp6))
327                                         err(1, "rpcb_set udp6 failed");
328                         if (nfs_minvers <= NFS_VER3)
329                                 if (!rpcb_set(NFS_PROGRAM, 3, nconf_udp6,
330                                     &nb_udp6))
331                                         err(1, "rpcb_set udp6 failed");
332                         freeaddrinfo(ai_udp6);
333                 }
334                 if (tcpflag) {
335                         memset(&hints, 0, sizeof hints);
336                         hints.ai_flags = AI_PASSIVE;
337                         hints.ai_family = AF_INET;
338                         hints.ai_socktype = SOCK_STREAM;
339                         hints.ai_protocol = IPPROTO_TCP;
340                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
341                         if (ecode != 0)
342                                 err(1, "getaddrinfo tcp: %s", gai_strerror(ecode));
343                         nconf_tcp = getnetconfigent("tcp");
344                         if (nconf_tcp == NULL)
345                                 err(1, "getnetconfigent tcp failed");
346                         nb_tcp.buf = ai_tcp->ai_addr;
347                         nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
348                         if (nfs_minvers == NFS_VER2)
349                                 if (!rpcb_set(NFS_PROGRAM, 2, nconf_tcp,
350                                     &nb_tcp))
351                                         err(1, "rpcb_set tcp failed");
352                         if (nfs_minvers <= NFS_VER3)
353                                 if (!rpcb_set(NFS_PROGRAM, 3, nconf_tcp,
354                                     &nb_tcp))
355                                         err(1, "rpcb_set tcp failed");
356                         freeaddrinfo(ai_tcp);
357                 }
358                 if (tcpflag && ip6flag) {
359                         memset(&hints, 0, sizeof hints);
360                         hints.ai_flags = AI_PASSIVE;
361                         hints.ai_family = AF_INET6;
362                         hints.ai_socktype = SOCK_STREAM;
363                         hints.ai_protocol = IPPROTO_TCP;
364                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
365                         if (ecode != 0)
366                                 err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode));
367                         nconf_tcp6 = getnetconfigent("tcp6");
368                         if (nconf_tcp6 == NULL)
369                                 err(1, "getnetconfigent tcp6 failed");
370                         nb_tcp6.buf = ai_tcp6->ai_addr;
371                         nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
372                         if (nfs_minvers == NFS_VER2)
373                                 if (!rpcb_set(NFS_PROGRAM, 2, nconf_tcp6,
374                                     &nb_tcp6))
375                                         err(1, "rpcb_set tcp6 failed");
376                         if (nfs_minvers <= NFS_VER3)
377                                 if (!rpcb_set(NFS_PROGRAM, 3, nconf_tcp6, 
378                                    &nb_tcp6))
379                                         err(1, "rpcb_set tcp6 failed");
380                         freeaddrinfo(ai_tcp6);
381                 }
382                 exit (0);
383         }
384         if (debug == 0) {
385                 daemon(0, 0);
386                 (void)signal(SIGHUP, SIG_IGN);
387                 (void)signal(SIGINT, SIG_IGN);
388                 /*
389                  * nfsd sits in the kernel most of the time.  It needs
390                  * to ignore SIGTERM/SIGQUIT in order to stay alive as long
391                  * as possible during a shutdown, otherwise loopback
392                  * mounts will not be able to unmount. 
393                  */
394                 (void)signal(SIGTERM, SIG_IGN);
395                 (void)signal(SIGQUIT, SIG_IGN);
396         }
397         (void)signal(SIGSYS, nonfs);
398         (void)signal(SIGCHLD, reapchild);
399         (void)signal(SIGUSR2, backup_stable);
400
401         openlog("nfsd", LOG_PID | (debug ? LOG_PERROR : 0), LOG_DAEMON);
402
403         /*
404          * For V4, we open the stablerestart file and call nfssvc()
405          * to get it loaded. This is done before the daemons do the
406          * regular nfssvc() call to service NFS requests.
407          * (This way the file remains open until the last nfsd is killed
408          *  off.)
409          * It and the backup copy will be created as empty files
410          * the first time this nfsd is started and should never be
411          * deleted/replaced if at all possible. It should live on a
412          * local, non-volatile storage device that does not do hardware
413          * level write-back caching. (See SCSI doc for more information
414          * on how to prevent write-back caching on SCSI disks.)
415          */
416         open_stable(&stablefd, &backupfd);
417         if (stablefd < 0) {
418                 syslog(LOG_ERR, "Can't open %s: %m\n", NFSD_STABLERESTART);
419                 exit(1);
420         }
421         /* This system call will fail for old kernels, but that's ok. */
422         nfssvc(NFSSVC_BACKUPSTABLE, NULL);
423         if (nfssvc(NFSSVC_STABLERESTART, (caddr_t)&stablefd) < 0) {
424                 syslog(LOG_ERR, "Can't read stable storage file: %m\n");
425                 exit(1);
426         }
427         nfssvc_addsock = NFSSVC_NFSDADDSOCK;
428         nfssvc_nfsd = NFSSVC_NFSDNFSD;
429
430         if (tcpflag) {
431                 /*
432                  * For TCP mode, we fork once to start the first
433                  * kernel nfsd thread. The kernel will add more
434                  * threads as needed.
435                  */
436                 pid = fork();
437                 if (pid == -1) {
438                         syslog(LOG_ERR, "fork: %m");
439                         nfsd_exit(1);
440                 }
441                 if (pid) {
442                         children[0] = pid;
443                 } else {
444                         (void)signal(SIGUSR1, child_cleanup);
445                         setproctitle("server");
446                         start_server(0);
447                 }
448         }
449
450         (void)signal(SIGUSR1, cleanup);
451         FD_ZERO(&sockbits);
452  
453         rpcbregcnt = 0;
454         /* Set up the socket for udp and rpcb register it. */
455         if (udpflag) {
456                 rpcbreg = 0;
457                 for (i = 0; i < bindhostc; i++) {
458                         memset(&hints, 0, sizeof hints);
459                         hints.ai_flags = AI_PASSIVE;
460                         hints.ai_family = AF_INET;
461                         hints.ai_socktype = SOCK_DGRAM;
462                         hints.ai_protocol = IPPROTO_UDP;
463                         if (setbindhost(&ai_udp, bindhost[i], hints) == 0) {
464                                 rpcbreg = 1;
465                                 rpcbregcnt++;
466                                 if ((sock = socket(ai_udp->ai_family,
467                                     ai_udp->ai_socktype,
468                                     ai_udp->ai_protocol)) < 0) {
469                                         syslog(LOG_ERR,
470                                             "can't create udp socket");
471                                         nfsd_exit(1);
472                                 }
473                                 if (bind(sock, ai_udp->ai_addr,
474                                     ai_udp->ai_addrlen) < 0) {
475                                         syslog(LOG_ERR,
476                                             "can't bind udp addr %s: %m",
477                                             bindhost[i]);
478                                         nfsd_exit(1);
479                                 }
480                                 freeaddrinfo(ai_udp);
481                                 addsockargs.sock = sock;
482                                 addsockargs.name = NULL;
483                                 addsockargs.namelen = 0;
484                                 if (nfssvc(nfssvc_addsock, &addsockargs) < 0) {
485                                         syslog(LOG_ERR, "can't Add UDP socket");
486                                         nfsd_exit(1);
487                                 }
488                                 (void)close(sock);
489                         }
490                 }
491                 if (rpcbreg == 1) {
492                         memset(&hints, 0, sizeof hints);
493                         hints.ai_flags = AI_PASSIVE;
494                         hints.ai_family = AF_INET;
495                         hints.ai_socktype = SOCK_DGRAM;
496                         hints.ai_protocol = IPPROTO_UDP;
497                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
498                         if (ecode != 0) {
499                                 syslog(LOG_ERR, "getaddrinfo udp: %s",
500                                    gai_strerror(ecode));
501                                 nfsd_exit(1);
502                         }
503                         nconf_udp = getnetconfigent("udp");
504                         if (nconf_udp == NULL)
505                                 err(1, "getnetconfigent udp failed");
506                         nb_udp.buf = ai_udp->ai_addr;
507                         nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
508                         if (nfs_minvers == NFS_VER2)
509                                 if (!rpcb_set(NFS_PROGRAM, 2, nconf_udp,
510                                     &nb_udp))
511                                         err(1, "rpcb_set udp failed");
512                         if (nfs_minvers <= NFS_VER3)
513                                 if (!rpcb_set(NFS_PROGRAM, 3, nconf_udp,
514                                     &nb_udp))
515                                         err(1, "rpcb_set udp failed");
516                         freeaddrinfo(ai_udp);
517                 }
518         }
519
520         /* Set up the socket for udp6 and rpcb register it. */
521         if (udpflag && ip6flag) {
522                 rpcbreg = 0;
523                 for (i = 0; i < bindhostc; i++) {
524                         memset(&hints, 0, sizeof hints);
525                         hints.ai_flags = AI_PASSIVE;
526                         hints.ai_family = AF_INET6;
527                         hints.ai_socktype = SOCK_DGRAM;
528                         hints.ai_protocol = IPPROTO_UDP;
529                         if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) {
530                                 rpcbreg = 1;
531                                 rpcbregcnt++;
532                                 if ((sock = socket(ai_udp6->ai_family,
533                                     ai_udp6->ai_socktype,
534                                     ai_udp6->ai_protocol)) < 0) {
535                                         syslog(LOG_ERR,
536                                                 "can't create udp6 socket");
537                                         nfsd_exit(1);
538                                 }
539                                 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
540                                     &on, sizeof on) < 0) {
541                                         syslog(LOG_ERR,
542                                             "can't set v6-only binding for "
543                                             "udp6 socket: %m");
544                                         nfsd_exit(1);
545                                 }
546                                 if (bind(sock, ai_udp6->ai_addr,
547                                     ai_udp6->ai_addrlen) < 0) {
548                                         syslog(LOG_ERR,
549                                             "can't bind udp6 addr %s: %m",
550                                             bindhost[i]);
551                                         nfsd_exit(1);
552                                 }
553                                 freeaddrinfo(ai_udp6);
554                                 addsockargs.sock = sock;
555                                 addsockargs.name = NULL;
556                                 addsockargs.namelen = 0;
557                                 if (nfssvc(nfssvc_addsock, &addsockargs) < 0) {
558                                         syslog(LOG_ERR,
559                                             "can't add UDP6 socket");
560                                         nfsd_exit(1);
561                                 }
562                                 (void)close(sock);    
563                         }
564                 }
565                 if (rpcbreg == 1) {
566                         memset(&hints, 0, sizeof hints);
567                         hints.ai_flags = AI_PASSIVE;
568                         hints.ai_family = AF_INET6;
569                         hints.ai_socktype = SOCK_DGRAM;
570                         hints.ai_protocol = IPPROTO_UDP;
571                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
572                         if (ecode != 0) {
573                                 syslog(LOG_ERR, "getaddrinfo udp6: %s",
574                                    gai_strerror(ecode));
575                                 nfsd_exit(1);
576                         }
577                         nconf_udp6 = getnetconfigent("udp6");
578                         if (nconf_udp6 == NULL)
579                                 err(1, "getnetconfigent udp6 failed");
580                         nb_udp6.buf = ai_udp6->ai_addr;
581                         nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
582                         if (nfs_minvers == NFS_VER2)
583                                 if (!rpcb_set(NFS_PROGRAM, 2, nconf_udp6,
584                                     &nb_udp6))
585                                         err(1,
586                                             "rpcb_set udp6 failed");
587                         if (nfs_minvers <= NFS_VER3)
588                                 if (!rpcb_set(NFS_PROGRAM, 3, nconf_udp6,
589                                     &nb_udp6))
590                                         err(1,
591                                             "rpcb_set udp6 failed");
592                         freeaddrinfo(ai_udp6);
593                 }
594         }
595
596         /* Set up the socket for tcp and rpcb register it. */
597         if (tcpflag) {
598                 rpcbreg = 0;
599                 for (i = 0; i < bindhostc; i++) {
600                         memset(&hints, 0, sizeof hints);
601                         hints.ai_flags = AI_PASSIVE;
602                         hints.ai_family = AF_INET;
603                         hints.ai_socktype = SOCK_STREAM;
604                         hints.ai_protocol = IPPROTO_TCP;
605                         if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) {
606                                 rpcbreg = 1;
607                                 rpcbregcnt++;
608                                 if ((tcpsock = socket(AF_INET, SOCK_STREAM,
609                                     0)) < 0) {
610                                         syslog(LOG_ERR,
611                                             "can't create tcp socket");
612                                         nfsd_exit(1);
613                                 }
614                                 if (setsockopt(tcpsock, SOL_SOCKET,
615                                     SO_REUSEADDR,
616                                     (char *)&on, sizeof(on)) < 0)
617                                         syslog(LOG_ERR,
618                                              "setsockopt SO_REUSEADDR: %m");
619                                 if (bind(tcpsock, ai_tcp->ai_addr,
620                                     ai_tcp->ai_addrlen) < 0) {
621                                         syslog(LOG_ERR,
622                                             "can't bind tcp addr %s: %m",
623                                             bindhost[i]);
624                                         nfsd_exit(1);
625                                 }
626                                 if (listen(tcpsock, -1) < 0) {
627                                         syslog(LOG_ERR, "listen failed");
628                                         nfsd_exit(1);
629                                 }
630                                 freeaddrinfo(ai_tcp);
631                                 FD_SET(tcpsock, &sockbits);
632                                 maxsock = tcpsock;
633                                 connect_type_cnt++;
634                         }
635                 }
636                 if (rpcbreg == 1) {
637                         memset(&hints, 0, sizeof hints);
638                         hints.ai_flags = AI_PASSIVE;
639                         hints.ai_family = AF_INET;
640                         hints.ai_socktype = SOCK_STREAM;
641                         hints.ai_protocol = IPPROTO_TCP;
642                         ecode = getaddrinfo(NULL, "nfs", &hints,
643                              &ai_tcp);
644                         if (ecode != 0) {
645                                 syslog(LOG_ERR, "getaddrinfo tcp: %s",
646                                    gai_strerror(ecode));
647                                 nfsd_exit(1);
648                         }
649                         nconf_tcp = getnetconfigent("tcp");
650                         if (nconf_tcp == NULL)
651                                 err(1, "getnetconfigent tcp failed");
652                         nb_tcp.buf = ai_tcp->ai_addr;
653                         nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
654                         if (nfs_minvers == NFS_VER2)
655                                 if (!rpcb_set(NFS_PROGRAM, 2, nconf_tcp,
656                                     &nb_tcp))
657                                         err(1, "rpcb_set tcp failed");
658                         if (nfs_minvers <= NFS_VER3)
659                                 if (!rpcb_set(NFS_PROGRAM, 3, nconf_tcp,
660                                     &nb_tcp))
661                                         err(1, "rpcb_set tcp failed");
662                         freeaddrinfo(ai_tcp);
663                 }
664         }
665
666         /* Set up the socket for tcp6 and rpcb register it. */
667         if (tcpflag && ip6flag) {
668                 rpcbreg = 0;
669                 for (i = 0; i < bindhostc; i++) {
670                         memset(&hints, 0, sizeof hints);
671                         hints.ai_flags = AI_PASSIVE;
672                         hints.ai_family = AF_INET6;
673                         hints.ai_socktype = SOCK_STREAM;
674                         hints.ai_protocol = IPPROTO_TCP;
675                         if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) {
676                                 rpcbreg = 1;
677                                 rpcbregcnt++;
678                                 if ((tcp6sock = socket(ai_tcp6->ai_family,
679                                     ai_tcp6->ai_socktype,
680                                     ai_tcp6->ai_protocol)) < 0) {
681                                         syslog(LOG_ERR,
682                                             "can't create tcp6 socket");
683                                         nfsd_exit(1);
684                                 }
685                                 if (setsockopt(tcp6sock, SOL_SOCKET,
686                                     SO_REUSEADDR,
687                                     (char *)&on, sizeof(on)) < 0)
688                                         syslog(LOG_ERR,
689                                             "setsockopt SO_REUSEADDR: %m");
690                                 if (setsockopt(tcp6sock, IPPROTO_IPV6,
691                                     IPV6_V6ONLY, &on, sizeof on) < 0) {
692                                         syslog(LOG_ERR,
693                                         "can't set v6-only binding for tcp6 "
694                                             "socket: %m");
695                                         nfsd_exit(1);
696                                 }
697                                 if (bind(tcp6sock, ai_tcp6->ai_addr,
698                                     ai_tcp6->ai_addrlen) < 0) {
699                                         syslog(LOG_ERR,
700                                             "can't bind tcp6 addr %s: %m",
701                                             bindhost[i]);
702                                         nfsd_exit(1);
703                                 }
704                                 if (listen(tcp6sock, -1) < 0) {
705                                         syslog(LOG_ERR, "listen failed");
706                                         nfsd_exit(1);
707                                 }
708                                 freeaddrinfo(ai_tcp6);
709                                 FD_SET(tcp6sock, &sockbits);
710                                 if (maxsock < tcp6sock)
711                                         maxsock = tcp6sock;
712                                 connect_type_cnt++;
713                         }
714                 }
715                 if (rpcbreg == 1) {
716                         memset(&hints, 0, sizeof hints);
717                         hints.ai_flags = AI_PASSIVE;
718                         hints.ai_family = AF_INET6;
719                         hints.ai_socktype = SOCK_STREAM;
720                         hints.ai_protocol = IPPROTO_TCP;
721                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
722                         if (ecode != 0) {
723                                 syslog(LOG_ERR, "getaddrinfo tcp6: %s",
724                                    gai_strerror(ecode));
725                                 nfsd_exit(1);
726                         }
727                         nconf_tcp6 = getnetconfigent("tcp6");
728                         if (nconf_tcp6 == NULL)
729                                 err(1, "getnetconfigent tcp6 failed");
730                         nb_tcp6.buf = ai_tcp6->ai_addr;
731                         nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
732                         if (nfs_minvers == NFS_VER2)
733                                 if (!rpcb_set(NFS_PROGRAM, 2, nconf_tcp6,
734                                     &nb_tcp6))
735                                         err(1, "rpcb_set tcp6 failed");
736                         if (nfs_minvers <= NFS_VER3)
737                                 if (!rpcb_set(NFS_PROGRAM, 3, nconf_tcp6,
738                                     &nb_tcp6))
739                                         err(1, "rpcb_set tcp6 failed");
740                         freeaddrinfo(ai_tcp6);
741                 }
742         }
743
744         if (rpcbregcnt == 0) {
745                 syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m");
746                 nfsd_exit(1);
747         }
748
749         if (tcpflag && connect_type_cnt == 0) {
750                 syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m");
751                 nfsd_exit(1);
752         }
753
754         setproctitle("master");
755         /*
756          * We always want a master to have a clean way to to shut nfsd down
757          * (with unregistration): if the master is killed, it unregisters and
758          * kills all children. If we run for UDP only (and so do not have to
759          * loop waiting waiting for accept), we instead make the parent
760          * a "server" too. start_server will not return.
761          */
762         if (!tcpflag)
763                 start_server(1);
764
765         /*
766          * Loop forever accepting connections and passing the sockets
767          * into the kernel for the mounts.
768          */
769         for (;;) {
770                 ready = sockbits;
771                 if (connect_type_cnt > 1) {
772                         if (select(maxsock + 1,
773                             &ready, NULL, NULL, NULL) < 1) {
774                                 error = errno;
775                                 if (error == EINTR)
776                                         continue;
777                                 syslog(LOG_ERR, "select failed: %m");
778                                 nfsd_exit(1);
779                         }
780                 }
781                 for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) {
782                         if (FD_ISSET(tcpsock, &ready)) {
783                                 len = sizeof(peer);
784                                 if ((msgsock = accept(tcpsock,
785                                     (struct sockaddr *)&peer, &len)) < 0) {
786                                         error = errno;
787                                         syslog(LOG_ERR, "accept failed: %m");
788                                         if (error == ECONNABORTED ||
789                                             error == EINTR)
790                                                 continue;
791                                         nfsd_exit(1);
792                                 }
793                                 if (setsockopt(msgsock, SOL_SOCKET,
794                                     SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
795                                         syslog(LOG_ERR,
796                                             "setsockopt SO_KEEPALIVE: %m");
797                                 addsockargs.sock = msgsock;
798                                 addsockargs.name = (caddr_t)&peer;
799                                 addsockargs.namelen = len;
800                                 nfssvc(nfssvc_addsock, &addsockargs);
801                                 (void)close(msgsock);
802                         }
803                 }
804         }
805 }
806
807 static int
808 setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints)
809 {
810         int ecode;
811         u_int32_t host_addr[4];  /* IPv4 or IPv6 */
812         const char *hostptr;
813
814         if (bindhost == NULL || strcmp("*", bindhost) == 0)
815                 hostptr = NULL;
816         else
817                 hostptr = bindhost;
818
819         if (hostptr != NULL) {
820                 switch (hints.ai_family) {
821                 case AF_INET:
822                         if (inet_pton(AF_INET, hostptr, host_addr) == 1) {
823                                 hints.ai_flags = AI_NUMERICHOST;
824                         } else {
825                                 if (inet_pton(AF_INET6, hostptr,
826                                     host_addr) == 1)
827                                         return (1);
828                         }
829                         break;
830                 case AF_INET6:
831                         if (inet_pton(AF_INET6, hostptr, host_addr) == 1) {
832                                 hints.ai_flags = AI_NUMERICHOST;
833                         } else {
834                                 if (inet_pton(AF_INET, hostptr,
835                                     host_addr) == 1)
836                                         return (1);
837                         }
838                         break;
839                 default:
840                         break;
841                 }
842         }
843         
844         ecode = getaddrinfo(hostptr, "nfs", &hints, ai);
845         if (ecode != 0) {
846                 syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost,
847                     gai_strerror(ecode));
848                 return (1);
849         }
850         return (0);
851 }
852
853 static void
854 set_nfsdcnt(int proposed)
855 {
856
857         if (proposed < 1) {
858                 warnx("nfsd count too low %d; reset to %d", proposed,
859                     DEFNFSDCNT);
860                 nfsdcnt = DEFNFSDCNT;
861         } else if (proposed > MAXNFSDCNT) {
862                 warnx("nfsd count too high %d; truncated to %d", proposed,
863                     MAXNFSDCNT);
864                 nfsdcnt = MAXNFSDCNT;
865         } else
866                 nfsdcnt = proposed;
867         nfsdcnt_set = 1;
868 }
869
870 static void
871 usage(void)
872 {
873         (void)fprintf(stderr, "%s", getopt_usage);
874         exit(1);
875 }
876
877 static void
878 nonfs(__unused int signo)
879 {
880         syslog(LOG_ERR, "missing system call: NFS not available");
881 }
882
883 static void
884 reapchild(__unused int signo)
885 {
886         pid_t pid;
887         int i;
888
889         while ((pid = wait3(NULL, WNOHANG, NULL)) > 0) {
890                 for (i = 0; i < nfsdcnt; i++)
891                         if (pid == children[i])
892                                 children[i] = -1;
893         }
894 }
895
896 static void
897 unregistration(void)
898 {
899         if ((!rpcb_unset(NFS_PROGRAM, 2, NULL)) ||
900             (!rpcb_unset(NFS_PROGRAM, 3, NULL)))
901                 syslog(LOG_ERR, "rpcb_unset failed");
902 }
903
904 static void
905 killchildren(void)
906 {
907         int i;
908
909         for (i = 0; i < nfsdcnt; i++) {
910                 if (children[i] > 0)
911                         kill(children[i], SIGKILL);
912         }
913 }
914
915 /*
916  * Cleanup master after SIGUSR1.
917  */
918 static void
919 cleanup(__unused int signo)
920 {
921         nfsd_exit(0);
922 }
923
924 /*
925  * Cleanup child after SIGUSR1.
926  */
927 static void
928 child_cleanup(__unused int signo)
929 {
930         exit(0);
931 }
932
933 static void
934 nfsd_exit(int status)
935 {
936         killchildren();
937         unregistration();
938         exit(status);
939 }
940
941 static int
942 get_tuned_nfsdcount(void)
943 {
944         int ncpu, error, tuned_nfsdcnt;
945         size_t ncpu_size;
946
947         ncpu_size = sizeof(ncpu);
948         error = sysctlbyname("hw.ncpu", &ncpu, &ncpu_size, NULL, 0);
949         if (error) {
950                 warnx("sysctlbyname(hw.ncpu) failed defaulting to %d nfs servers",
951                     DEFNFSDCNT);
952                 tuned_nfsdcnt = DEFNFSDCNT;
953         } else {
954                 tuned_nfsdcnt = ncpu * 8;
955         }
956         return tuned_nfsdcnt;
957 }
958
959 static void
960 start_server(int master)
961 {
962         char principal[MAXHOSTNAMELEN + 5];
963         struct nfsd_nfsd_args nfsdargs;
964         int status, error;
965         char hostname[MAXHOSTNAMELEN + 1], *cp;
966         struct addrinfo *aip, hints;
967
968         status = 0;
969         gethostname(hostname, sizeof (hostname));
970         snprintf(principal, sizeof (principal), "nfs@%s", hostname);
971         if ((cp = strchr(hostname, '.')) == NULL ||
972             *(cp + 1) == '\0') {
973                 /* If not fully qualified, try getaddrinfo() */
974                 memset((void *)&hints, 0, sizeof (hints));
975                 hints.ai_flags = AI_CANONNAME;
976                 error = getaddrinfo(hostname, NULL, &hints, &aip);
977                 if (error == 0) {
978                         if (aip->ai_canonname != NULL &&
979                             (cp = strchr(aip->ai_canonname, '.')) !=
980                             NULL && *(cp + 1) != '\0')
981                                 snprintf(principal, sizeof (principal),
982                                     "nfs@%s", aip->ai_canonname);
983                         freeaddrinfo(aip);
984                 }
985         }
986         nfsdargs.principal = principal;
987
988         if (nfsdcnt_set)
989                 nfsdargs.minthreads = nfsdargs.maxthreads = nfsdcnt;
990         else {
991                 nfsdargs.minthreads = minthreads_set ? minthreads : get_tuned_nfsdcount();
992                 nfsdargs.maxthreads = maxthreads_set ? maxthreads : nfsdargs.minthreads;
993                 if (nfsdargs.maxthreads < nfsdargs.minthreads)
994                         nfsdargs.maxthreads = nfsdargs.minthreads;
995         }
996         error = nfssvc(nfssvc_nfsd, &nfsdargs);
997         if (error < 0 && errno == EAUTH) {
998                 /*
999                  * This indicates that it could not register the
1000                  * rpcsec_gss credentials, usually because the
1001                  * gssd daemon isn't running.
1002                  * (only the experimental server with nfsv4)
1003                  */
1004                 syslog(LOG_ERR, "No gssd, using AUTH_SYS only");
1005                 principal[0] = '\0';
1006                 error = nfssvc(nfssvc_nfsd, &nfsdargs);
1007         }
1008         if (error < 0) {
1009                 syslog(LOG_ERR, "nfssvc: %m");
1010                 status = 1;
1011         }
1012         if (master)
1013                 nfsd_exit(status);
1014         else
1015                 exit(status);
1016 }
1017
1018 /*
1019  * Open the stable restart file and return the file descriptor for it.
1020  */
1021 static void
1022 open_stable(int *stable_fdp, int *backup_fdp)
1023 {
1024         int stable_fd, backup_fd = -1, ret;
1025         struct stat st, backup_st;
1026
1027         /* Open and stat the stable restart file. */
1028         stable_fd = open(NFSD_STABLERESTART, O_RDWR, 0);
1029         if (stable_fd < 0)
1030                 stable_fd = open(NFSD_STABLERESTART, O_RDWR | O_CREAT, 0600);
1031         if (stable_fd >= 0) {
1032                 ret = fstat(stable_fd, &st);
1033                 if (ret < 0) {
1034                         close(stable_fd);
1035                         stable_fd = -1;
1036                 }
1037         }
1038
1039         /* Open and stat the backup stable restart file. */
1040         if (stable_fd >= 0) {
1041                 backup_fd = open(NFSD_STABLEBACKUP, O_RDWR, 0);
1042                 if (backup_fd < 0)
1043                         backup_fd = open(NFSD_STABLEBACKUP, O_RDWR | O_CREAT,
1044                             0600);
1045                 if (backup_fd >= 0) {
1046                         ret = fstat(backup_fd, &backup_st);
1047                         if (ret < 0) {
1048                                 close(backup_fd);
1049                                 backup_fd = -1;
1050                         }
1051                 }
1052                 if (backup_fd < 0) {
1053                         close(stable_fd);
1054                         stable_fd = -1;
1055                 }
1056         }
1057
1058         *stable_fdp = stable_fd;
1059         *backup_fdp = backup_fd;
1060         if (stable_fd < 0)
1061                 return;
1062
1063         /* Sync up the 2 files, as required. */
1064         if (st.st_size > 0)
1065                 copy_stable(stable_fd, backup_fd);
1066         else if (backup_st.st_size > 0)
1067                 copy_stable(backup_fd, stable_fd);
1068 }
1069
1070 /*
1071  * Copy the stable restart file to the backup or vice versa.
1072  */
1073 static void
1074 copy_stable(int from_fd, int to_fd)
1075 {
1076         int cnt, ret;
1077         static char buf[1024];
1078
1079         ret = lseek(from_fd, (off_t)0, SEEK_SET);
1080         if (ret >= 0)
1081                 ret = lseek(to_fd, (off_t)0, SEEK_SET);
1082         if (ret >= 0)
1083                 ret = ftruncate(to_fd, (off_t)0);
1084         if (ret >= 0)
1085                 do {
1086                         cnt = read(from_fd, buf, 1024);
1087                         if (cnt > 0)
1088                                 ret = write(to_fd, buf, cnt);
1089                         else if (cnt < 0)
1090                                 ret = cnt;
1091                 } while (cnt > 0 && ret >= 0);
1092         if (ret >= 0)
1093                 ret = fsync(to_fd);
1094         if (ret < 0)
1095                 syslog(LOG_ERR, "stable restart copy failure: %m");
1096 }
1097
1098 /*
1099  * Back up the stable restart file when indicated by the kernel.
1100  */
1101 static void
1102 backup_stable(__unused int signo)
1103 {
1104
1105         if (stablefd >= 0)
1106                 copy_stable(stablefd, backupfd);
1107 }
1108