1c5c4113dSnw141292 /* 2c5c4113dSnw141292 * CDDL HEADER START 3c5c4113dSnw141292 * 4c5c4113dSnw141292 * The contents of this file are subject to the terms of the 5c5c4113dSnw141292 * Common Development and Distribution License (the "License"). 6c5c4113dSnw141292 * You may not use this file except in compliance with the License. 7c5c4113dSnw141292 * 8c5c4113dSnw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9c5c4113dSnw141292 * or http://www.opensolaris.org/os/licensing. 10c5c4113dSnw141292 * See the License for the specific language governing permissions 11c5c4113dSnw141292 * and limitations under the License. 12c5c4113dSnw141292 * 13c5c4113dSnw141292 * When distributing Covered Code, include this CDDL HEADER in each 14c5c4113dSnw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15c5c4113dSnw141292 * If applicable, add the following below this CDDL HEADER, with the 16c5c4113dSnw141292 * fields enclosed by brackets "[]" replaced with your own identifying 17c5c4113dSnw141292 * information: Portions Copyright [yyyy] [name of copyright owner] 18c5c4113dSnw141292 * 19c5c4113dSnw141292 * CDDL HEADER END 20c5c4113dSnw141292 */ 21c5c4113dSnw141292 /* 22bda89588Sjp151216 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23c5c4113dSnw141292 * Use is subject to license terms. 24c5c4113dSnw141292 */ 25c5c4113dSnw141292 26c5c4113dSnw141292 #pragma ident "%Z%%M% %I% %E% SMI" 27c5c4113dSnw141292 28c5c4113dSnw141292 /* 29c5c4113dSnw141292 * main() of idmapd(1M) 30c5c4113dSnw141292 */ 31c5c4113dSnw141292 32c5c4113dSnw141292 #include "idmapd.h" 3371590c90Snw141292 #include <atomic.h> 34c5c4113dSnw141292 #include <signal.h> 35c5c4113dSnw141292 #include <rpc/pmap_clnt.h> /* for pmap_unset */ 36c5c4113dSnw141292 #include <string.h> /* strcmp */ 37c5c4113dSnw141292 #include <unistd.h> /* setsid */ 38c5c4113dSnw141292 #include <sys/types.h> 39c5c4113dSnw141292 #include <memory.h> 40c5c4113dSnw141292 #include <stropts.h> 41c5c4113dSnw141292 #include <netconfig.h> 42c5c4113dSnw141292 #include <sys/resource.h> /* rlimit */ 43c5c4113dSnw141292 #include <syslog.h> 44c5c4113dSnw141292 #include <rpcsvc/daemon_utils.h> /* DAEMON_UID and DAEMON_GID */ 45c5c4113dSnw141292 #include <priv_utils.h> /* privileges */ 46c5c4113dSnw141292 #include <locale.h> 47c5c4113dSnw141292 #include <sys/systeminfo.h> 48c5c4113dSnw141292 #include <errno.h> 49c5c4113dSnw141292 #include <sys/wait.h> 50c5c4113dSnw141292 #include <sys/time.h> 51c5c4113dSnw141292 #include <zone.h> 52c5c4113dSnw141292 #include <door.h> 53c8e26105Sjp151216 #include <port.h> 54c5c4113dSnw141292 #include <tsol/label.h> 55c5c4113dSnw141292 #include <sys/resource.h> 56c5c4113dSnw141292 #include <sys/sid.h> 57c5c4113dSnw141292 #include <sys/idmap.h> 58c5c4113dSnw141292 59c5c4113dSnw141292 static void term_handler(int); 60c5c4113dSnw141292 static void init_idmapd(); 61c5c4113dSnw141292 static void fini_idmapd(); 62c5c4113dSnw141292 63c5c4113dSnw141292 #define _RPCSVC_CLOSEDOWN 120 64c5c4113dSnw141292 65c5c4113dSnw141292 int _rpcsvcstate = _IDLE; /* Set when a request is serviced */ 66c5c4113dSnw141292 int _rpcsvccount = 0; /* Number of requests being serviced */ 67c5c4113dSnw141292 mutex_t _svcstate_lock; /* lock for _rpcsvcstate, _rpcsvccount */ 68c5c4113dSnw141292 idmapd_state_t _idmapdstate; 69c5c4113dSnw141292 70c5c4113dSnw141292 SVCXPRT *xprt = NULL; 71c5c4113dSnw141292 72c5c4113dSnw141292 static int dfd = -1; /* our door server fildes, for unregistration */ 7371590c90Snw141292 static int degraded = 0; /* whether the FMRI has been marked degraded */ 74c5c4113dSnw141292 75c5c4113dSnw141292 /* 76c5c4113dSnw141292 * This is needed for mech_krb5 -- we run as daemon, yes, but we want 7778b2cb9aSnw141292 * mech_krb5 to think we're root so it can get host/nodename.fqdn 7878b2cb9aSnw141292 * tickets for us so we can authenticate to AD as the machine account 7978b2cb9aSnw141292 * that we are. For more details look at the entry point in mech_krb5 8078b2cb9aSnw141292 * corresponding to gss_init_sec_context(). 8178b2cb9aSnw141292 * 8278b2cb9aSnw141292 * As a side effect of faking our effective UID to mech_krb5 we will use 8378b2cb9aSnw141292 * root's default ccache (/tmp/krb5cc_0). But if that's created by 8478b2cb9aSnw141292 * another process then we won't have access to it: we run as daemon and 8578b2cb9aSnw141292 * keep PRIV_FILE_DAC_READ, which is insufficient to share the ccache 8678b2cb9aSnw141292 * with others. We putenv("KRB5CCNAME=/var/run/idmap/ccache") in main() 8778b2cb9aSnw141292 * to avoid this issue; see main(). 88c5c4113dSnw141292 * 89c5c4113dSnw141292 * Someday we'll have gss/mech_krb5 extensions for acquiring initiator 90c5c4113dSnw141292 * creds with keytabs/raw keys, and someday we'll have extensions to 91c5c4113dSnw141292 * libsasl to specify creds/name to use on the initiator side, and 92c5c4113dSnw141292 * someday we'll have extensions to libldap to pass those through to 93c5c4113dSnw141292 * libsasl. Until then this interposer will have to do. 94c5c4113dSnw141292 * 95c5c4113dSnw141292 * Also, we have to tell lint to shut up: it thinks app_krb5_user_uid() 96c5c4113dSnw141292 * is defined but not used. 97c5c4113dSnw141292 */ 98c5c4113dSnw141292 /*LINTLIBRARY*/ 99c5c4113dSnw141292 uid_t 100c5c4113dSnw141292 app_krb5_user_uid(void) 101c5c4113dSnw141292 { 102c5c4113dSnw141292 return (0); 103c5c4113dSnw141292 } 104c5c4113dSnw141292 105c5c4113dSnw141292 /*ARGSUSED*/ 106c5c4113dSnw141292 static void 1074edd44c5Sjp151216 term_handler(int sig) 1084edd44c5Sjp151216 { 10971590c90Snw141292 idmapdlog(LOG_INFO, "Terminating."); 110c5c4113dSnw141292 fini_idmapd(); 111c5c4113dSnw141292 _exit(0); 112c5c4113dSnw141292 } 113c5c4113dSnw141292 11471590c90Snw141292 /*ARGSUSED*/ 11571590c90Snw141292 static void 11671590c90Snw141292 usr1_handler(int sig) 11771590c90Snw141292 { 11871590c90Snw141292 bool_t saved_debug_mode = _idmapdstate.debug_mode; 11971590c90Snw141292 12071590c90Snw141292 _idmapdstate.debug_mode = TRUE; 12171590c90Snw141292 print_idmapdstate(); 12271590c90Snw141292 _idmapdstate.debug_mode = saved_debug_mode; 12371590c90Snw141292 } 12471590c90Snw141292 125c5c4113dSnw141292 static int pipe_fd = -1; 126c5c4113dSnw141292 127c5c4113dSnw141292 static void 1284edd44c5Sjp151216 daemonize_ready(void) 1294edd44c5Sjp151216 { 130c5c4113dSnw141292 char data = '\0'; 131c5c4113dSnw141292 /* 132c5c4113dSnw141292 * wake the parent 133c5c4113dSnw141292 */ 134c5c4113dSnw141292 (void) write(pipe_fd, &data, 1); 135c5c4113dSnw141292 (void) close(pipe_fd); 136c5c4113dSnw141292 } 137c5c4113dSnw141292 138c5c4113dSnw141292 static int 1394edd44c5Sjp151216 daemonize_start(void) 1404edd44c5Sjp151216 { 141c5c4113dSnw141292 char data; 142c5c4113dSnw141292 int status; 143c5c4113dSnw141292 int devnull; 144c5c4113dSnw141292 int filedes[2]; 145c5c4113dSnw141292 pid_t pid; 146c5c4113dSnw141292 14778b2cb9aSnw141292 (void) sigset(SIGPIPE, SIG_IGN); 148c5c4113dSnw141292 devnull = open("/dev/null", O_RDONLY); 149c5c4113dSnw141292 if (devnull < 0) 150c5c4113dSnw141292 return (-1); 151c5c4113dSnw141292 (void) dup2(devnull, 0); 152c5c4113dSnw141292 (void) dup2(2, 1); /* stderr only */ 153c5c4113dSnw141292 if (pipe(filedes) < 0) 154c5c4113dSnw141292 return (-1); 155c5c4113dSnw141292 if ((pid = fork1()) < 0) 156c5c4113dSnw141292 return (-1); 157c5c4113dSnw141292 if (pid != 0) { 158c5c4113dSnw141292 /* 159c5c4113dSnw141292 * parent 160c5c4113dSnw141292 */ 161c5c4113dSnw141292 (void) close(filedes[1]); 162c5c4113dSnw141292 if (read(filedes[0], &data, 1) == 1) { 163c5c4113dSnw141292 /* presume success */ 164c5c4113dSnw141292 _exit(0); 165c5c4113dSnw141292 } 166c5c4113dSnw141292 status = -1; 167c5c4113dSnw141292 (void) wait4(pid, &status, 0, NULL); 168c5c4113dSnw141292 if (WIFEXITED(status)) 169c5c4113dSnw141292 _exit(WEXITSTATUS(status)); 170c5c4113dSnw141292 else 171c5c4113dSnw141292 _exit(-1); 172c5c4113dSnw141292 } 173c5c4113dSnw141292 174c5c4113dSnw141292 /* 175c5c4113dSnw141292 * child 176c5c4113dSnw141292 */ 177c5c4113dSnw141292 pipe_fd = filedes[1]; 178c5c4113dSnw141292 (void) close(filedes[0]); 179c5c4113dSnw141292 (void) setsid(); 180c5c4113dSnw141292 (void) umask(0077); 181c5c4113dSnw141292 openlog("idmap", LOG_PID, LOG_DAEMON); 182c5c4113dSnw141292 return (0); 183c5c4113dSnw141292 } 184c5c4113dSnw141292 185c5c4113dSnw141292 186c5c4113dSnw141292 int 187c5c4113dSnw141292 main(int argc, char **argv) 188c5c4113dSnw141292 { 189c5c4113dSnw141292 int c; 190*2b3ecdebSjp151216 struct rlimit rl; 191c5c4113dSnw141292 19271590c90Snw141292 _idmapdstate.daemon_mode = TRUE; 19371590c90Snw141292 _idmapdstate.debug_mode = FALSE; 19471590c90Snw141292 while ((c = getopt(argc, argv, "d")) != -1) { 195c5c4113dSnw141292 switch (c) { 196c5c4113dSnw141292 case 'd': 19771590c90Snw141292 _idmapdstate.daemon_mode = FALSE; 198c5c4113dSnw141292 break; 199c5c4113dSnw141292 default: 20071590c90Snw141292 fprintf(stderr, "Usage: /usr/lib/idmapd"); 20171590c90Snw141292 return (SMF_EXIT_ERR_CONFIG); 202c5c4113dSnw141292 break; 203c5c4113dSnw141292 } 204c5c4113dSnw141292 } 205c5c4113dSnw141292 206c5c4113dSnw141292 /* set locale and domain for internationalization */ 207c5c4113dSnw141292 (void) setlocale(LC_ALL, ""); 208c5c4113dSnw141292 (void) textdomain(TEXT_DOMAIN); 209c5c4113dSnw141292 210bda89588Sjp151216 if (is_system_labeled() && getzoneid() != GLOBAL_ZONEID) { 21171590c90Snw141292 idmapdlog(LOG_ERR, 21271590c90Snw141292 "with Trusted Extensions idmapd runs only in the " 213bda89588Sjp151216 "global zone"); 214c5c4113dSnw141292 exit(1); 215c5c4113dSnw141292 } 216c5c4113dSnw141292 217*2b3ecdebSjp151216 /* 218*2b3ecdebSjp151216 * Raise the fd limit to max 219*2b3ecdebSjp151216 */ 220*2b3ecdebSjp151216 if (getrlimit(RLIMIT_NOFILE, &rl) != 0) { 221*2b3ecdebSjp151216 idmapdlog(LOG_ERR, "getrlimit failed"); 222*2b3ecdebSjp151216 } else if (rl.rlim_cur < rl.rlim_max) { 223*2b3ecdebSjp151216 rl.rlim_cur = rl.rlim_max; 224*2b3ecdebSjp151216 if (setrlimit(RLIMIT_NOFILE, &rl) != 0) 225*2b3ecdebSjp151216 idmapdlog(LOG_ERR, 226*2b3ecdebSjp151216 "Unable to raise RLIMIT_NOFILE to %d", 227*2b3ecdebSjp151216 rl.rlim_cur); 228*2b3ecdebSjp151216 } 229*2b3ecdebSjp151216 230c5c4113dSnw141292 (void) mutex_init(&_svcstate_lock, USYNC_THREAD, NULL); 231c5c4113dSnw141292 23271590c90Snw141292 if (_idmapdstate.daemon_mode == TRUE) { 233c5c4113dSnw141292 if (daemonize_start() < 0) { 23471590c90Snw141292 (void) idmapdlog(LOG_ERR, "unable to daemonize"); 235c5c4113dSnw141292 exit(-1); 236c5c4113dSnw141292 } 237c5c4113dSnw141292 } else 238c5c4113dSnw141292 (void) umask(0077); 239c5c4113dSnw141292 24084decf41Sjp151216 idmap_init_tsd_key(); 24184decf41Sjp151216 242c5c4113dSnw141292 init_idmapd(); 243c5c4113dSnw141292 24478b2cb9aSnw141292 /* signal handlers that should run only after we're initialized */ 24578b2cb9aSnw141292 (void) sigset(SIGTERM, term_handler); 24671590c90Snw141292 (void) sigset(SIGUSR1, usr1_handler); 2470dcc7149Snw141292 (void) sigset(SIGHUP, idmap_cfg_hup_handler); 24878b2cb9aSnw141292 249c5c4113dSnw141292 if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 250c5c4113dSnw141292 DAEMON_UID, DAEMON_GID, 251c5c4113dSnw141292 PRIV_PROC_AUDIT, PRIV_FILE_DAC_READ, 252c5c4113dSnw141292 (char *)NULL) == -1) { 25371590c90Snw141292 idmapdlog(LOG_ERR, "unable to drop privileges"); 254c5c4113dSnw141292 exit(1); 255c5c4113dSnw141292 } 256c5c4113dSnw141292 257c5c4113dSnw141292 __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, 258c5c4113dSnw141292 PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL); 259c5c4113dSnw141292 26071590c90Snw141292 if (_idmapdstate.daemon_mode == TRUE) 261c5c4113dSnw141292 daemonize_ready(); 262c5c4113dSnw141292 263c5c4113dSnw141292 /* With doors RPC this just wastes this thread, oh well */ 264c5c4113dSnw141292 svc_run(); 265c5c4113dSnw141292 return (0); 266c5c4113dSnw141292 } 267c5c4113dSnw141292 268c5c4113dSnw141292 static void 2694edd44c5Sjp151216 init_idmapd() 2704edd44c5Sjp151216 { 271c5c4113dSnw141292 int error; 272d3a612caSnw141292 int connmaxrec = IDMAP_MAX_DOOR_RPC; 273c5c4113dSnw141292 27478b2cb9aSnw141292 /* create directories as root and chown to daemon uid */ 27578b2cb9aSnw141292 if (create_directory(IDMAP_DBDIR, DAEMON_UID, DAEMON_GID) < 0) 27678b2cb9aSnw141292 exit(1); 27778b2cb9aSnw141292 if (create_directory(IDMAP_CACHEDIR, DAEMON_UID, DAEMON_GID) < 0) 27878b2cb9aSnw141292 exit(1); 27978b2cb9aSnw141292 28078b2cb9aSnw141292 /* 28178b2cb9aSnw141292 * Set KRB5CCNAME in the environment. See app_krb5_user_uid() 282e3c2d6aaSnw141292 * for more details. We blow away the existing one, if there is 283e3c2d6aaSnw141292 * one. 28478b2cb9aSnw141292 */ 285e3c2d6aaSnw141292 (void) unlink(IDMAP_CACHEDIR "/ccache"); 28678b2cb9aSnw141292 putenv("KRB5CCNAME=" IDMAP_CACHEDIR "/ccache"); 28778b2cb9aSnw141292 288c5c4113dSnw141292 if (sysinfo(SI_HOSTNAME, _idmapdstate.hostname, 289c5c4113dSnw141292 sizeof (_idmapdstate.hostname)) == -1) { 290c5c4113dSnw141292 error = errno; 29171590c90Snw141292 idmapdlog(LOG_ERR, "unable to determine hostname, error: %d", 292c5c4113dSnw141292 error); 293c5c4113dSnw141292 exit(1); 294c5c4113dSnw141292 } 295c5c4113dSnw141292 296e8c27ec8Sbaban if ((error = init_mapping_system()) < 0) { 29771590c90Snw141292 idmapdlog(LOG_ERR, "unable to initialize mapping system"); 298e8c27ec8Sbaban exit(error < -2 ? SMF_EXIT_ERR_CONFIG : 1); 299c5c4113dSnw141292 } 300c5c4113dSnw141292 301d3a612caSnw141292 xprt = svc_door_create(idmap_prog_1, IDMAP_PROG, IDMAP_V1, connmaxrec); 302c5c4113dSnw141292 if (xprt == NULL) { 30371590c90Snw141292 idmapdlog(LOG_ERR, "unable to create door RPC service"); 304c5c4113dSnw141292 goto errout; 305c5c4113dSnw141292 } 306c5c4113dSnw141292 3078e228215Sdm199847 if (!svc_control(xprt, SVCSET_CONNMAXREC, &connmaxrec)) { 30871590c90Snw141292 idmapdlog(LOG_ERR, "unable to limit RPC request size"); 3098e228215Sdm199847 goto errout; 3108e228215Sdm199847 } 3118e228215Sdm199847 312c5c4113dSnw141292 dfd = xprt->xp_fd; 313c5c4113dSnw141292 314c5c4113dSnw141292 if (dfd == -1) { 31571590c90Snw141292 idmapdlog(LOG_ERR, "unable to register door"); 316c5c4113dSnw141292 goto errout; 317c5c4113dSnw141292 } 318c5c4113dSnw141292 if ((error = idmap_reg(dfd)) != 0) { 31971590c90Snw141292 idmapdlog(LOG_ERR, "unable to register door (%s)", 320bda89588Sjp151216 strerror(errno)); 321c5c4113dSnw141292 goto errout; 322c5c4113dSnw141292 } 323c5c4113dSnw141292 324c5c4113dSnw141292 if ((error = allocids(_idmapdstate.new_eph_db, 325c5c4113dSnw141292 8192, &_idmapdstate.next_uid, 326c5c4113dSnw141292 8192, &_idmapdstate.next_gid)) != 0) { 32771590c90Snw141292 idmapdlog(LOG_ERR, "unable to allocate ephemeral IDs (%s)", 32871590c90Snw141292 strerror(errno)); 329c5c4113dSnw141292 _idmapdstate.next_uid = _idmapdstate.limit_uid = SENTINEL_PID; 330c5c4113dSnw141292 _idmapdstate.next_gid = _idmapdstate.limit_gid = SENTINEL_PID; 331c5c4113dSnw141292 } else { 332c5c4113dSnw141292 _idmapdstate.limit_uid = _idmapdstate.next_uid + 8192; 333c5c4113dSnw141292 _idmapdstate.limit_gid = _idmapdstate.next_gid + 8192; 334c5c4113dSnw141292 } 335c5c4113dSnw141292 336c5c4113dSnw141292 print_idmapdstate(); 337c5c4113dSnw141292 338c5c4113dSnw141292 return; 339c5c4113dSnw141292 340c5c4113dSnw141292 errout: 341c5c4113dSnw141292 fini_idmapd(); 342c5c4113dSnw141292 exit(1); 343c5c4113dSnw141292 } 344c5c4113dSnw141292 345c5c4113dSnw141292 static void 3464edd44c5Sjp151216 fini_idmapd() 3474edd44c5Sjp151216 { 348c5c4113dSnw141292 idmap_unreg(dfd); 349c5c4113dSnw141292 fini_mapping_system(); 350c5c4113dSnw141292 if (xprt != NULL) 351c5c4113dSnw141292 svc_destroy(xprt); 352c5c4113dSnw141292 } 353c5c4113dSnw141292 35471590c90Snw141292 static 35571590c90Snw141292 const char * 35671590c90Snw141292 get_fmri(void) 35771590c90Snw141292 { 35871590c90Snw141292 static char *fmri = NULL; 35971590c90Snw141292 static char buf[60]; 36071590c90Snw141292 char *s; 36171590c90Snw141292 36271590c90Snw141292 membar_consumer(); 36371590c90Snw141292 s = fmri; 36471590c90Snw141292 if (s != NULL && *s == '\0') 36571590c90Snw141292 return (NULL); 36671590c90Snw141292 else if (s != NULL) 36771590c90Snw141292 return (s); 36871590c90Snw141292 36971590c90Snw141292 if ((s = getenv("SMF_FMRI")) == NULL || strlen(s) >= sizeof (buf)) 37071590c90Snw141292 buf[0] = '\0'; 37171590c90Snw141292 else 37271590c90Snw141292 (void) strlcpy(buf, s, sizeof (buf)); 37371590c90Snw141292 37471590c90Snw141292 membar_producer(); 37571590c90Snw141292 fmri = buf; 37671590c90Snw141292 37771590c90Snw141292 return (get_fmri()); 37871590c90Snw141292 } 37971590c90Snw141292 38071590c90Snw141292 /* 38171590c90Snw141292 * Wrappers for smf_degrade/restore_instance() 38271590c90Snw141292 * 38371590c90Snw141292 * smf_restore_instance() is too heavy duty to be calling every time we 38471590c90Snw141292 * have a successful AD name<->SID lookup. 38571590c90Snw141292 */ 38671590c90Snw141292 void 387349d5d8fSnw141292 degrade_svc(int poke_discovery, const char *reason) 38871590c90Snw141292 { 38971590c90Snw141292 const char *fmri; 39071590c90Snw141292 39171590c90Snw141292 /* 39271590c90Snw141292 * If the config update thread is in a state where auto-discovery could 39371590c90Snw141292 * be re-tried, then this will make it try it -- a sort of auto-refresh. 39471590c90Snw141292 */ 395349d5d8fSnw141292 if (poke_discovery) 39671590c90Snw141292 idmap_cfg_poke_updates(); 39771590c90Snw141292 39871590c90Snw141292 membar_consumer(); 39971590c90Snw141292 if (degraded) 40071590c90Snw141292 return; 401349d5d8fSnw141292 402349d5d8fSnw141292 idmapdlog(LOG_ERR, "Degraded operation (%s). If you are running an " 403349d5d8fSnw141292 "SMB server in workgroup mode, or if you're not running an SMB " 404349d5d8fSnw141292 "server, then you can ignore this message", reason); 405349d5d8fSnw141292 40671590c90Snw141292 membar_producer(); 40771590c90Snw141292 degraded = 1; 40871590c90Snw141292 40971590c90Snw141292 if ((fmri = get_fmri()) != NULL) 41071590c90Snw141292 (void) smf_degrade_instance(fmri, 0); 41171590c90Snw141292 } 41271590c90Snw141292 41371590c90Snw141292 void 41471590c90Snw141292 restore_svc(void) 41571590c90Snw141292 { 41671590c90Snw141292 const char *fmri; 41771590c90Snw141292 41871590c90Snw141292 membar_consumer(); 41971590c90Snw141292 if (!degraded) 42071590c90Snw141292 return; 42171590c90Snw141292 42271590c90Snw141292 if ((fmri = get_fmri()) == NULL) 42371590c90Snw141292 (void) smf_restore_instance(fmri); 42471590c90Snw141292 42571590c90Snw141292 membar_producer(); 42671590c90Snw141292 degraded = 0; 427349d5d8fSnw141292 idmapdlog(LOG_NOTICE, "Normal operation restored"); 42871590c90Snw141292 } 42971590c90Snw141292 430c5c4113dSnw141292 void 4314edd44c5Sjp151216 idmapdlog(int pri, const char *format, ...) 4324edd44c5Sjp151216 { 433c5c4113dSnw141292 va_list args; 434c5c4113dSnw141292 435c5c4113dSnw141292 va_start(args, format); 43671590c90Snw141292 43771590c90Snw141292 if (_idmapdstate.debug_mode == TRUE || 43871590c90Snw141292 _idmapdstate.daemon_mode == FALSE) { 439c5c4113dSnw141292 (void) vfprintf(stderr, format, args); 440c5c4113dSnw141292 (void) fprintf(stderr, "\n"); 441c5c4113dSnw141292 } 44271590c90Snw141292 44371590c90Snw141292 /* 44471590c90Snw141292 * We don't want to fill up the logs with useless messages when 44571590c90Snw141292 * we're degraded, but we still want to log. 44671590c90Snw141292 */ 44771590c90Snw141292 if (degraded) 44871590c90Snw141292 pri = LOG_DEBUG; 44971590c90Snw141292 450c5c4113dSnw141292 (void) vsyslog(pri, format, args); 451c5c4113dSnw141292 va_end(args); 452c5c4113dSnw141292 } 453