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