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