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 /*
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * Portions of this source code were derived from Berkeley 4.3 BSD
32 * under license from the Regents of the University of California.
33 */
34
35 #include <stdio.h>
36 #include <stdio_ext.h>
37 #include <stdlib.h>
38 #include <ctype.h>
39 #include <sys/types.h>
40 #include <string.h>
41 #include <syslog.h>
42 #include <sys/param.h>
43 #include <rpc/rpc.h>
44 #include <sys/stat.h>
100
101 static mutex_t logging_queue_lock;
102 static cond_t logging_queue_cv;
103
104 static share_t *find_lofsentry(char *, int *);
105 static int getclientsflavors_old(share_t *, struct cln *, int *);
106 static int getclientsflavors_new(share_t *, struct cln *, int *);
107 static int check_client_old(share_t *, struct cln *, int, uid_t, gid_t, uint_t,
108 gid_t *, uid_t *, gid_t *, uint_t *, gid_t **);
109 static int check_client_new(share_t *, struct cln *, int, uid_t, gid_t, uint_t,
110 gid_t *, uid_t *, gid_t *i, uint_t *, gid_t **);
111 static void mnt(struct svc_req *, SVCXPRT *);
112 static void mnt_pathconf(struct svc_req *);
113 static int mount(struct svc_req *r);
114 static void sh_free(struct sh_list *);
115 static void umount(struct svc_req *);
116 static void umountall(struct svc_req *);
117 static int newopts(char *);
118 static tsol_tpent_t *get_client_template(struct sockaddr *);
119
120 static int verbose;
121 static int rejecting;
122 static int mount_vers_min = MOUNTVERS;
123 static int mount_vers_max = MOUNTVERS3;
124
125 extern void nfscmd_func(void *, char *, size_t, door_desc_t *, uint_t);
126
127 thread_t nfsauth_thread;
128 thread_t cmd_thread;
129 thread_t logging_thread;
130
131 typedef struct logging_data {
132 char *ld_host;
133 char *ld_path;
134 char *ld_rpath;
135 int ld_status;
136 char *ld_netid;
137 struct netbuf *ld_nb;
138 struct logging_data *ld_next;
139 } logging_data;
140
141 static logging_data *logging_head = NULL;
142 static logging_data *logging_tail = NULL;
143
345 syslog(LOG_ERR, gettext("Logging server exited"));
346 return (NULL);
347 }
348
349 static int
350 convert_int(int *val, char *str)
351 {
352 long lval;
353
354 if (str == NULL || !isdigit(*str))
355 return (-1);
356
357 lval = strtol(str, &str, 10);
358 if (*str != '\0' || lval > INT_MAX)
359 return (-2);
360
361 *val = (int)lval;
362 return (0);
363 }
364
365 int
366 main(int argc, char *argv[])
367 {
368 int pid;
369 int c;
370 int rpc_svc_fdunlim = 1;
371 int rpc_svc_mode = RPC_SVC_MT_AUTO;
372 int maxrecsz = RPC_MAXDATASIZE;
373 bool_t exclbind = TRUE;
374 bool_t can_do_mlp;
375 long thr_flags = (THR_NEW_LWP|THR_DAEMON);
376 char defval[4];
377 int defvers, ret, bufsz;
378 struct rlimit rl;
379 int listen_backlog = 0;
380 int max_threads = 0;
381 int tmp;
382
383 int pipe_fd = -1;
384
385 /*
386 * Mountd requires uid 0 for:
387 * /etc/rmtab updates (we could chown it to daemon)
388 * /etc/dfs/dfstab reading (it wants to lock out share which
389 * doesn't do any locking before first truncate;
390 * NFS share does; should use fcntl locking instead)
391 * Needed privileges:
392 * auditing
393 * nfs syscall
394 * file dac search (so it can stat all files)
395 * Optional privileges:
396 * MLP
397 */
398 can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP);
399 if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, -1, -1,
400 PRIV_SYS_NFS, PRIV_PROC_AUDIT, PRIV_FILE_DAC_SEARCH,
401 can_do_mlp ? PRIV_NET_BINDMLP : NULL, NULL) == -1) {
402 (void) fprintf(stderr,
403 "%s: must be run with sufficient privileges\n",
404 argv[0]);
405 exit(1);
406 }
407
408 if (getrlimit(RLIMIT_NOFILE, &rl) != 0) {
409 syslog(LOG_ERR, "getrlimit failed");
410 } else {
411 rl.rlim_cur = rl.rlim_max;
412 if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
413 syslog(LOG_ERR, "setrlimit failed");
414 }
415
416 (void) enable_extended_FILE_stdio(-1, -1);
417
418 ret = nfs_smf_get_iprop("mountd_max_threads", &max_threads,
419 DEFAULT_INSTANCE, SCF_TYPE_INTEGER, NFSD);
420 if (ret != SA_OK) {
421 syslog(LOG_ERR, "Reading of mountd_max_threads from SMF "
422 "failed, using default value");
423 }
424
425 while ((c = getopt(argc, argv, "vrm:")) != EOF) {
426 switch (c) {
427 case 'v':
428 verbose++;
429 break;
430 case 'r':
431 rejecting = 1;
432 break;
433 case 'm':
434 if (convert_int(&tmp, optarg) != 0 || tmp < 1) {
435 (void) fprintf(stderr, "%s: invalid "
436 "max_threads option, using defaults\n",
437 argv[0]);
438 break;
439 }
440 max_threads = tmp;
441 break;
442 default:
443 fprintf(stderr, "usage: mountd [-v] [-r]\n");
444 exit(1);
445 }
446 }
447
448 /*
449 * Read in the NFS version values from config file.
450 */
451 bufsz = 4;
452 ret = nfs_smf_get_prop("server_versmin", defval, DEFAULT_INSTANCE,
453 SCF_TYPE_INTEGER, NFSD, &bufsz);
454 if (ret == SA_OK) {
455 errno = 0;
456 defvers = strtol(defval, (char **)NULL, 10);
457 if (errno == 0) {
458 mount_vers_min = defvers;
459 /*
460 * special because NFSv2 is
461 * supported by mount v1 & v2
471 if (ret == SA_OK) {
472 errno = 0;
473 defvers = strtol(defval, (char **)NULL, 10);
474 if (errno == 0) {
475 mount_vers_max = defvers;
476 }
477 }
478
479 ret = nfs_smf_get_iprop("mountd_listen_backlog", &listen_backlog,
480 DEFAULT_INSTANCE, SCF_TYPE_INTEGER, NFSD);
481 if (ret != SA_OK) {
482 syslog(LOG_ERR, "Reading of mountd_listen_backlog from SMF "
483 "failed, using default value");
484 }
485
486 /*
487 * Sanity check versions,
488 * even though we may get versions > MOUNTVERS3, we still need
489 * to start nfsauth service, so continue on regardless of values.
490 */
491 if (mount_vers_min > mount_vers_max) {
492 fprintf(stderr, "server_versmin > server_versmax\n");
493 mount_vers_max = mount_vers_min;
494 }
495 (void) setlocale(LC_ALL, "");
496 (void) rwlock_init(&sharetab_lock, USYNC_THREAD, NULL);
497 (void) mutex_init(&mnttab_lock, USYNC_THREAD, NULL);
498 (void) mutex_init(&logging_queue_lock, USYNC_THREAD, NULL);
499 (void) cond_init(&logging_queue_cv, USYNC_THREAD, NULL);
500
501 netgroup_init();
502
503 #if !defined(TEXT_DOMAIN)
504 #define TEXT_DOMAIN "SYS_TEST"
505 #endif
506 (void) textdomain(TEXT_DOMAIN);
507
508 /* Don't drop core if the NFS module isn't loaded. */
509 (void) signal(SIGSYS, SIG_IGN);
510
511 pipe_fd = daemonize_init();
512
513 /*
514 * If we coredump it'll be in /core
515 */
516 if (chdir("/") < 0)
517 fprintf(stderr, "chdir /: %s\n", strerror(errno));
518
519 openlog("mountd", LOG_PID, LOG_DAEMON);
520
521 /*
522 * establish our lock on the lock file and write our pid to it.
523 * exit if some other process holds the lock, or if there's any
524 * error in writing/locking the file.
525 */
526 pid = _enter_daemon_lock(MOUNTD);
527 switch (pid) {
528 case 0:
529 break;
530 case -1:
531 fprintf(stderr, "error locking for %s: %s\n", MOUNTD,
532 strerror(errno));
533 exit(2);
534 default:
535 /* daemon was already running */
536 exit(0);
537 }
538
584
585 /*
586 * Set the maximum number of outstanding connection
587 * indications (listen backlog) to the value specified.
588 */
589 if (listen_backlog > 0 && !rpc_control(__RPC_SVC_LSTNBKLOG_SET,
590 &listen_backlog)) {
591 fprintf(stderr, "unable to set listen backlog\n");
592 exit(1);
593 }
594
595 /*
596 * If max_threads was specified, then set the
597 * maximum number of threads to the value specified.
598 */
599 if (max_threads > 0 && !rpc_control(RPC_SVC_THRMAX_SET, &max_threads)) {
600 fprintf(stderr, "unable to set max_threads\n");
601 exit(1);
602 }
603
604 /*
605 * Make sure to unregister any previous versions in case the
606 * user is reconfiguring the server in interesting ways.
607 */
608 svc_unreg(MOUNTPROG, MOUNTVERS);
609 svc_unreg(MOUNTPROG, MOUNTVERS_POSIX);
610 svc_unreg(MOUNTPROG, MOUNTVERS3);
611
612 /*
613 * Create the nfsauth thread with same signal disposition
614 * as the main thread. We need to create a separate thread
615 * since mountd() will be both an RPC server (for remote
616 * traffic) _and_ a doors server (for kernel upcalls).
617 */
618 if (thr_create(NULL, 0, nfsauth_svc, 0, thr_flags, &nfsauth_thread)) {
619 fprintf(stderr,
620 gettext("Failed to create NFSAUTH svc thread\n"));
621 exit(2);
622 }
623
628 * traffic) _and_ a doors server (for kernel upcalls).
629 */
630 if (thr_create(NULL, 0, cmd_svc, 0, thr_flags, &cmd_thread)) {
631 syslog(LOG_ERR, gettext("Failed to create CMD svc thread"));
632 exit(2);
633 }
634
635 /*
636 * Create an additional thread to service the rmtab and
637 * audit_mountd_mount logging for mount requests. Use the same
638 * signal disposition as the main thread. We create
639 * a separate thread to allow the mount request threads to
640 * clear as soon as possible.
641 */
642 if (thr_create(NULL, 0, logging_svc, 0, thr_flags, &logging_thread)) {
643 syslog(LOG_ERR, gettext("Failed to create LOGGING svc thread"));
644 exit(2);
645 }
646
647 /*
648 * Create datagram and connection oriented services
649 */
650 if (mount_vers_max >= MOUNTVERS) {
651 if (svc_create(mnt, MOUNTPROG, MOUNTVERS, "datagram_v") == 0) {
652 fprintf(stderr,
653 "couldn't register datagram_v MOUNTVERS\n");
654 exit(1);
655 }
656 if (svc_create(mnt, MOUNTPROG, MOUNTVERS, "circuit_v") == 0) {
657 fprintf(stderr,
658 "couldn't register circuit_v MOUNTVERS\n");
659 exit(1);
660 }
661 }
662
663 if (mount_vers_max >= MOUNTVERS_POSIX) {
664 if (svc_create(mnt, MOUNTPROG, MOUNTVERS_POSIX,
665 "datagram_v") == 0) {
666 fprintf(stderr,
667 "couldn't register datagram_v MOUNTVERS_POSIX\n");
668 exit(1);
669 }
670 if (svc_create(mnt, MOUNTPROG, MOUNTVERS_POSIX,
671 "circuit_v") == 0) {
672 fprintf(stderr,
673 "couldn't register circuit_v MOUNTVERS_POSIX\n");
674 exit(1);
675 }
676 }
677
678 if (mount_vers_max >= MOUNTVERS3) {
679 if (svc_create(mnt, MOUNTPROG, MOUNTVERS3, "datagram_v") == 0) {
680 fprintf(stderr,
681 "couldn't register datagram_v MOUNTVERS3\n");
682 exit(1);
683 }
684 if (svc_create(mnt, MOUNTPROG, MOUNTVERS3, "circuit_v") == 0) {
685 fprintf(stderr,
686 "couldn't register circuit_v MOUNTVERS3\n");
687 exit(1);
688 }
689 }
690
691 /*
692 * Start serving
693 */
694 rmtab_load();
695
696 daemonize_fini(pipe_fd);
697
698 /* Get rid of the most dangerous basic privileges. */
699 __fini_daemon_priv(PRIV_PROC_EXEC, PRIV_PROC_INFO, PRIV_PROC_SESSION,
700 (char *)NULL);
701
702 svc_run();
703 syslog(LOG_ERR, "Error: svc_run shouldn't have returned");
704 abort();
705
706 /* NOTREACHED */
707 return (0);
708 }
709
710 /*
|
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 /*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
25 * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
26 */
27
28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 /*
32 * Portions of this source code were derived from Berkeley 4.3 BSD
33 * under license from the Regents of the University of California.
34 */
35
36 #include <stdio.h>
37 #include <stdio_ext.h>
38 #include <stdlib.h>
39 #include <ctype.h>
40 #include <sys/types.h>
41 #include <string.h>
42 #include <syslog.h>
43 #include <sys/param.h>
44 #include <rpc/rpc.h>
45 #include <sys/stat.h>
101
102 static mutex_t logging_queue_lock;
103 static cond_t logging_queue_cv;
104
105 static share_t *find_lofsentry(char *, int *);
106 static int getclientsflavors_old(share_t *, struct cln *, int *);
107 static int getclientsflavors_new(share_t *, struct cln *, int *);
108 static int check_client_old(share_t *, struct cln *, int, uid_t, gid_t, uint_t,
109 gid_t *, uid_t *, gid_t *, uint_t *, gid_t **);
110 static int check_client_new(share_t *, struct cln *, int, uid_t, gid_t, uint_t,
111 gid_t *, uid_t *, gid_t *i, uint_t *, gid_t **);
112 static void mnt(struct svc_req *, SVCXPRT *);
113 static void mnt_pathconf(struct svc_req *);
114 static int mount(struct svc_req *r);
115 static void sh_free(struct sh_list *);
116 static void umount(struct svc_req *);
117 static void umountall(struct svc_req *);
118 static int newopts(char *);
119 static tsol_tpent_t *get_client_template(struct sockaddr *);
120
121 static int debug;
122 static int verbose;
123 static int rejecting;
124 static int mount_vers_min = MOUNTVERS;
125 static int mount_vers_max = MOUNTVERS3;
126 static int mountd_port = 0;
127
128 extern void nfscmd_func(void *, char *, size_t, door_desc_t *, uint_t);
129
130 thread_t nfsauth_thread;
131 thread_t cmd_thread;
132 thread_t logging_thread;
133
134 typedef struct logging_data {
135 char *ld_host;
136 char *ld_path;
137 char *ld_rpath;
138 int ld_status;
139 char *ld_netid;
140 struct netbuf *ld_nb;
141 struct logging_data *ld_next;
142 } logging_data;
143
144 static logging_data *logging_head = NULL;
145 static logging_data *logging_tail = NULL;
146
348 syslog(LOG_ERR, gettext("Logging server exited"));
349 return (NULL);
350 }
351
352 static int
353 convert_int(int *val, char *str)
354 {
355 long lval;
356
357 if (str == NULL || !isdigit(*str))
358 return (-1);
359
360 lval = strtol(str, &str, 10);
361 if (*str != '\0' || lval > INT_MAX)
362 return (-2);
363
364 *val = (int)lval;
365 return (0);
366 }
367
368 /*
369 * This function is called for each configured network type to
370 * bind and register our RPC service programs.
371 *
372 * On TCP or UDP, we may want to bind MOUNTPROG on a specific port
373 * (when mountd_port is specified) in which case we'll use the
374 * variant of svc_tp_create() that lets us pass a bind address.
375 */
376 static void
377 md_svc_tp_create(struct netconfig *nconf)
378 {
379 char port_str[8];
380 struct nd_hostserv hs;
381 struct nd_addrlist *al = NULL;
382 SVCXPRT *xprt = NULL;
383 rpcvers_t vers;
384
385 vers = mount_vers_max;
386
387 /*
388 * If mountd_port is set and this is an inet transport,
389 * bind this service on the specified port. The TLI way
390 * to create such a bind address is netdir_getbyname()
391 * with the special "host" HOST_SELF_BIND. This builds
392 * an all-zeros IP address with the specified port.
393 */
394 if (mountd_port != 0 &&
395 (strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
396 strcmp(nconf->nc_protofmly, NC_INET6) == 0)) {
397 int err;
398
399 snprintf(port_str, sizeof (port_str), "%u",
400 (unsigned short)mountd_port);
401
402 hs.h_host = HOST_SELF_BIND;
403 hs.h_serv = port_str;
404 err = netdir_getbyname((struct netconfig *)nconf, &hs, &al);
405 if (err == 0 && al != NULL) {
406 xprt = svc_tp_create_addr(mnt, MOUNTPROG, vers,
407 nconf, al->n_addrs);
408 netdir_free(al, ND_ADDRLIST);
409 }
410 if (xprt == NULL) {
411 syslog(LOG_ERR, "mountd: unable to create "
412 "(MOUNTD,%d) on transport %s (port %d)",
413 vers, nconf->nc_netid, mountd_port);
414 }
415 /* fall-back to default bind */
416 }
417 if (xprt == NULL) {
418 /*
419 * Had mountd_port=0, or non-inet transport,
420 * or the bind to a specific port failed.
421 * Do a default bind.
422 */
423 xprt = svc_tp_create(mnt, MOUNTPROG, vers, nconf);
424 }
425 if (xprt == NULL) {
426 syslog(LOG_ERR, "mountd: unable to create "
427 "(MOUNTD,%d) on transport %s",
428 vers, nconf->nc_netid);
429 return;
430 }
431
432 /*
433 * Register additional versions on this transport.
434 */
435 while (--vers >= mount_vers_min) {
436 if (!svc_reg(xprt, MOUNTPROG, vers, mnt, nconf)) {
437 (void) syslog(LOG_ERR, "mountd: "
438 "failed to register vers %d on %s",
439 vers, nconf->nc_netid);
440 }
441 }
442 }
443
444 int
445 main(int argc, char *argv[])
446 {
447 int pid;
448 int c;
449 int rpc_svc_fdunlim = 1;
450 int rpc_svc_mode = RPC_SVC_MT_AUTO;
451 int maxrecsz = RPC_MAXDATASIZE;
452 bool_t exclbind = TRUE;
453 bool_t can_do_mlp;
454 long thr_flags = (THR_NEW_LWP|THR_DAEMON);
455 char defval[4];
456 int defvers, ret, bufsz;
457 struct rlimit rl;
458 int listen_backlog = 0;
459 int max_threads = 0;
460 int tmp;
461 struct netconfig *nconf;
462 NCONF_HANDLE *nc;
463
464 int pipe_fd = -1;
465
466 /*
467 * Mountd requires uid 0 for:
468 * /etc/rmtab updates (we could chown it to daemon)
469 * /etc/dfs/dfstab reading (it wants to lock out share which
470 * doesn't do any locking before first truncate;
471 * NFS share does; should use fcntl locking instead)
472 * Needed privileges:
473 * auditing
474 * nfs syscall
475 * file dac search (so it can stat all files)
476 * Optional privileges:
477 * MLP
478 */
479 can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP);
480 if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, -1, -1,
481 PRIV_SYS_NFS, PRIV_PROC_AUDIT, PRIV_FILE_DAC_SEARCH,
482 PRIV_NET_PRIVADDR,
483 can_do_mlp ? PRIV_NET_BINDMLP : NULL, NULL) == -1) {
484 (void) fprintf(stderr,
485 "%s: must be run with sufficient privileges\n",
486 argv[0]);
487 exit(1);
488 }
489
490 if (getrlimit(RLIMIT_NOFILE, &rl) != 0) {
491 syslog(LOG_ERR, "getrlimit failed");
492 } else {
493 rl.rlim_cur = rl.rlim_max;
494 if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
495 syslog(LOG_ERR, "setrlimit failed");
496 }
497
498 (void) enable_extended_FILE_stdio(-1, -1);
499
500 ret = nfs_smf_get_iprop("mountd_max_threads", &max_threads,
501 DEFAULT_INSTANCE, SCF_TYPE_INTEGER, NFSD);
502 if (ret != SA_OK) {
503 syslog(LOG_ERR, "Reading of mountd_max_threads from SMF "
504 "failed, using default value");
505 }
506
507 ret = nfs_smf_get_iprop("mountd_port", &mountd_port,
508 DEFAULT_INSTANCE, SCF_TYPE_INTEGER, NFSD);
509 if (ret != SA_OK) {
510 syslog(LOG_ERR, "Reading of mountd_port from SMF "
511 "failed, using default value");
512 }
513
514 while ((c = getopt(argc, argv, "dvrm:p:")) != EOF) {
515 switch (c) {
516 case 'd':
517 debug++;
518 break;
519 case 'v':
520 verbose++;
521 break;
522 case 'r':
523 rejecting = 1;
524 break;
525 case 'm':
526 if (convert_int(&tmp, optarg) != 0 || tmp < 1) {
527 (void) fprintf(stderr, "%s: invalid "
528 "max_threads option, using defaults\n",
529 argv[0]);
530 break;
531 }
532 max_threads = tmp;
533 break;
534 case 'p':
535 if (convert_int(&tmp, optarg) != 0 || tmp < 1 ||
536 tmp > UINT16_MAX) {
537 (void) fprintf(stderr, "%s: invalid port "
538 "number\n", argv[0]);
539 break;
540 }
541 mountd_port = tmp;
542 break;
543 default:
544 fprintf(stderr, "usage: mountd [-v] [-r]\n");
545 exit(1);
546 }
547 }
548
549 /*
550 * Read in the NFS version values from config file.
551 */
552 bufsz = 4;
553 ret = nfs_smf_get_prop("server_versmin", defval, DEFAULT_INSTANCE,
554 SCF_TYPE_INTEGER, NFSD, &bufsz);
555 if (ret == SA_OK) {
556 errno = 0;
557 defvers = strtol(defval, (char **)NULL, 10);
558 if (errno == 0) {
559 mount_vers_min = defvers;
560 /*
561 * special because NFSv2 is
562 * supported by mount v1 & v2
572 if (ret == SA_OK) {
573 errno = 0;
574 defvers = strtol(defval, (char **)NULL, 10);
575 if (errno == 0) {
576 mount_vers_max = defvers;
577 }
578 }
579
580 ret = nfs_smf_get_iprop("mountd_listen_backlog", &listen_backlog,
581 DEFAULT_INSTANCE, SCF_TYPE_INTEGER, NFSD);
582 if (ret != SA_OK) {
583 syslog(LOG_ERR, "Reading of mountd_listen_backlog from SMF "
584 "failed, using default value");
585 }
586
587 /*
588 * Sanity check versions,
589 * even though we may get versions > MOUNTVERS3, we still need
590 * to start nfsauth service, so continue on regardless of values.
591 */
592 if (mount_vers_max > MOUNTVERS3)
593 mount_vers_max = MOUNTVERS3;
594 if (mount_vers_min > mount_vers_max) {
595 fprintf(stderr, "server_versmin > server_versmax\n");
596 mount_vers_max = mount_vers_min;
597 }
598 (void) setlocale(LC_ALL, "");
599 (void) rwlock_init(&sharetab_lock, USYNC_THREAD, NULL);
600 (void) mutex_init(&mnttab_lock, USYNC_THREAD, NULL);
601 (void) mutex_init(&logging_queue_lock, USYNC_THREAD, NULL);
602 (void) cond_init(&logging_queue_cv, USYNC_THREAD, NULL);
603
604 netgroup_init();
605
606 #if !defined(TEXT_DOMAIN)
607 #define TEXT_DOMAIN "SYS_TEST"
608 #endif
609 (void) textdomain(TEXT_DOMAIN);
610
611 /* Don't drop core if the NFS module isn't loaded. */
612 (void) signal(SIGSYS, SIG_IGN);
613
614 if (!debug)
615 pipe_fd = daemonize_init();
616
617 /*
618 * If we coredump it'll be in /core
619 */
620 if (chdir("/") < 0)
621 fprintf(stderr, "chdir /: %s\n", strerror(errno));
622
623 if (!debug)
624 openlog("mountd", LOG_PID, LOG_DAEMON);
625
626 /*
627 * establish our lock on the lock file and write our pid to it.
628 * exit if some other process holds the lock, or if there's any
629 * error in writing/locking the file.
630 */
631 pid = _enter_daemon_lock(MOUNTD);
632 switch (pid) {
633 case 0:
634 break;
635 case -1:
636 fprintf(stderr, "error locking for %s: %s\n", MOUNTD,
637 strerror(errno));
638 exit(2);
639 default:
640 /* daemon was already running */
641 exit(0);
642 }
643
689
690 /*
691 * Set the maximum number of outstanding connection
692 * indications (listen backlog) to the value specified.
693 */
694 if (listen_backlog > 0 && !rpc_control(__RPC_SVC_LSTNBKLOG_SET,
695 &listen_backlog)) {
696 fprintf(stderr, "unable to set listen backlog\n");
697 exit(1);
698 }
699
700 /*
701 * If max_threads was specified, then set the
702 * maximum number of threads to the value specified.
703 */
704 if (max_threads > 0 && !rpc_control(RPC_SVC_THRMAX_SET, &max_threads)) {
705 fprintf(stderr, "unable to set max_threads\n");
706 exit(1);
707 }
708
709 if (mountd_port < 0 || mountd_port > UINT16_MAX) {
710 fprintf(stderr, "unable to use specified port\n");
711 exit(1);
712 }
713
714 /*
715 * Make sure to unregister any previous versions in case the
716 * user is reconfiguring the server in interesting ways.
717 */
718 svc_unreg(MOUNTPROG, MOUNTVERS);
719 svc_unreg(MOUNTPROG, MOUNTVERS_POSIX);
720 svc_unreg(MOUNTPROG, MOUNTVERS3);
721
722 /*
723 * Create the nfsauth thread with same signal disposition
724 * as the main thread. We need to create a separate thread
725 * since mountd() will be both an RPC server (for remote
726 * traffic) _and_ a doors server (for kernel upcalls).
727 */
728 if (thr_create(NULL, 0, nfsauth_svc, 0, thr_flags, &nfsauth_thread)) {
729 fprintf(stderr,
730 gettext("Failed to create NFSAUTH svc thread\n"));
731 exit(2);
732 }
733
738 * traffic) _and_ a doors server (for kernel upcalls).
739 */
740 if (thr_create(NULL, 0, cmd_svc, 0, thr_flags, &cmd_thread)) {
741 syslog(LOG_ERR, gettext("Failed to create CMD svc thread"));
742 exit(2);
743 }
744
745 /*
746 * Create an additional thread to service the rmtab and
747 * audit_mountd_mount logging for mount requests. Use the same
748 * signal disposition as the main thread. We create
749 * a separate thread to allow the mount request threads to
750 * clear as soon as possible.
751 */
752 if (thr_create(NULL, 0, logging_svc, 0, thr_flags, &logging_thread)) {
753 syslog(LOG_ERR, gettext("Failed to create LOGGING svc thread"));
754 exit(2);
755 }
756
757 /*
758 * Enumerate network transports and create service listeners
759 * as appropriate for each.
760 */
761 if ((nc = setnetconfig()) == NULL) {
762 syslog(LOG_ERR, "setnetconfig failed: %m");
763 return (-1);
764 }
765 while ((nconf = getnetconfig(nc)) != NULL) {
766 /*
767 * Skip things like tpi_raw, invisible...
768 */
769 if ((nconf->nc_flag & NC_VISIBLE) == 0)
770 continue;
771 if (nconf->nc_semantics != NC_TPI_CLTS &&
772 nconf->nc_semantics != NC_TPI_COTS &&
773 nconf->nc_semantics != NC_TPI_COTS_ORD)
774 continue;
775
776 md_svc_tp_create(nconf);
777 }
778 (void) endnetconfig(nc);
779
780 /*
781 * Start serving
782 */
783 rmtab_load();
784
785 daemonize_fini(pipe_fd);
786
787 /* Get rid of the most dangerous basic privileges. */
788 __fini_daemon_priv(PRIV_PROC_EXEC, PRIV_PROC_INFO, PRIV_PROC_SESSION,
789 (char *)NULL);
790
791 svc_run();
792 syslog(LOG_ERR, "Error: svc_run shouldn't have returned");
793 abort();
794
795 /* NOTREACHED */
796 return (0);
797 }
798
799 /*
|