1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 /* LINTLIBRARY */ 41 /* PROTOLIB1 */ 42 43 #pragma ident "%Z%%M% %I% %E% SMI" 44 45 /* NFS server */ 46 47 #include <sys/param.h> 48 #include <sys/types.h> 49 #include <syslog.h> 50 #include <tiuser.h> 51 #include <rpc/rpc.h> 52 #include <errno.h> 53 #include <thread.h> 54 #include <sys/resource.h> 55 #include <sys/time.h> 56 #include <sys/file.h> 57 #include <nfs/nfs.h> 58 #include <nfs/nfs_acl.h> 59 #include <nfs/nfssys.h> 60 #include <stdio.h> 61 #include <stdlib.h> 62 #include <signal.h> 63 #include <netconfig.h> 64 #include <netdir.h> 65 #include <string.h> 66 #include <unistd.h> 67 #include <stropts.h> 68 #include <sys/tihdr.h> 69 #include <poll.h> 70 #include <priv_utils.h> 71 #include <sys/tiuser.h> 72 #include <netinet/tcp.h> 73 #include <deflt.h> 74 #include <rpcsvc/daemon_utils.h> 75 #include <rpcsvc/nfs4_prot.h> 76 #include "nfs_tbind.h" 77 #include "thrpool.h" 78 79 /* quiesce requests will be ignored if nfs_server_vers_max < QUIESCE_VERSMIN */ 80 #define QUIESCE_VERSMIN 4 81 82 static int nfssvc(int, struct netbuf, struct netconfig *); 83 static int nfssvcpool(int maxservers); 84 static void usage(void); 85 86 extern int _nfssys(int, void *); 87 88 /* signal handlers */ 89 static void sigflush(int); 90 static void quiesce(int); 91 92 static char *MyName; 93 static NETSELDECL(defaultproviders)[] = { "/dev/tcp6", "/dev/tcp", "/dev/udp", 94 "/dev/udp6", NULL }; 95 /* static NETSELDECL(defaultprotos)[] = { NC_UDP, NC_TCP, NULL }; */ 96 /* 97 * The following are all globals used by routines in nfs_tbind.c. 98 */ 99 size_t end_listen_fds; /* used by conn_close_oldest() */ 100 size_t num_fds = 0; /* used by multiple routines */ 101 int listen_backlog = 32; /* used by bind_to_{provider,proto}() */ 102 int num_servers; /* used by cots_listen_event() */ 103 int (*Mysvc)(int, struct netbuf, struct netconfig *) = nfssvc; 104 /* used by cots_listen_event() */ 105 int max_conns_allowed = -1; /* used by cots_listen_event() */ 106 107 /* 108 * Keep track of min/max versions of NFS protocol to be started. 109 * Start with the defaults (min == 2, max == 3). We have the 110 * capability of starting vers=4 but only if the user requests it. 111 */ 112 int nfs_server_vers_min = NFS_VERSMIN_DEFAULT; 113 int nfs_server_vers_max = NFS_VERSMAX_DEFAULT; 114 115 /* 116 * Set the default for server delegation enablement and set per 117 * /etc/default/nfs configuration (if present). 118 */ 119 int nfs_server_delegation = NFS_SERVER_DELEGATION_DEFAULT; 120 121 int 122 main(int ac, char *av[]) 123 { 124 char *dir = "/"; 125 int allflag = 0; 126 int df_allflag = 0; 127 int opt_cnt = 0; 128 int maxservers = 1; /* zero allows inifinte number of threads */ 129 int maxservers_set = 0; 130 int logmaxservers = 0; 131 int pid; 132 int i; 133 char *provider = (char *)NULL; 134 char *df_provider = (char *)NULL; 135 struct protob *protobp0, *protobp; 136 NETSELDECL(proto) = NULL; 137 NETSELDECL(df_proto) = NULL; 138 NETSELPDECL(providerp); 139 char *defval; 140 141 MyName = *av; 142 143 /* 144 * Initializations that require more privileges than we need to run. 145 */ 146 (void) _create_daemon_lock(NFSD, DAEMON_UID, DAEMON_GID); 147 svcsetprio(); 148 149 if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 150 DAEMON_UID, DAEMON_GID, PRIV_SYS_NFS, (char *)NULL) == -1) { 151 (void) fprintf(stderr, "%s should be run with" 152 " sufficient privileges\n", av[0]); 153 exit(1); 154 } 155 156 /* 157 * Read in the values from config file first before we check 158 * commandline options so the options override the file. 159 */ 160 if ((defopen(NFSADMIN)) == 0) { 161 if ((defval = defread("NFSD_MAX_CONNECTIONS=")) != NULL) { 162 errno = 0; 163 max_conns_allowed = strtol(defval, (char **)NULL, 10); 164 if (errno != 0) { 165 max_conns_allowed = -1; 166 } 167 } 168 if ((defval = defread("NFSD_LISTEN_BACKLOG=")) != NULL) { 169 errno = 0; 170 listen_backlog = strtol(defval, (char **)NULL, 10); 171 if (errno != 0) { 172 listen_backlog = 32; 173 } 174 } 175 if ((defval = defread("NFSD_PROTOCOL=")) != NULL) { 176 df_proto = strdup(defval); 177 opt_cnt++; 178 if (strncasecmp("ALL", defval, 3) == 0) { 179 free(df_proto); 180 df_proto = NULL; 181 df_allflag = 1; 182 } 183 } 184 if ((defval = defread("NFSD_DEVICE=")) != NULL) { 185 df_provider = strdup(defval); 186 opt_cnt++; 187 } 188 if ((defval = defread("NFSD_SERVERS=")) != NULL) { 189 errno = 0; 190 maxservers = strtol(defval, (char **)NULL, 10); 191 if (errno != 0) { 192 maxservers = 1; 193 } else { 194 maxservers_set = 1; 195 } 196 } 197 if ((defval = defread("NFS_SERVER_VERSMIN=")) != NULL) { 198 errno = 0; 199 nfs_server_vers_min = 200 strtol(defval, (char **)NULL, 10); 201 if (errno != 0) { 202 nfs_server_vers_min = NFS_VERSMIN_DEFAULT; 203 } 204 } 205 if ((defval = defread("NFS_SERVER_VERSMAX=")) != NULL) { 206 errno = 0; 207 nfs_server_vers_max = 208 strtol(defval, (char **)NULL, 10); 209 if (errno != 0) { 210 nfs_server_vers_max = NFS_VERSMAX_DEFAULT; 211 } 212 } 213 if ((defval = defread("NFS_SERVER_DELEGATION=")) != NULL) { 214 if (strcmp(defval, "off") == 0) { 215 nfs_server_delegation = FALSE; 216 } 217 } 218 219 /* close defaults file */ 220 defopen(NULL); 221 } 222 223 /* 224 * Conflict options error messages. 225 */ 226 if (opt_cnt > 1) { 227 (void) fprintf(stderr, "\nConflicting options, only one of " 228 "the following options can be specified\n" 229 "in " NFSADMIN ":\n" 230 "\tNFSD_PROTOCOL=ALL\n" 231 "\tNFSD_PROTOCOL=protocol\n" 232 "\tNFSD_DEVICE=device\n\n"); 233 usage(); 234 } 235 opt_cnt = 0; 236 237 while ((i = getopt(ac, av, "ac:p:t:l:")) != EOF) { 238 switch (i) { 239 case 'a': 240 free(df_proto); 241 df_proto = NULL; 242 free(df_provider); 243 df_provider = NULL; 244 245 allflag = 1; 246 opt_cnt++; 247 break; 248 249 case 'c': 250 max_conns_allowed = atoi(optarg); 251 break; 252 253 case 'p': 254 proto = optarg; 255 df_allflag = 0; 256 opt_cnt++; 257 break; 258 259 case 't': 260 provider = optarg; 261 df_allflag = 0; 262 opt_cnt++; 263 break; 264 265 case 'l': 266 listen_backlog = atoi(optarg); 267 break; 268 269 case '?': 270 usage(); 271 /* NOTREACHED */ 272 } 273 } 274 275 allflag = df_allflag; 276 if (proto == NULL) 277 proto = df_proto; 278 if (provider == NULL) 279 provider = df_provider; 280 281 /* 282 * Conflict options error messages. 283 */ 284 if (opt_cnt > 1) { 285 (void) fprintf(stderr, "\nConflicting options, only one of " 286 "the following options can be specified\n" 287 "on the command line:\n" 288 "\t-a\n" 289 "\t-p protocol\n" 290 "\t-t transport\n\n"); 291 usage(); 292 } 293 294 if (proto != NULL && 295 strncasecmp(proto, NC_UDP, strlen(NC_UDP)) == 0) { 296 if (nfs_server_vers_max == NFS_V4) { 297 if (nfs_server_vers_min == NFS_V4) { 298 syslog(LOG_ERR, 299 "NFS version 4 is not supported " 300 "with the UDP protocol. Exiting\n"); 301 fprintf(stderr, 302 "NFS version 4 is not supported " 303 "with the UDP protocol. Exiting\n"); 304 exit(3); 305 } else { 306 fprintf(stderr, 307 "NFS version 4 is not supported " 308 "with the UDP protocol.\n"); 309 } 310 } 311 } 312 313 /* 314 * If there is exactly one more argument, it is the number of 315 * servers. 316 */ 317 if (optind == ac - 1) { 318 maxservers = atoi(av[optind]); 319 maxservers_set = 1; 320 } 321 /* 322 * If there are two or more arguments, then this is a usage error. 323 */ 324 else if (optind < ac - 1) 325 usage(); 326 /* 327 * Check the ranges for min/max version specified 328 */ 329 else if ((nfs_server_vers_min > nfs_server_vers_max) || 330 (nfs_server_vers_min < NFS_VERSMIN) || 331 (nfs_server_vers_max > NFS_VERSMAX)) 332 usage(); 333 /* 334 * There are no additional arguments, and we haven't set maxservers 335 * explicitly via the config file, we use a default number of 336 * servers. We will log this. 337 */ 338 else if (maxservers_set == 0) 339 logmaxservers = 1; 340 341 /* 342 * Basic Sanity checks on options 343 * 344 * max_conns_allowed must be positive, except for the special 345 * value of -1 which is used internally to mean unlimited, -1 isn't 346 * documented but we allow it anyway. 347 * 348 * maxservers must be positive 349 * listen_backlog must be positive or zero 350 */ 351 if (((max_conns_allowed != -1) && (max_conns_allowed <= 0)) || 352 (listen_backlog < 0) || (maxservers <= 0)) { 353 usage(); 354 } 355 356 /* 357 * Set current dir to server root 358 */ 359 if (chdir(dir) < 0) { 360 (void) fprintf(stderr, "%s: ", MyName); 361 perror(dir); 362 exit(1); 363 } 364 365 #ifndef DEBUG 366 /* 367 * Background 368 */ 369 pid = fork(); 370 if (pid < 0) { 371 perror("nfsd: fork"); 372 exit(1); 373 } 374 if (pid != 0) 375 exit(0); 376 377 /* 378 * Close existing file descriptors, open "/dev/null" as 379 * standard input, output, and error, and detach from 380 * controlling terminal. 381 */ 382 closefrom(0); 383 (void) open("/dev/null", O_RDONLY); 384 (void) open("/dev/null", O_WRONLY); 385 (void) dup(1); 386 (void) setsid(); 387 #endif 388 openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON); 389 390 /* 391 * establish our lock on the lock file and write our pid to it. 392 * exit if some other process holds the lock, or if there's any 393 * error in writing/locking the file. 394 */ 395 pid = _enter_daemon_lock(NFSD); 396 switch (pid) { 397 case 0: 398 break; 399 case -1: 400 syslog(LOG_ERR, "error locking for %s: %s", NFSD, 401 strerror(errno)); 402 exit(2); 403 default: 404 /* daemon was already running */ 405 exit(0); 406 } 407 408 sigset(SIGTERM, sigflush); 409 sigset(SIGUSR1, quiesce); 410 411 if (logmaxservers) { 412 (void) syslog(LOG_INFO, 413 "Number of servers not specified. Using default of %d.", 414 maxservers); 415 } 416 417 /* 418 * Make sure to unregister any previous versions in case the 419 * user is reconfiguring the server in interesting ways. 420 */ 421 svc_unreg(NFS_PROGRAM, NFS_VERSION); 422 svc_unreg(NFS_PROGRAM, NFS_V3); 423 svc_unreg(NFS_PROGRAM, NFS_V4); 424 svc_unreg(NFS_ACL_PROGRAM, NFS_ACL_V2); 425 svc_unreg(NFS_ACL_PROGRAM, NFS_ACL_V3); 426 427 /* 428 * Set up kernel RPC thread pool for the NFS server. 429 */ 430 if (nfssvcpool(maxservers)) { 431 (void) syslog(LOG_ERR, 432 "Can't set up kernel NFS service: %m. Exiting"); 433 exit(1); 434 } 435 436 437 /* 438 * Set up blocked thread to do LWP creation on behalf of the kernel. 439 */ 440 if (svcwait(NFS_SVCPOOL_ID)) { 441 (void) syslog(LOG_ERR, 442 "Can't set up NFS pool creator: %m, Exiting"); 443 exit(1); 444 } 445 446 /* 447 * RDMA start and stop thread. 448 * Per pool RDMA listener creation and 449 * destructor thread. 450 * 451 * start rdma services and block in the kernel. 452 */ 453 if (svcrdma(NFS_SVCPOOL_ID, nfs_server_vers_min, nfs_server_vers_max, 454 nfs_server_delegation)) { 455 (void) syslog(LOG_ERR, 456 "Can't set up RDMA creator thread : %m."); 457 } 458 459 /* 460 * Build a protocol block list for registration. 461 */ 462 protobp0 = protobp = (struct protob *)malloc(sizeof (struct protob)); 463 protobp->serv = "NFS"; 464 protobp->versmin = nfs_server_vers_min; 465 protobp->versmax = nfs_server_vers_max; 466 protobp->program = NFS_PROGRAM; 467 468 protobp->next = (struct protob *)malloc(sizeof (struct protob)); 469 protobp = protobp->next; 470 protobp->serv = "NFS_ACL"; /* not used */ 471 protobp->versmin = nfs_server_vers_min; 472 /* XXX - this needs work to get the version just right */ 473 protobp->versmax = (nfs_server_vers_max > NFS_ACL_V3) ? 474 NFS_ACL_V3 : nfs_server_vers_max; 475 protobp->program = NFS_ACL_PROGRAM; 476 protobp->next = (struct protob *)NULL; 477 478 if (allflag) { 479 if (do_all(protobp0, nfssvc) == -1) 480 exit(1); 481 } else if (proto) { 482 /* there's more than one match for the same protocol */ 483 struct netconfig *nconf; 484 NCONF_HANDLE *nc; 485 bool_t protoFound = FALSE; 486 if ((nc = setnetconfig()) == (NCONF_HANDLE *) NULL) { 487 syslog(LOG_ERR, "setnetconfig failed: %m"); 488 goto done; 489 } 490 while (nconf = getnetconfig(nc)) { 491 if (strcmp(nconf->nc_proto, proto) == 0) { 492 protoFound = TRUE; 493 do_one(nconf->nc_device, NULL, 494 protobp0, nfssvc); 495 } 496 } 497 (void) endnetconfig(nc); 498 if (protoFound == FALSE) 499 syslog(LOG_ERR, "couldn't find netconfig entry \ 500 for protocol %s", proto); 501 502 } else if (provider) 503 do_one(provider, proto, protobp0, nfssvc); 504 else { 505 for (providerp = defaultproviders; 506 *providerp != NULL; providerp++) { 507 provider = *providerp; 508 do_one(provider, NULL, protobp0, nfssvc); 509 } 510 } 511 done: 512 513 free(protobp); 514 free(protobp0); 515 516 if (num_fds == 0) { 517 (void) syslog(LOG_ERR, 518 "Could not start NFS service for any protocol. Exiting."); 519 exit(1); 520 } 521 522 end_listen_fds = num_fds; 523 524 /* 525 * Get rid of unneeded privileges. 526 */ 527 __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, 528 PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL); 529 530 /* 531 * Poll for non-data control events on the transport descriptors. 532 */ 533 poll_for_action(); 534 535 /* 536 * If we get here, something failed in poll_for_action(). 537 */ 538 return (1); 539 } 540 541 static int 542 nfssvcpool(int maxservers) 543 { 544 struct svcpool_args npa; 545 546 npa.id = NFS_SVCPOOL_ID; 547 npa.maxthreads = maxservers; 548 npa.redline = 0; 549 npa.qsize = 0; 550 npa.timeout = 0; 551 npa.stksize = 0; 552 npa.max_same_xprt = 0; 553 return (_nfssys(SVCPOOL_CREATE, &npa)); 554 } 555 556 /* 557 * Establish NFS service thread. 558 */ 559 static int 560 nfssvc(int fd, struct netbuf addrmask, struct netconfig *nconf) 561 { 562 struct nfs_svc_args nsa; 563 564 nsa.fd = fd; 565 nsa.netid = nconf->nc_netid; 566 nsa.addrmask = addrmask; 567 if (strncasecmp(nconf->nc_proto, NC_UDP, strlen(NC_UDP)) == 0) { 568 nsa.versmax = (nfs_server_vers_max > NFS_V3) ? 569 NFS_V3 : nfs_server_vers_max; 570 nsa.versmin = nfs_server_vers_min; 571 /* 572 * If no version left, silently do nothing, previous 573 * checks will have assured at least TCP is available. 574 */ 575 if (nsa.versmin > nsa.versmax) 576 return (0); 577 } else { 578 nsa.versmax = nfs_server_vers_max; 579 nsa.versmin = nfs_server_vers_min; 580 } 581 nsa.delegation = nfs_server_delegation; 582 return (_nfssys(NFS_SVC, &nsa)); 583 } 584 585 static void 586 usage(void) 587 { 588 (void) fprintf(stderr, 589 "usage: %s [ -a ] [ -c max_conns ] [ -p protocol ] [ -t transport ] ", MyName); 590 (void) fprintf(stderr, "\n[ -l listen_backlog ] [ nservers ]\n"); 591 (void) fprintf(stderr, 592 "\twhere -a causes <nservers> to be started on each appropriate transport,\n"); 593 (void) fprintf(stderr, 594 "\tmax_conns is the maximum number of concurrent connections allowed,\n"); 595 (void) fprintf(stderr, "\t\tand max_conns must be a decimal number"); 596 (void) fprintf(stderr, "> zero,\n"); 597 (void) fprintf(stderr, "\tprotocol is a protocol identifier,\n"); 598 (void) fprintf(stderr, 599 "\ttransport is a transport provider name (i.e. device),\n"); 600 (void) fprintf(stderr, 601 "\tlisten_backlog is the TCP listen backlog,\n"); 602 (void) fprintf(stderr, 603 "\tand <nservers> must be a decimal number > zero.\n"); 604 exit(1); 605 } 606 607 /* 608 * Issue nfssys system call to flush all logging buffers asynchronously. 609 * 610 * NOTICE: It is extremely important to flush NFS logging buffers when 611 * nfsd exits. When the system is halted or rebooted nfslogd 612 * may not have an opportunity to flush the buffers. 613 */ 614 static void 615 nfsl_flush() 616 { 617 struct nfsl_flush_args nfa; 618 619 memset((void *)&nfa, 0, sizeof (nfa)); 620 nfa.version = NFSL_FLUSH_ARGS_VERS; 621 nfa.directive = NFSL_ALL; /* flush all asynchronously */ 622 623 if (_nfssys(LOG_FLUSH, &nfa) < 0) 624 syslog(LOG_ERR, "_nfssys(LOG_FLUSH) failed: %s\n", 625 strerror(errno)); 626 } 627 628 /* 629 * SIGTERM handler. 630 * Flush logging buffers and exit. 631 */ 632 static void 633 sigflush(int sig) 634 { 635 nfsl_flush(); 636 exit(0); 637 } 638 639 /* 640 * SIGUSR1 handler. 641 * Request server quiesce, then exit. For subsequent warm start. 642 * Equivalent to SIGTERM handler if nfs_server_vers_max < QUIESCE_VERSMIN. 643 */ 644 static void 645 quiesce(int sig) 646 { 647 int error; 648 int id = NFS_SVCPOOL_ID; 649 650 if (nfs_server_vers_max >= QUIESCE_VERSMIN) { 651 /* Request server quiesce at next shutdown */ 652 error = _nfssys(NFS_SVC_REQUEST_QUIESCE, &id); 653 if (error) { 654 syslog(LOG_ERR, 655 "_nfssys(NFS_SVC_REQUEST_QUIESCE) failed: %s\n", 656 strerror(errno)); 657 return; 658 } 659 } 660 661 /* Flush logging buffers */ 662 nfsl_flush(); 663 664 exit(0); 665 } 666