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 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 <nfs/nfs.h> 64 65 #ifdef NFSKERB 66 #include <kerberosIV/des.h> 67 #include <kerberosIV/krb.h> 68 #endif 69 70 #include <err.h> 71 #include <errno.h> 72 #include <stdio.h> 73 #include <stdlib.h> 74 #include <strings.h> 75 #include <unistd.h> 76 #include <netdb.h> 77 78 /* Global defs */ 79 #ifdef DEBUG 80 #define syslog(e, s) fprintf(stderr,(s)) 81 int debug = 1; 82 #else 83 int debug = 0; 84 #endif 85 86 struct nfsd_srvargs nsd; 87 #ifdef OLD_SETPROCTITLE 88 char **Argv = NULL; /* pointer to argument vector */ 89 char *LastArg = NULL; /* end of argv */ 90 #endif 91 92 #ifdef NFSKERB 93 char lnam[ANAME_SZ]; 94 KTEXT_ST kt; 95 AUTH_DAT kauth; 96 char inst[INST_SZ]; 97 struct nfsrpc_fullblock kin, kout; 98 struct nfsrpc_fullverf kverf; 99 NFSKERBKEY_T kivec; 100 struct timeval ktv; 101 NFSKERBKEYSCHED_T kerb_keysched; 102 #endif 103 104 #define MAXNFSDCNT 20 105 #define DEFNFSDCNT 4 106 pid_t children[MAXNFSDCNT]; /* PIDs of children */ 107 int nfsdcnt; /* number of children */ 108 109 void cleanup(int); 110 void killchildren(void); 111 void nonfs (int); 112 void reapchild (int); 113 int setbindhost (struct addrinfo **ia, const char *bindhost, struct addrinfo hints); 114 #ifdef OLD_SETPROCTITLE 115 #ifdef __FreeBSD__ 116 void setproctitle (char *); 117 #endif 118 #endif 119 void unregistration (void); 120 void usage (void); 121 122 /* 123 * Nfs server daemon mostly just a user context for nfssvc() 124 * 125 * 1 - do file descriptor and signal cleanup 126 * 2 - fork the nfsd(s) 127 * 3 - create server socket(s) 128 * 4 - register socket with rpcbind 129 * 130 * For connectionless protocols, just pass the socket into the kernel via. 131 * nfssvc(). 132 * For connection based sockets, loop doing accepts. When you get a new 133 * socket from accept, pass the msgsock into the kernel via. nfssvc(). 134 * The arguments are: 135 * -c - support iso cltp clients 136 * -r - reregister with rpcbind 137 * -d - unregister with rpcbind 138 * -t - support tcp nfs clients 139 * -u - support udp nfs clients 140 * followed by "n" which is the number of nfsds' to fork off 141 */ 142 int 143 main(argc, argv, envp) 144 int argc; 145 char *argv[], *envp[]; 146 { 147 struct nfsd_args nfsdargs; 148 struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints; 149 struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6; 150 struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6; 151 struct sockaddr_in inetpeer; 152 struct sockaddr_in6 inet6peer; 153 fd_set ready, sockbits; 154 fd_set v4bits, v6bits; 155 int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock; 156 int nfssvc_flag, on = 1, unregister, reregister, sock; 157 int tcp6sock, ip6flag, tcpflag, tcpsock; 158 int udpflag, ecode, s; 159 int bindhostc = 0, bindanyflag, rpcbreg, rpcbregcnt; 160 char **bindhost = NULL; 161 pid_t pid; 162 #ifdef NFSKERB 163 struct group *grp; 164 struct passwd *pwd; 165 struct ucred *cr; 166 struct timeval ktv; 167 char **cpp; 168 #endif 169 #ifdef __FreeBSD__ 170 struct vfsconf vfc; 171 int error; 172 173 error = getvfsbyname("nfs", &vfc); 174 if (error && vfsisloadable("nfs")) { 175 if (vfsload("nfs")) 176 err(1, "vfsload(nfs)"); 177 endvfsent(); /* flush cache */ 178 error = getvfsbyname("nfs", &vfc); 179 } 180 if (error) 181 errx(1, "NFS is not available in the running kernel"); 182 #endif 183 184 #ifdef OLD_SETPROCTITLE 185 /* Save start and extent of argv for setproctitle. */ 186 Argv = argv; 187 if (envp == 0 || *envp == 0) 188 envp = argv; 189 while (*envp) 190 envp++; 191 LastArg = envp[-1] + strlen(envp[-1]); 192 #endif 193 194 nfsdcnt = DEFNFSDCNT; 195 cltpflag = unregister = reregister = tcpflag = 0; 196 bindanyflag = udpflag; 197 #define GETOPT "ah:n:rdtu" 198 #define USAGE "[-ardtu] [-n num_servers] [-h bindip]" 199 while ((ch = getopt(argc, argv, GETOPT)) != -1) 200 switch (ch) { 201 case 'a': 202 bindanyflag = 1; 203 break; 204 case 'n': 205 nfsdcnt = atoi(optarg); 206 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 207 warnx("nfsd count %d; reset to %d", nfsdcnt, 208 DEFNFSDCNT); 209 nfsdcnt = DEFNFSDCNT; 210 } 211 break; 212 case 'h': 213 bindhostc++; 214 bindhost = realloc(bindhost,sizeof(char *)*bindhostc); 215 if (bindhost == NULL) 216 errx(1, "Out of memory"); 217 bindhost[bindhostc-1] = strdup(optarg); 218 if (bindhost[bindhostc-1] == NULL) 219 errx(1, "Out of memory"); 220 break; 221 case 'r': 222 reregister = 1; 223 break; 224 case 'd': 225 unregister = 1; 226 break; 227 case 't': 228 tcpflag = 1; 229 break; 230 case 'u': 231 udpflag = 1; 232 break; 233 default: 234 case '?': 235 usage(); 236 }; 237 if (!tcpflag && !udpflag) 238 udpflag = 1; 239 argv += optind; 240 argc -= optind; 241 242 /* 243 * XXX 244 * Backward compatibility, trailing number is the count of daemons. 245 */ 246 if (argc > 1) 247 usage(); 248 if (argc == 1) { 249 nfsdcnt = atoi(argv[0]); 250 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 251 warnx("nfsd count %d; reset to %d", nfsdcnt, 252 DEFNFSDCNT); 253 nfsdcnt = DEFNFSDCNT; 254 } 255 } 256 257 ip6flag = 1; 258 s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 259 if (s == -1) { 260 if (errno != EPROTONOSUPPORT) 261 err(1, "socket"); 262 ip6flag = 0; 263 } else if (getnetconfigent("udp6") == NULL || 264 getnetconfigent("tcp6") == NULL) { 265 ip6flag = 0; 266 } 267 if (s != -1) 268 close(s); 269 270 if (bindhostc == 0 || bindanyflag) { 271 bindhostc++; 272 bindhost = realloc(bindhost,sizeof(char *)*bindhostc); 273 if (bindhost == NULL) 274 errx(1, "Out of memory"); 275 bindhost[bindhostc-1] = strdup("*"); 276 if (bindhost[bindhostc-1] == NULL) 277 errx(1, "Out of memory"); 278 } 279 280 if (unregister) { 281 unregistration(); 282 exit (0); 283 } 284 if (reregister) { 285 if (udpflag) { 286 memset(&hints, 0, sizeof hints); 287 hints.ai_flags = AI_PASSIVE; 288 hints.ai_family = AF_INET; 289 hints.ai_socktype = SOCK_DGRAM; 290 hints.ai_protocol = IPPROTO_UDP; 291 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); 292 if (ecode != 0) 293 err(1, "getaddrinfo udp: %s", gai_strerror(ecode)); 294 nconf_udp = getnetconfigent("udp"); 295 if (nconf_udp == NULL) 296 err(1, "getnetconfigent udp failed"); 297 nb_udp.buf = ai_udp->ai_addr; 298 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; 299 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) || 300 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp))) 301 err(1, "rpcb_set udp failed"); 302 freeaddrinfo(ai_udp); 303 } 304 if (udpflag && ip6flag) { 305 memset(&hints, 0, sizeof hints); 306 hints.ai_flags = AI_PASSIVE; 307 hints.ai_family = AF_INET6; 308 hints.ai_socktype = SOCK_DGRAM; 309 hints.ai_protocol = IPPROTO_UDP; 310 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); 311 if (ecode != 0) 312 err(1, "getaddrinfo udp6: %s", gai_strerror(ecode)); 313 nconf_udp6 = getnetconfigent("udp6"); 314 if (nconf_udp6 == NULL) 315 err(1, "getnetconfigent udp6 failed"); 316 nb_udp6.buf = ai_udp6->ai_addr; 317 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; 318 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) || 319 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6))) 320 err(1, "rpcb_set udp6 failed"); 321 freeaddrinfo(ai_udp6); 322 } 323 if (tcpflag) { 324 memset(&hints, 0, sizeof hints); 325 hints.ai_flags = AI_PASSIVE; 326 hints.ai_family = AF_INET; 327 hints.ai_socktype = SOCK_STREAM; 328 hints.ai_protocol = IPPROTO_TCP; 329 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp); 330 if (ecode != 0) 331 err(1, "getaddrinfo tcp: %s", gai_strerror(ecode)); 332 nconf_tcp = getnetconfigent("tcp"); 333 if (nconf_tcp == NULL) 334 err(1, "getnetconfigent tcp failed"); 335 nb_tcp.buf = ai_tcp->ai_addr; 336 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; 337 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) || 338 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp))) 339 err(1, "rpcb_set tcp failed"); 340 freeaddrinfo(ai_tcp); 341 } 342 if (tcpflag && ip6flag) { 343 memset(&hints, 0, sizeof hints); 344 hints.ai_flags = AI_PASSIVE; 345 hints.ai_family = AF_INET6; 346 hints.ai_socktype = SOCK_STREAM; 347 hints.ai_protocol = IPPROTO_TCP; 348 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); 349 if (ecode != 0) 350 err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode)); 351 nconf_tcp6 = getnetconfigent("tcp6"); 352 if (nconf_tcp6 == NULL) 353 err(1, "getnetconfigent tcp6 failed"); 354 nb_tcp6.buf = ai_tcp6->ai_addr; 355 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; 356 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) || 357 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6))) 358 err(1, "rpcb_set tcp6 failed"); 359 freeaddrinfo(ai_tcp6); 360 } 361 exit (0); 362 } 363 if (debug == 0) { 364 daemon(0, 0); 365 (void)signal(SIGHUP, SIG_IGN); 366 (void)signal(SIGINT, SIG_IGN); 367 (void)signal(SIGSYS, nonfs); 368 (void)signal(SIGUSR1, cleanup); 369 /* 370 * nfsd sits in the kernel most of the time. It needs 371 * to ignore SIGTERM/SIGQUIT in order to stay alive as long 372 * as possible during a shutdown, otherwise loopback 373 * mounts will not be able to unmount. 374 */ 375 (void)signal(SIGTERM, SIG_IGN); 376 (void)signal(SIGQUIT, SIG_IGN); 377 } 378 (void)signal(SIGCHLD, reapchild); 379 380 openlog("nfsd:", LOG_PID, LOG_DAEMON); 381 382 for (i = 0; i < nfsdcnt; i++) { 383 switch ((pid = fork())) { 384 case -1: 385 syslog(LOG_ERR, "fork: %m"); 386 killchildren(); 387 exit (1); 388 case 0: 389 break; 390 default: 391 children[i] = pid; 392 continue; 393 } 394 395 setproctitle("server"); 396 nfssvc_flag = NFSSVC_NFSD; 397 nsd.nsd_nfsd = NULL; 398 #ifdef NFSKERB 399 if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF || 400 sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK) 401 syslog(LOG_ERR, "Yikes NFSKERB structs not packed!"); 402 nsd.nsd_authstr = (u_char *)&kt; 403 nsd.nsd_authlen = sizeof (kt); 404 nsd.nsd_verfstr = (u_char *)&kverf; 405 nsd.nsd_verflen = sizeof (kverf); 406 #endif 407 while (nfssvc(nfssvc_flag, &nsd) < 0) { 408 if (errno != ENEEDAUTH) { 409 syslog(LOG_ERR, "nfssvc: %m"); 410 exit(1); 411 } 412 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; 413 #ifdef NFSKERB 414 /* 415 * Get the Kerberos ticket out of the authenticator 416 * verify it and convert the principal name to a user 417 * name. The user name is then converted to a set of 418 * user credentials via the password and group file. 419 * Finally, decrypt the timestamp and validate it. 420 * For more info see the IETF Draft "Authentication 421 * in ONC RPC". 422 */ 423 kt.length = ntohl(kt.length); 424 if (gettimeofday(&ktv, (struct timezone *)0) == 0 && 425 kt.length > 0 && kt.length <= 426 (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) { 427 kin.w1 = NFS_KERBW1(kt); 428 kt.mbz = 0; 429 (void)strcpy(inst, "*"); 430 if (krb_rd_req(&kt, NFS_KERBSRV, 431 inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK && 432 krb_kntoln(&kauth, lnam) == KSUCCESS && 433 (pwd = getpwnam(lnam)) != NULL) { 434 cr = &nsd.nsd_cr; 435 cr->cr_uid = pwd->pw_uid; 436 cr->cr_groups[0] = pwd->pw_gid; 437 cr->cr_ngroups = 1; 438 setgrent(); 439 while ((grp = getgrent()) != NULL) { 440 if (grp->gr_gid == cr->cr_groups[0]) 441 continue; 442 for (cpp = grp->gr_mem; 443 *cpp != NULL; ++cpp) 444 if (!strcmp(*cpp, lnam)) 445 break; 446 if (*cpp == NULL) 447 continue; 448 cr->cr_groups[cr->cr_ngroups++] 449 = grp->gr_gid; 450 if (cr->cr_ngroups == NGROUPS) 451 break; 452 } 453 endgrent(); 454 455 /* 456 * Get the timestamp verifier out of the 457 * authenticator and verifier strings. 458 */ 459 kin.t1 = kverf.t1; 460 kin.t2 = kverf.t2; 461 kin.w2 = kverf.w2; 462 bzero((caddr_t)kivec, sizeof (kivec)); 463 bcopy((caddr_t)kauth.session, 464 (caddr_t)nsd.nsd_key,sizeof(kauth.session)); 465 466 /* 467 * Decrypt the timestamp verifier in CBC mode. 468 */ 469 XXX 470 471 /* 472 * Validate the timestamp verifier, to 473 * check that the session key is ok. 474 */ 475 nsd.nsd_timestamp.tv_sec = ntohl(kout.t1); 476 nsd.nsd_timestamp.tv_usec = ntohl(kout.t2); 477 nsd.nsd_ttl = ntohl(kout.w1); 478 if ((nsd.nsd_ttl - 1) == ntohl(kout.w2)) 479 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; 480 } 481 #endif /* NFSKERB */ 482 } 483 exit(0); 484 } 485 486 if (atexit(killchildren) == -1) { 487 syslog(LOG_ERR, "atexit: %s", strerror(errno)); 488 exit(1); 489 } 490 FD_ZERO(&v4bits); 491 FD_ZERO(&v6bits); 492 493 rpcbregcnt = 0; 494 /* Set up the socket for udp and rpcb register it. */ 495 if (udpflag) { 496 rpcbreg = 0; 497 for (i = 0; i < bindhostc; i++) { 498 memset(&hints, 0, sizeof hints); 499 hints.ai_flags = AI_PASSIVE; 500 hints.ai_family = AF_INET; 501 hints.ai_socktype = SOCK_DGRAM; 502 hints.ai_protocol = IPPROTO_UDP; 503 if (setbindhost(&ai_udp, bindhost[i], hints) == 0) { 504 rpcbreg = 1; 505 rpcbregcnt++; 506 if ((sock = socket(ai_udp->ai_family, 507 ai_udp->ai_socktype, 508 ai_udp->ai_protocol)) < 0) { 509 syslog(LOG_ERR, 510 "can't create udp socket"); 511 exit(1); 512 } 513 if (bind(sock, ai_udp->ai_addr, 514 ai_udp->ai_addrlen) < 0) { 515 syslog(LOG_ERR, 516 "can't bind udp addr %s: %m", 517 bindhost[i]); 518 exit(1); 519 } 520 freeaddrinfo(ai_udp); 521 nfsdargs.sock = sock; 522 nfsdargs.name = NULL; 523 nfsdargs.namelen = 0; 524 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 525 syslog(LOG_ERR, "can't Add UDP socket"); 526 exit(1); 527 } 528 (void)close(sock); 529 } 530 } 531 if (rpcbreg == 1) { 532 memset(&hints, 0, sizeof hints); 533 hints.ai_flags = AI_PASSIVE; 534 hints.ai_family = AF_INET; 535 hints.ai_socktype = SOCK_DGRAM; 536 hints.ai_protocol = IPPROTO_UDP; 537 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); 538 if (ecode != 0) { 539 syslog(LOG_ERR, "getaddrinfo udp: %s", 540 gai_strerror(ecode)); 541 exit(1); 542 } 543 nconf_udp = getnetconfigent("udp"); 544 if (nconf_udp == NULL) 545 err(1, "getnetconfigent udp failed"); 546 nb_udp.buf = ai_udp->ai_addr; 547 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; 548 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) || 549 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp))) 550 err(1, "rpcb_set udp failed"); 551 freeaddrinfo(ai_udp); 552 } 553 } 554 555 /* Set up the socket for udp6 and rpcb register it. */ 556 if (udpflag && ip6flag) { 557 rpcbreg = 0; 558 for (i = 0; i < bindhostc; i++) { 559 memset(&hints, 0, sizeof hints); 560 hints.ai_flags = AI_PASSIVE; 561 hints.ai_family = AF_INET6; 562 hints.ai_socktype = SOCK_DGRAM; 563 hints.ai_protocol = IPPROTO_UDP; 564 if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) { 565 rpcbreg = 1; 566 rpcbregcnt++; 567 if ((sock = socket(ai_udp6->ai_family, 568 ai_udp6->ai_socktype, 569 ai_udp6->ai_protocol)) < 0) { 570 syslog(LOG_ERR, 571 "can't create udp6 socket"); 572 exit(1); 573 } 574 if (setsockopt(sock, IPPROTO_IPV6, 575 IPV6_BINDV6ONLY, 576 &on, sizeof on) < 0) { 577 syslog(LOG_ERR, 578 "can't set v6-only binding for " 579 "udp6 socket: %m"); 580 exit(1); 581 } 582 if (bind(sock, ai_udp6->ai_addr, 583 ai_udp6->ai_addrlen) < 0) { 584 syslog(LOG_ERR, 585 "can't bind udp6 addr %s: %m", 586 bindhost[i]); 587 exit(1); 588 } 589 freeaddrinfo(ai_udp6); 590 nfsdargs.sock = sock; 591 nfsdargs.name = NULL; 592 nfsdargs.namelen = 0; 593 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 594 syslog(LOG_ERR, 595 "can't add UDP6 socket"); 596 exit(1); 597 } 598 (void)close(sock); 599 } 600 } 601 if (rpcbreg == 1) { 602 memset(&hints, 0, sizeof hints); 603 hints.ai_flags = AI_PASSIVE; 604 hints.ai_family = AF_INET6; 605 hints.ai_socktype = SOCK_DGRAM; 606 hints.ai_protocol = IPPROTO_UDP; 607 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); 608 if (ecode != 0) { 609 syslog(LOG_ERR, "getaddrinfo udp6: %s", 610 gai_strerror(ecode)); 611 exit(1); 612 } 613 nconf_udp6 = getnetconfigent("udp6"); 614 if (nconf_udp6 == NULL) 615 err(1, "getnetconfigent udp6 failed"); 616 nb_udp6.buf = ai_udp6->ai_addr; 617 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; 618 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) || 619 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6))) 620 err(1, "rpcb_set udp6 failed"); 621 freeaddrinfo(ai_udp6); 622 } 623 } 624 625 /* Set up the socket for tcp and rpcb register it. */ 626 if (tcpflag) { 627 rpcbreg = 0; 628 for (i = 0; i < bindhostc; i++) { 629 memset(&hints, 0, sizeof hints); 630 hints.ai_flags = AI_PASSIVE; 631 hints.ai_family = AF_INET; 632 hints.ai_socktype = SOCK_STREAM; 633 hints.ai_protocol = IPPROTO_TCP; 634 if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) { 635 rpcbreg = 1; 636 rpcbregcnt++; 637 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 638 0)) < 0) { 639 syslog(LOG_ERR, 640 "can't create tpc socket"); 641 exit(1); 642 } 643 if (setsockopt(tcpsock, SOL_SOCKET, 644 SO_REUSEADDR, 645 (char *)&on, sizeof(on)) < 0) 646 syslog(LOG_ERR, 647 "setsockopt SO_REUSEADDR: %m"); 648 if (bind(tcpsock, ai_tcp->ai_addr, 649 ai_tcp->ai_addrlen) < 0) { 650 syslog(LOG_ERR, 651 "can't bind tcp addr %s: %m", 652 bindhost[i]); 653 exit(1); 654 } 655 if (listen(tcpsock, 5) < 0) { 656 syslog(LOG_ERR, "listen failed"); 657 exit(1); 658 } 659 freeaddrinfo(ai_tcp); 660 FD_SET(tcpsock, &sockbits); 661 FD_SET(tcpsock, &v4bits); 662 maxsock = tcpsock; 663 connect_type_cnt++; 664 } 665 } 666 if (rpcbreg == 1) { 667 memset(&hints, 0, sizeof hints); 668 hints.ai_flags = AI_PASSIVE; 669 hints.ai_family = AF_INET; 670 hints.ai_socktype = SOCK_STREAM; 671 hints.ai_protocol = IPPROTO_TCP; 672 ecode = getaddrinfo(NULL, "nfs", &hints, 673 &ai_tcp); 674 if (ecode != 0) { 675 syslog(LOG_ERR, "getaddrinfo tcp: %s", 676 gai_strerror(ecode)); 677 exit(1); 678 } 679 nconf_tcp = getnetconfigent("tcp"); 680 if (nconf_tcp == NULL) 681 err(1, "getnetconfigent tcp failed"); 682 nb_tcp.buf = ai_tcp->ai_addr; 683 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; 684 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, 685 &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3, 686 nconf_tcp, &nb_tcp))) 687 err(1, "rpcb_set tcp failed"); 688 freeaddrinfo(ai_tcp); 689 } 690 } 691 692 /* Set up the socket for tcp6 and rpcb register it. */ 693 if (tcpflag && ip6flag) { 694 rpcbreg = 0; 695 for (i = 0; i < bindhostc; i++) { 696 memset(&hints, 0, sizeof hints); 697 hints.ai_flags = AI_PASSIVE; 698 hints.ai_family = AF_INET6; 699 hints.ai_socktype = SOCK_STREAM; 700 hints.ai_protocol = IPPROTO_TCP; 701 if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) { 702 rpcbreg = 1; 703 rpcbregcnt++; 704 if ((tcp6sock = socket(ai_tcp6->ai_family, 705 ai_tcp6->ai_socktype, 706 ai_tcp6->ai_protocol)) < 0) { 707 syslog(LOG_ERR, 708 "can't create tcp6 socket"); 709 exit(1); 710 } 711 if (setsockopt(tcp6sock, SOL_SOCKET, 712 SO_REUSEADDR, 713 (char *)&on, sizeof(on)) < 0) 714 syslog(LOG_ERR, 715 "setsockopt SO_REUSEADDR: %m"); 716 if (setsockopt(tcp6sock, IPPROTO_IPV6, 717 IPV6_BINDV6ONLY, &on, sizeof on) < 0) { 718 syslog(LOG_ERR, 719 "can't set v6-only binding for tcp6 " 720 "socket: %m"); 721 exit(1); 722 } 723 if (bind(tcp6sock, ai_tcp6->ai_addr, 724 ai_tcp6->ai_addrlen) < 0) { 725 syslog(LOG_ERR, 726 "can't bind tcp6 addr %s: %m", 727 bindhost[i]); 728 exit(1); 729 } 730 if (listen(tcp6sock, 5) < 0) { 731 syslog(LOG_ERR, "listen failed"); 732 exit(1); 733 } 734 freeaddrinfo(ai_tcp6); 735 FD_SET(tcp6sock, &sockbits); 736 FD_SET(tcp6sock, &v6bits); 737 if (maxsock < tcp6sock) 738 maxsock = tcp6sock; 739 connect_type_cnt++; 740 } 741 } 742 if (rpcbreg == 1) { 743 memset(&hints, 0, sizeof hints); 744 hints.ai_flags = AI_PASSIVE; 745 hints.ai_family = AF_INET6; 746 hints.ai_socktype = SOCK_STREAM; 747 hints.ai_protocol = IPPROTO_TCP; 748 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); 749 if (ecode != 0) { 750 syslog(LOG_ERR, "getaddrinfo tcp6: %s", 751 gai_strerror(ecode)); 752 exit(1); 753 } 754 nconf_tcp6 = getnetconfigent("tcp6"); 755 if (nconf_tcp6 == NULL) 756 err(1, "getnetconfigent tcp6 failed"); 757 nb_tcp6.buf = ai_tcp6->ai_addr; 758 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; 759 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) || 760 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6))) 761 err(1, "rpcb_set tcp6 failed"); 762 freeaddrinfo(ai_tcp6); 763 } 764 } 765 766 if (rpcbregcnt == 0) { 767 syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m"); 768 exit(1); 769 } 770 771 if ((tcpflag) && (connect_type_cnt == 0)) { 772 syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m"); 773 exit(1); 774 } 775 776 setproctitle("master"); 777 778 /* 779 * Loop forever accepting connections and passing the sockets 780 * into the kernel for the mounts. 781 */ 782 for (;;) { 783 ready = sockbits; 784 if (connect_type_cnt > 1) { 785 if (select(maxsock + 1, 786 &ready, NULL, NULL, NULL) < 1) { 787 syslog(LOG_ERR, "select failed: %m"); 788 exit(1); 789 } 790 } 791 for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) { 792 if (FD_ISSET(tcpsock, &ready)) { 793 if (FD_ISSET(tcpsock, &v4bits)) { 794 len = sizeof(inetpeer); 795 if ((msgsock = accept(tcpsock, 796 (struct sockaddr *)&inetpeer, &len)) < 0) { 797 syslog(LOG_ERR, "accept failed: %m"); 798 exit(1); 799 } 800 memset(inetpeer.sin_zero, 0, 801 sizeof(inetpeer.sin_zero)); 802 if (setsockopt(msgsock, SOL_SOCKET, 803 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 804 syslog(LOG_ERR, 805 "setsockopt SO_KEEPALIVE: %m"); 806 nfsdargs.sock = msgsock; 807 nfsdargs.name = (caddr_t)&inetpeer; 808 nfsdargs.namelen = sizeof(inetpeer); 809 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 810 (void)close(msgsock); 811 } else if (FD_ISSET(tcpsock, &v6bits)) { 812 len = sizeof(inet6peer); 813 if ((msgsock = accept(tcpsock, 814 (struct sockaddr *)&inet6peer, 815 &len)) < 0) { 816 syslog(LOG_ERR, 817 "accept failed: %m"); 818 exit(1); 819 } 820 if (setsockopt(msgsock, SOL_SOCKET, 821 SO_KEEPALIVE, (char *)&on, 822 sizeof(on)) < 0) 823 syslog(LOG_ERR, "setsockopt " 824 "SO_KEEPALIVE: %m"); 825 nfsdargs.sock = msgsock; 826 nfsdargs.name = (caddr_t)&inet6peer; 827 nfsdargs.namelen = sizeof(inet6peer); 828 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 829 (void)close(msgsock); 830 } 831 } 832 } 833 } 834 } 835 836 int 837 setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints) 838 { 839 int ecode; 840 u_int32_t host_addr[4]; /* IPv4 or IPv6 */ 841 const char *hostptr; 842 843 if (bindhost == NULL || strcmp("*", bindhost) == 0) 844 hostptr = NULL; 845 else 846 hostptr = bindhost; 847 848 if (hostptr != NULL) { 849 switch (hints.ai_family) { 850 case AF_INET: 851 if (inet_pton(AF_INET, hostptr, host_addr) == 1) { 852 hints.ai_flags = AI_NUMERICHOST; 853 } else { 854 if (inet_pton(AF_INET6, hostptr, 855 host_addr) == 1) 856 return (1); 857 } 858 break; 859 case AF_INET6: 860 if (inet_pton(AF_INET6, hostptr, host_addr) == 1) { 861 hints.ai_flags = AI_NUMERICHOST; 862 } else { 863 if (inet_pton(AF_INET, hostptr, 864 host_addr) == 1) 865 return (1); 866 } 867 break; 868 default: 869 } 870 } 871 872 ecode = getaddrinfo(hostptr, "nfs", &hints, ai); 873 if (ecode != 0) { 874 syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost, 875 gai_strerror(ecode)); 876 return (1); 877 } 878 return (0); 879 } 880 881 void 882 usage() 883 { 884 (void)fprintf(stderr, "usage: nfsd %s\n", USAGE); 885 exit(1); 886 } 887 888 void 889 nonfs(signo) 890 int signo; 891 { 892 syslog(LOG_ERR, "missing system call: NFS not available"); 893 } 894 895 void 896 reapchild(signo) 897 int signo; 898 { 899 900 while (wait3(NULL, WNOHANG, NULL) > 0); 901 } 902 903 void 904 unregistration() 905 { 906 if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) || 907 (!rpcb_unset(RPCPROG_NFS, 3, NULL))) 908 syslog(LOG_ERR, "rpcb_unset failed"); 909 } 910 911 void 912 killchildren() 913 { 914 int i; 915 sigset_t sigs; 916 917 sigemptyset(&sigs); 918 /* 919 * Block SIGCHLD to avoid killing a reaped process (although it is 920 * unlikely, the pid might have been reused). 921 */ 922 sigaddset(&sigs, SIGCHLD); 923 if (sigprocmask(SIG_BLOCK, &sigs, NULL) == -1) { 924 syslog(LOG_ERR, "sigprocmask: %s", 925 strerror(errno)); 926 return; 927 } 928 for (i = 0; i < nfsdcnt; i++) { 929 if (children[i] > 0) 930 kill(children[i], SIGKILL); 931 } 932 if (sigprocmask(SIG_UNBLOCK, &sigs, NULL) == -1) { 933 syslog(LOG_ERR, "sigprocmask: %s", strerror(errno)); 934 } 935 unregistration(); 936 } 937 938 void 939 cleanup(signo) 940 { 941 killchildren(); 942 exit (0); 943 } 944 945 #ifdef OLD_SETPROCTITLE 946 #ifdef __FreeBSD__ 947 void 948 setproctitle(a) 949 char *a; 950 { 951 register char *cp; 952 char buf[80]; 953 954 cp = Argv[0]; 955 (void)snprintf(buf, sizeof(buf), "nfsd-%s", a); 956 (void)strncpy(cp, buf, LastArg - cp); 957 cp += strlen(cp); 958 while (cp < LastArg) 959 *cp++ = '\0'; 960 Argv[1] = NULL; 961 } 962 #endif /* __FreeBSD__ */ 963 #endif 964