]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/nfsd/nfsd.c
Update BIND to version 9.6.1rc1. This version has better performance and
[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
55 #include <rpc/rpc.h>
56 #include <rpc/pmap_clnt.h>
57
58 #include <netdb.h>
59 #include <arpa/inet.h>
60 #include <nfs/rpcv2.h>
61 #include <nfs/nfsproto.h>
62 #include <nfsserver/nfs.h>
63 #include <nfs/nfssvc.h>
64
65 #include <err.h>
66 #include <errno.h>
67 #include <signal.h>
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <unistd.h>
72 #include <netdb.h>
73
74 /* Global defs */
75 #ifdef DEBUG
76 #define syslog(e, s...) fprintf(stderr,s)
77 int     debug = 1;
78 #else
79 int     debug = 0;
80 #endif
81
82 #define NFSD_STABLERESTART      "/var/db/nfs-stablerestart"
83 #define MAXNFSDCNT      256
84 #define DEFNFSDCNT       4
85 pid_t   children[MAXNFSDCNT];   /* PIDs of children */
86 int     nfsdcnt;                /* number of children */
87 int     new_syscall;
88 int     run_v4server = 0;       /* Force running of nfsv4 server */
89 int     nfssvc_nfsd;            /* Set to correct NFSSVC_xxx flag */
90
91 void    cleanup(int);
92 void    child_cleanup(int);
93 void    killchildren(void);
94 void    nfsd_exit(int);
95 void    nonfs(int);
96 void    reapchild(int);
97 int     setbindhost(struct addrinfo **ia, const char *bindhost,
98             struct addrinfo hints);
99 void    start_server(int);
100 void    unregistration(void);
101 void    usage(void);
102
103 /*
104  * Nfs server daemon mostly just a user context for nfssvc()
105  *
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
110  *
111  * For connectionless protocols, just pass the socket into the kernel via.
112  * nfssvc().
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().
115  * The arguments are:
116  *      -r - reregister with rpcbind
117  *      -d - unregister with rpcbind
118  *      -t - support tcp nfs clients
119  *      -u - support udp nfs clients
120  *      -e - forces it to run a server that supports nfsv4
121  * followed by "n" which is the number of nfsds' to fork off
122  */
123 int
124 main(int argc, char **argv)
125 {
126         struct nfsd_addsock_args addsockargs;
127         struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
128         struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
129         struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
130         struct sockaddr_in inetpeer;
131         struct sockaddr_in6 inet6peer;
132         fd_set ready, sockbits;
133         fd_set v4bits, v6bits;
134         int ch, connect_type_cnt, i, maxsock, msgsock;
135         socklen_t len;
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         int stablefd, nfssvc_addsock;
141         char **bindhost = NULL;
142         pid_t pid;
143
144         nfsdcnt = DEFNFSDCNT;
145         unregister = reregister = tcpflag = maxsock = 0;
146         bindanyflag = udpflag = connect_type_cnt = bindhostc = 0;
147 #define GETOPT  "ah:n:rdtue"
148 #define USAGE   "[-ardtue] [-n num_servers] [-h bindip]"
149         while ((ch = getopt(argc, argv, GETOPT)) != -1)
150                 switch (ch) {
151                 case 'a':
152                         bindanyflag = 1;
153                         break;
154                 case 'n':
155                         nfsdcnt = atoi(optarg);
156                         if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
157                                 warnx("nfsd count %d; reset to %d", nfsdcnt,
158                                     DEFNFSDCNT);
159                                 nfsdcnt = DEFNFSDCNT;
160                         }
161                         break;
162                 case 'h':
163                         bindhostc++;
164                         bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
165                         if (bindhost == NULL) 
166                                 errx(1, "Out of memory");
167                         bindhost[bindhostc-1] = strdup(optarg);
168                         if (bindhost[bindhostc-1] == NULL)
169                                 errx(1, "Out of memory");
170                         break;
171                 case 'r':
172                         reregister = 1;
173                         break;
174                 case 'd':
175                         unregister = 1;
176                         break;
177                 case 't':
178                         tcpflag = 1;
179                         break;
180                 case 'u':
181                         udpflag = 1;
182                         break;
183                 case 'e':
184                         run_v4server = 1;
185                         break;
186                 default:
187                 case '?':
188                         usage();
189                 };
190         if (!tcpflag && !udpflag)
191                 udpflag = 1;
192         argv += optind;
193         argc -= optind;
194
195         /*
196          * XXX
197          * Backward compatibility, trailing number is the count of daemons.
198          */
199         if (argc > 1)
200                 usage();
201         if (argc == 1) {
202                 nfsdcnt = atoi(argv[0]);
203                 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
204                         warnx("nfsd count %d; reset to %d", nfsdcnt,
205                             DEFNFSDCNT);
206                         nfsdcnt = DEFNFSDCNT;
207                 }
208         }
209
210         /*
211          * If the "-e" option was specified OR only the nfsd module is
212          * found in the server, run "nfsd".
213          * Otherwise, try and run "nfsserver".
214          */
215         if (run_v4server > 0) {
216                 if (modfind("nfsd") < 0) {
217                         /* Not present in kernel, try loading it */
218                         if (kldload("nfsd") < 0 || modfind("nfsd") < 0)
219                                 errx(1, "NFS server is not available");
220                 }
221         } else if (modfind("nfsserver") < 0 && modfind("nfsd") >= 0) {
222                 run_v4server = 1;
223         } else if (modfind("nfsserver") < 0) {
224                 /* Not present in kernel, try loading it */
225                 if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0)
226                         errx(1, "NFS server is not available");
227         }
228
229         ip6flag = 1;
230         s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
231         if (s == -1) {
232                 if (errno != EPROTONOSUPPORT)
233                         err(1, "socket");
234                 ip6flag = 0;
235         } else if (getnetconfigent("udp6") == NULL ||
236                 getnetconfigent("tcp6") == NULL) {
237                 ip6flag = 0;
238         }
239         if (s != -1)
240                 close(s);
241
242         if (bindhostc == 0 || bindanyflag) {
243                 bindhostc++;
244                 bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
245                 if (bindhost == NULL) 
246                         errx(1, "Out of memory");
247                 bindhost[bindhostc-1] = strdup("*");
248                 if (bindhost[bindhostc-1] == NULL) 
249                         errx(1, "Out of memory");
250         }
251
252         if (unregister) {
253                 unregistration();
254                 exit (0);
255         }
256         if (reregister) {
257                 if (udpflag) {
258                         memset(&hints, 0, sizeof hints);
259                         hints.ai_flags = AI_PASSIVE;
260                         hints.ai_family = AF_INET;
261                         hints.ai_socktype = SOCK_DGRAM;
262                         hints.ai_protocol = IPPROTO_UDP;
263                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
264                         if (ecode != 0)
265                                 err(1, "getaddrinfo udp: %s", gai_strerror(ecode));
266                         nconf_udp = getnetconfigent("udp");
267                         if (nconf_udp == NULL)
268                                 err(1, "getnetconfigent udp failed");
269                         nb_udp.buf = ai_udp->ai_addr;
270                         nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
271                         if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
272                             (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
273                                 err(1, "rpcb_set udp failed");
274                         freeaddrinfo(ai_udp);
275                 }
276                 if (udpflag && ip6flag) {
277                         memset(&hints, 0, sizeof hints);
278                         hints.ai_flags = AI_PASSIVE;
279                         hints.ai_family = AF_INET6;
280                         hints.ai_socktype = SOCK_DGRAM;
281                         hints.ai_protocol = IPPROTO_UDP;
282                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
283                         if (ecode != 0)
284                                 err(1, "getaddrinfo udp6: %s", gai_strerror(ecode));
285                         nconf_udp6 = getnetconfigent("udp6");
286                         if (nconf_udp6 == NULL)
287                                 err(1, "getnetconfigent udp6 failed");
288                         nb_udp6.buf = ai_udp6->ai_addr;
289                         nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
290                         if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
291                             (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
292                                 err(1, "rpcb_set udp6 failed");
293                         freeaddrinfo(ai_udp6);
294                 }
295                 if (tcpflag) {
296                         memset(&hints, 0, sizeof hints);
297                         hints.ai_flags = AI_PASSIVE;
298                         hints.ai_family = AF_INET;
299                         hints.ai_socktype = SOCK_STREAM;
300                         hints.ai_protocol = IPPROTO_TCP;
301                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
302                         if (ecode != 0)
303                                 err(1, "getaddrinfo tcp: %s", gai_strerror(ecode));
304                         nconf_tcp = getnetconfigent("tcp");
305                         if (nconf_tcp == NULL)
306                                 err(1, "getnetconfigent tcp failed");
307                         nb_tcp.buf = ai_tcp->ai_addr;
308                         nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
309                         if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) ||
310                             (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)))
311                                 err(1, "rpcb_set tcp failed");
312                         freeaddrinfo(ai_tcp);
313                 }
314                 if (tcpflag && ip6flag) {
315                         memset(&hints, 0, sizeof hints);
316                         hints.ai_flags = AI_PASSIVE;
317                         hints.ai_family = AF_INET6;
318                         hints.ai_socktype = SOCK_STREAM;
319                         hints.ai_protocol = IPPROTO_TCP;
320                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
321                         if (ecode != 0)
322                                 err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode));
323                         nconf_tcp6 = getnetconfigent("tcp6");
324                         if (nconf_tcp6 == NULL)
325                                 err(1, "getnetconfigent tcp6 failed");
326                         nb_tcp6.buf = ai_tcp6->ai_addr;
327                         nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
328                         if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
329                             (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
330                                 err(1, "rpcb_set tcp6 failed");
331                         freeaddrinfo(ai_tcp6);
332                 }
333                 exit (0);
334         }
335         if (debug == 0) {
336                 daemon(0, 0);
337                 (void)signal(SIGHUP, SIG_IGN);
338                 (void)signal(SIGINT, SIG_IGN);
339                 /*
340                  * nfsd sits in the kernel most of the time.  It needs
341                  * to ignore SIGTERM/SIGQUIT in order to stay alive as long
342                  * as possible during a shutdown, otherwise loopback
343                  * mounts will not be able to unmount. 
344                  */
345                 (void)signal(SIGTERM, SIG_IGN);
346                 (void)signal(SIGQUIT, SIG_IGN);
347         }
348         (void)signal(SIGSYS, nonfs);
349         (void)signal(SIGCHLD, reapchild);
350
351         openlog("nfsd", LOG_PID, LOG_DAEMON);
352
353         /*
354          * For V4, we open the stablerestart file and call nfssvc()
355          * to get it loaded. This is done before the daemons do the
356          * regular nfssvc() call to service NFS requests.
357          * (This way the file remains open until the last nfsd is killed
358          *  off.)
359          * Note that this file is not created by this daemon and can
360          * only be relocated by recompiling the daemon, in order to
361          * minimize accidentally starting up with the wrong file.
362          * If should be created as an empty file Read and Write for
363          * root before the first time you run NFS v4 and should never
364          * be re-initialized if at all possible. It should live on a
365          * local, non-volatile storage device that does not do hardware
366          * level write-back caching. (See SCSI doc for more information
367          * on how to prevent write-back caching on SCSI disks.)
368          */
369         if (run_v4server > 0) {
370                 stablefd = open(NFSD_STABLERESTART, O_RDWR, 0);
371                 if (stablefd < 0) {
372                         syslog(LOG_ERR, "Can't open %s\n", NFSD_STABLERESTART);
373                         exit(1);
374                 }
375                 if (nfssvc(NFSSVC_STABLERESTART, (caddr_t)&stablefd) < 0) {
376                         syslog(LOG_ERR, "Can't read stable storage file\n");
377                         exit(1);
378                 }
379                 nfssvc_addsock = NFSSVC_NFSDADDSOCK;
380                 nfssvc_nfsd = NFSSVC_NFSDNFSD;
381                 new_syscall = TRUE;
382         } else {
383                 nfssvc_addsock = NFSSVC_ADDSOCK;
384                 nfssvc_nfsd = NFSSVC_NFSD;
385                 /*
386                  * Figure out if the kernel supports the new-style
387                  * NFSSVC_NFSD. Old kernels will return ENXIO because they
388                  * don't recognise the flag value, new ones will return EINVAL
389                  * because argp is NULL.
390                  */
391                 new_syscall = FALSE;
392                 if (nfssvc(NFSSVC_NFSD, NULL) < 0 && errno == EINVAL)
393                         new_syscall = TRUE;
394         }
395
396         if (!new_syscall) {
397                 /* If we use UDP only, we start the last server below. */
398                 srvcnt = tcpflag ? nfsdcnt : nfsdcnt - 1;
399                 for (i = 0; i < srvcnt; i++) {
400                         switch ((pid = fork())) {
401                         case -1:
402                                 syslog(LOG_ERR, "fork: %m");
403                                 nfsd_exit(1);
404                         case 0:
405                                 break;
406                         default:
407                                 children[i] = pid;
408                                 continue;
409                         }
410                         (void)signal(SIGUSR1, child_cleanup);
411                         setproctitle("server");
412
413                         start_server(0);
414                 }
415         } else if (tcpflag) {
416                 /*
417                  * For TCP mode, we fork once to start the first
418                  * kernel nfsd thread. The kernel will add more
419                  * threads as needed.
420                  */
421                 pid = fork();
422                 if (pid == -1) {
423                         syslog(LOG_ERR, "fork: %m");
424                         nfsd_exit(1);
425                 }
426                 if (pid) {
427                         children[0] = pid;
428                 } else {
429                         (void)signal(SIGUSR1, child_cleanup);
430                         setproctitle("server");
431                         start_server(0);
432                 }
433         }
434
435         (void)signal(SIGUSR1, cleanup);
436         FD_ZERO(&v4bits);
437         FD_ZERO(&v6bits);
438         FD_ZERO(&sockbits);
439  
440         rpcbregcnt = 0;
441         /* Set up the socket for udp and rpcb register it. */
442         if (udpflag) {
443                 rpcbreg = 0;
444                 for (i = 0; i < bindhostc; i++) {
445                         memset(&hints, 0, sizeof hints);
446                         hints.ai_flags = AI_PASSIVE;
447                         hints.ai_family = AF_INET;
448                         hints.ai_socktype = SOCK_DGRAM;
449                         hints.ai_protocol = IPPROTO_UDP;
450                         if (setbindhost(&ai_udp, bindhost[i], hints) == 0) {
451                                 rpcbreg = 1;
452                                 rpcbregcnt++;
453                                 if ((sock = socket(ai_udp->ai_family,
454                                     ai_udp->ai_socktype,
455                                     ai_udp->ai_protocol)) < 0) {
456                                         syslog(LOG_ERR,
457                                             "can't create udp socket");
458                                         nfsd_exit(1);
459                                 }
460                                 if (bind(sock, ai_udp->ai_addr,
461                                     ai_udp->ai_addrlen) < 0) {
462                                         syslog(LOG_ERR,
463                                             "can't bind udp addr %s: %m",
464                                             bindhost[i]);
465                                         nfsd_exit(1);
466                                 }
467                                 freeaddrinfo(ai_udp);
468                                 addsockargs.sock = sock;
469                                 addsockargs.name = NULL;
470                                 addsockargs.namelen = 0;
471                                 if (nfssvc(nfssvc_addsock, &addsockargs) < 0) {
472                                         syslog(LOG_ERR, "can't Add UDP socket");
473                                         nfsd_exit(1);
474                                 }
475                                 (void)close(sock);
476                         }
477                 }
478                 if (rpcbreg == 1) {
479                         memset(&hints, 0, sizeof hints);
480                         hints.ai_flags = AI_PASSIVE;
481                         hints.ai_family = AF_INET;
482                         hints.ai_socktype = SOCK_DGRAM;
483                         hints.ai_protocol = IPPROTO_UDP;
484                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
485                         if (ecode != 0) {
486                                 syslog(LOG_ERR, "getaddrinfo udp: %s",
487                                    gai_strerror(ecode));
488                                 nfsd_exit(1);
489                         }
490                         nconf_udp = getnetconfigent("udp");
491                         if (nconf_udp == NULL)
492                                 err(1, "getnetconfigent udp failed");
493                         nb_udp.buf = ai_udp->ai_addr;
494                         nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
495                         if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
496                             (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
497                                 err(1, "rpcb_set udp failed");
498                         freeaddrinfo(ai_udp);
499                 }
500         }
501
502         /* Set up the socket for udp6 and rpcb register it. */
503         if (udpflag && ip6flag) {
504                 rpcbreg = 0;
505                 for (i = 0; i < bindhostc; i++) {
506                         memset(&hints, 0, sizeof hints);
507                         hints.ai_flags = AI_PASSIVE;
508                         hints.ai_family = AF_INET6;
509                         hints.ai_socktype = SOCK_DGRAM;
510                         hints.ai_protocol = IPPROTO_UDP;
511                         if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) {
512                                 rpcbreg = 1;
513                                 rpcbregcnt++;
514                                 if ((sock = socket(ai_udp6->ai_family,
515                                     ai_udp6->ai_socktype,
516                                     ai_udp6->ai_protocol)) < 0) {
517                                         syslog(LOG_ERR,
518                                                 "can't create udp6 socket");
519                                         nfsd_exit(1);
520                                 }
521                                 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
522                                     &on, sizeof on) < 0) {
523                                         syslog(LOG_ERR,
524                                             "can't set v6-only binding for "
525                                             "udp6 socket: %m");
526                                         nfsd_exit(1);
527                                 }
528                                 if (bind(sock, ai_udp6->ai_addr,
529                                     ai_udp6->ai_addrlen) < 0) {
530                                         syslog(LOG_ERR,
531                                             "can't bind udp6 addr %s: %m",
532                                             bindhost[i]);
533                                         nfsd_exit(1);
534                                 }
535                                 freeaddrinfo(ai_udp6);
536                                 addsockargs.sock = sock;
537                                 addsockargs.name = NULL;
538                                 addsockargs.namelen = 0;
539                                 if (nfssvc(nfssvc_addsock, &addsockargs) < 0) {
540                                         syslog(LOG_ERR,
541                                             "can't add UDP6 socket");
542                                         nfsd_exit(1);
543                                 }
544                                 (void)close(sock);    
545                         }
546                 }
547                 if (rpcbreg == 1) {
548                         memset(&hints, 0, sizeof hints);
549                         hints.ai_flags = AI_PASSIVE;
550                         hints.ai_family = AF_INET6;
551                         hints.ai_socktype = SOCK_DGRAM;
552                         hints.ai_protocol = IPPROTO_UDP;
553                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
554                         if (ecode != 0) {
555                                 syslog(LOG_ERR, "getaddrinfo udp6: %s",
556                                    gai_strerror(ecode));
557                                 nfsd_exit(1);
558                         }
559                         nconf_udp6 = getnetconfigent("udp6");
560                         if (nconf_udp6 == NULL)
561                                 err(1, "getnetconfigent udp6 failed");
562                         nb_udp6.buf = ai_udp6->ai_addr;
563                         nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
564                         if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
565                             (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
566                                 err(1, "rpcb_set udp6 failed");
567                         freeaddrinfo(ai_udp6);
568                 }
569         }
570
571         /* Set up the socket for tcp and rpcb register it. */
572         if (tcpflag) {
573                 rpcbreg = 0;
574                 for (i = 0; i < bindhostc; i++) {
575                         memset(&hints, 0, sizeof hints);
576                         hints.ai_flags = AI_PASSIVE;
577                         hints.ai_family = AF_INET;
578                         hints.ai_socktype = SOCK_STREAM;
579                         hints.ai_protocol = IPPROTO_TCP;
580                         if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) {
581                                 rpcbreg = 1;
582                                 rpcbregcnt++;
583                                 if ((tcpsock = socket(AF_INET, SOCK_STREAM,
584                                     0)) < 0) {
585                                         syslog(LOG_ERR,
586                                             "can't create tpc socket");
587                                         nfsd_exit(1);
588                                 }
589                                 if (setsockopt(tcpsock, SOL_SOCKET,
590                                     SO_REUSEADDR,
591                                     (char *)&on, sizeof(on)) < 0)
592                                         syslog(LOG_ERR,
593                                              "setsockopt SO_REUSEADDR: %m");
594                                 if (bind(tcpsock, ai_tcp->ai_addr,
595                                     ai_tcp->ai_addrlen) < 0) {
596                                         syslog(LOG_ERR,
597                                             "can't bind tcp addr %s: %m",
598                                             bindhost[i]);
599                                         nfsd_exit(1);
600                                 }
601                                 if (listen(tcpsock, 5) < 0) {
602                                         syslog(LOG_ERR, "listen failed");
603                                         nfsd_exit(1);
604                                 }
605                                 freeaddrinfo(ai_tcp);
606                                 FD_SET(tcpsock, &sockbits);
607                                 FD_SET(tcpsock, &v4bits); 
608                                 maxsock = tcpsock;
609                                 connect_type_cnt++;
610                         }
611                 }
612                 if (rpcbreg == 1) {
613                         memset(&hints, 0, sizeof hints);
614                         hints.ai_flags = AI_PASSIVE;
615                         hints.ai_family = AF_INET;
616                         hints.ai_socktype = SOCK_STREAM;
617                         hints.ai_protocol = IPPROTO_TCP;
618                         ecode = getaddrinfo(NULL, "nfs", &hints,
619                              &ai_tcp);
620                         if (ecode != 0) {
621                                 syslog(LOG_ERR, "getaddrinfo tcp: %s",
622                                    gai_strerror(ecode));
623                                 nfsd_exit(1);
624                         }
625                         nconf_tcp = getnetconfigent("tcp");
626                         if (nconf_tcp == NULL)
627                                 err(1, "getnetconfigent tcp failed");
628                         nb_tcp.buf = ai_tcp->ai_addr;
629                         nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
630                         if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp,
631                             &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3,
632                             nconf_tcp, &nb_tcp)))
633                                 err(1, "rpcb_set tcp failed");
634                         freeaddrinfo(ai_tcp);
635                 }
636         }
637
638         /* Set up the socket for tcp6 and rpcb register it. */
639         if (tcpflag && ip6flag) {
640                 rpcbreg = 0;
641                 for (i = 0; i < bindhostc; i++) {
642                         memset(&hints, 0, sizeof hints);
643                         hints.ai_flags = AI_PASSIVE;
644                         hints.ai_family = AF_INET6;
645                         hints.ai_socktype = SOCK_STREAM;
646                         hints.ai_protocol = IPPROTO_TCP;
647                         if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) {
648                                 rpcbreg = 1;
649                                 rpcbregcnt++;
650                                 if ((tcp6sock = socket(ai_tcp6->ai_family,
651                                     ai_tcp6->ai_socktype,
652                                     ai_tcp6->ai_protocol)) < 0) {
653                                         syslog(LOG_ERR,
654                                             "can't create tcp6 socket");
655                                         nfsd_exit(1);
656                                 }
657                                 if (setsockopt(tcp6sock, SOL_SOCKET,
658                                     SO_REUSEADDR,
659                                     (char *)&on, sizeof(on)) < 0)
660                                         syslog(LOG_ERR,
661                                             "setsockopt SO_REUSEADDR: %m");
662                                 if (setsockopt(tcp6sock, IPPROTO_IPV6,
663                                     IPV6_V6ONLY, &on, sizeof on) < 0) {
664                                         syslog(LOG_ERR,
665                                         "can't set v6-only binding for tcp6 "
666                                             "socket: %m");
667                                         nfsd_exit(1);
668                                 }
669                                 if (bind(tcp6sock, ai_tcp6->ai_addr,
670                                     ai_tcp6->ai_addrlen) < 0) {
671                                         syslog(LOG_ERR,
672                                             "can't bind tcp6 addr %s: %m",
673                                             bindhost[i]);
674                                         nfsd_exit(1);
675                                 }
676                                 if (listen(tcp6sock, 5) < 0) {
677                                         syslog(LOG_ERR, "listen failed");
678                                         nfsd_exit(1);
679                                 }
680                                 freeaddrinfo(ai_tcp6);
681                                 FD_SET(tcp6sock, &sockbits);
682                                 FD_SET(tcp6sock, &v6bits);
683                                 if (maxsock < tcp6sock)
684                                         maxsock = tcp6sock;
685                                 connect_type_cnt++;
686                         }
687                 }
688                 if (rpcbreg == 1) {
689                         memset(&hints, 0, sizeof hints);
690                         hints.ai_flags = AI_PASSIVE;
691                         hints.ai_family = AF_INET6;
692                         hints.ai_socktype = SOCK_STREAM;
693                         hints.ai_protocol = IPPROTO_TCP;
694                         ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
695                         if (ecode != 0) {
696                                 syslog(LOG_ERR, "getaddrinfo tcp6: %s",
697                                    gai_strerror(ecode));
698                                 nfsd_exit(1);
699                         }
700                         nconf_tcp6 = getnetconfigent("tcp6");
701                         if (nconf_tcp6 == NULL)
702                                 err(1, "getnetconfigent tcp6 failed");
703                         nb_tcp6.buf = ai_tcp6->ai_addr;
704                         nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
705                         if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
706                             (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
707                                 err(1, "rpcb_set tcp6 failed");
708                         freeaddrinfo(ai_tcp6);
709                 }
710         }
711
712         if (rpcbregcnt == 0) {
713                 syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m");
714                 nfsd_exit(1);
715         }
716
717         if (tcpflag && connect_type_cnt == 0) {
718                 syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m");
719                 nfsd_exit(1);
720         }
721
722         setproctitle("master");
723         /*
724          * We always want a master to have a clean way to to shut nfsd down
725          * (with unregistration): if the master is killed, it unregisters and
726          * kills all children. If we run for UDP only (and so do not have to
727          * loop waiting waiting for accept), we instead make the parent
728          * a "server" too. start_server will not return.
729          */
730         if (!tcpflag)
731                 start_server(1);
732
733         /*
734          * Loop forever accepting connections and passing the sockets
735          * into the kernel for the mounts.
736          */
737         for (;;) {
738                 ready = sockbits;
739                 if (connect_type_cnt > 1) {
740                         if (select(maxsock + 1,
741                             &ready, NULL, NULL, NULL) < 1) {
742                                 syslog(LOG_ERR, "select failed: %m");
743                                 if (errno == EINTR)
744                                         continue;
745                                 nfsd_exit(1);
746                         }
747                 }
748                 for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) {
749                         if (FD_ISSET(tcpsock, &ready)) {
750                                 if (FD_ISSET(tcpsock, &v4bits)) {
751                                         len = sizeof(inetpeer);
752                                         if ((msgsock = accept(tcpsock,
753                                             (struct sockaddr *)&inetpeer, &len)) < 0) {
754                                                 syslog(LOG_ERR, "accept failed: %m");
755                                                 if (errno == ECONNABORTED ||
756                                                     errno == EINTR)
757                                                         continue;
758                                                 nfsd_exit(1);
759                                         }
760                                         memset(inetpeer.sin_zero, 0,
761                                                 sizeof(inetpeer.sin_zero));
762                                         if (setsockopt(msgsock, SOL_SOCKET,
763                                             SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
764                                                 syslog(LOG_ERR,
765                                                     "setsockopt SO_KEEPALIVE: %m");
766                                         addsockargs.sock = msgsock;
767                                         addsockargs.name = (caddr_t)&inetpeer;
768                                         addsockargs.namelen = len;
769                                         nfssvc(nfssvc_addsock, &addsockargs);
770                                         (void)close(msgsock);
771                                 } else if (FD_ISSET(tcpsock, &v6bits)) {
772                                         len = sizeof(inet6peer);
773                                         if ((msgsock = accept(tcpsock,
774                                             (struct sockaddr *)&inet6peer,
775                                             &len)) < 0) {
776                                                 syslog(LOG_ERR,
777                                                      "accept failed: %m");
778                                                 if (errno == ECONNABORTED ||
779                                                     errno == EINTR)
780                                                         continue;
781                                                 nfsd_exit(1);
782                                         }
783                                         if (setsockopt(msgsock, SOL_SOCKET,
784                                             SO_KEEPALIVE, (char *)&on,
785                                             sizeof(on)) < 0)
786                                                 syslog(LOG_ERR, "setsockopt "
787                                                     "SO_KEEPALIVE: %m");
788                                         addsockargs.sock = msgsock;
789                                         addsockargs.name = (caddr_t)&inet6peer;
790                                         addsockargs.namelen = len;
791                                         nfssvc(nfssvc_addsock, &addsockargs);
792                                         (void)close(msgsock);
793                                 }
794                         }
795                 }
796         }
797 }
798
799 int
800 setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints)
801 {
802         int ecode;
803         u_int32_t host_addr[4];  /* IPv4 or IPv6 */
804         const char *hostptr;
805
806         if (bindhost == NULL || strcmp("*", bindhost) == 0)
807                 hostptr = NULL;
808         else
809                 hostptr = bindhost;
810
811         if (hostptr != NULL) {
812                 switch (hints.ai_family) {
813                 case AF_INET:
814                         if (inet_pton(AF_INET, hostptr, host_addr) == 1) {
815                                 hints.ai_flags = AI_NUMERICHOST;
816                         } else {
817                                 if (inet_pton(AF_INET6, hostptr,
818                                     host_addr) == 1)
819                                         return (1);
820                         }
821                         break;
822                 case AF_INET6:
823                         if (inet_pton(AF_INET6, hostptr, host_addr) == 1) {
824                                 hints.ai_flags = AI_NUMERICHOST;
825                         } else {
826                                 if (inet_pton(AF_INET, hostptr,
827                                     host_addr) == 1)
828                                         return (1);
829                         }
830                         break;
831                 default:
832                         break;
833                 }
834         }
835         
836         ecode = getaddrinfo(hostptr, "nfs", &hints, ai);
837         if (ecode != 0) {
838                 syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost,
839                     gai_strerror(ecode));
840                 return (1);
841         }
842         return (0);
843 }
844
845 void
846 usage()
847 {
848         (void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
849         exit(1);
850 }
851
852 void
853 nonfs(__unused int signo)
854 {
855         syslog(LOG_ERR, "missing system call: NFS not available");
856 }
857
858 void
859 reapchild(__unused int signo)
860 {
861         pid_t pid;
862         int i;
863
864         while ((pid = wait3(NULL, WNOHANG, NULL)) > 0) {
865                 for (i = 0; i < nfsdcnt; i++)
866                         if (pid == children[i])
867                                 children[i] = -1;
868         }
869 }
870
871 void
872 unregistration()
873 {
874         if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) ||
875             (!rpcb_unset(RPCPROG_NFS, 3, NULL)))
876                 syslog(LOG_ERR, "rpcb_unset failed");
877 }
878
879 void
880 killchildren()
881 {
882         int i;
883
884         for (i = 0; i < nfsdcnt; i++) {
885                 if (children[i] > 0)
886                         kill(children[i], SIGKILL);
887         }
888 }
889
890 /*
891  * Cleanup master after SIGUSR1.
892  */
893 void
894 cleanup(__unused int signo)
895 {
896         nfsd_exit(0);
897 }
898
899 /*
900  * Cleanup child after SIGUSR1.
901  */
902 void
903 child_cleanup(__unused int signo)
904 {
905         exit(0);
906 }
907
908 void
909 nfsd_exit(int status)
910 {
911         killchildren();
912         unregistration();
913         exit(status);
914 }
915
916 void
917 start_server(int master)
918 {
919         char principal[MAXHOSTNAMELEN + 5];
920         struct nfsd_nfsd_args nfsdargs;
921         int status, error;
922         char hostname[MAXHOSTNAMELEN + 1], *cp;
923         struct addrinfo *aip, hints;
924
925         status = 0;
926         if (new_syscall) {
927                 gethostname(hostname, sizeof (hostname));
928                 snprintf(principal, sizeof (principal), "nfs@%s", hostname);
929                 if ((cp = strchr(hostname, '.')) == NULL ||
930                     *(cp + 1) == '\0') {
931                         /* If not fully qualified, try getaddrinfo() */
932                         memset((void *)&hints, 0, sizeof (hints));
933                         hints.ai_flags = AI_CANONNAME;
934                         error = getaddrinfo(hostname, NULL, &hints, &aip);
935                         if (error == 0) {
936                                 if (aip->ai_canonname != NULL &&
937                                     (cp = strchr(aip->ai_canonname, '.')) !=
938                                     NULL && *(cp + 1) != '\0')
939                                         snprintf(principal, sizeof (principal),
940                                             "nfs@%s", aip->ai_canonname);
941                                 freeaddrinfo(aip);
942                         }
943                 }
944                 nfsdargs.principal = principal;
945                 nfsdargs.minthreads = nfsdcnt;
946                 nfsdargs.maxthreads = nfsdcnt;
947                 error = nfssvc(nfssvc_nfsd, &nfsdargs);
948                 if (error < 0 && errno == EAUTH) {
949                         /*
950                          * This indicates that it could not register the
951                          * rpcsec_gss credentials, usually because the
952                          * gssd daemon isn't running.
953                          * (only the experimental server with nfsv4)
954                          */
955                         syslog(LOG_ERR, "No gssd, using AUTH_SYS only");
956                         principal[0] = '\0';
957                         error = nfssvc(nfssvc_nfsd, &nfsdargs);
958                 }
959                 if (error < 0) {
960                         syslog(LOG_ERR, "nfssvc: %m");
961                         status = 1;
962                 }
963         } else {
964                 if (nfssvc(NFSSVC_OLDNFSD, NULL) < 0) {
965                         syslog(LOG_ERR, "nfssvc: %m");
966                         status = 1;
967                 }
968         }
969         if (master)
970                 nfsd_exit(status);
971         else
972                 exit(status);
973 }