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