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