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