1 /* $NetBSD: nfsd.c,v 1.51 2007/07/11 04:59:19 yamt Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Rick Macklem at The University of Guelph. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 #ifndef lint 37 __COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\n\ 38 The Regents of the University of California. All rights reserved.\n"); 39 #endif /* not lint */ 40 41 #ifndef lint 42 #if 0 43 static char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95"; 44 #else 45 __RCSID("$NetBSD: nfsd.c,v 1.51 2007/07/11 04:59:19 yamt Exp $"); 46 #endif 47 #endif /* not lint */ 48 49 #include <sys/param.h> 50 #include <sys/ioctl.h> 51 #include <sys/stat.h> 52 #include <sys/wait.h> 53 #include <sys/uio.h> 54 #include <sys/ucred.h> 55 #include <sys/mount.h> 56 #include <sys/socket.h> 57 #include <sys/socketvar.h> 58 #include <poll.h> 59 60 #include <rpc/rpc.h> 61 #include <rpc/pmap_clnt.h> 62 #include <rpc/pmap_prot.h> 63 64 #ifdef ISO 65 #include <netiso/iso.h> 66 #endif 67 #include <nfs/rpcv2.h> 68 #include <nfs/nfsproto.h> 69 #include <nfs/nfs.h> 70 71 #include <err.h> 72 #include <errno.h> 73 #include <fcntl.h> 74 #include <grp.h> 75 #include <pwd.h> 76 #include <pthread.h> 77 #include <signal.h> 78 #include <stdio.h> 79 #include <stdlib.h> 80 #include <string.h> 81 #include <syslog.h> 82 #include <unistd.h> 83 #include <netdb.h> 84 85 /* Global defs */ 86 #ifdef DEBUG 87 #define syslog(e, s) fprintf(stderr,(s)) 88 int debug = 1; 89 #else 90 int debug = 0; 91 #endif 92 93 int main __P((int, char **)); 94 void nonfs __P((int)); 95 void usage __P((void)); 96 97 static void * 98 child(void *dummy) 99 { 100 struct nfsd_srvargs nsd; 101 int nfssvc_flag; 102 103 pthread_setname_np(pthread_self(), "slave", NULL); 104 nfssvc_flag = NFSSVC_NFSD; 105 memset(&nsd, 0, sizeof(nsd)); 106 while (nfssvc(nfssvc_flag, &nsd) < 0) { 107 if (errno != ENEEDAUTH) { 108 syslog(LOG_ERR, "nfssvc: %m"); 109 exit(1); 110 } 111 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; 112 } 113 114 return NULL; 115 } 116 117 /* 118 * Nfs server daemon mostly just a user context for nfssvc() 119 * 120 * 1 - do file descriptor and signal cleanup 121 * 2 - create the nfsd thread(s) 122 * 3 - create server socket(s) 123 * 4 - register socket with portmap 124 * 125 * For connectionless protocols, just pass the socket into the kernel via 126 * nfssvc(). 127 * For connection based sockets, loop doing accepts. When you get a new 128 * socket from accept, pass the msgsock into the kernel via nfssvc(). 129 * The arguments are: 130 * -c - support iso cltp clients 131 * -r - reregister with portmapper 132 * -t - support tcp nfs clients 133 * -u - support udp nfs clients 134 * followed by "n" which is the number of nfsd threads to create 135 */ 136 int 137 main(argc, argv) 138 int argc; 139 char *argv[]; 140 { 141 struct nfsd_args nfsdargs; 142 struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints; 143 struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6; 144 struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6; 145 struct sockaddr_in inetpeer; 146 struct sockaddr_in6 inet6peer; 147 #ifdef ISO 148 struct sockaddr_iso isoaddr, isopeer; 149 #endif 150 struct pollfd set[4]; 151 socklen_t len; 152 int ch, cltpflag, connect_type_cnt, i, maxsock, msgsock; 153 int nfsdcnt, on = 1, reregister, sock, tcpflag, tcpsock; 154 int tcp6sock, ip6flag; 155 int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag, ecode, s; 156 157 #define MAXNFSDCNT 1024 158 #define DEFNFSDCNT 4 159 nfsdcnt = DEFNFSDCNT; 160 cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0; 161 tpipflag = udpflag = ip6flag = 0; 162 nconf_udp = nconf_tcp = nconf_udp6 = nconf_tcp6 = NULL; 163 maxsock = 0; 164 tcpsock = tcp6sock = -1; 165 #ifdef ISO 166 #define GETOPT "6cn:rtu" 167 #define USAGE "[-crtu] [-n num_servers]" 168 #else 169 #define GETOPT "6n:rtu" 170 #define USAGE "[-rtu] [-n num_servers]" 171 #endif 172 while ((ch = getopt(argc, argv, GETOPT)) != -1) { 173 switch (ch) { 174 case '6': 175 ip6flag = 1; 176 s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); 177 if (s < 0 && (errno == EPROTONOSUPPORT || 178 errno == EPFNOSUPPORT || errno == EAFNOSUPPORT)) 179 ip6flag = 0; 180 else 181 close(s); 182 break; 183 case 'n': 184 nfsdcnt = atoi(optarg); 185 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 186 warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT); 187 nfsdcnt = DEFNFSDCNT; 188 } 189 break; 190 case 'r': 191 reregister = 1; 192 break; 193 case 't': 194 tcpflag = 1; 195 break; 196 case 'u': 197 udpflag = 1; 198 break; 199 #ifdef ISO 200 case 'c': 201 cltpflag = 1; 202 break; 203 #ifdef notyet 204 case 'i': 205 tp4cnt = 1; 206 break; 207 case 'p': 208 tpipcnt = 1; 209 break; 210 #endif /* notyet */ 211 #endif /* ISO */ 212 default: 213 case '?': 214 usage(); 215 }; 216 } 217 argv += optind; 218 argc -= optind; 219 220 /* 221 * XXX 222 * Backward compatibility, trailing number is the count of daemons. 223 */ 224 if (argc > 1) 225 usage(); 226 if (argc == 1) { 227 nfsdcnt = atoi(argv[0]); 228 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 229 warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT); 230 nfsdcnt = DEFNFSDCNT; 231 } 232 } 233 234 /* 235 * If none of TCP or UDP are specified, default to UDP only. 236 */ 237 if (tcpflag == 0 && udpflag == 0) 238 udpflag = 1; 239 240 if (debug == 0) { 241 daemon(0, 0); 242 (void)signal(SIGHUP, SIG_IGN); 243 (void)signal(SIGINT, SIG_IGN); 244 (void)signal(SIGQUIT, SIG_IGN); 245 (void)signal(SIGSYS, nonfs); 246 } 247 248 if (udpflag) { 249 memset(&hints, 0, sizeof hints); 250 hints.ai_flags = AI_PASSIVE; 251 hints.ai_family = PF_INET; 252 hints.ai_socktype = SOCK_DGRAM; 253 hints.ai_protocol = IPPROTO_UDP; 254 255 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); 256 if (ecode != 0) { 257 syslog(LOG_ERR, "getaddrinfo udp: %s", 258 gai_strerror(ecode)); 259 exit(1); 260 } 261 262 nconf_udp = getnetconfigent("udp"); 263 264 if (nconf_udp == NULL) 265 err(1, "getnetconfigent udp failed"); 266 267 nb_udp.buf = ai_udp->ai_addr; 268 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; 269 if (reregister) 270 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) 271 err(1, "rpcb_set udp failed"); 272 } 273 274 if (tcpflag) { 275 memset(&hints, 0, sizeof hints); 276 hints.ai_flags = AI_PASSIVE; 277 hints.ai_family = PF_INET; 278 hints.ai_socktype = SOCK_STREAM; 279 hints.ai_protocol = IPPROTO_TCP; 280 281 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp); 282 if (ecode != 0) { 283 syslog(LOG_ERR, "getaddrinfo tcp: %s", 284 gai_strerror(ecode)); 285 exit(1); 286 } 287 288 nconf_tcp = getnetconfigent("tcp"); 289 290 if (nconf_tcp == NULL) 291 err(1, "getnetconfigent tcp failed"); 292 293 nb_tcp.buf = ai_tcp->ai_addr; 294 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; 295 if (reregister) 296 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) 297 err(1, "rpcb_set tcp failed"); 298 } 299 300 if (udpflag && ip6flag) { 301 memset(&hints, 0, sizeof hints); 302 hints.ai_flags = AI_PASSIVE; 303 hints.ai_family = PF_INET6; 304 hints.ai_socktype = SOCK_DGRAM; 305 hints.ai_protocol = IPPROTO_UDP; 306 307 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); 308 if (ecode != 0) { 309 syslog(LOG_ERR, "getaddrinfo udp: %s", 310 gai_strerror(ecode)); 311 exit(1); 312 } 313 314 nconf_udp6 = getnetconfigent("udp6"); 315 316 if (nconf_udp6 == NULL) 317 err(1, "getnetconfigent udp6 failed"); 318 319 nb_udp6.buf = ai_udp6->ai_addr; 320 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; 321 if (reregister) 322 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) 323 err(1, "rpcb_set udp6 failed"); 324 } 325 326 if (tcpflag && ip6flag) { 327 memset(&hints, 0, sizeof hints); 328 hints.ai_flags = AI_PASSIVE; 329 hints.ai_family = PF_INET6; 330 hints.ai_socktype = SOCK_STREAM; 331 hints.ai_protocol = IPPROTO_TCP; 332 333 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); 334 if (ecode != 0) { 335 syslog(LOG_ERR, "getaddrinfo tcp: %s", 336 gai_strerror(ecode)); 337 exit(1); 338 } 339 340 nconf_tcp6 = getnetconfigent("tcp6"); 341 342 if (nconf_tcp6 == NULL) 343 err(1, "getnetconfigent tcp6 failed"); 344 345 nb_tcp6.buf = ai_tcp6->ai_addr; 346 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; 347 if (reregister) 348 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) 349 err(1, "rpcb_set tcp6 failed"); 350 } 351 352 openlog("nfsd", LOG_PID, LOG_DAEMON); 353 354 for (i = 0; i < nfsdcnt; i++) { 355 pthread_t t; 356 int error; 357 358 error = pthread_create(&t, NULL, child, NULL); 359 if (error) { 360 errno = error; 361 syslog(LOG_ERR, "pthread_create: %m"); 362 exit (1); 363 } 364 } 365 366 /* If we are serving udp, set up the socket. */ 367 if (udpflag) { 368 if ((sock = socket(ai_udp->ai_family, ai_udp->ai_socktype, 369 ai_udp->ai_protocol)) < 0) { 370 syslog(LOG_ERR, "can't create udp socket"); 371 exit(1); 372 } 373 if (bind(sock, ai_udp->ai_addr, ai_udp->ai_addrlen) < 0) { 374 syslog(LOG_ERR, "can't bind udp addr"); 375 exit(1); 376 } 377 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp) || 378 !rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)) { 379 syslog(LOG_ERR, "can't register with udp portmap"); 380 exit(1); 381 } 382 nfsdargs.sock = sock; 383 nfsdargs.name = NULL; 384 nfsdargs.namelen = 0; 385 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 386 syslog(LOG_ERR, "can't add UDP socket"); 387 exit(1); 388 } 389 (void)close(sock); 390 } 391 392 if (udpflag &&ip6flag) { 393 if ((sock = socket(ai_udp6->ai_family, ai_udp6->ai_socktype, 394 ai_udp6->ai_protocol)) < 0) { 395 syslog(LOG_ERR, "can't create udp socket"); 396 exit(1); 397 } 398 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, 399 &on, sizeof on) < 0) { 400 syslog(LOG_ERR, "can't set v6-only binding for udp6 " 401 "socket: %m"); 402 exit(1); 403 } 404 if (bind(sock, ai_udp6->ai_addr, ai_udp6->ai_addrlen) < 0) { 405 syslog(LOG_ERR, "can't bind udp addr"); 406 exit(1); 407 } 408 if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6) || 409 !rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)) { 410 syslog(LOG_ERR, "can't register with udp portmap"); 411 exit(1); 412 } 413 nfsdargs.sock = sock; 414 nfsdargs.name = NULL; 415 nfsdargs.namelen = 0; 416 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 417 syslog(LOG_ERR, "can't add UDP6 socket"); 418 exit(1); 419 } 420 (void)close(sock); 421 } 422 423 #ifdef ISO 424 /* If we are serving cltp, set up the socket. */ 425 if (cltpflag) { 426 if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) { 427 syslog(LOG_ERR, "can't create cltp socket"); 428 exit(1); 429 } 430 memset(&isoaddr, 0, sizeof(isoaddr)); 431 isoaddr.siso_family = AF_ISO; 432 isoaddr.siso_tlen = 2; 433 cp = TSEL(&isoaddr); 434 *cp++ = (NFS_PORT >> 8); 435 *cp = (NFS_PORT & 0xff); 436 isoaddr.siso_len = sizeof(isoaddr); 437 if (bind(sock, 438 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) { 439 syslog(LOG_ERR, "can't bind cltp addr"); 440 exit(1); 441 } 442 #ifdef notyet 443 /* 444 * XXX 445 * Someday this should probably use "rpcbind", the son of 446 * portmap. 447 */ 448 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { 449 syslog(LOG_ERR, "can't register with udp portmap"); 450 exit(1); 451 } 452 #endif /* notyet */ 453 nfsdargs.sock = sock; 454 nfsdargs.name = NULL; 455 nfsdargs.namelen = 0; 456 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 457 syslog(LOG_ERR, "can't add UDP socket"); 458 exit(1); 459 } 460 close(sock); 461 } 462 #endif /* ISO */ 463 464 /* Now set up the master server socket waiting for tcp connections. */ 465 on = 1; 466 connect_type_cnt = 0; 467 if (tcpflag) { 468 if ((tcpsock = socket(ai_tcp->ai_family, ai_tcp->ai_socktype, 469 ai_tcp->ai_protocol)) < 0) { 470 syslog(LOG_ERR, "can't create tcp socket"); 471 exit(1); 472 } 473 if (setsockopt(tcpsock, 474 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 475 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 476 if (bind(tcpsock, ai_tcp->ai_addr, ai_tcp->ai_addrlen) < 0) { 477 syslog(LOG_ERR, "can't bind tcp addr"); 478 exit(1); 479 } 480 if (listen(tcpsock, 5) < 0) { 481 syslog(LOG_ERR, "listen failed"); 482 exit(1); 483 } 484 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp) || 485 !rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)) { 486 syslog(LOG_ERR, "can't register tcp with rpcbind"); 487 exit(1); 488 } 489 set[0].fd = tcpsock; 490 set[0].events = POLLIN; 491 connect_type_cnt++; 492 } else 493 set[0].fd = -1; 494 495 if (tcpflag && ip6flag) { 496 if ((tcp6sock = socket(ai_tcp6->ai_family, ai_tcp6->ai_socktype, 497 ai_tcp6->ai_protocol)) < 0) { 498 syslog(LOG_ERR, "can't create tcp socket"); 499 exit(1); 500 } 501 if (setsockopt(tcp6sock, 502 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 503 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 504 if (setsockopt(tcp6sock, IPPROTO_IPV6, IPV6_V6ONLY, 505 &on, sizeof on) < 0) { 506 syslog(LOG_ERR, "can't set v6-only binding for tcp6 " 507 "socket: %m"); 508 exit(1); 509 } 510 if (bind(tcp6sock, ai_tcp6->ai_addr, ai_tcp6->ai_addrlen) < 0) { 511 syslog(LOG_ERR, "can't bind tcp6 addr"); 512 exit(1); 513 } 514 if (listen(tcp6sock, 5) < 0) { 515 syslog(LOG_ERR, "listen failed"); 516 exit(1); 517 } 518 if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6) || 519 !rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)) { 520 syslog(LOG_ERR, "can't register tcp6 with rpcbind"); 521 exit(1); 522 } 523 set[1].fd = tcp6sock; 524 set[1].events = POLLIN; 525 connect_type_cnt++; 526 } else 527 set[1].fd = -1; 528 529 #ifdef notyet 530 /* Now set up the master server socket waiting for tp4 connections. */ 531 if (tp4flag) { 532 if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) { 533 syslog(LOG_ERR, "can't create tp4 socket"); 534 exit(1); 535 } 536 if (setsockopt(tp4sock, 537 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 538 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 539 memset(&isoaddr, 0, sizeof(isoaddr)); 540 isoaddr.siso_family = AF_ISO; 541 isoaddr.siso_tlen = 2; 542 cp = TSEL(&isoaddr); 543 *cp++ = (NFS_PORT >> 8); 544 *cp = (NFS_PORT & 0xff); 545 isoaddr.siso_len = sizeof(isoaddr); 546 if (bind(tp4sock, 547 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) { 548 syslog(LOG_ERR, "can't bind tp4 addr"); 549 exit(1); 550 } 551 if (listen(tp4sock, 5) < 0) { 552 syslog(LOG_ERR, "listen failed"); 553 exit(1); 554 } 555 /* 556 * XXX 557 * Someday this should probably use "rpcbind", the son of 558 * portmap. 559 */ 560 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 561 syslog(LOG_ERR, "can't register tcp with portmap"); 562 exit(1); 563 } 564 set[2].fd = tp4sock; 565 set[2].events = POLLIN; 566 connect_type_cnt++; 567 } else 568 set[2].fd = -1; 569 570 /* Now set up the master server socket waiting for tpip connections. */ 571 if (tpipflag) { 572 if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) { 573 syslog(LOG_ERR, "can't create tpip socket"); 574 exit(1); 575 } 576 if (setsockopt(tpipsock, 577 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 578 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 579 inetaddr.sin_family = AF_INET; 580 inetaddr.sin_addr.s_addr = INADDR_ANY; 581 inetaddr.sin_port = htons(NFS_PORT); 582 inetaddr.sin_len = sizeof(inetaddr); 583 memset(inetaddr.sin_zero, 0, sizeof(inetaddr.sin_zero)); 584 if (bind(tpipsock, 585 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 586 syslog(LOG_ERR, "can't bind tcp addr"); 587 exit(1); 588 } 589 if (listen(tpipsock, 5) < 0) { 590 syslog(LOG_ERR, "listen failed"); 591 exit(1); 592 } 593 /* 594 * XXX 595 * Someday this should probably use "rpcbind", the son of 596 * portmap. 597 */ 598 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 599 syslog(LOG_ERR, "can't register tcp with portmap"); 600 exit(1); 601 } 602 set[3].fd = tpipsock; 603 set[3].events = POLLIN; 604 connect_type_cnt++; 605 } else 606 set[3].fd = -1; 607 #else 608 set[2].fd = -1; 609 set[3].fd = -1; 610 #endif /* notyet */ 611 612 if (connect_type_cnt == 0) 613 exit(0); 614 615 pthread_setname_np(pthread_self(), "master", NULL); 616 617 /* 618 * Loop forever accepting connections and passing the sockets 619 * into the kernel for the mounts. 620 */ 621 for (;;) { 622 if (poll(set, 4, INFTIM) < 1) { 623 syslog(LOG_ERR, "poll failed: %m"); 624 exit(1); 625 } 626 627 if (set[0].revents & POLLIN) { 628 len = sizeof(inetpeer); 629 if ((msgsock = accept(tcpsock, 630 (struct sockaddr *)&inetpeer, &len)) < 0) { 631 syslog(LOG_ERR, "accept failed: %m"); 632 exit(1); 633 } 634 memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); 635 if (setsockopt(msgsock, SOL_SOCKET, 636 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 637 syslog(LOG_ERR, 638 "setsockopt SO_KEEPALIVE: %m"); 639 nfsdargs.sock = msgsock; 640 nfsdargs.name = (caddr_t)&inetpeer; 641 nfsdargs.namelen = sizeof(inetpeer); 642 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 643 (void)close(msgsock); 644 } 645 646 if (set[1].revents & POLLIN) { 647 len = sizeof(inet6peer); 648 if ((msgsock = accept(tcp6sock, 649 (struct sockaddr *)&inet6peer, &len)) < 0) { 650 syslog(LOG_ERR, "accept failed: %m"); 651 exit(1); 652 } 653 if (setsockopt(msgsock, SOL_SOCKET, 654 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 655 syslog(LOG_ERR, 656 "setsockopt SO_KEEPALIVE: %m"); 657 nfsdargs.sock = msgsock; 658 nfsdargs.name = (caddr_t)&inet6peer; 659 nfsdargs.namelen = sizeof(inet6peer); 660 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 661 (void)close(msgsock); 662 } 663 664 #ifdef notyet 665 if (set[2].revents & POLLIN) { 666 len = sizeof(isopeer); 667 if ((msgsock = accept(tp4sock, 668 (struct sockaddr *)&isopeer, &len)) < 0) { 669 syslog(LOG_ERR, "accept failed: %m"); 670 exit(1); 671 } 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)&isopeer; 678 nfsdargs.namelen = len; 679 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 680 (void)close(msgsock); 681 } 682 683 if (set[3].revents & POLLIN) { 684 len = sizeof(inetpeer); 685 if ((msgsock = accept(tpipsock, 686 (struct sockaddr *)&inetpeer, &len)) < 0) { 687 syslog(LOG_ERR, "accept failed: %m"); 688 exit(1); 689 } 690 if (setsockopt(msgsock, SOL_SOCKET, 691 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 692 syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); 693 nfsdargs.sock = msgsock; 694 nfsdargs.name = (caddr_t)&inetpeer; 695 nfsdargs.namelen = len; 696 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 697 (void)close(msgsock); 698 } 699 #endif /* notyet */ 700 } 701 } 702 703 void 704 usage() 705 { 706 (void)fprintf(stderr, "usage: nfsd %s\n", USAGE); 707 exit(1); 708 } 709 710 void 711 nonfs(signo) 712 int signo; 713 { 714 syslog(LOG_ERR, "missing system call: NFS not available."); 715 } 716