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