14520Snw141292 /* 24520Snw141292 * CDDL HEADER START 34520Snw141292 * 44520Snw141292 * The contents of this file are subject to the terms of the 54520Snw141292 * Common Development and Distribution License (the "License"). 64520Snw141292 * You may not use this file except in compliance with the License. 74520Snw141292 * 84520Snw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94520Snw141292 * or http://www.opensolaris.org/os/licensing. 104520Snw141292 * See the License for the specific language governing permissions 114520Snw141292 * and limitations under the License. 124520Snw141292 * 134520Snw141292 * When distributing Covered Code, include this CDDL HEADER in each 144520Snw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154520Snw141292 * If applicable, add the following below this CDDL HEADER, with the 164520Snw141292 * fields enclosed by brackets "[]" replaced with your own identifying 174520Snw141292 * information: Portions Copyright [yyyy] [name of copyright owner] 184520Snw141292 * 194520Snw141292 * CDDL HEADER END 204520Snw141292 */ 214520Snw141292 /* 22*8671SJulian.Pullen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 234520Snw141292 * Use is subject to license terms. 244520Snw141292 */ 254520Snw141292 264520Snw141292 274520Snw141292 /* 284520Snw141292 * main() of idmapd(1M) 294520Snw141292 */ 304520Snw141292 314520Snw141292 #include "idmapd.h" 326017Snw141292 #include <atomic.h> 334520Snw141292 #include <signal.h> 344520Snw141292 #include <rpc/pmap_clnt.h> /* for pmap_unset */ 354520Snw141292 #include <string.h> /* strcmp */ 364520Snw141292 #include <unistd.h> /* setsid */ 374520Snw141292 #include <sys/types.h> 384520Snw141292 #include <memory.h> 394520Snw141292 #include <stropts.h> 404520Snw141292 #include <netconfig.h> 414520Snw141292 #include <sys/resource.h> /* rlimit */ 424520Snw141292 #include <rpcsvc/daemon_utils.h> /* DAEMON_UID and DAEMON_GID */ 434520Snw141292 #include <priv_utils.h> /* privileges */ 444520Snw141292 #include <locale.h> 454520Snw141292 #include <sys/systeminfo.h> 464520Snw141292 #include <errno.h> 474520Snw141292 #include <sys/wait.h> 484520Snw141292 #include <sys/time.h> 494520Snw141292 #include <zone.h> 504520Snw141292 #include <door.h> 515317Sjp151216 #include <port.h> 524520Snw141292 #include <tsol/label.h> 534520Snw141292 #include <sys/resource.h> 544520Snw141292 #include <sys/sid.h> 554520Snw141292 #include <sys/idmap.h> 566531Sjp151216 #include <pthread.h> 574520Snw141292 584520Snw141292 static void term_handler(int); 594520Snw141292 static void init_idmapd(); 604520Snw141292 static void fini_idmapd(); 614520Snw141292 62*8671SJulian.Pullen@Sun.COM 634520Snw141292 #define _RPCSVC_CLOSEDOWN 120 644520Snw141292 654520Snw141292 int _rpcsvcstate = _IDLE; /* Set when a request is serviced */ 664520Snw141292 int _rpcsvccount = 0; /* Number of requests being serviced */ 674520Snw141292 mutex_t _svcstate_lock; /* lock for _rpcsvcstate, _rpcsvccount */ 684520Snw141292 idmapd_state_t _idmapdstate; 694520Snw141292 704520Snw141292 SVCXPRT *xprt = NULL; 714520Snw141292 724520Snw141292 static int dfd = -1; /* our door server fildes, for unregistration */ 736017Snw141292 static int degraded = 0; /* whether the FMRI has been marked degraded */ 744520Snw141292 756531Sjp151216 766531Sjp151216 static uint32_t num_threads = 0; 776531Sjp151216 static pthread_key_t create_threads_key; 786531Sjp151216 static uint32_t max_threads = 40; 796531Sjp151216 80*8671SJulian.Pullen@Sun.COM 81*8671SJulian.Pullen@Sun.COM /* 82*8671SJulian.Pullen@Sun.COM * The following structure determines where the log messages from idmapdlog() 83*8671SJulian.Pullen@Sun.COM * go to. It can be stderr (idmapd -d) and/or the real idmapdlog (idmapd). 84*8671SJulian.Pullen@Sun.COM * 85*8671SJulian.Pullen@Sun.COM * logstate.max_pri is integer cutoff necessary to silence low-priority 86*8671SJulian.Pullen@Sun.COM * messages to stderr. idmapdlog has its own means so there a boolean 87*8671SJulian.Pullen@Sun.COM * logstate.write_idmapdlog is enough. 88*8671SJulian.Pullen@Sun.COM * 89*8671SJulian.Pullen@Sun.COM * logstate.degraded is a mode used by idmapd in its degraded state. 90*8671SJulian.Pullen@Sun.COM */ 91*8671SJulian.Pullen@Sun.COM 92*8671SJulian.Pullen@Sun.COM static struct { 93*8671SJulian.Pullen@Sun.COM boolean_t write_syslog; 94*8671SJulian.Pullen@Sun.COM int max_pri; /* Max priority written to stderr */ 95*8671SJulian.Pullen@Sun.COM boolean_t degraded; 96*8671SJulian.Pullen@Sun.COM } logstate = {B_FALSE, LOG_DEBUG, B_FALSE}; 97*8671SJulian.Pullen@Sun.COM 986531Sjp151216 /* 996531Sjp151216 * Server door thread start routine. 1006531Sjp151216 * 1016531Sjp151216 * Set a TSD value to the door thread. This enables the destructor to 1026531Sjp151216 * be called when this thread exits. 1036531Sjp151216 */ 1046531Sjp151216 /*ARGSUSED*/ 1056531Sjp151216 static void * 1066531Sjp151216 idmapd_door_thread_start(void *arg) 1076531Sjp151216 { 1086531Sjp151216 static void *value = 0; 1096531Sjp151216 1106531Sjp151216 /* 1116531Sjp151216 * Disable cancellation to avoid memory leaks from not running 1126531Sjp151216 * the thread cleanup code. 1136531Sjp151216 */ 1146531Sjp151216 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 1156531Sjp151216 (void) pthread_setspecific(create_threads_key, value); 1166531Sjp151216 (void) door_return(NULL, 0, NULL, 0); 1176531Sjp151216 1186531Sjp151216 /* make lint happy */ 1196531Sjp151216 return (NULL); 1206531Sjp151216 } 1216531Sjp151216 1226531Sjp151216 /* 1236531Sjp151216 * Server door threads creation 1246531Sjp151216 */ 1256531Sjp151216 /*ARGSUSED*/ 1266531Sjp151216 static void 1276531Sjp151216 idmapd_door_thread_create(door_info_t *dip) 1286531Sjp151216 { 1296531Sjp151216 int num; 1306531Sjp151216 pthread_t thread_id; 1316531Sjp151216 1326531Sjp151216 if ((num = atomic_inc_32_nv(&num_threads)) > max_threads) { 1336531Sjp151216 atomic_dec_32(&num_threads); 1346531Sjp151216 idmapdlog(LOG_DEBUG, 1356531Sjp151216 "thread creation refused - %d threads currently active", 1366531Sjp151216 num - 1); 1376531Sjp151216 return; 1386531Sjp151216 } 1396531Sjp151216 (void) pthread_create(&thread_id, NULL, idmapd_door_thread_start, NULL); 1406531Sjp151216 idmapdlog(LOG_DEBUG, 1416531Sjp151216 "created thread ID %d - %d threads currently active", 1426531Sjp151216 thread_id, num); 1436531Sjp151216 } 1446531Sjp151216 1456531Sjp151216 /* 1466531Sjp151216 * Server door thread cleanup 1476531Sjp151216 */ 1486531Sjp151216 /*ARGSUSED*/ 1496531Sjp151216 static void 1506531Sjp151216 idmapd_door_thread_cleanup(void *arg) 1516531Sjp151216 { 1526531Sjp151216 int num; 1536531Sjp151216 1546531Sjp151216 num = atomic_dec_32_nv(&num_threads); 1556531Sjp151216 idmapdlog(LOG_DEBUG, 1566531Sjp151216 "exiting thread ID %d - %d threads currently active", 1576531Sjp151216 pthread_self(), num); 1586531Sjp151216 } 1596531Sjp151216 1604520Snw141292 /* 1614520Snw141292 * This is needed for mech_krb5 -- we run as daemon, yes, but we want 1625034Snw141292 * mech_krb5 to think we're root so it can get host/nodename.fqdn 1635034Snw141292 * tickets for us so we can authenticate to AD as the machine account 1645034Snw141292 * that we are. For more details look at the entry point in mech_krb5 1655034Snw141292 * corresponding to gss_init_sec_context(). 1665034Snw141292 * 1675034Snw141292 * As a side effect of faking our effective UID to mech_krb5 we will use 1685034Snw141292 * root's default ccache (/tmp/krb5cc_0). But if that's created by 1695034Snw141292 * another process then we won't have access to it: we run as daemon and 1705034Snw141292 * keep PRIV_FILE_DAC_READ, which is insufficient to share the ccache 1715034Snw141292 * with others. We putenv("KRB5CCNAME=/var/run/idmap/ccache") in main() 1725034Snw141292 * to avoid this issue; see main(). 1734520Snw141292 * 1744520Snw141292 * Someday we'll have gss/mech_krb5 extensions for acquiring initiator 1754520Snw141292 * creds with keytabs/raw keys, and someday we'll have extensions to 1764520Snw141292 * libsasl to specify creds/name to use on the initiator side, and 1774520Snw141292 * someday we'll have extensions to libldap to pass those through to 1784520Snw141292 * libsasl. Until then this interposer will have to do. 1794520Snw141292 * 1804520Snw141292 * Also, we have to tell lint to shut up: it thinks app_krb5_user_uid() 1814520Snw141292 * is defined but not used. 1824520Snw141292 */ 1834520Snw141292 /*LINTLIBRARY*/ 1844520Snw141292 uid_t 1854520Snw141292 app_krb5_user_uid(void) 1864520Snw141292 { 1874520Snw141292 return (0); 1884520Snw141292 } 1894520Snw141292 1904520Snw141292 /*ARGSUSED*/ 1914520Snw141292 static void 1925908Sjp151216 term_handler(int sig) 1935908Sjp151216 { 1946017Snw141292 idmapdlog(LOG_INFO, "Terminating."); 1954520Snw141292 fini_idmapd(); 1964520Snw141292 _exit(0); 1974520Snw141292 } 1984520Snw141292 1996017Snw141292 /*ARGSUSED*/ 2006017Snw141292 static void 2016017Snw141292 usr1_handler(int sig) 2026017Snw141292 { 203*8671SJulian.Pullen@Sun.COM boolean_t saved_debug_mode = _idmapdstate.debug_mode; 2046017Snw141292 205*8671SJulian.Pullen@Sun.COM _idmapdstate.debug_mode = B_TRUE; 2066616Sdm199847 idmap_log_stderr(LOG_DEBUG); 2076616Sdm199847 2086017Snw141292 print_idmapdstate(); 2096616Sdm199847 2106017Snw141292 _idmapdstate.debug_mode = saved_debug_mode; 2116616Sdm199847 idmap_log_stderr(_idmapdstate.daemon_mode ? -1 : LOG_DEBUG); 2126616Sdm199847 2136017Snw141292 } 2146017Snw141292 2154520Snw141292 static int pipe_fd = -1; 2164520Snw141292 2174520Snw141292 static void 2185908Sjp151216 daemonize_ready(void) 2195908Sjp151216 { 2204520Snw141292 char data = '\0'; 2214520Snw141292 /* 2224520Snw141292 * wake the parent 2234520Snw141292 */ 2244520Snw141292 (void) write(pipe_fd, &data, 1); 2254520Snw141292 (void) close(pipe_fd); 2264520Snw141292 } 2274520Snw141292 2284520Snw141292 static int 2295908Sjp151216 daemonize_start(void) 2305908Sjp151216 { 2314520Snw141292 char data; 2324520Snw141292 int status; 2334520Snw141292 int devnull; 2344520Snw141292 int filedes[2]; 2354520Snw141292 pid_t pid; 2364520Snw141292 2375034Snw141292 (void) sigset(SIGPIPE, SIG_IGN); 2384520Snw141292 devnull = open("/dev/null", O_RDONLY); 2394520Snw141292 if (devnull < 0) 2404520Snw141292 return (-1); 2414520Snw141292 (void) dup2(devnull, 0); 2424520Snw141292 (void) dup2(2, 1); /* stderr only */ 2434520Snw141292 if (pipe(filedes) < 0) 2444520Snw141292 return (-1); 2454520Snw141292 if ((pid = fork1()) < 0) 2464520Snw141292 return (-1); 2474520Snw141292 if (pid != 0) { 2484520Snw141292 /* 2494520Snw141292 * parent 2504520Snw141292 */ 2514520Snw141292 (void) close(filedes[1]); 2524520Snw141292 if (read(filedes[0], &data, 1) == 1) { 2534520Snw141292 /* presume success */ 2544520Snw141292 _exit(0); 2554520Snw141292 } 2564520Snw141292 status = -1; 2574520Snw141292 (void) wait4(pid, &status, 0, NULL); 2584520Snw141292 if (WIFEXITED(status)) 2594520Snw141292 _exit(WEXITSTATUS(status)); 2604520Snw141292 else 2614520Snw141292 _exit(-1); 2624520Snw141292 } 2634520Snw141292 2644520Snw141292 /* 2654520Snw141292 * child 2664520Snw141292 */ 2674520Snw141292 pipe_fd = filedes[1]; 2684520Snw141292 (void) close(filedes[0]); 2694520Snw141292 (void) setsid(); 2704520Snw141292 (void) umask(0077); 2714520Snw141292 openlog("idmap", LOG_PID, LOG_DAEMON); 2726616Sdm199847 2734520Snw141292 return (0); 2744520Snw141292 } 2754520Snw141292 2764520Snw141292 2774520Snw141292 int 2784520Snw141292 main(int argc, char **argv) 2794520Snw141292 { 2804520Snw141292 int c; 2816414Sjp151216 struct rlimit rl; 2824520Snw141292 2836017Snw141292 _idmapdstate.daemon_mode = TRUE; 2846017Snw141292 _idmapdstate.debug_mode = FALSE; 2856017Snw141292 while ((c = getopt(argc, argv, "d")) != -1) { 2864520Snw141292 switch (c) { 2874520Snw141292 case 'd': 2886017Snw141292 _idmapdstate.daemon_mode = FALSE; 2894520Snw141292 break; 2904520Snw141292 default: 2916017Snw141292 fprintf(stderr, "Usage: /usr/lib/idmapd"); 2926017Snw141292 return (SMF_EXIT_ERR_CONFIG); 2934520Snw141292 break; 2944520Snw141292 } 2954520Snw141292 } 2964520Snw141292 2974520Snw141292 /* set locale and domain for internationalization */ 2984520Snw141292 (void) setlocale(LC_ALL, ""); 2994520Snw141292 (void) textdomain(TEXT_DOMAIN); 3004520Snw141292 301*8671SJulian.Pullen@Sun.COM idmap_set_logger(idmapdlog); 302*8671SJulian.Pullen@Sun.COM idmap_log_syslog(B_TRUE); 3036616Sdm199847 idmap_log_stderr(_idmapdstate.daemon_mode ? -1 : LOG_DEBUG); 3046616Sdm199847 3055771Sjp151216 if (is_system_labeled() && getzoneid() != GLOBAL_ZONEID) { 3066017Snw141292 idmapdlog(LOG_ERR, 3076017Snw141292 "with Trusted Extensions idmapd runs only in the " 3085771Sjp151216 "global zone"); 3094520Snw141292 exit(1); 3104520Snw141292 } 3114520Snw141292 3126414Sjp151216 /* 3136414Sjp151216 * Raise the fd limit to max 3146414Sjp151216 */ 3156414Sjp151216 if (getrlimit(RLIMIT_NOFILE, &rl) != 0) { 3166414Sjp151216 idmapdlog(LOG_ERR, "getrlimit failed"); 3176414Sjp151216 } else if (rl.rlim_cur < rl.rlim_max) { 3186414Sjp151216 rl.rlim_cur = rl.rlim_max; 3196414Sjp151216 if (setrlimit(RLIMIT_NOFILE, &rl) != 0) 3206414Sjp151216 idmapdlog(LOG_ERR, 3216414Sjp151216 "Unable to raise RLIMIT_NOFILE to %d", 3226414Sjp151216 rl.rlim_cur); 3236414Sjp151216 } 3246414Sjp151216 3254520Snw141292 (void) mutex_init(&_svcstate_lock, USYNC_THREAD, NULL); 3264520Snw141292 3276017Snw141292 if (_idmapdstate.daemon_mode == TRUE) { 3284520Snw141292 if (daemonize_start() < 0) { 329*8671SJulian.Pullen@Sun.COM idmapdlog(LOG_ERR, "unable to daemonize"); 3304520Snw141292 exit(-1); 3314520Snw141292 } 3324520Snw141292 } else 3334520Snw141292 (void) umask(0077); 3344520Snw141292 3354884Sjp151216 idmap_init_tsd_key(); 3364884Sjp151216 3374520Snw141292 init_idmapd(); 3384520Snw141292 3395034Snw141292 /* signal handlers that should run only after we're initialized */ 3405034Snw141292 (void) sigset(SIGTERM, term_handler); 3416017Snw141292 (void) sigset(SIGUSR1, usr1_handler); 3425968Snw141292 (void) sigset(SIGHUP, idmap_cfg_hup_handler); 3435034Snw141292 3444520Snw141292 if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 3454520Snw141292 DAEMON_UID, DAEMON_GID, 3464520Snw141292 PRIV_PROC_AUDIT, PRIV_FILE_DAC_READ, 3474520Snw141292 (char *)NULL) == -1) { 3486017Snw141292 idmapdlog(LOG_ERR, "unable to drop privileges"); 3494520Snw141292 exit(1); 3504520Snw141292 } 3514520Snw141292 3524520Snw141292 __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, 3534520Snw141292 PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL); 3544520Snw141292 3556017Snw141292 if (_idmapdstate.daemon_mode == TRUE) 3564520Snw141292 daemonize_ready(); 3574520Snw141292 3584520Snw141292 /* With doors RPC this just wastes this thread, oh well */ 3594520Snw141292 svc_run(); 3604520Snw141292 return (0); 3614520Snw141292 } 3624520Snw141292 3634520Snw141292 static void 3645908Sjp151216 init_idmapd() 3655908Sjp151216 { 3664520Snw141292 int error; 3676531Sjp151216 int connmaxrec = IDMAP_MAX_DOOR_RPC; 3686531Sjp151216 3694520Snw141292 3705034Snw141292 /* create directories as root and chown to daemon uid */ 3715034Snw141292 if (create_directory(IDMAP_DBDIR, DAEMON_UID, DAEMON_GID) < 0) 3725034Snw141292 exit(1); 3735034Snw141292 if (create_directory(IDMAP_CACHEDIR, DAEMON_UID, DAEMON_GID) < 0) 3745034Snw141292 exit(1); 3755034Snw141292 3765034Snw141292 /* 3775034Snw141292 * Set KRB5CCNAME in the environment. See app_krb5_user_uid() 3785447Snw141292 * for more details. We blow away the existing one, if there is 3795447Snw141292 * one. 3805034Snw141292 */ 3815447Snw141292 (void) unlink(IDMAP_CACHEDIR "/ccache"); 3825034Snw141292 putenv("KRB5CCNAME=" IDMAP_CACHEDIR "/ccache"); 3835034Snw141292 3844520Snw141292 if (sysinfo(SI_HOSTNAME, _idmapdstate.hostname, 3855908Sjp151216 sizeof (_idmapdstate.hostname)) == -1) { 3864520Snw141292 error = errno; 3876017Snw141292 idmapdlog(LOG_ERR, "unable to determine hostname, error: %d", 3885908Sjp151216 error); 3894520Snw141292 exit(1); 3904520Snw141292 } 3914520Snw141292 3925731Sbaban if ((error = init_mapping_system()) < 0) { 3936017Snw141292 idmapdlog(LOG_ERR, "unable to initialize mapping system"); 3945731Sbaban exit(error < -2 ? SMF_EXIT_ERR_CONFIG : 1); 3954520Snw141292 } 3964520Snw141292 3976531Sjp151216 (void) door_server_create(idmapd_door_thread_create); 3986531Sjp151216 if ((error = pthread_key_create(&create_threads_key, 3996531Sjp151216 idmapd_door_thread_cleanup)) != 0) { 4006531Sjp151216 idmapdlog(LOG_ERR, "unable to create threads key (%s)", 4016531Sjp151216 strerror(error)); 4026531Sjp151216 goto errout; 4036531Sjp151216 } 4046531Sjp151216 4055232Snw141292 xprt = svc_door_create(idmap_prog_1, IDMAP_PROG, IDMAP_V1, connmaxrec); 4064520Snw141292 if (xprt == NULL) { 4076017Snw141292 idmapdlog(LOG_ERR, "unable to create door RPC service"); 4084520Snw141292 goto errout; 4094520Snw141292 } 4104520Snw141292 4115064Sdm199847 if (!svc_control(xprt, SVCSET_CONNMAXREC, &connmaxrec)) { 4126017Snw141292 idmapdlog(LOG_ERR, "unable to limit RPC request size"); 4135064Sdm199847 goto errout; 4145064Sdm199847 } 4155064Sdm199847 4164520Snw141292 dfd = xprt->xp_fd; 4174520Snw141292 4184520Snw141292 if (dfd == -1) { 4196017Snw141292 idmapdlog(LOG_ERR, "unable to register door"); 4204520Snw141292 goto errout; 4214520Snw141292 } 4224520Snw141292 if ((error = idmap_reg(dfd)) != 0) { 4236017Snw141292 idmapdlog(LOG_ERR, "unable to register door (%s)", 4245908Sjp151216 strerror(errno)); 4254520Snw141292 goto errout; 4264520Snw141292 } 4274520Snw141292 4284520Snw141292 if ((error = allocids(_idmapdstate.new_eph_db, 4295908Sjp151216 8192, &_idmapdstate.next_uid, 4305908Sjp151216 8192, &_idmapdstate.next_gid)) != 0) { 4316017Snw141292 idmapdlog(LOG_ERR, "unable to allocate ephemeral IDs (%s)", 4326017Snw141292 strerror(errno)); 4334520Snw141292 _idmapdstate.next_uid = _idmapdstate.limit_uid = SENTINEL_PID; 4344520Snw141292 _idmapdstate.next_gid = _idmapdstate.limit_gid = SENTINEL_PID; 4354520Snw141292 } else { 4364520Snw141292 _idmapdstate.limit_uid = _idmapdstate.next_uid + 8192; 4374520Snw141292 _idmapdstate.limit_gid = _idmapdstate.next_gid + 8192; 4384520Snw141292 } 4394520Snw141292 4404520Snw141292 print_idmapdstate(); 4414520Snw141292 4424520Snw141292 return; 4434520Snw141292 4444520Snw141292 errout: 4454520Snw141292 fini_idmapd(); 4464520Snw141292 exit(1); 4474520Snw141292 } 4484520Snw141292 4494520Snw141292 static void 4505908Sjp151216 fini_idmapd() 4515908Sjp151216 { 4524520Snw141292 idmap_unreg(dfd); 4534520Snw141292 fini_mapping_system(); 4544520Snw141292 if (xprt != NULL) 4554520Snw141292 svc_destroy(xprt); 4564520Snw141292 } 4574520Snw141292 4586017Snw141292 static 4596017Snw141292 const char * 4606017Snw141292 get_fmri(void) 4616017Snw141292 { 4626017Snw141292 static char *fmri = NULL; 4636017Snw141292 static char buf[60]; 4646017Snw141292 char *s; 4656017Snw141292 4666017Snw141292 membar_consumer(); 4676017Snw141292 s = fmri; 4686017Snw141292 if (s != NULL && *s == '\0') 4696017Snw141292 return (NULL); 4706017Snw141292 else if (s != NULL) 4716017Snw141292 return (s); 4726017Snw141292 4736017Snw141292 if ((s = getenv("SMF_FMRI")) == NULL || strlen(s) >= sizeof (buf)) 4746017Snw141292 buf[0] = '\0'; 4756017Snw141292 else 4766017Snw141292 (void) strlcpy(buf, s, sizeof (buf)); 4776017Snw141292 4786017Snw141292 membar_producer(); 4796017Snw141292 fmri = buf; 4806017Snw141292 4816017Snw141292 return (get_fmri()); 4826017Snw141292 } 4836017Snw141292 4846017Snw141292 /* 4856017Snw141292 * Wrappers for smf_degrade/restore_instance() 4866017Snw141292 * 4876017Snw141292 * smf_restore_instance() is too heavy duty to be calling every time we 4886017Snw141292 * have a successful AD name<->SID lookup. 4896017Snw141292 */ 4906017Snw141292 void 4916097Snw141292 degrade_svc(int poke_discovery, const char *reason) 4926017Snw141292 { 4936017Snw141292 const char *fmri; 4946017Snw141292 4956017Snw141292 /* 4966017Snw141292 * If the config update thread is in a state where auto-discovery could 4976017Snw141292 * be re-tried, then this will make it try it -- a sort of auto-refresh. 4986017Snw141292 */ 4996097Snw141292 if (poke_discovery) 5006097Snw141292 idmap_cfg_poke_updates(); 5016017Snw141292 5026017Snw141292 membar_consumer(); 5036017Snw141292 if (degraded) 5046017Snw141292 return; 5056097Snw141292 5066097Snw141292 idmapdlog(LOG_ERR, "Degraded operation (%s). If you are running an " 5076097Snw141292 "SMB server in workgroup mode, or if you're not running an SMB " 5086097Snw141292 "server, then you can ignore this message", reason); 5096097Snw141292 5106017Snw141292 membar_producer(); 5116017Snw141292 degraded = 1; 512*8671SJulian.Pullen@Sun.COM idmap_log_degraded(B_TRUE); 5136017Snw141292 5146017Snw141292 if ((fmri = get_fmri()) != NULL) 5156017Snw141292 (void) smf_degrade_instance(fmri, 0); 5166017Snw141292 } 5176017Snw141292 5186017Snw141292 void 5196017Snw141292 restore_svc(void) 5206017Snw141292 { 5216017Snw141292 const char *fmri; 5226017Snw141292 5236017Snw141292 membar_consumer(); 5246017Snw141292 if (!degraded) 5256017Snw141292 return; 5266017Snw141292 5276017Snw141292 if ((fmri = get_fmri()) == NULL) 5286017Snw141292 (void) smf_restore_instance(fmri); 5296017Snw141292 5306017Snw141292 membar_producer(); 5316017Snw141292 degraded = 0; 532*8671SJulian.Pullen@Sun.COM idmap_log_degraded(B_FALSE); 5336616Sdm199847 5346097Snw141292 idmapdlog(LOG_NOTICE, "Normal operation restored"); 5356017Snw141292 } 5366017Snw141292 537*8671SJulian.Pullen@Sun.COM 538*8671SJulian.Pullen@Sun.COM /* printflike */ 5394520Snw141292 void 540*8671SJulian.Pullen@Sun.COM idmapdlog(int pri, const char *format, ...) { 5414520Snw141292 va_list args; 5424520Snw141292 543*8671SJulian.Pullen@Sun.COM if (pri <= logstate.max_pri) { 544*8671SJulian.Pullen@Sun.COM va_start(args, format); 5454520Snw141292 (void) vfprintf(stderr, format, args); 5464520Snw141292 (void) fprintf(stderr, "\n"); 547*8671SJulian.Pullen@Sun.COM va_end(args); 5484520Snw141292 } 5496017Snw141292 5506017Snw141292 /* 5516017Snw141292 * We don't want to fill up the logs with useless messages when 5526017Snw141292 * we're degraded, but we still want to log. 5536017Snw141292 */ 554*8671SJulian.Pullen@Sun.COM if (logstate.degraded) 5556017Snw141292 pri = LOG_DEBUG; 5566017Snw141292 557*8671SJulian.Pullen@Sun.COM if (logstate.write_syslog) { 558*8671SJulian.Pullen@Sun.COM va_start(args, format); 559*8671SJulian.Pullen@Sun.COM vsyslog(pri, format, args); 560*8671SJulian.Pullen@Sun.COM va_end(args); 561*8671SJulian.Pullen@Sun.COM } 562*8671SJulian.Pullen@Sun.COM } 563*8671SJulian.Pullen@Sun.COM 564*8671SJulian.Pullen@Sun.COM void 565*8671SJulian.Pullen@Sun.COM idmap_log_stderr(int pri) 566*8671SJulian.Pullen@Sun.COM { 567*8671SJulian.Pullen@Sun.COM logstate.max_pri = pri; 5684520Snw141292 } 569*8671SJulian.Pullen@Sun.COM 570*8671SJulian.Pullen@Sun.COM void 571*8671SJulian.Pullen@Sun.COM idmap_log_syslog(boolean_t what) 572*8671SJulian.Pullen@Sun.COM { 573*8671SJulian.Pullen@Sun.COM logstate.write_syslog = what; 574*8671SJulian.Pullen@Sun.COM } 575*8671SJulian.Pullen@Sun.COM 576*8671SJulian.Pullen@Sun.COM void 577*8671SJulian.Pullen@Sun.COM idmap_log_degraded(boolean_t what) 578*8671SJulian.Pullen@Sun.COM { 579*8671SJulian.Pullen@Sun.COM logstate.degraded = what; 580*8671SJulian.Pullen@Sun.COM } 581