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 20 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(argc, argv, envp) 118 int argc; 119 char *argv[], *envp[]; 120 { 121 struct nfsd_args nfsdargs; 122 struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints; 123 struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6; 124 struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6; 125 struct sockaddr_in inetpeer; 126 struct sockaddr_in6 inet6peer; 127 fd_set ready, sockbits; 128 fd_set v4bits, v6bits; 129 int ch, connect_type_cnt, i, len, maxsock, msgsock; 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 /* If we use UDP only, we start the last server below. */ 331 srvcnt = tcpflag ? nfsdcnt : nfsdcnt - 1; 332 for (i = 0; i < srvcnt; i++) { 333 switch ((pid = fork())) { 334 case -1: 335 syslog(LOG_ERR, "fork: %m"); 336 nfsd_exit(1); 337 case 0: 338 break; 339 default: 340 children[i] = pid; 341 continue; 342 } 343 (void)signal(SIGUSR1, child_cleanup); 344 setproctitle("server"); 345 346 start_server(0); 347 } 348 349 (void)signal(SIGUSR1, cleanup); 350 FD_ZERO(&v4bits); 351 FD_ZERO(&v6bits); 352 FD_ZERO(&sockbits); 353 354 rpcbregcnt = 0; 355 /* Set up the socket for udp and rpcb register it. */ 356 if (udpflag) { 357 rpcbreg = 0; 358 for (i = 0; i < bindhostc; i++) { 359 memset(&hints, 0, sizeof hints); 360 hints.ai_flags = AI_PASSIVE; 361 hints.ai_family = AF_INET; 362 hints.ai_socktype = SOCK_DGRAM; 363 hints.ai_protocol = IPPROTO_UDP; 364 if (setbindhost(&ai_udp, bindhost[i], hints) == 0) { 365 rpcbreg = 1; 366 rpcbregcnt++; 367 if ((sock = socket(ai_udp->ai_family, 368 ai_udp->ai_socktype, 369 ai_udp->ai_protocol)) < 0) { 370 syslog(LOG_ERR, 371 "can't create udp socket"); 372 nfsd_exit(1); 373 } 374 if (bind(sock, ai_udp->ai_addr, 375 ai_udp->ai_addrlen) < 0) { 376 syslog(LOG_ERR, 377 "can't bind udp addr %s: %m", 378 bindhost[i]); 379 nfsd_exit(1); 380 } 381 freeaddrinfo(ai_udp); 382 nfsdargs.sock = sock; 383 nfsdargs.name = NULL; 384 nfsdargs.namelen = 0; 385 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 386 syslog(LOG_ERR, "can't Add UDP socket"); 387 nfsd_exit(1); 388 } 389 (void)close(sock); 390 } 391 } 392 if (rpcbreg == 1) { 393 memset(&hints, 0, sizeof hints); 394 hints.ai_flags = AI_PASSIVE; 395 hints.ai_family = AF_INET; 396 hints.ai_socktype = SOCK_DGRAM; 397 hints.ai_protocol = IPPROTO_UDP; 398 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); 399 if (ecode != 0) { 400 syslog(LOG_ERR, "getaddrinfo udp: %s", 401 gai_strerror(ecode)); 402 nfsd_exit(1); 403 } 404 nconf_udp = getnetconfigent("udp"); 405 if (nconf_udp == NULL) 406 err(1, "getnetconfigent udp failed"); 407 nb_udp.buf = ai_udp->ai_addr; 408 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; 409 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) || 410 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp))) 411 err(1, "rpcb_set udp failed"); 412 freeaddrinfo(ai_udp); 413 } 414 } 415 416 /* Set up the socket for udp6 and rpcb register it. */ 417 if (udpflag && ip6flag) { 418 rpcbreg = 0; 419 for (i = 0; i < bindhostc; i++) { 420 memset(&hints, 0, sizeof hints); 421 hints.ai_flags = AI_PASSIVE; 422 hints.ai_family = AF_INET6; 423 hints.ai_socktype = SOCK_DGRAM; 424 hints.ai_protocol = IPPROTO_UDP; 425 if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) { 426 rpcbreg = 1; 427 rpcbregcnt++; 428 if ((sock = socket(ai_udp6->ai_family, 429 ai_udp6->ai_socktype, 430 ai_udp6->ai_protocol)) < 0) { 431 syslog(LOG_ERR, 432 "can't create udp6 socket"); 433 nfsd_exit(1); 434 } 435 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, 436 &on, sizeof on) < 0) { 437 syslog(LOG_ERR, 438 "can't set v6-only binding for " 439 "udp6 socket: %m"); 440 nfsd_exit(1); 441 } 442 if (bind(sock, ai_udp6->ai_addr, 443 ai_udp6->ai_addrlen) < 0) { 444 syslog(LOG_ERR, 445 "can't bind udp6 addr %s: %m", 446 bindhost[i]); 447 nfsd_exit(1); 448 } 449 freeaddrinfo(ai_udp6); 450 nfsdargs.sock = sock; 451 nfsdargs.name = NULL; 452 nfsdargs.namelen = 0; 453 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 454 syslog(LOG_ERR, 455 "can't add UDP6 socket"); 456 nfsd_exit(1); 457 } 458 (void)close(sock); 459 } 460 } 461 if (rpcbreg == 1) { 462 memset(&hints, 0, sizeof hints); 463 hints.ai_flags = AI_PASSIVE; 464 hints.ai_family = AF_INET6; 465 hints.ai_socktype = SOCK_DGRAM; 466 hints.ai_protocol = IPPROTO_UDP; 467 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); 468 if (ecode != 0) { 469 syslog(LOG_ERR, "getaddrinfo udp6: %s", 470 gai_strerror(ecode)); 471 nfsd_exit(1); 472 } 473 nconf_udp6 = getnetconfigent("udp6"); 474 if (nconf_udp6 == NULL) 475 err(1, "getnetconfigent udp6 failed"); 476 nb_udp6.buf = ai_udp6->ai_addr; 477 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; 478 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) || 479 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6))) 480 err(1, "rpcb_set udp6 failed"); 481 freeaddrinfo(ai_udp6); 482 } 483 } 484 485 /* Set up the socket for tcp and rpcb register it. */ 486 if (tcpflag) { 487 rpcbreg = 0; 488 for (i = 0; i < bindhostc; i++) { 489 memset(&hints, 0, sizeof hints); 490 hints.ai_flags = AI_PASSIVE; 491 hints.ai_family = AF_INET; 492 hints.ai_socktype = SOCK_STREAM; 493 hints.ai_protocol = IPPROTO_TCP; 494 if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) { 495 rpcbreg = 1; 496 rpcbregcnt++; 497 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 498 0)) < 0) { 499 syslog(LOG_ERR, 500 "can't create tpc socket"); 501 nfsd_exit(1); 502 } 503 if (setsockopt(tcpsock, SOL_SOCKET, 504 SO_REUSEADDR, 505 (char *)&on, sizeof(on)) < 0) 506 syslog(LOG_ERR, 507 "setsockopt SO_REUSEADDR: %m"); 508 if (bind(tcpsock, ai_tcp->ai_addr, 509 ai_tcp->ai_addrlen) < 0) { 510 syslog(LOG_ERR, 511 "can't bind tcp addr %s: %m", 512 bindhost[i]); 513 nfsd_exit(1); 514 } 515 if (listen(tcpsock, 5) < 0) { 516 syslog(LOG_ERR, "listen failed"); 517 nfsd_exit(1); 518 } 519 freeaddrinfo(ai_tcp); 520 FD_SET(tcpsock, &sockbits); 521 FD_SET(tcpsock, &v4bits); 522 maxsock = tcpsock; 523 connect_type_cnt++; 524 } 525 } 526 if (rpcbreg == 1) { 527 memset(&hints, 0, sizeof hints); 528 hints.ai_flags = AI_PASSIVE; 529 hints.ai_family = AF_INET; 530 hints.ai_socktype = SOCK_STREAM; 531 hints.ai_protocol = IPPROTO_TCP; 532 ecode = getaddrinfo(NULL, "nfs", &hints, 533 &ai_tcp); 534 if (ecode != 0) { 535 syslog(LOG_ERR, "getaddrinfo tcp: %s", 536 gai_strerror(ecode)); 537 nfsd_exit(1); 538 } 539 nconf_tcp = getnetconfigent("tcp"); 540 if (nconf_tcp == NULL) 541 err(1, "getnetconfigent tcp failed"); 542 nb_tcp.buf = ai_tcp->ai_addr; 543 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; 544 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, 545 &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3, 546 nconf_tcp, &nb_tcp))) 547 err(1, "rpcb_set tcp failed"); 548 freeaddrinfo(ai_tcp); 549 } 550 } 551 552 /* Set up the socket for tcp6 and rpcb register it. */ 553 if (tcpflag && ip6flag) { 554 rpcbreg = 0; 555 for (i = 0; i < bindhostc; i++) { 556 memset(&hints, 0, sizeof hints); 557 hints.ai_flags = AI_PASSIVE; 558 hints.ai_family = AF_INET6; 559 hints.ai_socktype = SOCK_STREAM; 560 hints.ai_protocol = IPPROTO_TCP; 561 if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) { 562 rpcbreg = 1; 563 rpcbregcnt++; 564 if ((tcp6sock = socket(ai_tcp6->ai_family, 565 ai_tcp6->ai_socktype, 566 ai_tcp6->ai_protocol)) < 0) { 567 syslog(LOG_ERR, 568 "can't create tcp6 socket"); 569 nfsd_exit(1); 570 } 571 if (setsockopt(tcp6sock, SOL_SOCKET, 572 SO_REUSEADDR, 573 (char *)&on, sizeof(on)) < 0) 574 syslog(LOG_ERR, 575 "setsockopt SO_REUSEADDR: %m"); 576 if (setsockopt(tcp6sock, IPPROTO_IPV6, 577 IPV6_V6ONLY, &on, sizeof on) < 0) { 578 syslog(LOG_ERR, 579 "can't set v6-only binding for tcp6 " 580 "socket: %m"); 581 nfsd_exit(1); 582 } 583 if (bind(tcp6sock, ai_tcp6->ai_addr, 584 ai_tcp6->ai_addrlen) < 0) { 585 syslog(LOG_ERR, 586 "can't bind tcp6 addr %s: %m", 587 bindhost[i]); 588 nfsd_exit(1); 589 } 590 if (listen(tcp6sock, 5) < 0) { 591 syslog(LOG_ERR, "listen failed"); 592 nfsd_exit(1); 593 } 594 freeaddrinfo(ai_tcp6); 595 FD_SET(tcp6sock, &sockbits); 596 FD_SET(tcp6sock, &v6bits); 597 if (maxsock < tcp6sock) 598 maxsock = tcp6sock; 599 connect_type_cnt++; 600 } 601 } 602 if (rpcbreg == 1) { 603 memset(&hints, 0, sizeof hints); 604 hints.ai_flags = AI_PASSIVE; 605 hints.ai_family = AF_INET6; 606 hints.ai_socktype = SOCK_STREAM; 607 hints.ai_protocol = IPPROTO_TCP; 608 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); 609 if (ecode != 0) { 610 syslog(LOG_ERR, "getaddrinfo tcp6: %s", 611 gai_strerror(ecode)); 612 nfsd_exit(1); 613 } 614 nconf_tcp6 = getnetconfigent("tcp6"); 615 if (nconf_tcp6 == NULL) 616 err(1, "getnetconfigent tcp6 failed"); 617 nb_tcp6.buf = ai_tcp6->ai_addr; 618 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; 619 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) || 620 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6))) 621 err(1, "rpcb_set tcp6 failed"); 622 freeaddrinfo(ai_tcp6); 623 } 624 } 625 626 if (rpcbregcnt == 0) { 627 syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m"); 628 nfsd_exit(1); 629 } 630 631 if (tcpflag && connect_type_cnt == 0) { 632 syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m"); 633 nfsd_exit(1); 634 } 635 636 setproctitle("master"); 637 /* 638 * We always want a master to have a clean way to to shut nfsd down 639 * (with unregistration): if the master is killed, it unregisters and 640 * kills all children. If we run for UDP only (and so do not have to 641 * loop waiting waiting for accept), we instead make the parent 642 * a "server" too. start_server will not return. 643 */ 644 if (!tcpflag) 645 start_server(1); 646 647 /* 648 * Loop forever accepting connections and passing the sockets 649 * into the kernel for the mounts. 650 */ 651 for (;;) { 652 ready = sockbits; 653 if (connect_type_cnt > 1) { 654 if (select(maxsock + 1, 655 &ready, NULL, NULL, NULL) < 1) { 656 syslog(LOG_ERR, "select failed: %m"); 657 if (errno == EINTR) 658 continue; 659 nfsd_exit(1); 660 } 661 } 662 for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) { 663 if (FD_ISSET(tcpsock, &ready)) { 664 if (FD_ISSET(tcpsock, &v4bits)) { 665 len = sizeof(inetpeer); 666 if ((msgsock = accept(tcpsock, 667 (struct sockaddr *)&inetpeer, &len)) < 0) { 668 syslog(LOG_ERR, "accept failed: %m"); 669 if (errno == ECONNABORTED || 670 errno == EINTR) 671 continue; 672 nfsd_exit(1); 673 } 674 memset(inetpeer.sin_zero, 0, 675 sizeof(inetpeer.sin_zero)); 676 if (setsockopt(msgsock, SOL_SOCKET, 677 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 678 syslog(LOG_ERR, 679 "setsockopt SO_KEEPALIVE: %m"); 680 nfsdargs.sock = msgsock; 681 nfsdargs.name = (caddr_t)&inetpeer; 682 nfsdargs.namelen = len; 683 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 684 (void)close(msgsock); 685 } else if (FD_ISSET(tcpsock, &v6bits)) { 686 len = sizeof(inet6peer); 687 if ((msgsock = accept(tcpsock, 688 (struct sockaddr *)&inet6peer, 689 &len)) < 0) { 690 syslog(LOG_ERR, 691 "accept failed: %m"); 692 if (errno == ECONNABORTED || 693 errno == EINTR) 694 continue; 695 nfsd_exit(1); 696 } 697 if (setsockopt(msgsock, SOL_SOCKET, 698 SO_KEEPALIVE, (char *)&on, 699 sizeof(on)) < 0) 700 syslog(LOG_ERR, "setsockopt " 701 "SO_KEEPALIVE: %m"); 702 nfsdargs.sock = msgsock; 703 nfsdargs.name = (caddr_t)&inet6peer; 704 nfsdargs.namelen = len; 705 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 706 (void)close(msgsock); 707 } 708 } 709 } 710 } 711 } 712 713 int 714 setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints) 715 { 716 int ecode; 717 u_int32_t host_addr[4]; /* IPv4 or IPv6 */ 718 const char *hostptr; 719 720 if (bindhost == NULL || strcmp("*", bindhost) == 0) 721 hostptr = NULL; 722 else 723 hostptr = bindhost; 724 725 if (hostptr != NULL) { 726 switch (hints.ai_family) { 727 case AF_INET: 728 if (inet_pton(AF_INET, hostptr, host_addr) == 1) { 729 hints.ai_flags = AI_NUMERICHOST; 730 } else { 731 if (inet_pton(AF_INET6, hostptr, 732 host_addr) == 1) 733 return (1); 734 } 735 break; 736 case AF_INET6: 737 if (inet_pton(AF_INET6, hostptr, host_addr) == 1) { 738 hints.ai_flags = AI_NUMERICHOST; 739 } else { 740 if (inet_pton(AF_INET, hostptr, 741 host_addr) == 1) 742 return (1); 743 } 744 break; 745 default: 746 break; 747 } 748 } 749 750 ecode = getaddrinfo(hostptr, "nfs", &hints, ai); 751 if (ecode != 0) { 752 syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost, 753 gai_strerror(ecode)); 754 return (1); 755 } 756 return (0); 757 } 758 759 void 760 usage() 761 { 762 (void)fprintf(stderr, "usage: nfsd %s\n", USAGE); 763 exit(1); 764 } 765 766 void 767 nonfs(signo) 768 int signo; 769 { 770 syslog(LOG_ERR, "missing system call: NFS not available"); 771 } 772 773 void 774 reapchild(signo) 775 int signo; 776 { 777 pid_t pid; 778 int i; 779 780 while ((pid = wait3(NULL, WNOHANG, NULL)) > 0) { 781 for (i = 0; i < nfsdcnt; i++) 782 if (pid == children[i]) 783 children[i] = -1; 784 } 785 } 786 787 void 788 unregistration() 789 { 790 if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) || 791 (!rpcb_unset(RPCPROG_NFS, 3, NULL))) 792 syslog(LOG_ERR, "rpcb_unset failed"); 793 } 794 795 void 796 killchildren() 797 { 798 int i; 799 800 for (i = 0; i < nfsdcnt; i++) { 801 if (children[i] > 0) 802 kill(children[i], SIGKILL); 803 } 804 } 805 806 /* 807 * Cleanup master after SIGUSR1. 808 */ 809 void 810 cleanup(signo) 811 { 812 nfsd_exit(0); 813 } 814 815 /* 816 * Cleanup child after SIGUSR1. 817 */ 818 void 819 child_cleanup(signo) 820 { 821 exit(0); 822 } 823 824 void 825 nfsd_exit(int status) 826 { 827 killchildren(); 828 unregistration(); 829 exit(status); 830 } 831 832 void 833 start_server(int master) 834 { 835 int status; 836 837 status = 0; 838 if (nfssvc(NFSSVC_NFSD, NULL) < 0) { 839 syslog(LOG_ERR, "nfssvc: %m"); 840 status = 1; 841 } 842 if (master) 843 nfsd_exit(status); 844 else 845 exit(status); 846 } 847