xref: /onnv-gate/usr/src/cmd/idmap/idmapd/idmap_config.c (revision 8671:d3ec1a19966c)
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  * Config routines common to idmap(1M) and idmapd(1M)
294520Snw141292  */
304520Snw141292 
314520Snw141292 #include <stdlib.h>
324520Snw141292 #include <strings.h>
334520Snw141292 #include <libintl.h>
344520Snw141292 #include <ctype.h>
354520Snw141292 #include <errno.h>
364644Sbaban #include "idmapd.h"
374520Snw141292 #include <stdio.h>
384520Snw141292 #include <stdarg.h>
394695Sbaban #include <uuid/uuid.h>
405317Sjp151216 #include <pthread.h>
415317Sjp151216 #include <port.h>
425968Snw141292 #include <net/route.h>
438361SJulian.Pullen@Sun.COM #include <sys/u8_textprep.h>
445317Sjp151216 #include "addisc.h"
454520Snw141292 
467031Snw141292 #define	MACHINE_SID_LEN		(9 + 3 * 11)
475968Snw141292 #define	FMRI_BASE		"svc:/system/idmap"
485968Snw141292 #define	CONFIG_PG		"config"
495968Snw141292 #define	GENERAL_PG		"general"
505968Snw141292 #define	RECONFIGURE		1
515968Snw141292 #define	POKE_AUTO_DISCOVERY	2
524520Snw141292 
535317Sjp151216 /*LINTLIBRARY*/
545317Sjp151216 
555317Sjp151216 
565317Sjp151216 static pthread_t update_thread_handle = 0;
575317Sjp151216 
585968Snw141292 static int idmapd_ev_port = -1;
595968Snw141292 static int rt_sock = -1;
605317Sjp151216 
614695Sbaban static int
625908Sjp151216 generate_machine_sid(char **machine_sid)
635908Sjp151216 {
644695Sbaban 	char *p;
654695Sbaban 	uuid_t uu;
664695Sbaban 	int i, j, len, rlen;
674695Sbaban 	uint32_t rid;
684695Sbaban 
694695Sbaban 	/*
707031Snw141292 	 * Generate and split 128-bit UUID into three 32-bit RIDs The
717031Snw141292 	 * machine_sid will be of the form S-1-5-21-N1-N2-N3 (that's
727031Snw141292 	 * four RIDs altogether).
737031Snw141292 	 *
747031Snw141292 	 * Technically we could use upto 14 random RIDs here, but it
757031Snw141292 	 * turns out that with some versions of Windows using SIDs with
767031Snw141292 	 * more than  five RIDs in security descriptors causes problems.
774695Sbaban 	 */
784695Sbaban 
794695Sbaban 	*machine_sid = calloc(1, MACHINE_SID_LEN);
804695Sbaban 	if (*machine_sid == NULL) {
816017Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
824695Sbaban 		return (-1);
834695Sbaban 	}
844695Sbaban 	(void) strcpy(*machine_sid, "S-1-5-21");
854695Sbaban 	p = *machine_sid + strlen("S-1-5-21");
864695Sbaban 	len = MACHINE_SID_LEN - strlen("S-1-5-21");
874695Sbaban 
884695Sbaban 	uuid_clear(uu);
894695Sbaban 	uuid_generate_random(uu);
904695Sbaban 
917031Snw141292 #if UUID_LEN != 16
927031Snw141292 #error UUID size is not 16!
937031Snw141292 #endif
947031Snw141292 
957031Snw141292 	for (i = 0; i < 3; i++) {
964695Sbaban 		j = i * 4;
974695Sbaban 		rid = (uu[j] << 24) | (uu[j + 1] << 16) |
985908Sjp151216 		    (uu[j + 2] << 8) | (uu[j + 3]);
994695Sbaban 		rlen = snprintf(p, len, "-%u", rid);
1004695Sbaban 		p += rlen;
1014695Sbaban 		len -= rlen;
1024695Sbaban 	}
1034695Sbaban 
1044695Sbaban 	return (0);
1054695Sbaban }
1064695Sbaban 
1076616Sdm199847 
1086616Sdm199847 /* In the case of error, exists is set to FALSE anyway */
1096616Sdm199847 static int
110*8671SJulian.Pullen@Sun.COM prop_exists(idmap_cfg_handles_t *handles, char *name, boolean_t *exists)
1116017Snw141292 {
1126616Sdm199847 
1136616Sdm199847 	scf_property_t *scf_prop;
1146616Sdm199847 	scf_value_t *value;
1156616Sdm199847 
116*8671SJulian.Pullen@Sun.COM 	*exists = B_FALSE;
1176017Snw141292 
1186616Sdm199847 	scf_prop = scf_property_create(handles->main);
1196616Sdm199847 	if (scf_prop == NULL) {
1206616Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
1216616Sdm199847 		    scf_strerror(scf_error()));
1226616Sdm199847 		return (-1);
1236616Sdm199847 	}
1246616Sdm199847 	value = scf_value_create(handles->main);
1256616Sdm199847 	if (value == NULL) {
1266616Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
1276616Sdm199847 		    scf_strerror(scf_error()));
1286616Sdm199847 		scf_property_destroy(scf_prop);
1296616Sdm199847 		return (-1);
1306616Sdm199847 	}
1316017Snw141292 
1326017Snw141292 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) == 0)
133*8671SJulian.Pullen@Sun.COM 		*exists = B_TRUE;
1346017Snw141292 
1356017Snw141292 	scf_value_destroy(value);
1366017Snw141292 	scf_property_destroy(scf_prop);
1376017Snw141292 
1386616Sdm199847 	return (0);
1396017Snw141292 }
1406017Snw141292 
1414520Snw141292 /* Check if in the case of failure the original value of *val is preserved */
1424520Snw141292 static int
1435317Sjp151216 get_val_int(idmap_cfg_handles_t *handles, char *name,
1445317Sjp151216 	void *val, scf_type_t type)
1454520Snw141292 {
1464520Snw141292 	int rc = 0;
1474520Snw141292 
1486616Sdm199847 	scf_property_t *scf_prop;
1496616Sdm199847 	scf_value_t *value;
1506616Sdm199847 
1517031Snw141292 	switch (type) {
1527031Snw141292 	case SCF_TYPE_BOOLEAN:
1537031Snw141292 		*(uint8_t *)val = 0;
1547031Snw141292 		break;
1557031Snw141292 	case SCF_TYPE_COUNT:
1567031Snw141292 		*(uint64_t *)val = 0;
1577031Snw141292 		break;
1587031Snw141292 	case SCF_TYPE_INTEGER:
1597031Snw141292 		*(int64_t *)val = 0;
1607031Snw141292 		break;
1617031Snw141292 	default:
1627031Snw141292 		idmapdlog(LOG_ERR, "Invalid scf integer type (%d)",
1637031Snw141292 		    type);
1647031Snw141292 		abort();
1657031Snw141292 	}
1667031Snw141292 
1676616Sdm199847 	scf_prop = scf_property_create(handles->main);
1686616Sdm199847 	if (scf_prop == NULL) {
1696616Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
1706616Sdm199847 		    scf_strerror(scf_error()));
1716616Sdm199847 		return (-1);
1726616Sdm199847 	}
1736616Sdm199847 	value = scf_value_create(handles->main);
1746616Sdm199847 	if (value == NULL) {
1756616Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
1766616Sdm199847 		    scf_strerror(scf_error()));
1776616Sdm199847 		scf_property_destroy(scf_prop);
1786616Sdm199847 		return (-1);
1796616Sdm199847 	}
1804520Snw141292 
1815317Sjp151216 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
1824520Snw141292 	/* this is OK: the property is just undefined */
1834520Snw141292 		goto destruction;
1844520Snw141292 
1854520Snw141292 
1865317Sjp151216 	if (scf_property_get_value(scf_prop, value) < 0)
1874520Snw141292 	/* It is still OK when a property doesn't have any value */
1884520Snw141292 		goto destruction;
1894520Snw141292 
1904520Snw141292 	switch (type) {
1914520Snw141292 	case SCF_TYPE_BOOLEAN:
1924520Snw141292 		rc = scf_value_get_boolean(value, val);
1934520Snw141292 		break;
1944520Snw141292 	case SCF_TYPE_COUNT:
1954520Snw141292 		rc = scf_value_get_count(value, val);
1964520Snw141292 		break;
1974520Snw141292 	case SCF_TYPE_INTEGER:
1984520Snw141292 		rc = scf_value_get_integer(value, val);
1994520Snw141292 		break;
2004520Snw141292 	}
2014520Snw141292 
2024520Snw141292 
2034520Snw141292 destruction:
2044520Snw141292 	scf_value_destroy(value);
2054520Snw141292 	scf_property_destroy(scf_prop);
2064520Snw141292 
2074520Snw141292 	return (rc);
2084520Snw141292 }
2094520Snw141292 
2104520Snw141292 static char *
2115908Sjp151216 scf_value2string(scf_value_t *value)
2125908Sjp151216 {
2134520Snw141292 	int rc = -1;
2144520Snw141292 	char buf_size = 127;
2154520Snw141292 	int length;
2164520Snw141292 	char *buf = NULL;
2174520Snw141292 	buf = (char *) malloc(sizeof (char) * buf_size);
2184520Snw141292 
2194520Snw141292 	for (;;) {
2204520Snw141292 		length = scf_value_get_astring(value, buf, buf_size);
2214520Snw141292 		if (length < 0) {
2224520Snw141292 			rc = -1;
2234520Snw141292 			goto destruction;
2244520Snw141292 		}
2254520Snw141292 
2264520Snw141292 		if (length == buf_size - 1) {
2274520Snw141292 			buf_size *= 2;
2284520Snw141292 			buf = (char *)realloc(buf, buf_size * sizeof (char));
2294520Snw141292 			if (!buf) {
2306017Snw141292 				idmapdlog(LOG_ERR, "Out of memory");
2314520Snw141292 				rc = -1;
2324520Snw141292 				goto destruction;
2334520Snw141292 			}
2344520Snw141292 		} else {
2354520Snw141292 			rc = 0;
2365908Sjp151216 			break;
2375908Sjp151216 		}
2384520Snw141292 	}
2394520Snw141292 
2404520Snw141292 destruction:
2414520Snw141292 	if (rc < 0) {
2424520Snw141292 		if (buf)
2434520Snw141292 			free(buf);
2444520Snw141292 		buf = NULL;
2454520Snw141292 	}
2464520Snw141292 
2474520Snw141292 	return (buf);
2484520Snw141292 }
2494520Snw141292 
2505317Sjp151216 static int
2515317Sjp151216 get_val_ds(idmap_cfg_handles_t *handles, const char *name, int defport,
2526616Sdm199847 		idmap_ad_disc_ds_t **val)
2535317Sjp151216 {
2546616Sdm199847 	idmap_ad_disc_ds_t *servers = NULL;
2555317Sjp151216 	scf_property_t *scf_prop;
2565317Sjp151216 	scf_value_t *value;
2575317Sjp151216 	scf_iter_t *iter;
2585317Sjp151216 	char *host, *portstr;
2595447Snw141292 	int len, i;
2605317Sjp151216 	int count = 0;
2615447Snw141292 	int rc = -1;
2625317Sjp151216 
2635317Sjp151216 	*val = NULL;
2645317Sjp151216 
2655317Sjp151216 restart:
2665317Sjp151216 	scf_prop = scf_property_create(handles->main);
2676616Sdm199847 	if (scf_prop == NULL) {
2686616Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
2696616Sdm199847 		    scf_strerror(scf_error()));
2706616Sdm199847 		return (-1);
2716616Sdm199847 	}
2726616Sdm199847 
2735317Sjp151216 	value = scf_value_create(handles->main);
2746616Sdm199847 	if (value == NULL) {
2756616Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
2766616Sdm199847 		    scf_strerror(scf_error()));
2776616Sdm199847 		scf_property_destroy(scf_prop);
2786616Sdm199847 		return (-1);
2796616Sdm199847 	}
2806616Sdm199847 
2815317Sjp151216 	iter = scf_iter_create(handles->main);
2826616Sdm199847 	if (iter == NULL) {
2836616Sdm199847 		idmapdlog(LOG_ERR, "scf_iter_create() failed: %s",
2846616Sdm199847 		    scf_strerror(scf_error()));
2856616Sdm199847 		scf_value_destroy(value);
2866616Sdm199847 		scf_property_destroy(scf_prop);
2876616Sdm199847 		return (-1);
2886616Sdm199847 	}
2895317Sjp151216 
2905447Snw141292 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) {
2915317Sjp151216 		/* this is OK: the property is just undefined */
2925447Snw141292 		rc = 0;
2935317Sjp151216 		goto destruction;
2945447Snw141292 	}
2955317Sjp151216 
2965317Sjp151216 	if (scf_iter_property_values(iter, scf_prop) < 0) {
2975317Sjp151216 		idmapdlog(LOG_ERR,
2986017Snw141292 		    "scf_iter_property_values(%s) failed: %s",
2996017Snw141292 		    name, scf_strerror(scf_error()));
3005317Sjp151216 		goto destruction;
3015317Sjp151216 	}
3025317Sjp151216 
3035317Sjp151216 	/* Workaround scf bugs -- can't reset an iteration */
3045317Sjp151216 	if (count == 0) {
3055317Sjp151216 		while (scf_iter_next_value(iter, value) > 0)
3065317Sjp151216 			count++;
3075317Sjp151216 
3085447Snw141292 		if (count == 0) {
3095317Sjp151216 			/* no values */
3105447Snw141292 			rc = 0;
3115317Sjp151216 			goto destruction;
3125447Snw141292 		}
3135317Sjp151216 
3145317Sjp151216 		scf_value_destroy(value);
3155317Sjp151216 		scf_iter_destroy(iter);
3165317Sjp151216 		scf_property_destroy(scf_prop);
3175317Sjp151216 		goto restart;
3185317Sjp151216 	}
3195317Sjp151216 
3205317Sjp151216 	if ((servers = calloc(count + 1, sizeof (*servers))) == NULL) {
3216017Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
3225317Sjp151216 		goto destruction;
3235317Sjp151216 	}
3245317Sjp151216 
3255447Snw141292 	i = 0;
3265447Snw141292 	while (i < count && scf_iter_next_value(iter, value) > 0) {
3275447Snw141292 		servers[i].priority = 0;
3285447Snw141292 		servers[i].weight = 100;
3295447Snw141292 		servers[i].port = defport;
3305317Sjp151216 		if ((host = scf_value2string(value)) == NULL) {
3315317Sjp151216 			goto destruction;
3325317Sjp151216 		}
3335317Sjp151216 		if ((portstr = strchr(host, ':')) != NULL) {
3345317Sjp151216 			*portstr++ = '\0';
3355447Snw141292 			servers[i].port = strtol(portstr,
3365317Sjp151216 			    (char **)NULL, 10);
3375447Snw141292 			if (servers[i].port == 0)
3385447Snw141292 				servers[i].port = defport;
3395317Sjp151216 		}
3405447Snw141292 		len = strlcpy(servers[i].host, host,
3415317Sjp151216 		    sizeof (servers->host));
3425317Sjp151216 
3435317Sjp151216 		free(host);
3445317Sjp151216 
3455317Sjp151216 		/* Ignore this server if the hostname is too long */
3465317Sjp151216 		if (len < sizeof (servers->host))
3475447Snw141292 			i++;
3485317Sjp151216 	}
3495317Sjp151216 
3505317Sjp151216 	*val = servers;
3515317Sjp151216 
3525447Snw141292 	rc = 0;
3535447Snw141292 
3545317Sjp151216 destruction:
3555317Sjp151216 	scf_value_destroy(value);
3565317Sjp151216 	scf_iter_destroy(iter);
3575317Sjp151216 	scf_property_destroy(scf_prop);
3585317Sjp151216 
3595317Sjp151216 	if (rc < 0) {
3605317Sjp151216 		if (servers)
3615317Sjp151216 			free(servers);
3625317Sjp151216 		*val = NULL;
3635317Sjp151216 	}
3645317Sjp151216 
3655317Sjp151216 	return (rc);
3665317Sjp151216 }
3675317Sjp151216 
3684520Snw141292 
3694520Snw141292 static int
3705317Sjp151216 get_val_astring(idmap_cfg_handles_t *handles, char *name, char **val)
3714520Snw141292 {
3724520Snw141292 	int rc = 0;
3734520Snw141292 
3746616Sdm199847 	scf_property_t *scf_prop;
3756616Sdm199847 	scf_value_t *value;
3766616Sdm199847 
3776616Sdm199847 	scf_prop = scf_property_create(handles->main);
3786616Sdm199847 	if (scf_prop == NULL) {
3796616Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
3806616Sdm199847 		    scf_strerror(scf_error()));
3816616Sdm199847 		return (-1);
3826616Sdm199847 	}
3836616Sdm199847 	value = scf_value_create(handles->main);
3846616Sdm199847 	if (value == NULL) {
3856616Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
3866616Sdm199847 		    scf_strerror(scf_error()));
3876616Sdm199847 		scf_property_destroy(scf_prop);
3886616Sdm199847 		return (-1);
3896616Sdm199847 	}
3904520Snw141292 
3915317Sjp151216 	*val = NULL;
3924520Snw141292 
3935317Sjp151216 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
3944520Snw141292 	/* this is OK: the property is just undefined */
3954520Snw141292 		goto destruction;
3964520Snw141292 
3975317Sjp151216 	if (scf_property_get_value(scf_prop, value) < 0) {
3984644Sbaban 		idmapdlog(LOG_ERR,
3996017Snw141292 		    "scf_property_get_value(%s) failed: %s",
4006017Snw141292 		    name, scf_strerror(scf_error()));
4014520Snw141292 		rc = -1;
4024520Snw141292 		goto destruction;
4034520Snw141292 	}
4044520Snw141292 
4055317Sjp151216 	if (!(*val = scf_value2string(value)))
4064520Snw141292 		rc = -1;
4074520Snw141292 
4084520Snw141292 destruction:
4094520Snw141292 	scf_value_destroy(value);
4104520Snw141292 	scf_property_destroy(scf_prop);
4114520Snw141292 
4124520Snw141292 	if (rc < 0) {
4134520Snw141292 		if (*val)
4144520Snw141292 			free(*val);
4154520Snw141292 		*val = NULL;
4164520Snw141292 	}
4174520Snw141292 
4184520Snw141292 	return (rc);
4194520Snw141292 }
4204520Snw141292 
4215317Sjp151216 
4224695Sbaban static int
4235317Sjp151216 set_val_astring(idmap_cfg_handles_t *handles, char *name, const char *val)
4244695Sbaban {
4255447Snw141292 	int			rc = -1;
4265447Snw141292 	int			ret = -2;
4275447Snw141292 	int			i;
4284695Sbaban 	scf_property_t		*scf_prop = NULL;
4294695Sbaban 	scf_value_t		*value = NULL;
4304695Sbaban 	scf_transaction_t	*tx = NULL;
4314695Sbaban 	scf_transaction_entry_t	*ent = NULL;
4324695Sbaban 
4335317Sjp151216 	if ((scf_prop = scf_property_create(handles->main)) == NULL ||
4345317Sjp151216 	    (value = scf_value_create(handles->main)) == NULL ||
4355317Sjp151216 	    (tx = scf_transaction_create(handles->main)) == NULL ||
4365317Sjp151216 	    (ent = scf_entry_create(handles->main)) == NULL) {
4376017Snw141292 		idmapdlog(LOG_ERR, "Unable to set property %s",
4386017Snw141292 		    name, scf_strerror(scf_error()));
4394695Sbaban 		goto destruction;
4404695Sbaban 	}
4414695Sbaban 
4425447Snw141292 	for (i = 0; i < MAX_TRIES && (ret == -2 || ret == 0); i++) {
4435317Sjp151216 		if (scf_transaction_start(tx, handles->config_pg) == -1) {
4444695Sbaban 			idmapdlog(LOG_ERR,
4456017Snw141292 			    "scf_transaction_start(%s) failed: %s",
4466017Snw141292 			    name, scf_strerror(scf_error()));
4474695Sbaban 			goto destruction;
4484695Sbaban 		}
4494695Sbaban 
4505447Snw141292 		if (scf_transaction_property_new(tx, ent, name,
4515447Snw141292 		    SCF_TYPE_ASTRING) < 0) {
4524695Sbaban 			idmapdlog(LOG_ERR,
4536017Snw141292 			    "scf_transaction_property_new() failed: %s",
4546017Snw141292 			    scf_strerror(scf_error()));
4554695Sbaban 			goto destruction;
4564695Sbaban 		}
4574695Sbaban 
4584695Sbaban 		if (scf_value_set_astring(value, val) == -1) {
4594695Sbaban 			idmapdlog(LOG_ERR,
4606017Snw141292 			    "scf_value_set_astring() failed: %s",
4616017Snw141292 			    scf_strerror(scf_error()));
4624695Sbaban 			goto destruction;
4634695Sbaban 		}
4644695Sbaban 
4654695Sbaban 		if (scf_entry_add_value(ent, value) == -1) {
4664695Sbaban 			idmapdlog(LOG_ERR,
4676017Snw141292 			    "scf_entry_add_value() failed: %s",
4686017Snw141292 			    scf_strerror(scf_error()));
4694695Sbaban 			goto destruction;
4704695Sbaban 		}
4714695Sbaban 
4725447Snw141292 		if ((ret = scf_transaction_commit(tx)) == 1)
4735447Snw141292 			break;
4745447Snw141292 
4755447Snw141292 		if (ret == 0 && i < MAX_TRIES - 1) {
4764695Sbaban 			/*
4774695Sbaban 			 * Property group set in scf_transaction_start()
4784695Sbaban 			 * is not the most recent. Update pg, reset tx and
4794695Sbaban 			 * retry tx.
4804695Sbaban 			 */
4814695Sbaban 			idmapdlog(LOG_WARNING,
4826017Snw141292 			    "scf_transaction_commit(%s) failed - Retry: %s",
4836017Snw141292 			    name, scf_strerror(scf_error()));
4845317Sjp151216 			if (scf_pg_update(handles->config_pg) == -1) {
4854695Sbaban 				idmapdlog(LOG_ERR,
4866017Snw141292 				    "scf_pg_update() failed: %s",
4876017Snw141292 				    scf_strerror(scf_error()));
4884695Sbaban 				goto destruction;
4894695Sbaban 			}
4904695Sbaban 			scf_transaction_reset(tx);
4914695Sbaban 		}
4924695Sbaban 	}
4934695Sbaban 
4945447Snw141292 
4955447Snw141292 	if (ret == 1)
4965447Snw141292 		rc = 0;
4975447Snw141292 	else if (ret != -2)
4984695Sbaban 		idmapdlog(LOG_ERR,
4996017Snw141292 		    "scf_transaction_commit(%s) failed: %s",
5006017Snw141292 		    name, scf_strerror(scf_error()));
5014695Sbaban 
5024695Sbaban destruction:
5034695Sbaban 	scf_value_destroy(value);
5044695Sbaban 	scf_entry_destroy(ent);
5054695Sbaban 	scf_transaction_destroy(tx);
5064695Sbaban 	scf_property_destroy(scf_prop);
5074695Sbaban 	return (rc);
5084695Sbaban }
5094695Sbaban 
5108361SJulian.Pullen@Sun.COM 
5118361SJulian.Pullen@Sun.COM 
5128361SJulian.Pullen@Sun.COM /*
5138361SJulian.Pullen@Sun.COM  * This function updates a boolean value.
5148361SJulian.Pullen@Sun.COM  * If nothing has changed it returns 0 else 1
5158361SJulian.Pullen@Sun.COM  */
5165317Sjp151216 static int
517*8671SJulian.Pullen@Sun.COM update_bool(boolean_t *value, boolean_t *new, char *name)
5187031Snw141292 {
5197031Snw141292 	if (*value == *new)
5207031Snw141292 		return (0);
5217031Snw141292 
5227031Snw141292 	idmapdlog(LOG_INFO, "change %s=%s", name, *new ? "true" : "false");
5237031Snw141292 	*value = *new;
5247031Snw141292 	return (1);
5257031Snw141292 }
5267031Snw141292 
5278361SJulian.Pullen@Sun.COM 
5288361SJulian.Pullen@Sun.COM /*
5298361SJulian.Pullen@Sun.COM  * This function updates a string value.
5308361SJulian.Pullen@Sun.COM  * If nothing has changed it returns 0 else 1
5318361SJulian.Pullen@Sun.COM  */
5327031Snw141292 static int
5337031Snw141292 update_string(char **value, char **new, char *name)
5344520Snw141292 {
5355317Sjp151216 	if (*new == NULL)
5366097Snw141292 		return (0);
5374520Snw141292 
5385317Sjp151216 	if (*value != NULL && strcmp(*new, *value) == 0) {
5395317Sjp151216 		free(*new);
5405317Sjp151216 		*new = NULL;
5416097Snw141292 		return (0);
5424520Snw141292 	}
5434520Snw141292 
5446017Snw141292 	idmapdlog(LOG_INFO, "change %s=%s", name, CHECK_NULL(*new));
5455317Sjp151216 	if (*value != NULL)
5465317Sjp151216 		free(*value);
5475317Sjp151216 	*value = *new;
5485317Sjp151216 	*new = NULL;
5496097Snw141292 	return (1);
5505317Sjp151216 }
5515317Sjp151216 
5528361SJulian.Pullen@Sun.COM 
5538361SJulian.Pullen@Sun.COM /*
5548361SJulian.Pullen@Sun.COM  * This function updates a directory service structure.
5558361SJulian.Pullen@Sun.COM  * If nothing has changed it returns 0 else 1
5568361SJulian.Pullen@Sun.COM  */
5575317Sjp151216 static int
5586616Sdm199847 update_dirs(idmap_ad_disc_ds_t **value, idmap_ad_disc_ds_t **new, char *name)
5595317Sjp151216 {
5605317Sjp151216 	int i;
5615317Sjp151216 
5625968Snw141292 	if (*value == *new)
5635968Snw141292 		/* Nothing to do */
5646097Snw141292 		return (0);
5655317Sjp151216 
5665968Snw141292 	if (*value != NULL && *new != NULL &&
5675968Snw141292 	    ad_disc_compare_ds(*value, *new) == 0) {
5685317Sjp151216 		free(*new);
5695317Sjp151216 		*new = NULL;
5706097Snw141292 		return (0);
5714520Snw141292 	}
5724520Snw141292 
5738361SJulian.Pullen@Sun.COM 	if (*value != NULL)
5745317Sjp151216 		free(*value);
5755317Sjp151216 
5765317Sjp151216 	*value = *new;
5775317Sjp151216 	*new = NULL;
5785968Snw141292 
5795968Snw141292 	if (*value == NULL) {
5805968Snw141292 		/* We're unsetting this DS property */
5816017Snw141292 		idmapdlog(LOG_INFO, "change %s=<none>", name);
5826097Snw141292 		return (1);
5835968Snw141292 	}
5845968Snw141292 
5855968Snw141292 	/* List all the new DSs */
5865968Snw141292 	for (i = 0; (*value)[i].host[0] != '\0'; i++)
5876017Snw141292 		idmapdlog(LOG_INFO, "change %s=%s port=%d", name,
5885968Snw141292 		    (*value)[i].host, (*value)[i].port);
5896097Snw141292 	return (1);
5905317Sjp151216 }
5915317Sjp151216 
5928361SJulian.Pullen@Sun.COM /*
5938361SJulian.Pullen@Sun.COM  * This function updates a trusted domains structure.
5948361SJulian.Pullen@Sun.COM  * If nothing has changed it returns 0 else 1
5958361SJulian.Pullen@Sun.COM  */
5968361SJulian.Pullen@Sun.COM static int
5978361SJulian.Pullen@Sun.COM update_trusted_domains(ad_disc_trusteddomains_t **value,
5988361SJulian.Pullen@Sun.COM 			ad_disc_trusteddomains_t **new, char *name)
5998361SJulian.Pullen@Sun.COM {
6008361SJulian.Pullen@Sun.COM 	int i;
6018361SJulian.Pullen@Sun.COM 
6028361SJulian.Pullen@Sun.COM 	if (*value == *new)
6038361SJulian.Pullen@Sun.COM 		/* Nothing to do */
6048361SJulian.Pullen@Sun.COM 		return (0);
6058361SJulian.Pullen@Sun.COM 
6068361SJulian.Pullen@Sun.COM 	if (*value != NULL && *new != NULL &&
6078361SJulian.Pullen@Sun.COM 	    ad_disc_compare_trusteddomains(*value, *new) == 0) {
6088361SJulian.Pullen@Sun.COM 		free(*new);
6098361SJulian.Pullen@Sun.COM 		*new = NULL;
6108361SJulian.Pullen@Sun.COM 		return (0);
6118361SJulian.Pullen@Sun.COM 	}
6128361SJulian.Pullen@Sun.COM 
6138361SJulian.Pullen@Sun.COM 	if (*value != NULL)
6148361SJulian.Pullen@Sun.COM 		free(*value);
6158361SJulian.Pullen@Sun.COM 
6168361SJulian.Pullen@Sun.COM 	*value = *new;
6178361SJulian.Pullen@Sun.COM 	*new = NULL;
6188361SJulian.Pullen@Sun.COM 
6198361SJulian.Pullen@Sun.COM 	if (*value == NULL) {
6208361SJulian.Pullen@Sun.COM 		/* We're unsetting this DS property */
6218361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_INFO, "change %s=<none>", name);
6228361SJulian.Pullen@Sun.COM 		return (1);
6238361SJulian.Pullen@Sun.COM 	}
6248361SJulian.Pullen@Sun.COM 
6258361SJulian.Pullen@Sun.COM 	/* List all the new domains */
6268361SJulian.Pullen@Sun.COM 	for (i = 0; (*value)[i].domain[0] != '\0'; i++)
6278361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_INFO, "change %s=%s direction=%s", name,
6288361SJulian.Pullen@Sun.COM 		    (*value)[i].domain,
6298361SJulian.Pullen@Sun.COM 		    (*value)[i].direction == 3 ? "bi-directional" : "inbound");
6308361SJulian.Pullen@Sun.COM 	return (1);
6318361SJulian.Pullen@Sun.COM }
6328361SJulian.Pullen@Sun.COM 
6338361SJulian.Pullen@Sun.COM 
6348361SJulian.Pullen@Sun.COM /*
6358361SJulian.Pullen@Sun.COM  * This function updates a domains in a forest structure.
6368361SJulian.Pullen@Sun.COM  * If nothing has changed it returns 0 else 1
6378361SJulian.Pullen@Sun.COM  */
6388361SJulian.Pullen@Sun.COM static int
6398361SJulian.Pullen@Sun.COM update_domains_in_forest(ad_disc_domainsinforest_t **value,
6408361SJulian.Pullen@Sun.COM 			ad_disc_domainsinforest_t **new, char *name)
6418361SJulian.Pullen@Sun.COM {
6428361SJulian.Pullen@Sun.COM 	int i;
6438361SJulian.Pullen@Sun.COM 
6448361SJulian.Pullen@Sun.COM 	if (*value == *new)
6458361SJulian.Pullen@Sun.COM 		/* Nothing to do */
6468361SJulian.Pullen@Sun.COM 		return (0);
6478361SJulian.Pullen@Sun.COM 
6488361SJulian.Pullen@Sun.COM 	if (*value != NULL && *new != NULL &&
6498361SJulian.Pullen@Sun.COM 	    ad_disc_compare_domainsinforest(*value, *new) == 0) {
6508361SJulian.Pullen@Sun.COM 		free(*new);
6518361SJulian.Pullen@Sun.COM 		*new = NULL;
6528361SJulian.Pullen@Sun.COM 		return (0);
6538361SJulian.Pullen@Sun.COM 	}
6548361SJulian.Pullen@Sun.COM 
6558361SJulian.Pullen@Sun.COM 	if (*value != NULL)
6568361SJulian.Pullen@Sun.COM 		free(*value);
6578361SJulian.Pullen@Sun.COM 
6588361SJulian.Pullen@Sun.COM 	*value = *new;
6598361SJulian.Pullen@Sun.COM 	*new = NULL;
6608361SJulian.Pullen@Sun.COM 
6618361SJulian.Pullen@Sun.COM 	if (*value == NULL) {
6628361SJulian.Pullen@Sun.COM 		/* We're unsetting this DS property */
6638361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_INFO, "change %s=<none>", name);
6648361SJulian.Pullen@Sun.COM 		return (1);
6658361SJulian.Pullen@Sun.COM 	}
6668361SJulian.Pullen@Sun.COM 
6678361SJulian.Pullen@Sun.COM 	/* List all the new domains */
6688361SJulian.Pullen@Sun.COM 	for (i = 0; (*value)[i].domain[0] != '\0'; i++)
6698361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_INFO, "change %s=%s", name,
6708361SJulian.Pullen@Sun.COM 		    (*value)[i].domain);
6718361SJulian.Pullen@Sun.COM 	return (1);
6728361SJulian.Pullen@Sun.COM }
6738361SJulian.Pullen@Sun.COM 
6748361SJulian.Pullen@Sun.COM 
6758361SJulian.Pullen@Sun.COM static void
6768361SJulian.Pullen@Sun.COM free_trusted_forests(idmap_trustedforest_t **value, int *num_values)
6778361SJulian.Pullen@Sun.COM {
6788361SJulian.Pullen@Sun.COM 	int i;
6798361SJulian.Pullen@Sun.COM 
6808361SJulian.Pullen@Sun.COM 	for (i = 0; i < *num_values; i++) {
6818361SJulian.Pullen@Sun.COM 		free((*value)[i].forest_name);
6828361SJulian.Pullen@Sun.COM 		free((*value)[i].global_catalog);
6838361SJulian.Pullen@Sun.COM 		free((*value)[i].domains_in_forest);
6848361SJulian.Pullen@Sun.COM 	}
6858361SJulian.Pullen@Sun.COM 	free(*value);
6868361SJulian.Pullen@Sun.COM 	*value = NULL;
6878361SJulian.Pullen@Sun.COM 	*num_values = 0;
6888361SJulian.Pullen@Sun.COM }
6898361SJulian.Pullen@Sun.COM 
6908361SJulian.Pullen@Sun.COM 
6918361SJulian.Pullen@Sun.COM static int
6928361SJulian.Pullen@Sun.COM compare_trusteddomainsinforest(ad_disc_domainsinforest_t *df1,
6938361SJulian.Pullen@Sun.COM 			ad_disc_domainsinforest_t *df2)
6948361SJulian.Pullen@Sun.COM {
695*8671SJulian.Pullen@Sun.COM 	int		i, j;
696*8671SJulian.Pullen@Sun.COM 	int		num_df1 = 0;
697*8671SJulian.Pullen@Sun.COM 	int		num_df2 = 0;
698*8671SJulian.Pullen@Sun.COM 	boolean_t	match;
699*8671SJulian.Pullen@Sun.COM 	int		err;
7008361SJulian.Pullen@Sun.COM 
7018361SJulian.Pullen@Sun.COM 	for (i = 0; df1[i].domain[0] != '\0'; i++)
7028361SJulian.Pullen@Sun.COM 		if (df1[i].trusted)
7038361SJulian.Pullen@Sun.COM 			num_df1++;
7048361SJulian.Pullen@Sun.COM 
7058361SJulian.Pullen@Sun.COM 	for (j = 0; df2[j].domain[0] != '\0'; j++)
7068361SJulian.Pullen@Sun.COM 		if (df2[j].trusted)
7078361SJulian.Pullen@Sun.COM 			num_df2++;
7088361SJulian.Pullen@Sun.COM 
7098361SJulian.Pullen@Sun.COM 	if (num_df1 != num_df2)
7108361SJulian.Pullen@Sun.COM 		return (1);
7118361SJulian.Pullen@Sun.COM 
7128361SJulian.Pullen@Sun.COM 	for (i = 0; df1[i].domain[0] != '\0'; i++) {
7138361SJulian.Pullen@Sun.COM 		if (df1[i].trusted) {
714*8671SJulian.Pullen@Sun.COM 			match = B_FALSE;
7158361SJulian.Pullen@Sun.COM 			for (j = 0; df2[j].domain[0] != '\0'; j++) {
7168361SJulian.Pullen@Sun.COM 				if (df2[j].trusted &&
7178361SJulian.Pullen@Sun.COM 				    u8_strcmp(df1[i].domain, df2[i].domain, 0,
7188361SJulian.Pullen@Sun.COM 				    U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err)
7198361SJulian.Pullen@Sun.COM 				    == 0 && err == 0 &&
7208361SJulian.Pullen@Sun.COM 				    strcmp(df1[i].sid, df2[i].sid) == 0) {
721*8671SJulian.Pullen@Sun.COM 					match = B_TRUE;
7228361SJulian.Pullen@Sun.COM 					break;
7238361SJulian.Pullen@Sun.COM 				}
7248361SJulian.Pullen@Sun.COM 			}
7258361SJulian.Pullen@Sun.COM 			if (!match)
7268361SJulian.Pullen@Sun.COM 				return (1);
7278361SJulian.Pullen@Sun.COM 		}
7288361SJulian.Pullen@Sun.COM 	}
7298361SJulian.Pullen@Sun.COM 	return (0);
7308361SJulian.Pullen@Sun.COM }
7318361SJulian.Pullen@Sun.COM 
7328361SJulian.Pullen@Sun.COM 
7338361SJulian.Pullen@Sun.COM 
7348361SJulian.Pullen@Sun.COM /*
7358361SJulian.Pullen@Sun.COM  * This function updates trusted forest structure.
7368361SJulian.Pullen@Sun.COM  * If nothing has changed it returns 0 else 1
7378361SJulian.Pullen@Sun.COM  */
7388361SJulian.Pullen@Sun.COM static int
7398361SJulian.Pullen@Sun.COM update_trusted_forest(idmap_trustedforest_t **value, int *num_value,
7408361SJulian.Pullen@Sun.COM 			idmap_trustedforest_t **new, int *num_new, char *name)
7418361SJulian.Pullen@Sun.COM {
7428361SJulian.Pullen@Sun.COM 	int i, j;
743*8671SJulian.Pullen@Sun.COM 	boolean_t match;
7448361SJulian.Pullen@Sun.COM 
7458361SJulian.Pullen@Sun.COM 	if (*value == *new)
7468361SJulian.Pullen@Sun.COM 		/* Nothing to do */
7478361SJulian.Pullen@Sun.COM 		return (0);
7488361SJulian.Pullen@Sun.COM 
7498361SJulian.Pullen@Sun.COM 	if (*value != NULL && *new != NULL) {
7508361SJulian.Pullen@Sun.COM 		if (*num_value != *num_new)
7518361SJulian.Pullen@Sun.COM 			goto not_equal;
7528361SJulian.Pullen@Sun.COM 		for (i = 0; i < *num_value; i++) {
753*8671SJulian.Pullen@Sun.COM 			match = B_FALSE;
7548361SJulian.Pullen@Sun.COM 			for (j = 0; j < *num_new; j++) {
7558361SJulian.Pullen@Sun.COM 				if (strcmp((*value)[i].forest_name,
7568361SJulian.Pullen@Sun.COM 				    (*new)[j].forest_name) == 0 &&
7578361SJulian.Pullen@Sun.COM 				    ad_disc_compare_ds(
7588361SJulian.Pullen@Sun.COM 				    (*value)[i].global_catalog,
7598361SJulian.Pullen@Sun.COM 				    (*new)[i].global_catalog) == 0 &&
7608361SJulian.Pullen@Sun.COM 				    compare_trusteddomainsinforest(
7618361SJulian.Pullen@Sun.COM 				    (*value)[i].domains_in_forest,
7628361SJulian.Pullen@Sun.COM 				    (*new)[i].domains_in_forest) == 0) {
763*8671SJulian.Pullen@Sun.COM 					match = B_TRUE;
7648361SJulian.Pullen@Sun.COM 					break;
7658361SJulian.Pullen@Sun.COM 				}
7668361SJulian.Pullen@Sun.COM 			}
7678361SJulian.Pullen@Sun.COM 			if (!match)
7688361SJulian.Pullen@Sun.COM 				goto not_equal;
7698361SJulian.Pullen@Sun.COM 		}
7708361SJulian.Pullen@Sun.COM 		free_trusted_forests(new, num_new);
7718361SJulian.Pullen@Sun.COM 		return (0);
7728361SJulian.Pullen@Sun.COM 	}
7738361SJulian.Pullen@Sun.COM not_equal:
7748361SJulian.Pullen@Sun.COM 	if (*value != NULL)
7758361SJulian.Pullen@Sun.COM 		free_trusted_forests(value, num_value);
7768361SJulian.Pullen@Sun.COM 	*value = *new;
7778361SJulian.Pullen@Sun.COM 	*num_value = *num_new;
7788361SJulian.Pullen@Sun.COM 	*new = NULL;
7798361SJulian.Pullen@Sun.COM 	*num_new = 0;
7808361SJulian.Pullen@Sun.COM 
7818361SJulian.Pullen@Sun.COM 	if (*value == NULL) {
7828361SJulian.Pullen@Sun.COM 		/* We're unsetting this DS property */
7838361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_INFO, "change %s=<none>", name);
7848361SJulian.Pullen@Sun.COM 		return (1);
7858361SJulian.Pullen@Sun.COM 	}
7868361SJulian.Pullen@Sun.COM 
7878361SJulian.Pullen@Sun.COM 	/* List all the trusted forests */
7888361SJulian.Pullen@Sun.COM 	for (i = 0; i < *num_value; i++) {
7898361SJulian.Pullen@Sun.COM 		for (j = 0; (*value)[i].domains_in_forest[j].domain[0] != '\0';
7908361SJulian.Pullen@Sun.COM 		    j++) {
7918361SJulian.Pullen@Sun.COM 			/* List trusted Domains in the forest. */
7928361SJulian.Pullen@Sun.COM 			if ((*value)[i].domains_in_forest[j].trusted)
7938361SJulian.Pullen@Sun.COM 				idmapdlog(LOG_INFO, "change %s=%s domain=%s",
7948361SJulian.Pullen@Sun.COM 				    name, (*value)[i].forest_name,
7958361SJulian.Pullen@Sun.COM 				    (*value)[i].domains_in_forest[j].domain);
7968361SJulian.Pullen@Sun.COM 		}
7978361SJulian.Pullen@Sun.COM 		/* List the hosts */
7988361SJulian.Pullen@Sun.COM 		for (j = 0; (*value)[i].global_catalog[j].host[0] != '\0'; j++)
7998361SJulian.Pullen@Sun.COM 			idmapdlog(LOG_INFO, "change %s=%s host=%s port=%d",
8008361SJulian.Pullen@Sun.COM 			    name, (*value)[i].forest_name,
8018361SJulian.Pullen@Sun.COM 			    (*value)[i].global_catalog[j].host,
8028361SJulian.Pullen@Sun.COM 			    (*value)[i].global_catalog[j].port);
8038361SJulian.Pullen@Sun.COM 	}
8048361SJulian.Pullen@Sun.COM 	return (1);
8058361SJulian.Pullen@Sun.COM }
8068361SJulian.Pullen@Sun.COM 
8075317Sjp151216 
8085968Snw141292 #define	MAX_CHECK_TIME		(20 * 60)
8094520Snw141292 
8105317Sjp151216 /*
8115968Snw141292  * Returns 1 if the PF_ROUTE socket event indicates that we should rescan the
8125968Snw141292  * interfaces.
8135317Sjp151216  *
8145968Snw141292  * Shamelessly based on smb_nics_changed() and other PF_ROUTE uses in ON.
8155968Snw141292  */
8165968Snw141292 static
8175968Snw141292 int
8185968Snw141292 pfroute_event_is_interesting(int rt_sock)
8195968Snw141292 {
8205968Snw141292 	int nbytes;
8215968Snw141292 	int64_t msg[2048 / 8];
8225968Snw141292 	struct rt_msghdr *rtm;
8235968Snw141292 	int is_interesting = FALSE;
8245968Snw141292 
8255968Snw141292 	for (;;) {
8265968Snw141292 		if ((nbytes = read(rt_sock, msg, sizeof (msg))) <= 0)
8275968Snw141292 			break;
8285968Snw141292 		rtm = (struct rt_msghdr *)msg;
8295968Snw141292 		if (rtm->rtm_version != RTM_VERSION)
8305968Snw141292 			continue;
8315968Snw141292 		if (nbytes < rtm->rtm_msglen)
8325968Snw141292 			continue;
8335968Snw141292 		switch (rtm->rtm_type) {
8345968Snw141292 		case RTM_NEWADDR:
8355968Snw141292 		case RTM_DELADDR:
8365968Snw141292 		case RTM_IFINFO:
8375968Snw141292 			is_interesting = TRUE;
8385968Snw141292 			break;
8395968Snw141292 		default:
8405968Snw141292 			break;
8415968Snw141292 		}
8425968Snw141292 	}
8435968Snw141292 	return (is_interesting);
8445968Snw141292 }
8455968Snw141292 
8465968Snw141292 /*
8475968Snw141292  * Returns 1 if SIGHUP has been received (see hup_handler() elsewhere) or if an
8485968Snw141292  * interface address was added or removed; otherwise it returns 0.
8495968Snw141292  *
8505968Snw141292  * Note that port_get() does not update its timeout argument when EINTR, unlike
8515968Snw141292  * nanosleep().  We probably don't care very much here, but if we did care then
8525968Snw141292  * we could always use a timer event and associate it with the same event port,
8535317Sjp151216  * then we could get accurate waiting regardless of EINTRs.
8545317Sjp151216  */
8555317Sjp151216 static
8565317Sjp151216 int
8576097Snw141292 wait_for_event(int poke_is_interesting, struct timespec *timeoutp)
8585317Sjp151216 {
8595317Sjp151216 	port_event_t pe;
8605317Sjp151216 
8615317Sjp151216 retry:
8625968Snw141292 	memset(&pe, 0, sizeof (pe));
8636097Snw141292 	if (port_get(idmapd_ev_port, &pe, timeoutp) != 0) {
8645317Sjp151216 		switch (errno) {
8655317Sjp151216 		case EINTR:
8665968Snw141292 			goto retry;
8675317Sjp151216 		case ETIME:
8685317Sjp151216 			/* Timeout */
8695968Snw141292 			return (FALSE);
8705317Sjp151216 		default:
8715968Snw141292 			/* EBADF, EBADFD, EFAULT, EINVAL (end of time?)? */
8725968Snw141292 			idmapdlog(LOG_ERR, "Event port failed: %s",
8735968Snw141292 			    strerror(errno));
8745968Snw141292 			exit(1);
8755968Snw141292 			/* NOTREACHED */
8765317Sjp151216 			break;
8774520Snw141292 		}
8784520Snw141292 	}
8794520Snw141292 
8805968Snw141292 	if (pe.portev_source == PORT_SOURCE_USER &&
8815968Snw141292 	    pe.portev_events == POKE_AUTO_DISCOVERY)
8825968Snw141292 		return (poke_is_interesting ? TRUE : FALSE);
8835317Sjp151216 
8845968Snw141292 	if (pe.portev_source == PORT_SOURCE_FD && pe.portev_object == rt_sock) {
8855968Snw141292 		/* PF_ROUTE socket read event, re-associate fd, handle event */
8865968Snw141292 		if (port_associate(idmapd_ev_port, PORT_SOURCE_FD, rt_sock,
8875968Snw141292 		    POLLIN, NULL) != 0) {
8885968Snw141292 			idmapdlog(LOG_ERR, "Failed to re-associate the "
8895968Snw141292 			    "routing socket with the event port: %s",
8905968Snw141292 			    strerror(errno));
8915968Snw141292 			exit(1);
8925968Snw141292 		}
8935968Snw141292 		/*
8945968Snw141292 		 * The network configuration may still be in flux.  No matter,
8955968Snw141292 		 * the resolver will re-transmit and timout if need be.
8965968Snw141292 		 */
8975968Snw141292 		return (pfroute_event_is_interesting(rt_sock));
8985968Snw141292 	}
8995968Snw141292 
9005968Snw141292 	if (pe.portev_source == PORT_SOURCE_USER &&
9015968Snw141292 	    pe.portev_events == RECONFIGURE) {
9025447Snw141292 		int rc;
9035447Snw141292 
9045447Snw141292 		/*
9055447Snw141292 		 * Blow away the ccache, we might have re-joined the
9065447Snw141292 		 * domain or joined a new one
9075447Snw141292 		 */
9085447Snw141292 		(void) unlink(IDMAP_CACHEDIR "/ccache");
9095447Snw141292 		/* HUP is the refresh method, so re-read SMF config */
910*8671SJulian.Pullen@Sun.COM 		idmapdlog(LOG_INFO, "SMF refresh");
9116097Snw141292 		rc = idmap_cfg_load(_idmapdstate.cfg, CFG_DISCOVER|CFG_LOG);
9126097Snw141292 		if (rc < -1) {
913*8671SJulian.Pullen@Sun.COM 			idmapdlog(LOG_ERR, "Fatal errors while reading "
9146097Snw141292 			    "SMF properties");
9156097Snw141292 			exit(1);
9166097Snw141292 		} else if (rc == -1) {
917*8671SJulian.Pullen@Sun.COM 			idmapdlog(LOG_WARNING, "Various errors "
9186097Snw141292 			    "re-loading configuration may cause AD lookups "
9196097Snw141292 			    "to fail");
9206097Snw141292 		}
9216097Snw141292 		return (FALSE);
9225317Sjp151216 	}
9235317Sjp151216 
9245968Snw141292 	return (FALSE);
9255317Sjp151216 }
9265317Sjp151216 
9275317Sjp151216 void *
9285317Sjp151216 idmap_cfg_update_thread(void *arg)
9295317Sjp151216 {
9305317Sjp151216 
9315968Snw141292 	int			ttl, changed, poke_is_interesting;
9325317Sjp151216 	idmap_cfg_handles_t	*handles = &_idmapdstate.cfg->handles;
9335317Sjp151216 	ad_disc_t		ad_ctx = handles->ad_ctx;
9346097Snw141292 	struct timespec		timeout, *timeoutp;
9355317Sjp151216 
9365968Snw141292 	poke_is_interesting = 1;
9375968Snw141292 	for (ttl = 0, changed = TRUE; ; ttl = ad_disc_get_TTL(ad_ctx)) {
9386097Snw141292 		/*
9396097Snw141292 		 * If ttl < 0 then we can wait for an event without timing out.
9406097Snw141292 		 * If idmapd needs to notice that the system has been joined to
9416097Snw141292 		 * a Windows domain then idmapd needs to be refreshed.
9426097Snw141292 		 */
9436097Snw141292 		timeoutp = (ttl < 0) ? NULL : &timeout;
9446097Snw141292 		if (ttl > MAX_CHECK_TIME)
9455317Sjp151216 			ttl = MAX_CHECK_TIME;
9465968Snw141292 		timeout.tv_sec = ttl;
9475968Snw141292 		timeout.tv_nsec = 0;
9486097Snw141292 		changed = wait_for_event(poke_is_interesting, timeoutp);
9495968Snw141292 
9505968Snw141292 		/*
9515968Snw141292 		 * If there are no interesting events, and this is not the first
9525968Snw141292 		 * time through the loop, and we haven't waited the most that
9535968Snw141292 		 * we're willing to wait, so do nothing but wait some more.
9545968Snw141292 		 */
9555968Snw141292 		if (changed == FALSE && ttl > 0 && ttl < MAX_CHECK_TIME)
9565968Snw141292 			continue;
9575968Snw141292 
9585968Snw141292 		(void) ad_disc_SubnetChanged(ad_ctx);
9595317Sjp151216 
9606097Snw141292 		if (idmap_cfg_load(_idmapdstate.cfg, CFG_DISCOVER) < -1) {
961*8671SJulian.Pullen@Sun.COM 			idmapdlog(LOG_ERR, "Fatal errors while reading "
9626097Snw141292 			    "SMF properties");
9636097Snw141292 			exit(1);
9645317Sjp151216 		}
9655317Sjp151216 
9666097Snw141292 		if (_idmapdstate.cfg->pgcfg.global_catalog == NULL ||
9676097Snw141292 		    _idmapdstate.cfg->pgcfg.global_catalog[0].host[0] == '\0')
9686097Snw141292 			poke_is_interesting = 1;
9696097Snw141292 		else
9706097Snw141292 			poke_is_interesting = 0;
9715317Sjp151216 	}
9725317Sjp151216 	/*NOTREACHED*/
9735317Sjp151216 	return (NULL);
9745317Sjp151216 }
9755317Sjp151216 
9765968Snw141292 int
9775968Snw141292 idmap_cfg_start_updates(void)
9785968Snw141292 {
9795968Snw141292 	if ((idmapd_ev_port = port_create()) < 0) {
9806017Snw141292 		idmapdlog(LOG_ERR, "Failed to create event port: %s",
9816017Snw141292 		    strerror(errno));
9825968Snw141292 		return (-1);
9835968Snw141292 	}
9845968Snw141292 
9855968Snw141292 	if ((rt_sock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
9866017Snw141292 		idmapdlog(LOG_ERR, "Failed to open routing socket: %s",
9876017Snw141292 		    strerror(errno));
9885968Snw141292 		(void) close(idmapd_ev_port);
9895968Snw141292 		return (-1);
9905968Snw141292 	}
9915317Sjp151216 
9925968Snw141292 	if (fcntl(rt_sock, F_SETFL, O_NDELAY|O_NONBLOCK) < 0) {
9936017Snw141292 		idmapdlog(LOG_ERR, "Failed to set routing socket flags: %s",
9946017Snw141292 		    strerror(errno));
9955968Snw141292 		(void) close(rt_sock);
9965968Snw141292 		(void) close(idmapd_ev_port);
9974520Snw141292 		return (-1);
9985968Snw141292 	}
9995968Snw141292 
10005968Snw141292 	if (port_associate(idmapd_ev_port, PORT_SOURCE_FD,
10015968Snw141292 	    rt_sock, POLLIN, NULL) != 0) {
10026017Snw141292 		idmapdlog(LOG_ERR, "Failed to associate the routing "
10036017Snw141292 		    "socket with the event port: %s", strerror(errno));
10045968Snw141292 		(void) close(rt_sock);
10055968Snw141292 		(void) close(idmapd_ev_port);
10065968Snw141292 		return (-1);
10075968Snw141292 	}
10085968Snw141292 
10095968Snw141292 	if ((errno = pthread_create(&update_thread_handle, NULL,
10105968Snw141292 	    idmap_cfg_update_thread, NULL)) != 0) {
10116017Snw141292 		idmapdlog(LOG_ERR, "Failed to start update thread: %s",
10126017Snw141292 		    strerror(errno));
10135968Snw141292 		(void) port_dissociate(idmapd_ev_port, PORT_SOURCE_FD, rt_sock);
10145968Snw141292 		(void) close(rt_sock);
10155968Snw141292 		(void) close(idmapd_ev_port);
10165968Snw141292 		return (-1);
10175968Snw141292 	}
10185968Snw141292 
10195968Snw141292 	return (0);
10205317Sjp151216 }
10215317Sjp151216 
10226097Snw141292 /*
10236616Sdm199847  * Reject attribute names with invalid characters.
10246616Sdm199847  */
10256616Sdm199847 static
10266616Sdm199847 int
10276616Sdm199847 valid_ldap_attr(const char *attr) {
10286616Sdm199847 	for (; *attr; attr++) {
10296616Sdm199847 		if (!isalnum(*attr) && *attr != '-' &&
10306616Sdm199847 		    *attr != '_' && *attr != '.' && *attr != ';')
10316616Sdm199847 			return (0);
10326616Sdm199847 	}
10336616Sdm199847 	return (1);
10346616Sdm199847 }
10356616Sdm199847 
10366616Sdm199847 /*
10376097Snw141292  * This is the half of idmap_cfg_load() that loads property values from
10386097Snw141292  * SMF (using the config/ property group of the idmap FMRI).
10396097Snw141292  *
10406097Snw141292  * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
10416616Sdm199847  *               -3 -> hard smf config failures
10426097Snw141292  * reading from SMF.
10436097Snw141292  */
10446097Snw141292 static
10455317Sjp151216 int
10466097Snw141292 idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
10476097Snw141292 	int *errors)
10485317Sjp151216 {
10495447Snw141292 	int rc;
10505731Sbaban 	uint8_t bool_val;
10515317Sjp151216 	char *str = NULL;
1052*8671SJulian.Pullen@Sun.COM 	boolean_t new_debug_mode;
10535317Sjp151216 
10545317Sjp151216 	if (scf_pg_update(handles->config_pg) < 0) {
10556017Snw141292 		idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
10566017Snw141292 		    scf_strerror(scf_error()));
10576097Snw141292 		return (-2);
10585317Sjp151216 	}
10595317Sjp151216 
10605317Sjp151216 	if (scf_pg_update(handles->general_pg) < 0) {
10616017Snw141292 		idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
10626017Snw141292 		    scf_strerror(scf_error()));
10636097Snw141292 		return (-2);
10645317Sjp151216 	}
10655317Sjp151216 
10666616Sdm199847 
10676616Sdm199847 	rc = prop_exists(handles, "debug", &new_debug_mode);
10686616Sdm199847 	if (rc != 0)
10696616Sdm199847 		errors++;
10706616Sdm199847 
10716017Snw141292 	if (_idmapdstate.debug_mode != new_debug_mode) {
1072*8671SJulian.Pullen@Sun.COM 		if (!_idmapdstate.debug_mode) {
10736017Snw141292 			_idmapdstate.debug_mode = new_debug_mode;
10747031Snw141292 			idmap_log_stderr(LOG_DEBUG);
10756017Snw141292 			idmapdlog(LOG_DEBUG, "debug mode enabled");
10766017Snw141292 		} else {
10776017Snw141292 			idmapdlog(LOG_DEBUG, "debug mode disabled");
10787031Snw141292 			idmap_log_stderr(-1);
10796017Snw141292 			_idmapdstate.debug_mode = new_debug_mode;
10806017Snw141292 		}
10816017Snw141292 	}
10826017Snw141292 
10837031Snw141292 	rc = get_val_int(handles, "unresolvable_sid_mapping",
10847031Snw141292 	    &pgcfg->eph_map_unres_sids, SCF_TYPE_BOOLEAN);
10857031Snw141292 	if (rc != 0)
10867031Snw141292 		errors++;
10877031Snw141292 
10885317Sjp151216 	rc = get_val_int(handles, "list_size_limit",
10895317Sjp151216 	    &pgcfg->list_size_limit, SCF_TYPE_COUNT);
10907031Snw141292 	if (rc != 0)
10915447Snw141292 		errors++;
10925317Sjp151216 
10935317Sjp151216 	rc = get_val_astring(handles, "domain_name",
10945317Sjp151216 	    &pgcfg->domain_name);
10955447Snw141292 	if (rc != 0)
10965447Snw141292 		errors++;
10978361SJulian.Pullen@Sun.COM 	else {
10986097Snw141292 		(void) ad_disc_set_DomainName(handles->ad_ctx,
10996097Snw141292 		    pgcfg->domain_name);
1100*8671SJulian.Pullen@Sun.COM 		pgcfg->domain_name_auto_disc = B_FALSE;
11018361SJulian.Pullen@Sun.COM 	}
11025317Sjp151216 
11035317Sjp151216 	rc = get_val_astring(handles, "default_domain",
11045317Sjp151216 	    &pgcfg->default_domain);
11055317Sjp151216 	if (rc != 0) {
11065447Snw141292 		/*
11075447Snw141292 		 * SCF failures fetching config/default_domain we treat
11085447Snw141292 		 * as fatal as they may leave ID mapping rules that
11095447Snw141292 		 * match unqualified winnames flapping in the wind.
11105447Snw141292 		 */
11116097Snw141292 		return (-2);
11125317Sjp151216 	}
11135317Sjp151216 
11145317Sjp151216 	rc = get_val_astring(handles, "mapping_domain", &str);
11155447Snw141292 	if (rc != 0)
11165447Snw141292 		errors++;
11175317Sjp151216 
11185317Sjp151216 	/*
11195317Sjp151216 	 * We treat default_domain as having been specified in SMF IFF
11205317Sjp151216 	 * either (the config/default_domain property was set) or (the
11215317Sjp151216 	 * old, obsolete, never documented config/mapping_domain
11225317Sjp151216 	 * property was set and the new config/domain_name property was
11235317Sjp151216 	 * not set).
11245317Sjp151216 	 */
1125*8671SJulian.Pullen@Sun.COM 	pgcfg->dflt_dom_set_in_smf = B_TRUE;
11265317Sjp151216 	if (pgcfg->default_domain == NULL) {
11275317Sjp151216 
1128*8671SJulian.Pullen@Sun.COM 		pgcfg->dflt_dom_set_in_smf = B_FALSE;
11295317Sjp151216 
11305317Sjp151216 		if (pgcfg->domain_name != NULL) {
11315317Sjp151216 			pgcfg->default_domain = strdup(pgcfg->domain_name);
11325317Sjp151216 			if (str != NULL) {
11335317Sjp151216 				idmapdlog(LOG_WARNING,
11346017Snw141292 				    "Ignoring obsolete, undocumented "
11356017Snw141292 				    "config/mapping_domain property");
11365317Sjp151216 			}
11375317Sjp151216 		} else if (str != NULL) {
11385317Sjp151216 			pgcfg->default_domain = strdup(str);
1139*8671SJulian.Pullen@Sun.COM 			pgcfg->dflt_dom_set_in_smf = B_TRUE;
11405317Sjp151216 			idmapdlog(LOG_WARNING,
11416017Snw141292 			    "The config/mapping_domain property is "
11425317Sjp151216 			    "obsolete; support for it will be removed, "
11436017Snw141292 			    "please use config/default_domain instead");
11444695Sbaban 		}
11454695Sbaban 	}
11464520Snw141292 
11475317Sjp151216 	if (str != NULL)
11485317Sjp151216 		free(str);
11495317Sjp151216 
11505317Sjp151216 	rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid);
11515447Snw141292 	if (rc != 0)
11525447Snw141292 		errors++;
11535317Sjp151216 	if (pgcfg->machine_sid == NULL) {
11545317Sjp151216 		/* If machine_sid not configured, generate one */
11556097Snw141292 		if (generate_machine_sid(&pgcfg->machine_sid) < 0)
11566097Snw141292 			return (-2);
11575317Sjp151216 		rc = set_val_astring(handles, "machine_sid",
11585317Sjp151216 		    pgcfg->machine_sid);
11595447Snw141292 		if (rc != 0)
11605447Snw141292 			errors++;
11615317Sjp151216 	}
11625317Sjp151216 
11635317Sjp151216 	str = NULL;
11645317Sjp151216 	rc = get_val_ds(handles, "domain_controller", 389,
11655317Sjp151216 	    &pgcfg->domain_controller);
11665447Snw141292 	if (rc != 0)
11675447Snw141292 		errors++;
11688361SJulian.Pullen@Sun.COM 	else {
11696097Snw141292 		(void) ad_disc_set_DomainController(handles->ad_ctx,
11705447Snw141292 		    pgcfg->domain_controller);
1171*8671SJulian.Pullen@Sun.COM 		pgcfg->domain_controller_auto_disc = B_FALSE;
11728361SJulian.Pullen@Sun.COM 	}
11735317Sjp151216 
11745317Sjp151216 	rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name);
11755447Snw141292 	if (rc != 0)
11765447Snw141292 		errors++;
11778361SJulian.Pullen@Sun.COM 	else {
11786097Snw141292 		(void) ad_disc_set_ForestName(handles->ad_ctx,
11796097Snw141292 		    pgcfg->forest_name);
1180*8671SJulian.Pullen@Sun.COM 		pgcfg->forest_name_auto_disc = B_FALSE;
11818361SJulian.Pullen@Sun.COM 	}
11825317Sjp151216 
11835317Sjp151216 	rc = get_val_astring(handles, "site_name", &pgcfg->site_name);
11845447Snw141292 	if (rc != 0)
11855447Snw141292 		errors++;
11865447Snw141292 	else
11876097Snw141292 		(void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name);
11885317Sjp151216 
11895317Sjp151216 	str = NULL;
11905317Sjp151216 	rc = get_val_ds(handles, "global_catalog", 3268,
11915317Sjp151216 	    &pgcfg->global_catalog);
11925447Snw141292 	if (rc != 0)
11935447Snw141292 		errors++;
11948361SJulian.Pullen@Sun.COM 	else {
11956097Snw141292 		(void) ad_disc_set_GlobalCatalog(handles->ad_ctx,
11966097Snw141292 		    pgcfg->global_catalog);
1197*8671SJulian.Pullen@Sun.COM 		pgcfg->global_catalog_auto_disc = B_FALSE;
11988361SJulian.Pullen@Sun.COM 	}
11995447Snw141292 
12005731Sbaban 	/*
12015731Sbaban 	 * Read directory-based name mappings related SMF properties
12025731Sbaban 	 */
12035731Sbaban 	rc = get_val_int(handles, "ds_name_mapping_enabled",
12045731Sbaban 	    &bool_val, SCF_TYPE_BOOLEAN);
12056097Snw141292 	if (rc != 0)
12066097Snw141292 		return (-2);
12076097Snw141292 
12086097Snw141292 	if (!bool_val)
12096097Snw141292 		return (rc);
12105731Sbaban 
1211*8671SJulian.Pullen@Sun.COM 	pgcfg->ds_name_mapping_enabled = B_TRUE;
12126097Snw141292 	rc = get_val_astring(handles, "ad_unixuser_attr",
12136097Snw141292 	    &pgcfg->ad_unixuser_attr);
12146097Snw141292 	if (rc != 0)
12156097Snw141292 		return (-2);
12166616Sdm199847 	if (pgcfg->ad_unixuser_attr != NULL &&
12176616Sdm199847 	    !valid_ldap_attr(pgcfg->ad_unixuser_attr)) {
12186616Sdm199847 		idmapdlog(LOG_ERR, "config/ad_unixuser_attr=%s is not a "
12196616Sdm199847 		    "valid LDAP attribute name", pgcfg->ad_unixuser_attr);
12206616Sdm199847 		return (-3);
12216616Sdm199847 	}
12226097Snw141292 
12236097Snw141292 	rc = get_val_astring(handles, "ad_unixgroup_attr",
12246097Snw141292 	    &pgcfg->ad_unixgroup_attr);
12256097Snw141292 	if (rc != 0)
12266097Snw141292 		return (-2);
12276616Sdm199847 	if (pgcfg->ad_unixgroup_attr != NULL &&
12286616Sdm199847 	    !valid_ldap_attr(pgcfg->ad_unixgroup_attr)) {
12296616Sdm199847 		idmapdlog(LOG_ERR, "config/ad_unixgroup_attr=%s is not a "
12306616Sdm199847 		    "valid LDAP attribute name", pgcfg->ad_unixgroup_attr);
12316616Sdm199847 		return (-3);
12326616Sdm199847 	}
12335731Sbaban 
12346097Snw141292 	rc = get_val_astring(handles, "nldap_winname_attr",
12356097Snw141292 	    &pgcfg->nldap_winname_attr);
12366097Snw141292 	if (rc != 0)
12376097Snw141292 		return (-2);
12386616Sdm199847 	if (pgcfg->nldap_winname_attr != NULL &&
12396616Sdm199847 	    !valid_ldap_attr(pgcfg->nldap_winname_attr)) {
12406616Sdm199847 		idmapdlog(LOG_ERR, "config/nldap_winname_attr=%s is not a "
12416616Sdm199847 		    "valid LDAP attribute name", pgcfg->nldap_winname_attr);
12426097Snw141292 		return (-3);
12436097Snw141292 	}
12446097Snw141292 	if (pgcfg->ad_unixuser_attr == NULL &&
12456616Sdm199847 	    pgcfg->ad_unixgroup_attr == NULL &&
12466616Sdm199847 	    pgcfg->nldap_winname_attr == NULL) {
12476097Snw141292 		idmapdlog(LOG_ERR,
12486097Snw141292 		    "If config/ds_name_mapping_enabled property is set to "
12496097Snw141292 		    "true then atleast one of the following name mapping "
12506097Snw141292 		    "attributes must be specified. (config/ad_unixuser_attr OR "
12516616Sdm199847 		    "config/ad_unixgroup_attr OR config/nldap_winname_attr)");
12526097Snw141292 		return (-3);
12535731Sbaban 	}
12545731Sbaban 
12556097Snw141292 	return (rc);
12565447Snw141292 
12576097Snw141292 }
12585317Sjp151216 
12598361SJulian.Pullen@Sun.COM 
12606097Snw141292 /*
12616097Snw141292  * This is the half of idmap_cfg_load() that auto-discovers values of
12626097Snw141292  * discoverable properties that weren't already set via SMF properties.
12636097Snw141292  *
12646097Snw141292  * idmap_cfg_discover() is called *after* idmap_cfg_load_smf(), so it
12656097Snw141292  * needs to be careful not to overwrite any properties set in SMF.
12666097Snw141292  */
12676097Snw141292 static
12686097Snw141292 void
12696097Snw141292 idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
12706097Snw141292 {
12716097Snw141292 	ad_disc_t ad_ctx = handles->ad_ctx;
12728361SJulian.Pullen@Sun.COM 	ad_disc_t trusted_ctx;
12738361SJulian.Pullen@Sun.COM 	int i, j, k, l;
12748361SJulian.Pullen@Sun.COM 	char *forestname;
12758361SJulian.Pullen@Sun.COM 	int num_trusteddomains;
1276*8671SJulian.Pullen@Sun.COM 	boolean_t new_forest;
12778361SJulian.Pullen@Sun.COM 	int err;
12788361SJulian.Pullen@Sun.COM 	char *trusteddomain;
12798361SJulian.Pullen@Sun.COM 	idmap_ad_disc_ds_t *globalcatalog;
12808361SJulian.Pullen@Sun.COM 	idmap_trustedforest_t *trustedforests;
12818361SJulian.Pullen@Sun.COM 	ad_disc_domainsinforest_t *domainsinforest;
12826097Snw141292 
12836097Snw141292 	ad_disc_refresh(ad_ctx);
12846097Snw141292 
12856097Snw141292 	if (pgcfg->default_domain == NULL)
12868361SJulian.Pullen@Sun.COM 		pgcfg->default_domain = ad_disc_get_DomainName(ad_ctx,
12878361SJulian.Pullen@Sun.COM 		    NULL);
12885317Sjp151216 
12896097Snw141292 	if (pgcfg->domain_name == NULL)
12908361SJulian.Pullen@Sun.COM 		pgcfg->domain_name = ad_disc_get_DomainName(ad_ctx,
12918361SJulian.Pullen@Sun.COM 		    &pgcfg->domain_name_auto_disc);
12925317Sjp151216 
12936097Snw141292 	if (pgcfg->domain_controller == NULL)
12945317Sjp151216 		pgcfg->domain_controller =
12958361SJulian.Pullen@Sun.COM 		    ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE,
12968361SJulian.Pullen@Sun.COM 		    &pgcfg->domain_controller_auto_disc);
12976097Snw141292 
12986097Snw141292 	if (pgcfg->forest_name == NULL)
12998361SJulian.Pullen@Sun.COM 		pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx,
13008361SJulian.Pullen@Sun.COM 		    &pgcfg->forest_name_auto_disc);
13016097Snw141292 
13026097Snw141292 	if (pgcfg->site_name == NULL)
13038361SJulian.Pullen@Sun.COM 		pgcfg->site_name = ad_disc_get_SiteName(ad_ctx,
13048361SJulian.Pullen@Sun.COM 		    &pgcfg->site_name_auto_disc);
13056097Snw141292 
13066097Snw141292 	if (pgcfg->global_catalog == NULL)
13076097Snw141292 		pgcfg->global_catalog =
13088361SJulian.Pullen@Sun.COM 		    ad_disc_get_GlobalCatalog(ad_ctx, AD_DISC_PREFER_SITE,
13098361SJulian.Pullen@Sun.COM 		    &pgcfg->global_catalog_auto_disc);
13108361SJulian.Pullen@Sun.COM 
13118361SJulian.Pullen@Sun.COM 	pgcfg->domains_in_forest =
13128361SJulian.Pullen@Sun.COM 	    ad_disc_get_DomainsInForest(ad_ctx, NULL);
13138361SJulian.Pullen@Sun.COM 
13148361SJulian.Pullen@Sun.COM 	pgcfg->trusted_domains =
13158361SJulian.Pullen@Sun.COM 	    ad_disc_get_TrustedDomains(ad_ctx, NULL);
13168361SJulian.Pullen@Sun.COM 
13178361SJulian.Pullen@Sun.COM 	if (pgcfg->forest_name != NULL && pgcfg->trusted_domains != NULL &&
13188361SJulian.Pullen@Sun.COM 	    pgcfg->trusted_domains[0].domain[0] != '\0') {
13198361SJulian.Pullen@Sun.COM 		/*
13208361SJulian.Pullen@Sun.COM 		 * We have trusted domains.  We need to go through every
13218361SJulian.Pullen@Sun.COM 		 * one and find its forest. If it is a new forest we then need
13228361SJulian.Pullen@Sun.COM 		 * to find its Global Catalog and the domains in the forest
13238361SJulian.Pullen@Sun.COM 		 */
13248361SJulian.Pullen@Sun.COM 		for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++)
13258361SJulian.Pullen@Sun.COM 			continue;
13268361SJulian.Pullen@Sun.COM 		num_trusteddomains = i;
13278361SJulian.Pullen@Sun.COM 
13288361SJulian.Pullen@Sun.COM 		trustedforests = calloc(num_trusteddomains,
13298361SJulian.Pullen@Sun.COM 		    sizeof (idmap_trustedforest_t));
13308361SJulian.Pullen@Sun.COM 		j = 0;
13318361SJulian.Pullen@Sun.COM 		for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) {
13328361SJulian.Pullen@Sun.COM 			trusteddomain = pgcfg->trusted_domains[i].domain;
13338361SJulian.Pullen@Sun.COM 			trusted_ctx = ad_disc_init();
13348361SJulian.Pullen@Sun.COM 			ad_disc_set_DomainName(trusted_ctx,
13358361SJulian.Pullen@Sun.COM 			    trusteddomain);
13368361SJulian.Pullen@Sun.COM 			forestname =
13378361SJulian.Pullen@Sun.COM 			    ad_disc_get_ForestName(trusted_ctx, NULL);
13388361SJulian.Pullen@Sun.COM 			if (forestname == NULL) {
13398361SJulian.Pullen@Sun.COM 				idmapdlog(LOG_DEBUG, "unable to discover "
13408361SJulian.Pullen@Sun.COM 				    "Forest Name for the trusted domain %s",
13418361SJulian.Pullen@Sun.COM 				    trusteddomain);
13428361SJulian.Pullen@Sun.COM 				ad_disc_fini(trusted_ctx);
13438361SJulian.Pullen@Sun.COM 				continue;
13448361SJulian.Pullen@Sun.COM 			}
13458361SJulian.Pullen@Sun.COM 
13468361SJulian.Pullen@Sun.COM 			if (strcasecmp(forestname, pgcfg->forest_name) == 0) {
13478361SJulian.Pullen@Sun.COM 				/*
13488361SJulian.Pullen@Sun.COM 				 * Ignore the domain as it is part of
13498361SJulian.Pullen@Sun.COM 				 * the primary forest
13508361SJulian.Pullen@Sun.COM 				 */
13518361SJulian.Pullen@Sun.COM 				free(forestname);
13528361SJulian.Pullen@Sun.COM 				ad_disc_fini(trusted_ctx);
13538361SJulian.Pullen@Sun.COM 				continue;
13548361SJulian.Pullen@Sun.COM 			}
13558361SJulian.Pullen@Sun.COM 
13568361SJulian.Pullen@Sun.COM 			/* Is this a new forest? */
1357*8671SJulian.Pullen@Sun.COM 			new_forest = B_TRUE;
13588361SJulian.Pullen@Sun.COM 			for (k = 0; k < j; k++) {
13598361SJulian.Pullen@Sun.COM 				if (strcasecmp(forestname,
13608361SJulian.Pullen@Sun.COM 				    trustedforests[k].forest_name) == 0) {
1361*8671SJulian.Pullen@Sun.COM 					new_forest = B_FALSE;
13628361SJulian.Pullen@Sun.COM 					domainsinforest =
13638361SJulian.Pullen@Sun.COM 					    trustedforests[k].domains_in_forest;
13648361SJulian.Pullen@Sun.COM 					break;
13658361SJulian.Pullen@Sun.COM 				}
13668361SJulian.Pullen@Sun.COM 			}
13678361SJulian.Pullen@Sun.COM 			if (!new_forest) {
13688361SJulian.Pullen@Sun.COM 				/* Mark the domain as trusted */
13698361SJulian.Pullen@Sun.COM 				for (l = 0;
13708361SJulian.Pullen@Sun.COM 				    domainsinforest[l].domain[0] != '\0'; l++) {
13718361SJulian.Pullen@Sun.COM 					if (u8_strcmp(trusteddomain,
13728361SJulian.Pullen@Sun.COM 					    domainsinforest[l].domain, 0,
13738361SJulian.Pullen@Sun.COM 					    U8_STRCMP_CI_LOWER,
13748361SJulian.Pullen@Sun.COM 					    U8_UNICODE_LATEST, &err) == 0 &&
13758361SJulian.Pullen@Sun.COM 					    err == 0) {
13768361SJulian.Pullen@Sun.COM 						domainsinforest[l].trusted =
13778361SJulian.Pullen@Sun.COM 						    TRUE;
13788361SJulian.Pullen@Sun.COM 						break;
13798361SJulian.Pullen@Sun.COM 					}
13808361SJulian.Pullen@Sun.COM 				}
13818361SJulian.Pullen@Sun.COM 				free(forestname);
13828361SJulian.Pullen@Sun.COM 				ad_disc_fini(trusted_ctx);
13838361SJulian.Pullen@Sun.COM 				continue;
13848361SJulian.Pullen@Sun.COM 			}
13858361SJulian.Pullen@Sun.COM 
13868361SJulian.Pullen@Sun.COM 			/*
13878361SJulian.Pullen@Sun.COM 			 * Get the Global Catalog and the domains in
13888361SJulian.Pullen@Sun.COM 			 * this new forest.
13898361SJulian.Pullen@Sun.COM 			 */
13908361SJulian.Pullen@Sun.COM 			globalcatalog =
13918361SJulian.Pullen@Sun.COM 			    ad_disc_get_GlobalCatalog(trusted_ctx,
13928361SJulian.Pullen@Sun.COM 			    AD_DISC_PREFER_SITE, NULL);
13938361SJulian.Pullen@Sun.COM 			if (globalcatalog == NULL) {
13948361SJulian.Pullen@Sun.COM 				idmapdlog(LOG_DEBUG,
13958361SJulian.Pullen@Sun.COM 				    "unable to discover Global "
13968361SJulian.Pullen@Sun.COM 				    "Catalog for the trusted domain %s",
13978361SJulian.Pullen@Sun.COM 				    trusteddomain);
13988361SJulian.Pullen@Sun.COM 				free(forestname);
13998361SJulian.Pullen@Sun.COM 				ad_disc_fini(trusted_ctx);
14008361SJulian.Pullen@Sun.COM 				continue;
14018361SJulian.Pullen@Sun.COM 			}
14028361SJulian.Pullen@Sun.COM 			domainsinforest =
14038361SJulian.Pullen@Sun.COM 			    ad_disc_get_DomainsInForest(trusted_ctx,
14048361SJulian.Pullen@Sun.COM 			    NULL);
14058361SJulian.Pullen@Sun.COM 			if (domainsinforest == NULL) {
14068361SJulian.Pullen@Sun.COM 				idmapdlog(LOG_DEBUG,
14078361SJulian.Pullen@Sun.COM 				    "unable to discover Domains in the Forest "
14088361SJulian.Pullen@Sun.COM 				    "for the trusted domain %s",
14098361SJulian.Pullen@Sun.COM 				    trusteddomain);
14108361SJulian.Pullen@Sun.COM 				free(globalcatalog);
14118361SJulian.Pullen@Sun.COM 				free(forestname);
14128361SJulian.Pullen@Sun.COM 				ad_disc_fini(trusted_ctx);
14138361SJulian.Pullen@Sun.COM 				continue;
14148361SJulian.Pullen@Sun.COM 			}
14158361SJulian.Pullen@Sun.COM 
14168361SJulian.Pullen@Sun.COM 			trustedforests[j].forest_name = forestname;
14178361SJulian.Pullen@Sun.COM 			trustedforests[j].global_catalog = globalcatalog;
14188361SJulian.Pullen@Sun.COM 			trustedforests[j].domains_in_forest = domainsinforest;
14198361SJulian.Pullen@Sun.COM 			j++;
14208361SJulian.Pullen@Sun.COM 			/* Mark the domain as trusted */
14218361SJulian.Pullen@Sun.COM 			for (l = 0; domainsinforest[l].domain[0] != '\0';
14228361SJulian.Pullen@Sun.COM 			    l++) {
14238361SJulian.Pullen@Sun.COM 				if (u8_strcmp(trusteddomain,
14248361SJulian.Pullen@Sun.COM 				    domainsinforest[l].domain, 0,
14258361SJulian.Pullen@Sun.COM 				    U8_STRCMP_CI_LOWER,
14268361SJulian.Pullen@Sun.COM 				    U8_UNICODE_LATEST, &err) == 0 &&
14278361SJulian.Pullen@Sun.COM 				    err == 0) {
14288361SJulian.Pullen@Sun.COM 					domainsinforest[l].trusted = TRUE;
14298361SJulian.Pullen@Sun.COM 					break;
14308361SJulian.Pullen@Sun.COM 				}
14318361SJulian.Pullen@Sun.COM 			}
14328361SJulian.Pullen@Sun.COM 			ad_disc_fini(trusted_ctx);
14338361SJulian.Pullen@Sun.COM 		}
14348361SJulian.Pullen@Sun.COM 		if (j > 0) {
14358361SJulian.Pullen@Sun.COM 			pgcfg->num_trusted_forests = j;
14368361SJulian.Pullen@Sun.COM 			pgcfg->trusted_forests = trustedforests;
14378361SJulian.Pullen@Sun.COM 		}
14388361SJulian.Pullen@Sun.COM 	}
14396097Snw141292 
14406097Snw141292 	if (pgcfg->domain_name == NULL)
14416097Snw141292 		idmapdlog(LOG_DEBUG, "unable to discover Domain Name");
14426097Snw141292 	if (pgcfg->domain_controller == NULL)
14436097Snw141292 		idmapdlog(LOG_DEBUG, "unable to discover Domain Controller");
14446097Snw141292 	if (pgcfg->forest_name == NULL)
14456097Snw141292 		idmapdlog(LOG_DEBUG, "unable to discover Forest Name");
14466097Snw141292 	if (pgcfg->site_name == NULL)
14476097Snw141292 		idmapdlog(LOG_DEBUG, "unable to discover Site Name");
14486097Snw141292 	if (pgcfg->global_catalog == NULL)
14496097Snw141292 		idmapdlog(LOG_DEBUG, "unable to discover Global Catalog");
14508361SJulian.Pullen@Sun.COM 	if (pgcfg->domains_in_forest == NULL)
14518361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_DEBUG,
14528361SJulian.Pullen@Sun.COM 		    "unable to discover Domains in the Forest");
14538361SJulian.Pullen@Sun.COM 	if (pgcfg->trusted_domains == NULL)
14548361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_DEBUG, "unable to discover Trusted Domains");
14556097Snw141292 }
14565317Sjp151216 
14578361SJulian.Pullen@Sun.COM 
14586097Snw141292 /*
14596097Snw141292  * idmap_cfg_load() is called at startup, and periodically via the
14606097Snw141292  * update thread when the auto-discovery TTLs expire, as well as part of
14616097Snw141292  * the refresh method, to update the current configuration.  It always
14626097Snw141292  * reads from SMF, but you still have to refresh the service after
14636097Snw141292  * changing the config pg in order for the changes to take effect.
14646097Snw141292  *
14656097Snw141292  * There are two flags:
14666097Snw141292  *
14676097Snw141292  *  - CFG_DISCOVER
14686097Snw141292  *  - CFG_LOG
14696097Snw141292  *
14706097Snw141292  * If CFG_DISCOVER is set then idmap_cfg_load() calls
14716097Snw141292  * idmap_cfg_discover() to discover, via DNS and LDAP lookups, property
14726097Snw141292  * values that weren't set in SMF.
14736097Snw141292  *
14746097Snw141292  * If CFG_LOG is set then idmap_cfg_load() will log (to LOG_NOTICE)
14756097Snw141292  * whether the configuration changed.  This should be used only from the
14766097Snw141292  * refresh method.
14776097Snw141292  *
14786097Snw141292  * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
14796097Snw141292  * reading from SMF.
14806097Snw141292  */
14816097Snw141292 int
14826097Snw141292 idmap_cfg_load(idmap_cfg_t *cfg, int flags)
14836097Snw141292 {
14846097Snw141292 	int rc = 0;
14856097Snw141292 	int errors = 0;
14866097Snw141292 	int changed = 0;
14878361SJulian.Pullen@Sun.COM 	int ad_reload_required = 0;
14886097Snw141292 	idmap_pg_config_t new_pgcfg, *live_pgcfg;
14896097Snw141292 
14906097Snw141292 	live_pgcfg = &cfg->pgcfg;
14916097Snw141292 	(void) memset(&new_pgcfg, 0, sizeof (new_pgcfg));
14926097Snw141292 
14936097Snw141292 	pthread_mutex_lock(&cfg->handles.mutex);
14946097Snw141292 
14956097Snw141292 	if ((rc = idmap_cfg_load_smf(&cfg->handles, &new_pgcfg, &errors)) < -1)
14966097Snw141292 		goto err;
14976097Snw141292 
14986097Snw141292 	if (flags & CFG_DISCOVER)
14996097Snw141292 		idmap_cfg_discover(&cfg->handles, &new_pgcfg);
15006097Snw141292 
15016097Snw141292 	WRLOCK_CONFIG();
15026097Snw141292 	if (live_pgcfg->list_size_limit != new_pgcfg.list_size_limit) {
15036097Snw141292 		idmapdlog(LOG_INFO, "change list_size=%d",
15046097Snw141292 		    new_pgcfg.list_size_limit);
15056097Snw141292 		live_pgcfg->list_size_limit = new_pgcfg.list_size_limit;
15065317Sjp151216 	}
15075317Sjp151216 
15086097Snw141292 	/* Non-discoverable props updated here */
15097031Snw141292 	changed += update_string(&live_pgcfg->machine_sid,
15106097Snw141292 	    &new_pgcfg.machine_sid, "machine_sid");
15116097Snw141292 
15127031Snw141292 	changed += update_bool(&live_pgcfg->eph_map_unres_sids,
15137031Snw141292 	    &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping");
15147031Snw141292 
15156097Snw141292 	changed += live_pgcfg->ds_name_mapping_enabled !=
15166097Snw141292 	    new_pgcfg.ds_name_mapping_enabled;
15176097Snw141292 	live_pgcfg->ds_name_mapping_enabled =
15186097Snw141292 	    new_pgcfg.ds_name_mapping_enabled;
15196097Snw141292 
15207031Snw141292 	changed += update_string(&live_pgcfg->ad_unixuser_attr,
15216097Snw141292 	    &new_pgcfg.ad_unixuser_attr, "ad_unixuser_attr");
15226097Snw141292 
15237031Snw141292 	changed += update_string(&live_pgcfg->ad_unixgroup_attr,
15246097Snw141292 	    &new_pgcfg.ad_unixgroup_attr, "ad_unixgroup_attr");
15256097Snw141292 
15267031Snw141292 	changed += update_string(&live_pgcfg->nldap_winname_attr,
15276097Snw141292 	    &new_pgcfg.nldap_winname_attr, "nldap_winname_attr");
15286097Snw141292 
15296097Snw141292 	/* Props that can be discovered and set in SMF updated here */
1530*8671SJulian.Pullen@Sun.COM 	if (!live_pgcfg->dflt_dom_set_in_smf)
15317031Snw141292 		changed += update_string(&live_pgcfg->default_domain,
15326097Snw141292 		    &new_pgcfg.default_domain, "default_domain");
15336097Snw141292 
15347031Snw141292 	changed += update_string(&live_pgcfg->domain_name,
15356097Snw141292 	    &new_pgcfg.domain_name, "domain_name");
15368361SJulian.Pullen@Sun.COM 	live_pgcfg->domain_name_auto_disc = new_pgcfg.domain_name_auto_disc;
15376097Snw141292 
15386097Snw141292 	changed += update_dirs(&live_pgcfg->domain_controller,
15396097Snw141292 	    &new_pgcfg.domain_controller, "domain_controller");
15408361SJulian.Pullen@Sun.COM 	live_pgcfg->domain_controller_auto_disc =
15418361SJulian.Pullen@Sun.COM 	    new_pgcfg.domain_controller_auto_disc;
15426097Snw141292 
15437031Snw141292 	changed += update_string(&live_pgcfg->forest_name,
15446097Snw141292 	    &new_pgcfg.forest_name, "forest_name");
15458361SJulian.Pullen@Sun.COM 	live_pgcfg->forest_name_auto_disc = new_pgcfg.forest_name_auto_disc;
15466097Snw141292 
15477031Snw141292 	changed += update_string(&live_pgcfg->site_name,
15486097Snw141292 	    &new_pgcfg.site_name, "site_name");
15498361SJulian.Pullen@Sun.COM 	live_pgcfg->site_name_auto_disc = new_pgcfg.site_name_auto_disc;
15506097Snw141292 
15516097Snw141292 	if (update_dirs(&live_pgcfg->global_catalog,
15526097Snw141292 	    &new_pgcfg.global_catalog, "global_catalog")) {
15536097Snw141292 		changed++;
15546097Snw141292 		if (live_pgcfg->global_catalog != NULL &&
15556097Snw141292 		    live_pgcfg->global_catalog[0].host[0] != '\0')
15568361SJulian.Pullen@Sun.COM 			ad_reload_required = TRUE;
15578361SJulian.Pullen@Sun.COM 	}
15588361SJulian.Pullen@Sun.COM 	live_pgcfg->global_catalog_auto_disc =
15598361SJulian.Pullen@Sun.COM 	    new_pgcfg.global_catalog_auto_disc;
15608361SJulian.Pullen@Sun.COM 
15618361SJulian.Pullen@Sun.COM 	if (update_domains_in_forest(&live_pgcfg->domains_in_forest,
15628361SJulian.Pullen@Sun.COM 	    &new_pgcfg.domains_in_forest, "domains_in_forest")) {
15638361SJulian.Pullen@Sun.COM 		changed++;
15648361SJulian.Pullen@Sun.COM 		ad_reload_required = TRUE;
15655317Sjp151216 	}
15665317Sjp151216 
15678361SJulian.Pullen@Sun.COM 	if (update_trusted_domains(&live_pgcfg->trusted_domains,
15688361SJulian.Pullen@Sun.COM 	    &new_pgcfg.trusted_domains, "trusted_domains")) {
15698361SJulian.Pullen@Sun.COM 		changed++;
15708361SJulian.Pullen@Sun.COM 		if (live_pgcfg->trusted_domains != NULL &&
15718361SJulian.Pullen@Sun.COM 		    live_pgcfg->trusted_domains[0].domain[0] != '\0')
15728361SJulian.Pullen@Sun.COM 			ad_reload_required = TRUE;
15738361SJulian.Pullen@Sun.COM 	}
15748361SJulian.Pullen@Sun.COM 
15758361SJulian.Pullen@Sun.COM 	if (update_trusted_forest(&live_pgcfg->trusted_forests,
15768361SJulian.Pullen@Sun.COM 	    &live_pgcfg->num_trusted_forests, &new_pgcfg.trusted_forests,
15778361SJulian.Pullen@Sun.COM 	    &new_pgcfg.num_trusted_forests, "trusted_forest")) {
15788361SJulian.Pullen@Sun.COM 		changed++;
15798361SJulian.Pullen@Sun.COM 		if (live_pgcfg->trusted_forests != NULL)
15808361SJulian.Pullen@Sun.COM 			ad_reload_required = TRUE;
15818361SJulian.Pullen@Sun.COM 	}
15828361SJulian.Pullen@Sun.COM 
15838361SJulian.Pullen@Sun.COM 	if (ad_reload_required)
15848361SJulian.Pullen@Sun.COM 		reload_ad();
15858361SJulian.Pullen@Sun.COM 
15866097Snw141292 	idmap_cfg_unload(&new_pgcfg);
15876097Snw141292 
15886097Snw141292 	if (flags & CFG_LOG) {
15896097Snw141292 		/*
15906097Snw141292 		 * If the config changes as a result of a refresh of the
15916097Snw141292 		 * service, then logging about it can provide useful
15926097Snw141292 		 * feedback to the sysadmin.
15936097Snw141292 		 */
15946097Snw141292 		idmapdlog(LOG_NOTICE, "Configuration %schanged",
15956097Snw141292 		    changed ? "" : "un");
15965317Sjp151216 	}
15975447Snw141292 
15986097Snw141292 	UNLOCK_CONFIG();
15996097Snw141292 
16006097Snw141292 err:
16016097Snw141292 	pthread_mutex_unlock(&cfg->handles.mutex);
16024520Snw141292 
16035731Sbaban 	if (rc < -1)
16045447Snw141292 		return (rc);
16055447Snw141292 
16065447Snw141292 	return ((errors == 0) ? 0 : -1);
16074520Snw141292 }
16084520Snw141292 
16094644Sbaban /*
16104644Sbaban  * Initialize 'cfg'.
16114644Sbaban  */
16124520Snw141292 idmap_cfg_t *
16135908Sjp151216 idmap_cfg_init()
16145908Sjp151216 {
16155317Sjp151216 	idmap_cfg_handles_t *handles;
16164520Snw141292 
16174520Snw141292 	/* First the smf repository handles: */
16184520Snw141292 	idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t));
16194520Snw141292 	if (!cfg) {
16206017Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
16214520Snw141292 		return (NULL);
16224520Snw141292 	}
16235317Sjp151216 	handles = &cfg->handles;
16244520Snw141292 
16255317Sjp151216 	(void) pthread_mutex_init(&handles->mutex, NULL);
16265317Sjp151216 
16275317Sjp151216 	if (!(handles->main = scf_handle_create(SCF_VERSION))) {
16286017Snw141292 		idmapdlog(LOG_ERR, "scf_handle_create() failed: %s",
16296017Snw141292 		    scf_strerror(scf_error()));
16304520Snw141292 		goto error;
16314520Snw141292 	}
16324520Snw141292 
16335317Sjp151216 	if (scf_handle_bind(handles->main) < 0) {
16346017Snw141292 		idmapdlog(LOG_ERR, "scf_handle_bind() failed: %s",
16356017Snw141292 		    scf_strerror(scf_error()));
16364520Snw141292 		goto error;
16374520Snw141292 	}
16384520Snw141292 
16395317Sjp151216 	if (!(handles->service = scf_service_create(handles->main)) ||
16405317Sjp151216 	    !(handles->instance = scf_instance_create(handles->main)) ||
16415317Sjp151216 	    !(handles->config_pg = scf_pg_create(handles->main)) ||
16425317Sjp151216 	    !(handles->general_pg = scf_pg_create(handles->main))) {
16436017Snw141292 		idmapdlog(LOG_ERR, "scf handle creation failed: %s",
16446017Snw141292 		    scf_strerror(scf_error()));
16454520Snw141292 		goto error;
16464520Snw141292 	}
16474520Snw141292 
16485317Sjp151216 	if (scf_handle_decode_fmri(handles->main,
16495908Sjp151216 	    FMRI_BASE "/:properties/" CONFIG_PG,
16505908Sjp151216 	    NULL,				/* scope */
16515908Sjp151216 	    handles->service,		/* service */
16525908Sjp151216 	    handles->instance,		/* instance */
16535908Sjp151216 	    handles->config_pg,		/* pg */
16545908Sjp151216 	    NULL,				/* prop */
16555908Sjp151216 	    SCF_DECODE_FMRI_EXACT) < 0) {
16566017Snw141292 		idmapdlog(LOG_ERR, "scf_handle_decode_fmri() failed: %s",
16576017Snw141292 		    scf_strerror(scf_error()));
16584520Snw141292 		goto error;
16594520Snw141292 	}
16604520Snw141292 
16615317Sjp151216 	if (scf_service_get_pg(handles->service,
16625908Sjp151216 	    GENERAL_PG, handles->general_pg) < 0) {
16636017Snw141292 		idmapdlog(LOG_ERR, "scf_service_get_pg() failed: %s",
16646017Snw141292 		    scf_strerror(scf_error()));
16654520Snw141292 		goto error;
16664520Snw141292 	}
16674520Snw141292 
16685317Sjp151216 	/* Initialize AD Auto Discovery context */
16695317Sjp151216 	handles->ad_ctx = ad_disc_init();
16705317Sjp151216 	if (handles->ad_ctx == NULL)
16715317Sjp151216 		goto error;
16725317Sjp151216 
16734520Snw141292 	return (cfg);
16744520Snw141292 
16754520Snw141292 error:
16764520Snw141292 	(void) idmap_cfg_fini(cfg);
16774520Snw141292 	return (NULL);
16784520Snw141292 }
16794520Snw141292 
16805317Sjp151216 void
16815908Sjp151216 idmap_cfg_unload(idmap_pg_config_t *pgcfg)
16825908Sjp151216 {
16835317Sjp151216 
16845317Sjp151216 	if (pgcfg->default_domain) {
16855317Sjp151216 		free(pgcfg->default_domain);
16865317Sjp151216 		pgcfg->default_domain = NULL;
16875317Sjp151216 	}
16885317Sjp151216 	if (pgcfg->domain_name) {
16895317Sjp151216 		free(pgcfg->domain_name);
16905317Sjp151216 		pgcfg->domain_name = NULL;
16915317Sjp151216 	}
16925317Sjp151216 	if (pgcfg->machine_sid) {
16935317Sjp151216 		free(pgcfg->machine_sid);
16945317Sjp151216 		pgcfg->machine_sid = NULL;
16955317Sjp151216 	}
16965317Sjp151216 	if (pgcfg->domain_controller) {
16975317Sjp151216 		free(pgcfg->domain_controller);
16985317Sjp151216 		pgcfg->domain_controller = NULL;
16995317Sjp151216 	}
17005317Sjp151216 	if (pgcfg->forest_name) {
17015317Sjp151216 		free(pgcfg->forest_name);
17025317Sjp151216 		pgcfg->forest_name = NULL;
17035317Sjp151216 	}
17045317Sjp151216 	if (pgcfg->site_name) {
17055317Sjp151216 		free(pgcfg->site_name);
17065317Sjp151216 		pgcfg->site_name = NULL;
17075317Sjp151216 	}
17085317Sjp151216 	if (pgcfg->global_catalog) {
17094520Snw141292 		free(pgcfg->global_catalog);
17105317Sjp151216 		pgcfg->global_catalog = NULL;
17115317Sjp151216 	}
17128361SJulian.Pullen@Sun.COM 	if (pgcfg->trusted_domains) {
17138361SJulian.Pullen@Sun.COM 		free(pgcfg->trusted_domains);
17148361SJulian.Pullen@Sun.COM 		pgcfg->trusted_domains = NULL;
17158361SJulian.Pullen@Sun.COM 	}
17168361SJulian.Pullen@Sun.COM 	if (pgcfg->trusted_forests)
17178361SJulian.Pullen@Sun.COM 		free_trusted_forests(&pgcfg->trusted_forests,
17188361SJulian.Pullen@Sun.COM 		    &pgcfg->num_trusted_forests);
17198361SJulian.Pullen@Sun.COM 
17205731Sbaban 	if (pgcfg->ad_unixuser_attr) {
17215731Sbaban 		free(pgcfg->ad_unixuser_attr);
17225731Sbaban 		pgcfg->ad_unixuser_attr = NULL;
17235731Sbaban 	}
17245731Sbaban 	if (pgcfg->ad_unixgroup_attr) {
17255731Sbaban 		free(pgcfg->ad_unixgroup_attr);
17265731Sbaban 		pgcfg->ad_unixgroup_attr = NULL;
17275731Sbaban 	}
17285731Sbaban 	if (pgcfg->nldap_winname_attr) {
17295731Sbaban 		free(pgcfg->nldap_winname_attr);
17305731Sbaban 		pgcfg->nldap_winname_attr = NULL;
17315731Sbaban 	}
17324520Snw141292 }
17334520Snw141292 
17344520Snw141292 int
17354520Snw141292 idmap_cfg_fini(idmap_cfg_t *cfg)
17364520Snw141292 {
17375317Sjp151216 	idmap_cfg_handles_t *handles = &cfg->handles;
17385317Sjp151216 	idmap_cfg_unload(&cfg->pgcfg);
17394520Snw141292 
17405317Sjp151216 	(void) pthread_mutex_destroy(&handles->mutex);
17415317Sjp151216 	scf_pg_destroy(handles->config_pg);
17425317Sjp151216 	scf_pg_destroy(handles->general_pg);
17435317Sjp151216 	scf_instance_destroy(handles->instance);
17445317Sjp151216 	scf_service_destroy(handles->service);
17455317Sjp151216 	scf_handle_destroy(handles->main);
17465731Sbaban 	if (handles->ad_ctx != NULL)
17475731Sbaban 		ad_disc_fini(handles->ad_ctx);
17484520Snw141292 	free(cfg);
17494520Snw141292 
17504520Snw141292 	return (0);
17514520Snw141292 }
17525968Snw141292 
17535968Snw141292 void
17545968Snw141292 idmap_cfg_poke_updates(void)
17555968Snw141292 {
17566097Snw141292 	if (idmapd_ev_port != -1)
17576097Snw141292 		(void) port_send(idmapd_ev_port, POKE_AUTO_DISCOVERY, NULL);
17585968Snw141292 }
17595968Snw141292 
17605968Snw141292 /*ARGSUSED*/
17615968Snw141292 void
17626097Snw141292 idmap_cfg_hup_handler(int sig)
17636097Snw141292 {
17645968Snw141292 	if (idmapd_ev_port >= 0)
17655968Snw141292 		(void) port_send(idmapd_ev_port, RECONFIGURE, NULL);
17665968Snw141292 }
1767