xref: /onnv-gate/usr/src/cmd/idmap/idmapd/idmap_config.c (revision 12065:0e89d02a32ea)
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*12065SKeyur.Desai@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
234520Snw141292  */
244520Snw141292 
254520Snw141292 
264520Snw141292 /*
274520Snw141292  * Config routines common to idmap(1M) and idmapd(1M)
284520Snw141292  */
294520Snw141292 
304520Snw141292 #include <stdlib.h>
314520Snw141292 #include <strings.h>
324520Snw141292 #include <libintl.h>
334520Snw141292 #include <ctype.h>
344520Snw141292 #include <errno.h>
354644Sbaban #include "idmapd.h"
364520Snw141292 #include <stdio.h>
374520Snw141292 #include <stdarg.h>
384695Sbaban #include <uuid/uuid.h>
395317Sjp151216 #include <pthread.h>
405317Sjp151216 #include <port.h>
415968Snw141292 #include <net/route.h>
428361SJulian.Pullen@Sun.COM #include <sys/u8_textprep.h>
435317Sjp151216 #include "addisc.h"
444520Snw141292 
457031Snw141292 #define	MACHINE_SID_LEN		(9 + 3 * 11)
465968Snw141292 #define	FMRI_BASE		"svc:/system/idmap"
475968Snw141292 #define	CONFIG_PG		"config"
485968Snw141292 #define	GENERAL_PG		"general"
495968Snw141292 #define	RECONFIGURE		1
505968Snw141292 #define	POKE_AUTO_DISCOVERY	2
514520Snw141292 
52*12065SKeyur.Desai@Sun.COM enum event_type {
53*12065SKeyur.Desai@Sun.COM 	EVENT_NOTHING,	/* Woke up for no good reason */
54*12065SKeyur.Desai@Sun.COM 	EVENT_TIMEOUT,	/* Timeout expired */
55*12065SKeyur.Desai@Sun.COM 	EVENT_ROUTING,	/* An interesting routing event happened */
56*12065SKeyur.Desai@Sun.COM 	EVENT_DEGRADE,	/* An error occurred in the mainline */
57*12065SKeyur.Desai@Sun.COM 	EVENT_REFRESH,	/* SMF refresh */
58*12065SKeyur.Desai@Sun.COM };
59*12065SKeyur.Desai@Sun.COM 
605317Sjp151216 /*LINTLIBRARY*/
615317Sjp151216 
625317Sjp151216 
635317Sjp151216 static pthread_t update_thread_handle = 0;
645317Sjp151216 
655968Snw141292 static int idmapd_ev_port = -1;
665968Snw141292 static int rt_sock = -1;
675317Sjp151216 
6810504SKeyur.Desai@Sun.COM struct enum_lookup_map directory_mapping_map[] = {
6910504SKeyur.Desai@Sun.COM 	{ DIRECTORY_MAPPING_NONE, "none" },
7010504SKeyur.Desai@Sun.COM 	{ DIRECTORY_MAPPING_NAME, "name" },
7110504SKeyur.Desai@Sun.COM 	{ DIRECTORY_MAPPING_IDMU, "idmu" },
7210504SKeyur.Desai@Sun.COM 	{ 0, NULL },
7310504SKeyur.Desai@Sun.COM };
7410504SKeyur.Desai@Sun.COM 
754695Sbaban static int
765908Sjp151216 generate_machine_sid(char **machine_sid)
775908Sjp151216 {
784695Sbaban 	char *p;
794695Sbaban 	uuid_t uu;
804695Sbaban 	int i, j, len, rlen;
814695Sbaban 	uint32_t rid;
824695Sbaban 
834695Sbaban 	/*
847031Snw141292 	 * Generate and split 128-bit UUID into three 32-bit RIDs The
857031Snw141292 	 * machine_sid will be of the form S-1-5-21-N1-N2-N3 (that's
867031Snw141292 	 * four RIDs altogether).
877031Snw141292 	 *
8810504SKeyur.Desai@Sun.COM 	 * Technically we could use up to 14 random RIDs here, but it
897031Snw141292 	 * turns out that with some versions of Windows using SIDs with
907031Snw141292 	 * more than  five RIDs in security descriptors causes problems.
914695Sbaban 	 */
924695Sbaban 
934695Sbaban 	*machine_sid = calloc(1, MACHINE_SID_LEN);
944695Sbaban 	if (*machine_sid == NULL) {
956017Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
964695Sbaban 		return (-1);
974695Sbaban 	}
984695Sbaban 	(void) strcpy(*machine_sid, "S-1-5-21");
994695Sbaban 	p = *machine_sid + strlen("S-1-5-21");
1004695Sbaban 	len = MACHINE_SID_LEN - strlen("S-1-5-21");
1014695Sbaban 
1024695Sbaban 	uuid_clear(uu);
1034695Sbaban 	uuid_generate_random(uu);
1044695Sbaban 
1057031Snw141292 #if UUID_LEN != 16
1067031Snw141292 #error UUID size is not 16!
1077031Snw141292 #endif
1087031Snw141292 
1097031Snw141292 	for (i = 0; i < 3; i++) {
1104695Sbaban 		j = i * 4;
1114695Sbaban 		rid = (uu[j] << 24) | (uu[j + 1] << 16) |
1125908Sjp151216 		    (uu[j + 2] << 8) | (uu[j + 3]);
1134695Sbaban 		rlen = snprintf(p, len, "-%u", rid);
1144695Sbaban 		p += rlen;
1154695Sbaban 		len -= rlen;
1164695Sbaban 	}
1174695Sbaban 
1184695Sbaban 	return (0);
1194695Sbaban }
1204695Sbaban 
1216616Sdm199847 
1226616Sdm199847 /* In the case of error, exists is set to FALSE anyway */
1236616Sdm199847 static int
12410504SKeyur.Desai@Sun.COM prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists)
1256017Snw141292 {
1266616Sdm199847 
1276616Sdm199847 	scf_property_t *scf_prop;
1286616Sdm199847 	scf_value_t *value;
1296616Sdm199847 
1308671SJulian.Pullen@Sun.COM 	*exists = B_FALSE;
1316017Snw141292 
1326616Sdm199847 	scf_prop = scf_property_create(handles->main);
1336616Sdm199847 	if (scf_prop == NULL) {
1346616Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
1356616Sdm199847 		    scf_strerror(scf_error()));
1366616Sdm199847 		return (-1);
1376616Sdm199847 	}
1386616Sdm199847 	value = scf_value_create(handles->main);
1396616Sdm199847 	if (value == NULL) {
1406616Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
1416616Sdm199847 		    scf_strerror(scf_error()));
1426616Sdm199847 		scf_property_destroy(scf_prop);
1436616Sdm199847 		return (-1);
1446616Sdm199847 	}
1456017Snw141292 
1466017Snw141292 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) == 0)
1478671SJulian.Pullen@Sun.COM 		*exists = B_TRUE;
1486017Snw141292 
1496017Snw141292 	scf_value_destroy(value);
1506017Snw141292 	scf_property_destroy(scf_prop);
1516017Snw141292 
1526616Sdm199847 	return (0);
1536017Snw141292 }
1546017Snw141292 
1554520Snw141292 /* Check if in the case of failure the original value of *val is preserved */
1564520Snw141292 static int
15710504SKeyur.Desai@Sun.COM get_val_int(idmap_cfg_handles_t *handles, const char *name,
1585317Sjp151216 	void *val, scf_type_t type)
1594520Snw141292 {
1604520Snw141292 	int rc = 0;
1614520Snw141292 
1626616Sdm199847 	scf_property_t *scf_prop;
1636616Sdm199847 	scf_value_t *value;
16410504SKeyur.Desai@Sun.COM 	uint8_t b;
1656616Sdm199847 
1667031Snw141292 	switch (type) {
1677031Snw141292 	case SCF_TYPE_BOOLEAN:
16810504SKeyur.Desai@Sun.COM 		*(boolean_t *)val = B_FALSE;
1697031Snw141292 		break;
1707031Snw141292 	case SCF_TYPE_COUNT:
1717031Snw141292 		*(uint64_t *)val = 0;
1727031Snw141292 		break;
1737031Snw141292 	case SCF_TYPE_INTEGER:
1747031Snw141292 		*(int64_t *)val = 0;
1757031Snw141292 		break;
1767031Snw141292 	default:
1777031Snw141292 		idmapdlog(LOG_ERR, "Invalid scf integer type (%d)",
1787031Snw141292 		    type);
1797031Snw141292 		abort();
1807031Snw141292 	}
1817031Snw141292 
1826616Sdm199847 	scf_prop = scf_property_create(handles->main);
1836616Sdm199847 	if (scf_prop == NULL) {
1846616Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
1856616Sdm199847 		    scf_strerror(scf_error()));
1866616Sdm199847 		return (-1);
1876616Sdm199847 	}
1886616Sdm199847 	value = scf_value_create(handles->main);
1896616Sdm199847 	if (value == NULL) {
1906616Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
1916616Sdm199847 		    scf_strerror(scf_error()));
1926616Sdm199847 		scf_property_destroy(scf_prop);
1936616Sdm199847 		return (-1);
1946616Sdm199847 	}
1954520Snw141292 
1965317Sjp151216 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
1974520Snw141292 	/* this is OK: the property is just undefined */
1984520Snw141292 		goto destruction;
1994520Snw141292 
2004520Snw141292 
2015317Sjp151216 	if (scf_property_get_value(scf_prop, value) < 0)
2024520Snw141292 	/* It is still OK when a property doesn't have any value */
2034520Snw141292 		goto destruction;
2044520Snw141292 
2054520Snw141292 	switch (type) {
2064520Snw141292 	case SCF_TYPE_BOOLEAN:
20710504SKeyur.Desai@Sun.COM 		rc = scf_value_get_boolean(value, &b);
20810504SKeyur.Desai@Sun.COM 		*(boolean_t *)val = b;
2094520Snw141292 		break;
2104520Snw141292 	case SCF_TYPE_COUNT:
2114520Snw141292 		rc = scf_value_get_count(value, val);
2124520Snw141292 		break;
2134520Snw141292 	case SCF_TYPE_INTEGER:
2144520Snw141292 		rc = scf_value_get_integer(value, val);
2154520Snw141292 		break;
21610504SKeyur.Desai@Sun.COM 	default:
21710504SKeyur.Desai@Sun.COM 		abort();	/* tested above */
21810504SKeyur.Desai@Sun.COM 		/* NOTREACHED */
2194520Snw141292 	}
2204520Snw141292 
22110504SKeyur.Desai@Sun.COM 	if (rc != 0) {
22210504SKeyur.Desai@Sun.COM 		idmapdlog(LOG_ERR, "Can not retrieve config/%s:  %s",
22310504SKeyur.Desai@Sun.COM 		    name, scf_strerror(scf_error()));
22410504SKeyur.Desai@Sun.COM 	}
2254520Snw141292 
2264520Snw141292 destruction:
2274520Snw141292 	scf_value_destroy(value);
2284520Snw141292 	scf_property_destroy(scf_prop);
2294520Snw141292 
2304520Snw141292 	return (rc);
2314520Snw141292 }
2324520Snw141292 
2334520Snw141292 static char *
23410504SKeyur.Desai@Sun.COM scf_value2string(const char *name, scf_value_t *value)
2355908Sjp151216 {
23610504SKeyur.Desai@Sun.COM 	static size_t max_val = 0;
2374520Snw141292 
23810504SKeyur.Desai@Sun.COM 	if (max_val == 0)
23910504SKeyur.Desai@Sun.COM 		max_val = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
2404520Snw141292 
24110504SKeyur.Desai@Sun.COM 	char buf[max_val + 1];
24210504SKeyur.Desai@Sun.COM 	if (scf_value_get_astring(value, buf, max_val + 1) < 0) {
24310504SKeyur.Desai@Sun.COM 		idmapdlog(LOG_ERR, "Can not retrieve config/%s:  %s",
24410504SKeyur.Desai@Sun.COM 		    name, scf_strerror(scf_error()));
24510504SKeyur.Desai@Sun.COM 		return (NULL);
2464520Snw141292 	}
2474520Snw141292 
24810504SKeyur.Desai@Sun.COM 	char *s = strdup(buf);
24910504SKeyur.Desai@Sun.COM 	if (s == NULL)
25010504SKeyur.Desai@Sun.COM 		idmapdlog(LOG_ERR, "Out of memory");
2514520Snw141292 
25210504SKeyur.Desai@Sun.COM 	return (s);
2534520Snw141292 }
2544520Snw141292 
2555317Sjp151216 static int
2565317Sjp151216 get_val_ds(idmap_cfg_handles_t *handles, const char *name, int defport,
2576616Sdm199847 		idmap_ad_disc_ds_t **val)
2585317Sjp151216 {
2596616Sdm199847 	idmap_ad_disc_ds_t *servers = NULL;
2605317Sjp151216 	scf_property_t *scf_prop;
2615317Sjp151216 	scf_value_t *value;
2625317Sjp151216 	scf_iter_t *iter;
2635317Sjp151216 	char *host, *portstr;
2645447Snw141292 	int len, i;
2655317Sjp151216 	int count = 0;
2665447Snw141292 	int rc = -1;
2675317Sjp151216 
2685317Sjp151216 	*val = NULL;
2695317Sjp151216 
2705317Sjp151216 restart:
2715317Sjp151216 	scf_prop = scf_property_create(handles->main);
2726616Sdm199847 	if (scf_prop == NULL) {
2736616Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
2746616Sdm199847 		    scf_strerror(scf_error()));
2756616Sdm199847 		return (-1);
2766616Sdm199847 	}
2776616Sdm199847 
2785317Sjp151216 	value = scf_value_create(handles->main);
2796616Sdm199847 	if (value == NULL) {
2806616Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
2816616Sdm199847 		    scf_strerror(scf_error()));
2826616Sdm199847 		scf_property_destroy(scf_prop);
2836616Sdm199847 		return (-1);
2846616Sdm199847 	}
2856616Sdm199847 
2865317Sjp151216 	iter = scf_iter_create(handles->main);
2876616Sdm199847 	if (iter == NULL) {
2886616Sdm199847 		idmapdlog(LOG_ERR, "scf_iter_create() failed: %s",
2896616Sdm199847 		    scf_strerror(scf_error()));
2906616Sdm199847 		scf_value_destroy(value);
2916616Sdm199847 		scf_property_destroy(scf_prop);
2926616Sdm199847 		return (-1);
2936616Sdm199847 	}
2945317Sjp151216 
2955447Snw141292 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) {
2965317Sjp151216 		/* this is OK: the property is just undefined */
2975447Snw141292 		rc = 0;
2985317Sjp151216 		goto destruction;
2995447Snw141292 	}
3005317Sjp151216 
3015317Sjp151216 	if (scf_iter_property_values(iter, scf_prop) < 0) {
3025317Sjp151216 		idmapdlog(LOG_ERR,
3036017Snw141292 		    "scf_iter_property_values(%s) failed: %s",
3046017Snw141292 		    name, scf_strerror(scf_error()));
3055317Sjp151216 		goto destruction;
3065317Sjp151216 	}
3075317Sjp151216 
3085317Sjp151216 	/* Workaround scf bugs -- can't reset an iteration */
3095317Sjp151216 	if (count == 0) {
3105317Sjp151216 		while (scf_iter_next_value(iter, value) > 0)
3115317Sjp151216 			count++;
3125317Sjp151216 
3135447Snw141292 		if (count == 0) {
3145317Sjp151216 			/* no values */
3155447Snw141292 			rc = 0;
3165317Sjp151216 			goto destruction;
3175447Snw141292 		}
3185317Sjp151216 
3195317Sjp151216 		scf_value_destroy(value);
3205317Sjp151216 		scf_iter_destroy(iter);
3215317Sjp151216 		scf_property_destroy(scf_prop);
3225317Sjp151216 		goto restart;
3235317Sjp151216 	}
3245317Sjp151216 
3255317Sjp151216 	if ((servers = calloc(count + 1, sizeof (*servers))) == NULL) {
3266017Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
3275317Sjp151216 		goto destruction;
3285317Sjp151216 	}
3295317Sjp151216 
3305447Snw141292 	i = 0;
3315447Snw141292 	while (i < count && scf_iter_next_value(iter, value) > 0) {
3325447Snw141292 		servers[i].priority = 0;
3335447Snw141292 		servers[i].weight = 100;
3345447Snw141292 		servers[i].port = defport;
33510504SKeyur.Desai@Sun.COM 		if ((host = scf_value2string(name, value)) == NULL) {
3365317Sjp151216 			goto destruction;
3375317Sjp151216 		}
3385317Sjp151216 		if ((portstr = strchr(host, ':')) != NULL) {
3395317Sjp151216 			*portstr++ = '\0';
3405447Snw141292 			servers[i].port = strtol(portstr,
3415317Sjp151216 			    (char **)NULL, 10);
3425447Snw141292 			if (servers[i].port == 0)
3435447Snw141292 				servers[i].port = defport;
3445317Sjp151216 		}
3455447Snw141292 		len = strlcpy(servers[i].host, host,
3465317Sjp151216 		    sizeof (servers->host));
3475317Sjp151216 
3485317Sjp151216 		free(host);
3495317Sjp151216 
3505317Sjp151216 		/* Ignore this server if the hostname is too long */
3515317Sjp151216 		if (len < sizeof (servers->host))
3525447Snw141292 			i++;
3535317Sjp151216 	}
3545317Sjp151216 
3555317Sjp151216 	*val = servers;
3565317Sjp151216 
3575447Snw141292 	rc = 0;
3585447Snw141292 
3595317Sjp151216 destruction:
3605317Sjp151216 	scf_value_destroy(value);
3615317Sjp151216 	scf_iter_destroy(iter);
3625317Sjp151216 	scf_property_destroy(scf_prop);
3635317Sjp151216 
3645317Sjp151216 	if (rc < 0) {
3655317Sjp151216 		if (servers)
3665317Sjp151216 			free(servers);
3675317Sjp151216 		*val = NULL;
3685317Sjp151216 	}
3695317Sjp151216 
3705317Sjp151216 	return (rc);
3715317Sjp151216 }
3725317Sjp151216 
3734520Snw141292 
3744520Snw141292 static int
37510504SKeyur.Desai@Sun.COM get_val_astring(idmap_cfg_handles_t *handles, const char *name, char **val)
3764520Snw141292 {
3774520Snw141292 	int rc = 0;
3784520Snw141292 
3796616Sdm199847 	scf_property_t *scf_prop;
3806616Sdm199847 	scf_value_t *value;
3816616Sdm199847 
3826616Sdm199847 	scf_prop = scf_property_create(handles->main);
3836616Sdm199847 	if (scf_prop == NULL) {
3846616Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
3856616Sdm199847 		    scf_strerror(scf_error()));
3866616Sdm199847 		return (-1);
3876616Sdm199847 	}
3886616Sdm199847 	value = scf_value_create(handles->main);
3896616Sdm199847 	if (value == NULL) {
3906616Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
3916616Sdm199847 		    scf_strerror(scf_error()));
3926616Sdm199847 		scf_property_destroy(scf_prop);
3936616Sdm199847 		return (-1);
3946616Sdm199847 	}
3954520Snw141292 
3965317Sjp151216 	*val = NULL;
3974520Snw141292 
3985317Sjp151216 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
3994520Snw141292 	/* this is OK: the property is just undefined */
4004520Snw141292 		goto destruction;
4014520Snw141292 
4025317Sjp151216 	if (scf_property_get_value(scf_prop, value) < 0) {
4034644Sbaban 		idmapdlog(LOG_ERR,
4046017Snw141292 		    "scf_property_get_value(%s) failed: %s",
4056017Snw141292 		    name, scf_strerror(scf_error()));
4064520Snw141292 		rc = -1;
4074520Snw141292 		goto destruction;
4084520Snw141292 	}
4094520Snw141292 
41010504SKeyur.Desai@Sun.COM 	*val = scf_value2string(name, value);
41110504SKeyur.Desai@Sun.COM 	if (*val == NULL)
4124520Snw141292 		rc = -1;
4134520Snw141292 
4144520Snw141292 destruction:
4154520Snw141292 	scf_value_destroy(value);
4164520Snw141292 	scf_property_destroy(scf_prop);
4174520Snw141292 
4184520Snw141292 	if (rc < 0) {
4194520Snw141292 		if (*val)
4204520Snw141292 			free(*val);
4214520Snw141292 		*val = NULL;
4224520Snw141292 	}
4234520Snw141292 
4244520Snw141292 	return (rc);
4254520Snw141292 }
4264520Snw141292 
4275317Sjp151216 
4284695Sbaban static int
42910504SKeyur.Desai@Sun.COM del_val(idmap_cfg_handles_t *handles, const char *name)
43010504SKeyur.Desai@Sun.COM {
43110504SKeyur.Desai@Sun.COM 	int			rc = -1;
43210504SKeyur.Desai@Sun.COM 	int			ret;
43310504SKeyur.Desai@Sun.COM 	scf_transaction_t	*tx = NULL;
43410504SKeyur.Desai@Sun.COM 	scf_transaction_entry_t	*ent = NULL;
43510504SKeyur.Desai@Sun.COM 
43610504SKeyur.Desai@Sun.COM 	if ((tx = scf_transaction_create(handles->main)) == NULL) {
43710504SKeyur.Desai@Sun.COM 		idmapdlog(LOG_ERR,
43810504SKeyur.Desai@Sun.COM 		    "scf_transaction_create() failed: %s",
43910504SKeyur.Desai@Sun.COM 		    scf_strerror(scf_error()));
44010504SKeyur.Desai@Sun.COM 		goto destruction;
44110504SKeyur.Desai@Sun.COM 	}
44210504SKeyur.Desai@Sun.COM 	if ((ent = scf_entry_create(handles->main)) == NULL) {
44310504SKeyur.Desai@Sun.COM 		idmapdlog(LOG_ERR,
44410504SKeyur.Desai@Sun.COM 		    "scf_entry_create() failed: %s",
44510504SKeyur.Desai@Sun.COM 		    scf_strerror(scf_error()));
44610504SKeyur.Desai@Sun.COM 		goto destruction;
44710504SKeyur.Desai@Sun.COM 	}
44810504SKeyur.Desai@Sun.COM 
44910504SKeyur.Desai@Sun.COM 	do {
45010504SKeyur.Desai@Sun.COM 		if (scf_pg_update(handles->config_pg) == -1) {
45110504SKeyur.Desai@Sun.COM 			idmapdlog(LOG_ERR,
45210504SKeyur.Desai@Sun.COM 			    "scf_pg_update(%s) failed: %s",
45310504SKeyur.Desai@Sun.COM 			    name, scf_strerror(scf_error()));
45410504SKeyur.Desai@Sun.COM 			goto destruction;
45510504SKeyur.Desai@Sun.COM 		}
45610504SKeyur.Desai@Sun.COM 		if (scf_transaction_start(tx, handles->config_pg) != 0) {
45710504SKeyur.Desai@Sun.COM 			idmapdlog(LOG_ERR,
45810504SKeyur.Desai@Sun.COM 			    "scf_transaction_start(%s) failed: %s",
45910504SKeyur.Desai@Sun.COM 			    name, scf_strerror(scf_error()));
46010504SKeyur.Desai@Sun.COM 			goto destruction;
46110504SKeyur.Desai@Sun.COM 		}
46210504SKeyur.Desai@Sun.COM 
46310504SKeyur.Desai@Sun.COM 		if (scf_transaction_property_delete(tx, ent, name) != 0) {
46410504SKeyur.Desai@Sun.COM 			/* Don't complain if it already doesn't exist. */
46510504SKeyur.Desai@Sun.COM 			if (scf_error() != SCF_ERROR_NOT_FOUND) {
46610504SKeyur.Desai@Sun.COM 				idmapdlog(LOG_ERR,
46710504SKeyur.Desai@Sun.COM 				    "scf_transaction_property_delete() failed:"
46810504SKeyur.Desai@Sun.COM 				    " %s",
46910504SKeyur.Desai@Sun.COM 				    scf_strerror(scf_error()));
47010504SKeyur.Desai@Sun.COM 			}
47110504SKeyur.Desai@Sun.COM 			goto destruction;
47210504SKeyur.Desai@Sun.COM 		}
47310504SKeyur.Desai@Sun.COM 
47410504SKeyur.Desai@Sun.COM 		ret = scf_transaction_commit(tx);
47510504SKeyur.Desai@Sun.COM 
47610504SKeyur.Desai@Sun.COM 		if (ret == 0)
47710504SKeyur.Desai@Sun.COM 			scf_transaction_reset(tx);
47810504SKeyur.Desai@Sun.COM 	} while (ret == 0);
47910504SKeyur.Desai@Sun.COM 
48010504SKeyur.Desai@Sun.COM 	if (ret == -1) {
48110504SKeyur.Desai@Sun.COM 		idmapdlog(LOG_ERR,
48210504SKeyur.Desai@Sun.COM 		    "scf_transaction_commit(%s) failed: %s",
48310504SKeyur.Desai@Sun.COM 		    name, scf_strerror(scf_error()));
48410504SKeyur.Desai@Sun.COM 		goto destruction;
48510504SKeyur.Desai@Sun.COM 	}
48610504SKeyur.Desai@Sun.COM 
48710504SKeyur.Desai@Sun.COM 	rc = 0;
48810504SKeyur.Desai@Sun.COM 
48910504SKeyur.Desai@Sun.COM destruction:
49010504SKeyur.Desai@Sun.COM 	if (ent != NULL)
49110504SKeyur.Desai@Sun.COM 		scf_entry_destroy(ent);
49210504SKeyur.Desai@Sun.COM 	if (tx != NULL)
49310504SKeyur.Desai@Sun.COM 		scf_transaction_destroy(tx);
49410504SKeyur.Desai@Sun.COM 	return (rc);
49510504SKeyur.Desai@Sun.COM }
49610504SKeyur.Desai@Sun.COM 
49710504SKeyur.Desai@Sun.COM 
49810504SKeyur.Desai@Sun.COM static int
49910504SKeyur.Desai@Sun.COM set_val_astring(idmap_cfg_handles_t *handles, const char *name, const char *val)
5004695Sbaban {
5015447Snw141292 	int			rc = -1;
5025447Snw141292 	int			ret = -2;
5035447Snw141292 	int			i;
5044695Sbaban 	scf_property_t		*scf_prop = NULL;
5054695Sbaban 	scf_value_t		*value = NULL;
5064695Sbaban 	scf_transaction_t	*tx = NULL;
5074695Sbaban 	scf_transaction_entry_t	*ent = NULL;
5084695Sbaban 
5095317Sjp151216 	if ((scf_prop = scf_property_create(handles->main)) == NULL ||
5105317Sjp151216 	    (value = scf_value_create(handles->main)) == NULL ||
5115317Sjp151216 	    (tx = scf_transaction_create(handles->main)) == NULL ||
5125317Sjp151216 	    (ent = scf_entry_create(handles->main)) == NULL) {
5136017Snw141292 		idmapdlog(LOG_ERR, "Unable to set property %s",
5146017Snw141292 		    name, scf_strerror(scf_error()));
5154695Sbaban 		goto destruction;
5164695Sbaban 	}
5174695Sbaban 
5185447Snw141292 	for (i = 0; i < MAX_TRIES && (ret == -2 || ret == 0); i++) {
5195317Sjp151216 		if (scf_transaction_start(tx, handles->config_pg) == -1) {
5204695Sbaban 			idmapdlog(LOG_ERR,
5216017Snw141292 			    "scf_transaction_start(%s) failed: %s",
5226017Snw141292 			    name, scf_strerror(scf_error()));
5234695Sbaban 			goto destruction;
5244695Sbaban 		}
5254695Sbaban 
5265447Snw141292 		if (scf_transaction_property_new(tx, ent, name,
5275447Snw141292 		    SCF_TYPE_ASTRING) < 0) {
5284695Sbaban 			idmapdlog(LOG_ERR,
5296017Snw141292 			    "scf_transaction_property_new() failed: %s",
5306017Snw141292 			    scf_strerror(scf_error()));
5314695Sbaban 			goto destruction;
5324695Sbaban 		}
5334695Sbaban 
5344695Sbaban 		if (scf_value_set_astring(value, val) == -1) {
5354695Sbaban 			idmapdlog(LOG_ERR,
5366017Snw141292 			    "scf_value_set_astring() failed: %s",
5376017Snw141292 			    scf_strerror(scf_error()));
5384695Sbaban 			goto destruction;
5394695Sbaban 		}
5404695Sbaban 
5414695Sbaban 		if (scf_entry_add_value(ent, value) == -1) {
5424695Sbaban 			idmapdlog(LOG_ERR,
5436017Snw141292 			    "scf_entry_add_value() failed: %s",
5446017Snw141292 			    scf_strerror(scf_error()));
5454695Sbaban 			goto destruction;
5464695Sbaban 		}
5474695Sbaban 
5485447Snw141292 		if ((ret = scf_transaction_commit(tx)) == 1)
5495447Snw141292 			break;
5505447Snw141292 
5515447Snw141292 		if (ret == 0 && i < MAX_TRIES - 1) {
5524695Sbaban 			/*
5534695Sbaban 			 * Property group set in scf_transaction_start()
5544695Sbaban 			 * is not the most recent. Update pg, reset tx and
5554695Sbaban 			 * retry tx.
5564695Sbaban 			 */
5574695Sbaban 			idmapdlog(LOG_WARNING,
5586017Snw141292 			    "scf_transaction_commit(%s) failed - Retry: %s",
5596017Snw141292 			    name, scf_strerror(scf_error()));
5605317Sjp151216 			if (scf_pg_update(handles->config_pg) == -1) {
5614695Sbaban 				idmapdlog(LOG_ERR,
5626017Snw141292 				    "scf_pg_update() failed: %s",
5636017Snw141292 				    scf_strerror(scf_error()));
5644695Sbaban 				goto destruction;
5654695Sbaban 			}
5664695Sbaban 			scf_transaction_reset(tx);
5674695Sbaban 		}
5684695Sbaban 	}
5694695Sbaban 
5705447Snw141292 
5715447Snw141292 	if (ret == 1)
5725447Snw141292 		rc = 0;
5735447Snw141292 	else if (ret != -2)
5744695Sbaban 		idmapdlog(LOG_ERR,
5756017Snw141292 		    "scf_transaction_commit(%s) failed: %s",
5766017Snw141292 		    name, scf_strerror(scf_error()));
5774695Sbaban 
5784695Sbaban destruction:
5794695Sbaban 	scf_value_destroy(value);
5804695Sbaban 	scf_entry_destroy(ent);
5814695Sbaban 	scf_transaction_destroy(tx);
5824695Sbaban 	scf_property_destroy(scf_prop);
5834695Sbaban 	return (rc);
5844695Sbaban }
5854695Sbaban 
5868361SJulian.Pullen@Sun.COM 
5878361SJulian.Pullen@Sun.COM 
5888361SJulian.Pullen@Sun.COM /*
5898361SJulian.Pullen@Sun.COM  * This function updates a boolean value.
5908361SJulian.Pullen@Sun.COM  * If nothing has changed it returns 0 else 1
5918361SJulian.Pullen@Sun.COM  */
5925317Sjp151216 static int
5938671SJulian.Pullen@Sun.COM update_bool(boolean_t *value, boolean_t *new, char *name)
5947031Snw141292 {
5957031Snw141292 	if (*value == *new)
5967031Snw141292 		return (0);
5977031Snw141292 
5987031Snw141292 	idmapdlog(LOG_INFO, "change %s=%s", name, *new ? "true" : "false");
5997031Snw141292 	*value = *new;
6007031Snw141292 	return (1);
6017031Snw141292 }
6027031Snw141292 
6038361SJulian.Pullen@Sun.COM 
6048361SJulian.Pullen@Sun.COM /*
6058361SJulian.Pullen@Sun.COM  * This function updates a string value.
6068361SJulian.Pullen@Sun.COM  * If nothing has changed it returns 0 else 1
6078361SJulian.Pullen@Sun.COM  */
6087031Snw141292 static int
6097031Snw141292 update_string(char **value, char **new, char *name)
6104520Snw141292 {
6115317Sjp151216 	if (*new == NULL)
6126097Snw141292 		return (0);
6134520Snw141292 
6145317Sjp151216 	if (*value != NULL && strcmp(*new, *value) == 0) {
6155317Sjp151216 		free(*new);
6165317Sjp151216 		*new = NULL;
6176097Snw141292 		return (0);
6184520Snw141292 	}
6194520Snw141292 
6206017Snw141292 	idmapdlog(LOG_INFO, "change %s=%s", name, CHECK_NULL(*new));
6215317Sjp151216 	if (*value != NULL)
6225317Sjp151216 		free(*value);
6235317Sjp151216 	*value = *new;
6245317Sjp151216 	*new = NULL;
6256097Snw141292 	return (1);
6265317Sjp151216 }
6275317Sjp151216 
62810504SKeyur.Desai@Sun.COM static int
62910504SKeyur.Desai@Sun.COM update_enum(int *value, int *new, char *name, struct enum_lookup_map *map)
63010504SKeyur.Desai@Sun.COM {
63110504SKeyur.Desai@Sun.COM 	if (*value == *new)
63210504SKeyur.Desai@Sun.COM 		return (0);
63310504SKeyur.Desai@Sun.COM 
63410504SKeyur.Desai@Sun.COM 	idmapdlog(LOG_INFO, "change %s=%s", name, enum_lookup(*new, map));
63510504SKeyur.Desai@Sun.COM 
63610504SKeyur.Desai@Sun.COM 	*value = *new;
63710504SKeyur.Desai@Sun.COM 
63810504SKeyur.Desai@Sun.COM 	return (1);
63910504SKeyur.Desai@Sun.COM }
6408361SJulian.Pullen@Sun.COM 
6418361SJulian.Pullen@Sun.COM /*
6428361SJulian.Pullen@Sun.COM  * This function updates a directory service structure.
6438361SJulian.Pullen@Sun.COM  * If nothing has changed it returns 0 else 1
6448361SJulian.Pullen@Sun.COM  */
6455317Sjp151216 static int
6466616Sdm199847 update_dirs(idmap_ad_disc_ds_t **value, idmap_ad_disc_ds_t **new, char *name)
6475317Sjp151216 {
6485317Sjp151216 	int i;
6495317Sjp151216 
6505968Snw141292 	if (*value == *new)
6515968Snw141292 		/* Nothing to do */
6526097Snw141292 		return (0);
6535317Sjp151216 
6545968Snw141292 	if (*value != NULL && *new != NULL &&
6555968Snw141292 	    ad_disc_compare_ds(*value, *new) == 0) {
6565317Sjp151216 		free(*new);
6575317Sjp151216 		*new = NULL;
6586097Snw141292 		return (0);
6594520Snw141292 	}
6604520Snw141292 
6618361SJulian.Pullen@Sun.COM 	if (*value != NULL)
6625317Sjp151216 		free(*value);
6635317Sjp151216 
6645317Sjp151216 	*value = *new;
6655317Sjp151216 	*new = NULL;
6665968Snw141292 
6675968Snw141292 	if (*value == NULL) {
6685968Snw141292 		/* We're unsetting this DS property */
6696017Snw141292 		idmapdlog(LOG_INFO, "change %s=<none>", name);
6706097Snw141292 		return (1);
6715968Snw141292 	}
6725968Snw141292 
6735968Snw141292 	/* List all the new DSs */
6745968Snw141292 	for (i = 0; (*value)[i].host[0] != '\0'; i++)
6756017Snw141292 		idmapdlog(LOG_INFO, "change %s=%s port=%d", name,
6765968Snw141292 		    (*value)[i].host, (*value)[i].port);
6776097Snw141292 	return (1);
6785317Sjp151216 }
6795317Sjp151216 
6808361SJulian.Pullen@Sun.COM /*
6818361SJulian.Pullen@Sun.COM  * This function updates a trusted domains structure.
6828361SJulian.Pullen@Sun.COM  * If nothing has changed it returns 0 else 1
6838361SJulian.Pullen@Sun.COM  */
6848361SJulian.Pullen@Sun.COM static int
6858361SJulian.Pullen@Sun.COM update_trusted_domains(ad_disc_trusteddomains_t **value,
6868361SJulian.Pullen@Sun.COM 			ad_disc_trusteddomains_t **new, char *name)
6878361SJulian.Pullen@Sun.COM {
6888361SJulian.Pullen@Sun.COM 	int i;
6898361SJulian.Pullen@Sun.COM 
6908361SJulian.Pullen@Sun.COM 	if (*value == *new)
6918361SJulian.Pullen@Sun.COM 		/* Nothing to do */
6928361SJulian.Pullen@Sun.COM 		return (0);
6938361SJulian.Pullen@Sun.COM 
6948361SJulian.Pullen@Sun.COM 	if (*value != NULL && *new != NULL &&
6958361SJulian.Pullen@Sun.COM 	    ad_disc_compare_trusteddomains(*value, *new) == 0) {
6968361SJulian.Pullen@Sun.COM 		free(*new);
6978361SJulian.Pullen@Sun.COM 		*new = NULL;
6988361SJulian.Pullen@Sun.COM 		return (0);
6998361SJulian.Pullen@Sun.COM 	}
7008361SJulian.Pullen@Sun.COM 
7018361SJulian.Pullen@Sun.COM 	if (*value != NULL)
7028361SJulian.Pullen@Sun.COM 		free(*value);
7038361SJulian.Pullen@Sun.COM 
7048361SJulian.Pullen@Sun.COM 	*value = *new;
7058361SJulian.Pullen@Sun.COM 	*new = NULL;
7068361SJulian.Pullen@Sun.COM 
7078361SJulian.Pullen@Sun.COM 	if (*value == NULL) {
7088361SJulian.Pullen@Sun.COM 		/* We're unsetting this DS property */
7098361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_INFO, "change %s=<none>", name);
7108361SJulian.Pullen@Sun.COM 		return (1);
7118361SJulian.Pullen@Sun.COM 	}
7128361SJulian.Pullen@Sun.COM 
7138361SJulian.Pullen@Sun.COM 	/* List all the new domains */
7148361SJulian.Pullen@Sun.COM 	for (i = 0; (*value)[i].domain[0] != '\0'; i++)
7158361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_INFO, "change %s=%s direction=%s", name,
7168361SJulian.Pullen@Sun.COM 		    (*value)[i].domain,
7178361SJulian.Pullen@Sun.COM 		    (*value)[i].direction == 3 ? "bi-directional" : "inbound");
7188361SJulian.Pullen@Sun.COM 	return (1);
7198361SJulian.Pullen@Sun.COM }
7208361SJulian.Pullen@Sun.COM 
7218361SJulian.Pullen@Sun.COM 
7228361SJulian.Pullen@Sun.COM /*
7238361SJulian.Pullen@Sun.COM  * This function updates a domains in a forest structure.
7248361SJulian.Pullen@Sun.COM  * If nothing has changed it returns 0 else 1
7258361SJulian.Pullen@Sun.COM  */
7268361SJulian.Pullen@Sun.COM static int
7278361SJulian.Pullen@Sun.COM update_domains_in_forest(ad_disc_domainsinforest_t **value,
7288361SJulian.Pullen@Sun.COM 			ad_disc_domainsinforest_t **new, char *name)
7298361SJulian.Pullen@Sun.COM {
7308361SJulian.Pullen@Sun.COM 	int i;
7318361SJulian.Pullen@Sun.COM 
7328361SJulian.Pullen@Sun.COM 	if (*value == *new)
7338361SJulian.Pullen@Sun.COM 		/* Nothing to do */
7348361SJulian.Pullen@Sun.COM 		return (0);
7358361SJulian.Pullen@Sun.COM 
7368361SJulian.Pullen@Sun.COM 	if (*value != NULL && *new != NULL &&
7378361SJulian.Pullen@Sun.COM 	    ad_disc_compare_domainsinforest(*value, *new) == 0) {
7388361SJulian.Pullen@Sun.COM 		free(*new);
7398361SJulian.Pullen@Sun.COM 		*new = NULL;
7408361SJulian.Pullen@Sun.COM 		return (0);
7418361SJulian.Pullen@Sun.COM 	}
7428361SJulian.Pullen@Sun.COM 
7438361SJulian.Pullen@Sun.COM 	if (*value != NULL)
7448361SJulian.Pullen@Sun.COM 		free(*value);
7458361SJulian.Pullen@Sun.COM 
7468361SJulian.Pullen@Sun.COM 	*value = *new;
7478361SJulian.Pullen@Sun.COM 	*new = NULL;
7488361SJulian.Pullen@Sun.COM 
7498361SJulian.Pullen@Sun.COM 	if (*value == NULL) {
7508361SJulian.Pullen@Sun.COM 		/* We're unsetting this DS property */
7518361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_INFO, "change %s=<none>", name);
7528361SJulian.Pullen@Sun.COM 		return (1);
7538361SJulian.Pullen@Sun.COM 	}
7548361SJulian.Pullen@Sun.COM 
7558361SJulian.Pullen@Sun.COM 	/* List all the new domains */
7568361SJulian.Pullen@Sun.COM 	for (i = 0; (*value)[i].domain[0] != '\0'; i++)
7578361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_INFO, "change %s=%s", name,
7588361SJulian.Pullen@Sun.COM 		    (*value)[i].domain);
7598361SJulian.Pullen@Sun.COM 	return (1);
7608361SJulian.Pullen@Sun.COM }
7618361SJulian.Pullen@Sun.COM 
7628361SJulian.Pullen@Sun.COM 
7638361SJulian.Pullen@Sun.COM static void
7648361SJulian.Pullen@Sun.COM free_trusted_forests(idmap_trustedforest_t **value, int *num_values)
7658361SJulian.Pullen@Sun.COM {
7668361SJulian.Pullen@Sun.COM 	int i;
7678361SJulian.Pullen@Sun.COM 
7688361SJulian.Pullen@Sun.COM 	for (i = 0; i < *num_values; i++) {
7698361SJulian.Pullen@Sun.COM 		free((*value)[i].forest_name);
7708361SJulian.Pullen@Sun.COM 		free((*value)[i].global_catalog);
7718361SJulian.Pullen@Sun.COM 		free((*value)[i].domains_in_forest);
7728361SJulian.Pullen@Sun.COM 	}
7738361SJulian.Pullen@Sun.COM 	free(*value);
7748361SJulian.Pullen@Sun.COM 	*value = NULL;
7758361SJulian.Pullen@Sun.COM 	*num_values = 0;
7768361SJulian.Pullen@Sun.COM }
7778361SJulian.Pullen@Sun.COM 
7788361SJulian.Pullen@Sun.COM 
7798361SJulian.Pullen@Sun.COM static int
7808361SJulian.Pullen@Sun.COM compare_trusteddomainsinforest(ad_disc_domainsinforest_t *df1,
7818361SJulian.Pullen@Sun.COM 			ad_disc_domainsinforest_t *df2)
7828361SJulian.Pullen@Sun.COM {
7838671SJulian.Pullen@Sun.COM 	int		i, j;
7848671SJulian.Pullen@Sun.COM 	int		num_df1 = 0;
7858671SJulian.Pullen@Sun.COM 	int		num_df2 = 0;
7868671SJulian.Pullen@Sun.COM 	boolean_t	match;
7878361SJulian.Pullen@Sun.COM 
7888361SJulian.Pullen@Sun.COM 	for (i = 0; df1[i].domain[0] != '\0'; i++)
7898361SJulian.Pullen@Sun.COM 		if (df1[i].trusted)
7908361SJulian.Pullen@Sun.COM 			num_df1++;
7918361SJulian.Pullen@Sun.COM 
7928361SJulian.Pullen@Sun.COM 	for (j = 0; df2[j].domain[0] != '\0'; j++)
7938361SJulian.Pullen@Sun.COM 		if (df2[j].trusted)
7948361SJulian.Pullen@Sun.COM 			num_df2++;
7958361SJulian.Pullen@Sun.COM 
7968361SJulian.Pullen@Sun.COM 	if (num_df1 != num_df2)
7978361SJulian.Pullen@Sun.COM 		return (1);
7988361SJulian.Pullen@Sun.COM 
7998361SJulian.Pullen@Sun.COM 	for (i = 0; df1[i].domain[0] != '\0'; i++) {
8008361SJulian.Pullen@Sun.COM 		if (df1[i].trusted) {
8018671SJulian.Pullen@Sun.COM 			match = B_FALSE;
8028361SJulian.Pullen@Sun.COM 			for (j = 0; df2[j].domain[0] != '\0'; j++) {
8038361SJulian.Pullen@Sun.COM 				if (df2[j].trusted &&
80410122SJordan.Brown@Sun.COM 				    domain_eq(df1[i].domain, df2[j].domain) &&
80510122SJordan.Brown@Sun.COM 				    strcmp(df1[i].sid, df2[j].sid) == 0) {
8068671SJulian.Pullen@Sun.COM 					match = B_TRUE;
8078361SJulian.Pullen@Sun.COM 					break;
8088361SJulian.Pullen@Sun.COM 				}
8098361SJulian.Pullen@Sun.COM 			}
8108361SJulian.Pullen@Sun.COM 			if (!match)
8118361SJulian.Pullen@Sun.COM 				return (1);
8128361SJulian.Pullen@Sun.COM 		}
8138361SJulian.Pullen@Sun.COM 	}
8148361SJulian.Pullen@Sun.COM 	return (0);
8158361SJulian.Pullen@Sun.COM }
8168361SJulian.Pullen@Sun.COM 
8178361SJulian.Pullen@Sun.COM 
8188361SJulian.Pullen@Sun.COM 
8198361SJulian.Pullen@Sun.COM /*
8208361SJulian.Pullen@Sun.COM  * This function updates trusted forest structure.
8218361SJulian.Pullen@Sun.COM  * If nothing has changed it returns 0 else 1
8228361SJulian.Pullen@Sun.COM  */
8238361SJulian.Pullen@Sun.COM static int
8248361SJulian.Pullen@Sun.COM update_trusted_forest(idmap_trustedforest_t **value, int *num_value,
8258361SJulian.Pullen@Sun.COM 			idmap_trustedforest_t **new, int *num_new, char *name)
8268361SJulian.Pullen@Sun.COM {
8278361SJulian.Pullen@Sun.COM 	int i, j;
8288671SJulian.Pullen@Sun.COM 	boolean_t match;
8298361SJulian.Pullen@Sun.COM 
8308361SJulian.Pullen@Sun.COM 	if (*value == *new)
8318361SJulian.Pullen@Sun.COM 		/* Nothing to do */
8328361SJulian.Pullen@Sun.COM 		return (0);
8338361SJulian.Pullen@Sun.COM 
8348361SJulian.Pullen@Sun.COM 	if (*value != NULL && *new != NULL) {
8358361SJulian.Pullen@Sun.COM 		if (*num_value != *num_new)
8368361SJulian.Pullen@Sun.COM 			goto not_equal;
8378361SJulian.Pullen@Sun.COM 		for (i = 0; i < *num_value; i++) {
8388671SJulian.Pullen@Sun.COM 			match = B_FALSE;
8398361SJulian.Pullen@Sun.COM 			for (j = 0; j < *num_new; j++) {
8408361SJulian.Pullen@Sun.COM 				if (strcmp((*value)[i].forest_name,
8418361SJulian.Pullen@Sun.COM 				    (*new)[j].forest_name) == 0 &&
8428361SJulian.Pullen@Sun.COM 				    ad_disc_compare_ds(
8438361SJulian.Pullen@Sun.COM 				    (*value)[i].global_catalog,
84410122SJordan.Brown@Sun.COM 				    (*new)[j].global_catalog) == 0 &&
8458361SJulian.Pullen@Sun.COM 				    compare_trusteddomainsinforest(
8468361SJulian.Pullen@Sun.COM 				    (*value)[i].domains_in_forest,
84710122SJordan.Brown@Sun.COM 				    (*new)[j].domains_in_forest) == 0) {
8488671SJulian.Pullen@Sun.COM 					match = B_TRUE;
8498361SJulian.Pullen@Sun.COM 					break;
8508361SJulian.Pullen@Sun.COM 				}
8518361SJulian.Pullen@Sun.COM 			}
8528361SJulian.Pullen@Sun.COM 			if (!match)
8538361SJulian.Pullen@Sun.COM 				goto not_equal;
8548361SJulian.Pullen@Sun.COM 		}
8558361SJulian.Pullen@Sun.COM 		free_trusted_forests(new, num_new);
8568361SJulian.Pullen@Sun.COM 		return (0);
8578361SJulian.Pullen@Sun.COM 	}
8588361SJulian.Pullen@Sun.COM not_equal:
8598361SJulian.Pullen@Sun.COM 	if (*value != NULL)
8608361SJulian.Pullen@Sun.COM 		free_trusted_forests(value, num_value);
8618361SJulian.Pullen@Sun.COM 	*value = *new;
8628361SJulian.Pullen@Sun.COM 	*num_value = *num_new;
8638361SJulian.Pullen@Sun.COM 	*new = NULL;
8648361SJulian.Pullen@Sun.COM 	*num_new = 0;
8658361SJulian.Pullen@Sun.COM 
8668361SJulian.Pullen@Sun.COM 	if (*value == NULL) {
8678361SJulian.Pullen@Sun.COM 		/* We're unsetting this DS property */
8688361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_INFO, "change %s=<none>", name);
8698361SJulian.Pullen@Sun.COM 		return (1);
8708361SJulian.Pullen@Sun.COM 	}
8718361SJulian.Pullen@Sun.COM 
8728361SJulian.Pullen@Sun.COM 	/* List all the trusted forests */
8738361SJulian.Pullen@Sun.COM 	for (i = 0; i < *num_value; i++) {
8748361SJulian.Pullen@Sun.COM 		for (j = 0; (*value)[i].domains_in_forest[j].domain[0] != '\0';
8758361SJulian.Pullen@Sun.COM 		    j++) {
8768361SJulian.Pullen@Sun.COM 			/* List trusted Domains in the forest. */
8778361SJulian.Pullen@Sun.COM 			if ((*value)[i].domains_in_forest[j].trusted)
8788361SJulian.Pullen@Sun.COM 				idmapdlog(LOG_INFO, "change %s=%s domain=%s",
8798361SJulian.Pullen@Sun.COM 				    name, (*value)[i].forest_name,
8808361SJulian.Pullen@Sun.COM 				    (*value)[i].domains_in_forest[j].domain);
8818361SJulian.Pullen@Sun.COM 		}
8828361SJulian.Pullen@Sun.COM 		/* List the hosts */
8838361SJulian.Pullen@Sun.COM 		for (j = 0; (*value)[i].global_catalog[j].host[0] != '\0'; j++)
8848361SJulian.Pullen@Sun.COM 			idmapdlog(LOG_INFO, "change %s=%s host=%s port=%d",
8858361SJulian.Pullen@Sun.COM 			    name, (*value)[i].forest_name,
8868361SJulian.Pullen@Sun.COM 			    (*value)[i].global_catalog[j].host,
8878361SJulian.Pullen@Sun.COM 			    (*value)[i].global_catalog[j].port);
8888361SJulian.Pullen@Sun.COM 	}
8898361SJulian.Pullen@Sun.COM 	return (1);
8908361SJulian.Pullen@Sun.COM }
8918361SJulian.Pullen@Sun.COM 
89210504SKeyur.Desai@Sun.COM const char *
89310504SKeyur.Desai@Sun.COM enum_lookup(int value, struct enum_lookup_map *map)
89410504SKeyur.Desai@Sun.COM {
89510504SKeyur.Desai@Sun.COM 	for (; map->string != NULL; map++) {
89610504SKeyur.Desai@Sun.COM 		if (value == map->value) {
89710504SKeyur.Desai@Sun.COM 			return (map->string);
89810504SKeyur.Desai@Sun.COM 		}
89910504SKeyur.Desai@Sun.COM 	}
90010504SKeyur.Desai@Sun.COM 	return ("(invalid)");
90110504SKeyur.Desai@Sun.COM }
9025317Sjp151216 
9035317Sjp151216 /*
9045968Snw141292  * Returns 1 if the PF_ROUTE socket event indicates that we should rescan the
9055968Snw141292  * interfaces.
9065317Sjp151216  *
9075968Snw141292  * Shamelessly based on smb_nics_changed() and other PF_ROUTE uses in ON.
9085968Snw141292  */
9095968Snw141292 static
910*12065SKeyur.Desai@Sun.COM boolean_t
9115968Snw141292 pfroute_event_is_interesting(int rt_sock)
9125968Snw141292 {
9135968Snw141292 	int nbytes;
9145968Snw141292 	int64_t msg[2048 / 8];
9155968Snw141292 	struct rt_msghdr *rtm;
916*12065SKeyur.Desai@Sun.COM 	boolean_t is_interesting = B_FALSE;
9175968Snw141292 
9185968Snw141292 	for (;;) {
9195968Snw141292 		if ((nbytes = read(rt_sock, msg, sizeof (msg))) <= 0)
9205968Snw141292 			break;
9215968Snw141292 		rtm = (struct rt_msghdr *)msg;
9225968Snw141292 		if (rtm->rtm_version != RTM_VERSION)
9235968Snw141292 			continue;
9245968Snw141292 		if (nbytes < rtm->rtm_msglen)
9255968Snw141292 			continue;
9265968Snw141292 		switch (rtm->rtm_type) {
9275968Snw141292 		case RTM_NEWADDR:
9285968Snw141292 		case RTM_DELADDR:
9295968Snw141292 		case RTM_IFINFO:
930*12065SKeyur.Desai@Sun.COM 			is_interesting = B_TRUE;
9315968Snw141292 			break;
9325968Snw141292 		default:
9335968Snw141292 			break;
9345968Snw141292 		}
9355968Snw141292 	}
9365968Snw141292 	return (is_interesting);
9375968Snw141292 }
9385968Snw141292 
9395968Snw141292 /*
940*12065SKeyur.Desai@Sun.COM  * Wait for an event, and report what kind of event occurred.
9415968Snw141292  *
942*12065SKeyur.Desai@Sun.COM  * Note that there are cases where we are awoken but don't care about
943*12065SKeyur.Desai@Sun.COM  * the lower-level event.  We can't just loop here because we can't
944*12065SKeyur.Desai@Sun.COM  * readily calculate how long to sleep the next time.  We return
945*12065SKeyur.Desai@Sun.COM  * EVENT_NOTHING and let the caller loop.
9465317Sjp151216  */
9475317Sjp151216 static
948*12065SKeyur.Desai@Sun.COM enum event_type
949*12065SKeyur.Desai@Sun.COM wait_for_event(struct timespec *timeoutp)
9505317Sjp151216 {
9515317Sjp151216 	port_event_t pe;
9525317Sjp151216 
9535968Snw141292 	memset(&pe, 0, sizeof (pe));
9546097Snw141292 	if (port_get(idmapd_ev_port, &pe, timeoutp) != 0) {
9555317Sjp151216 		switch (errno) {
9565317Sjp151216 		case EINTR:
957*12065SKeyur.Desai@Sun.COM 			return (EVENT_NOTHING);
9585317Sjp151216 		case ETIME:
9595317Sjp151216 			/* Timeout */
960*12065SKeyur.Desai@Sun.COM 			return (EVENT_TIMEOUT);
9615317Sjp151216 		default:
9625968Snw141292 			/* EBADF, EBADFD, EFAULT, EINVAL (end of time?)? */
9635968Snw141292 			idmapdlog(LOG_ERR, "Event port failed: %s",
9645968Snw141292 			    strerror(errno));
9655968Snw141292 			exit(1);
9665968Snw141292 			/* NOTREACHED */
9674520Snw141292 		}
9684520Snw141292 	}
9694520Snw141292 
970*12065SKeyur.Desai@Sun.COM 
971*12065SKeyur.Desai@Sun.COM 	switch (pe.portev_source) {
972*12065SKeyur.Desai@Sun.COM 	case 0:
973*12065SKeyur.Desai@Sun.COM 		/*
974*12065SKeyur.Desai@Sun.COM 		 * This isn't documented, but seems to be what you get if
975*12065SKeyur.Desai@Sun.COM 		 * the timeout is zero seconds and there are no events
976*12065SKeyur.Desai@Sun.COM 		 * pending.
977*12065SKeyur.Desai@Sun.COM 		 */
978*12065SKeyur.Desai@Sun.COM 		return (EVENT_TIMEOUT);
979*12065SKeyur.Desai@Sun.COM 
980*12065SKeyur.Desai@Sun.COM 	case PORT_SOURCE_USER:
981*12065SKeyur.Desai@Sun.COM 		if (pe.portev_events == POKE_AUTO_DISCOVERY)
982*12065SKeyur.Desai@Sun.COM 			return (EVENT_DEGRADE);
983*12065SKeyur.Desai@Sun.COM 		if (pe.portev_events == RECONFIGURE)
984*12065SKeyur.Desai@Sun.COM 			return (EVENT_REFRESH);
985*12065SKeyur.Desai@Sun.COM 		break;
9865317Sjp151216 
987*12065SKeyur.Desai@Sun.COM 	case PORT_SOURCE_FD:
988*12065SKeyur.Desai@Sun.COM 		if (pe.portev_object == rt_sock) {
989*12065SKeyur.Desai@Sun.COM 			/*
990*12065SKeyur.Desai@Sun.COM 			 * PF_ROUTE socket read event:
991*12065SKeyur.Desai@Sun.COM 			 *    re-associate fd
992*12065SKeyur.Desai@Sun.COM 			 *    handle event
993*12065SKeyur.Desai@Sun.COM 			 */
994*12065SKeyur.Desai@Sun.COM 			if (port_associate(idmapd_ev_port, PORT_SOURCE_FD,
995*12065SKeyur.Desai@Sun.COM 			    rt_sock, POLLIN, NULL) != 0) {
996*12065SKeyur.Desai@Sun.COM 				idmapdlog(LOG_ERR, "Failed to re-associate the "
997*12065SKeyur.Desai@Sun.COM 				    "routing socket with the event port: %s",
998*12065SKeyur.Desai@Sun.COM 				    strerror(errno));
999*12065SKeyur.Desai@Sun.COM 				abort();
1000*12065SKeyur.Desai@Sun.COM 			}
1001*12065SKeyur.Desai@Sun.COM 			/*
1002*12065SKeyur.Desai@Sun.COM 			 * The network configuration may still be in flux.
1003*12065SKeyur.Desai@Sun.COM 			 * No matter, the resolver will re-transmit and
1004*12065SKeyur.Desai@Sun.COM 			 * timeout if need be.
1005*12065SKeyur.Desai@Sun.COM 			 */
1006*12065SKeyur.Desai@Sun.COM 			if (pfroute_event_is_interesting(rt_sock)) {
1007*12065SKeyur.Desai@Sun.COM 				idmapdlog(LOG_DEBUG,
1008*12065SKeyur.Desai@Sun.COM 				    "Interesting routing event");
1009*12065SKeyur.Desai@Sun.COM 				return (EVENT_ROUTING);
1010*12065SKeyur.Desai@Sun.COM 			} else {
1011*12065SKeyur.Desai@Sun.COM 				idmapdlog(LOG_DEBUG,
1012*12065SKeyur.Desai@Sun.COM 				    "Boring routing event");
1013*12065SKeyur.Desai@Sun.COM 				return (EVENT_NOTHING);
1014*12065SKeyur.Desai@Sun.COM 			}
10155968Snw141292 		}
1016*12065SKeyur.Desai@Sun.COM 		/* Event on an FD other than the routing FD? Ignore it. */
1017*12065SKeyur.Desai@Sun.COM 		break;
10185968Snw141292 	}
10195968Snw141292 
1020*12065SKeyur.Desai@Sun.COM 	return (EVENT_NOTHING);
10215317Sjp151216 }
10225317Sjp151216 
10235317Sjp151216 void *
10245317Sjp151216 idmap_cfg_update_thread(void *arg)
10255317Sjp151216 {
10265317Sjp151216 
1027*12065SKeyur.Desai@Sun.COM 	const ad_disc_t		ad_ctx = _idmapdstate.cfg->handles.ad_ctx;
10285317Sjp151216 
1029*12065SKeyur.Desai@Sun.COM 	for (;;) {
1030*12065SKeyur.Desai@Sun.COM 		struct timespec timeout;
1031*12065SKeyur.Desai@Sun.COM 		struct timespec	*timeoutp;
1032*12065SKeyur.Desai@Sun.COM 		int		rc;
1033*12065SKeyur.Desai@Sun.COM 		int		ttl;
10345968Snw141292 
10355968Snw141292 		(void) ad_disc_SubnetChanged(ad_ctx);
10365317Sjp151216 
1037*12065SKeyur.Desai@Sun.COM 		rc = idmap_cfg_load(_idmapdstate.cfg, CFG_DISCOVER);
1038*12065SKeyur.Desai@Sun.COM 		if (rc < -1) {
10398671SJulian.Pullen@Sun.COM 			idmapdlog(LOG_ERR, "Fatal errors while reading "
10406097Snw141292 			    "SMF properties");
10416097Snw141292 			exit(1);
1042*12065SKeyur.Desai@Sun.COM 		} else if (rc == -1) {
1043*12065SKeyur.Desai@Sun.COM 			idmapdlog(LOG_WARNING,
1044*12065SKeyur.Desai@Sun.COM 			    "Errors re-loading configuration may cause AD "
1045*12065SKeyur.Desai@Sun.COM 			    "lookups to fail");
10465317Sjp151216 		}
10475317Sjp151216 
1048*12065SKeyur.Desai@Sun.COM 		/*
1049*12065SKeyur.Desai@Sun.COM 		 * Wait for an interesting event.  Note that we might get
1050*12065SKeyur.Desai@Sun.COM 		 * boring events between interesting events.  If so, we loop.
1051*12065SKeyur.Desai@Sun.COM 		 */
1052*12065SKeyur.Desai@Sun.COM 		for (;;) {
1053*12065SKeyur.Desai@Sun.COM 			ttl = ad_disc_get_TTL(ad_ctx);
1054*12065SKeyur.Desai@Sun.COM 
1055*12065SKeyur.Desai@Sun.COM 			if (ttl < 0) {
1056*12065SKeyur.Desai@Sun.COM 				timeoutp = NULL;
1057*12065SKeyur.Desai@Sun.COM 			} else {
1058*12065SKeyur.Desai@Sun.COM 				timeoutp = &timeout;
1059*12065SKeyur.Desai@Sun.COM 				timeout.tv_sec = ttl;
1060*12065SKeyur.Desai@Sun.COM 				timeout.tv_nsec = 0;
1061*12065SKeyur.Desai@Sun.COM 			}
1062*12065SKeyur.Desai@Sun.COM 
1063*12065SKeyur.Desai@Sun.COM 			switch (wait_for_event(timeoutp)) {
1064*12065SKeyur.Desai@Sun.COM 			case EVENT_NOTHING:
1065*12065SKeyur.Desai@Sun.COM 				idmapdlog(LOG_DEBUG, "Boring event.");
1066*12065SKeyur.Desai@Sun.COM 				continue;
1067*12065SKeyur.Desai@Sun.COM 			case EVENT_REFRESH:
1068*12065SKeyur.Desai@Sun.COM 				idmapdlog(LOG_INFO, "SMF refresh");
1069*12065SKeyur.Desai@Sun.COM 				/*
1070*12065SKeyur.Desai@Sun.COM 				 * Blow away the ccache, we might have
1071*12065SKeyur.Desai@Sun.COM 				 * re-joined the domain or joined a new one
1072*12065SKeyur.Desai@Sun.COM 				 */
1073*12065SKeyur.Desai@Sun.COM 				(void) unlink(IDMAP_CACHEDIR "/ccache");
1074*12065SKeyur.Desai@Sun.COM 				break;
1075*12065SKeyur.Desai@Sun.COM 			case EVENT_DEGRADE:
1076*12065SKeyur.Desai@Sun.COM 				idmapdlog(LOG_DEBUG,
1077*12065SKeyur.Desai@Sun.COM 				    "Service degraded");
1078*12065SKeyur.Desai@Sun.COM 				break;
1079*12065SKeyur.Desai@Sun.COM 			case EVENT_TIMEOUT:
1080*12065SKeyur.Desai@Sun.COM 				idmapdlog(LOG_DEBUG, "TTL expired");
1081*12065SKeyur.Desai@Sun.COM 				break;
1082*12065SKeyur.Desai@Sun.COM 			case EVENT_ROUTING:
1083*12065SKeyur.Desai@Sun.COM 				/* Already logged to DEBUG */
1084*12065SKeyur.Desai@Sun.COM 				break;
1085*12065SKeyur.Desai@Sun.COM 			}
1086*12065SKeyur.Desai@Sun.COM 			/* An interesting event! */
1087*12065SKeyur.Desai@Sun.COM 			break;
1088*12065SKeyur.Desai@Sun.COM 		}
10895317Sjp151216 	}
1090*12065SKeyur.Desai@Sun.COM 	/*
1091*12065SKeyur.Desai@Sun.COM 	 * Lint isn't happy with the concept of a function declared to
1092*12065SKeyur.Desai@Sun.COM 	 * return something, that doesn't return.  Of course, merely adding
1093*12065SKeyur.Desai@Sun.COM 	 * the return isn't enough, because it's never reached...
1094*12065SKeyur.Desai@Sun.COM 	 */
10955317Sjp151216 	/*NOTREACHED*/
10965317Sjp151216 	return (NULL);
10975317Sjp151216 }
10985317Sjp151216 
10995968Snw141292 int
11005968Snw141292 idmap_cfg_start_updates(void)
11015968Snw141292 {
11025968Snw141292 	if ((idmapd_ev_port = port_create()) < 0) {
11036017Snw141292 		idmapdlog(LOG_ERR, "Failed to create event port: %s",
11046017Snw141292 		    strerror(errno));
11055968Snw141292 		return (-1);
11065968Snw141292 	}
11075968Snw141292 
11085968Snw141292 	if ((rt_sock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
11096017Snw141292 		idmapdlog(LOG_ERR, "Failed to open routing socket: %s",
11106017Snw141292 		    strerror(errno));
11115968Snw141292 		(void) close(idmapd_ev_port);
11125968Snw141292 		return (-1);
11135968Snw141292 	}
11145317Sjp151216 
11155968Snw141292 	if (fcntl(rt_sock, F_SETFL, O_NDELAY|O_NONBLOCK) < 0) {
11166017Snw141292 		idmapdlog(LOG_ERR, "Failed to set routing socket flags: %s",
11176017Snw141292 		    strerror(errno));
11185968Snw141292 		(void) close(rt_sock);
11195968Snw141292 		(void) close(idmapd_ev_port);
11204520Snw141292 		return (-1);
11215968Snw141292 	}
11225968Snw141292 
11235968Snw141292 	if (port_associate(idmapd_ev_port, PORT_SOURCE_FD,
11245968Snw141292 	    rt_sock, POLLIN, NULL) != 0) {
11256017Snw141292 		idmapdlog(LOG_ERR, "Failed to associate the routing "
11266017Snw141292 		    "socket with the event port: %s", strerror(errno));
11275968Snw141292 		(void) close(rt_sock);
11285968Snw141292 		(void) close(idmapd_ev_port);
11295968Snw141292 		return (-1);
11305968Snw141292 	}
11315968Snw141292 
11325968Snw141292 	if ((errno = pthread_create(&update_thread_handle, NULL,
11335968Snw141292 	    idmap_cfg_update_thread, NULL)) != 0) {
11346017Snw141292 		idmapdlog(LOG_ERR, "Failed to start update thread: %s",
11356017Snw141292 		    strerror(errno));
11365968Snw141292 		(void) port_dissociate(idmapd_ev_port, PORT_SOURCE_FD, rt_sock);
11375968Snw141292 		(void) close(rt_sock);
11385968Snw141292 		(void) close(idmapd_ev_port);
11395968Snw141292 		return (-1);
11405968Snw141292 	}
11415968Snw141292 
11425968Snw141292 	return (0);
11435317Sjp151216 }
11445317Sjp151216 
11456097Snw141292 /*
11466616Sdm199847  * Reject attribute names with invalid characters.
11476616Sdm199847  */
11486616Sdm199847 static
11496616Sdm199847 int
11506616Sdm199847 valid_ldap_attr(const char *attr) {
11516616Sdm199847 	for (; *attr; attr++) {
11526616Sdm199847 		if (!isalnum(*attr) && *attr != '-' &&
11536616Sdm199847 		    *attr != '_' && *attr != '.' && *attr != ';')
11546616Sdm199847 			return (0);
11556616Sdm199847 	}
11566616Sdm199847 	return (1);
11576616Sdm199847 }
11586616Sdm199847 
115910504SKeyur.Desai@Sun.COM static
116010504SKeyur.Desai@Sun.COM int
116110504SKeyur.Desai@Sun.COM check_smf_debug_mode(idmap_cfg_handles_t *handles)
116210504SKeyur.Desai@Sun.COM {
116310504SKeyur.Desai@Sun.COM 	boolean_t new_debug_mode;
116410504SKeyur.Desai@Sun.COM 	int rc;
116510504SKeyur.Desai@Sun.COM 
116610504SKeyur.Desai@Sun.COM 	rc = prop_exists(handles, "debug", &new_debug_mode);
116710504SKeyur.Desai@Sun.COM 	if (rc != 0)
116810504SKeyur.Desai@Sun.COM 		return (rc);
116910504SKeyur.Desai@Sun.COM 
117010504SKeyur.Desai@Sun.COM 	if (_idmapdstate.debug_mode != new_debug_mode) {
117110504SKeyur.Desai@Sun.COM 		if (!_idmapdstate.debug_mode) {
117210504SKeyur.Desai@Sun.COM 			_idmapdstate.debug_mode = new_debug_mode;
117310504SKeyur.Desai@Sun.COM 			idmap_log_stderr(LOG_DEBUG);
117410504SKeyur.Desai@Sun.COM 			idmapdlog(LOG_DEBUG, "debug mode enabled");
117510504SKeyur.Desai@Sun.COM 		} else {
117610504SKeyur.Desai@Sun.COM 			idmapdlog(LOG_DEBUG, "debug mode disabled");
117710504SKeyur.Desai@Sun.COM 			idmap_log_stderr(-1);
117810504SKeyur.Desai@Sun.COM 			_idmapdstate.debug_mode = new_debug_mode;
117910504SKeyur.Desai@Sun.COM 		}
118010504SKeyur.Desai@Sun.COM 	}
118110504SKeyur.Desai@Sun.COM 
118210504SKeyur.Desai@Sun.COM 	return (0);
118310504SKeyur.Desai@Sun.COM }
118410504SKeyur.Desai@Sun.COM 
11856616Sdm199847 /*
11866097Snw141292  * This is the half of idmap_cfg_load() that loads property values from
11876097Snw141292  * SMF (using the config/ property group of the idmap FMRI).
11886097Snw141292  *
11896097Snw141292  * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
11906616Sdm199847  *               -3 -> hard smf config failures
11916097Snw141292  * reading from SMF.
11926097Snw141292  */
11936097Snw141292 static
11945317Sjp151216 int
11956097Snw141292 idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
119610504SKeyur.Desai@Sun.COM 	int * const errors)
11975317Sjp151216 {
11985447Snw141292 	int rc;
119910504SKeyur.Desai@Sun.COM 	char *s;
120010504SKeyur.Desai@Sun.COM 
120110504SKeyur.Desai@Sun.COM 	*errors = 0;
12025317Sjp151216 
12035317Sjp151216 	if (scf_pg_update(handles->config_pg) < 0) {
12046017Snw141292 		idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
12056017Snw141292 		    scf_strerror(scf_error()));
12066097Snw141292 		return (-2);
12075317Sjp151216 	}
12085317Sjp151216 
12095317Sjp151216 	if (scf_pg_update(handles->general_pg) < 0) {
12106017Snw141292 		idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
12116017Snw141292 		    scf_strerror(scf_error()));
12126097Snw141292 		return (-2);
12135317Sjp151216 	}
12145317Sjp151216 
121510504SKeyur.Desai@Sun.COM 	rc = check_smf_debug_mode(handles);
12166616Sdm199847 	if (rc != 0)
121710504SKeyur.Desai@Sun.COM 		(*errors)++;
12186017Snw141292 
12197031Snw141292 	rc = get_val_int(handles, "unresolvable_sid_mapping",
12207031Snw141292 	    &pgcfg->eph_map_unres_sids, SCF_TYPE_BOOLEAN);
12217031Snw141292 	if (rc != 0)
122210504SKeyur.Desai@Sun.COM 		(*errors)++;
122310504SKeyur.Desai@Sun.COM 
122410504SKeyur.Desai@Sun.COM 	rc = get_val_astring(handles, "directory_based_mapping", &s);
122510504SKeyur.Desai@Sun.COM 	if (rc != 0)
122610504SKeyur.Desai@Sun.COM 		(*errors)++;
122710504SKeyur.Desai@Sun.COM 	else if (s == NULL || strcasecmp(s, "none") == 0)
122810504SKeyur.Desai@Sun.COM 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
122910504SKeyur.Desai@Sun.COM 	else if (strcasecmp(s, "name") == 0)
123010504SKeyur.Desai@Sun.COM 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NAME;
123110504SKeyur.Desai@Sun.COM 	else if (strcasecmp(s, "idmu") == 0)
123210504SKeyur.Desai@Sun.COM 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_IDMU;
123310504SKeyur.Desai@Sun.COM 	else {
123410504SKeyur.Desai@Sun.COM 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
123510504SKeyur.Desai@Sun.COM 		idmapdlog(LOG_ERR,
123610504SKeyur.Desai@Sun.COM 		"config/directory_based_mapping:  invalid value \"%s\" ignored",
123710504SKeyur.Desai@Sun.COM 		    s);
123810504SKeyur.Desai@Sun.COM 		(*errors)++;
123910504SKeyur.Desai@Sun.COM 	}
124010504SKeyur.Desai@Sun.COM 	free(s);
12417031Snw141292 
12425317Sjp151216 	rc = get_val_int(handles, "list_size_limit",
12435317Sjp151216 	    &pgcfg->list_size_limit, SCF_TYPE_COUNT);
12447031Snw141292 	if (rc != 0)
124510504SKeyur.Desai@Sun.COM 		(*errors)++;
12465317Sjp151216 
12475317Sjp151216 	rc = get_val_astring(handles, "domain_name",
12485317Sjp151216 	    &pgcfg->domain_name);
12495447Snw141292 	if (rc != 0)
125010504SKeyur.Desai@Sun.COM 		(*errors)++;
12518361SJulian.Pullen@Sun.COM 	else {
12526097Snw141292 		(void) ad_disc_set_DomainName(handles->ad_ctx,
12536097Snw141292 		    pgcfg->domain_name);
12548671SJulian.Pullen@Sun.COM 		pgcfg->domain_name_auto_disc = B_FALSE;
12558361SJulian.Pullen@Sun.COM 	}
12565317Sjp151216 
12575317Sjp151216 	rc = get_val_astring(handles, "default_domain",
12585317Sjp151216 	    &pgcfg->default_domain);
12595317Sjp151216 	if (rc != 0) {
12605447Snw141292 		/*
12615447Snw141292 		 * SCF failures fetching config/default_domain we treat
12625447Snw141292 		 * as fatal as they may leave ID mapping rules that
12635447Snw141292 		 * match unqualified winnames flapping in the wind.
12645447Snw141292 		 */
12656097Snw141292 		return (-2);
12665317Sjp151216 	}
12675317Sjp151216 
126810504SKeyur.Desai@Sun.COM 	if (pgcfg->default_domain == NULL && pgcfg->domain_name != NULL) {
126910504SKeyur.Desai@Sun.COM 		pgcfg->default_domain = strdup(pgcfg->domain_name);
12704695Sbaban 	}
12714520Snw141292 
12725317Sjp151216 	rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid);
12735447Snw141292 	if (rc != 0)
127410504SKeyur.Desai@Sun.COM 		(*errors)++;
12755317Sjp151216 	if (pgcfg->machine_sid == NULL) {
12765317Sjp151216 		/* If machine_sid not configured, generate one */
12776097Snw141292 		if (generate_machine_sid(&pgcfg->machine_sid) < 0)
12786097Snw141292 			return (-2);
12795317Sjp151216 		rc = set_val_astring(handles, "machine_sid",
12805317Sjp151216 		    pgcfg->machine_sid);
12815447Snw141292 		if (rc != 0)
128210504SKeyur.Desai@Sun.COM 			(*errors)++;
12835317Sjp151216 	}
12845317Sjp151216 
12855317Sjp151216 	rc = get_val_ds(handles, "domain_controller", 389,
12865317Sjp151216 	    &pgcfg->domain_controller);
12875447Snw141292 	if (rc != 0)
128810504SKeyur.Desai@Sun.COM 		(*errors)++;
12898361SJulian.Pullen@Sun.COM 	else {
12906097Snw141292 		(void) ad_disc_set_DomainController(handles->ad_ctx,
12915447Snw141292 		    pgcfg->domain_controller);
12928671SJulian.Pullen@Sun.COM 		pgcfg->domain_controller_auto_disc = B_FALSE;
12938361SJulian.Pullen@Sun.COM 	}
12945317Sjp151216 
12955317Sjp151216 	rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name);
12965447Snw141292 	if (rc != 0)
129710504SKeyur.Desai@Sun.COM 		(*errors)++;
12988361SJulian.Pullen@Sun.COM 	else {
12996097Snw141292 		(void) ad_disc_set_ForestName(handles->ad_ctx,
13006097Snw141292 		    pgcfg->forest_name);
13018671SJulian.Pullen@Sun.COM 		pgcfg->forest_name_auto_disc = B_FALSE;
13028361SJulian.Pullen@Sun.COM 	}
13035317Sjp151216 
13045317Sjp151216 	rc = get_val_astring(handles, "site_name", &pgcfg->site_name);
13055447Snw141292 	if (rc != 0)
130610504SKeyur.Desai@Sun.COM 		(*errors)++;
13075447Snw141292 	else
13086097Snw141292 		(void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name);
13095317Sjp151216 
13105317Sjp151216 	rc = get_val_ds(handles, "global_catalog", 3268,
13115317Sjp151216 	    &pgcfg->global_catalog);
13125447Snw141292 	if (rc != 0)
131310504SKeyur.Desai@Sun.COM 		(*errors)++;
13148361SJulian.Pullen@Sun.COM 	else {
13156097Snw141292 		(void) ad_disc_set_GlobalCatalog(handles->ad_ctx,
13166097Snw141292 		    pgcfg->global_catalog);
13178671SJulian.Pullen@Sun.COM 		pgcfg->global_catalog_auto_disc = B_FALSE;
13188361SJulian.Pullen@Sun.COM 	}
13195447Snw141292 
132010504SKeyur.Desai@Sun.COM 	/* Unless we're doing directory-based name mapping, we're done. */
132110504SKeyur.Desai@Sun.COM 	if (pgcfg->directory_based_mapping != DIRECTORY_MAPPING_NAME)
132210504SKeyur.Desai@Sun.COM 		return (0);
13236097Snw141292 
13246097Snw141292 	rc = get_val_astring(handles, "ad_unixuser_attr",
13256097Snw141292 	    &pgcfg->ad_unixuser_attr);
13266097Snw141292 	if (rc != 0)
13276097Snw141292 		return (-2);
13286616Sdm199847 	if (pgcfg->ad_unixuser_attr != NULL &&
13296616Sdm199847 	    !valid_ldap_attr(pgcfg->ad_unixuser_attr)) {
13306616Sdm199847 		idmapdlog(LOG_ERR, "config/ad_unixuser_attr=%s is not a "
13316616Sdm199847 		    "valid LDAP attribute name", pgcfg->ad_unixuser_attr);
13326616Sdm199847 		return (-3);
13336616Sdm199847 	}
13346097Snw141292 
13356097Snw141292 	rc = get_val_astring(handles, "ad_unixgroup_attr",
13366097Snw141292 	    &pgcfg->ad_unixgroup_attr);
13376097Snw141292 	if (rc != 0)
13386097Snw141292 		return (-2);
13396616Sdm199847 	if (pgcfg->ad_unixgroup_attr != NULL &&
13406616Sdm199847 	    !valid_ldap_attr(pgcfg->ad_unixgroup_attr)) {
13416616Sdm199847 		idmapdlog(LOG_ERR, "config/ad_unixgroup_attr=%s is not a "
13426616Sdm199847 		    "valid LDAP attribute name", pgcfg->ad_unixgroup_attr);
13436616Sdm199847 		return (-3);
13446616Sdm199847 	}
13455731Sbaban 
13466097Snw141292 	rc = get_val_astring(handles, "nldap_winname_attr",
13476097Snw141292 	    &pgcfg->nldap_winname_attr);
13486097Snw141292 	if (rc != 0)
13496097Snw141292 		return (-2);
13506616Sdm199847 	if (pgcfg->nldap_winname_attr != NULL &&
13516616Sdm199847 	    !valid_ldap_attr(pgcfg->nldap_winname_attr)) {
13526616Sdm199847 		idmapdlog(LOG_ERR, "config/nldap_winname_attr=%s is not a "
13536616Sdm199847 		    "valid LDAP attribute name", pgcfg->nldap_winname_attr);
13546097Snw141292 		return (-3);
13556097Snw141292 	}
13566097Snw141292 	if (pgcfg->ad_unixuser_attr == NULL &&
13576616Sdm199847 	    pgcfg->ad_unixgroup_attr == NULL &&
13586616Sdm199847 	    pgcfg->nldap_winname_attr == NULL) {
13596097Snw141292 		idmapdlog(LOG_ERR,
136010504SKeyur.Desai@Sun.COM 		    "If config/directory_based_mapping property is set to "
136110504SKeyur.Desai@Sun.COM 		    "\"name\" then at least one of the following name mapping "
13626097Snw141292 		    "attributes must be specified. (config/ad_unixuser_attr OR "
13636616Sdm199847 		    "config/ad_unixgroup_attr OR config/nldap_winname_attr)");
13646097Snw141292 		return (-3);
13655731Sbaban 	}
13665731Sbaban 
13676097Snw141292 	return (rc);
13685447Snw141292 
13696097Snw141292 }
13705317Sjp151216 
13718361SJulian.Pullen@Sun.COM 
13726097Snw141292 /*
13736097Snw141292  * This is the half of idmap_cfg_load() that auto-discovers values of
13746097Snw141292  * discoverable properties that weren't already set via SMF properties.
13756097Snw141292  *
13766097Snw141292  * idmap_cfg_discover() is called *after* idmap_cfg_load_smf(), so it
13776097Snw141292  * needs to be careful not to overwrite any properties set in SMF.
13786097Snw141292  */
13796097Snw141292 static
13806097Snw141292 void
13816097Snw141292 idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
13826097Snw141292 {
13836097Snw141292 	ad_disc_t ad_ctx = handles->ad_ctx;
13848361SJulian.Pullen@Sun.COM 	ad_disc_t trusted_ctx;
13858361SJulian.Pullen@Sun.COM 	int i, j, k, l;
13868361SJulian.Pullen@Sun.COM 	char *forestname;
13878361SJulian.Pullen@Sun.COM 	int num_trusteddomains;
13888671SJulian.Pullen@Sun.COM 	boolean_t new_forest;
13898361SJulian.Pullen@Sun.COM 	char *trusteddomain;
13908361SJulian.Pullen@Sun.COM 	idmap_ad_disc_ds_t *globalcatalog;
13918361SJulian.Pullen@Sun.COM 	idmap_trustedforest_t *trustedforests;
13928361SJulian.Pullen@Sun.COM 	ad_disc_domainsinforest_t *domainsinforest;
13936097Snw141292 
1394*12065SKeyur.Desai@Sun.COM 	idmapdlog(LOG_DEBUG, "Running discovery.");
1395*12065SKeyur.Desai@Sun.COM 
13966097Snw141292 	ad_disc_refresh(ad_ctx);
13976097Snw141292 
13986097Snw141292 	if (pgcfg->default_domain == NULL)
13998361SJulian.Pullen@Sun.COM 		pgcfg->default_domain = ad_disc_get_DomainName(ad_ctx,
14008361SJulian.Pullen@Sun.COM 		    NULL);
14015317Sjp151216 
14026097Snw141292 	if (pgcfg->domain_name == NULL)
14038361SJulian.Pullen@Sun.COM 		pgcfg->domain_name = ad_disc_get_DomainName(ad_ctx,
14048361SJulian.Pullen@Sun.COM 		    &pgcfg->domain_name_auto_disc);
14055317Sjp151216 
14066097Snw141292 	if (pgcfg->domain_controller == NULL)
14075317Sjp151216 		pgcfg->domain_controller =
14088361SJulian.Pullen@Sun.COM 		    ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE,
14098361SJulian.Pullen@Sun.COM 		    &pgcfg->domain_controller_auto_disc);
14106097Snw141292 
14116097Snw141292 	if (pgcfg->forest_name == NULL)
14128361SJulian.Pullen@Sun.COM 		pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx,
14138361SJulian.Pullen@Sun.COM 		    &pgcfg->forest_name_auto_disc);
14146097Snw141292 
14156097Snw141292 	if (pgcfg->site_name == NULL)
14168361SJulian.Pullen@Sun.COM 		pgcfg->site_name = ad_disc_get_SiteName(ad_ctx,
14178361SJulian.Pullen@Sun.COM 		    &pgcfg->site_name_auto_disc);
14186097Snw141292 
14196097Snw141292 	if (pgcfg->global_catalog == NULL)
14206097Snw141292 		pgcfg->global_catalog =
14218361SJulian.Pullen@Sun.COM 		    ad_disc_get_GlobalCatalog(ad_ctx, AD_DISC_PREFER_SITE,
14228361SJulian.Pullen@Sun.COM 		    &pgcfg->global_catalog_auto_disc);
14238361SJulian.Pullen@Sun.COM 
14248361SJulian.Pullen@Sun.COM 	pgcfg->domains_in_forest =
14258361SJulian.Pullen@Sun.COM 	    ad_disc_get_DomainsInForest(ad_ctx, NULL);
14268361SJulian.Pullen@Sun.COM 
14278361SJulian.Pullen@Sun.COM 	pgcfg->trusted_domains =
14288361SJulian.Pullen@Sun.COM 	    ad_disc_get_TrustedDomains(ad_ctx, NULL);
14298361SJulian.Pullen@Sun.COM 
14308361SJulian.Pullen@Sun.COM 	if (pgcfg->forest_name != NULL && pgcfg->trusted_domains != NULL &&
14318361SJulian.Pullen@Sun.COM 	    pgcfg->trusted_domains[0].domain[0] != '\0') {
14328361SJulian.Pullen@Sun.COM 		/*
14338361SJulian.Pullen@Sun.COM 		 * We have trusted domains.  We need to go through every
14348361SJulian.Pullen@Sun.COM 		 * one and find its forest. If it is a new forest we then need
14358361SJulian.Pullen@Sun.COM 		 * to find its Global Catalog and the domains in the forest
14368361SJulian.Pullen@Sun.COM 		 */
14378361SJulian.Pullen@Sun.COM 		for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++)
14388361SJulian.Pullen@Sun.COM 			continue;
14398361SJulian.Pullen@Sun.COM 		num_trusteddomains = i;
14408361SJulian.Pullen@Sun.COM 
14418361SJulian.Pullen@Sun.COM 		trustedforests = calloc(num_trusteddomains,
14428361SJulian.Pullen@Sun.COM 		    sizeof (idmap_trustedforest_t));
14438361SJulian.Pullen@Sun.COM 		j = 0;
14448361SJulian.Pullen@Sun.COM 		for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) {
14458361SJulian.Pullen@Sun.COM 			trusteddomain = pgcfg->trusted_domains[i].domain;
14468361SJulian.Pullen@Sun.COM 			trusted_ctx = ad_disc_init();
14478361SJulian.Pullen@Sun.COM 			ad_disc_set_DomainName(trusted_ctx,
14488361SJulian.Pullen@Sun.COM 			    trusteddomain);
14498361SJulian.Pullen@Sun.COM 			forestname =
14508361SJulian.Pullen@Sun.COM 			    ad_disc_get_ForestName(trusted_ctx, NULL);
14518361SJulian.Pullen@Sun.COM 			if (forestname == NULL) {
14528361SJulian.Pullen@Sun.COM 				idmapdlog(LOG_DEBUG, "unable to discover "
14538361SJulian.Pullen@Sun.COM 				    "Forest Name for the trusted domain %s",
14548361SJulian.Pullen@Sun.COM 				    trusteddomain);
14558361SJulian.Pullen@Sun.COM 				ad_disc_fini(trusted_ctx);
14568361SJulian.Pullen@Sun.COM 				continue;
14578361SJulian.Pullen@Sun.COM 			}
14588361SJulian.Pullen@Sun.COM 
14598361SJulian.Pullen@Sun.COM 			if (strcasecmp(forestname, pgcfg->forest_name) == 0) {
14608361SJulian.Pullen@Sun.COM 				/*
14618361SJulian.Pullen@Sun.COM 				 * Ignore the domain as it is part of
14628361SJulian.Pullen@Sun.COM 				 * the primary forest
14638361SJulian.Pullen@Sun.COM 				 */
14648361SJulian.Pullen@Sun.COM 				free(forestname);
14658361SJulian.Pullen@Sun.COM 				ad_disc_fini(trusted_ctx);
14668361SJulian.Pullen@Sun.COM 				continue;
14678361SJulian.Pullen@Sun.COM 			}
14688361SJulian.Pullen@Sun.COM 
14698361SJulian.Pullen@Sun.COM 			/* Is this a new forest? */
14708671SJulian.Pullen@Sun.COM 			new_forest = B_TRUE;
14718361SJulian.Pullen@Sun.COM 			for (k = 0; k < j; k++) {
14728361SJulian.Pullen@Sun.COM 				if (strcasecmp(forestname,
14738361SJulian.Pullen@Sun.COM 				    trustedforests[k].forest_name) == 0) {
14748671SJulian.Pullen@Sun.COM 					new_forest = B_FALSE;
14758361SJulian.Pullen@Sun.COM 					domainsinforest =
14768361SJulian.Pullen@Sun.COM 					    trustedforests[k].domains_in_forest;
14778361SJulian.Pullen@Sun.COM 					break;
14788361SJulian.Pullen@Sun.COM 				}
14798361SJulian.Pullen@Sun.COM 			}
14808361SJulian.Pullen@Sun.COM 			if (!new_forest) {
14818361SJulian.Pullen@Sun.COM 				/* Mark the domain as trusted */
14828361SJulian.Pullen@Sun.COM 				for (l = 0;
14838361SJulian.Pullen@Sun.COM 				    domainsinforest[l].domain[0] != '\0'; l++) {
148410122SJordan.Brown@Sun.COM 					if (domain_eq(trusteddomain,
148510122SJordan.Brown@Sun.COM 					    domainsinforest[l].domain)) {
14868361SJulian.Pullen@Sun.COM 						domainsinforest[l].trusted =
14878361SJulian.Pullen@Sun.COM 						    TRUE;
14888361SJulian.Pullen@Sun.COM 						break;
14898361SJulian.Pullen@Sun.COM 					}
14908361SJulian.Pullen@Sun.COM 				}
14918361SJulian.Pullen@Sun.COM 				free(forestname);
14928361SJulian.Pullen@Sun.COM 				ad_disc_fini(trusted_ctx);
14938361SJulian.Pullen@Sun.COM 				continue;
14948361SJulian.Pullen@Sun.COM 			}
14958361SJulian.Pullen@Sun.COM 
14968361SJulian.Pullen@Sun.COM 			/*
14978361SJulian.Pullen@Sun.COM 			 * Get the Global Catalog and the domains in
14988361SJulian.Pullen@Sun.COM 			 * this new forest.
14998361SJulian.Pullen@Sun.COM 			 */
15008361SJulian.Pullen@Sun.COM 			globalcatalog =
15018361SJulian.Pullen@Sun.COM 			    ad_disc_get_GlobalCatalog(trusted_ctx,
15028361SJulian.Pullen@Sun.COM 			    AD_DISC_PREFER_SITE, NULL);
15038361SJulian.Pullen@Sun.COM 			if (globalcatalog == NULL) {
15048361SJulian.Pullen@Sun.COM 				idmapdlog(LOG_DEBUG,
15058361SJulian.Pullen@Sun.COM 				    "unable to discover Global "
15068361SJulian.Pullen@Sun.COM 				    "Catalog for the trusted domain %s",
15078361SJulian.Pullen@Sun.COM 				    trusteddomain);
15088361SJulian.Pullen@Sun.COM 				free(forestname);
15098361SJulian.Pullen@Sun.COM 				ad_disc_fini(trusted_ctx);
15108361SJulian.Pullen@Sun.COM 				continue;
15118361SJulian.Pullen@Sun.COM 			}
15128361SJulian.Pullen@Sun.COM 			domainsinforest =
15138361SJulian.Pullen@Sun.COM 			    ad_disc_get_DomainsInForest(trusted_ctx,
15148361SJulian.Pullen@Sun.COM 			    NULL);
15158361SJulian.Pullen@Sun.COM 			if (domainsinforest == NULL) {
15168361SJulian.Pullen@Sun.COM 				idmapdlog(LOG_DEBUG,
15178361SJulian.Pullen@Sun.COM 				    "unable to discover Domains in the Forest "
15188361SJulian.Pullen@Sun.COM 				    "for the trusted domain %s",
15198361SJulian.Pullen@Sun.COM 				    trusteddomain);
15208361SJulian.Pullen@Sun.COM 				free(globalcatalog);
15218361SJulian.Pullen@Sun.COM 				free(forestname);
15228361SJulian.Pullen@Sun.COM 				ad_disc_fini(trusted_ctx);
15238361SJulian.Pullen@Sun.COM 				continue;
15248361SJulian.Pullen@Sun.COM 			}
15258361SJulian.Pullen@Sun.COM 
15268361SJulian.Pullen@Sun.COM 			trustedforests[j].forest_name = forestname;
15278361SJulian.Pullen@Sun.COM 			trustedforests[j].global_catalog = globalcatalog;
15288361SJulian.Pullen@Sun.COM 			trustedforests[j].domains_in_forest = domainsinforest;
15298361SJulian.Pullen@Sun.COM 			j++;
15308361SJulian.Pullen@Sun.COM 			/* Mark the domain as trusted */
15318361SJulian.Pullen@Sun.COM 			for (l = 0; domainsinforest[l].domain[0] != '\0';
15328361SJulian.Pullen@Sun.COM 			    l++) {
153310122SJordan.Brown@Sun.COM 				if (domain_eq(trusteddomain,
153410122SJordan.Brown@Sun.COM 				    domainsinforest[l].domain)) {
15358361SJulian.Pullen@Sun.COM 					domainsinforest[l].trusted = TRUE;
15368361SJulian.Pullen@Sun.COM 					break;
15378361SJulian.Pullen@Sun.COM 				}
15388361SJulian.Pullen@Sun.COM 			}
15398361SJulian.Pullen@Sun.COM 			ad_disc_fini(trusted_ctx);
15408361SJulian.Pullen@Sun.COM 		}
15418361SJulian.Pullen@Sun.COM 		if (j > 0) {
15428361SJulian.Pullen@Sun.COM 			pgcfg->num_trusted_forests = j;
15438361SJulian.Pullen@Sun.COM 			pgcfg->trusted_forests = trustedforests;
154410122SJordan.Brown@Sun.COM 		} else {
154510122SJordan.Brown@Sun.COM 			free(trustedforests);
15468361SJulian.Pullen@Sun.COM 		}
15478361SJulian.Pullen@Sun.COM 	}
15486097Snw141292 
15496097Snw141292 	if (pgcfg->domain_name == NULL)
15506097Snw141292 		idmapdlog(LOG_DEBUG, "unable to discover Domain Name");
15516097Snw141292 	if (pgcfg->domain_controller == NULL)
15526097Snw141292 		idmapdlog(LOG_DEBUG, "unable to discover Domain Controller");
15536097Snw141292 	if (pgcfg->forest_name == NULL)
15546097Snw141292 		idmapdlog(LOG_DEBUG, "unable to discover Forest Name");
15556097Snw141292 	if (pgcfg->site_name == NULL)
15566097Snw141292 		idmapdlog(LOG_DEBUG, "unable to discover Site Name");
15576097Snw141292 	if (pgcfg->global_catalog == NULL)
15586097Snw141292 		idmapdlog(LOG_DEBUG, "unable to discover Global Catalog");
15598361SJulian.Pullen@Sun.COM 	if (pgcfg->domains_in_forest == NULL)
15608361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_DEBUG,
15618361SJulian.Pullen@Sun.COM 		    "unable to discover Domains in the Forest");
15628361SJulian.Pullen@Sun.COM 	if (pgcfg->trusted_domains == NULL)
15638361SJulian.Pullen@Sun.COM 		idmapdlog(LOG_DEBUG, "unable to discover Trusted Domains");
1564*12065SKeyur.Desai@Sun.COM 
1565*12065SKeyur.Desai@Sun.COM 	ad_disc_done(ad_ctx);
1566*12065SKeyur.Desai@Sun.COM 	idmapdlog(LOG_DEBUG, "Discovery done.");
15676097Snw141292 }
15685317Sjp151216 
15698361SJulian.Pullen@Sun.COM 
15706097Snw141292 /*
15716097Snw141292  * idmap_cfg_load() is called at startup, and periodically via the
15726097Snw141292  * update thread when the auto-discovery TTLs expire, as well as part of
15736097Snw141292  * the refresh method, to update the current configuration.  It always
15746097Snw141292  * reads from SMF, but you still have to refresh the service after
15756097Snw141292  * changing the config pg in order for the changes to take effect.
15766097Snw141292  *
15776097Snw141292  * There are two flags:
15786097Snw141292  *
15796097Snw141292  *  - CFG_DISCOVER
15806097Snw141292  *  - CFG_LOG
15816097Snw141292  *
15826097Snw141292  * If CFG_DISCOVER is set then idmap_cfg_load() calls
15836097Snw141292  * idmap_cfg_discover() to discover, via DNS and LDAP lookups, property
15846097Snw141292  * values that weren't set in SMF.
15856097Snw141292  *
15866097Snw141292  * If CFG_LOG is set then idmap_cfg_load() will log (to LOG_NOTICE)
15876097Snw141292  * whether the configuration changed.  This should be used only from the
15886097Snw141292  * refresh method.
15896097Snw141292  *
15906097Snw141292  * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
15916097Snw141292  * reading from SMF.
15926097Snw141292  */
15936097Snw141292 int
15946097Snw141292 idmap_cfg_load(idmap_cfg_t *cfg, int flags)
15956097Snw141292 {
15966097Snw141292 	int rc = 0;
159710504SKeyur.Desai@Sun.COM 	int errors;
15986097Snw141292 	int changed = 0;
15998361SJulian.Pullen@Sun.COM 	int ad_reload_required = 0;
16006097Snw141292 	idmap_pg_config_t new_pgcfg, *live_pgcfg;
16016097Snw141292 
16026097Snw141292 	live_pgcfg = &cfg->pgcfg;
16036097Snw141292 	(void) memset(&new_pgcfg, 0, sizeof (new_pgcfg));
16046097Snw141292 
16056097Snw141292 	pthread_mutex_lock(&cfg->handles.mutex);
16066097Snw141292 
16076097Snw141292 	if ((rc = idmap_cfg_load_smf(&cfg->handles, &new_pgcfg, &errors)) < -1)
16086097Snw141292 		goto err;
16096097Snw141292 
16106097Snw141292 	if (flags & CFG_DISCOVER)
16116097Snw141292 		idmap_cfg_discover(&cfg->handles, &new_pgcfg);
16126097Snw141292 
16136097Snw141292 	WRLOCK_CONFIG();
16146097Snw141292 	if (live_pgcfg->list_size_limit != new_pgcfg.list_size_limit) {
16156097Snw141292 		idmapdlog(LOG_INFO, "change list_size=%d",
16166097Snw141292 		    new_pgcfg.list_size_limit);
16176097Snw141292 		live_pgcfg->list_size_limit = new_pgcfg.list_size_limit;
16185317Sjp151216 	}
16195317Sjp151216 
16206097Snw141292 	/* Non-discoverable props updated here */
16217031Snw141292 	changed += update_string(&live_pgcfg->machine_sid,
16226097Snw141292 	    &new_pgcfg.machine_sid, "machine_sid");
16236097Snw141292 
16247031Snw141292 	changed += update_bool(&live_pgcfg->eph_map_unres_sids,
16257031Snw141292 	    &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping");
16267031Snw141292 
162710504SKeyur.Desai@Sun.COM 	changed += update_enum(&live_pgcfg->directory_based_mapping,
162810504SKeyur.Desai@Sun.COM 	    &new_pgcfg.directory_based_mapping, "directory_based_mapping",
162910504SKeyur.Desai@Sun.COM 	    directory_mapping_map);
16306097Snw141292 
16317031Snw141292 	changed += update_string(&live_pgcfg->ad_unixuser_attr,
16326097Snw141292 	    &new_pgcfg.ad_unixuser_attr, "ad_unixuser_attr");
16336097Snw141292 
16347031Snw141292 	changed += update_string(&live_pgcfg->ad_unixgroup_attr,
16356097Snw141292 	    &new_pgcfg.ad_unixgroup_attr, "ad_unixgroup_attr");
16366097Snw141292 
16377031Snw141292 	changed += update_string(&live_pgcfg->nldap_winname_attr,
16386097Snw141292 	    &new_pgcfg.nldap_winname_attr, "nldap_winname_attr");
16396097Snw141292 
16406097Snw141292 	/* Props that can be discovered and set in SMF updated here */
164110504SKeyur.Desai@Sun.COM 	changed += update_string(&live_pgcfg->default_domain,
164210504SKeyur.Desai@Sun.COM 	    &new_pgcfg.default_domain, "default_domain");
16436097Snw141292 
16447031Snw141292 	changed += update_string(&live_pgcfg->domain_name,
16456097Snw141292 	    &new_pgcfg.domain_name, "domain_name");
16468361SJulian.Pullen@Sun.COM 	live_pgcfg->domain_name_auto_disc = new_pgcfg.domain_name_auto_disc;
16476097Snw141292 
16486097Snw141292 	changed += update_dirs(&live_pgcfg->domain_controller,
16496097Snw141292 	    &new_pgcfg.domain_controller, "domain_controller");
16508361SJulian.Pullen@Sun.COM 	live_pgcfg->domain_controller_auto_disc =
16518361SJulian.Pullen@Sun.COM 	    new_pgcfg.domain_controller_auto_disc;
16526097Snw141292 
16537031Snw141292 	changed += update_string(&live_pgcfg->forest_name,
16546097Snw141292 	    &new_pgcfg.forest_name, "forest_name");
16558361SJulian.Pullen@Sun.COM 	live_pgcfg->forest_name_auto_disc = new_pgcfg.forest_name_auto_disc;
16566097Snw141292 
16577031Snw141292 	changed += update_string(&live_pgcfg->site_name,
16586097Snw141292 	    &new_pgcfg.site_name, "site_name");
16598361SJulian.Pullen@Sun.COM 	live_pgcfg->site_name_auto_disc = new_pgcfg.site_name_auto_disc;
16606097Snw141292 
16616097Snw141292 	if (update_dirs(&live_pgcfg->global_catalog,
16626097Snw141292 	    &new_pgcfg.global_catalog, "global_catalog")) {
16636097Snw141292 		changed++;
16646097Snw141292 		if (live_pgcfg->global_catalog != NULL &&
16656097Snw141292 		    live_pgcfg->global_catalog[0].host[0] != '\0')
16668361SJulian.Pullen@Sun.COM 			ad_reload_required = TRUE;
16678361SJulian.Pullen@Sun.COM 	}
16688361SJulian.Pullen@Sun.COM 	live_pgcfg->global_catalog_auto_disc =
16698361SJulian.Pullen@Sun.COM 	    new_pgcfg.global_catalog_auto_disc;
16708361SJulian.Pullen@Sun.COM 
16718361SJulian.Pullen@Sun.COM 	if (update_domains_in_forest(&live_pgcfg->domains_in_forest,
16728361SJulian.Pullen@Sun.COM 	    &new_pgcfg.domains_in_forest, "domains_in_forest")) {
16738361SJulian.Pullen@Sun.COM 		changed++;
16748361SJulian.Pullen@Sun.COM 		ad_reload_required = TRUE;
16755317Sjp151216 	}
16765317Sjp151216 
16778361SJulian.Pullen@Sun.COM 	if (update_trusted_domains(&live_pgcfg->trusted_domains,
16788361SJulian.Pullen@Sun.COM 	    &new_pgcfg.trusted_domains, "trusted_domains")) {
16798361SJulian.Pullen@Sun.COM 		changed++;
16808361SJulian.Pullen@Sun.COM 		if (live_pgcfg->trusted_domains != NULL &&
16818361SJulian.Pullen@Sun.COM 		    live_pgcfg->trusted_domains[0].domain[0] != '\0')
16828361SJulian.Pullen@Sun.COM 			ad_reload_required = TRUE;
16838361SJulian.Pullen@Sun.COM 	}
16848361SJulian.Pullen@Sun.COM 
16858361SJulian.Pullen@Sun.COM 	if (update_trusted_forest(&live_pgcfg->trusted_forests,
16868361SJulian.Pullen@Sun.COM 	    &live_pgcfg->num_trusted_forests, &new_pgcfg.trusted_forests,
16878361SJulian.Pullen@Sun.COM 	    &new_pgcfg.num_trusted_forests, "trusted_forest")) {
16888361SJulian.Pullen@Sun.COM 		changed++;
16898361SJulian.Pullen@Sun.COM 		if (live_pgcfg->trusted_forests != NULL)
16908361SJulian.Pullen@Sun.COM 			ad_reload_required = TRUE;
16918361SJulian.Pullen@Sun.COM 	}
16928361SJulian.Pullen@Sun.COM 
16938361SJulian.Pullen@Sun.COM 	if (ad_reload_required)
16948361SJulian.Pullen@Sun.COM 		reload_ad();
16958361SJulian.Pullen@Sun.COM 
16966097Snw141292 	idmap_cfg_unload(&new_pgcfg);
16976097Snw141292 
16986097Snw141292 	if (flags & CFG_LOG) {
16996097Snw141292 		/*
17006097Snw141292 		 * If the config changes as a result of a refresh of the
17016097Snw141292 		 * service, then logging about it can provide useful
17026097Snw141292 		 * feedback to the sysadmin.
17036097Snw141292 		 */
17046097Snw141292 		idmapdlog(LOG_NOTICE, "Configuration %schanged",
17056097Snw141292 		    changed ? "" : "un");
17065317Sjp151216 	}
17075447Snw141292 
17086097Snw141292 	UNLOCK_CONFIG();
17096097Snw141292 
17106097Snw141292 err:
17116097Snw141292 	pthread_mutex_unlock(&cfg->handles.mutex);
17124520Snw141292 
17135731Sbaban 	if (rc < -1)
17145447Snw141292 		return (rc);
17155447Snw141292 
17165447Snw141292 	return ((errors == 0) ? 0 : -1);
17174520Snw141292 }
17184520Snw141292 
17194644Sbaban /*
17204644Sbaban  * Initialize 'cfg'.
17214644Sbaban  */
17224520Snw141292 idmap_cfg_t *
17235908Sjp151216 idmap_cfg_init()
17245908Sjp151216 {
17255317Sjp151216 	idmap_cfg_handles_t *handles;
17264520Snw141292 
17274520Snw141292 	/* First the smf repository handles: */
17284520Snw141292 	idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t));
17294520Snw141292 	if (!cfg) {
17306017Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
17314520Snw141292 		return (NULL);
17324520Snw141292 	}
17335317Sjp151216 	handles = &cfg->handles;
17344520Snw141292 
17355317Sjp151216 	(void) pthread_mutex_init(&handles->mutex, NULL);
17365317Sjp151216 
17375317Sjp151216 	if (!(handles->main = scf_handle_create(SCF_VERSION))) {
17386017Snw141292 		idmapdlog(LOG_ERR, "scf_handle_create() failed: %s",
17396017Snw141292 		    scf_strerror(scf_error()));
17404520Snw141292 		goto error;
17414520Snw141292 	}
17424520Snw141292 
17435317Sjp151216 	if (scf_handle_bind(handles->main) < 0) {
17446017Snw141292 		idmapdlog(LOG_ERR, "scf_handle_bind() failed: %s",
17456017Snw141292 		    scf_strerror(scf_error()));
17464520Snw141292 		goto error;
17474520Snw141292 	}
17484520Snw141292 
17495317Sjp151216 	if (!(handles->service = scf_service_create(handles->main)) ||
17505317Sjp151216 	    !(handles->instance = scf_instance_create(handles->main)) ||
17515317Sjp151216 	    !(handles->config_pg = scf_pg_create(handles->main)) ||
17525317Sjp151216 	    !(handles->general_pg = scf_pg_create(handles->main))) {
17536017Snw141292 		idmapdlog(LOG_ERR, "scf handle creation failed: %s",
17546017Snw141292 		    scf_strerror(scf_error()));
17554520Snw141292 		goto error;
17564520Snw141292 	}
17574520Snw141292 
17585317Sjp151216 	if (scf_handle_decode_fmri(handles->main,
17595908Sjp151216 	    FMRI_BASE "/:properties/" CONFIG_PG,
17605908Sjp151216 	    NULL,				/* scope */
17615908Sjp151216 	    handles->service,		/* service */
17625908Sjp151216 	    handles->instance,		/* instance */
17635908Sjp151216 	    handles->config_pg,		/* pg */
17645908Sjp151216 	    NULL,				/* prop */
17655908Sjp151216 	    SCF_DECODE_FMRI_EXACT) < 0) {
17666017Snw141292 		idmapdlog(LOG_ERR, "scf_handle_decode_fmri() failed: %s",
17676017Snw141292 		    scf_strerror(scf_error()));
17684520Snw141292 		goto error;
17694520Snw141292 	}
17704520Snw141292 
17715317Sjp151216 	if (scf_service_get_pg(handles->service,
17725908Sjp151216 	    GENERAL_PG, handles->general_pg) < 0) {
17736017Snw141292 		idmapdlog(LOG_ERR, "scf_service_get_pg() failed: %s",
17746017Snw141292 		    scf_strerror(scf_error()));
17754520Snw141292 		goto error;
17764520Snw141292 	}
17774520Snw141292 
177810504SKeyur.Desai@Sun.COM 	if (check_smf_debug_mode(handles) != 0)
177910504SKeyur.Desai@Sun.COM 		goto error;
178010504SKeyur.Desai@Sun.COM 
17815317Sjp151216 	/* Initialize AD Auto Discovery context */
17825317Sjp151216 	handles->ad_ctx = ad_disc_init();
17835317Sjp151216 	if (handles->ad_ctx == NULL)
17845317Sjp151216 		goto error;
17855317Sjp151216 
17864520Snw141292 	return (cfg);
17874520Snw141292 
17884520Snw141292 error:
17894520Snw141292 	(void) idmap_cfg_fini(cfg);
17904520Snw141292 	return (NULL);
17914520Snw141292 }
17924520Snw141292 
17935317Sjp151216 void
17945908Sjp151216 idmap_cfg_unload(idmap_pg_config_t *pgcfg)
17955908Sjp151216 {
17965317Sjp151216 
17975317Sjp151216 	if (pgcfg->default_domain) {
17985317Sjp151216 		free(pgcfg->default_domain);
17995317Sjp151216 		pgcfg->default_domain = NULL;
18005317Sjp151216 	}
18015317Sjp151216 	if (pgcfg->domain_name) {
18025317Sjp151216 		free(pgcfg->domain_name);
18035317Sjp151216 		pgcfg->domain_name = NULL;
18045317Sjp151216 	}
18055317Sjp151216 	if (pgcfg->machine_sid) {
18065317Sjp151216 		free(pgcfg->machine_sid);
18075317Sjp151216 		pgcfg->machine_sid = NULL;
18085317Sjp151216 	}
18095317Sjp151216 	if (pgcfg->domain_controller) {
18105317Sjp151216 		free(pgcfg->domain_controller);
18115317Sjp151216 		pgcfg->domain_controller = NULL;
18125317Sjp151216 	}
18135317Sjp151216 	if (pgcfg->forest_name) {
18145317Sjp151216 		free(pgcfg->forest_name);
18155317Sjp151216 		pgcfg->forest_name = NULL;
18165317Sjp151216 	}
18175317Sjp151216 	if (pgcfg->site_name) {
18185317Sjp151216 		free(pgcfg->site_name);
18195317Sjp151216 		pgcfg->site_name = NULL;
18205317Sjp151216 	}
18215317Sjp151216 	if (pgcfg->global_catalog) {
18224520Snw141292 		free(pgcfg->global_catalog);
18235317Sjp151216 		pgcfg->global_catalog = NULL;
18245317Sjp151216 	}
18258361SJulian.Pullen@Sun.COM 	if (pgcfg->trusted_domains) {
18268361SJulian.Pullen@Sun.COM 		free(pgcfg->trusted_domains);
18278361SJulian.Pullen@Sun.COM 		pgcfg->trusted_domains = NULL;
18288361SJulian.Pullen@Sun.COM 	}
18298361SJulian.Pullen@Sun.COM 	if (pgcfg->trusted_forests)
18308361SJulian.Pullen@Sun.COM 		free_trusted_forests(&pgcfg->trusted_forests,
18318361SJulian.Pullen@Sun.COM 		    &pgcfg->num_trusted_forests);
18328361SJulian.Pullen@Sun.COM 
18335731Sbaban 	if (pgcfg->ad_unixuser_attr) {
18345731Sbaban 		free(pgcfg->ad_unixuser_attr);
18355731Sbaban 		pgcfg->ad_unixuser_attr = NULL;
18365731Sbaban 	}
18375731Sbaban 	if (pgcfg->ad_unixgroup_attr) {
18385731Sbaban 		free(pgcfg->ad_unixgroup_attr);
18395731Sbaban 		pgcfg->ad_unixgroup_attr = NULL;
18405731Sbaban 	}
18415731Sbaban 	if (pgcfg->nldap_winname_attr) {
18425731Sbaban 		free(pgcfg->nldap_winname_attr);
18435731Sbaban 		pgcfg->nldap_winname_attr = NULL;
18445731Sbaban 	}
18454520Snw141292 }
18464520Snw141292 
18474520Snw141292 int
18484520Snw141292 idmap_cfg_fini(idmap_cfg_t *cfg)
18494520Snw141292 {
18505317Sjp151216 	idmap_cfg_handles_t *handles = &cfg->handles;
18515317Sjp151216 	idmap_cfg_unload(&cfg->pgcfg);
18524520Snw141292 
18535317Sjp151216 	(void) pthread_mutex_destroy(&handles->mutex);
18545317Sjp151216 	scf_pg_destroy(handles->config_pg);
18555317Sjp151216 	scf_pg_destroy(handles->general_pg);
18565317Sjp151216 	scf_instance_destroy(handles->instance);
18575317Sjp151216 	scf_service_destroy(handles->service);
18585317Sjp151216 	scf_handle_destroy(handles->main);
18595731Sbaban 	if (handles->ad_ctx != NULL)
18605731Sbaban 		ad_disc_fini(handles->ad_ctx);
18614520Snw141292 	free(cfg);
18624520Snw141292 
18634520Snw141292 	return (0);
18644520Snw141292 }
18655968Snw141292 
18665968Snw141292 void
18675968Snw141292 idmap_cfg_poke_updates(void)
18685968Snw141292 {
18696097Snw141292 	if (idmapd_ev_port != -1)
18706097Snw141292 		(void) port_send(idmapd_ev_port, POKE_AUTO_DISCOVERY, NULL);
18715968Snw141292 }
18725968Snw141292 
18735968Snw141292 /*ARGSUSED*/
18745968Snw141292 void
18756097Snw141292 idmap_cfg_hup_handler(int sig)
18766097Snw141292 {
18775968Snw141292 	if (idmapd_ev_port >= 0)
18785968Snw141292 		(void) port_send(idmapd_ev_port, RECONFIGURE, NULL);
18795968Snw141292 }
188010504SKeyur.Desai@Sun.COM 
188110504SKeyur.Desai@Sun.COM /*
188210504SKeyur.Desai@Sun.COM  * Upgrade the DS mapping flags.
188310504SKeyur.Desai@Sun.COM  *
188410504SKeyur.Desai@Sun.COM  * If the old ds_name_mapping_enabled flag is present, then
188510504SKeyur.Desai@Sun.COM  *     if the new directory_based_mapping value is present, then
188610504SKeyur.Desai@Sun.COM  *         if the two are compatible, delete the old and note it
188710504SKeyur.Desai@Sun.COM  *         else delete the old and warn
188810504SKeyur.Desai@Sun.COM  *     else
188910504SKeyur.Desai@Sun.COM  *         set the new based on the old, and note it
189010504SKeyur.Desai@Sun.COM  *         delete the old
189110504SKeyur.Desai@Sun.COM  */
189210504SKeyur.Desai@Sun.COM static
189310504SKeyur.Desai@Sun.COM int
189410504SKeyur.Desai@Sun.COM upgrade_directory_mapping(idmap_cfg_handles_t *handles)
189510504SKeyur.Desai@Sun.COM {
189610504SKeyur.Desai@Sun.COM 	boolean_t legacy_ds_name_mapping_present;
189710504SKeyur.Desai@Sun.COM 	const char DS_NAME_MAPPING_ENABLED[] = "ds_name_mapping_enabled";
189810504SKeyur.Desai@Sun.COM 	const char DIRECTORY_BASED_MAPPING[] = "directory_based_mapping";
189910504SKeyur.Desai@Sun.COM 	int rc;
190010504SKeyur.Desai@Sun.COM 
190110504SKeyur.Desai@Sun.COM 	rc = prop_exists(handles, DS_NAME_MAPPING_ENABLED,
190210504SKeyur.Desai@Sun.COM 	    &legacy_ds_name_mapping_present);
190310504SKeyur.Desai@Sun.COM 
190410504SKeyur.Desai@Sun.COM 	if (rc != 0)
190510504SKeyur.Desai@Sun.COM 		return (rc);
190610504SKeyur.Desai@Sun.COM 
190710504SKeyur.Desai@Sun.COM 	if (!legacy_ds_name_mapping_present)
190810504SKeyur.Desai@Sun.COM 		return (0);
190910504SKeyur.Desai@Sun.COM 
191010504SKeyur.Desai@Sun.COM 	boolean_t legacy_ds_name_mapping_enabled;
191110504SKeyur.Desai@Sun.COM 	rc = get_val_int(handles, DS_NAME_MAPPING_ENABLED,
191210504SKeyur.Desai@Sun.COM 	    &legacy_ds_name_mapping_enabled, SCF_TYPE_BOOLEAN);
191310504SKeyur.Desai@Sun.COM 	if (rc != 0)
191410504SKeyur.Desai@Sun.COM 		return (rc);
191510504SKeyur.Desai@Sun.COM 
191610504SKeyur.Desai@Sun.COM 	char *legacy_mode;
191710504SKeyur.Desai@Sun.COM 	char *legacy_bool_string;
191810504SKeyur.Desai@Sun.COM 	if (legacy_ds_name_mapping_enabled) {
191910504SKeyur.Desai@Sun.COM 		legacy_mode = "name";
192010504SKeyur.Desai@Sun.COM 		legacy_bool_string = "true";
192110504SKeyur.Desai@Sun.COM 	} else {
192210504SKeyur.Desai@Sun.COM 		legacy_mode = "none";
192310504SKeyur.Desai@Sun.COM 		legacy_bool_string = "false";
192410504SKeyur.Desai@Sun.COM 	}
192510504SKeyur.Desai@Sun.COM 
192610504SKeyur.Desai@Sun.COM 	char *directory_based_mapping;
192710504SKeyur.Desai@Sun.COM 	rc = get_val_astring(handles, DIRECTORY_BASED_MAPPING,
192810504SKeyur.Desai@Sun.COM 	    &directory_based_mapping);
192910504SKeyur.Desai@Sun.COM 	if (rc != 0)
193010504SKeyur.Desai@Sun.COM 		return (rc);
193110504SKeyur.Desai@Sun.COM 
193210504SKeyur.Desai@Sun.COM 	if (directory_based_mapping == NULL) {
193310504SKeyur.Desai@Sun.COM 		idmapdlog(LOG_INFO,
193410504SKeyur.Desai@Sun.COM 		    "Upgrading old %s=%s setting\n"
193510504SKeyur.Desai@Sun.COM 		    "to %s=%s.",
193610504SKeyur.Desai@Sun.COM 		    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
193710504SKeyur.Desai@Sun.COM 		    DIRECTORY_BASED_MAPPING, legacy_mode);
193810504SKeyur.Desai@Sun.COM 		rc = set_val_astring(handles, DIRECTORY_BASED_MAPPING,
193910504SKeyur.Desai@Sun.COM 		    legacy_mode);
194010504SKeyur.Desai@Sun.COM 		if (rc != 0)
194110504SKeyur.Desai@Sun.COM 			return (rc);
194210504SKeyur.Desai@Sun.COM 	} else {
194310504SKeyur.Desai@Sun.COM 		boolean_t new_name_mapping;
194410504SKeyur.Desai@Sun.COM 		if (strcasecmp(directory_based_mapping, "name") == 0)
194510504SKeyur.Desai@Sun.COM 			new_name_mapping = B_TRUE;
194610504SKeyur.Desai@Sun.COM 		else
194710504SKeyur.Desai@Sun.COM 			new_name_mapping = B_FALSE;
194810504SKeyur.Desai@Sun.COM 
194910504SKeyur.Desai@Sun.COM 		if (legacy_ds_name_mapping_enabled == new_name_mapping) {
195010504SKeyur.Desai@Sun.COM 			idmapdlog(LOG_INFO,
195110504SKeyur.Desai@Sun.COM 			    "Automatically removing old %s=%s setting\n"
195210504SKeyur.Desai@Sun.COM 			    "in favor of %s=%s.",
195310504SKeyur.Desai@Sun.COM 			    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
195410504SKeyur.Desai@Sun.COM 			    DIRECTORY_BASED_MAPPING, directory_based_mapping);
195510504SKeyur.Desai@Sun.COM 		} else {
195610504SKeyur.Desai@Sun.COM 			idmapdlog(LOG_WARNING,
195710504SKeyur.Desai@Sun.COM 			    "Removing conflicting %s=%s setting\n"
195810504SKeyur.Desai@Sun.COM 			    "in favor of %s=%s.",
195910504SKeyur.Desai@Sun.COM 			    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
196010504SKeyur.Desai@Sun.COM 			    DIRECTORY_BASED_MAPPING, directory_based_mapping);
196110504SKeyur.Desai@Sun.COM 		}
196210504SKeyur.Desai@Sun.COM 		free(directory_based_mapping);
196310504SKeyur.Desai@Sun.COM 	}
196410504SKeyur.Desai@Sun.COM 
196510504SKeyur.Desai@Sun.COM 	rc = del_val(handles, DS_NAME_MAPPING_ENABLED);
196610504SKeyur.Desai@Sun.COM 	if (rc != 0)
196710504SKeyur.Desai@Sun.COM 		return (rc);
196810504SKeyur.Desai@Sun.COM 
196910504SKeyur.Desai@Sun.COM 	return (0);
197010504SKeyur.Desai@Sun.COM }
197110504SKeyur.Desai@Sun.COM 
197210504SKeyur.Desai@Sun.COM /*
197310504SKeyur.Desai@Sun.COM  * Do whatever is necessary to upgrade idmap's configuration before
197410504SKeyur.Desai@Sun.COM  * we load it.
197510504SKeyur.Desai@Sun.COM  */
197610504SKeyur.Desai@Sun.COM int
197710504SKeyur.Desai@Sun.COM idmap_cfg_upgrade(idmap_cfg_t *cfg)
197810504SKeyur.Desai@Sun.COM {
197910504SKeyur.Desai@Sun.COM 	int rc;
198010504SKeyur.Desai@Sun.COM 
198110504SKeyur.Desai@Sun.COM 	rc = upgrade_directory_mapping(&cfg->handles);
198210504SKeyur.Desai@Sun.COM 	if (rc != 0)
198310504SKeyur.Desai@Sun.COM 		return (rc);
198410504SKeyur.Desai@Sun.COM 
198510504SKeyur.Desai@Sun.COM 	return (0);
198610504SKeyur.Desai@Sun.COM }
1987