1c5c4113dSnw /*
2c5c4113dSnw  * CDDL HEADER START
3c5c4113dSnw  *
4c5c4113dSnw  * The contents of this file are subject to the terms of the
5c5c4113dSnw  * Common Development and Distribution License (the "License").
6c5c4113dSnw  * You may not use this file except in compliance with the License.
7c5c4113dSnw  *
8c5c4113dSnw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c5c4113dSnw  * or http://www.opensolaris.org/os/licensing.
10c5c4113dSnw  * See the License for the specific language governing permissions
11c5c4113dSnw  * and limitations under the License.
12c5c4113dSnw  *
13c5c4113dSnw  * When distributing Covered Code, include this CDDL HEADER in each
14c5c4113dSnw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c5c4113dSnw  * If applicable, add the following below this CDDL HEADER, with the
16c5c4113dSnw  * fields enclosed by brackets "[]" replaced with your own identifying
17c5c4113dSnw  * information: Portions Copyright [yyyy] [name of copyright owner]
18c5c4113dSnw  *
19c5c4113dSnw  * CDDL HEADER END
20c5c4113dSnw  */
21c5c4113dSnw /*
22*c5866007SKeyur Desai  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23c5c4113dSnw  */
24c5c4113dSnw 
25c5c4113dSnw 
26c5c4113dSnw /*
27c5c4113dSnw  * Config routines common to idmap(1M) and idmapd(1M)
28c5c4113dSnw  */
29c5c4113dSnw 
30c5c4113dSnw #include <stdlib.h>
31c5c4113dSnw #include <strings.h>
32c5c4113dSnw #include <libintl.h>
33c5c4113dSnw #include <ctype.h>
34c5c4113dSnw #include <errno.h>
35651c0131Sbaban #include "idmapd.h"
36c5c4113dSnw #include <stdio.h>
37c5c4113dSnw #include <stdarg.h>
388edda628Sbaban #include <uuid/uuid.h>
39c8e26105Sjp #include <pthread.h>
40c8e26105Sjp #include <port.h>
410dcc7149Snw #include <net/route.h>
424d61c878SJulian Pullen #include <sys/u8_textprep.h>
43c8e26105Sjp #include "addisc.h"
44c5c4113dSnw 
454aa0a5e7Snw #define	MACHINE_SID_LEN		(9 + 3 * 11)
460dcc7149Snw #define	FMRI_BASE		"svc:/system/idmap"
470dcc7149Snw #define	CONFIG_PG		"config"
480dcc7149Snw #define	GENERAL_PG		"general"
490dcc7149Snw #define	RECONFIGURE		1
500dcc7149Snw #define	POKE_AUTO_DISCOVERY	2
51c5c4113dSnw 
52*c5866007SKeyur Desai enum event_type {
53*c5866007SKeyur Desai 	EVENT_NOTHING,	/* Woke up for no good reason */
54*c5866007SKeyur Desai 	EVENT_TIMEOUT,	/* Timeout expired */
55*c5866007SKeyur Desai 	EVENT_ROUTING,	/* An interesting routing event happened */
56*c5866007SKeyur Desai 	EVENT_DEGRADE,	/* An error occurred in the mainline */
57*c5866007SKeyur Desai 	EVENT_REFRESH,	/* SMF refresh */
58*c5866007SKeyur Desai };
59*c5866007SKeyur Desai 
60c8e26105Sjp /*LINTLIBRARY*/
61c8e26105Sjp 
62c8e26105Sjp 
63c8e26105Sjp static pthread_t update_thread_handle = 0;
64c8e26105Sjp 
650dcc7149Snw static int idmapd_ev_port = -1;
660dcc7149Snw static int rt_sock = -1;
67c8e26105Sjp 
68e3f2c991SKeyur Desai struct enum_lookup_map directory_mapping_map[] = {
69e3f2c991SKeyur Desai 	{ DIRECTORY_MAPPING_NONE, "none" },
70e3f2c991SKeyur Desai 	{ DIRECTORY_MAPPING_NAME, "name" },
71e3f2c991SKeyur Desai 	{ DIRECTORY_MAPPING_IDMU, "idmu" },
72e3f2c991SKeyur Desai 	{ 0, NULL },
73e3f2c991SKeyur Desai };
74e3f2c991SKeyur Desai 
758edda628Sbaban static int
764edd44c5Sjp generate_machine_sid(char **machine_sid)
774edd44c5Sjp {
788edda628Sbaban 	char *p;
798edda628Sbaban 	uuid_t uu;
808edda628Sbaban 	int i, j, len, rlen;
818edda628Sbaban 	uint32_t rid;
828edda628Sbaban 
838edda628Sbaban 	/*
844aa0a5e7Snw 	 * Generate and split 128-bit UUID into three 32-bit RIDs The
854aa0a5e7Snw 	 * machine_sid will be of the form S-1-5-21-N1-N2-N3 (that's
864aa0a5e7Snw 	 * four RIDs altogether).
874aa0a5e7Snw 	 *
88e3f2c991SKeyur Desai 	 * Technically we could use up to 14 random RIDs here, but it
894aa0a5e7Snw 	 * turns out that with some versions of Windows using SIDs with
904aa0a5e7Snw 	 * more than  five RIDs in security descriptors causes problems.
918edda628Sbaban 	 */
928edda628Sbaban 
938edda628Sbaban 	*machine_sid = calloc(1, MACHINE_SID_LEN);
948edda628Sbaban 	if (*machine_sid == NULL) {
9571590c90Snw 		idmapdlog(LOG_ERR, "Out of memory");
968edda628Sbaban 		return (-1);
978edda628Sbaban 	}
988edda628Sbaban 	(void) strcpy(*machine_sid, "S-1-5-21");
998edda628Sbaban 	p = *machine_sid + strlen("S-1-5-21");
1008edda628Sbaban 	len = MACHINE_SID_LEN - strlen("S-1-5-21");
1018edda628Sbaban 
1028edda628Sbaban 	uuid_clear(uu);
1038edda628Sbaban 	uuid_generate_random(uu);
1048edda628Sbaban 
1054aa0a5e7Snw #if UUID_LEN != 16
1064aa0a5e7Snw #error UUID size is not 16!
1074aa0a5e7Snw #endif
1084aa0a5e7Snw 
1094aa0a5e7Snw 	for (i = 0; i < 3; i++) {
1108edda628Sbaban 		j = i * 4;
1118edda628Sbaban 		rid = (uu[j] << 24) | (uu[j + 1] << 16) |
1124edd44c5Sjp 		    (uu[j + 2] << 8) | (uu[j + 3]);
1138edda628Sbaban 		rlen = snprintf(p, len, "-%u", rid);
1148edda628Sbaban 		p += rlen;
1158edda628Sbaban 		len -= rlen;
1168edda628Sbaban 	}
1178edda628Sbaban 
1188edda628Sbaban 	return (0);
1198edda628Sbaban }
1208edda628Sbaban 
121479ac375Sdm 
122479ac375Sdm /* In the case of error, exists is set to FALSE anyway */
123479ac375Sdm static int
124e3f2c991SKeyur Desai prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists)
12571590c90Snw {
12671590c90Snw 
127479ac375Sdm 	scf_property_t *scf_prop;
128479ac375Sdm 	scf_value_t *value;
129479ac375Sdm 
1307a8a68f5SJulian Pullen 	*exists = B_FALSE;
131479ac375Sdm 
132479ac375Sdm 	scf_prop = scf_property_create(handles->main);
133479ac375Sdm 	if (scf_prop == NULL) {
134479ac375Sdm 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
135479ac375Sdm 		    scf_strerror(scf_error()));
136479ac375Sdm 		return (-1);
137479ac375Sdm 	}
138479ac375Sdm 	value = scf_value_create(handles->main);
139479ac375Sdm 	if (value == NULL) {
140479ac375Sdm 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
141479ac375Sdm 		    scf_strerror(scf_error()));
142479ac375Sdm 		scf_property_destroy(scf_prop);
143479ac375Sdm 		return (-1);
144479ac375Sdm 	}
14571590c90Snw 
14671590c90Snw 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) == 0)
1477a8a68f5SJulian Pullen 		*exists = B_TRUE;
14871590c90Snw 
14971590c90Snw 	scf_value_destroy(value);
15071590c90Snw 	scf_property_destroy(scf_prop);
15171590c90Snw 
152479ac375Sdm 	return (0);
15371590c90Snw }
15471590c90Snw 
155c5c4113dSnw /* Check if in the case of failure the original value of *val is preserved */
156c5c4113dSnw static int
157e3f2c991SKeyur Desai get_val_int(idmap_cfg_handles_t *handles, const char *name,
158c8e26105Sjp 	void *val, scf_type_t type)
159c5c4113dSnw {
160c5c4113dSnw 	int rc = 0;
161c5c4113dSnw 
162479ac375Sdm 	scf_property_t *scf_prop;
163479ac375Sdm 	scf_value_t *value;
164e3f2c991SKeyur Desai 	uint8_t b;
165479ac375Sdm 
1664aa0a5e7Snw 	switch (type) {
1674aa0a5e7Snw 	case SCF_TYPE_BOOLEAN:
168e3f2c991SKeyur Desai 		*(boolean_t *)val = B_FALSE;
1694aa0a5e7Snw 		break;
1704aa0a5e7Snw 	case SCF_TYPE_COUNT:
1714aa0a5e7Snw 		*(uint64_t *)val = 0;
1724aa0a5e7Snw 		break;
1734aa0a5e7Snw 	case SCF_TYPE_INTEGER:
1744aa0a5e7Snw 		*(int64_t *)val = 0;
1754aa0a5e7Snw 		break;
1764aa0a5e7Snw 	default:
1774aa0a5e7Snw 		idmapdlog(LOG_ERR, "Invalid scf integer type (%d)",
1784aa0a5e7Snw 		    type);
1794aa0a5e7Snw 		abort();
1804aa0a5e7Snw 	}
1814aa0a5e7Snw 
182479ac375Sdm 	scf_prop = scf_property_create(handles->main);
183479ac375Sdm 	if (scf_prop == NULL) {
184479ac375Sdm 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
185479ac375Sdm 		    scf_strerror(scf_error()));
186479ac375Sdm 		return (-1);
187479ac375Sdm 	}
188479ac375Sdm 	value = scf_value_create(handles->main);
189479ac375Sdm 	if (value == NULL) {
190479ac375Sdm 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
191479ac375Sdm 		    scf_strerror(scf_error()));
192479ac375Sdm 		scf_property_destroy(scf_prop);
193479ac375Sdm 		return (-1);
194479ac375Sdm 	}
195c5c4113dSnw 
196c8e26105Sjp 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
197c5c4113dSnw 	/* this is OK: the property is just undefined */
198c5c4113dSnw 		goto destruction;
199c5c4113dSnw 
200c5c4113dSnw 
201c8e26105Sjp 	if (scf_property_get_value(scf_prop, value) < 0)
202c5c4113dSnw 	/* It is still OK when a property doesn't have any value */
203c5c4113dSnw 		goto destruction;
204c5c4113dSnw 
205c5c4113dSnw 	switch (type) {
206c5c4113dSnw 	case SCF_TYPE_BOOLEAN:
207e3f2c991SKeyur Desai 		rc = scf_value_get_boolean(value, &b);
208e3f2c991SKeyur Desai 		*(boolean_t *)val = b;
209c5c4113dSnw 		break;
210c5c4113dSnw 	case SCF_TYPE_COUNT:
211c5c4113dSnw 		rc = scf_value_get_count(value, val);
212c5c4113dSnw 		break;
213c5c4113dSnw 	case SCF_TYPE_INTEGER:
214c5c4113dSnw 		rc = scf_value_get_integer(value, val);
215c5c4113dSnw 		break;
216e3f2c991SKeyur Desai 	default:
217e3f2c991SKeyur Desai 		abort();	/* tested above */
218e3f2c991SKeyur Desai 		/* NOTREACHED */
219c5c4113dSnw 	}
220c5c4113dSnw 
221e3f2c991SKeyur Desai 	if (rc != 0) {
222e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "Can not retrieve config/%s:  %s",
223e3f2c991SKeyur Desai 		    name, scf_strerror(scf_error()));
224e3f2c991SKeyur Desai 	}
225c5c4113dSnw 
226c5c4113dSnw destruction:
227c5c4113dSnw 	scf_value_destroy(value);
228c5c4113dSnw 	scf_property_destroy(scf_prop);
229c5c4113dSnw 
230c5c4113dSnw 	return (rc);
231c5c4113dSnw }
232c5c4113dSnw 
233c5c4113dSnw static char *
234e3f2c991SKeyur Desai scf_value2string(const char *name, scf_value_t *value)
2354edd44c5Sjp {
236e3f2c991SKeyur Desai 	static size_t max_val = 0;
237c5c4113dSnw 
238e3f2c991SKeyur Desai 	if (max_val == 0)
239e3f2c991SKeyur Desai 		max_val = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
240c5c4113dSnw 
241e3f2c991SKeyur Desai 	char buf[max_val + 1];
242e3f2c991SKeyur Desai 	if (scf_value_get_astring(value, buf, max_val + 1) < 0) {
243e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "Can not retrieve config/%s:  %s",
244e3f2c991SKeyur Desai 		    name, scf_strerror(scf_error()));
245e3f2c991SKeyur Desai 		return (NULL);
246c5c4113dSnw 	}
247c5c4113dSnw 
248e3f2c991SKeyur Desai 	char *s = strdup(buf);
249e3f2c991SKeyur Desai 	if (s == NULL)
250e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "Out of memory");
251c5c4113dSnw 
252e3f2c991SKeyur Desai 	return (s);
253c5c4113dSnw }
254c5c4113dSnw 
255c8e26105Sjp static int
256c8e26105Sjp get_val_ds(idmap_cfg_handles_t *handles, const char *name, int defport,
257479ac375Sdm 		idmap_ad_disc_ds_t **val)
258c8e26105Sjp {
259479ac375Sdm 	idmap_ad_disc_ds_t *servers = NULL;
260c8e26105Sjp 	scf_property_t *scf_prop;
261c8e26105Sjp 	scf_value_t *value;
262c8e26105Sjp 	scf_iter_t *iter;
263c8e26105Sjp 	char *host, *portstr;
264e3c2d6aaSnw 	int len, i;
265c8e26105Sjp 	int count = 0;
266e3c2d6aaSnw 	int rc = -1;
267c8e26105Sjp 
268c8e26105Sjp 	*val = NULL;
269c8e26105Sjp 
270c8e26105Sjp restart:
271c8e26105Sjp 	scf_prop = scf_property_create(handles->main);
272479ac375Sdm 	if (scf_prop == NULL) {
273479ac375Sdm 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
274479ac375Sdm 		    scf_strerror(scf_error()));
275479ac375Sdm 		return (-1);
276479ac375Sdm 	}
277479ac375Sdm 
278c8e26105Sjp 	value = scf_value_create(handles->main);
279479ac375Sdm 	if (value == NULL) {
280479ac375Sdm 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
281479ac375Sdm 		    scf_strerror(scf_error()));
282479ac375Sdm 		scf_property_destroy(scf_prop);
283479ac375Sdm 		return (-1);
284479ac375Sdm 	}
285479ac375Sdm 
286c8e26105Sjp 	iter = scf_iter_create(handles->main);
287479ac375Sdm 	if (iter == NULL) {
288479ac375Sdm 		idmapdlog(LOG_ERR, "scf_iter_create() failed: %s",
289479ac375Sdm 		    scf_strerror(scf_error()));
290479ac375Sdm 		scf_value_destroy(value);
291479ac375Sdm 		scf_property_destroy(scf_prop);
292479ac375Sdm 		return (-1);
293479ac375Sdm 	}
294c8e26105Sjp 
295e3c2d6aaSnw 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) {
296c8e26105Sjp 		/* this is OK: the property is just undefined */
297e3c2d6aaSnw 		rc = 0;
298c8e26105Sjp 		goto destruction;
299e3c2d6aaSnw 	}
300c8e26105Sjp 
301c8e26105Sjp 	if (scf_iter_property_values(iter, scf_prop) < 0) {
302c8e26105Sjp 		idmapdlog(LOG_ERR,
30371590c90Snw 		    "scf_iter_property_values(%s) failed: %s",
30471590c90Snw 		    name, scf_strerror(scf_error()));
305c8e26105Sjp 		goto destruction;
306c8e26105Sjp 	}
307c8e26105Sjp 
308c8e26105Sjp 	/* Workaround scf bugs -- can't reset an iteration */
309c8e26105Sjp 	if (count == 0) {
310c8e26105Sjp 		while (scf_iter_next_value(iter, value) > 0)
311c8e26105Sjp 			count++;
312c8e26105Sjp 
313e3c2d6aaSnw 		if (count == 0) {
314c8e26105Sjp 			/* no values */
315e3c2d6aaSnw 			rc = 0;
316c8e26105Sjp 			goto destruction;
317e3c2d6aaSnw 		}
318c8e26105Sjp 
319c8e26105Sjp 		scf_value_destroy(value);
320c8e26105Sjp 		scf_iter_destroy(iter);
321c8e26105Sjp 		scf_property_destroy(scf_prop);
322c8e26105Sjp 		goto restart;
323c8e26105Sjp 	}
324c8e26105Sjp 
325c8e26105Sjp 	if ((servers = calloc(count + 1, sizeof (*servers))) == NULL) {
32671590c90Snw 		idmapdlog(LOG_ERR, "Out of memory");
327c8e26105Sjp 		goto destruction;
328c8e26105Sjp 	}
329c8e26105Sjp 
330e3c2d6aaSnw 	i = 0;
331e3c2d6aaSnw 	while (i < count && scf_iter_next_value(iter, value) > 0) {
332e3c2d6aaSnw 		servers[i].priority = 0;
333e3c2d6aaSnw 		servers[i].weight = 100;
334e3c2d6aaSnw 		servers[i].port = defport;
335e3f2c991SKeyur Desai 		if ((host = scf_value2string(name, value)) == NULL) {
336c8e26105Sjp 			goto destruction;
337c8e26105Sjp 		}
338c8e26105Sjp 		if ((portstr = strchr(host, ':')) != NULL) {
339c8e26105Sjp 			*portstr++ = '\0';
340e3c2d6aaSnw 			servers[i].port = strtol(portstr,
341c8e26105Sjp 			    (char **)NULL, 10);
342e3c2d6aaSnw 			if (servers[i].port == 0)
343e3c2d6aaSnw 				servers[i].port = defport;
344c8e26105Sjp 		}
345e3c2d6aaSnw 		len = strlcpy(servers[i].host, host,
346c8e26105Sjp 		    sizeof (servers->host));
347c8e26105Sjp 
348c8e26105Sjp 		free(host);
349c8e26105Sjp 
350c8e26105Sjp 		/* Ignore this server if the hostname is too long */
351c8e26105Sjp 		if (len < sizeof (servers->host))
352e3c2d6aaSnw 			i++;
353c8e26105Sjp 	}
354c8e26105Sjp 
355c8e26105Sjp 	*val = servers;
356c8e26105Sjp 
357e3c2d6aaSnw 	rc = 0;
358e3c2d6aaSnw 
359c8e26105Sjp destruction:
360c8e26105Sjp 	scf_value_destroy(value);
361c8e26105Sjp 	scf_iter_destroy(iter);
362c8e26105Sjp 	scf_property_destroy(scf_prop);
363c8e26105Sjp 
364c8e26105Sjp 	if (rc < 0) {
365c8e26105Sjp 		if (servers)
366c8e26105Sjp 			free(servers);
367c8e26105Sjp 		*val = NULL;
368c8e26105Sjp 	}
369c8e26105Sjp 
370c8e26105Sjp 	return (rc);
371c8e26105Sjp }
372c8e26105Sjp 
373c5c4113dSnw 
374c5c4113dSnw static int
375e3f2c991SKeyur Desai get_val_astring(idmap_cfg_handles_t *handles, const char *name, char **val)
376c5c4113dSnw {
377c5c4113dSnw 	int rc = 0;
378c5c4113dSnw 
379479ac375Sdm 	scf_property_t *scf_prop;
380479ac375Sdm 	scf_value_t *value;
381479ac375Sdm 
382479ac375Sdm 	scf_prop = scf_property_create(handles->main);
383479ac375Sdm 	if (scf_prop == NULL) {
384479ac375Sdm 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
385479ac375Sdm 		    scf_strerror(scf_error()));
386479ac375Sdm 		return (-1);
387479ac375Sdm 	}
388479ac375Sdm 	value = scf_value_create(handles->main);
389479ac375Sdm 	if (value == NULL) {
390479ac375Sdm 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
391479ac375Sdm 		    scf_strerror(scf_error()));
392479ac375Sdm 		scf_property_destroy(scf_prop);
393479ac375Sdm 		return (-1);
394479ac375Sdm 	}
395c5c4113dSnw 
396c8e26105Sjp 	*val = NULL;
397c5c4113dSnw 
398c8e26105Sjp 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
399c5c4113dSnw 	/* this is OK: the property is just undefined */
400c5c4113dSnw 		goto destruction;
401c5c4113dSnw 
402c8e26105Sjp 	if (scf_property_get_value(scf_prop, value) < 0) {
403651c0131Sbaban 		idmapdlog(LOG_ERR,
40471590c90Snw 		    "scf_property_get_value(%s) failed: %s",
40571590c90Snw 		    name, scf_strerror(scf_error()));
406c5c4113dSnw 		rc = -1;
407c5c4113dSnw 		goto destruction;
408c5c4113dSnw 	}
409c5c4113dSnw 
410e3f2c991SKeyur Desai 	*val = scf_value2string(name, value);
411e3f2c991SKeyur Desai 	if (*val == NULL)
412c5c4113dSnw 		rc = -1;
413c5c4113dSnw 
414c5c4113dSnw destruction:
415c5c4113dSnw 	scf_value_destroy(value);
416c5c4113dSnw 	scf_property_destroy(scf_prop);
417c5c4113dSnw 
418c5c4113dSnw 	if (rc < 0) {
419c5c4113dSnw 		if (*val)
420c5c4113dSnw 			free(*val);
421c5c4113dSnw 		*val = NULL;
422c5c4113dSnw 	}
423c5c4113dSnw 
424c5c4113dSnw 	return (rc);
425c5c4113dSnw }
426c5c4113dSnw 
427c8e26105Sjp 
4288edda628Sbaban static int
429e3f2c991SKeyur Desai del_val(idmap_cfg_handles_t *handles, const char *name)
430e3f2c991SKeyur Desai {
431e3f2c991SKeyur Desai 	int			rc = -1;
432e3f2c991SKeyur Desai 	int			ret;
433e3f2c991SKeyur Desai 	scf_transaction_t	*tx = NULL;
434e3f2c991SKeyur Desai 	scf_transaction_entry_t	*ent = NULL;
435e3f2c991SKeyur Desai 
436e3f2c991SKeyur Desai 	if ((tx = scf_transaction_create(handles->main)) == NULL) {
437e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
438e3f2c991SKeyur Desai 		    "scf_transaction_create() failed: %s",
439e3f2c991SKeyur Desai 		    scf_strerror(scf_error()));
440e3f2c991SKeyur Desai 		goto destruction;
441e3f2c991SKeyur Desai 	}
442e3f2c991SKeyur Desai 	if ((ent = scf_entry_create(handles->main)) == NULL) {
443e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
444e3f2c991SKeyur Desai 		    "scf_entry_create() failed: %s",
445e3f2c991SKeyur Desai 		    scf_strerror(scf_error()));
446e3f2c991SKeyur Desai 		goto destruction;
447e3f2c991SKeyur Desai 	}
448e3f2c991SKeyur Desai 
449e3f2c991SKeyur Desai 	do {
450e3f2c991SKeyur Desai 		if (scf_pg_update(handles->config_pg) == -1) {
451e3f2c991SKeyur Desai 			idmapdlog(LOG_ERR,
452e3f2c991SKeyur Desai 			    "scf_pg_update(%s) failed: %s",
453e3f2c991SKeyur Desai 			    name, scf_strerror(scf_error()));
454e3f2c991SKeyur Desai 			goto destruction;
455e3f2c991SKeyur Desai 		}
456e3f2c991SKeyur Desai 		if (scf_transaction_start(tx, handles->config_pg) != 0) {
457e3f2c991SKeyur Desai 			idmapdlog(LOG_ERR,
458e3f2c991SKeyur Desai 			    "scf_transaction_start(%s) failed: %s",
459e3f2c991SKeyur Desai 			    name, scf_strerror(scf_error()));
460e3f2c991SKeyur Desai 			goto destruction;
461e3f2c991SKeyur Desai 		}
462e3f2c991SKeyur Desai 
463e3f2c991SKeyur Desai 		if (scf_transaction_property_delete(tx, ent, name) != 0) {
464e3f2c991SKeyur Desai 			/* Don't complain if it already doesn't exist. */
465e3f2c991SKeyur Desai 			if (scf_error() != SCF_ERROR_NOT_FOUND) {
466e3f2c991SKeyur Desai 				idmapdlog(LOG_ERR,
467e3f2c991SKeyur Desai 				    "scf_transaction_property_delete() failed:"
468e3f2c991SKeyur Desai 				    " %s",
469e3f2c991SKeyur Desai 				    scf_strerror(scf_error()));
470e3f2c991SKeyur Desai 			}
471e3f2c991SKeyur Desai 			goto destruction;
472e3f2c991SKeyur Desai 		}
473e3f2c991SKeyur Desai 
474e3f2c991SKeyur Desai 		ret = scf_transaction_commit(tx);
475e3f2c991SKeyur Desai 
476e3f2c991SKeyur Desai 		if (ret == 0)
477e3f2c991SKeyur Desai 			scf_transaction_reset(tx);
478e3f2c991SKeyur Desai 	} while (ret == 0);
479e3f2c991SKeyur Desai 
480e3f2c991SKeyur Desai 	if (ret == -1) {
481e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
482e3f2c991SKeyur Desai 		    "scf_transaction_commit(%s) failed: %s",
483e3f2c991SKeyur Desai 		    name, scf_strerror(scf_error()));
484e3f2c991SKeyur Desai 		goto destruction;
485e3f2c991SKeyur Desai 	}
486e3f2c991SKeyur Desai 
487e3f2c991SKeyur Desai 	rc = 0;
488e3f2c991SKeyur Desai 
489e3f2c991SKeyur Desai destruction:
490e3f2c991SKeyur Desai 	if (ent != NULL)
491e3f2c991SKeyur Desai 		scf_entry_destroy(ent);
492e3f2c991SKeyur Desai 	if (tx != NULL)
493e3f2c991SKeyur Desai 		scf_transaction_destroy(tx);
494e3f2c991SKeyur Desai 	return (rc);
495e3f2c991SKeyur Desai }
496e3f2c991SKeyur Desai 
497e3f2c991SKeyur Desai 
498e3f2c991SKeyur Desai static int
499e3f2c991SKeyur Desai set_val_astring(idmap_cfg_handles_t *handles, const char *name, const char *val)
5008edda628Sbaban {
501e3c2d6aaSnw 	int			rc = -1;
502e3c2d6aaSnw 	int			ret = -2;
503e3c2d6aaSnw 	int			i;
5048edda628Sbaban 	scf_property_t		*scf_prop = NULL;
5058edda628Sbaban 	scf_value_t		*value = NULL;
5068edda628Sbaban 	scf_transaction_t	*tx = NULL;
5078edda628Sbaban 	scf_transaction_entry_t	*ent = NULL;
5088edda628Sbaban 
509c8e26105Sjp 	if ((scf_prop = scf_property_create(handles->main)) == NULL ||
510c8e26105Sjp 	    (value = scf_value_create(handles->main)) == NULL ||
511c8e26105Sjp 	    (tx = scf_transaction_create(handles->main)) == NULL ||
512c8e26105Sjp 	    (ent = scf_entry_create(handles->main)) == NULL) {
51371590c90Snw 		idmapdlog(LOG_ERR, "Unable to set property %s",
51471590c90Snw 		    name, scf_strerror(scf_error()));
5158edda628Sbaban 		goto destruction;
5168edda628Sbaban 	}
5178edda628Sbaban 
518e3c2d6aaSnw 	for (i = 0; i < MAX_TRIES && (ret == -2 || ret == 0); i++) {
519c8e26105Sjp 		if (scf_transaction_start(tx, handles->config_pg) == -1) {
5208edda628Sbaban 			idmapdlog(LOG_ERR,
52171590c90Snw 			    "scf_transaction_start(%s) failed: %s",
52271590c90Snw 			    name, scf_strerror(scf_error()));
5238edda628Sbaban 			goto destruction;
5248edda628Sbaban 		}
5258edda628Sbaban 
526e3c2d6aaSnw 		if (scf_transaction_property_new(tx, ent, name,
527e3c2d6aaSnw 		    SCF_TYPE_ASTRING) < 0) {
5288edda628Sbaban 			idmapdlog(LOG_ERR,
52971590c90Snw 			    "scf_transaction_property_new() failed: %s",
53071590c90Snw 			    scf_strerror(scf_error()));
5318edda628Sbaban 			goto destruction;
5328edda628Sbaban 		}
5338edda628Sbaban 
5348edda628Sbaban 		if (scf_value_set_astring(value, val) == -1) {
5358edda628Sbaban 			idmapdlog(LOG_ERR,
53671590c90Snw 			    "scf_value_set_astring() failed: %s",
53771590c90Snw 			    scf_strerror(scf_error()));
5388edda628Sbaban 			goto destruction;
5398edda628Sbaban 		}
5408edda628Sbaban 
5418edda628Sbaban 		if (scf_entry_add_value(ent, value) == -1) {
5428edda628Sbaban 			idmapdlog(LOG_ERR,
54371590c90Snw 			    "scf_entry_add_value() failed: %s",
54471590c90Snw 			    scf_strerror(scf_error()));
5458edda628Sbaban 			goto destruction;
5468edda628Sbaban 		}
5478edda628Sbaban 
548e3c2d6aaSnw 		if ((ret = scf_transaction_commit(tx)) == 1)
549e3c2d6aaSnw 			break;
550e3c2d6aaSnw 
551e3c2d6aaSnw 		if (ret == 0 && i < MAX_TRIES - 1) {
5528edda628Sbaban 			/*
5538edda628Sbaban 			 * Property group set in scf_transaction_start()
5548edda628Sbaban 			 * is not the most recent. Update pg, reset tx and
5558edda628Sbaban 			 * retry tx.
5568edda628Sbaban 			 */
5578edda628Sbaban 			idmapdlog(LOG_WARNING,
55871590c90Snw 			    "scf_transaction_commit(%s) failed - Retry: %s",
55971590c90Snw 			    name, scf_strerror(scf_error()));
560c8e26105Sjp 			if (scf_pg_update(handles->config_pg) == -1) {
5618edda628Sbaban 				idmapdlog(LOG_ERR,
56271590c90Snw 				    "scf_pg_update() failed: %s",
56371590c90Snw 				    scf_strerror(scf_error()));
5648edda628Sbaban 				goto destruction;
5658edda628Sbaban 			}
5668edda628Sbaban 			scf_transaction_reset(tx);
5678edda628Sbaban 		}
5688edda628Sbaban 	}
5698edda628Sbaban 
570e3c2d6aaSnw 
571e3c2d6aaSnw 	if (ret == 1)
572e3c2d6aaSnw 		rc = 0;
573e3c2d6aaSnw 	else if (ret != -2)
5748edda628Sbaban 		idmapdlog(LOG_ERR,
57571590c90Snw 		    "scf_transaction_commit(%s) failed: %s",
57671590c90Snw 		    name, scf_strerror(scf_error()));
5778edda628Sbaban 
5788edda628Sbaban destruction:
5798edda628Sbaban 	scf_value_destroy(value);
5808edda628Sbaban 	scf_entry_destroy(ent);
5818edda628Sbaban 	scf_transaction_destroy(tx);
5828edda628Sbaban 	scf_property_destroy(scf_prop);
5838edda628Sbaban 	return (rc);
5848edda628Sbaban }
5858edda628Sbaban 
5864d61c878SJulian Pullen 
5874d61c878SJulian Pullen 
5884d61c878SJulian Pullen /*
5894d61c878SJulian Pullen  * This function updates a boolean value.
5904d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
5914d61c878SJulian Pullen  */
592c8e26105Sjp static int
5937a8a68f5SJulian Pullen update_bool(boolean_t *value, boolean_t *new, char *name)
5944aa0a5e7Snw {
5954aa0a5e7Snw 	if (*value == *new)
5964aa0a5e7Snw 		return (0);
5974aa0a5e7Snw 
5984aa0a5e7Snw 	idmapdlog(LOG_INFO, "change %s=%s", name, *new ? "true" : "false");
5994aa0a5e7Snw 	*value = *new;
6004aa0a5e7Snw 	return (1);
6014aa0a5e7Snw }
6024aa0a5e7Snw 
6034d61c878SJulian Pullen 
6044d61c878SJulian Pullen /*
6054d61c878SJulian Pullen  * This function updates a string value.
6064d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
6074d61c878SJulian Pullen  */
6084aa0a5e7Snw static int
6094aa0a5e7Snw update_string(char **value, char **new, char *name)
610c8e26105Sjp {
611c8e26105Sjp 	if (*new == NULL)
612349d5d8fSnw 		return (0);
613c8e26105Sjp 
614c8e26105Sjp 	if (*value != NULL && strcmp(*new, *value) == 0) {
615c8e26105Sjp 		free(*new);
616c8e26105Sjp 		*new = NULL;
617349d5d8fSnw 		return (0);
618c8e26105Sjp 	}
619c8e26105Sjp 
62071590c90Snw 	idmapdlog(LOG_INFO, "change %s=%s", name, CHECK_NULL(*new));
621c8e26105Sjp 	if (*value != NULL)
622c8e26105Sjp 		free(*value);
623c8e26105Sjp 	*value = *new;
624c8e26105Sjp 	*new = NULL;
625349d5d8fSnw 	return (1);
626c8e26105Sjp }
627c8e26105Sjp 
628e3f2c991SKeyur Desai static int
629e3f2c991SKeyur Desai update_enum(int *value, int *new, char *name, struct enum_lookup_map *map)
630e3f2c991SKeyur Desai {
631e3f2c991SKeyur Desai 	if (*value == *new)
632e3f2c991SKeyur Desai 		return (0);
633e3f2c991SKeyur Desai 
634e3f2c991SKeyur Desai 	idmapdlog(LOG_INFO, "change %s=%s", name, enum_lookup(*new, map));
635e3f2c991SKeyur Desai 
636e3f2c991SKeyur Desai 	*value = *new;
637e3f2c991SKeyur Desai 
638e3f2c991SKeyur Desai 	return (1);
639e3f2c991SKeyur Desai }
6404d61c878SJulian Pullen 
6414d61c878SJulian Pullen /*
6424d61c878SJulian Pullen  * This function updates a directory service structure.
6434d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
6444d61c878SJulian Pullen  */
645c8e26105Sjp static int
646479ac375Sdm update_dirs(idmap_ad_disc_ds_t **value, idmap_ad_disc_ds_t **new, char *name)
647c8e26105Sjp {
648c8e26105Sjp 	int i;
649c8e26105Sjp 
6500dcc7149Snw 	if (*value == *new)
6510dcc7149Snw 		/* Nothing to do */
652349d5d8fSnw 		return (0);
653c8e26105Sjp 
6540dcc7149Snw 	if (*value != NULL && *new != NULL &&
6550dcc7149Snw 	    ad_disc_compare_ds(*value, *new) == 0) {
656c8e26105Sjp 		free(*new);
657c8e26105Sjp 		*new = NULL;
658349d5d8fSnw 		return (0);
659c8e26105Sjp 	}
660c8e26105Sjp 
6614d61c878SJulian Pullen 	if (*value != NULL)
662c8e26105Sjp 		free(*value);
663c8e26105Sjp 
664c8e26105Sjp 	*value = *new;
665c8e26105Sjp 	*new = NULL;
6660dcc7149Snw 
6670dcc7149Snw 	if (*value == NULL) {
6680dcc7149Snw 		/* We're unsetting this DS property */
66971590c90Snw 		idmapdlog(LOG_INFO, "change %s=<none>", name);
670349d5d8fSnw 		return (1);
6710dcc7149Snw 	}
6720dcc7149Snw 
6730dcc7149Snw 	/* List all the new DSs */
6740dcc7149Snw 	for (i = 0; (*value)[i].host[0] != '\0'; i++)
67571590c90Snw 		idmapdlog(LOG_INFO, "change %s=%s port=%d", name,
6760dcc7149Snw 		    (*value)[i].host, (*value)[i].port);
677349d5d8fSnw 	return (1);
678c8e26105Sjp }
679c8e26105Sjp 
6804d61c878SJulian Pullen /*
6814d61c878SJulian Pullen  * This function updates a trusted domains structure.
6824d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
6834d61c878SJulian Pullen  */
6844d61c878SJulian Pullen static int
6854d61c878SJulian Pullen update_trusted_domains(ad_disc_trusteddomains_t **value,
6864d61c878SJulian Pullen 			ad_disc_trusteddomains_t **new, char *name)
6874d61c878SJulian Pullen {
6884d61c878SJulian Pullen 	int i;
6894d61c878SJulian Pullen 
6904d61c878SJulian Pullen 	if (*value == *new)
6914d61c878SJulian Pullen 		/* Nothing to do */
6924d61c878SJulian Pullen 		return (0);
6934d61c878SJulian Pullen 
6944d61c878SJulian Pullen 	if (*value != NULL && *new != NULL &&
6954d61c878SJulian Pullen 	    ad_disc_compare_trusteddomains(*value, *new) == 0) {
6964d61c878SJulian Pullen 		free(*new);
6974d61c878SJulian Pullen 		*new = NULL;
6984d61c878SJulian Pullen 		return (0);
6994d61c878SJulian Pullen 	}
7004d61c878SJulian Pullen 
7014d61c878SJulian Pullen 	if (*value != NULL)
7024d61c878SJulian Pullen 		free(*value);
7034d61c878SJulian Pullen 
7044d61c878SJulian Pullen 	*value = *new;
7054d61c878SJulian Pullen 	*new = NULL;
7064d61c878SJulian Pullen 
7074d61c878SJulian Pullen 	if (*value == NULL) {
7084d61c878SJulian Pullen 		/* We're unsetting this DS property */
7094d61c878SJulian Pullen 		idmapdlog(LOG_INFO, "change %s=<none>", name);
7104d61c878SJulian Pullen 		return (1);
7114d61c878SJulian Pullen 	}
7124d61c878SJulian Pullen 
7134d61c878SJulian Pullen 	/* List all the new domains */
7144d61c878SJulian Pullen 	for (i = 0; (*value)[i].domain[0] != '\0'; i++)
7154d61c878SJulian Pullen 		idmapdlog(LOG_INFO, "change %s=%s direction=%s", name,
7164d61c878SJulian Pullen 		    (*value)[i].domain,
7174d61c878SJulian Pullen 		    (*value)[i].direction == 3 ? "bi-directional" : "inbound");
7184d61c878SJulian Pullen 	return (1);
7194d61c878SJulian Pullen }
7204d61c878SJulian Pullen 
7214d61c878SJulian Pullen 
7224d61c878SJulian Pullen /*
7234d61c878SJulian Pullen  * This function updates a domains in a forest structure.
7244d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
7254d61c878SJulian Pullen  */
7264d61c878SJulian Pullen static int
7274d61c878SJulian Pullen update_domains_in_forest(ad_disc_domainsinforest_t **value,
7284d61c878SJulian Pullen 			ad_disc_domainsinforest_t **new, char *name)
7294d61c878SJulian Pullen {
7304d61c878SJulian Pullen 	int i;
7314d61c878SJulian Pullen 
7324d61c878SJulian Pullen 	if (*value == *new)
7334d61c878SJulian Pullen 		/* Nothing to do */
7344d61c878SJulian Pullen 		return (0);
7354d61c878SJulian Pullen 
7364d61c878SJulian Pullen 	if (*value != NULL && *new != NULL &&
7374d61c878SJulian Pullen 	    ad_disc_compare_domainsinforest(*value, *new) == 0) {
7384d61c878SJulian Pullen 		free(*new);
7394d61c878SJulian Pullen 		*new = NULL;
7404d61c878SJulian Pullen 		return (0);
7414d61c878SJulian Pullen 	}
7424d61c878SJulian Pullen 
7434d61c878SJulian Pullen 	if (*value != NULL)
7444d61c878SJulian Pullen 		free(*value);
7454d61c878SJulian Pullen 
7464d61c878SJulian Pullen 	*value = *new;
7474d61c878SJulian Pullen 	*new = NULL;
7484d61c878SJulian Pullen 
7494d61c878SJulian Pullen 	if (*value == NULL) {
7504d61c878SJulian Pullen 		/* We're unsetting this DS property */
7514d61c878SJulian Pullen 		idmapdlog(LOG_INFO, "change %s=<none>", name);
7524d61c878SJulian Pullen 		return (1);
7534d61c878SJulian Pullen 	}
7544d61c878SJulian Pullen 
7554d61c878SJulian Pullen 	/* List all the new domains */
7564d61c878SJulian Pullen 	for (i = 0; (*value)[i].domain[0] != '\0'; i++)
7574d61c878SJulian Pullen 		idmapdlog(LOG_INFO, "change %s=%s", name,
7584d61c878SJulian Pullen 		    (*value)[i].domain);
7594d61c878SJulian Pullen 	return (1);
7604d61c878SJulian Pullen }
7614d61c878SJulian Pullen 
7624d61c878SJulian Pullen 
7634d61c878SJulian Pullen static void
7644d61c878SJulian Pullen free_trusted_forests(idmap_trustedforest_t **value, int *num_values)
7654d61c878SJulian Pullen {
7664d61c878SJulian Pullen 	int i;
7674d61c878SJulian Pullen 
7684d61c878SJulian Pullen 	for (i = 0; i < *num_values; i++) {
7694d61c878SJulian Pullen 		free((*value)[i].forest_name);
7704d61c878SJulian Pullen 		free((*value)[i].global_catalog);
7714d61c878SJulian Pullen 		free((*value)[i].domains_in_forest);
7724d61c878SJulian Pullen 	}
7734d61c878SJulian Pullen 	free(*value);
7744d61c878SJulian Pullen 	*value = NULL;
7754d61c878SJulian Pullen 	*num_values = 0;
7764d61c878SJulian Pullen }
7774d61c878SJulian Pullen 
7784d61c878SJulian Pullen 
7794d61c878SJulian Pullen static int
7804d61c878SJulian Pullen compare_trusteddomainsinforest(ad_disc_domainsinforest_t *df1,
7814d61c878SJulian Pullen 			ad_disc_domainsinforest_t *df2)
7824d61c878SJulian Pullen {
7837a8a68f5SJulian Pullen 	int		i, j;
7847a8a68f5SJulian Pullen 	int		num_df1 = 0;
7857a8a68f5SJulian Pullen 	int		num_df2 = 0;
7867a8a68f5SJulian Pullen 	boolean_t	match;
7874d61c878SJulian Pullen 
7884d61c878SJulian Pullen 	for (i = 0; df1[i].domain[0] != '\0'; i++)
7894d61c878SJulian Pullen 		if (df1[i].trusted)
7904d61c878SJulian Pullen 			num_df1++;
7914d61c878SJulian Pullen 
7924d61c878SJulian Pullen 	for (j = 0; df2[j].domain[0] != '\0'; j++)
7934d61c878SJulian Pullen 		if (df2[j].trusted)
7944d61c878SJulian Pullen 			num_df2++;
7954d61c878SJulian Pullen 
7964d61c878SJulian Pullen 	if (num_df1 != num_df2)
7974d61c878SJulian Pullen 		return (1);
7984d61c878SJulian Pullen 
7994d61c878SJulian Pullen 	for (i = 0; df1[i].domain[0] != '\0'; i++) {
8004d61c878SJulian Pullen 		if (df1[i].trusted) {
8017a8a68f5SJulian Pullen 			match = B_FALSE;
8024d61c878SJulian Pullen 			for (j = 0; df2[j].domain[0] != '\0'; j++) {
8034d61c878SJulian Pullen 				if (df2[j].trusted &&
8041fcced4cSJordan Brown 				    domain_eq(df1[i].domain, df2[j].domain) &&
8051fcced4cSJordan Brown 				    strcmp(df1[i].sid, df2[j].sid) == 0) {
8067a8a68f5SJulian Pullen 					match = B_TRUE;
8074d61c878SJulian Pullen 					break;
8084d61c878SJulian Pullen 				}
8094d61c878SJulian Pullen 			}
8104d61c878SJulian Pullen 			if (!match)
8114d61c878SJulian Pullen 				return (1);
8124d61c878SJulian Pullen 		}
8134d61c878SJulian Pullen 	}
8144d61c878SJulian Pullen 	return (0);
8154d61c878SJulian Pullen }
8164d61c878SJulian Pullen 
8174d61c878SJulian Pullen 
8184d61c878SJulian Pullen 
8194d61c878SJulian Pullen /*
8204d61c878SJulian Pullen  * This function updates trusted forest structure.
8214d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
8224d61c878SJulian Pullen  */
8234d61c878SJulian Pullen static int
8244d61c878SJulian Pullen update_trusted_forest(idmap_trustedforest_t **value, int *num_value,
8254d61c878SJulian Pullen 			idmap_trustedforest_t **new, int *num_new, char *name)
8264d61c878SJulian Pullen {
8274d61c878SJulian Pullen 	int i, j;
8287a8a68f5SJulian Pullen 	boolean_t match;
8294d61c878SJulian Pullen 
8304d61c878SJulian Pullen 	if (*value == *new)
8314d61c878SJulian Pullen 		/* Nothing to do */
8324d61c878SJulian Pullen 		return (0);
8334d61c878SJulian Pullen 
8344d61c878SJulian Pullen 	if (*value != NULL && *new != NULL) {
8354d61c878SJulian Pullen 		if (*num_value != *num_new)
8364d61c878SJulian Pullen 			goto not_equal;
8374d61c878SJulian Pullen 		for (i = 0; i < *num_value; i++) {
8387a8a68f5SJulian Pullen 			match = B_FALSE;
8394d61c878SJulian Pullen 			for (j = 0; j < *num_new; j++) {
8404d61c878SJulian Pullen 				if (strcmp((*value)[i].forest_name,
8414d61c878SJulian Pullen 				    (*new)[j].forest_name) == 0 &&
8424d61c878SJulian Pullen 				    ad_disc_compare_ds(
8434d61c878SJulian Pullen 				    (*value)[i].global_catalog,
8441fcced4cSJordan Brown 				    (*new)[j].global_catalog) == 0 &&
8454d61c878SJulian Pullen 				    compare_trusteddomainsinforest(
8464d61c878SJulian Pullen 				    (*value)[i].domains_in_forest,
8471fcced4cSJordan Brown 				    (*new)[j].domains_in_forest) == 0) {
8487a8a68f5SJulian Pullen 					match = B_TRUE;
8494d61c878SJulian Pullen 					break;
8504d61c878SJulian Pullen 				}
8514d61c878SJulian Pullen 			}
8524d61c878SJulian Pullen 			if (!match)
8534d61c878SJulian Pullen 				goto not_equal;
8544d61c878SJulian Pullen 		}
8554d61c878SJulian Pullen 		free_trusted_forests(new, num_new);
8564d61c878SJulian Pullen 		return (0);
8574d61c878SJulian Pullen 	}
8584d61c878SJulian Pullen not_equal:
8594d61c878SJulian Pullen 	if (*value != NULL)
8604d61c878SJulian Pullen 		free_trusted_forests(value, num_value);
8614d61c878SJulian Pullen 	*value = *new;
8624d61c878SJulian Pullen 	*num_value = *num_new;
8634d61c878SJulian Pullen 	*new = NULL;
8644d61c878SJulian Pullen 	*num_new = 0;
8654d61c878SJulian Pullen 
8664d61c878SJulian Pullen 	if (*value == NULL) {
8674d61c878SJulian Pullen 		/* We're unsetting this DS property */
8684d61c878SJulian Pullen 		idmapdlog(LOG_INFO, "change %s=<none>", name);
8694d61c878SJulian Pullen 		return (1);
8704d61c878SJulian Pullen 	}
8714d61c878SJulian Pullen 
8724d61c878SJulian Pullen 	/* List all the trusted forests */
8734d61c878SJulian Pullen 	for (i = 0; i < *num_value; i++) {
8744d61c878SJulian Pullen 		for (j = 0; (*value)[i].domains_in_forest[j].domain[0] != '\0';
8754d61c878SJulian Pullen 		    j++) {
8764d61c878SJulian Pullen 			/* List trusted Domains in the forest. */
8774d61c878SJulian Pullen 			if ((*value)[i].domains_in_forest[j].trusted)
8784d61c878SJulian Pullen 				idmapdlog(LOG_INFO, "change %s=%s domain=%s",
8794d61c878SJulian Pullen 				    name, (*value)[i].forest_name,
8804d61c878SJulian Pullen 				    (*value)[i].domains_in_forest[j].domain);
8814d61c878SJulian Pullen 		}
8824d61c878SJulian Pullen 		/* List the hosts */
8834d61c878SJulian Pullen 		for (j = 0; (*value)[i].global_catalog[j].host[0] != '\0'; j++)
8844d61c878SJulian Pullen 			idmapdlog(LOG_INFO, "change %s=%s host=%s port=%d",
8854d61c878SJulian Pullen 			    name, (*value)[i].forest_name,
8864d61c878SJulian Pullen 			    (*value)[i].global_catalog[j].host,
8874d61c878SJulian Pullen 			    (*value)[i].global_catalog[j].port);
8884d61c878SJulian Pullen 	}
8894d61c878SJulian Pullen 	return (1);
8904d61c878SJulian Pullen }
8914d61c878SJulian Pullen 
892e3f2c991SKeyur Desai const char *
893e3f2c991SKeyur Desai enum_lookup(int value, struct enum_lookup_map *map)
894e3f2c991SKeyur Desai {
895e3f2c991SKeyur Desai 	for (; map->string != NULL; map++) {
896e3f2c991SKeyur Desai 		if (value == map->value) {
897e3f2c991SKeyur Desai 			return (map->string);
898e3f2c991SKeyur Desai 		}
899e3f2c991SKeyur Desai 	}
900e3f2c991SKeyur Desai 	return ("(invalid)");
901e3f2c991SKeyur Desai }
902c8e26105Sjp 
903c8e26105Sjp /*
9040dcc7149Snw  * Returns 1 if the PF_ROUTE socket event indicates that we should rescan the
9050dcc7149Snw  * interfaces.
906c8e26105Sjp  *
9070dcc7149Snw  * Shamelessly based on smb_nics_changed() and other PF_ROUTE uses in ON.
908c8e26105Sjp  */
909c8e26105Sjp static
910*c5866007SKeyur Desai boolean_t
9110dcc7149Snw pfroute_event_is_interesting(int rt_sock)
912c8e26105Sjp {
9130dcc7149Snw 	int nbytes;
9140dcc7149Snw 	int64_t msg[2048 / 8];
9150dcc7149Snw 	struct rt_msghdr *rtm;
916*c5866007SKeyur Desai 	boolean_t is_interesting = B_FALSE;
917c8e26105Sjp 
9180dcc7149Snw 	for (;;) {
9190dcc7149Snw 		if ((nbytes = read(rt_sock, msg, sizeof (msg))) <= 0)
9200dcc7149Snw 			break;
9210dcc7149Snw 		rtm = (struct rt_msghdr *)msg;
9220dcc7149Snw 		if (rtm->rtm_version != RTM_VERSION)
9230dcc7149Snw 			continue;
9240dcc7149Snw 		if (nbytes < rtm->rtm_msglen)
9250dcc7149Snw 			continue;
9260dcc7149Snw 		switch (rtm->rtm_type) {
9270dcc7149Snw 		case RTM_NEWADDR:
9280dcc7149Snw 		case RTM_DELADDR:
9290dcc7149Snw 		case RTM_IFINFO:
930*c5866007SKeyur Desai 			is_interesting = B_TRUE;
9310dcc7149Snw 			break;
9320dcc7149Snw 		default:
9330dcc7149Snw 			break;
9340dcc7149Snw 		}
935c8e26105Sjp 	}
9360dcc7149Snw 	return (is_interesting);
9370dcc7149Snw }
9380dcc7149Snw 
9390dcc7149Snw /*
940*c5866007SKeyur Desai  * Wait for an event, and report what kind of event occurred.
9410dcc7149Snw  *
942*c5866007SKeyur Desai  * Note that there are cases where we are awoken but don't care about
943*c5866007SKeyur Desai  * the lower-level event.  We can't just loop here because we can't
944*c5866007SKeyur Desai  * readily calculate how long to sleep the next time.  We return
945*c5866007SKeyur Desai  * EVENT_NOTHING and let the caller loop.
9460dcc7149Snw  */
9470dcc7149Snw static
948*c5866007SKeyur Desai enum event_type
949*c5866007SKeyur Desai wait_for_event(struct timespec *timeoutp)
9500dcc7149Snw {
9510dcc7149Snw 	port_event_t pe;
952c8e26105Sjp 
9530dcc7149Snw 	memset(&pe, 0, sizeof (pe));
954349d5d8fSnw 	if (port_get(idmapd_ev_port, &pe, timeoutp) != 0) {
955c8e26105Sjp 		switch (errno) {
956c8e26105Sjp 		case EINTR:
957*c5866007SKeyur Desai 			return (EVENT_NOTHING);
958c8e26105Sjp 		case ETIME:
959c8e26105Sjp 			/* Timeout */
960*c5866007SKeyur Desai 			return (EVENT_TIMEOUT);
961c8e26105Sjp 		default:
9620dcc7149Snw 			/* EBADF, EBADFD, EFAULT, EINVAL (end of time?)? */
9630dcc7149Snw 			idmapdlog(LOG_ERR, "Event port failed: %s",
9640dcc7149Snw 			    strerror(errno));
9650dcc7149Snw 			exit(1);
9660dcc7149Snw 			/* NOTREACHED */
967c8e26105Sjp 		}
968c8e26105Sjp 	}
969c8e26105Sjp 
9700dcc7149Snw 
971*c5866007SKeyur Desai 	switch (pe.portev_source) {
972*c5866007SKeyur Desai 	case 0:
9730dcc7149Snw 		/*
974*c5866007SKeyur Desai 		 * This isn't documented, but seems to be what you get if
975*c5866007SKeyur Desai 		 * the timeout is zero seconds and there are no events
976*c5866007SKeyur Desai 		 * pending.
9770dcc7149Snw 		 */
978*c5866007SKeyur Desai 		return (EVENT_TIMEOUT);
979c8e26105Sjp 
980*c5866007SKeyur Desai 	case PORT_SOURCE_USER:
981*c5866007SKeyur Desai 		if (pe.portev_events == POKE_AUTO_DISCOVERY)
982*c5866007SKeyur Desai 			return (EVENT_DEGRADE);
983*c5866007SKeyur Desai 		if (pe.portev_events == RECONFIGURE)
984*c5866007SKeyur Desai 			return (EVENT_REFRESH);
985*c5866007SKeyur Desai 		break;
986e3c2d6aaSnw 
987*c5866007SKeyur Desai 	case PORT_SOURCE_FD:
988*c5866007SKeyur Desai 		if (pe.portev_object == rt_sock) {
989*c5866007SKeyur Desai 			/*
990*c5866007SKeyur Desai 			 * PF_ROUTE socket read event:
991*c5866007SKeyur Desai 			 *    re-associate fd
992*c5866007SKeyur Desai 			 *    handle event
993*c5866007SKeyur Desai 			 */
994*c5866007SKeyur Desai 			if (port_associate(idmapd_ev_port, PORT_SOURCE_FD,
995*c5866007SKeyur Desai 			    rt_sock, POLLIN, NULL) != 0) {
996*c5866007SKeyur Desai 				idmapdlog(LOG_ERR, "Failed to re-associate the "
997*c5866007SKeyur Desai 				    "routing socket with the event port: %s",
998*c5866007SKeyur Desai 				    strerror(errno));
999*c5866007SKeyur Desai 				abort();
1000*c5866007SKeyur Desai 			}
1001*c5866007SKeyur Desai 			/*
1002*c5866007SKeyur Desai 			 * The network configuration may still be in flux.
1003*c5866007SKeyur Desai 			 * No matter, the resolver will re-transmit and
1004*c5866007SKeyur Desai 			 * timeout if need be.
1005*c5866007SKeyur Desai 			 */
1006*c5866007SKeyur Desai 			if (pfroute_event_is_interesting(rt_sock)) {
1007*c5866007SKeyur Desai 				idmapdlog(LOG_DEBUG,
1008*c5866007SKeyur Desai 				    "Interesting routing event");
1009*c5866007SKeyur Desai 				return (EVENT_ROUTING);
1010*c5866007SKeyur Desai 			} else {
1011*c5866007SKeyur Desai 				idmapdlog(LOG_DEBUG,
1012*c5866007SKeyur Desai 				    "Boring routing event");
1013*c5866007SKeyur Desai 				return (EVENT_NOTHING);
1014*c5866007SKeyur Desai 			}
1015349d5d8fSnw 		}
1016*c5866007SKeyur Desai 		/* Event on an FD other than the routing FD? Ignore it. */
1017*c5866007SKeyur Desai 		break;
1018c8e26105Sjp 	}
1019c8e26105Sjp 
1020*c5866007SKeyur Desai 	return (EVENT_NOTHING);
1021c8e26105Sjp }
1022c8e26105Sjp 
1023c8e26105Sjp void *
1024c8e26105Sjp idmap_cfg_update_thread(void *arg)
1025c8e26105Sjp {
1026c8e26105Sjp 
1027*c5866007SKeyur Desai 	const ad_disc_t		ad_ctx = _idmapdstate.cfg->handles.ad_ctx;
10280dcc7149Snw 
1029*c5866007SKeyur Desai 	for (;;) {
1030*c5866007SKeyur Desai 		struct timespec timeout;
1031*c5866007SKeyur Desai 		struct timespec	*timeoutp;
1032*c5866007SKeyur Desai 		int		rc;
1033*c5866007SKeyur Desai 		int		ttl;
10340dcc7149Snw 
10350dcc7149Snw 		(void) ad_disc_SubnetChanged(ad_ctx);
1036c8e26105Sjp 
1037*c5866007SKeyur Desai 		rc = idmap_cfg_load(_idmapdstate.cfg, CFG_DISCOVER);
1038*c5866007SKeyur Desai 		if (rc < -1) {
10397a8a68f5SJulian Pullen 			idmapdlog(LOG_ERR, "Fatal errors while reading "
1040349d5d8fSnw 			    "SMF properties");
1041349d5d8fSnw 			exit(1);
1042*c5866007SKeyur Desai 		} else if (rc == -1) {
1043*c5866007SKeyur Desai 			idmapdlog(LOG_WARNING,
1044*c5866007SKeyur Desai 			    "Errors re-loading configuration may cause AD "
1045*c5866007SKeyur Desai 			    "lookups to fail");
1046349d5d8fSnw 		}
1047c8e26105Sjp 
1048*c5866007SKeyur Desai 		/*
1049*c5866007SKeyur Desai 		 * Wait for an interesting event.  Note that we might get
1050*c5866007SKeyur Desai 		 * boring events between interesting events.  If so, we loop.
1051*c5866007SKeyur Desai 		 */
1052*c5866007SKeyur Desai 		for (;;) {
1053*c5866007SKeyur Desai 			ttl = ad_disc_get_TTL(ad_ctx);
1054*c5866007SKeyur Desai 
1055*c5866007SKeyur Desai 			if (ttl < 0) {
1056*c5866007SKeyur Desai 				timeoutp = NULL;
1057*c5866007SKeyur Desai 			} else {
1058*c5866007SKeyur Desai 				timeoutp = &timeout;
1059*c5866007SKeyur Desai 				timeout.tv_sec = ttl;
1060*c5866007SKeyur Desai 				timeout.tv_nsec = 0;
1061*c5866007SKeyur Desai 			}
1062*c5866007SKeyur Desai 
1063*c5866007SKeyur Desai 			switch (wait_for_event(timeoutp)) {
1064*c5866007SKeyur Desai 			case EVENT_NOTHING:
1065*c5866007SKeyur Desai 				idmapdlog(LOG_DEBUG, "Boring event.");
1066*c5866007SKeyur Desai 				continue;
1067*c5866007SKeyur Desai 			case EVENT_REFRESH:
1068*c5866007SKeyur Desai 				idmapdlog(LOG_INFO, "SMF refresh");
1069*c5866007SKeyur Desai 				/*
1070*c5866007SKeyur Desai 				 * Blow away the ccache, we might have
1071*c5866007SKeyur Desai 				 * re-joined the domain or joined a new one
1072*c5866007SKeyur Desai 				 */
1073*c5866007SKeyur Desai 				(void) unlink(IDMAP_CACHEDIR "/ccache");
1074*c5866007SKeyur Desai 				break;
1075*c5866007SKeyur Desai 			case EVENT_DEGRADE:
1076*c5866007SKeyur Desai 				idmapdlog(LOG_DEBUG,
1077*c5866007SKeyur Desai 				    "Service degraded");
1078*c5866007SKeyur Desai 				break;
1079*c5866007SKeyur Desai 			case EVENT_TIMEOUT:
1080*c5866007SKeyur Desai 				idmapdlog(LOG_DEBUG, "TTL expired");
1081*c5866007SKeyur Desai 				break;
1082*c5866007SKeyur Desai 			case EVENT_ROUTING:
1083*c5866007SKeyur Desai 				/* Already logged to DEBUG */
1084*c5866007SKeyur Desai 				break;
1085*c5866007SKeyur Desai 			}
1086*c5866007SKeyur Desai 			/* An interesting event! */
1087*c5866007SKeyur Desai 			break;
1088*c5866007SKeyur Desai 		}
1089c8e26105Sjp 	}
1090*c5866007SKeyur Desai 	/*
1091*c5866007SKeyur Desai 	 * Lint isn't happy with the concept of a function declared to
1092*c5866007SKeyur Desai 	 * return something, that doesn't return.  Of course, merely adding
1093*c5866007SKeyur Desai 	 * the return isn't enough, because it's never reached...
1094*c5866007SKeyur Desai 	 */
1095c8e26105Sjp 	/*NOTREACHED*/
1096c8e26105Sjp 	return (NULL);
1097c8e26105Sjp }
1098c8e26105Sjp 
1099c8e26105Sjp int
11000dcc7149Snw idmap_cfg_start_updates(void)
1101c8e26105Sjp {
11020dcc7149Snw 	if ((idmapd_ev_port = port_create()) < 0) {
110371590c90Snw 		idmapdlog(LOG_ERR, "Failed to create event port: %s",
110471590c90Snw 		    strerror(errno));
1105c8e26105Sjp 		return (-1);
11060dcc7149Snw 	}
11070dcc7149Snw 
11080dcc7149Snw 	if ((rt_sock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
110971590c90Snw 		idmapdlog(LOG_ERR, "Failed to open routing socket: %s",
111071590c90Snw 		    strerror(errno));
11110dcc7149Snw 		(void) close(idmapd_ev_port);
11120dcc7149Snw 		return (-1);
11130dcc7149Snw 	}
11140dcc7149Snw 
11150dcc7149Snw 	if (fcntl(rt_sock, F_SETFL, O_NDELAY|O_NONBLOCK) < 0) {
111671590c90Snw 		idmapdlog(LOG_ERR, "Failed to set routing socket flags: %s",
111771590c90Snw 		    strerror(errno));
11180dcc7149Snw 		(void) close(rt_sock);
11190dcc7149Snw 		(void) close(idmapd_ev_port);
11200dcc7149Snw 		return (-1);
11210dcc7149Snw 	}
11220dcc7149Snw 
11230dcc7149Snw 	if (port_associate(idmapd_ev_port, PORT_SOURCE_FD,
11240dcc7149Snw 	    rt_sock, POLLIN, NULL) != 0) {
112571590c90Snw 		idmapdlog(LOG_ERR, "Failed to associate the routing "
112671590c90Snw 		    "socket with the event port: %s", strerror(errno));
11270dcc7149Snw 		(void) close(rt_sock);
11280dcc7149Snw 		(void) close(idmapd_ev_port);
11290dcc7149Snw 		return (-1);
11300dcc7149Snw 	}
11310dcc7149Snw 
11320dcc7149Snw 	if ((errno = pthread_create(&update_thread_handle, NULL,
11330dcc7149Snw 	    idmap_cfg_update_thread, NULL)) != 0) {
113471590c90Snw 		idmapdlog(LOG_ERR, "Failed to start update thread: %s",
113571590c90Snw 		    strerror(errno));
11360dcc7149Snw 		(void) port_dissociate(idmapd_ev_port, PORT_SOURCE_FD, rt_sock);
11370dcc7149Snw 		(void) close(rt_sock);
11380dcc7149Snw 		(void) close(idmapd_ev_port);
11390dcc7149Snw 		return (-1);
11400dcc7149Snw 	}
11410dcc7149Snw 
11420dcc7149Snw 	return (0);
1143c8e26105Sjp }
1144c8e26105Sjp 
1145479ac375Sdm /*
1146479ac375Sdm  * Reject attribute names with invalid characters.
1147479ac375Sdm  */
1148479ac375Sdm static
1149479ac375Sdm int
1150479ac375Sdm valid_ldap_attr(const char *attr) {
1151479ac375Sdm 	for (; *attr; attr++) {
1152479ac375Sdm 		if (!isalnum(*attr) && *attr != '-' &&
1153479ac375Sdm 		    *attr != '_' && *attr != '.' && *attr != ';')
1154479ac375Sdm 			return (0);
1155479ac375Sdm 	}
1156479ac375Sdm 	return (1);
1157479ac375Sdm }
1158479ac375Sdm 
1159e3f2c991SKeyur Desai static
1160e3f2c991SKeyur Desai int
1161e3f2c991SKeyur Desai check_smf_debug_mode(idmap_cfg_handles_t *handles)
1162e3f2c991SKeyur Desai {
1163e3f2c991SKeyur Desai 	boolean_t new_debug_mode;
1164e3f2c991SKeyur Desai 	int rc;
1165e3f2c991SKeyur Desai 
1166e3f2c991SKeyur Desai 	rc = prop_exists(handles, "debug", &new_debug_mode);
1167e3f2c991SKeyur Desai 	if (rc != 0)
1168e3f2c991SKeyur Desai 		return (rc);
1169e3f2c991SKeyur Desai 
1170e3f2c991SKeyur Desai 	if (_idmapdstate.debug_mode != new_debug_mode) {
1171e3f2c991SKeyur Desai 		if (!_idmapdstate.debug_mode) {
1172e3f2c991SKeyur Desai 			_idmapdstate.debug_mode = new_debug_mode;
1173e3f2c991SKeyur Desai 			idmap_log_stderr(LOG_DEBUG);
1174e3f2c991SKeyur Desai 			idmapdlog(LOG_DEBUG, "debug mode enabled");
1175e3f2c991SKeyur Desai 		} else {
1176e3f2c991SKeyur Desai 			idmapdlog(LOG_DEBUG, "debug mode disabled");
1177e3f2c991SKeyur Desai 			idmap_log_stderr(-1);
1178e3f2c991SKeyur Desai 			_idmapdstate.debug_mode = new_debug_mode;
1179e3f2c991SKeyur Desai 		}
1180e3f2c991SKeyur Desai 	}
1181e3f2c991SKeyur Desai 
1182e3f2c991SKeyur Desai 	return (0);
1183e3f2c991SKeyur Desai }
1184e3f2c991SKeyur Desai 
1185349d5d8fSnw /*
1186349d5d8fSnw  * This is the half of idmap_cfg_load() that loads property values from
1187349d5d8fSnw  * SMF (using the config/ property group of the idmap FMRI).
1188349d5d8fSnw  *
1189349d5d8fSnw  * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
1190479ac375Sdm  *               -3 -> hard smf config failures
1191349d5d8fSnw  * reading from SMF.
1192349d5d8fSnw  */
1193349d5d8fSnw static
1194c5c4113dSnw int
1195349d5d8fSnw idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
1196e3f2c991SKeyur Desai 	int * const errors)
1197c5c4113dSnw {
1198e3c2d6aaSnw 	int rc;
1199e3f2c991SKeyur Desai 	char *s;
1200e3f2c991SKeyur Desai 
1201e3f2c991SKeyur Desai 	*errors = 0;
1202c8e26105Sjp 
1203c8e26105Sjp 	if (scf_pg_update(handles->config_pg) < 0) {
120471590c90Snw 		idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
120571590c90Snw 		    scf_strerror(scf_error()));
1206349d5d8fSnw 		return (-2);
1207c5c4113dSnw 	}
1208c5c4113dSnw 
1209c8e26105Sjp 	if (scf_pg_update(handles->general_pg) < 0) {
121071590c90Snw 		idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
121171590c90Snw 		    scf_strerror(scf_error()));
1212349d5d8fSnw 		return (-2);
1213c5c4113dSnw 	}
1214c5c4113dSnw 
1215e3f2c991SKeyur Desai 	rc = check_smf_debug_mode(handles);
1216479ac375Sdm 	if (rc != 0)
1217e3f2c991SKeyur Desai 		(*errors)++;
121871590c90Snw 
12194aa0a5e7Snw 	rc = get_val_int(handles, "unresolvable_sid_mapping",
12204aa0a5e7Snw 	    &pgcfg->eph_map_unres_sids, SCF_TYPE_BOOLEAN);
12214aa0a5e7Snw 	if (rc != 0)
1222e3f2c991SKeyur Desai 		(*errors)++;
1223e3f2c991SKeyur Desai 
1224e3f2c991SKeyur Desai 	rc = get_val_astring(handles, "directory_based_mapping", &s);
1225e3f2c991SKeyur Desai 	if (rc != 0)
1226e3f2c991SKeyur Desai 		(*errors)++;
1227e3f2c991SKeyur Desai 	else if (s == NULL || strcasecmp(s, "none") == 0)
1228e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1229e3f2c991SKeyur Desai 	else if (strcasecmp(s, "name") == 0)
1230e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NAME;
1231e3f2c991SKeyur Desai 	else if (strcasecmp(s, "idmu") == 0)
1232e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_IDMU;
1233e3f2c991SKeyur Desai 	else {
1234e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1235e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
1236e3f2c991SKeyur Desai 		"config/directory_based_mapping:  invalid value \"%s\" ignored",
1237e3f2c991SKeyur Desai 		    s);
1238e3f2c991SKeyur Desai 		(*errors)++;
1239e3f2c991SKeyur Desai 	}
1240e3f2c991SKeyur Desai 	free(s);
12414aa0a5e7Snw 
1242c8e26105Sjp 	rc = get_val_int(handles, "list_size_limit",
1243c8e26105Sjp 	    &pgcfg->list_size_limit, SCF_TYPE_COUNT);
12444aa0a5e7Snw 	if (rc != 0)
1245e3f2c991SKeyur Desai 		(*errors)++;
1246c5c4113dSnw 
1247c8e26105Sjp 	rc = get_val_astring(handles, "domain_name",
1248c8e26105Sjp 	    &pgcfg->domain_name);
1249e3c2d6aaSnw 	if (rc != 0)
1250e3f2c991SKeyur Desai 		(*errors)++;
12514d61c878SJulian Pullen 	else {
1252349d5d8fSnw 		(void) ad_disc_set_DomainName(handles->ad_ctx,
1253349d5d8fSnw 		    pgcfg->domain_name);
12547a8a68f5SJulian Pullen 		pgcfg->domain_name_auto_disc = B_FALSE;
12554d61c878SJulian Pullen 	}
1256c8e26105Sjp 
1257c8e26105Sjp 	rc = get_val_astring(handles, "default_domain",
1258c8e26105Sjp 	    &pgcfg->default_domain);
1259c8e26105Sjp 	if (rc != 0) {
1260e3c2d6aaSnw 		/*
1261e3c2d6aaSnw 		 * SCF failures fetching config/default_domain we treat
1262e3c2d6aaSnw 		 * as fatal as they may leave ID mapping rules that
1263e3c2d6aaSnw 		 * match unqualified winnames flapping in the wind.
1264e3c2d6aaSnw 		 */
1265349d5d8fSnw 		return (-2);
1266c8e26105Sjp 	}
1267c8e26105Sjp 
1268e3f2c991SKeyur Desai 	if (pgcfg->default_domain == NULL && pgcfg->domain_name != NULL) {
1269e3f2c991SKeyur Desai 		pgcfg->default_domain = strdup(pgcfg->domain_name);
1270c5c4113dSnw 	}
1271c5c4113dSnw 
1272c8e26105Sjp 	rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid);
1273e3c2d6aaSnw 	if (rc != 0)
1274e3f2c991SKeyur Desai 		(*errors)++;
1275c8e26105Sjp 	if (pgcfg->machine_sid == NULL) {
12768edda628Sbaban 		/* If machine_sid not configured, generate one */
1277349d5d8fSnw 		if (generate_machine_sid(&pgcfg->machine_sid) < 0)
1278349d5d8fSnw 			return (-2);
1279c8e26105Sjp 		rc = set_val_astring(handles, "machine_sid",
1280c8e26105Sjp 		    pgcfg->machine_sid);
1281e3c2d6aaSnw 		if (rc != 0)
1282e3f2c991SKeyur Desai 			(*errors)++;
12838edda628Sbaban 	}
1284c5c4113dSnw 
1285c8e26105Sjp 	rc = get_val_ds(handles, "domain_controller", 389,
1286c8e26105Sjp 	    &pgcfg->domain_controller);
1287e3c2d6aaSnw 	if (rc != 0)
1288e3f2c991SKeyur Desai 		(*errors)++;
12894d61c878SJulian Pullen 	else {
1290349d5d8fSnw 		(void) ad_disc_set_DomainController(handles->ad_ctx,
1291e3c2d6aaSnw 		    pgcfg->domain_controller);
12927a8a68f5SJulian Pullen 		pgcfg->domain_controller_auto_disc = B_FALSE;
12934d61c878SJulian Pullen 	}
1294c5c4113dSnw 
1295c8e26105Sjp 	rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name);
1296e3c2d6aaSnw 	if (rc != 0)
1297e3f2c991SKeyur Desai 		(*errors)++;
12984d61c878SJulian Pullen 	else {
1299349d5d8fSnw 		(void) ad_disc_set_ForestName(handles->ad_ctx,
1300349d5d8fSnw 		    pgcfg->forest_name);
13017a8a68f5SJulian Pullen 		pgcfg->forest_name_auto_disc = B_FALSE;
13024d61c878SJulian Pullen 	}
1303c8e26105Sjp 
1304c8e26105Sjp 	rc = get_val_astring(handles, "site_name", &pgcfg->site_name);
1305e3c2d6aaSnw 	if (rc != 0)
1306e3f2c991SKeyur Desai 		(*errors)++;
1307e3c2d6aaSnw 	else
1308349d5d8fSnw 		(void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name);
1309c8e26105Sjp 
1310c8e26105Sjp 	rc = get_val_ds(handles, "global_catalog", 3268,
1311c8e26105Sjp 	    &pgcfg->global_catalog);
1312e3c2d6aaSnw 	if (rc != 0)
1313e3f2c991SKeyur Desai 		(*errors)++;
13144d61c878SJulian Pullen 	else {
1315349d5d8fSnw 		(void) ad_disc_set_GlobalCatalog(handles->ad_ctx,
1316349d5d8fSnw 		    pgcfg->global_catalog);
13177a8a68f5SJulian Pullen 		pgcfg->global_catalog_auto_disc = B_FALSE;
13184d61c878SJulian Pullen 	}
1319c8e26105Sjp 
1320e3f2c991SKeyur Desai 	/* Unless we're doing directory-based name mapping, we're done. */
1321e3f2c991SKeyur Desai 	if (pgcfg->directory_based_mapping != DIRECTORY_MAPPING_NAME)
1322e3f2c991SKeyur Desai 		return (0);
1323e8c27ec8Sbaban 
1324349d5d8fSnw 	rc = get_val_astring(handles, "ad_unixuser_attr",
1325349d5d8fSnw 	    &pgcfg->ad_unixuser_attr);
1326349d5d8fSnw 	if (rc != 0)
1327349d5d8fSnw 		return (-2);
1328479ac375Sdm 	if (pgcfg->ad_unixuser_attr != NULL &&
1329479ac375Sdm 	    !valid_ldap_attr(pgcfg->ad_unixuser_attr)) {
1330479ac375Sdm 		idmapdlog(LOG_ERR, "config/ad_unixuser_attr=%s is not a "
1331479ac375Sdm 		    "valid LDAP attribute name", pgcfg->ad_unixuser_attr);
1332479ac375Sdm 		return (-3);
1333479ac375Sdm 	}
1334e8c27ec8Sbaban 
1335349d5d8fSnw 	rc = get_val_astring(handles, "ad_unixgroup_attr",
1336349d5d8fSnw 	    &pgcfg->ad_unixgroup_attr);
1337349d5d8fSnw 	if (rc != 0)
1338349d5d8fSnw 		return (-2);
1339479ac375Sdm 	if (pgcfg->ad_unixgroup_attr != NULL &&
1340479ac375Sdm 	    !valid_ldap_attr(pgcfg->ad_unixgroup_attr)) {
1341479ac375Sdm 		idmapdlog(LOG_ERR, "config/ad_unixgroup_attr=%s is not a "
1342479ac375Sdm 		    "valid LDAP attribute name", pgcfg->ad_unixgroup_attr);
1343479ac375Sdm 		return (-3);
1344479ac375Sdm 	}
1345e8c27ec8Sbaban 
1346349d5d8fSnw 	rc = get_val_astring(handles, "nldap_winname_attr",
1347349d5d8fSnw 	    &pgcfg->nldap_winname_attr);
1348349d5d8fSnw 	if (rc != 0)
1349349d5d8fSnw 		return (-2);
1350479ac375Sdm 	if (pgcfg->nldap_winname_attr != NULL &&
1351479ac375Sdm 	    !valid_ldap_attr(pgcfg->nldap_winname_attr)) {
1352479ac375Sdm 		idmapdlog(LOG_ERR, "config/nldap_winname_attr=%s is not a "
1353479ac375Sdm 		    "valid LDAP attribute name", pgcfg->nldap_winname_attr);
1354349d5d8fSnw 		return (-3);
1355e8c27ec8Sbaban 	}
1356349d5d8fSnw 	if (pgcfg->ad_unixuser_attr == NULL &&
1357479ac375Sdm 	    pgcfg->ad_unixgroup_attr == NULL &&
1358479ac375Sdm 	    pgcfg->nldap_winname_attr == NULL) {
1359349d5d8fSnw 		idmapdlog(LOG_ERR,
1360e3f2c991SKeyur Desai 		    "If config/directory_based_mapping property is set to "
1361e3f2c991SKeyur Desai 		    "\"name\" then at least one of the following name mapping "
1362349d5d8fSnw 		    "attributes must be specified. (config/ad_unixuser_attr OR "
1363479ac375Sdm 		    "config/ad_unixgroup_attr OR config/nldap_winname_attr)");
1364349d5d8fSnw 		return (-3);
1365349d5d8fSnw 	}
1366c8e26105Sjp 
1367349d5d8fSnw 	return (rc);
1368e3c2d6aaSnw 
1369349d5d8fSnw }
1370349d5d8fSnw 
13714d61c878SJulian Pullen 
1372349d5d8fSnw /*
1373349d5d8fSnw  * This is the half of idmap_cfg_load() that auto-discovers values of
1374349d5d8fSnw  * discoverable properties that weren't already set via SMF properties.
1375349d5d8fSnw  *
1376349d5d8fSnw  * idmap_cfg_discover() is called *after* idmap_cfg_load_smf(), so it
1377349d5d8fSnw  * needs to be careful not to overwrite any properties set in SMF.
1378349d5d8fSnw  */
1379349d5d8fSnw static
1380349d5d8fSnw void
1381349d5d8fSnw idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
1382349d5d8fSnw {
1383349d5d8fSnw 	ad_disc_t ad_ctx = handles->ad_ctx;
13844d61c878SJulian Pullen 	ad_disc_t trusted_ctx;
13854d61c878SJulian Pullen 	int i, j, k, l;
13864d61c878SJulian Pullen 	char *forestname;
13874d61c878SJulian Pullen 	int num_trusteddomains;
13887a8a68f5SJulian Pullen 	boolean_t new_forest;
13894d61c878SJulian Pullen 	char *trusteddomain;
13904d61c878SJulian Pullen 	idmap_ad_disc_ds_t *globalcatalog;
13914d61c878SJulian Pullen 	idmap_trustedforest_t *trustedforests;
13924d61c878SJulian Pullen 	ad_disc_domainsinforest_t *domainsinforest;
1393349d5d8fSnw 
1394*c5866007SKeyur Desai 	idmapdlog(LOG_DEBUG, "Running discovery.");
1395*c5866007SKeyur Desai 
1396349d5d8fSnw 	ad_disc_refresh(ad_ctx);
1397349d5d8fSnw 
1398349d5d8fSnw 	if (pgcfg->default_domain == NULL)
13994d61c878SJulian Pullen 		pgcfg->default_domain = ad_disc_get_DomainName(ad_ctx,
14004d61c878SJulian Pullen 		    NULL);
1401c8e26105Sjp 
1402349d5d8fSnw 	if (pgcfg->domain_name == NULL)
14034d61c878SJulian Pullen 		pgcfg->domain_name = ad_disc_get_DomainName(ad_ctx,
14044d61c878SJulian Pullen 		    &pgcfg->domain_name_auto_disc);
1405c8e26105Sjp 
1406349d5d8fSnw 	if (pgcfg->domain_controller == NULL)
1407c8e26105Sjp 		pgcfg->domain_controller =
14084d61c878SJulian Pullen 		    ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE,
14094d61c878SJulian Pullen 		    &pgcfg->domain_controller_auto_disc);
1410c8e26105Sjp 
1411349d5d8fSnw 	if (pgcfg->forest_name == NULL)
14124d61c878SJulian Pullen 		pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx,
14134d61c878SJulian Pullen 		    &pgcfg->forest_name_auto_disc);
1414c8e26105Sjp 
1415349d5d8fSnw 	if (pgcfg->site_name == NULL)
14164d61c878SJulian Pullen 		pgcfg->site_name = ad_disc_get_SiteName(ad_ctx,
14174d61c878SJulian Pullen 		    &pgcfg->site_name_auto_disc);
1418c8e26105Sjp 
1419349d5d8fSnw 	if (pgcfg->global_catalog == NULL)
1420c8e26105Sjp 		pgcfg->global_catalog =
14214d61c878SJulian Pullen 		    ad_disc_get_GlobalCatalog(ad_ctx, AD_DISC_PREFER_SITE,
14224d61c878SJulian Pullen 		    &pgcfg->global_catalog_auto_disc);
14234d61c878SJulian Pullen 
14244d61c878SJulian Pullen 	pgcfg->domains_in_forest =
14254d61c878SJulian Pullen 	    ad_disc_get_DomainsInForest(ad_ctx, NULL);
14264d61c878SJulian Pullen 
14274d61c878SJulian Pullen 	pgcfg->trusted_domains =
14284d61c878SJulian Pullen 	    ad_disc_get_TrustedDomains(ad_ctx, NULL);
14294d61c878SJulian Pullen 
14304d61c878SJulian Pullen 	if (pgcfg->forest_name != NULL && pgcfg->trusted_domains != NULL &&
14314d61c878SJulian Pullen 	    pgcfg->trusted_domains[0].domain[0] != '\0') {
14324d61c878SJulian Pullen 		/*
14334d61c878SJulian Pullen 		 * We have trusted domains.  We need to go through every
14344d61c878SJulian Pullen 		 * one and find its forest. If it is a new forest we then need
14354d61c878SJulian Pullen 		 * to find its Global Catalog and the domains in the forest
14364d61c878SJulian Pullen 		 */
14374d61c878SJulian Pullen 		for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++)
14384d61c878SJulian Pullen 			continue;
14394d61c878SJulian Pullen 		num_trusteddomains = i;
14404d61c878SJulian Pullen 
14414d61c878SJulian Pullen 		trustedforests = calloc(num_trusteddomains,
14424d61c878SJulian Pullen 		    sizeof (idmap_trustedforest_t));
14434d61c878SJulian Pullen 		j = 0;
14444d61c878SJulian Pullen 		for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) {
14454d61c878SJulian Pullen 			trusteddomain = pgcfg->trusted_domains[i].domain;
14464d61c878SJulian Pullen 			trusted_ctx = ad_disc_init();
14474d61c878SJulian Pullen 			ad_disc_set_DomainName(trusted_ctx,
14484d61c878SJulian Pullen 			    trusteddomain);
14494d61c878SJulian Pullen 			forestname =
14504d61c878SJulian Pullen 			    ad_disc_get_ForestName(trusted_ctx, NULL);
14514d61c878SJulian Pullen 			if (forestname == NULL) {
14524d61c878SJulian Pullen 				idmapdlog(LOG_DEBUG, "unable to discover "
14534d61c878SJulian Pullen 				    "Forest Name for the trusted domain %s",
14544d61c878SJulian Pullen 				    trusteddomain);
14554d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
14564d61c878SJulian Pullen 				continue;
14574d61c878SJulian Pullen 			}
14584d61c878SJulian Pullen 
14594d61c878SJulian Pullen 			if (strcasecmp(forestname, pgcfg->forest_name) == 0) {
14604d61c878SJulian Pullen 				/*
14614d61c878SJulian Pullen 				 * Ignore the domain as it is part of
14624d61c878SJulian Pullen 				 * the primary forest
14634d61c878SJulian Pullen 				 */
14644d61c878SJulian Pullen 				free(forestname);
14654d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
14664d61c878SJulian Pullen 				continue;
14674d61c878SJulian Pullen 			}
14684d61c878SJulian Pullen 
14694d61c878SJulian Pullen 			/* Is this a new forest? */
14707a8a68f5SJulian Pullen 			new_forest = B_TRUE;
14714d61c878SJulian Pullen 			for (k = 0; k < j; k++) {
14724d61c878SJulian Pullen 				if (strcasecmp(forestname,
14734d61c878SJulian Pullen 				    trustedforests[k].forest_name) == 0) {
14747a8a68f5SJulian Pullen 					new_forest = B_FALSE;
14754d61c878SJulian Pullen 					domainsinforest =
14764d61c878SJulian Pullen 					    trustedforests[k].domains_in_forest;
14774d61c878SJulian Pullen 					break;
14784d61c878SJulian Pullen 				}
14794d61c878SJulian Pullen 			}
14804d61c878SJulian Pullen 			if (!new_forest) {
14814d61c878SJulian Pullen 				/* Mark the domain as trusted */
14824d61c878SJulian Pullen 				for (l = 0;
14834d61c878SJulian Pullen 				    domainsinforest[l].domain[0] != '\0'; l++) {
14841fcced4cSJordan Brown 					if (domain_eq(trusteddomain,
14851fcced4cSJordan Brown 					    domainsinforest[l].domain)) {
14864d61c878SJulian Pullen 						domainsinforest[l].trusted =
14874d61c878SJulian Pullen 						    TRUE;
14884d61c878SJulian Pullen 						break;
14894d61c878SJulian Pullen 					}
14904d61c878SJulian Pullen 				}
14914d61c878SJulian Pullen 				free(forestname);
14924d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
14934d61c878SJulian Pullen 				continue;
14944d61c878SJulian Pullen 			}
14954d61c878SJulian Pullen 
14964d61c878SJulian Pullen 			/*
14974d61c878SJulian Pullen 			 * Get the Global Catalog and the domains in
14984d61c878SJulian Pullen 			 * this new forest.
14994d61c878SJulian Pullen 			 */
15004d61c878SJulian Pullen 			globalcatalog =
15014d61c878SJulian Pullen 			    ad_disc_get_GlobalCatalog(trusted_ctx,
15024d61c878SJulian Pullen 			    AD_DISC_PREFER_SITE, NULL);
15034d61c878SJulian Pullen 			if (globalcatalog == NULL) {
15044d61c878SJulian Pullen 				idmapdlog(LOG_DEBUG,
15054d61c878SJulian Pullen 				    "unable to discover Global "
15064d61c878SJulian Pullen 				    "Catalog for the trusted domain %s",
15074d61c878SJulian Pullen 				    trusteddomain);
15084d61c878SJulian Pullen 				free(forestname);
15094d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
15104d61c878SJulian Pullen 				continue;
15114d61c878SJulian Pullen 			}
15124d61c878SJulian Pullen 			domainsinforest =
15134d61c878SJulian Pullen 			    ad_disc_get_DomainsInForest(trusted_ctx,
15144d61c878SJulian Pullen 			    NULL);
15154d61c878SJulian Pullen 			if (domainsinforest == NULL) {
15164d61c878SJulian Pullen 				idmapdlog(LOG_DEBUG,
15174d61c878SJulian Pullen 				    "unable to discover Domains in the Forest "
15184d61c878SJulian Pullen 				    "for the trusted domain %s",
15194d61c878SJulian Pullen 				    trusteddomain);
15204d61c878SJulian Pullen 				free(globalcatalog);
15214d61c878SJulian Pullen 				free(forestname);
15224d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
15234d61c878SJulian Pullen 				continue;
15244d61c878SJulian Pullen 			}
15254d61c878SJulian Pullen 
15264d61c878SJulian Pullen 			trustedforests[j].forest_name = forestname;
15274d61c878SJulian Pullen 			trustedforests[j].global_catalog = globalcatalog;
15284d61c878SJulian Pullen 			trustedforests[j].domains_in_forest = domainsinforest;
15294d61c878SJulian Pullen 			j++;
15304d61c878SJulian Pullen 			/* Mark the domain as trusted */
15314d61c878SJulian Pullen 			for (l = 0; domainsinforest[l].domain[0] != '\0';
15324d61c878SJulian Pullen 			    l++) {
15331fcced4cSJordan Brown 				if (domain_eq(trusteddomain,
15341fcced4cSJordan Brown 				    domainsinforest[l].domain)) {
15354d61c878SJulian Pullen 					domainsinforest[l].trusted = TRUE;
15364d61c878SJulian Pullen 					break;
15374d61c878SJulian Pullen 				}
15384d61c878SJulian Pullen 			}
15394d61c878SJulian Pullen 			ad_disc_fini(trusted_ctx);
15404d61c878SJulian Pullen 		}
15414d61c878SJulian Pullen 		if (j > 0) {
15424d61c878SJulian Pullen 			pgcfg->num_trusted_forests = j;
15434d61c878SJulian Pullen 			pgcfg->trusted_forests = trustedforests;
15441fcced4cSJordan Brown 		} else {
15451fcced4cSJordan Brown 			free(trustedforests);
15464d61c878SJulian Pullen 		}
15474d61c878SJulian Pullen 	}
1548349d5d8fSnw 
1549349d5d8fSnw 	if (pgcfg->domain_name == NULL)
1550349d5d8fSnw 		idmapdlog(LOG_DEBUG, "unable to discover Domain Name");
1551349d5d8fSnw 	if (pgcfg->domain_controller == NULL)
1552349d5d8fSnw 		idmapdlog(LOG_DEBUG, "unable to discover Domain Controller");
1553349d5d8fSnw 	if (pgcfg->forest_name == NULL)
1554349d5d8fSnw 		idmapdlog(LOG_DEBUG, "unable to discover Forest Name");
1555349d5d8fSnw 	if (pgcfg->site_name == NULL)
1556349d5d8fSnw 		idmapdlog(LOG_DEBUG, "unable to discover Site Name");
1557349d5d8fSnw 	if (pgcfg->global_catalog == NULL)
1558349d5d8fSnw 		idmapdlog(LOG_DEBUG, "unable to discover Global Catalog");
15594d61c878SJulian Pullen 	if (pgcfg->domains_in_forest == NULL)
15604d61c878SJulian Pullen 		idmapdlog(LOG_DEBUG,
15614d61c878SJulian Pullen 		    "unable to discover Domains in the Forest");
15624d61c878SJulian Pullen 	if (pgcfg->trusted_domains == NULL)
15634d61c878SJulian Pullen 		idmapdlog(LOG_DEBUG, "unable to discover Trusted Domains");
1564*c5866007SKeyur Desai 
1565*c5866007SKeyur Desai 	ad_disc_done(ad_ctx);
1566*c5866007SKeyur Desai 	idmapdlog(LOG_DEBUG, "Discovery done.");
1567349d5d8fSnw }
1568349d5d8fSnw 
15694d61c878SJulian Pullen 
1570349d5d8fSnw /*
1571349d5d8fSnw  * idmap_cfg_load() is called at startup, and periodically via the
1572349d5d8fSnw  * update thread when the auto-discovery TTLs expire, as well as part of
1573349d5d8fSnw  * the refresh method, to update the current configuration.  It always
1574349d5d8fSnw  * reads from SMF, but you still have to refresh the service after
1575349d5d8fSnw  * changing the config pg in order for the changes to take effect.
1576349d5d8fSnw  *
1577349d5d8fSnw  * There are two flags:
1578349d5d8fSnw  *
1579349d5d8fSnw  *  - CFG_DISCOVER
1580349d5d8fSnw  *  - CFG_LOG
1581349d5d8fSnw  *
1582349d5d8fSnw  * If CFG_DISCOVER is set then idmap_cfg_load() calls
1583349d5d8fSnw  * idmap_cfg_discover() to discover, via DNS and LDAP lookups, property
1584349d5d8fSnw  * values that weren't set in SMF.
1585349d5d8fSnw  *
1586349d5d8fSnw  * If CFG_LOG is set then idmap_cfg_load() will log (to LOG_NOTICE)
1587349d5d8fSnw  * whether the configuration changed.  This should be used only from the
1588349d5d8fSnw  * refresh method.
1589349d5d8fSnw  *
1590349d5d8fSnw  * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
1591349d5d8fSnw  * reading from SMF.
1592349d5d8fSnw  */
1593349d5d8fSnw int
1594349d5d8fSnw idmap_cfg_load(idmap_cfg_t *cfg, int flags)
1595349d5d8fSnw {
1596349d5d8fSnw 	int rc = 0;
1597e3f2c991SKeyur Desai 	int errors;
1598349d5d8fSnw 	int changed = 0;
15994d61c878SJulian Pullen 	int ad_reload_required = 0;
1600349d5d8fSnw 	idmap_pg_config_t new_pgcfg, *live_pgcfg;
1601349d5d8fSnw 
1602349d5d8fSnw 	live_pgcfg = &cfg->pgcfg;
1603349d5d8fSnw 	(void) memset(&new_pgcfg, 0, sizeof (new_pgcfg));
1604349d5d8fSnw 
1605349d5d8fSnw 	pthread_mutex_lock(&cfg->handles.mutex);
1606349d5d8fSnw 
1607349d5d8fSnw 	if ((rc = idmap_cfg_load_smf(&cfg->handles, &new_pgcfg, &errors)) < -1)
1608349d5d8fSnw 		goto err;
1609349d5d8fSnw 
1610349d5d8fSnw 	if (flags & CFG_DISCOVER)
1611349d5d8fSnw 		idmap_cfg_discover(&cfg->handles, &new_pgcfg);
1612349d5d8fSnw 
1613349d5d8fSnw 	WRLOCK_CONFIG();
1614349d5d8fSnw 	if (live_pgcfg->list_size_limit != new_pgcfg.list_size_limit) {
1615349d5d8fSnw 		idmapdlog(LOG_INFO, "change list_size=%d",
1616349d5d8fSnw 		    new_pgcfg.list_size_limit);
1617349d5d8fSnw 		live_pgcfg->list_size_limit = new_pgcfg.list_size_limit;
1618349d5d8fSnw 	}
1619349d5d8fSnw 
1620349d5d8fSnw 	/* Non-discoverable props updated here */
16214aa0a5e7Snw 	changed += update_string(&live_pgcfg->machine_sid,
1622349d5d8fSnw 	    &new_pgcfg.machine_sid, "machine_sid");
1623349d5d8fSnw 
16244aa0a5e7Snw 	changed += update_bool(&live_pgcfg->eph_map_unres_sids,
16254aa0a5e7Snw 	    &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping");
16264aa0a5e7Snw 
1627e3f2c991SKeyur Desai 	changed += update_enum(&live_pgcfg->directory_based_mapping,
1628e3f2c991SKeyur Desai 	    &new_pgcfg.directory_based_mapping, "directory_based_mapping",
1629e3f2c991SKeyur Desai 	    directory_mapping_map);
1630349d5d8fSnw 
16314aa0a5e7Snw 	changed += update_string(&live_pgcfg->ad_unixuser_attr,
1632349d5d8fSnw 	    &new_pgcfg.ad_unixuser_attr, "ad_unixuser_attr");
1633349d5d8fSnw 
16344aa0a5e7Snw 	changed += update_string(&live_pgcfg->ad_unixgroup_attr,
1635349d5d8fSnw 	    &new_pgcfg.ad_unixgroup_attr, "ad_unixgroup_attr");
1636349d5d8fSnw 
16374aa0a5e7Snw 	changed += update_string(&live_pgcfg->nldap_winname_attr,
1638349d5d8fSnw 	    &new_pgcfg.nldap_winname_attr, "nldap_winname_attr");
1639349d5d8fSnw 
1640349d5d8fSnw 	/* Props that can be discovered and set in SMF updated here */
1641e3f2c991SKeyur Desai 	changed += update_string(&live_pgcfg->default_domain,
1642e3f2c991SKeyur Desai 	    &new_pgcfg.default_domain, "default_domain");
1643349d5d8fSnw 
16444aa0a5e7Snw 	changed += update_string(&live_pgcfg->domain_name,
1645349d5d8fSnw 	    &new_pgcfg.domain_name, "domain_name");
16464d61c878SJulian Pullen 	live_pgcfg->domain_name_auto_disc = new_pgcfg.domain_name_auto_disc;
1647349d5d8fSnw 
1648349d5d8fSnw 	changed += update_dirs(&live_pgcfg->domain_controller,
1649349d5d8fSnw 	    &new_pgcfg.domain_controller, "domain_controller");
16504d61c878SJulian Pullen 	live_pgcfg->domain_controller_auto_disc =
16514d61c878SJulian Pullen 	    new_pgcfg.domain_controller_auto_disc;
1652349d5d8fSnw 
16534aa0a5e7Snw 	changed += update_string(&live_pgcfg->forest_name,
1654349d5d8fSnw 	    &new_pgcfg.forest_name, "forest_name");
16554d61c878SJulian Pullen 	live_pgcfg->forest_name_auto_disc = new_pgcfg.forest_name_auto_disc;
1656349d5d8fSnw 
16574aa0a5e7Snw 	changed += update_string(&live_pgcfg->site_name,
1658349d5d8fSnw 	    &new_pgcfg.site_name, "site_name");
16594d61c878SJulian Pullen 	live_pgcfg->site_name_auto_disc = new_pgcfg.site_name_auto_disc;
1660349d5d8fSnw 
1661349d5d8fSnw 	if (update_dirs(&live_pgcfg->global_catalog,
1662349d5d8fSnw 	    &new_pgcfg.global_catalog, "global_catalog")) {
1663349d5d8fSnw 		changed++;
1664349d5d8fSnw 		if (live_pgcfg->global_catalog != NULL &&
1665349d5d8fSnw 		    live_pgcfg->global_catalog[0].host[0] != '\0')
16664d61c878SJulian Pullen 			ad_reload_required = TRUE;
1667349d5d8fSnw 	}
16684d61c878SJulian Pullen 	live_pgcfg->global_catalog_auto_disc =
16694d61c878SJulian Pullen 	    new_pgcfg.global_catalog_auto_disc;
16704d61c878SJulian Pullen 
16714d61c878SJulian Pullen 	if (update_domains_in_forest(&live_pgcfg->domains_in_forest,
16724d61c878SJulian Pullen 	    &new_pgcfg.domains_in_forest, "domains_in_forest")) {
16734d61c878SJulian Pullen 		changed++;
16744d61c878SJulian Pullen 		ad_reload_required = TRUE;
16754d61c878SJulian Pullen 	}
16764d61c878SJulian Pullen 
16774d61c878SJulian Pullen 	if (update_trusted_domains(&live_pgcfg->trusted_domains,
16784d61c878SJulian Pullen 	    &new_pgcfg.trusted_domains, "trusted_domains")) {
16794d61c878SJulian Pullen 		changed++;
16804d61c878SJulian Pullen 		if (live_pgcfg->trusted_domains != NULL &&
16814d61c878SJulian Pullen 		    live_pgcfg->trusted_domains[0].domain[0] != '\0')
16824d61c878SJulian Pullen 			ad_reload_required = TRUE;
16834d61c878SJulian Pullen 	}
16844d61c878SJulian Pullen 
16854d61c878SJulian Pullen 	if (update_trusted_forest(&live_pgcfg->trusted_forests,
16864d61c878SJulian Pullen 	    &live_pgcfg->num_trusted_forests, &new_pgcfg.trusted_forests,
16874d61c878SJulian Pullen 	    &new_pgcfg.num_trusted_forests, "trusted_forest")) {
16884d61c878SJulian Pullen 		changed++;
16894d61c878SJulian Pullen 		if (live_pgcfg->trusted_forests != NULL)
16904d61c878SJulian Pullen 			ad_reload_required = TRUE;
16914d61c878SJulian Pullen 	}
16924d61c878SJulian Pullen 
16934d61c878SJulian Pullen 	if (ad_reload_required)
16944d61c878SJulian Pullen 		reload_ad();
1695349d5d8fSnw 
1696349d5d8fSnw 	idmap_cfg_unload(&new_pgcfg);
1697349d5d8fSnw 
1698349d5d8fSnw 	if (flags & CFG_LOG) {
1699349d5d8fSnw 		/*
1700349d5d8fSnw 		 * If the config changes as a result of a refresh of the
1701349d5d8fSnw 		 * service, then logging about it can provide useful
1702349d5d8fSnw 		 * feedback to the sysadmin.
1703349d5d8fSnw 		 */
1704349d5d8fSnw 		idmapdlog(LOG_NOTICE, "Configuration %schanged",
1705349d5d8fSnw 		    changed ? "" : "un");
1706c8e26105Sjp 	}
1707e3c2d6aaSnw 
1708349d5d8fSnw 	UNLOCK_CONFIG();
1709349d5d8fSnw 
1710349d5d8fSnw err:
1711349d5d8fSnw 	pthread_mutex_unlock(&cfg->handles.mutex);
1712c5c4113dSnw 
1713e8c27ec8Sbaban 	if (rc < -1)
1714e3c2d6aaSnw 		return (rc);
1715e3c2d6aaSnw 
1716e3c2d6aaSnw 	return ((errors == 0) ? 0 : -1);
1717c5c4113dSnw }
1718c5c4113dSnw 
1719651c0131Sbaban /*
1720651c0131Sbaban  * Initialize 'cfg'.
1721651c0131Sbaban  */
1722c5c4113dSnw idmap_cfg_t *
17234edd44c5Sjp idmap_cfg_init()
17244edd44c5Sjp {
1725c8e26105Sjp 	idmap_cfg_handles_t *handles;
1726c5c4113dSnw 
1727c5c4113dSnw 	/* First the smf repository handles: */
1728c5c4113dSnw 	idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t));
1729c5c4113dSnw 	if (!cfg) {
173071590c90Snw 		idmapdlog(LOG_ERR, "Out of memory");
1731c5c4113dSnw 		return (NULL);
1732c5c4113dSnw 	}
1733c8e26105Sjp 	handles = &cfg->handles;
1734c5c4113dSnw 
1735c8e26105Sjp 	(void) pthread_mutex_init(&handles->mutex, NULL);
1736c8e26105Sjp 
1737c8e26105Sjp 	if (!(handles->main = scf_handle_create(SCF_VERSION))) {
173871590c90Snw 		idmapdlog(LOG_ERR, "scf_handle_create() failed: %s",
173971590c90Snw 		    scf_strerror(scf_error()));
1740c5c4113dSnw 		goto error;
1741c5c4113dSnw 	}
1742c5c4113dSnw 
1743c8e26105Sjp 	if (scf_handle_bind(handles->main) < 0) {
174471590c90Snw 		idmapdlog(LOG_ERR, "scf_handle_bind() failed: %s",
174571590c90Snw 		    scf_strerror(scf_error()));
1746c5c4113dSnw 		goto error;
1747c5c4113dSnw 	}
1748c5c4113dSnw 
1749c8e26105Sjp 	if (!(handles->service = scf_service_create(handles->main)) ||
1750c8e26105Sjp 	    !(handles->instance = scf_instance_create(handles->main)) ||
1751c8e26105Sjp 	    !(handles->config_pg = scf_pg_create(handles->main)) ||
1752c8e26105Sjp 	    !(handles->general_pg = scf_pg_create(handles->main))) {
175371590c90Snw 		idmapdlog(LOG_ERR, "scf handle creation failed: %s",
175471590c90Snw 		    scf_strerror(scf_error()));
1755c5c4113dSnw 		goto error;
1756c5c4113dSnw 	}
1757c5c4113dSnw 
1758c8e26105Sjp 	if (scf_handle_decode_fmri(handles->main,
17594edd44c5Sjp 	    FMRI_BASE "/:properties/" CONFIG_PG,
17604edd44c5Sjp 	    NULL,				/* scope */
17614edd44c5Sjp 	    handles->service,		/* service */
17624edd44c5Sjp 	    handles->instance,		/* instance */
17634edd44c5Sjp 	    handles->config_pg,		/* pg */
17644edd44c5Sjp 	    NULL,				/* prop */
17654edd44c5Sjp 	    SCF_DECODE_FMRI_EXACT) < 0) {
176671590c90Snw 		idmapdlog(LOG_ERR, "scf_handle_decode_fmri() failed: %s",
176771590c90Snw 		    scf_strerror(scf_error()));
1768c5c4113dSnw 		goto error;
1769c5c4113dSnw 	}
1770c5c4113dSnw 
1771c8e26105Sjp 	if (scf_service_get_pg(handles->service,
17724edd44c5Sjp 	    GENERAL_PG, handles->general_pg) < 0) {
177371590c90Snw 		idmapdlog(LOG_ERR, "scf_service_get_pg() failed: %s",
177471590c90Snw 		    scf_strerror(scf_error()));
1775c5c4113dSnw 		goto error;
1776c5c4113dSnw 	}
1777c5c4113dSnw 
1778e3f2c991SKeyur Desai 	if (check_smf_debug_mode(handles) != 0)
1779e3f2c991SKeyur Desai 		goto error;
1780e3f2c991SKeyur Desai 
1781c8e26105Sjp 	/* Initialize AD Auto Discovery context */
1782c8e26105Sjp 	handles->ad_ctx = ad_disc_init();
1783c8e26105Sjp 	if (handles->ad_ctx == NULL)
1784c8e26105Sjp 		goto error;
1785c8e26105Sjp 
1786c5c4113dSnw 	return (cfg);
1787c5c4113dSnw 
1788c5c4113dSnw error:
1789c5c4113dSnw 	(void) idmap_cfg_fini(cfg);
1790c5c4113dSnw 	return (NULL);
1791c5c4113dSnw }
1792c5c4113dSnw 
1793c8e26105Sjp void
17944edd44c5Sjp idmap_cfg_unload(idmap_pg_config_t *pgcfg)
17954edd44c5Sjp {
1796c8e26105Sjp 
1797c8e26105Sjp 	if (pgcfg->default_domain) {
1798c8e26105Sjp 		free(pgcfg->default_domain);
1799c8e26105Sjp 		pgcfg->default_domain = NULL;
1800c8e26105Sjp 	}
1801c8e26105Sjp 	if (pgcfg->domain_name) {
1802c8e26105Sjp 		free(pgcfg->domain_name);
1803c8e26105Sjp 		pgcfg->domain_name = NULL;
1804c8e26105Sjp 	}
1805c8e26105Sjp 	if (pgcfg->machine_sid) {
1806c8e26105Sjp 		free(pgcfg->machine_sid);
1807c8e26105Sjp 		pgcfg->machine_sid = NULL;
1808c8e26105Sjp 	}
1809c8e26105Sjp 	if (pgcfg->domain_controller) {
1810c5c4113dSnw 		free(pgcfg->domain_controller);
1811c8e26105Sjp 		pgcfg->domain_controller = NULL;
1812c8e26105Sjp 	}
1813c8e26105Sjp 	if (pgcfg->forest_name) {
1814c8e26105Sjp 		free(pgcfg->forest_name);
1815c8e26105Sjp 		pgcfg->forest_name = NULL;
1816c8e26105Sjp 	}
1817c8e26105Sjp 	if (pgcfg->site_name) {
1818c8e26105Sjp 		free(pgcfg->site_name);
1819c8e26105Sjp 		pgcfg->site_name = NULL;
1820c8e26105Sjp 	}
1821c8e26105Sjp 	if (pgcfg->global_catalog) {
1822c8e26105Sjp 		free(pgcfg->global_catalog);
1823c8e26105Sjp 		pgcfg->global_catalog = NULL;
1824c8e26105Sjp 	}
18254d61c878SJulian Pullen 	if (pgcfg->trusted_domains) {
18264d61c878SJulian Pullen 		free(pgcfg->trusted_domains);
18274d61c878SJulian Pullen 		pgcfg->trusted_domains = NULL;
18284d61c878SJulian Pullen 	}
18294d61c878SJulian Pullen 	if (pgcfg->trusted_forests)
18304d61c878SJulian Pullen 		free_trusted_forests(&pgcfg->trusted_forests,
18314d61c878SJulian Pullen 		    &pgcfg->num_trusted_forests);
18324d61c878SJulian Pullen 
1833e8c27ec8Sbaban 	if (pgcfg->ad_unixuser_attr) {
1834e8c27ec8Sbaban 		free(pgcfg->ad_unixuser_attr);
1835e8c27ec8Sbaban 		pgcfg->ad_unixuser_attr = NULL;
1836e8c27ec8Sbaban 	}
1837e8c27ec8Sbaban 	if (pgcfg->ad_unixgroup_attr) {
1838e8c27ec8Sbaban 		free(pgcfg->ad_unixgroup_attr);
1839e8c27ec8Sbaban 		pgcfg->ad_unixgroup_attr = NULL;
1840e8c27ec8Sbaban 	}
1841e8c27ec8Sbaban 	if (pgcfg->nldap_winname_attr) {
1842e8c27ec8Sbaban 		free(pgcfg->nldap_winname_attr);
1843e8c27ec8Sbaban 		pgcfg->nldap_winname_attr = NULL;
1844e8c27ec8Sbaban 	}
1845c5c4113dSnw }
1846c5c4113dSnw 
1847c5c4113dSnw int
1848c5c4113dSnw idmap_cfg_fini(idmap_cfg_t *cfg)
1849c5c4113dSnw {
1850c8e26105Sjp 	idmap_cfg_handles_t *handles = &cfg->handles;
1851c8e26105Sjp 	idmap_cfg_unload(&cfg->pgcfg);
1852c8e26105Sjp 
1853c8e26105Sjp 	(void) pthread_mutex_destroy(&handles->mutex);
1854c8e26105Sjp 	scf_pg_destroy(handles->config_pg);
1855c8e26105Sjp 	scf_pg_destroy(handles->general_pg);
1856c8e26105Sjp 	scf_instance_destroy(handles->instance);
1857c8e26105Sjp 	scf_service_destroy(handles->service);
1858c8e26105Sjp 	scf_handle_destroy(handles->main);
1859e8c27ec8Sbaban 	if (handles->ad_ctx != NULL)
1860e8c27ec8Sbaban 		ad_disc_fini(handles->ad_ctx);
1861c5c4113dSnw 	free(cfg);
1862c5c4113dSnw 
1863c5c4113dSnw 	return (0);
1864c5c4113dSnw }
18650dcc7149Snw 
18660dcc7149Snw void
18670dcc7149Snw idmap_cfg_poke_updates(void)
18680dcc7149Snw {
1869349d5d8fSnw 	if (idmapd_ev_port != -1)
1870349d5d8fSnw 		(void) port_send(idmapd_ev_port, POKE_AUTO_DISCOVERY, NULL);
18710dcc7149Snw }
18720dcc7149Snw 
18730dcc7149Snw /*ARGSUSED*/
18740dcc7149Snw void
1875349d5d8fSnw idmap_cfg_hup_handler(int sig)
1876349d5d8fSnw {
18770dcc7149Snw 	if (idmapd_ev_port >= 0)
18780dcc7149Snw 		(void) port_send(idmapd_ev_port, RECONFIGURE, NULL);
18790dcc7149Snw }
1880e3f2c991SKeyur Desai 
1881e3f2c991SKeyur Desai /*
1882e3f2c991SKeyur Desai  * Upgrade the DS mapping flags.
1883e3f2c991SKeyur Desai  *
1884e3f2c991SKeyur Desai  * If the old ds_name_mapping_enabled flag is present, then
1885e3f2c991SKeyur Desai  *     if the new directory_based_mapping value is present, then
1886e3f2c991SKeyur Desai  *         if the two are compatible, delete the old and note it
1887e3f2c991SKeyur Desai  *         else delete the old and warn
1888e3f2c991SKeyur Desai  *     else
1889e3f2c991SKeyur Desai  *         set the new based on the old, and note it
1890e3f2c991SKeyur Desai  *         delete the old
1891e3f2c991SKeyur Desai  */
1892e3f2c991SKeyur Desai static
1893e3f2c991SKeyur Desai int
1894e3f2c991SKeyur Desai upgrade_directory_mapping(idmap_cfg_handles_t *handles)
1895e3f2c991SKeyur Desai {
1896e3f2c991SKeyur Desai 	boolean_t legacy_ds_name_mapping_present;
1897e3f2c991SKeyur Desai 	const char DS_NAME_MAPPING_ENABLED[] = "ds_name_mapping_enabled";
1898e3f2c991SKeyur Desai 	const char DIRECTORY_BASED_MAPPING[] = "directory_based_mapping";
1899e3f2c991SKeyur Desai 	int rc;
1900e3f2c991SKeyur Desai 
1901e3f2c991SKeyur Desai 	rc = prop_exists(handles, DS_NAME_MAPPING_ENABLED,
1902e3f2c991SKeyur Desai 	    &legacy_ds_name_mapping_present);
1903e3f2c991SKeyur Desai 
1904e3f2c991SKeyur Desai 	if (rc != 0)
1905e3f2c991SKeyur Desai 		return (rc);
1906e3f2c991SKeyur Desai 
1907e3f2c991SKeyur Desai 	if (!legacy_ds_name_mapping_present)
1908e3f2c991SKeyur Desai 		return (0);
1909e3f2c991SKeyur Desai 
1910e3f2c991SKeyur Desai 	boolean_t legacy_ds_name_mapping_enabled;
1911e3f2c991SKeyur Desai 	rc = get_val_int(handles, DS_NAME_MAPPING_ENABLED,
1912e3f2c991SKeyur Desai 	    &legacy_ds_name_mapping_enabled, SCF_TYPE_BOOLEAN);
1913e3f2c991SKeyur Desai 	if (rc != 0)
1914e3f2c991SKeyur Desai 		return (rc);
1915e3f2c991SKeyur Desai 
1916e3f2c991SKeyur Desai 	char *legacy_mode;
1917e3f2c991SKeyur Desai 	char *legacy_bool_string;
1918e3f2c991SKeyur Desai 	if (legacy_ds_name_mapping_enabled) {
1919e3f2c991SKeyur Desai 		legacy_mode = "name";
1920e3f2c991SKeyur Desai 		legacy_bool_string = "true";
1921e3f2c991SKeyur Desai 	} else {
1922e3f2c991SKeyur Desai 		legacy_mode = "none";
1923e3f2c991SKeyur Desai 		legacy_bool_string = "false";
1924e3f2c991SKeyur Desai 	}
1925e3f2c991SKeyur Desai 
1926e3f2c991SKeyur Desai 	char *directory_based_mapping;
1927e3f2c991SKeyur Desai 	rc = get_val_astring(handles, DIRECTORY_BASED_MAPPING,
1928e3f2c991SKeyur Desai 	    &directory_based_mapping);
1929e3f2c991SKeyur Desai 	if (rc != 0)
1930e3f2c991SKeyur Desai 		return (rc);
1931e3f2c991SKeyur Desai 
1932e3f2c991SKeyur Desai 	if (directory_based_mapping == NULL) {
1933e3f2c991SKeyur Desai 		idmapdlog(LOG_INFO,
1934e3f2c991SKeyur Desai 		    "Upgrading old %s=%s setting\n"
1935e3f2c991SKeyur Desai 		    "to %s=%s.",
1936e3f2c991SKeyur Desai 		    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
1937e3f2c991SKeyur Desai 		    DIRECTORY_BASED_MAPPING, legacy_mode);
1938e3f2c991SKeyur Desai 		rc = set_val_astring(handles, DIRECTORY_BASED_MAPPING,
1939e3f2c991SKeyur Desai 		    legacy_mode);
1940e3f2c991SKeyur Desai 		if (rc != 0)
1941e3f2c991SKeyur Desai 			return (rc);
1942e3f2c991SKeyur Desai 	} else {
1943e3f2c991SKeyur Desai 		boolean_t new_name_mapping;
1944e3f2c991SKeyur Desai 		if (strcasecmp(directory_based_mapping, "name") == 0)
1945e3f2c991SKeyur Desai 			new_name_mapping = B_TRUE;
1946e3f2c991SKeyur Desai 		else
1947e3f2c991SKeyur Desai 			new_name_mapping = B_FALSE;
1948e3f2c991SKeyur Desai 
1949e3f2c991SKeyur Desai 		if (legacy_ds_name_mapping_enabled == new_name_mapping) {
1950e3f2c991SKeyur Desai 			idmapdlog(LOG_INFO,
1951e3f2c991SKeyur Desai 			    "Automatically removing old %s=%s setting\n"
1952e3f2c991SKeyur Desai 			    "in favor of %s=%s.",
1953e3f2c991SKeyur Desai 			    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
1954e3f2c991SKeyur Desai 			    DIRECTORY_BASED_MAPPING, directory_based_mapping);
1955e3f2c991SKeyur Desai 		} else {
1956e3f2c991SKeyur Desai 			idmapdlog(LOG_WARNING,
1957e3f2c991SKeyur Desai 			    "Removing conflicting %s=%s setting\n"
1958e3f2c991SKeyur Desai 			    "in favor of %s=%s.",
1959e3f2c991SKeyur Desai 			    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
1960e3f2c991SKeyur Desai 			    DIRECTORY_BASED_MAPPING, directory_based_mapping);
1961e3f2c991SKeyur Desai 		}
1962e3f2c991SKeyur Desai 		free(directory_based_mapping);
1963e3f2c991SKeyur Desai 	}
1964e3f2c991SKeyur Desai 
1965e3f2c991SKeyur Desai 	rc = del_val(handles, DS_NAME_MAPPING_ENABLED);
1966e3f2c991SKeyur Desai 	if (rc != 0)
1967e3f2c991SKeyur Desai 		return (rc);
1968e3f2c991SKeyur Desai 
1969e3f2c991SKeyur Desai 	return (0);
1970e3f2c991SKeyur Desai }
1971e3f2c991SKeyur Desai 
1972e3f2c991SKeyur Desai /*
1973e3f2c991SKeyur Desai  * Do whatever is necessary to upgrade idmap's configuration before
1974e3f2c991SKeyur Desai  * we load it.
1975e3f2c991SKeyur Desai  */
1976e3f2c991SKeyur Desai int
1977e3f2c991SKeyur Desai idmap_cfg_upgrade(idmap_cfg_t *cfg)
1978e3f2c991SKeyur Desai {
1979e3f2c991SKeyur Desai 	int rc;
1980e3f2c991SKeyur Desai 
1981e3f2c991SKeyur Desai 	rc = upgrade_directory_mapping(&cfg->handles);
1982e3f2c991SKeyur Desai 	if (rc != 0)
1983e3f2c991SKeyur Desai 		return (rc);
1984e3f2c991SKeyur Desai 
1985e3f2c991SKeyur Desai 	return (0);
1986e3f2c991SKeyur Desai }
1987