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 148 /* Save start and extent of argv for setproctitle. */ 149 Argv = argv; 150 if (envp == 0 || *envp == 0) 151 envp = argv; 152 while (*envp) 153 envp++; 154 LastArg = envp[-1] + strlen(envp[-1]); 155 156 #define MAXNFSDCNT 20 157 #define DEFNFSDCNT 4 158 nfsdcnt = DEFNFSDCNT; 159 cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0; 160 tpipflag = udpflag = 0; 161 #ifdef ISO 162 #define GETOPT "cn:rtu" 163 #define USAGE "[-crtu] [-n num_servers]" 164 #else 165 #define GETOPT "n:rtu" 166 #define USAGE "[-rtu] [-n num_servers]" 167 #endif 168 while ((ch = getopt(argc, argv, GETOPT)) != EOF) 169 switch (ch) { 170 case 'n': 171 nfsdcnt = atoi(optarg); 172 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 173 warnx("nfsd count %d; reset to %d", DEFNFSDCNT); 174 nfsdcnt = DEFNFSDCNT; 175 } 176 break; 177 case 'r': 178 reregister = 1; 179 break; 180 case 't': 181 tcpflag = 1; 182 break; 183 case 'u': 184 udpflag = 1; 185 break; 186 #ifdef ISO 187 case 'c': 188 cltpflag = 1; 189 break; 190 #ifdef notyet 191 case 'i': 192 tp4cnt = 1; 193 break; 194 case 'p': 195 tpipcnt = 1; 196 break; 197 #endif /* notyet */ 198 #endif /* ISO */ 199 default: 200 case '?': 201 usage(); 202 }; 203 argv += optind; 204 argc -= optind; 205 206 /* 207 * XXX 208 * Backward compatibility, trailing number is the count of daemons. 209 */ 210 if (argc > 1) 211 usage(); 212 if (argc == 1) { 213 nfsdcnt = atoi(argv[0]); 214 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 215 warnx("nfsd count %d; reset to %d", DEFNFSDCNT); 216 nfsdcnt = DEFNFSDCNT; 217 } 218 } 219 220 if (debug == 0) { 221 daemon(0, 0); 222 (void)signal(SIGHUP, SIG_IGN); 223 (void)signal(SIGINT, SIG_IGN); 224 (void)signal(SIGQUIT, SIG_IGN); 225 (void)signal(SIGSYS, nonfs); 226 (void)signal(SIGTERM, SIG_IGN); 227 } 228 (void)signal(SIGCHLD, reapchild); 229 230 if (reregister) { 231 if (udpflag && 232 !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) 233 err(1, "can't register with portmap for UDP."); 234 if (tcpflag && 235 !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) 236 err(1, "can't register with portmap for TCP."); 237 exit(0); 238 } 239 openlog("nfsd:", LOG_PID, LOG_DAEMON); 240 241 for (i = 0; i < nfsdcnt; i++) { 242 switch (fork()) { 243 case -1: 244 syslog(LOG_ERR, "fork: %m"); 245 exit (1); 246 case 0: 247 break; 248 default: 249 continue; 250 } 251 252 setproctitle("nfsd-srv"); 253 nfssvc_flag = NFSSVC_NFSD; 254 nsd.nsd_nfsd = NULL; 255 #ifdef KERBEROS 256 nsd.nsd_authstr = (char *)kt.dat; 257 #endif 258 while (nfssvc(nfssvc_flag, &nsd) < 0) { 259 if (errno != ENEEDAUTH) { 260 syslog(LOG_ERR, "nfssvc: %m"); 261 exit(1); 262 } 263 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; 264 #ifdef KERBEROS 265 kt.length = nsd.nsd_authlen; 266 kt.mbz = 0; 267 (void)strcpy(inst, "*"); 268 if (krb_rd_req(&kt, "rcmd", 269 inst, nsd.nsd_haddr, &auth, "") == RD_AP_OK && 270 krb_kntoln(&auth, lnam) == KSUCCESS && 271 (pwd = getpwnam(lnam)) != NULL) { 272 cr = &nsd.nsd_cr; 273 cr->cr_uid = pwd->pw_uid; 274 cr->cr_groups[0] = pwd->pw_gid; 275 cr->cr_ngroups = 1; 276 setgrent(); 277 while ((grp = getgrent()) != NULL) { 278 if (grp->gr_gid == cr->cr_groups[0]) 279 continue; 280 for (cpp = grp->gr_mem; 281 *cpp != NULL; ++cpp) 282 if (!strcmp(*cpp, lnam)) 283 break; 284 if (*cpp == NULL) 285 continue; 286 cr->cr_groups[cr->cr_ngroups++] 287 = grp->gr_gid; 288 if (cr->cr_ngroups == NGROUPS) 289 break; 290 } 291 endgrent(); 292 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; 293 } 294 #endif /* KERBEROS */ 295 } 296 exit(0); 297 } 298 299 /* If we are serving udp, set up the socket. */ 300 if (udpflag) { 301 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 302 syslog(LOG_ERR, "can't create udp socket"); 303 exit(1); 304 } 305 inetaddr.sin_family = AF_INET; 306 inetaddr.sin_addr.s_addr = INADDR_ANY; 307 inetaddr.sin_port = htons(NFS_PORT); 308 inetaddr.sin_len = sizeof(inetaddr); 309 if (bind(sock, 310 (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) { 311 syslog(LOG_ERR, "can't bind udp addr"); 312 exit(1); 313 } 314 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { 315 syslog(LOG_ERR, "can't register with udp portmap"); 316 exit(1); 317 } 318 nfsdargs.sock = sock; 319 nfsdargs.name = NULL; 320 nfsdargs.namelen = 0; 321 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 322 syslog(LOG_ERR, "can't Add UDP socket"); 323 exit(1); 324 } 325 (void)close(sock); 326 } 327 328 #ifdef ISO 329 /* If we are serving cltp, set up the socket. */ 330 if (cltpflag) { 331 if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) { 332 syslog(LOG_ERR, "can't create cltp socket"); 333 exit(1); 334 } 335 memset(&isoaddr, 0, sizeof(isoaddr)); 336 isoaddr.siso_family = AF_ISO; 337 isoaddr.siso_tlen = 2; 338 cp = TSEL(&isoaddr); 339 *cp++ = (NFS_PORT >> 8); 340 *cp = (NFS_PORT & 0xff); 341 isoaddr.siso_len = sizeof(isoaddr); 342 if (bind(sock, 343 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) { 344 syslog(LOG_ERR, "can't bind cltp addr"); 345 exit(1); 346 } 347 #ifdef notyet 348 /* 349 * XXX 350 * Someday this should probably use "rpcbind", the son of 351 * portmap. 352 */ 353 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { 354 syslog(LOG_ERR, "can't register with udp portmap"); 355 exit(1); 356 } 357 #endif /* notyet */ 358 nfsdargs.sock = sock; 359 nfsdargs.name = NULL; 360 nfsdargs.namelen = 0; 361 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 362 syslog(LOG_ERR, "can't add UDP socket"); 363 exit(1); 364 } 365 close(sock); 366 } 367 #endif /* ISO */ 368 369 /* Now set up the master server socket waiting for tcp connections. */ 370 on = 1; 371 FD_ZERO(&sockbits); 372 connect_type_cnt = 0; 373 if (tcpflag) { 374 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 375 syslog(LOG_ERR, "can't create tcp socket"); 376 exit(1); 377 } 378 if (setsockopt(tcpsock, 379 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 380 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 381 inetaddr.sin_family = AF_INET; 382 inetaddr.sin_addr.s_addr = INADDR_ANY; 383 inetaddr.sin_port = htons(NFS_PORT); 384 inetaddr.sin_len = sizeof(inetaddr); 385 if (bind(tcpsock, 386 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 387 syslog(LOG_ERR, "can't bind tcp addr"); 388 exit(1); 389 } 390 if (listen(tcpsock, 5) < 0) { 391 syslog(LOG_ERR, "listen failed"); 392 exit(1); 393 } 394 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 395 syslog(LOG_ERR, "can't register tcp with portmap"); 396 exit(1); 397 } 398 FD_SET(tcpsock, &sockbits); 399 maxsock = tcpsock; 400 connect_type_cnt++; 401 } 402 403 #ifdef notyet 404 /* Now set up the master server socket waiting for tp4 connections. */ 405 if (tp4flag) { 406 if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) { 407 syslog(LOG_ERR, "can't create tp4 socket"); 408 exit(1); 409 } 410 if (setsockopt(tp4sock, 411 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 412 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 413 memset(&isoaddr, 0, sizeof(isoaddr)); 414 isoaddr.siso_family = AF_ISO; 415 isoaddr.siso_tlen = 2; 416 cp = TSEL(&isoaddr); 417 *cp++ = (NFS_PORT >> 8); 418 *cp = (NFS_PORT & 0xff); 419 isoaddr.siso_len = sizeof(isoaddr); 420 if (bind(tp4sock, 421 (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) { 422 syslog(LOG_ERR, "can't bind tp4 addr"); 423 exit(1); 424 } 425 if (listen(tp4sock, 5) < 0) { 426 syslog(LOG_ERR, "listen failed"); 427 exit(1); 428 } 429 /* 430 * XXX 431 * Someday this should probably use "rpcbind", the son of 432 * portmap. 433 */ 434 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 435 syslog(LOG_ERR, "can't register tcp with portmap"); 436 exit(1); 437 } 438 FD_SET(tp4sock, &sockbits); 439 maxsock = tp4sock; 440 connect_type_cnt++; 441 } 442 443 /* Now set up the master server socket waiting for tpip connections. */ 444 if (tpipflag) { 445 if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) { 446 syslog(LOG_ERR, "can't create tpip socket"); 447 exit(1); 448 } 449 if (setsockopt(tpipsock, 450 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 451 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 452 inetaddr.sin_family = AF_INET; 453 inetaddr.sin_addr.s_addr = INADDR_ANY; 454 inetaddr.sin_port = htons(NFS_PORT); 455 inetaddr.sin_len = sizeof(inetaddr); 456 if (bind(tpipsock, 457 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 458 syslog(LOG_ERR, "can't bind tcp addr"); 459 exit(1); 460 } 461 if (listen(tpipsock, 5) < 0) { 462 syslog(LOG_ERR, "listen failed"); 463 exit(1); 464 } 465 /* 466 * XXX 467 * Someday this should probably use "rpcbind", the son of 468 * portmap. 469 */ 470 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 471 syslog(LOG_ERR, "can't register tcp with portmap"); 472 exit(1); 473 } 474 FD_SET(tpipsock, &sockbits); 475 maxsock = tpipsock; 476 connect_type_cnt++; 477 } 478 #endif /* notyet */ 479 480 if (connect_type_cnt == 0) 481 exit(0); 482 483 setproctitle("nfsd-master"); 484 485 /* 486 * Loop forever accepting connections and passing the sockets 487 * into the kernel for the mounts. 488 */ 489 for (;;) { 490 ready = sockbits; 491 if (connect_type_cnt > 1) { 492 if (select(maxsock + 1, 493 &ready, NULL, NULL, NULL) < 1) { 494 syslog(LOG_ERR, "select failed: %m"); 495 exit(1); 496 } 497 } 498 if (tcpflag && FD_ISSET(tcpsock, &ready)) { 499 len = sizeof(inetpeer); 500 if ((msgsock = accept(tcpsock, 501 (struct sockaddr *)&inetpeer, &len)) < 0) { 502 syslog(LOG_ERR, "accept failed: %m"); 503 exit(1); 504 } 505 memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); 506 if (setsockopt(msgsock, SOL_SOCKET, 507 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 508 syslog(LOG_ERR, 509 "setsockopt SO_KEEPALIVE: %m"); 510 nfsdargs.sock = msgsock; 511 nfsdargs.name = (caddr_t)&inetpeer; 512 nfsdargs.namelen = sizeof(inetpeer); 513 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 514 (void)close(msgsock); 515 } 516 #ifdef notyet 517 if (tp4flag && FD_ISSET(tp4sock, &ready)) { 518 len = sizeof(isopeer); 519 if ((msgsock = accept(tp4sock, 520 (struct sockaddr *)&isopeer, &len)) < 0) { 521 syslog(LOG_ERR, "accept failed: %m"); 522 exit(1); 523 } 524 if (setsockopt(msgsock, SOL_SOCKET, 525 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 526 syslog(LOG_ERR, 527 "setsockopt SO_KEEPALIVE: %m"); 528 nfsdargs.sock = msgsock; 529 nfsdargs.name = (caddr_t)&isopeer; 530 nfsdargs.namelen = len; 531 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 532 (void)close(msgsock); 533 } 534 if (tpipflag && FD_ISSET(tpipsock, &ready)) { 535 len = sizeof(inetpeer); 536 if ((msgsock = accept(tpipsock, 537 (struct sockaddr *)&inetpeer, &len)) < 0) { 538 syslog(LOG_ERR, "Accept failed: %m"); 539 exit(1); 540 } 541 if (setsockopt(msgsock, SOL_SOCKET, 542 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 543 syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); 544 nfsdargs.sock = msgsock; 545 nfsdargs.name = (caddr_t)&inetpeer; 546 nfsdargs.namelen = len; 547 nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 548 (void)close(msgsock); 549 } 550 #endif /* notyet */ 551 } 552 } 553 554 void 555 usage() 556 { 557 (void)fprintf(stderr, "nfsd %s\n", USAGE); 558 exit(1); 559 } 560 561 void 562 nonfs(signo) 563 int signo; 564 { 565 syslog(LOG_ERR, "missing system call: NFS not available."); 566 } 567 568 void 569 reapchild(signo) 570 int signo; 571 { 572 573 while (wait3(NULL, WNOHANG, NULL)); 574 } 575 576 void 577 setproctitle(a) 578 char *a; 579 { 580 register char *cp; 581 char buf[80]; 582 583 cp = Argv[0]; 584 (void)snprintf(buf, sizeof(buf), "%s", a); 585 (void)strncpy(cp, buf, LastArg - cp); 586 cp += strlen(cp); 587 while (cp < LastArg) 588 *cp++ = ' '; 589 } 590