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