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 #ifdef ISO 62 #include <netiso/iso.h> 63 #endif 64 #include <nfs/rpcv2.h> 65 #include <nfs/nfsproto.h> 66 #include <nfs/nfs.h> 67 68 #ifdef NFSKERB 69 #include <kerberosIV/des.h> 70 #include <kerberosIV/krb.h> 71 #endif 72 73 #include <err.h> 74 #include <errno.h> 75 #include <stdio.h> 76 #include <stdlib.h> 77 #include <strings.h> 78 #include <unistd.h> 79 80 /* Global defs */ 81 #ifdef DEBUG 82 #define syslog(e, s) fprintf(stderr,(s)) 83 int debug = 1; 84 #else 85 int debug = 0; 86 #endif 87 88 struct nfsd_srvargs nsd; 89 #ifdef OLD_SETPROCTITLE 90 char **Argv = NULL; /* pointer to argument vector */ 91 char *LastArg = NULL; /* end of argv */ 92 #endif 93 94 #ifdef NFSKERB 95 char lnam[ANAME_SZ]; 96 KTEXT_ST kt; 97 AUTH_DAT kauth; 98 char inst[INST_SZ]; 99 struct nfsrpc_fullblock kin, kout; 100 struct nfsrpc_fullverf kverf; 101 NFSKERBKEY_T kivec; 102 struct timeval ktv; 103 NFSKERBKEYSCHED_T kerb_keysched; 104 #endif 105 106 void nonfs __P((int)); 107 void reapchild __P((int)); 108 void setbindhost __P((struct sockaddr_in *ia, const char *bindhost)); 109 #ifdef OLD_SETPROCTITLE 110 #ifdef __FreeBSD__ 111 void setproctitle __P((char *)); 112 #endif 113 #endif 114 void usage __P((void)); 115 116 /* 117 * Nfs server daemon mostly just a user context for nfssvc() 118 * 119 * 1 - do file descriptor and signal cleanup 120 * 2 - fork the nfsd(s) 121 * 3 - create server socket(s) 122 * 4 - register socket with portmap 123 * 124 * For connectionless protocols, just pass the socket into the kernel via. 125 * nfssvc(). 126 * For connection based sockets, loop doing accepts. When you get a new 127 * socket from accept, pass the msgsock into the kernel via. nfssvc(). 128 * The arguments are: 129 * -c - support iso cltp clients 130 * -r - reregister with portmapper 131 * -t - support tcp nfs clients 132 * -u - support udp nfs clients 133 * followed by "n" which is the number of nfsds' to fork off 134 */ 135 int 136 main(argc, argv, envp) 137 int argc; 138 char *argv[], *envp[]; 139 { 140 struct nfsd_args nfsdargs; 141 struct sockaddr_in inetaddr, inetpeer; 142 #ifdef ISO 143 struct sockaddr_iso isoaddr, isopeer; 144 char *cp; 145 #endif 146 fd_set ready, sockbits; 147 int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock; 148 int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock; 149 int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag; 150 int bindhostc = 0, bindanyflag; 151 char **bindhost = NULL; 152 #ifdef notyet 153 int tp4sock, tpipsock; 154 #endif 155 #ifdef NFSKERB 156 struct group *grp; 157 struct passwd *pwd; 158 struct ucred *cr; 159 struct timeval ktv; 160 char **cpp; 161 #endif 162 #ifdef __FreeBSD__ 163 struct vfsconf vfc; 164 int error; 165 166 error = getvfsbyname("nfs", &vfc); 167 if (error && vfsisloadable("nfs")) { 168 if (vfsload("nfs")) 169 err(1, "vfsload(nfs)"); 170 endvfsent(); /* flush cache */ 171 error = getvfsbyname("nfs", &vfc); 172 } 173 if (error) 174 errx(1, "NFS is not available in the running kernel"); 175 #endif 176 177 #ifdef OLD_SETPROCTITLE 178 /* Save start and extent of argv for setproctitle. */ 179 Argv = argv; 180 if (envp == 0 || *envp == 0) 181 envp = argv; 182 while (*envp) 183 envp++; 184 LastArg = envp[-1] + strlen(envp[-1]); 185 #endif 186 187 #define MAXNFSDCNT 20 188 #define DEFNFSDCNT 4 189 nfsdcnt = DEFNFSDCNT; 190 cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0; 191 bindanyflag = tpipflag = udpflag = 0; 192 #ifdef ISO 193 #define GETOPT "ach:n:rtu" 194 #define USAGE "[-acrtu] [-n num_servers] [-h bindip]" 195 #else 196 #define GETOPT "ah:n:rtu" 197 #define USAGE "[-artu] [-n num_servers] [-h bindip]" 198 #endif 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 't': 225 tcpflag = 1; 226 break; 227 case 'u': 228 udpflag = 1; 229 break; 230 #ifdef ISO 231 case 'c': 232 cltpflag = 1; 233 break; 234 #ifdef notyet 235 case 'i': 236 tp4cnt = 1; 237 break; 238 case 'p': 239 tpipcnt = 1; 240 break; 241 #endif /* notyet */ 242 #endif /* ISO */ 243 default: 244 case '?': 245 usage(); 246 }; 247 if (!tcpflag && !udpflag) 248 udpflag = 1; 249 argv += optind; 250 argc -= optind; 251 252 /* 253 * XXX 254 * Backward compatibility, trailing number is the count of daemons. 255 */ 256 if (argc > 1) 257 usage(); 258 if (argc == 1) { 259 nfsdcnt = atoi(argv[0]); 260 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 261 warnx("nfsd count %d; reset to %d", nfsdcnt, 262 DEFNFSDCNT); 263 nfsdcnt = DEFNFSDCNT; 264 } 265 } 266 267 if (bindhostc == 0 || bindanyflag) { 268 bindhostc++; 269 bindhost = realloc(bindhost,sizeof(char *)*bindhostc); 270 if (bindhost == NULL) 271 errx(1, "Out of memory"); 272 bindhost[bindhostc-1] = strdup("*"); 273 if (bindhost[bindhostc-1] == NULL) 274 errx(1, "Out of memory"); 275 } 276 277 if (debug == 0) { 278 daemon(0, 0); 279 (void)signal(SIGHUP, SIG_IGN); 280 (void)signal(SIGINT, SIG_IGN); 281 (void)signal(SIGQUIT, SIG_IGN); 282 (void)signal(SIGSYS, nonfs); 283 (void)signal(SIGTERM, SIG_IGN); 284 } 285 (void)signal(SIGCHLD, reapchild); 286 287 if (reregister) { 288 if (udpflag && 289 (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || 290 !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT))) 291 err(1, "can't register with portmap for UDP"); 292 if (tcpflag && 293 (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || 294 !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT))) 295 err(1, "can't register with portmap for TCP"); 296 exit(0); 297 } 298 openlog("nfsd:", LOG_PID, LOG_DAEMON); 299 300 for (i = 0; i < nfsdcnt; i++) { 301 switch (fork()) { 302 case -1: 303 syslog(LOG_ERR, "fork: %m"); 304 exit (1); 305 case 0: 306 break; 307 default: 308 continue; 309 } 310 311 setproctitle("server"); 312 nfssvc_flag = NFSSVC_NFSD; 313 nsd.nsd_nfsd = NULL; 314 #ifdef NFSKERB 315 if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF || 316 sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK) 317 syslog(LOG_ERR, "Yikes NFSKERB structs not packed!"); 318 nsd.nsd_authstr = (u_char *)&kt; 319 nsd.nsd_authlen = sizeof (kt); 320 nsd.nsd_verfstr = (u_char *)&kverf; 321 nsd.nsd_verflen = sizeof (kverf); 322 #endif 323 while (nfssvc(nfssvc_flag, &nsd) < 0) { 324 if (errno != ENEEDAUTH) { 325 syslog(LOG_ERR, "nfssvc: %m"); 326 exit(1); 327 } 328 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; 329 #ifdef NFSKERB 330 /* 331 * Get the Kerberos ticket out of the authenticator 332 * verify it and convert the principal name to a user 333 * name. The user name is then converted to a set of 334 * user credentials via the password and group file. 335 * Finally, decrypt the timestamp and validate it. 336 * For more info see the IETF Draft "Authentication 337 * in ONC RPC". 338 */ 339 kt.length = ntohl(kt.length); 340 if (gettimeofday(&ktv, (struct timezone *)0) == 0 && 341 kt.length > 0 && kt.length <= 342 (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) { 343 kin.w1 = NFS_KERBW1(kt); 344 kt.mbz = 0; 345 (void)strcpy(inst, "*"); 346 if (krb_rd_req(&kt, NFS_KERBSRV, 347 inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK && 348 krb_kntoln(&kauth, lnam) == KSUCCESS && 349 (pwd = getpwnam(lnam)) != NULL) { 350 cr = &nsd.nsd_cr; 351 cr->cr_uid = pwd->pw_uid; 352 cr->cr_groups[0] = pwd->pw_gid; 353 cr->cr_ngroups = 1; 354 setgrent(); 355 while ((grp = getgrent()) != NULL) { 356 if (grp->gr_gid == cr->cr_groups[0]) 357 continue; 358 for (cpp = grp->gr_mem; 359 *cpp != NULL; ++cpp) 360 if (!strcmp(*cpp, lnam)) 361 break; 362 if (*cpp == NULL) 363 continue; 364 cr->cr_groups[cr->cr_ngroups++] 365 = grp->gr_gid; 366 if (cr->cr_ngroups == NGROUPS) 367 break; 368 } 369 endgrent(); 370 371 /* 372 * Get the timestamp verifier out of the 373 * authenticator and verifier strings. 374 */ 375 kin.t1 = kverf.t1; 376 kin.t2 = kverf.t2; 377 kin.w2 = kverf.w2; 378 bzero((caddr_t)kivec, sizeof (kivec)); 379 bcopy((caddr_t)kauth.session, 380 (caddr_t)nsd.nsd_key,sizeof(kauth.session)); 381 382 /* 383 * Decrypt the timestamp verifier in CBC mode. 384 */ 385 XXX 386 387 /* 388 * Validate the timestamp verifier, to 389 * check that the session key is ok. 390 */ 391 nsd.nsd_timestamp.tv_sec = ntohl(kout.t1); 392 nsd.nsd_timestamp.tv_usec = ntohl(kout.t2); 393 nsd.nsd_ttl = ntohl(kout.w1); 394 if ((nsd.nsd_ttl - 1) == ntohl(kout.w2)) 395 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; 396 } 397 #endif /* NFSKERB */ 398 } 399 exit(0); 400 } 401 402 /* If we are serving udp, set up the socket. */ 403 for (i = 0; udpflag && i < bindhostc; i++) { 404 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 405 syslog(LOG_ERR, "can't create udp socket"); 406 exit(1); 407 } 408 setbindhost(&inetaddr, bindhost[i]); 409 if (bind(sock, 410 (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) { 411 syslog(LOG_ERR, "can't bind udp addr %s: %m", bindhost[i]); 412 exit(1); 413 } 414 if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || 415 !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) { 416 syslog(LOG_ERR, "can't register with udp portmap"); 417 exit(1); 418 } 419 nfsdargs.sock = sock; 420 nfsdargs.name = NULL; 421 nfsdargs.namelen = 0; 422 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 423 syslog(LOG_ERR, "can't Add UDP socket"); 424 exit(1); 425 } 426 (void)close(sock); 427 } 428 429 #ifdef ISO 430 /* If we are serving cltp, set up the socket. */ 431 if (cltpflag) { 432 if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) { 433 syslog(LOG_ERR, "can't create cltp socket"); 434 exit(1); 435 } 436 memset(&isoaddr, 0, sizeof(isoaddr)); 437 isoaddr.siso_family = AF_ISO; 438 isoaddr.siso_tlen = 2; 439 cp = TSEL(&isoaddr); 440 *cp++ = (NFS_PORT >> 8); 441 *cp = (NFS_PORT & 0xff); 442 isoaddr.siso_len = sizeof(isoaddr); 443 if (bind(sock, 444 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) { 445 syslog(LOG_ERR, "can't bind cltp addr"); 446 exit(1); 447 } 448 #ifdef notyet 449 /* 450 * XXX 451 * Someday this should probably use "rpcbind", the son of 452 * portmap. 453 */ 454 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { 455 syslog(LOG_ERR, "can't register with udp portmap"); 456 exit(1); 457 } 458 #endif /* notyet */ 459 nfsdargs.sock = sock; 460 nfsdargs.name = NULL; 461 nfsdargs.namelen = 0; 462 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 463 syslog(LOG_ERR, "can't add UDP socket"); 464 exit(1); 465 } 466 close(sock); 467 } 468 #endif /* ISO */ 469 470 /* Now set up the master server socket waiting for tcp connections. */ 471 on = 1; 472 FD_ZERO(&sockbits); 473 connect_type_cnt = 0; 474 for (i = 0; tcpflag && i < bindhostc; i++) { 475 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 476 syslog(LOG_ERR, "can't create tcp socket"); 477 exit(1); 478 } 479 if (setsockopt(tcpsock, 480 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 481 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 482 setbindhost(&inetaddr, bindhost[i]); 483 if (bind(tcpsock, 484 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 485 syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]); 486 exit(1); 487 } 488 if (listen(tcpsock, 5) < 0) { 489 syslog(LOG_ERR, "listen failed"); 490 exit(1); 491 } 492 if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || 493 !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) { 494 syslog(LOG_ERR, "can't register tcp with portmap"); 495 exit(1); 496 } 497 FD_SET(tcpsock, &sockbits); 498 maxsock = tcpsock; 499 connect_type_cnt++; 500 } 501 502 #ifdef notyet 503 /* Now set up the master server socket waiting for tp4 connections. */ 504 if (tp4flag) { 505 if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) { 506 syslog(LOG_ERR, "can't create tp4 socket"); 507 exit(1); 508 } 509 if (setsockopt(tp4sock, 510 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 511 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 512 memset(&isoaddr, 0, sizeof(isoaddr)); 513 isoaddr.siso_family = AF_ISO; 514 isoaddr.siso_tlen = 2; 515 cp = TSEL(&isoaddr); 516 *cp++ = (NFS_PORT >> 8); 517 *cp = (NFS_PORT & 0xff); 518 isoaddr.siso_len = sizeof(isoaddr); 519 if (bind(tp4sock, 520 (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) { 521 syslog(LOG_ERR, "can't bind tp4 addr"); 522 exit(1); 523 } 524 if (listen(tp4sock, 5) < 0) { 525 syslog(LOG_ERR, "listen failed"); 526 exit(1); 527 } 528 /* 529 * XXX 530 * Someday this should probably use "rpcbind", the son of 531 * portmap. 532 */ 533 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 534 syslog(LOG_ERR, "can't register tcp with portmap"); 535 exit(1); 536 } 537 FD_SET(tp4sock, &sockbits); 538 maxsock = tp4sock; 539 connect_type_cnt++; 540 } 541 542 /* Now set up the master server socket waiting for tpip connections. */ 543 for (i = 0; tpipflag && i < bindhostc; i++) { 544 if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) { 545 syslog(LOG_ERR, "can't create tpip socket"); 546 exit(1); 547 } 548 if (setsockopt(tpipsock, 549 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 550 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 551 setbindhost(&inetaddr, bindhost[i]); 552 if (bind(tpipsock, 553 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 554 syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]); 555 exit(1); 556 } 557 if (listen(tpipsock, 5) < 0) { 558 syslog(LOG_ERR, "listen failed"); 559 exit(1); 560 } 561 /* 562 * XXX 563 * Someday this should probably use "rpcbind", the son of 564 * portmap. 565 */ 566 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 567 syslog(LOG_ERR, "can't register tcp with portmap"); 568 exit(1); 569 } 570 FD_SET(tpipsock, &sockbits); 571 maxsock = tpipsock; 572 connect_type_cnt++; 573 } 574 #endif /* notyet */ 575 576 if (connect_type_cnt == 0) 577 exit(0); 578 579 setproctitle("master"); 580 581 /* 582 * Loop forever accepting connections and passing the sockets 583 * into the kernel for the mounts. 584 */ 585 for (;;) { 586 ready = sockbits; 587 if (connect_type_cnt > 1) { 588 if (select(maxsock + 1, 589 &ready, NULL, NULL, NULL) < 1) { 590 syslog(LOG_ERR, "select failed: %m"); 591 exit(1); 592 } 593 } 594 if (tcpflag && FD_ISSET(tcpsock, &ready)) { 595 len = sizeof(inetpeer); 596 if ((msgsock = accept(tcpsock, 597 (struct sockaddr *)&inetpeer, &len)) < 0) { 598 syslog(LOG_ERR, "accept failed: %m"); 599 exit(1); 600 } 601 memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); 602 if (setsockopt(msgsock, SOL_SOCKET, 603 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 604 syslog(LOG_ERR, 605 "setsockopt SO_KEEPALIVE: %m"); 606 nfsdargs.sock = msgsock; 607 nfsdargs.name = (caddr_t)&inetpeer; 608 nfsdargs.namelen = sizeof(inetpeer); 609 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 610 (void)close(msgsock); 611 } 612 #ifdef notyet 613 if (tp4flag && FD_ISSET(tp4sock, &ready)) { 614 len = sizeof(isopeer); 615 if ((msgsock = accept(tp4sock, 616 (struct sockaddr *)&isopeer, &len)) < 0) { 617 syslog(LOG_ERR, "accept failed: %m"); 618 exit(1); 619 } 620 if (setsockopt(msgsock, SOL_SOCKET, 621 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 622 syslog(LOG_ERR, 623 "setsockopt SO_KEEPALIVE: %m"); 624 nfsdargs.sock = msgsock; 625 nfsdargs.name = (caddr_t)&isopeer; 626 nfsdargs.namelen = len; 627 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 628 (void)close(msgsock); 629 } 630 if (tpipflag && FD_ISSET(tpipsock, &ready)) { 631 len = sizeof(inetpeer); 632 if ((msgsock = accept(tpipsock, 633 (struct sockaddr *)&inetpeer, &len)) < 0) { 634 syslog(LOG_ERR, "accept failed: %m"); 635 exit(1); 636 } 637 if (setsockopt(msgsock, SOL_SOCKET, 638 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 639 syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); 640 nfsdargs.sock = msgsock; 641 nfsdargs.name = (caddr_t)&inetpeer; 642 nfsdargs.namelen = len; 643 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 644 (void)close(msgsock); 645 } 646 #endif /* notyet */ 647 } 648 } 649 650 void 651 setbindhost(struct sockaddr_in *ia, const char *bindhost) 652 { 653 ia->sin_family = AF_INET; 654 ia->sin_port = htons(NFS_PORT); 655 ia->sin_len = sizeof(*ia); 656 if (bindhost == NULL || strcmp(bindhost,"*") == 0) { 657 ia->sin_addr.s_addr = INADDR_ANY; 658 } else { 659 if (inet_aton(bindhost, &ia->sin_addr) == 0) { 660 struct hostent *he; 661 662 he = gethostbyname2(bindhost, ia->sin_family); 663 if (he == NULL) { 664 syslog(LOG_ERR, "gethostbyname of %s failed", bindhost); 665 exit(1); 666 } 667 bcopy(he->h_addr, &ia->sin_addr, he->h_length); 668 } 669 } 670 } 671 672 void 673 usage() 674 { 675 (void)fprintf(stderr, "usage: nfsd %s\n", USAGE); 676 exit(1); 677 } 678 679 void 680 nonfs(signo) 681 int signo; 682 { 683 syslog(LOG_ERR, "missing system call: NFS not available"); 684 } 685 686 void 687 reapchild(signo) 688 int signo; 689 { 690 691 while (wait3(NULL, WNOHANG, NULL) > 0); 692 } 693 694 #ifdef OLD_SETPROCTITLE 695 #ifdef __FreeBSD__ 696 void 697 setproctitle(a) 698 char *a; 699 { 700 register char *cp; 701 char buf[80]; 702 703 cp = Argv[0]; 704 (void)snprintf(buf, sizeof(buf), "nfsd-%s", a); 705 (void)strncpy(cp, buf, LastArg - cp); 706 cp += strlen(cp); 707 while (cp < LastArg) 708 *cp++ = '\0'; 709 Argv[1] = NULL; 710 } 711 #endif /* __FreeBSD__ */ 712 #endif 713