nfsd.c revision 83688
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 38static 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 45static char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95"; 46#endif 47static const char rcsid[] = 48 "$FreeBSD: head/usr.sbin/nfsd/nfsd.c 83688 2001-09-20 02:18:06Z peter $"; 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 56#include <rpc/rpc.h> 57#include <rpc/pmap_clnt.h> 58 59#include <netdb.h> 60#include <arpa/inet.h> 61#include <nfs/rpcv2.h> 62#include <nfs/nfsproto.h> 63#include <nfsserver/nfs.h> 64 65#include <err.h> 66#include <errno.h> 67#include <stdio.h> 68#include <stdlib.h> 69#include <strings.h> 70#include <unistd.h> 71#include <netdb.h> 72 73/* Global defs */ 74#ifdef DEBUG 75#define syslog(e, s) fprintf(stderr,(s)) 76int debug = 1; 77#else 78int debug = 0; 79#endif 80 81struct nfsd_srvargs nsd; 82 83#define MAXNFSDCNT 20 84#define DEFNFSDCNT 4 85pid_t children[MAXNFSDCNT]; /* PIDs of children */ 86int nfsdcnt; /* number of children */ 87 88void cleanup(int); 89void killchildren(void); 90void nonfs (int); 91void reapchild (int); 92int setbindhost (struct addrinfo **ia, const char *bindhost, struct addrinfo hints); 93void unregistration (void); 94void usage (void); 95 96/* 97 * Nfs server daemon mostly just a user context for nfssvc() 98 * 99 * 1 - do file descriptor and signal cleanup 100 * 2 - fork the nfsd(s) 101 * 3 - create server socket(s) 102 * 4 - register socket with rpcbind 103 * 104 * For connectionless protocols, just pass the socket into the kernel via. 105 * nfssvc(). 106 * For connection based sockets, loop doing accepts. When you get a new 107 * socket from accept, pass the msgsock into the kernel via. nfssvc(). 108 * The arguments are: 109 * -r - reregister with rpcbind 110 * -d - unregister with rpcbind 111 * -t - support tcp nfs clients 112 * -u - support udp nfs clients 113 * followed by "n" which is the number of nfsds' to fork off 114 */ 115int 116main(argc, argv, envp) 117 int argc; 118 char *argv[], *envp[]; 119{ 120 struct nfsd_args nfsdargs; 121 struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints; 122 struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6; 123 struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6; 124 struct sockaddr_in inetpeer; 125 struct sockaddr_in6 inet6peer; 126 fd_set ready, sockbits; 127 fd_set v4bits, v6bits; 128 int ch, connect_type_cnt, i, len, maxsock, msgsock; 129 int nfssvc_flag, on = 1, unregister, reregister, sock; 130 int tcp6sock, ip6flag, tcpflag, tcpsock; 131 int udpflag, ecode, s; 132 int bindhostc = 0, bindanyflag, rpcbreg, rpcbregcnt; 133 char **bindhost = NULL; 134 pid_t pid; 135 int error; 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 serveris not available"); 141 } 142 143 nfsdcnt = DEFNFSDCNT; 144 unregister = reregister = tcpflag = 0; 145 bindanyflag = udpflag; 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 (void)signal(SIGSYS, nonfs); 317 (void)signal(SIGUSR1, cleanup); 318 /* 319 * nfsd sits in the kernel most of the time. It needs 320 * to ignore SIGTERM/SIGQUIT in order to stay alive as long 321 * as possible during a shutdown, otherwise loopback 322 * mounts will not be able to unmount. 323 */ 324 (void)signal(SIGTERM, SIG_IGN); 325 (void)signal(SIGQUIT, SIG_IGN); 326 } 327 (void)signal(SIGCHLD, reapchild); 328 329 openlog("nfsd:", LOG_PID, LOG_DAEMON); 330 331 for (i = 0; i < nfsdcnt; i++) { 332 switch ((pid = fork())) { 333 case -1: 334 syslog(LOG_ERR, "fork: %m"); 335 killchildren(); 336 exit (1); 337 case 0: 338 break; 339 default: 340 children[i] = pid; 341 continue; 342 } 343 344 setproctitle("server"); 345 nfssvc_flag = NFSSVC_NFSD; 346 nsd.nsd_nfsd = NULL; 347 while (nfssvc(nfssvc_flag, &nsd) < 0) { 348 if (errno) { 349 syslog(LOG_ERR, "nfssvc: %m"); 350 exit(1); 351 } 352 nfssvc_flag = NFSSVC_NFSD; 353 } 354 exit(0); 355 } 356 357 if (atexit(killchildren) == -1) { 358 syslog(LOG_ERR, "atexit: %s", strerror(errno)); 359 exit(1); 360 } 361 FD_ZERO(&v4bits); 362 FD_ZERO(&v6bits); 363 364 rpcbregcnt = 0; 365 /* Set up the socket for udp and rpcb register it. */ 366 if (udpflag) { 367 rpcbreg = 0; 368 for (i = 0; i < bindhostc; i++) { 369 memset(&hints, 0, sizeof hints); 370 hints.ai_flags = AI_PASSIVE; 371 hints.ai_family = AF_INET; 372 hints.ai_socktype = SOCK_DGRAM; 373 hints.ai_protocol = IPPROTO_UDP; 374 if (setbindhost(&ai_udp, bindhost[i], hints) == 0) { 375 rpcbreg = 1; 376 rpcbregcnt++; 377 if ((sock = socket(ai_udp->ai_family, 378 ai_udp->ai_socktype, 379 ai_udp->ai_protocol)) < 0) { 380 syslog(LOG_ERR, 381 "can't create udp socket"); 382 exit(1); 383 } 384 if (bind(sock, ai_udp->ai_addr, 385 ai_udp->ai_addrlen) < 0) { 386 syslog(LOG_ERR, 387 "can't bind udp addr %s: %m", 388 bindhost[i]); 389 exit(1); 390 } 391 freeaddrinfo(ai_udp); 392 nfsdargs.sock = sock; 393 nfsdargs.name = NULL; 394 nfsdargs.namelen = 0; 395 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 396 syslog(LOG_ERR, "can't Add UDP socket"); 397 exit(1); 398 } 399 (void)close(sock); 400 } 401 } 402 if (rpcbreg == 1) { 403 memset(&hints, 0, sizeof hints); 404 hints.ai_flags = AI_PASSIVE; 405 hints.ai_family = AF_INET; 406 hints.ai_socktype = SOCK_DGRAM; 407 hints.ai_protocol = IPPROTO_UDP; 408 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); 409 if (ecode != 0) { 410 syslog(LOG_ERR, "getaddrinfo udp: %s", 411 gai_strerror(ecode)); 412 exit(1); 413 } 414 nconf_udp = getnetconfigent("udp"); 415 if (nconf_udp == NULL) 416 err(1, "getnetconfigent udp failed"); 417 nb_udp.buf = ai_udp->ai_addr; 418 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; 419 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) || 420 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp))) 421 err(1, "rpcb_set udp failed"); 422 freeaddrinfo(ai_udp); 423 } 424 } 425 426 /* Set up the socket for udp6 and rpcb register it. */ 427 if (udpflag && ip6flag) { 428 rpcbreg = 0; 429 for (i = 0; i < bindhostc; i++) { 430 memset(&hints, 0, sizeof hints); 431 hints.ai_flags = AI_PASSIVE; 432 hints.ai_family = AF_INET6; 433 hints.ai_socktype = SOCK_DGRAM; 434 hints.ai_protocol = IPPROTO_UDP; 435 if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) { 436 rpcbreg = 1; 437 rpcbregcnt++; 438 if ((sock = socket(ai_udp6->ai_family, 439 ai_udp6->ai_socktype, 440 ai_udp6->ai_protocol)) < 0) { 441 syslog(LOG_ERR, 442 "can't create udp6 socket"); 443 exit(1); 444 } 445 if (setsockopt(sock, IPPROTO_IPV6, 446 IPV6_BINDV6ONLY, 447 &on, sizeof on) < 0) { 448 syslog(LOG_ERR, 449 "can't set v6-only binding for " 450 "udp6 socket: %m"); 451 exit(1); 452 } 453 if (bind(sock, ai_udp6->ai_addr, 454 ai_udp6->ai_addrlen) < 0) { 455 syslog(LOG_ERR, 456 "can't bind udp6 addr %s: %m", 457 bindhost[i]); 458 exit(1); 459 } 460 freeaddrinfo(ai_udp6); 461 nfsdargs.sock = sock; 462 nfsdargs.name = NULL; 463 nfsdargs.namelen = 0; 464 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 465 syslog(LOG_ERR, 466 "can't add UDP6 socket"); 467 exit(1); 468 } 469 (void)close(sock); 470 } 471 } 472 if (rpcbreg == 1) { 473 memset(&hints, 0, sizeof hints); 474 hints.ai_flags = AI_PASSIVE; 475 hints.ai_family = AF_INET6; 476 hints.ai_socktype = SOCK_DGRAM; 477 hints.ai_protocol = IPPROTO_UDP; 478 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); 479 if (ecode != 0) { 480 syslog(LOG_ERR, "getaddrinfo udp6: %s", 481 gai_strerror(ecode)); 482 exit(1); 483 } 484 nconf_udp6 = getnetconfigent("udp6"); 485 if (nconf_udp6 == NULL) 486 err(1, "getnetconfigent udp6 failed"); 487 nb_udp6.buf = ai_udp6->ai_addr; 488 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; 489 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) || 490 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6))) 491 err(1, "rpcb_set udp6 failed"); 492 freeaddrinfo(ai_udp6); 493 } 494 } 495 496 /* Set up the socket for tcp and rpcb register it. */ 497 if (tcpflag) { 498 rpcbreg = 0; 499 for (i = 0; i < bindhostc; i++) { 500 memset(&hints, 0, sizeof hints); 501 hints.ai_flags = AI_PASSIVE; 502 hints.ai_family = AF_INET; 503 hints.ai_socktype = SOCK_STREAM; 504 hints.ai_protocol = IPPROTO_TCP; 505 if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) { 506 rpcbreg = 1; 507 rpcbregcnt++; 508 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 509 0)) < 0) { 510 syslog(LOG_ERR, 511 "can't create tpc socket"); 512 exit(1); 513 } 514 if (setsockopt(tcpsock, SOL_SOCKET, 515 SO_REUSEADDR, 516 (char *)&on, sizeof(on)) < 0) 517 syslog(LOG_ERR, 518 "setsockopt SO_REUSEADDR: %m"); 519 if (bind(tcpsock, ai_tcp->ai_addr, 520 ai_tcp->ai_addrlen) < 0) { 521 syslog(LOG_ERR, 522 "can't bind tcp addr %s: %m", 523 bindhost[i]); 524 exit(1); 525 } 526 if (listen(tcpsock, 5) < 0) { 527 syslog(LOG_ERR, "listen failed"); 528 exit(1); 529 } 530 freeaddrinfo(ai_tcp); 531 FD_SET(tcpsock, &sockbits); 532 FD_SET(tcpsock, &v4bits); 533 maxsock = tcpsock; 534 connect_type_cnt++; 535 } 536 } 537 if (rpcbreg == 1) { 538 memset(&hints, 0, sizeof hints); 539 hints.ai_flags = AI_PASSIVE; 540 hints.ai_family = AF_INET; 541 hints.ai_socktype = SOCK_STREAM; 542 hints.ai_protocol = IPPROTO_TCP; 543 ecode = getaddrinfo(NULL, "nfs", &hints, 544 &ai_tcp); 545 if (ecode != 0) { 546 syslog(LOG_ERR, "getaddrinfo tcp: %s", 547 gai_strerror(ecode)); 548 exit(1); 549 } 550 nconf_tcp = getnetconfigent("tcp"); 551 if (nconf_tcp == NULL) 552 err(1, "getnetconfigent tcp failed"); 553 nb_tcp.buf = ai_tcp->ai_addr; 554 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; 555 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, 556 &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3, 557 nconf_tcp, &nb_tcp))) 558 err(1, "rpcb_set tcp failed"); 559 freeaddrinfo(ai_tcp); 560 } 561 } 562 563 /* Set up the socket for tcp6 and rpcb register it. */ 564 if (tcpflag && ip6flag) { 565 rpcbreg = 0; 566 for (i = 0; i < bindhostc; i++) { 567 memset(&hints, 0, sizeof hints); 568 hints.ai_flags = AI_PASSIVE; 569 hints.ai_family = AF_INET6; 570 hints.ai_socktype = SOCK_STREAM; 571 hints.ai_protocol = IPPROTO_TCP; 572 if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) { 573 rpcbreg = 1; 574 rpcbregcnt++; 575 if ((tcp6sock = socket(ai_tcp6->ai_family, 576 ai_tcp6->ai_socktype, 577 ai_tcp6->ai_protocol)) < 0) { 578 syslog(LOG_ERR, 579 "can't create tcp6 socket"); 580 exit(1); 581 } 582 if (setsockopt(tcp6sock, SOL_SOCKET, 583 SO_REUSEADDR, 584 (char *)&on, sizeof(on)) < 0) 585 syslog(LOG_ERR, 586 "setsockopt SO_REUSEADDR: %m"); 587 if (setsockopt(tcp6sock, IPPROTO_IPV6, 588 IPV6_BINDV6ONLY, &on, sizeof on) < 0) { 589 syslog(LOG_ERR, 590 "can't set v6-only binding for tcp6 " 591 "socket: %m"); 592 exit(1); 593 } 594 if (bind(tcp6sock, ai_tcp6->ai_addr, 595 ai_tcp6->ai_addrlen) < 0) { 596 syslog(LOG_ERR, 597 "can't bind tcp6 addr %s: %m", 598 bindhost[i]); 599 exit(1); 600 } 601 if (listen(tcp6sock, 5) < 0) { 602 syslog(LOG_ERR, "listen failed"); 603 exit(1); 604 } 605 freeaddrinfo(ai_tcp6); 606 FD_SET(tcp6sock, &sockbits); 607 FD_SET(tcp6sock, &v6bits); 608 if (maxsock < tcp6sock) 609 maxsock = tcp6sock; 610 connect_type_cnt++; 611 } 612 } 613 if (rpcbreg == 1) { 614 memset(&hints, 0, sizeof hints); 615 hints.ai_flags = AI_PASSIVE; 616 hints.ai_family = AF_INET6; 617 hints.ai_socktype = SOCK_STREAM; 618 hints.ai_protocol = IPPROTO_TCP; 619 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); 620 if (ecode != 0) { 621 syslog(LOG_ERR, "getaddrinfo tcp6: %s", 622 gai_strerror(ecode)); 623 exit(1); 624 } 625 nconf_tcp6 = getnetconfigent("tcp6"); 626 if (nconf_tcp6 == NULL) 627 err(1, "getnetconfigent tcp6 failed"); 628 nb_tcp6.buf = ai_tcp6->ai_addr; 629 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; 630 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) || 631 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6))) 632 err(1, "rpcb_set tcp6 failed"); 633 freeaddrinfo(ai_tcp6); 634 } 635 } 636 637 if (rpcbregcnt == 0) { 638 syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m"); 639 exit(1); 640 } 641 642 if ((tcpflag) && (connect_type_cnt == 0)) { 643 syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m"); 644 exit(1); 645 } 646 647 setproctitle("master"); 648 649 /* 650 * Loop forever accepting connections and passing the sockets 651 * into the kernel for the mounts. 652 */ 653 for (;;) { 654 ready = sockbits; 655 if (connect_type_cnt > 1) { 656 if (select(maxsock + 1, 657 &ready, NULL, NULL, NULL) < 1) { 658 syslog(LOG_ERR, "select failed: %m"); 659 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 exit(1); 670 } 671 memset(inetpeer.sin_zero, 0, 672 sizeof(inetpeer.sin_zero)); 673 if (setsockopt(msgsock, SOL_SOCKET, 674 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 675 syslog(LOG_ERR, 676 "setsockopt SO_KEEPALIVE: %m"); 677 nfsdargs.sock = msgsock; 678 nfsdargs.name = (caddr_t)&inetpeer; 679 nfsdargs.namelen = sizeof(inetpeer); 680 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 681 (void)close(msgsock); 682 } else if (FD_ISSET(tcpsock, &v6bits)) { 683 len = sizeof(inet6peer); 684 if ((msgsock = accept(tcpsock, 685 (struct sockaddr *)&inet6peer, 686 &len)) < 0) { 687 syslog(LOG_ERR, 688 "accept failed: %m"); 689 exit(1); 690 } 691 if (setsockopt(msgsock, SOL_SOCKET, 692 SO_KEEPALIVE, (char *)&on, 693 sizeof(on)) < 0) 694 syslog(LOG_ERR, "setsockopt " 695 "SO_KEEPALIVE: %m"); 696 nfsdargs.sock = msgsock; 697 nfsdargs.name = (caddr_t)&inet6peer; 698 nfsdargs.namelen = sizeof(inet6peer); 699 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 700 (void)close(msgsock); 701 } 702 } 703 } 704 } 705} 706 707int 708setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints) 709{ 710 int ecode; 711 u_int32_t host_addr[4]; /* IPv4 or IPv6 */ 712 const char *hostptr; 713 714 if (bindhost == NULL || strcmp("*", bindhost) == 0) 715 hostptr = NULL; 716 else 717 hostptr = bindhost; 718 719 if (hostptr != NULL) { 720 switch (hints.ai_family) { 721 case AF_INET: 722 if (inet_pton(AF_INET, hostptr, host_addr) == 1) { 723 hints.ai_flags = AI_NUMERICHOST; 724 } else { 725 if (inet_pton(AF_INET6, hostptr, 726 host_addr) == 1) 727 return (1); 728 } 729 break; 730 case AF_INET6: 731 if (inet_pton(AF_INET6, hostptr, host_addr) == 1) { 732 hints.ai_flags = AI_NUMERICHOST; 733 } else { 734 if (inet_pton(AF_INET, hostptr, 735 host_addr) == 1) 736 return (1); 737 } 738 break; 739 default: 740 } 741 } 742 743 ecode = getaddrinfo(hostptr, "nfs", &hints, ai); 744 if (ecode != 0) { 745 syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost, 746 gai_strerror(ecode)); 747 return (1); 748 } 749 return (0); 750} 751 752void 753usage() 754{ 755 (void)fprintf(stderr, "usage: nfsd %s\n", USAGE); 756 exit(1); 757} 758 759void 760nonfs(signo) 761 int signo; 762{ 763 syslog(LOG_ERR, "missing system call: NFS not available"); 764} 765 766void 767reapchild(signo) 768 int signo; 769{ 770 771 while (wait3(NULL, WNOHANG, NULL) > 0); 772} 773 774void 775unregistration() 776{ 777 if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) || 778 (!rpcb_unset(RPCPROG_NFS, 3, NULL))) 779 syslog(LOG_ERR, "rpcb_unset failed"); 780} 781 782void 783killchildren() 784{ 785 int i; 786 sigset_t sigs; 787 788 sigemptyset(&sigs); 789 /* 790 * Block SIGCHLD to avoid killing a reaped process (although it is 791 * unlikely, the pid might have been reused). 792 */ 793 sigaddset(&sigs, SIGCHLD); 794 if (sigprocmask(SIG_BLOCK, &sigs, NULL) == -1) { 795 syslog(LOG_ERR, "sigprocmask: %s", 796 strerror(errno)); 797 return; 798 } 799 for (i = 0; i < nfsdcnt; i++) { 800 if (children[i] > 0) 801 kill(children[i], SIGKILL); 802 } 803 if (sigprocmask(SIG_UNBLOCK, &sigs, NULL) == -1) { 804 syslog(LOG_ERR, "sigprocmask: %s", strerror(errno)); 805 } 806 unregistration(); 807} 808 809void 810cleanup(signo) 811{ 812 killchildren(); 813 exit (0); 814} 815