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 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #ifndef lint 38 static const char copyright[] = 39 "@(#) Copyright (c) 1989, 1993, 1994\n\ 40 The Regents of the University of California. All rights reserved.\n"; 41 #endif /* not lint */ 42 43 #ifndef lint 44 #if 0 45 static char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95"; 46 #endif 47 static const char rcsid[] = 48 "$FreeBSD$"; 49 #endif /* not lint */ 50 51 #include <sys/param.h> 52 #include <sys/syslog.h> 53 #include <sys/wait.h> 54 #include <sys/mount.h> 55 #include <sys/linker.h> 56 #include <sys/module.h> 57 58 #include <rpc/rpc.h> 59 #include <rpc/pmap_clnt.h> 60 61 #include <netdb.h> 62 #include <arpa/inet.h> 63 #include <nfs/rpcv2.h> 64 #include <nfs/nfsproto.h> 65 #include <nfsserver/nfs.h> 66 67 #include <err.h> 68 #include <errno.h> 69 #include <signal.h> 70 #include <stdio.h> 71 #include <stdlib.h> 72 #include <string.h> 73 #include <unistd.h> 74 #include <netdb.h> 75 76 /* Global defs */ 77 #ifdef DEBUG 78 #define syslog(e, s...) fprintf(stderr,s) 79 int debug = 1; 80 #else 81 int debug = 0; 82 #endif 83 84 struct nfsd_srvargs nsd; 85 86 #define MAXNFSDCNT 20 87 #define DEFNFSDCNT 4 88 pid_t children[MAXNFSDCNT]; /* PIDs of children */ 89 int nfsdcnt; /* number of children */ 90 91 void cleanup(int); 92 void child_cleanup(int); 93 void killchildren(void); 94 void nfsd_exit(int); 95 void nonfs(int); 96 void reapchild(int); 97 int setbindhost(struct addrinfo **ia, const char *bindhost, 98 struct addrinfo hints); 99 void start_server(int); 100 void unregistration(void); 101 void usage(void); 102 103 /* 104 * Nfs server daemon mostly just a user context for nfssvc() 105 * 106 * 1 - do file descriptor and signal cleanup 107 * 2 - fork the nfsd(s) 108 * 3 - create server socket(s) 109 * 4 - register socket with rpcbind 110 * 111 * For connectionless protocols, just pass the socket into the kernel via. 112 * nfssvc(). 113 * For connection based sockets, loop doing accepts. When you get a new 114 * socket from accept, pass the msgsock into the kernel via. nfssvc(). 115 * The arguments are: 116 * -r - reregister with rpcbind 117 * -d - unregister with rpcbind 118 * -t - support tcp nfs clients 119 * -u - support udp nfs clients 120 * followed by "n" which is the number of nfsds' to fork off 121 */ 122 int 123 main(argc, argv, envp) 124 int argc; 125 char *argv[], *envp[]; 126 { 127 struct nfsd_args nfsdargs; 128 struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints; 129 struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6; 130 struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6; 131 struct sockaddr_in inetpeer; 132 struct sockaddr_in6 inet6peer; 133 fd_set ready, sockbits; 134 fd_set v4bits, v6bits; 135 int ch, connect_type_cnt, i, len, maxsock, msgsock; 136 int on = 1, unregister, reregister, sock; 137 int tcp6sock, ip6flag, tcpflag, tcpsock; 138 int udpflag, ecode, s, srvcnt; 139 int bindhostc, bindanyflag, rpcbreg, rpcbregcnt; 140 char **bindhost = NULL; 141 pid_t pid; 142 143 if (modfind("nfsserver") < 0) { 144 /* Not present in kernel, try loading it */ 145 if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0) 146 errx(1, "NFS server is not available"); 147 } 148 149 nfsdcnt = DEFNFSDCNT; 150 unregister = reregister = tcpflag = maxsock = 0; 151 bindanyflag = udpflag = connect_type_cnt = bindhostc = 0; 152 #define GETOPT "ah:n:rdtu" 153 #define USAGE "[-ardtu] [-n num_servers] [-h bindip]" 154 while ((ch = getopt(argc, argv, GETOPT)) != -1) 155 switch (ch) { 156 case 'a': 157 bindanyflag = 1; 158 break; 159 case 'n': 160 nfsdcnt = atoi(optarg); 161 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 162 warnx("nfsd count %d; reset to %d", nfsdcnt, 163 DEFNFSDCNT); 164 nfsdcnt = DEFNFSDCNT; 165 } 166 break; 167 case 'h': 168 bindhostc++; 169 bindhost = realloc(bindhost,sizeof(char *)*bindhostc); 170 if (bindhost == NULL) 171 errx(1, "Out of memory"); 172 bindhost[bindhostc-1] = strdup(optarg); 173 if (bindhost[bindhostc-1] == NULL) 174 errx(1, "Out of memory"); 175 break; 176 case 'r': 177 reregister = 1; 178 break; 179 case 'd': 180 unregister = 1; 181 break; 182 case 't': 183 tcpflag = 1; 184 break; 185 case 'u': 186 udpflag = 1; 187 break; 188 default: 189 case '?': 190 usage(); 191 }; 192 if (!tcpflag && !udpflag) 193 udpflag = 1; 194 argv += optind; 195 argc -= optind; 196 197 /* 198 * XXX 199 * Backward compatibility, trailing number is the count of daemons. 200 */ 201 if (argc > 1) 202 usage(); 203 if (argc == 1) { 204 nfsdcnt = atoi(argv[0]); 205 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 206 warnx("nfsd count %d; reset to %d", nfsdcnt, 207 DEFNFSDCNT); 208 nfsdcnt = DEFNFSDCNT; 209 } 210 } 211 212 ip6flag = 1; 213 s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 214 if (s == -1) { 215 if (errno != EPROTONOSUPPORT) 216 err(1, "socket"); 217 ip6flag = 0; 218 } else if (getnetconfigent("udp6") == NULL || 219 getnetconfigent("tcp6") == NULL) { 220 ip6flag = 0; 221 } 222 if (s != -1) 223 close(s); 224 225 if (bindhostc == 0 || bindanyflag) { 226 bindhostc++; 227 bindhost = realloc(bindhost,sizeof(char *)*bindhostc); 228 if (bindhost == NULL) 229 errx(1, "Out of memory"); 230 bindhost[bindhostc-1] = strdup("*"); 231 if (bindhost[bindhostc-1] == NULL) 232 errx(1, "Out of memory"); 233 } 234 235 if (unregister) { 236 unregistration(); 237 exit (0); 238 } 239 if (reregister) { 240 if (udpflag) { 241 memset(&hints, 0, sizeof hints); 242 hints.ai_flags = AI_PASSIVE; 243 hints.ai_family = AF_INET; 244 hints.ai_socktype = SOCK_DGRAM; 245 hints.ai_protocol = IPPROTO_UDP; 246 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); 247 if (ecode != 0) 248 err(1, "getaddrinfo udp: %s", gai_strerror(ecode)); 249 nconf_udp = getnetconfigent("udp"); 250 if (nconf_udp == NULL) 251 err(1, "getnetconfigent udp failed"); 252 nb_udp.buf = ai_udp->ai_addr; 253 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; 254 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) || 255 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp))) 256 err(1, "rpcb_set udp failed"); 257 freeaddrinfo(ai_udp); 258 } 259 if (udpflag && ip6flag) { 260 memset(&hints, 0, sizeof hints); 261 hints.ai_flags = AI_PASSIVE; 262 hints.ai_family = AF_INET6; 263 hints.ai_socktype = SOCK_DGRAM; 264 hints.ai_protocol = IPPROTO_UDP; 265 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); 266 if (ecode != 0) 267 err(1, "getaddrinfo udp6: %s", gai_strerror(ecode)); 268 nconf_udp6 = getnetconfigent("udp6"); 269 if (nconf_udp6 == NULL) 270 err(1, "getnetconfigent udp6 failed"); 271 nb_udp6.buf = ai_udp6->ai_addr; 272 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; 273 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) || 274 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6))) 275 err(1, "rpcb_set udp6 failed"); 276 freeaddrinfo(ai_udp6); 277 } 278 if (tcpflag) { 279 memset(&hints, 0, sizeof hints); 280 hints.ai_flags = AI_PASSIVE; 281 hints.ai_family = AF_INET; 282 hints.ai_socktype = SOCK_STREAM; 283 hints.ai_protocol = IPPROTO_TCP; 284 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp); 285 if (ecode != 0) 286 err(1, "getaddrinfo tcp: %s", gai_strerror(ecode)); 287 nconf_tcp = getnetconfigent("tcp"); 288 if (nconf_tcp == NULL) 289 err(1, "getnetconfigent tcp failed"); 290 nb_tcp.buf = ai_tcp->ai_addr; 291 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; 292 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) || 293 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp))) 294 err(1, "rpcb_set tcp failed"); 295 freeaddrinfo(ai_tcp); 296 } 297 if (tcpflag && ip6flag) { 298 memset(&hints, 0, sizeof hints); 299 hints.ai_flags = AI_PASSIVE; 300 hints.ai_family = AF_INET6; 301 hints.ai_socktype = SOCK_STREAM; 302 hints.ai_protocol = IPPROTO_TCP; 303 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); 304 if (ecode != 0) 305 err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode)); 306 nconf_tcp6 = getnetconfigent("tcp6"); 307 if (nconf_tcp6 == NULL) 308 err(1, "getnetconfigent tcp6 failed"); 309 nb_tcp6.buf = ai_tcp6->ai_addr; 310 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; 311 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) || 312 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6))) 313 err(1, "rpcb_set tcp6 failed"); 314 freeaddrinfo(ai_tcp6); 315 } 316 exit (0); 317 } 318 if (debug == 0) { 319 daemon(0, 0); 320 (void)signal(SIGHUP, SIG_IGN); 321 (void)signal(SIGINT, SIG_IGN); 322 /* 323 * nfsd sits in the kernel most of the time. It needs 324 * to ignore SIGTERM/SIGQUIT in order to stay alive as long 325 * as possible during a shutdown, otherwise loopback 326 * mounts will not be able to unmount. 327 */ 328 (void)signal(SIGTERM, SIG_IGN); 329 (void)signal(SIGQUIT, SIG_IGN); 330 } 331 (void)signal(SIGSYS, nonfs); 332 (void)signal(SIGCHLD, reapchild); 333 334 openlog("nfsd", LOG_PID, LOG_DAEMON); 335 336 /* If we use UDP only, we start the last server below. */ 337 srvcnt = tcpflag ? nfsdcnt : nfsdcnt - 1; 338 for (i = 0; i < srvcnt; i++) { 339 switch ((pid = fork())) { 340 case -1: 341 syslog(LOG_ERR, "fork: %m"); 342 nfsd_exit(1); 343 case 0: 344 break; 345 default: 346 children[i] = pid; 347 continue; 348 } 349 (void)signal(SIGUSR1, child_cleanup); 350 setproctitle("server"); 351 352 start_server(0); 353 } 354 355 (void)signal(SIGUSR1, cleanup); 356 FD_ZERO(&v4bits); 357 FD_ZERO(&v6bits); 358 359 rpcbregcnt = 0; 360 /* Set up the socket for udp and rpcb register it. */ 361 if (udpflag) { 362 rpcbreg = 0; 363 for (i = 0; i < bindhostc; i++) { 364 memset(&hints, 0, sizeof hints); 365 hints.ai_flags = AI_PASSIVE; 366 hints.ai_family = AF_INET; 367 hints.ai_socktype = SOCK_DGRAM; 368 hints.ai_protocol = IPPROTO_UDP; 369 if (setbindhost(&ai_udp, bindhost[i], hints) == 0) { 370 rpcbreg = 1; 371 rpcbregcnt++; 372 if ((sock = socket(ai_udp->ai_family, 373 ai_udp->ai_socktype, 374 ai_udp->ai_protocol)) < 0) { 375 syslog(LOG_ERR, 376 "can't create udp socket"); 377 nfsd_exit(1); 378 } 379 if (bind(sock, ai_udp->ai_addr, 380 ai_udp->ai_addrlen) < 0) { 381 syslog(LOG_ERR, 382 "can't bind udp addr %s: %m", 383 bindhost[i]); 384 nfsd_exit(1); 385 } 386 freeaddrinfo(ai_udp); 387 nfsdargs.sock = sock; 388 nfsdargs.name = NULL; 389 nfsdargs.namelen = 0; 390 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 391 syslog(LOG_ERR, "can't Add UDP socket"); 392 nfsd_exit(1); 393 } 394 (void)close(sock); 395 } 396 } 397 if (rpcbreg == 1) { 398 memset(&hints, 0, sizeof hints); 399 hints.ai_flags = AI_PASSIVE; 400 hints.ai_family = AF_INET; 401 hints.ai_socktype = SOCK_DGRAM; 402 hints.ai_protocol = IPPROTO_UDP; 403 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); 404 if (ecode != 0) { 405 syslog(LOG_ERR, "getaddrinfo udp: %s", 406 gai_strerror(ecode)); 407 nfsd_exit(1); 408 } 409 nconf_udp = getnetconfigent("udp"); 410 if (nconf_udp == NULL) 411 err(1, "getnetconfigent udp failed"); 412 nb_udp.buf = ai_udp->ai_addr; 413 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; 414 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) || 415 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp))) 416 err(1, "rpcb_set udp failed"); 417 freeaddrinfo(ai_udp); 418 } 419 } 420 421 /* Set up the socket for udp6 and rpcb register it. */ 422 if (udpflag && ip6flag) { 423 rpcbreg = 0; 424 for (i = 0; i < bindhostc; i++) { 425 memset(&hints, 0, sizeof hints); 426 hints.ai_flags = AI_PASSIVE; 427 hints.ai_family = AF_INET6; 428 hints.ai_socktype = SOCK_DGRAM; 429 hints.ai_protocol = IPPROTO_UDP; 430 if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) { 431 rpcbreg = 1; 432 rpcbregcnt++; 433 if ((sock = socket(ai_udp6->ai_family, 434 ai_udp6->ai_socktype, 435 ai_udp6->ai_protocol)) < 0) { 436 syslog(LOG_ERR, 437 "can't create udp6 socket"); 438 nfsd_exit(1); 439 } 440 if (setsockopt(sock, IPPROTO_IPV6, 441 IPV6_BINDV6ONLY, 442 &on, sizeof on) < 0) { 443 syslog(LOG_ERR, 444 "can't set v6-only binding for " 445 "udp6 socket: %m"); 446 nfsd_exit(1); 447 } 448 if (bind(sock, ai_udp6->ai_addr, 449 ai_udp6->ai_addrlen) < 0) { 450 syslog(LOG_ERR, 451 "can't bind udp6 addr %s: %m", 452 bindhost[i]); 453 nfsd_exit(1); 454 } 455 freeaddrinfo(ai_udp6); 456 nfsdargs.sock = sock; 457 nfsdargs.name = NULL; 458 nfsdargs.namelen = 0; 459 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 460 syslog(LOG_ERR, 461 "can't add UDP6 socket"); 462 nfsd_exit(1); 463 } 464 (void)close(sock); 465 } 466 } 467 if (rpcbreg == 1) { 468 memset(&hints, 0, sizeof hints); 469 hints.ai_flags = AI_PASSIVE; 470 hints.ai_family = AF_INET6; 471 hints.ai_socktype = SOCK_DGRAM; 472 hints.ai_protocol = IPPROTO_UDP; 473 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); 474 if (ecode != 0) { 475 syslog(LOG_ERR, "getaddrinfo udp6: %s", 476 gai_strerror(ecode)); 477 nfsd_exit(1); 478 } 479 nconf_udp6 = getnetconfigent("udp6"); 480 if (nconf_udp6 == NULL) 481 err(1, "getnetconfigent udp6 failed"); 482 nb_udp6.buf = ai_udp6->ai_addr; 483 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; 484 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) || 485 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6))) 486 err(1, "rpcb_set udp6 failed"); 487 freeaddrinfo(ai_udp6); 488 } 489 } 490 491 /* Set up the socket for tcp and rpcb register it. */ 492 if (tcpflag) { 493 rpcbreg = 0; 494 for (i = 0; i < bindhostc; i++) { 495 memset(&hints, 0, sizeof hints); 496 hints.ai_flags = AI_PASSIVE; 497 hints.ai_family = AF_INET; 498 hints.ai_socktype = SOCK_STREAM; 499 hints.ai_protocol = IPPROTO_TCP; 500 if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) { 501 rpcbreg = 1; 502 rpcbregcnt++; 503 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 504 0)) < 0) { 505 syslog(LOG_ERR, 506 "can't create tpc socket"); 507 nfsd_exit(1); 508 } 509 if (setsockopt(tcpsock, SOL_SOCKET, 510 SO_REUSEADDR, 511 (char *)&on, sizeof(on)) < 0) 512 syslog(LOG_ERR, 513 "setsockopt SO_REUSEADDR: %m"); 514 if (bind(tcpsock, ai_tcp->ai_addr, 515 ai_tcp->ai_addrlen) < 0) { 516 syslog(LOG_ERR, 517 "can't bind tcp addr %s: %m", 518 bindhost[i]); 519 nfsd_exit(1); 520 } 521 if (listen(tcpsock, 5) < 0) { 522 syslog(LOG_ERR, "listen failed"); 523 nfsd_exit(1); 524 } 525 freeaddrinfo(ai_tcp); 526 FD_SET(tcpsock, &sockbits); 527 FD_SET(tcpsock, &v4bits); 528 maxsock = tcpsock; 529 connect_type_cnt++; 530 } 531 } 532 if (rpcbreg == 1) { 533 memset(&hints, 0, sizeof hints); 534 hints.ai_flags = AI_PASSIVE; 535 hints.ai_family = AF_INET; 536 hints.ai_socktype = SOCK_STREAM; 537 hints.ai_protocol = IPPROTO_TCP; 538 ecode = getaddrinfo(NULL, "nfs", &hints, 539 &ai_tcp); 540 if (ecode != 0) { 541 syslog(LOG_ERR, "getaddrinfo tcp: %s", 542 gai_strerror(ecode)); 543 nfsd_exit(1); 544 } 545 nconf_tcp = getnetconfigent("tcp"); 546 if (nconf_tcp == NULL) 547 err(1, "getnetconfigent tcp failed"); 548 nb_tcp.buf = ai_tcp->ai_addr; 549 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; 550 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, 551 &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3, 552 nconf_tcp, &nb_tcp))) 553 err(1, "rpcb_set tcp failed"); 554 freeaddrinfo(ai_tcp); 555 } 556 } 557 558 /* Set up the socket for tcp6 and rpcb register it. */ 559 if (tcpflag && ip6flag) { 560 rpcbreg = 0; 561 for (i = 0; i < bindhostc; i++) { 562 memset(&hints, 0, sizeof hints); 563 hints.ai_flags = AI_PASSIVE; 564 hints.ai_family = AF_INET6; 565 hints.ai_socktype = SOCK_STREAM; 566 hints.ai_protocol = IPPROTO_TCP; 567 if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) { 568 rpcbreg = 1; 569 rpcbregcnt++; 570 if ((tcp6sock = socket(ai_tcp6->ai_family, 571 ai_tcp6->ai_socktype, 572 ai_tcp6->ai_protocol)) < 0) { 573 syslog(LOG_ERR, 574 "can't create tcp6 socket"); 575 nfsd_exit(1); 576 } 577 if (setsockopt(tcp6sock, SOL_SOCKET, 578 SO_REUSEADDR, 579 (char *)&on, sizeof(on)) < 0) 580 syslog(LOG_ERR, 581 "setsockopt SO_REUSEADDR: %m"); 582 if (setsockopt(tcp6sock, IPPROTO_IPV6, 583 IPV6_BINDV6ONLY, &on, sizeof on) < 0) { 584 syslog(LOG_ERR, 585 "can't set v6-only binding for tcp6 " 586 "socket: %m"); 587 nfsd_exit(1); 588 } 589 if (bind(tcp6sock, ai_tcp6->ai_addr, 590 ai_tcp6->ai_addrlen) < 0) { 591 syslog(LOG_ERR, 592 "can't bind tcp6 addr %s: %m", 593 bindhost[i]); 594 nfsd_exit(1); 595 } 596 if (listen(tcp6sock, 5) < 0) { 597 syslog(LOG_ERR, "listen failed"); 598 nfsd_exit(1); 599 } 600 freeaddrinfo(ai_tcp6); 601 FD_SET(tcp6sock, &sockbits); 602 FD_SET(tcp6sock, &v6bits); 603 if (maxsock < tcp6sock) 604 maxsock = tcp6sock; 605 connect_type_cnt++; 606 } 607 } 608 if (rpcbreg == 1) { 609 memset(&hints, 0, sizeof hints); 610 hints.ai_flags = AI_PASSIVE; 611 hints.ai_family = AF_INET6; 612 hints.ai_socktype = SOCK_STREAM; 613 hints.ai_protocol = IPPROTO_TCP; 614 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); 615 if (ecode != 0) { 616 syslog(LOG_ERR, "getaddrinfo tcp6: %s", 617 gai_strerror(ecode)); 618 nfsd_exit(1); 619 } 620 nconf_tcp6 = getnetconfigent("tcp6"); 621 if (nconf_tcp6 == NULL) 622 err(1, "getnetconfigent tcp6 failed"); 623 nb_tcp6.buf = ai_tcp6->ai_addr; 624 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; 625 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) || 626 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6))) 627 err(1, "rpcb_set tcp6 failed"); 628 freeaddrinfo(ai_tcp6); 629 } 630 } 631 632 if (rpcbregcnt == 0) { 633 syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m"); 634 nfsd_exit(1); 635 } 636 637 if (tcpflag && connect_type_cnt == 0) { 638 syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m"); 639 nfsd_exit(1); 640 } 641 642 setproctitle("master"); 643 /* 644 * We always want a master to have a clean way to to shut nfsd down 645 * (with unregistration): if the master is killed, it unregisters and 646 * kills all children. If we run for UDP only (and so do not have to 647 * loop waiting waiting for accept), we instead make the parent 648 * a "server" too. start_server will not return. 649 */ 650 if (!tcpflag) 651 start_server(1); 652 653 /* 654 * Loop forever accepting connections and passing the sockets 655 * into the kernel for the mounts. 656 */ 657 for (;;) { 658 ready = sockbits; 659 if (connect_type_cnt > 1) { 660 if (select(maxsock + 1, 661 &ready, NULL, NULL, NULL) < 1) { 662 syslog(LOG_ERR, "select failed: %m"); 663 nfsd_exit(1); 664 } 665 } 666 for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) { 667 if (FD_ISSET(tcpsock, &ready)) { 668 if (FD_ISSET(tcpsock, &v4bits)) { 669 len = sizeof(inetpeer); 670 if ((msgsock = accept(tcpsock, 671 (struct sockaddr *)&inetpeer, &len)) < 0) { 672 syslog(LOG_ERR, "accept failed: %m"); 673 nfsd_exit(1); 674 } 675 memset(inetpeer.sin_zero, 0, 676 sizeof(inetpeer.sin_zero)); 677 if (setsockopt(msgsock, SOL_SOCKET, 678 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 679 syslog(LOG_ERR, 680 "setsockopt SO_KEEPALIVE: %m"); 681 nfsdargs.sock = msgsock; 682 nfsdargs.name = (caddr_t)&inetpeer; 683 nfsdargs.namelen = len; 684 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 685 (void)close(msgsock); 686 } else if (FD_ISSET(tcpsock, &v6bits)) { 687 len = sizeof(inet6peer); 688 if ((msgsock = accept(tcpsock, 689 (struct sockaddr *)&inet6peer, 690 &len)) < 0) { 691 syslog(LOG_ERR, 692 "accept failed: %m"); 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(signo) 766 int signo; 767 { 768 syslog(LOG_ERR, "missing system call: NFS not available"); 769 } 770 771 void 772 reapchild(signo) 773 int signo; 774 { 775 pid_t pid; 776 int i; 777 778 while ((pid = wait3(NULL, WNOHANG, NULL)) > 0) { 779 for (i = 0; i < nfsdcnt; i++) 780 if (pid == children[i]) 781 children[i] = -1; 782 } 783 } 784 785 void 786 unregistration() 787 { 788 if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) || 789 (!rpcb_unset(RPCPROG_NFS, 3, NULL))) 790 syslog(LOG_ERR, "rpcb_unset failed"); 791 } 792 793 void 794 killchildren() 795 { 796 int i; 797 798 for (i = 0; i < nfsdcnt; i++) { 799 if (children[i] > 0) 800 kill(children[i], SIGKILL); 801 } 802 } 803 804 /* 805 * Cleanup master after SIGUSR1. 806 */ 807 void 808 cleanup(signo) 809 { 810 nfsd_exit(0); 811 } 812 813 /* 814 * Cleanup child after SIGUSR1. 815 */ 816 void 817 child_cleanup(signo) 818 { 819 exit(0); 820 } 821 822 void 823 nfsd_exit(int status) 824 { 825 killchildren(); 826 unregistration(); 827 exit(status); 828 } 829 830 void 831 start_server(int master) 832 { 833 int status; 834 835 status = 0; 836 nsd.nsd_nfsd = NULL; 837 if (nfssvc(NFSSVC_NFSD, &nsd) < 0) { 838 syslog(LOG_ERR, "nfssvc: %m"); 839 status = 1; 840 } 841 if (master) 842 nfsd_exit(status); 843 else 844 exit(status); 845 } 846