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 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 static char sccsid[] = "@(#)nfsd.c 8.7 (Berkeley) 2/22/94"; 45 #endif not lint 46 47 #include <sys/param.h> 48 #include <sys/syslog.h> 49 #include <sys/ioctl.h> 50 #include <sys/stat.h> 51 #include <sys/wait.h> 52 #include <sys/uio.h> 53 #include <sys/ucred.h> 54 #include <sys/mount.h> 55 #include <sys/socket.h> 56 #include <sys/socketvar.h> 57 58 #include <rpc/rpc.h> 59 #include <rpc/pmap_clnt.h> 60 #include <rpc/pmap_prot.h> 61 62 #ifdef ISO 63 #include <netiso/iso.h> 64 #endif 65 #include <nfs/rpcv2.h> 66 #include <nfs/nfsv2.h> 67 #include <nfs/nfs.h> 68 69 #ifdef KERBEROS 70 #include <kerberosIV/des.h> 71 #include <kerberosIV/krb.h> 72 #endif 73 74 #include <err.h> 75 #include <errno.h> 76 #include <fcntl.h> 77 #include <grp.h> 78 #include <pwd.h> 79 #include <signal.h> 80 #include <stdio.h> 81 #include <stdlib.h> 82 #include <strings.h> 83 #include <unistd.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 struct nfsd_srvargs nsd; 94 char **Argv = NULL; /* pointer to argument vector */ 95 char *LastArg = NULL; /* end of argv */ 96 97 #ifdef KERBEROS 98 char lnam[ANAME_SZ]; 99 KTEXT_ST kt; 100 AUTH_DAT auth; 101 char inst[INST_SZ]; 102 #endif 103 104 void nonfs __P((int)); 105 void reapchild __P((int)); 106 void setproctitle __P((char *)); 107 void usage __P((void)); 108 109 /* 110 * Nfs server daemon mostly just a user context for nfssvc() 111 * 112 * 1 - do file descriptor and signal cleanup 113 * 2 - fork the nfsd(s) 114 * 3 - create server socket(s) 115 * 4 - register socket with portmap 116 * 117 * For connectionless protocols, just pass the socket into the kernel via. 118 * nfssvc(). 119 * For connection based sockets, loop doing accepts. When you get a new 120 * socket from accept, pass the msgsock into the kernel via. nfssvc(). 121 * The arguments are: 122 * -c - support iso cltp clients 123 * -r - reregister with portmapper 124 * -t - support tcp nfs clients 125 * -u - support udp nfs clients 126 * followed by "n" which is the number of nfsds' to fork off 127 */ 128 int 129 main(argc, argv, envp) 130 int argc; 131 char *argv[], *envp[]; 132 { 133 extern int optind; 134 struct group *grp; 135 struct nfsd_args nfsdargs; 136 struct passwd *pwd; 137 struct ucred *cr; 138 struct sockaddr_in inetaddr, inetpeer; 139 #ifdef ISO 140 struct sockaddr_iso isoaddr, isopeer; 141 #endif 142 fd_set ready, sockbits; 143 int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock; 144 int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock; 145 int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag; 146 char *cp, **cpp; 147 struct vfsconf *vfc; 148 149 vfc = getvfsbyname("nfs"); 150 if(!vfc && vfsisloadable("nfs")) { 151 if(vfsload("nfs")) 152 err(1, "vfsload(nfs)"); 153 endvfsent(); /* flush cache */ 154 vfc = getvfsbyname("nfs"); /* probably unnecessary */ 155 } 156 if(!vfc) { 157 errx(1, "NFS is not available in the running kernel"); 158 } 159 160 /* Save start and extent of argv for setproctitle. */ 161 Argv = argv; 162 if (envp == 0 || *envp == 0) 163 envp = argv; 164 while (*envp) 165 envp++; 166 LastArg = envp[-1] + strlen(envp[-1]); 167 168 #define MAXNFSDCNT 20 169 #define DEFNFSDCNT 4 170 nfsdcnt = DEFNFSDCNT; 171 cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0; 172 tpipflag = udpflag = 0; 173 #ifdef ISO 174 #define GETOPT "cn:rtu" 175 #define USAGE "[-crtu] [-n num_servers]" 176 #else 177 #define GETOPT "n:rtu" 178 #define USAGE "[-rtu] [-n num_servers]" 179 #endif 180 while ((ch = getopt(argc, argv, GETOPT)) != EOF) 181 switch (ch) { 182 case 'n': 183 nfsdcnt = atoi(optarg); 184 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 185 warnx("nfsd count %d; reset to %d", DEFNFSDCNT); 186 nfsdcnt = DEFNFSDCNT; 187 } 188 break; 189 case 'r': 190 reregister = 1; 191 break; 192 case 't': 193 tcpflag = 1; 194 break; 195 case 'u': 196 udpflag = 1; 197 break; 198 #ifdef ISO 199 case 'c': 200 cltpflag = 1; 201 break; 202 #ifdef notyet 203 case 'i': 204 tp4cnt = 1; 205 break; 206 case 'p': 207 tpipcnt = 1; 208 break; 209 #endif /* notyet */ 210 #endif /* ISO */ 211 default: 212 case '?': 213 usage(); 214 }; 215 argv += optind; 216 argc -= optind; 217 218 /* 219 * XXX 220 * Backward compatibility, trailing number is the count of daemons. 221 */ 222 if (argc > 1) 223 usage(); 224 if (argc == 1) { 225 nfsdcnt = atoi(argv[0]); 226 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 227 warnx("nfsd count %d; reset to %d", DEFNFSDCNT); 228 nfsdcnt = DEFNFSDCNT; 229 } 230 } 231 232 if (debug == 0) { 233 daemon(0, 0); 234 (void)signal(SIGHUP, SIG_IGN); 235 (void)signal(SIGINT, SIG_IGN); 236 (void)signal(SIGQUIT, SIG_IGN); 237 (void)signal(SIGSYS, nonfs); 238 (void)signal(SIGTERM, SIG_IGN); 239 } 240 (void)signal(SIGCHLD, reapchild); 241 242 if (reregister) { 243 if (udpflag && 244 !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) 245 err(1, "can't register with portmap for UDP."); 246 if (tcpflag && 247 !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) 248 err(1, "can't register with portmap for TCP."); 249 exit(0); 250 } 251 openlog("nfsd:", LOG_PID, LOG_DAEMON); 252 253 for (i = 0; i < nfsdcnt; i++) { 254 switch (fork()) { 255 case -1: 256 syslog(LOG_ERR, "fork: %m"); 257 exit (1); 258 case 0: 259 break; 260 default: 261 continue; 262 } 263 264 setproctitle("nfsd-srv"); 265 nfssvc_flag = NFSSVC_NFSD; 266 nsd.nsd_nfsd = NULL; 267 #ifdef KERBEROS 268 nsd.nsd_authstr = (char *)kt.dat; 269 #endif 270 while (nfssvc(nfssvc_flag, &nsd) < 0) { 271 if (errno != ENEEDAUTH) { 272 syslog(LOG_ERR, "nfssvc: %m"); 273 exit(1); 274 } 275 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; 276 #ifdef KERBEROS 277 kt.length = nsd.nsd_authlen; 278 kt.mbz = 0; 279 (void)strcpy(inst, "*"); 280 if (krb_rd_req(&kt, "rcmd", 281 inst, nsd.nsd_haddr, &auth, "") == RD_AP_OK && 282 krb_kntoln(&auth, lnam) == KSUCCESS && 283 (pwd = getpwnam(lnam)) != NULL) { 284 cr = &nsd.nsd_cr; 285 cr->cr_uid = pwd->pw_uid; 286 cr->cr_groups[0] = pwd->pw_gid; 287 cr->cr_ngroups = 1; 288 setgrent(); 289 while ((grp = getgrent()) != NULL) { 290 if (grp->gr_gid == cr->cr_groups[0]) 291 continue; 292 for (cpp = grp->gr_mem; 293 *cpp != NULL; ++cpp) 294 if (!strcmp(*cpp, lnam)) 295 break; 296 if (*cpp == NULL) 297 continue; 298 cr->cr_groups[cr->cr_ngroups++] 299 = grp->gr_gid; 300 if (cr->cr_ngroups == NGROUPS) 301 break; 302 } 303 endgrent(); 304 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; 305 } 306 #endif /* KERBEROS */ 307 } 308 exit(0); 309 } 310 311 /* If we are serving udp, set up the socket. */ 312 if (udpflag) { 313 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 314 syslog(LOG_ERR, "can't create udp socket"); 315 exit(1); 316 } 317 inetaddr.sin_family = AF_INET; 318 inetaddr.sin_addr.s_addr = INADDR_ANY; 319 inetaddr.sin_port = htons(NFS_PORT); 320 inetaddr.sin_len = sizeof(inetaddr); 321 if (bind(sock, 322 (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) { 323 syslog(LOG_ERR, "can't bind udp addr"); 324 exit(1); 325 } 326 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { 327 syslog(LOG_ERR, "can't register with udp portmap"); 328 exit(1); 329 } 330 nfsdargs.sock = sock; 331 nfsdargs.name = NULL; 332 nfsdargs.namelen = 0; 333 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 334 syslog(LOG_ERR, "can't Add UDP socket"); 335 exit(1); 336 } 337 (void)close(sock); 338 } 339 340 #ifdef ISO 341 /* If we are serving cltp, set up the socket. */ 342 if (cltpflag) { 343 if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) { 344 syslog(LOG_ERR, "can't create cltp socket"); 345 exit(1); 346 } 347 memset(&isoaddr, 0, sizeof(isoaddr)); 348 isoaddr.siso_family = AF_ISO; 349 isoaddr.siso_tlen = 2; 350 cp = TSEL(&isoaddr); 351 *cp++ = (NFS_PORT >> 8); 352 *cp = (NFS_PORT & 0xff); 353 isoaddr.siso_len = sizeof(isoaddr); 354 if (bind(sock, 355 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) { 356 syslog(LOG_ERR, "can't bind cltp addr"); 357 exit(1); 358 } 359 #ifdef notyet 360 /* 361 * XXX 362 * Someday this should probably use "rpcbind", the son of 363 * portmap. 364 */ 365 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { 366 syslog(LOG_ERR, "can't register with udp portmap"); 367 exit(1); 368 } 369 #endif /* notyet */ 370 nfsdargs.sock = sock; 371 nfsdargs.name = NULL; 372 nfsdargs.namelen = 0; 373 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 374 syslog(LOG_ERR, "can't add UDP socket"); 375 exit(1); 376 } 377 close(sock); 378 } 379 #endif /* ISO */ 380 381 /* Now set up the master server socket waiting for tcp connections. */ 382 on = 1; 383 FD_ZERO(&sockbits); 384 connect_type_cnt = 0; 385 if (tcpflag) { 386 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 387 syslog(LOG_ERR, "can't create tcp socket"); 388 exit(1); 389 } 390 if (setsockopt(tcpsock, 391 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 392 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 393 inetaddr.sin_family = AF_INET; 394 inetaddr.sin_addr.s_addr = INADDR_ANY; 395 inetaddr.sin_port = htons(NFS_PORT); 396 inetaddr.sin_len = sizeof(inetaddr); 397 if (bind(tcpsock, 398 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 399 syslog(LOG_ERR, "can't bind tcp addr"); 400 exit(1); 401 } 402 if (listen(tcpsock, 5) < 0) { 403 syslog(LOG_ERR, "listen failed"); 404 exit(1); 405 } 406 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 407 syslog(LOG_ERR, "can't register tcp with portmap"); 408 exit(1); 409 } 410 FD_SET(tcpsock, &sockbits); 411 maxsock = tcpsock; 412 connect_type_cnt++; 413 } 414 415 #ifdef notyet 416 /* Now set up the master server socket waiting for tp4 connections. */ 417 if (tp4flag) { 418 if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) { 419 syslog(LOG_ERR, "can't create tp4 socket"); 420 exit(1); 421 } 422 if (setsockopt(tp4sock, 423 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 424 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 425 memset(&isoaddr, 0, sizeof(isoaddr)); 426 isoaddr.siso_family = AF_ISO; 427 isoaddr.siso_tlen = 2; 428 cp = TSEL(&isoaddr); 429 *cp++ = (NFS_PORT >> 8); 430 *cp = (NFS_PORT & 0xff); 431 isoaddr.siso_len = sizeof(isoaddr); 432 if (bind(tp4sock, 433 (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) { 434 syslog(LOG_ERR, "can't bind tp4 addr"); 435 exit(1); 436 } 437 if (listen(tp4sock, 5) < 0) { 438 syslog(LOG_ERR, "listen failed"); 439 exit(1); 440 } 441 /* 442 * XXX 443 * Someday this should probably use "rpcbind", the son of 444 * portmap. 445 */ 446 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 447 syslog(LOG_ERR, "can't register tcp with portmap"); 448 exit(1); 449 } 450 FD_SET(tp4sock, &sockbits); 451 maxsock = tp4sock; 452 connect_type_cnt++; 453 } 454 455 /* Now set up the master server socket waiting for tpip connections. */ 456 if (tpipflag) { 457 if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) { 458 syslog(LOG_ERR, "can't create tpip socket"); 459 exit(1); 460 } 461 if (setsockopt(tpipsock, 462 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 463 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 464 inetaddr.sin_family = AF_INET; 465 inetaddr.sin_addr.s_addr = INADDR_ANY; 466 inetaddr.sin_port = htons(NFS_PORT); 467 inetaddr.sin_len = sizeof(inetaddr); 468 if (bind(tpipsock, 469 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 470 syslog(LOG_ERR, "can't bind tcp addr"); 471 exit(1); 472 } 473 if (listen(tpipsock, 5) < 0) { 474 syslog(LOG_ERR, "listen failed"); 475 exit(1); 476 } 477 /* 478 * XXX 479 * Someday this should probably use "rpcbind", the son of 480 * portmap. 481 */ 482 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 483 syslog(LOG_ERR, "can't register tcp with portmap"); 484 exit(1); 485 } 486 FD_SET(tpipsock, &sockbits); 487 maxsock = tpipsock; 488 connect_type_cnt++; 489 } 490 #endif /* notyet */ 491 492 if (connect_type_cnt == 0) 493 exit(0); 494 495 setproctitle("nfsd-master"); 496 497 /* 498 * Loop forever accepting connections and passing the sockets 499 * into the kernel for the mounts. 500 */ 501 for (;;) { 502 ready = sockbits; 503 if (connect_type_cnt > 1) { 504 if (select(maxsock + 1, 505 &ready, NULL, NULL, NULL) < 1) { 506 syslog(LOG_ERR, "select failed: %m"); 507 exit(1); 508 } 509 } 510 if (tcpflag && FD_ISSET(tcpsock, &ready)) { 511 len = sizeof(inetpeer); 512 if ((msgsock = accept(tcpsock, 513 (struct sockaddr *)&inetpeer, &len)) < 0) { 514 syslog(LOG_ERR, "accept failed: %m"); 515 exit(1); 516 } 517 memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); 518 if (setsockopt(msgsock, SOL_SOCKET, 519 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 520 syslog(LOG_ERR, 521 "setsockopt SO_KEEPALIVE: %m"); 522 nfsdargs.sock = msgsock; 523 nfsdargs.name = (caddr_t)&inetpeer; 524 nfsdargs.namelen = sizeof(inetpeer); 525 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 526 (void)close(msgsock); 527 } 528 #ifdef notyet 529 if (tp4flag && FD_ISSET(tp4sock, &ready)) { 530 len = sizeof(isopeer); 531 if ((msgsock = accept(tp4sock, 532 (struct sockaddr *)&isopeer, &len)) < 0) { 533 syslog(LOG_ERR, "accept failed: %m"); 534 exit(1); 535 } 536 if (setsockopt(msgsock, SOL_SOCKET, 537 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 538 syslog(LOG_ERR, 539 "setsockopt SO_KEEPALIVE: %m"); 540 nfsdargs.sock = msgsock; 541 nfsdargs.name = (caddr_t)&isopeer; 542 nfsdargs.namelen = len; 543 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 544 (void)close(msgsock); 545 } 546 if (tpipflag && FD_ISSET(tpipsock, &ready)) { 547 len = sizeof(inetpeer); 548 if ((msgsock = accept(tpipsock, 549 (struct sockaddr *)&inetpeer, &len)) < 0) { 550 syslog(LOG_ERR, "Accept failed: %m"); 551 exit(1); 552 } 553 if (setsockopt(msgsock, SOL_SOCKET, 554 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 555 syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); 556 nfsdargs.sock = msgsock; 557 nfsdargs.name = (caddr_t)&inetpeer; 558 nfsdargs.namelen = len; 559 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 560 (void)close(msgsock); 561 } 562 #endif /* notyet */ 563 } 564 } 565 566 void 567 usage() 568 { 569 (void)fprintf(stderr, "nfsd %s\n", USAGE); 570 exit(1); 571 } 572 573 void 574 nonfs(signo) 575 int signo; 576 { 577 syslog(LOG_ERR, "missing system call: NFS not available."); 578 } 579 580 void 581 reapchild(signo) 582 int signo; 583 { 584 585 while (wait3(NULL, WNOHANG, NULL)); 586 } 587 588 void 589 setproctitle(a) 590 char *a; 591 { 592 register char *cp; 593 char buf[80]; 594 595 cp = Argv[0]; 596 (void)snprintf(buf, sizeof(buf), "%s", a); 597 (void)strncpy(cp, buf, LastArg - cp); 598 cp += strlen(cp); 599 while (cp < LastArg) 600 *cp++ = '\0'; 601 } 602