xref: /titanic_41/usr/src/cmd/idmap/idmapd/idmap_config.c (revision 4f4499478f0aa55fc93bcd8030ba3d128663ae70)
1c5c4113dSnw141292 /*
2c5c4113dSnw141292  * CDDL HEADER START
3c5c4113dSnw141292  *
4c5c4113dSnw141292  * The contents of this file are subject to the terms of the
5c5c4113dSnw141292  * Common Development and Distribution License (the "License").
6c5c4113dSnw141292  * You may not use this file except in compliance with the License.
7c5c4113dSnw141292  *
8c5c4113dSnw141292  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c5c4113dSnw141292  * or http://www.opensolaris.org/os/licensing.
10c5c4113dSnw141292  * See the License for the specific language governing permissions
11c5c4113dSnw141292  * and limitations under the License.
12c5c4113dSnw141292  *
13c5c4113dSnw141292  * When distributing Covered Code, include this CDDL HEADER in each
14c5c4113dSnw141292  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c5c4113dSnw141292  * If applicable, add the following below this CDDL HEADER, with the
16c5c4113dSnw141292  * fields enclosed by brackets "[]" replaced with your own identifying
17c5c4113dSnw141292  * information: Portions Copyright [yyyy] [name of copyright owner]
18c5c4113dSnw141292  *
19c5c4113dSnw141292  * CDDL HEADER END
20c5c4113dSnw141292  */
21c5c4113dSnw141292 /*
22c5866007SKeyur Desai  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*4f449947SGordon Ross  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
24c5c4113dSnw141292  */
25c5c4113dSnw141292 
26c5c4113dSnw141292 
27c5c4113dSnw141292 /*
28c5c4113dSnw141292  * Config routines common to idmap(1M) and idmapd(1M)
29c5c4113dSnw141292  */
30c5c4113dSnw141292 
31c5c4113dSnw141292 #include <stdlib.h>
32c5c4113dSnw141292 #include <strings.h>
33c5c4113dSnw141292 #include <libintl.h>
34c5c4113dSnw141292 #include <ctype.h>
35c5c4113dSnw141292 #include <errno.h>
36651c0131Sbaban #include "idmapd.h"
37c5c4113dSnw141292 #include <stdio.h>
38c5c4113dSnw141292 #include <stdarg.h>
398edda628Sbaban #include <uuid/uuid.h>
40c8e26105Sjp151216 #include <pthread.h>
41c8e26105Sjp151216 #include <port.h>
420dcc7149Snw141292 #include <net/route.h>
434d61c878SJulian Pullen #include <sys/u8_textprep.h>
44148c5f43SAlan Wright #include <note.h>
45c8e26105Sjp151216 #include "addisc.h"
46c5c4113dSnw141292 
474aa0a5e7Snw141292 #define	MACHINE_SID_LEN		(9 + 3 * 11)
48c5c4113dSnw141292 #define	FMRI_BASE		"svc:/system/idmap"
49c5c4113dSnw141292 #define	CONFIG_PG		"config"
50148c5f43SAlan Wright #define	DEBUG_PG		"debug"
510dcc7149Snw141292 #define	RECONFIGURE		1
520dcc7149Snw141292 #define	POKE_AUTO_DISCOVERY	2
53c5c4113dSnw141292 
5448cd229bSGordon Ross /*
5548cd229bSGordon Ross  * Default cache timeouts.  Can override via svccfg
5648cd229bSGordon Ross  * config/id_cache_timeout = count: seconds
5748cd229bSGordon Ross  * config/name_cache_timeout = count: seconds
5848cd229bSGordon Ross  */
59baaccc4cSBayard Bell #define	ID_CACHE_TMO_DEFAULT	86400
60baaccc4cSBayard Bell #define	NAME_CACHE_TMO_DEFAULT	604800
6148cd229bSGordon Ross 
62c5866007SKeyur Desai enum event_type {
63c5866007SKeyur Desai 	EVENT_NOTHING,	/* Woke up for no good reason */
64c5866007SKeyur Desai 	EVENT_TIMEOUT,	/* Timeout expired */
65c5866007SKeyur Desai 	EVENT_ROUTING,	/* An interesting routing event happened */
66c5866007SKeyur Desai 	EVENT_DEGRADE,	/* An error occurred in the mainline */
67c5866007SKeyur Desai 	EVENT_REFRESH,	/* SMF refresh */
68c5866007SKeyur Desai };
69c5866007SKeyur Desai 
70c8e26105Sjp151216 
71c8e26105Sjp151216 
72c8e26105Sjp151216 static pthread_t update_thread_handle = 0;
73c8e26105Sjp151216 
740dcc7149Snw141292 static int idmapd_ev_port = -1;
750dcc7149Snw141292 static int rt_sock = -1;
76c8e26105Sjp151216 
77e3f2c991SKeyur Desai struct enum_lookup_map directory_mapping_map[] = {
78e3f2c991SKeyur Desai 	{ DIRECTORY_MAPPING_NONE, "none" },
79e3f2c991SKeyur Desai 	{ DIRECTORY_MAPPING_NAME, "name" },
80e3f2c991SKeyur Desai 	{ DIRECTORY_MAPPING_IDMU, "idmu" },
81e3f2c991SKeyur Desai 	{ 0, NULL },
82e3f2c991SKeyur Desai };
83e3f2c991SKeyur Desai 
84148c5f43SAlan Wright struct enum_lookup_map trust_dir_map[] = {
85148c5f43SAlan Wright 	{ 1, "they trust us" },
86148c5f43SAlan Wright 	{ 2, "we trust them" },
87148c5f43SAlan Wright 	{ 3, "we trust each other" },
88148c5f43SAlan Wright 	{ 0, NULL },
89148c5f43SAlan Wright };
90148c5f43SAlan Wright 
918edda628Sbaban static int
generate_machine_sid(char ** machine_sid)924edd44c5Sjp151216 generate_machine_sid(char **machine_sid)
934edd44c5Sjp151216 {
948edda628Sbaban 	char *p;
958edda628Sbaban 	uuid_t uu;
968edda628Sbaban 	int i, j, len, rlen;
978edda628Sbaban 	uint32_t rid;
988edda628Sbaban 
998edda628Sbaban 	/*
1004aa0a5e7Snw141292 	 * Generate and split 128-bit UUID into three 32-bit RIDs The
1014aa0a5e7Snw141292 	 * machine_sid will be of the form S-1-5-21-N1-N2-N3 (that's
1024aa0a5e7Snw141292 	 * four RIDs altogether).
1034aa0a5e7Snw141292 	 *
1044aa0a5e7Snw141292 	 * Technically we could use up to 14 random RIDs here, but it
1054aa0a5e7Snw141292 	 * turns out that with some versions of Windows using SIDs with
1064aa0a5e7Snw141292 	 * more than  five RIDs in security descriptors causes problems.
1078edda628Sbaban 	 */
1088edda628Sbaban 
1098edda628Sbaban 	*machine_sid = calloc(1, MACHINE_SID_LEN);
1108edda628Sbaban 	if (*machine_sid == NULL) {
11171590c90Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
1128edda628Sbaban 		return (-1);
1138edda628Sbaban 	}
1148edda628Sbaban 	(void) strcpy(*machine_sid, "S-1-5-21");
1158edda628Sbaban 	p = *machine_sid + strlen("S-1-5-21");
1168edda628Sbaban 	len = MACHINE_SID_LEN - strlen("S-1-5-21");
1178edda628Sbaban 
1188edda628Sbaban 	uuid_clear(uu);
1198edda628Sbaban 	uuid_generate_random(uu);
1208edda628Sbaban 
1214aa0a5e7Snw141292 #if UUID_LEN != 16
1224aa0a5e7Snw141292 #error UUID size is not 16!
1234aa0a5e7Snw141292 #endif
1244aa0a5e7Snw141292 
1254aa0a5e7Snw141292 	for (i = 0; i < 3; i++) {
1268edda628Sbaban 		j = i * 4;
1278edda628Sbaban 		rid = (uu[j] << 24) | (uu[j + 1] << 16) |
1288edda628Sbaban 		    (uu[j + 2] << 8) | (uu[j + 3]);
1298edda628Sbaban 		rlen = snprintf(p, len, "-%u", rid);
1308edda628Sbaban 		p += rlen;
1318edda628Sbaban 		len -= rlen;
1328edda628Sbaban 	}
1338edda628Sbaban 
1348edda628Sbaban 	return (0);
1358edda628Sbaban }
1368edda628Sbaban 
13771590c90Snw141292 
138479ac375Sdm199847 /* In the case of error, exists is set to FALSE anyway */
139479ac375Sdm199847 static int
prop_exists(idmap_cfg_handles_t * handles,const char * name,boolean_t * exists)140e3f2c991SKeyur Desai prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists)
141479ac375Sdm199847 {
142479ac375Sdm199847 
143479ac375Sdm199847 	scf_property_t *scf_prop;
144479ac375Sdm199847 
1457a8a68f5SJulian Pullen 	*exists = B_FALSE;
146479ac375Sdm199847 
147479ac375Sdm199847 	scf_prop = scf_property_create(handles->main);
148479ac375Sdm199847 	if (scf_prop == NULL) {
149479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
150479ac375Sdm199847 		    scf_strerror(scf_error()));
151479ac375Sdm199847 		return (-1);
152479ac375Sdm199847 	}
153148c5f43SAlan Wright 
154148c5f43SAlan Wright 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) == 0)
155148c5f43SAlan Wright 		*exists = B_TRUE;
156148c5f43SAlan Wright 
157148c5f43SAlan Wright 	scf_property_destroy(scf_prop);
158148c5f43SAlan Wright 
159148c5f43SAlan Wright 	return (0);
160148c5f43SAlan Wright }
161148c5f43SAlan Wright 
162148c5f43SAlan Wright static int
get_debug(idmap_cfg_handles_t * handles,const char * name)163148c5f43SAlan Wright get_debug(idmap_cfg_handles_t *handles, const char *name)
164148c5f43SAlan Wright {
165148c5f43SAlan Wright 	int64_t i64 = 0;
166148c5f43SAlan Wright 
167148c5f43SAlan Wright 	scf_property_t *scf_prop;
168148c5f43SAlan Wright 	scf_value_t *value;
169148c5f43SAlan Wright 
170148c5f43SAlan Wright 	scf_prop = scf_property_create(handles->main);
171148c5f43SAlan Wright 	if (scf_prop == NULL) {
172148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
173148c5f43SAlan Wright 		    scf_strerror(scf_error()));
174148c5f43SAlan Wright 		abort();
175148c5f43SAlan Wright 	}
176148c5f43SAlan Wright 	value = scf_value_create(handles->main);
177148c5f43SAlan Wright 	if (value == NULL) {
178148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
179148c5f43SAlan Wright 		    scf_strerror(scf_error()));
180148c5f43SAlan Wright 		abort();
181148c5f43SAlan Wright 	}
182148c5f43SAlan Wright 
183148c5f43SAlan Wright 	if (scf_pg_get_property(handles->debug_pg, name, scf_prop) < 0) {
184148c5f43SAlan Wright 		/* this is OK: the property is just undefined */
185148c5f43SAlan Wright 		goto destruction;
186148c5f43SAlan Wright 	}
187148c5f43SAlan Wright 
188148c5f43SAlan Wright 
189148c5f43SAlan Wright 	if (scf_property_get_value(scf_prop, value) < 0) {
190148c5f43SAlan Wright 		/* It is still OK when a property doesn't have any value */
191148c5f43SAlan Wright 		goto destruction;
192148c5f43SAlan Wright 	}
193148c5f43SAlan Wright 
194148c5f43SAlan Wright 	if (scf_value_get_integer(value, &i64) != 0) {
195148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "Can not retrieve %s/%s:  %s",
196148c5f43SAlan Wright 		    DEBUG_PG, name, scf_strerror(scf_error()));
197148c5f43SAlan Wright 		abort();
198148c5f43SAlan Wright 	}
199148c5f43SAlan Wright 
200148c5f43SAlan Wright destruction:
201148c5f43SAlan Wright 	scf_value_destroy(value);
202148c5f43SAlan Wright 	scf_property_destroy(scf_prop);
203148c5f43SAlan Wright 
204148c5f43SAlan Wright 	return ((int)i64);
205148c5f43SAlan Wright }
206148c5f43SAlan Wright 
207148c5f43SAlan Wright static int
get_val_bool(idmap_cfg_handles_t * handles,const char * name,boolean_t * val,boolean_t default_val)208148c5f43SAlan Wright get_val_bool(idmap_cfg_handles_t *handles, const char *name,
209148c5f43SAlan Wright 	boolean_t *val, boolean_t default_val)
210148c5f43SAlan Wright {
211148c5f43SAlan Wright 	int rc = 0;
212148c5f43SAlan Wright 
213148c5f43SAlan Wright 	scf_property_t *scf_prop;
214148c5f43SAlan Wright 	scf_value_t *value;
215148c5f43SAlan Wright 
216148c5f43SAlan Wright 	*val = default_val;
217148c5f43SAlan Wright 
218148c5f43SAlan Wright 	scf_prop = scf_property_create(handles->main);
219148c5f43SAlan Wright 	if (scf_prop == NULL) {
220148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
221148c5f43SAlan Wright 		    scf_strerror(scf_error()));
222148c5f43SAlan Wright 		return (-1);
223148c5f43SAlan Wright 	}
224479ac375Sdm199847 	value = scf_value_create(handles->main);
225479ac375Sdm199847 	if (value == NULL) {
226479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
227479ac375Sdm199847 		    scf_strerror(scf_error()));
228479ac375Sdm199847 		scf_property_destroy(scf_prop);
229479ac375Sdm199847 		return (-1);
230479ac375Sdm199847 	}
23171590c90Snw141292 
232148c5f43SAlan Wright 	/* It is OK if the property is undefined */
233148c5f43SAlan Wright 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
234148c5f43SAlan Wright 		goto destruction;
23571590c90Snw141292 
236148c5f43SAlan Wright 
237148c5f43SAlan Wright 	/* It is still OK when a property doesn't have any value */
238148c5f43SAlan Wright 	if (scf_property_get_value(scf_prop, value) < 0)
239148c5f43SAlan Wright 		goto destruction;
240148c5f43SAlan Wright 
241148c5f43SAlan Wright 	uint8_t b;
242148c5f43SAlan Wright 	rc = scf_value_get_boolean(value, &b);
243148c5f43SAlan Wright 
244148c5f43SAlan Wright 	if (rc == 0)
245148c5f43SAlan Wright 		*val = (boolean_t)b;
246148c5f43SAlan Wright 
247148c5f43SAlan Wright destruction:
24871590c90Snw141292 	scf_value_destroy(value);
24971590c90Snw141292 	scf_property_destroy(scf_prop);
25071590c90Snw141292 
251148c5f43SAlan Wright 	return (rc);
25271590c90Snw141292 }
25371590c90Snw141292 
254c5c4113dSnw141292 static int
get_val_int(idmap_cfg_handles_t * handles,const char * name,void * val,scf_type_t type)255e3f2c991SKeyur Desai get_val_int(idmap_cfg_handles_t *handles, const char *name,
256c8e26105Sjp151216 	void *val, scf_type_t type)
257c5c4113dSnw141292 {
258c5c4113dSnw141292 	int rc = 0;
259c5c4113dSnw141292 
260479ac375Sdm199847 	scf_property_t *scf_prop;
261479ac375Sdm199847 	scf_value_t *value;
262479ac375Sdm199847 
2634aa0a5e7Snw141292 	switch (type) {
2644aa0a5e7Snw141292 	case SCF_TYPE_COUNT:
2654aa0a5e7Snw141292 		*(uint64_t *)val = 0;
2664aa0a5e7Snw141292 		break;
2674aa0a5e7Snw141292 	case SCF_TYPE_INTEGER:
2684aa0a5e7Snw141292 		*(int64_t *)val = 0;
2694aa0a5e7Snw141292 		break;
2704aa0a5e7Snw141292 	default:
2714aa0a5e7Snw141292 		idmapdlog(LOG_ERR, "Invalid scf integer type (%d)",
2724aa0a5e7Snw141292 		    type);
2734aa0a5e7Snw141292 		abort();
2744aa0a5e7Snw141292 	}
2754aa0a5e7Snw141292 
276479ac375Sdm199847 	scf_prop = scf_property_create(handles->main);
277479ac375Sdm199847 	if (scf_prop == NULL) {
278479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
279479ac375Sdm199847 		    scf_strerror(scf_error()));
280479ac375Sdm199847 		return (-1);
281479ac375Sdm199847 	}
282479ac375Sdm199847 	value = scf_value_create(handles->main);
283479ac375Sdm199847 	if (value == NULL) {
284479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
285479ac375Sdm199847 		    scf_strerror(scf_error()));
286479ac375Sdm199847 		scf_property_destroy(scf_prop);
287479ac375Sdm199847 		return (-1);
288479ac375Sdm199847 	}
289c5c4113dSnw141292 
290c8e26105Sjp151216 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
291c5c4113dSnw141292 	/* this is OK: the property is just undefined */
292c5c4113dSnw141292 		goto destruction;
293c5c4113dSnw141292 
294c5c4113dSnw141292 
295c8e26105Sjp151216 	if (scf_property_get_value(scf_prop, value) < 0)
296c5c4113dSnw141292 	/* It is still OK when a property doesn't have any value */
297c5c4113dSnw141292 		goto destruction;
298c5c4113dSnw141292 
299c5c4113dSnw141292 	switch (type) {
300c5c4113dSnw141292 	case SCF_TYPE_COUNT:
301c5c4113dSnw141292 		rc = scf_value_get_count(value, val);
302c5c4113dSnw141292 		break;
303c5c4113dSnw141292 	case SCF_TYPE_INTEGER:
304c5c4113dSnw141292 		rc = scf_value_get_integer(value, val);
305c5c4113dSnw141292 		break;
306e3f2c991SKeyur Desai 	default:
307e3f2c991SKeyur Desai 		abort();	/* tested above */
308e3f2c991SKeyur Desai 		/* NOTREACHED */
309c5c4113dSnw141292 	}
310c5c4113dSnw141292 
311e3f2c991SKeyur Desai 	if (rc != 0) {
312e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "Can not retrieve config/%s:  %s",
313e3f2c991SKeyur Desai 		    name, scf_strerror(scf_error()));
314e3f2c991SKeyur Desai 	}
315c5c4113dSnw141292 
316c5c4113dSnw141292 destruction:
317c5c4113dSnw141292 	scf_value_destroy(value);
318c5c4113dSnw141292 	scf_property_destroy(scf_prop);
319c5c4113dSnw141292 
320c5c4113dSnw141292 	return (rc);
321c5c4113dSnw141292 }
322c5c4113dSnw141292 
323c5c4113dSnw141292 static char *
scf_value2string(const char * name,scf_value_t * value)324e3f2c991SKeyur Desai scf_value2string(const char *name, scf_value_t *value)
3254edd44c5Sjp151216 {
326e3f2c991SKeyur Desai 	static size_t max_val = 0;
327c5c4113dSnw141292 
328e3f2c991SKeyur Desai 	if (max_val == 0)
329e3f2c991SKeyur Desai 		max_val = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
330e3f2c991SKeyur Desai 
331e3f2c991SKeyur Desai 	char buf[max_val + 1];
332e3f2c991SKeyur Desai 	if (scf_value_get_astring(value, buf, max_val + 1) < 0) {
333e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "Can not retrieve config/%s:  %s",
334e3f2c991SKeyur Desai 		    name, scf_strerror(scf_error()));
335e3f2c991SKeyur Desai 		return (NULL);
336c5c4113dSnw141292 	}
337c5c4113dSnw141292 
338e3f2c991SKeyur Desai 	char *s = strdup(buf);
339e3f2c991SKeyur Desai 	if (s == NULL)
34071590c90Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
341c5c4113dSnw141292 
342e3f2c991SKeyur Desai 	return (s);
343c5c4113dSnw141292 }
344c5c4113dSnw141292 
345c5c4113dSnw141292 static int
get_val_ds(idmap_cfg_handles_t * handles,const char * name,int defport,idmap_ad_disc_ds_t ** val)346c8e26105Sjp151216 get_val_ds(idmap_cfg_handles_t *handles, const char *name, int defport,
347479ac375Sdm199847 		idmap_ad_disc_ds_t **val)
348c5c4113dSnw141292 {
349479ac375Sdm199847 	idmap_ad_disc_ds_t *servers = NULL;
350c8e26105Sjp151216 	scf_property_t *scf_prop;
351c8e26105Sjp151216 	scf_value_t *value;
352c8e26105Sjp151216 	scf_iter_t *iter;
353c8e26105Sjp151216 	char *host, *portstr;
354e3c2d6aaSnw141292 	int len, i;
355c8e26105Sjp151216 	int count = 0;
356e3c2d6aaSnw141292 	int rc = -1;
357c5c4113dSnw141292 
358c8e26105Sjp151216 	*val = NULL;
359c5c4113dSnw141292 
360c8e26105Sjp151216 restart:
361c8e26105Sjp151216 	scf_prop = scf_property_create(handles->main);
362479ac375Sdm199847 	if (scf_prop == NULL) {
363479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
364479ac375Sdm199847 		    scf_strerror(scf_error()));
365479ac375Sdm199847 		return (-1);
366479ac375Sdm199847 	}
367479ac375Sdm199847 
368c8e26105Sjp151216 	value = scf_value_create(handles->main);
369479ac375Sdm199847 	if (value == NULL) {
370479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
371479ac375Sdm199847 		    scf_strerror(scf_error()));
372479ac375Sdm199847 		scf_property_destroy(scf_prop);
373479ac375Sdm199847 		return (-1);
374479ac375Sdm199847 	}
375479ac375Sdm199847 
376c8e26105Sjp151216 	iter = scf_iter_create(handles->main);
377479ac375Sdm199847 	if (iter == NULL) {
378479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_iter_create() failed: %s",
379479ac375Sdm199847 		    scf_strerror(scf_error()));
380479ac375Sdm199847 		scf_value_destroy(value);
381479ac375Sdm199847 		scf_property_destroy(scf_prop);
382479ac375Sdm199847 		return (-1);
383479ac375Sdm199847 	}
384c5c4113dSnw141292 
385e3c2d6aaSnw141292 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) {
386c5c4113dSnw141292 		/* this is OK: the property is just undefined */
387e3c2d6aaSnw141292 		rc = 0;
388c5c4113dSnw141292 		goto destruction;
389e3c2d6aaSnw141292 	}
390c5c4113dSnw141292 
391c8e26105Sjp151216 	if (scf_iter_property_values(iter, scf_prop) < 0) {
392c8e26105Sjp151216 		idmapdlog(LOG_ERR,
39371590c90Snw141292 		    "scf_iter_property_values(%s) failed: %s",
39471590c90Snw141292 		    name, scf_strerror(scf_error()));
395c8e26105Sjp151216 		goto destruction;
396c8e26105Sjp151216 	}
397c8e26105Sjp151216 
398c8e26105Sjp151216 	/* Workaround scf bugs -- can't reset an iteration */
399c8e26105Sjp151216 	if (count == 0) {
400c8e26105Sjp151216 		while (scf_iter_next_value(iter, value) > 0)
401c8e26105Sjp151216 			count++;
402c8e26105Sjp151216 
403e3c2d6aaSnw141292 		if (count == 0) {
404c8e26105Sjp151216 			/* no values */
405e3c2d6aaSnw141292 			rc = 0;
406c8e26105Sjp151216 			goto destruction;
407e3c2d6aaSnw141292 		}
408c8e26105Sjp151216 
409c8e26105Sjp151216 		scf_value_destroy(value);
410c8e26105Sjp151216 		scf_iter_destroy(iter);
411c8e26105Sjp151216 		scf_property_destroy(scf_prop);
412c8e26105Sjp151216 		goto restart;
413c8e26105Sjp151216 	}
414c8e26105Sjp151216 
415c8e26105Sjp151216 	if ((servers = calloc(count + 1, sizeof (*servers))) == NULL) {
41671590c90Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
417c8e26105Sjp151216 		goto destruction;
418c8e26105Sjp151216 	}
419c8e26105Sjp151216 
420e3c2d6aaSnw141292 	i = 0;
421e3c2d6aaSnw141292 	while (i < count && scf_iter_next_value(iter, value) > 0) {
422e3c2d6aaSnw141292 		servers[i].priority = 0;
423e3c2d6aaSnw141292 		servers[i].weight = 100;
424e3c2d6aaSnw141292 		servers[i].port = defport;
425e3f2c991SKeyur Desai 		if ((host = scf_value2string(name, value)) == NULL) {
426c8e26105Sjp151216 			goto destruction;
427c8e26105Sjp151216 		}
428c8e26105Sjp151216 		if ((portstr = strchr(host, ':')) != NULL) {
429c8e26105Sjp151216 			*portstr++ = '\0';
430e3c2d6aaSnw141292 			servers[i].port = strtol(portstr,
431c8e26105Sjp151216 			    (char **)NULL, 10);
432e3c2d6aaSnw141292 			if (servers[i].port == 0)
433e3c2d6aaSnw141292 				servers[i].port = defport;
434c8e26105Sjp151216 		}
435e3c2d6aaSnw141292 		len = strlcpy(servers[i].host, host,
436c8e26105Sjp151216 		    sizeof (servers->host));
437c8e26105Sjp151216 
438c8e26105Sjp151216 		free(host);
439c8e26105Sjp151216 
440c8e26105Sjp151216 		/* Ignore this server if the hostname is too long */
441c8e26105Sjp151216 		if (len < sizeof (servers->host))
442e3c2d6aaSnw141292 			i++;
443c8e26105Sjp151216 	}
444c8e26105Sjp151216 
445c8e26105Sjp151216 	*val = servers;
446c8e26105Sjp151216 
447e3c2d6aaSnw141292 	rc = 0;
448e3c2d6aaSnw141292 
449c8e26105Sjp151216 destruction:
450c8e26105Sjp151216 	scf_value_destroy(value);
451c8e26105Sjp151216 	scf_iter_destroy(iter);
452c8e26105Sjp151216 	scf_property_destroy(scf_prop);
453c8e26105Sjp151216 
454c8e26105Sjp151216 	if (rc < 0) {
455c8e26105Sjp151216 		if (servers)
456c8e26105Sjp151216 			free(servers);
457c8e26105Sjp151216 		*val = NULL;
458c8e26105Sjp151216 	}
459c8e26105Sjp151216 
460c8e26105Sjp151216 	return (rc);
461c8e26105Sjp151216 }
462c8e26105Sjp151216 
463c8e26105Sjp151216 
464c8e26105Sjp151216 static int
get_val_astring(idmap_cfg_handles_t * handles,const char * name,char ** val)465e3f2c991SKeyur Desai get_val_astring(idmap_cfg_handles_t *handles, const char *name, char **val)
466c8e26105Sjp151216 {
467c8e26105Sjp151216 	int rc = 0;
468c8e26105Sjp151216 
469479ac375Sdm199847 	scf_property_t *scf_prop;
470479ac375Sdm199847 	scf_value_t *value;
471479ac375Sdm199847 
472479ac375Sdm199847 	scf_prop = scf_property_create(handles->main);
473479ac375Sdm199847 	if (scf_prop == NULL) {
474479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
475479ac375Sdm199847 		    scf_strerror(scf_error()));
476479ac375Sdm199847 		return (-1);
477479ac375Sdm199847 	}
478479ac375Sdm199847 	value = scf_value_create(handles->main);
479479ac375Sdm199847 	if (value == NULL) {
480479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
481479ac375Sdm199847 		    scf_strerror(scf_error()));
482479ac375Sdm199847 		scf_property_destroy(scf_prop);
483479ac375Sdm199847 		return (-1);
484479ac375Sdm199847 	}
485c8e26105Sjp151216 
486c8e26105Sjp151216 	*val = NULL;
487c8e26105Sjp151216 
488c8e26105Sjp151216 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
489c8e26105Sjp151216 	/* this is OK: the property is just undefined */
490c8e26105Sjp151216 		goto destruction;
491c8e26105Sjp151216 
492c8e26105Sjp151216 	if (scf_property_get_value(scf_prop, value) < 0) {
493651c0131Sbaban 		idmapdlog(LOG_ERR,
49471590c90Snw141292 		    "scf_property_get_value(%s) failed: %s",
49571590c90Snw141292 		    name, scf_strerror(scf_error()));
496c5c4113dSnw141292 		rc = -1;
497c5c4113dSnw141292 		goto destruction;
498c5c4113dSnw141292 	}
499c5c4113dSnw141292 
500e3f2c991SKeyur Desai 	*val = scf_value2string(name, value);
501e3f2c991SKeyur Desai 	if (*val == NULL)
502c5c4113dSnw141292 		rc = -1;
503c5c4113dSnw141292 
504c5c4113dSnw141292 destruction:
505c5c4113dSnw141292 	scf_value_destroy(value);
506c5c4113dSnw141292 	scf_property_destroy(scf_prop);
507c5c4113dSnw141292 
508c5c4113dSnw141292 	if (rc < 0) {
509c5c4113dSnw141292 		if (*val)
510c5c4113dSnw141292 			free(*val);
511c5c4113dSnw141292 		*val = NULL;
512c5c4113dSnw141292 	}
513c5c4113dSnw141292 
514c5c4113dSnw141292 	return (rc);
515c5c4113dSnw141292 }
516c5c4113dSnw141292 
517c8e26105Sjp151216 
5188edda628Sbaban static int
del_val(idmap_cfg_handles_t * handles,scf_propertygroup_t * pg,const char * name)519148c5f43SAlan Wright del_val(
520148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
521148c5f43SAlan Wright     scf_propertygroup_t *pg,
522148c5f43SAlan Wright     const char *name)
523e3f2c991SKeyur Desai {
524e3f2c991SKeyur Desai 	int			rc = -1;
525e3f2c991SKeyur Desai 	int			ret;
526e3f2c991SKeyur Desai 	scf_transaction_t	*tx = NULL;
527e3f2c991SKeyur Desai 	scf_transaction_entry_t	*ent = NULL;
528e3f2c991SKeyur Desai 
529e3f2c991SKeyur Desai 	if ((tx = scf_transaction_create(handles->main)) == NULL) {
530e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
531e3f2c991SKeyur Desai 		    "scf_transaction_create() failed: %s",
532e3f2c991SKeyur Desai 		    scf_strerror(scf_error()));
533e3f2c991SKeyur Desai 		goto destruction;
534e3f2c991SKeyur Desai 	}
535e3f2c991SKeyur Desai 	if ((ent = scf_entry_create(handles->main)) == NULL) {
536e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
537e3f2c991SKeyur Desai 		    "scf_entry_create() failed: %s",
538e3f2c991SKeyur Desai 		    scf_strerror(scf_error()));
539e3f2c991SKeyur Desai 		goto destruction;
540e3f2c991SKeyur Desai 	}
541e3f2c991SKeyur Desai 
542e3f2c991SKeyur Desai 	do {
543148c5f43SAlan Wright 		if (scf_pg_update(pg) == -1) {
544e3f2c991SKeyur Desai 			idmapdlog(LOG_ERR,
545e3f2c991SKeyur Desai 			    "scf_pg_update(%s) failed: %s",
546e3f2c991SKeyur Desai 			    name, scf_strerror(scf_error()));
547e3f2c991SKeyur Desai 			goto destruction;
548e3f2c991SKeyur Desai 		}
549148c5f43SAlan Wright 		if (scf_transaction_start(tx, pg) != 0) {
550e3f2c991SKeyur Desai 			idmapdlog(LOG_ERR,
551e3f2c991SKeyur Desai 			    "scf_transaction_start(%s) failed: %s",
552e3f2c991SKeyur Desai 			    name, scf_strerror(scf_error()));
553e3f2c991SKeyur Desai 			goto destruction;
554e3f2c991SKeyur Desai 		}
555e3f2c991SKeyur Desai 
556e3f2c991SKeyur Desai 		if (scf_transaction_property_delete(tx, ent, name) != 0) {
557e3f2c991SKeyur Desai 			/* Don't complain if it already doesn't exist. */
558e3f2c991SKeyur Desai 			if (scf_error() != SCF_ERROR_NOT_FOUND) {
559e3f2c991SKeyur Desai 				idmapdlog(LOG_ERR,
560e3f2c991SKeyur Desai 				    "scf_transaction_property_delete() failed:"
561e3f2c991SKeyur Desai 				    " %s",
562e3f2c991SKeyur Desai 				    scf_strerror(scf_error()));
563e3f2c991SKeyur Desai 			}
564e3f2c991SKeyur Desai 			goto destruction;
565e3f2c991SKeyur Desai 		}
566e3f2c991SKeyur Desai 
567e3f2c991SKeyur Desai 		ret = scf_transaction_commit(tx);
568e3f2c991SKeyur Desai 
569e3f2c991SKeyur Desai 		if (ret == 0)
570e3f2c991SKeyur Desai 			scf_transaction_reset(tx);
571e3f2c991SKeyur Desai 	} while (ret == 0);
572e3f2c991SKeyur Desai 
573e3f2c991SKeyur Desai 	if (ret == -1) {
574e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
575e3f2c991SKeyur Desai 		    "scf_transaction_commit(%s) failed: %s",
576e3f2c991SKeyur Desai 		    name, scf_strerror(scf_error()));
577e3f2c991SKeyur Desai 		goto destruction;
578e3f2c991SKeyur Desai 	}
579e3f2c991SKeyur Desai 
580e3f2c991SKeyur Desai 	rc = 0;
581e3f2c991SKeyur Desai 
582e3f2c991SKeyur Desai destruction:
583e3f2c991SKeyur Desai 	if (ent != NULL)
584e3f2c991SKeyur Desai 		scf_entry_destroy(ent);
585e3f2c991SKeyur Desai 	if (tx != NULL)
586e3f2c991SKeyur Desai 		scf_transaction_destroy(tx);
587e3f2c991SKeyur Desai 	return (rc);
588e3f2c991SKeyur Desai }
589e3f2c991SKeyur Desai 
590e3f2c991SKeyur Desai 
591e3f2c991SKeyur Desai static int
set_val(idmap_cfg_handles_t * handles,scf_propertygroup_t * pg,const char * name,scf_value_t * value)592148c5f43SAlan Wright set_val(
593148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
594148c5f43SAlan Wright     scf_propertygroup_t *pg,
595148c5f43SAlan Wright     const char *name,
596148c5f43SAlan Wright     scf_value_t *value)
5978edda628Sbaban {
598e3c2d6aaSnw141292 	int			rc = -1;
599e3c2d6aaSnw141292 	int			i;
600148c5f43SAlan Wright 	scf_property_t		*prop = NULL;
6018edda628Sbaban 	scf_transaction_t	*tx = NULL;
6028edda628Sbaban 	scf_transaction_entry_t	*ent = NULL;
6038edda628Sbaban 
604148c5f43SAlan Wright 	if ((prop = scf_property_create(handles->main)) == NULL ||
605c8e26105Sjp151216 	    (tx = scf_transaction_create(handles->main)) == NULL ||
606c8e26105Sjp151216 	    (ent = scf_entry_create(handles->main)) == NULL) {
60771590c90Snw141292 		idmapdlog(LOG_ERR, "Unable to set property %s",
60871590c90Snw141292 		    name, scf_strerror(scf_error()));
6098edda628Sbaban 		goto destruction;
6108edda628Sbaban 	}
6118edda628Sbaban 
612148c5f43SAlan Wright 	for (i = 0; i < MAX_TRIES; i++) {
613148c5f43SAlan Wright 		int ret;
614148c5f43SAlan Wright 
615148c5f43SAlan Wright 		if (scf_pg_update(pg) == -1) {
616148c5f43SAlan Wright 			idmapdlog(LOG_ERR,
617148c5f43SAlan Wright 			    "scf_pg_update() failed: %s",
618148c5f43SAlan Wright 			    scf_strerror(scf_error()));
619148c5f43SAlan Wright 			goto destruction;
620148c5f43SAlan Wright 		}
621148c5f43SAlan Wright 
622148c5f43SAlan Wright 		if (scf_transaction_start(tx, pg) == -1) {
6238edda628Sbaban 			idmapdlog(LOG_ERR,
62471590c90Snw141292 			    "scf_transaction_start(%s) failed: %s",
62571590c90Snw141292 			    name, scf_strerror(scf_error()));
6268edda628Sbaban 			goto destruction;
6278edda628Sbaban 		}
6288edda628Sbaban 
629148c5f43SAlan Wright 		ret = scf_pg_get_property(pg, name, prop);
630148c5f43SAlan Wright 		if (ret == SCF_SUCCESS) {
631148c5f43SAlan Wright 			if (scf_transaction_property_change_type(tx, ent, name,
632148c5f43SAlan Wright 			    scf_value_type(value)) < 0) {
633148c5f43SAlan Wright 				idmapdlog(LOG_ERR,
634148c5f43SAlan Wright 				    "scf_transaction_property_change_type(%s)"
635148c5f43SAlan Wright 				    " failed: %s",
636148c5f43SAlan Wright 				    name, scf_strerror(scf_error()));
637148c5f43SAlan Wright 				goto destruction;
638148c5f43SAlan Wright 			}
639148c5f43SAlan Wright 		} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
640e3c2d6aaSnw141292 			if (scf_transaction_property_new(tx, ent, name,
641148c5f43SAlan Wright 			    scf_value_type(value)) < 0) {
6428edda628Sbaban 				idmapdlog(LOG_ERR,
64371590c90Snw141292 				    "scf_transaction_property_new() failed: %s",
64471590c90Snw141292 				    scf_strerror(scf_error()));
6458edda628Sbaban 				goto destruction;
6468edda628Sbaban 			}
647148c5f43SAlan Wright 		} else {
6488edda628Sbaban 			idmapdlog(LOG_ERR,
649148c5f43SAlan Wright 			    "scf_pg_get_property(%s) failed: %s",
650148c5f43SAlan Wright 			    name, scf_strerror(scf_error()));
6518edda628Sbaban 			goto destruction;
6528edda628Sbaban 		}
6538edda628Sbaban 
6548edda628Sbaban 		if (scf_entry_add_value(ent, value) == -1) {
6558edda628Sbaban 			idmapdlog(LOG_ERR,
65671590c90Snw141292 			    "scf_entry_add_value() failed: %s",
65771590c90Snw141292 			    scf_strerror(scf_error()));
6588edda628Sbaban 			goto destruction;
6598edda628Sbaban 		}
6608edda628Sbaban 
661148c5f43SAlan Wright 		ret = scf_transaction_commit(tx);
662148c5f43SAlan Wright 		if (ret == 0) {
6638edda628Sbaban 			/*
6648edda628Sbaban 			 * Property group set in scf_transaction_start()
6658edda628Sbaban 			 * is not the most recent. Update pg, reset tx and
6668edda628Sbaban 			 * retry tx.
6678edda628Sbaban 			 */
6688edda628Sbaban 			idmapdlog(LOG_WARNING,
669148c5f43SAlan Wright 			    "scf_transaction_commit(%s) failed: %s",
67071590c90Snw141292 			    name, scf_strerror(scf_error()));
6718edda628Sbaban 			scf_transaction_reset(tx);
672148c5f43SAlan Wright 			continue;
6738edda628Sbaban 		}
674148c5f43SAlan Wright 		if (ret != 1) {
6758edda628Sbaban 			idmapdlog(LOG_ERR,
67671590c90Snw141292 			    "scf_transaction_commit(%s) failed: %s",
67771590c90Snw141292 			    name, scf_strerror(scf_error()));
678148c5f43SAlan Wright 			goto destruction;
679148c5f43SAlan Wright 		}
680148c5f43SAlan Wright 		/* Success! */
681148c5f43SAlan Wright 		rc = 0;
682148c5f43SAlan Wright 		break;
683148c5f43SAlan Wright 	}
6848edda628Sbaban 
6858edda628Sbaban destruction:
6868edda628Sbaban 	scf_entry_destroy(ent);
6878edda628Sbaban 	scf_transaction_destroy(tx);
688148c5f43SAlan Wright 	scf_property_destroy(prop);
689148c5f43SAlan Wright 	return (rc);
690148c5f43SAlan Wright }
691148c5f43SAlan Wright 
692148c5f43SAlan Wright static int
set_val_integer(idmap_cfg_handles_t * handles,scf_propertygroup_t * pg,const char * name,int64_t val)693148c5f43SAlan Wright set_val_integer(
694148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
695148c5f43SAlan Wright     scf_propertygroup_t *pg,
696148c5f43SAlan Wright     const char *name,
697148c5f43SAlan Wright     int64_t val)
698148c5f43SAlan Wright {
699148c5f43SAlan Wright 	scf_value_t		*value = NULL;
700148c5f43SAlan Wright 	int			rc;
701148c5f43SAlan Wright 
702148c5f43SAlan Wright 	if ((value = scf_value_create(handles->main)) == NULL) {
703148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "Unable to set property %s",
704148c5f43SAlan Wright 		    name, scf_strerror(scf_error()));
705148c5f43SAlan Wright 		return (-1);
706148c5f43SAlan Wright 	}
707148c5f43SAlan Wright 
708148c5f43SAlan Wright 	scf_value_set_integer(value, val);
709148c5f43SAlan Wright 
710148c5f43SAlan Wright 	rc = set_val(handles, pg, name, value);
711148c5f43SAlan Wright 
712148c5f43SAlan Wright 	scf_value_destroy(value);
713148c5f43SAlan Wright 
714148c5f43SAlan Wright 	return (rc);
715148c5f43SAlan Wright }
716148c5f43SAlan Wright 
717148c5f43SAlan Wright 
718148c5f43SAlan Wright static int
set_val_astring(idmap_cfg_handles_t * handles,scf_propertygroup_t * pg,const char * name,const char * val)719148c5f43SAlan Wright set_val_astring(
720148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
721148c5f43SAlan Wright     scf_propertygroup_t *pg,
722148c5f43SAlan Wright     const char *name,
723148c5f43SAlan Wright     const char *val)
724148c5f43SAlan Wright {
725148c5f43SAlan Wright 	scf_value_t		*value = NULL;
726148c5f43SAlan Wright 	int			rc = -1;
727148c5f43SAlan Wright 
728148c5f43SAlan Wright 	if ((value = scf_value_create(handles->main)) == NULL) {
729148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "Unable to set property %s",
730148c5f43SAlan Wright 		    name, scf_strerror(scf_error()));
731148c5f43SAlan Wright 		goto out;
732148c5f43SAlan Wright 	}
733148c5f43SAlan Wright 
734148c5f43SAlan Wright 	if (scf_value_set_astring(value, val) == -1) {
735148c5f43SAlan Wright 		idmapdlog(LOG_ERR,
736148c5f43SAlan Wright 		    "scf_value_set_astring() failed: %s",
737148c5f43SAlan Wright 		    scf_strerror(scf_error()));
738148c5f43SAlan Wright 		goto out;
739148c5f43SAlan Wright 	}
740148c5f43SAlan Wright 
741148c5f43SAlan Wright 	rc = set_val(handles, pg, name, value);
742148c5f43SAlan Wright 
743148c5f43SAlan Wright out:
744148c5f43SAlan Wright 	scf_value_destroy(value);
7458edda628Sbaban 	return (rc);
7468edda628Sbaban }
7478edda628Sbaban 
7484d61c878SJulian Pullen 
7494d61c878SJulian Pullen 
7504d61c878SJulian Pullen /*
7514d61c878SJulian Pullen  * This function updates a boolean value.
7524d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
7534d61c878SJulian Pullen  */
754c8e26105Sjp151216 static int
update_bool(boolean_t * value,boolean_t * new,char * name)7557a8a68f5SJulian Pullen update_bool(boolean_t *value, boolean_t *new, char *name)
7564aa0a5e7Snw141292 {
7574aa0a5e7Snw141292 	if (*value == *new)
7584aa0a5e7Snw141292 		return (0);
7594aa0a5e7Snw141292 
760148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
761148c5f43SAlan Wright 		idmapdlog(LOG_INFO, "change %s=%s", name,
762148c5f43SAlan Wright 		    *new ? "true" : "false");
763148c5f43SAlan Wright 	}
764148c5f43SAlan Wright 
7654aa0a5e7Snw141292 	*value = *new;
7664aa0a5e7Snw141292 	return (1);
7674aa0a5e7Snw141292 }
7684aa0a5e7Snw141292 
7694d61c878SJulian Pullen /*
77048cd229bSGordon Ross  * This function updates a uint64_t value.
77148cd229bSGordon Ross  * If nothing has changed it returns 0 else 1
77248cd229bSGordon Ross  */
77348cd229bSGordon Ross static int
update_uint64(uint64_t * value,uint64_t * new,char * name)77448cd229bSGordon Ross update_uint64(uint64_t *value, uint64_t *new, char *name)
77548cd229bSGordon Ross {
77648cd229bSGordon Ross 	if (*value == *new)
77748cd229bSGordon Ross 		return (0);
77848cd229bSGordon Ross 
77948cd229bSGordon Ross 	if (DBG(CONFIG, 1))
78048cd229bSGordon Ross 		idmapdlog(LOG_INFO, "change %s=%llu", name, *new);
78148cd229bSGordon Ross 
78248cd229bSGordon Ross 	*value = *new;
78348cd229bSGordon Ross 	return (1);
78448cd229bSGordon Ross }
78548cd229bSGordon Ross 
78648cd229bSGordon Ross /*
7874d61c878SJulian Pullen  * This function updates a string value.
7884d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
7894d61c878SJulian Pullen  */
7904aa0a5e7Snw141292 static int
update_string(char ** value,char ** new,char * name)7914aa0a5e7Snw141292 update_string(char **value, char **new, char *name)
792c5c4113dSnw141292 {
793148c5f43SAlan Wright 	int changed;
794c5c4113dSnw141292 
795148c5f43SAlan Wright 	if (*new == NULL && *value != NULL)
796148c5f43SAlan Wright 		changed = 1;
797148c5f43SAlan Wright 	else if (*new != NULL && *value == NULL)
798148c5f43SAlan Wright 		changed = 1;
799148c5f43SAlan Wright 	else if (*new != NULL && *value != NULL && strcmp(*new, *value) != 0)
800148c5f43SAlan Wright 		changed = 1;
801148c5f43SAlan Wright 	else
802148c5f43SAlan Wright 		changed = 0;
803c5c4113dSnw141292 
804148c5f43SAlan Wright 	/*
805148c5f43SAlan Wright 	 * Note that even if unchanged we can't just return; we must free one
806148c5f43SAlan Wright 	 * of the values.
807148c5f43SAlan Wright 	 */
808148c5f43SAlan Wright 
809148c5f43SAlan Wright 	if (DBG(CONFIG, 1) && changed)
81071590c90Snw141292 		idmapdlog(LOG_INFO, "change %s=%s", name, CHECK_NULL(*new));
811148c5f43SAlan Wright 
812c8e26105Sjp151216 	free(*value);
813c8e26105Sjp151216 	*value = *new;
814c8e26105Sjp151216 	*new = NULL;
815148c5f43SAlan Wright 	return (changed);
816c5c4113dSnw141292 }
817c5c4113dSnw141292 
818e3f2c991SKeyur Desai static int
update_enum(int * value,int * new,char * name,struct enum_lookup_map * map)819e3f2c991SKeyur Desai update_enum(int *value, int *new, char *name, struct enum_lookup_map *map)
820e3f2c991SKeyur Desai {
821e3f2c991SKeyur Desai 	if (*value == *new)
822e3f2c991SKeyur Desai 		return (0);
823e3f2c991SKeyur Desai 
824148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
825148c5f43SAlan Wright 		idmapdlog(LOG_INFO, "change %s=%s", name,
826148c5f43SAlan Wright 		    enum_lookup(*new, map));
827148c5f43SAlan Wright 	}
828e3f2c991SKeyur Desai 
829e3f2c991SKeyur Desai 	*value = *new;
830e3f2c991SKeyur Desai 
831e3f2c991SKeyur Desai 	return (1);
832e3f2c991SKeyur Desai }
8334d61c878SJulian Pullen 
8344d61c878SJulian Pullen /*
8354d61c878SJulian Pullen  * This function updates a directory service structure.
8364d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
8374d61c878SJulian Pullen  */
838c8e26105Sjp151216 static int
update_dirs(idmap_ad_disc_ds_t ** value,idmap_ad_disc_ds_t ** new,char * name)839479ac375Sdm199847 update_dirs(idmap_ad_disc_ds_t **value, idmap_ad_disc_ds_t **new, char *name)
840c8e26105Sjp151216 {
841c8e26105Sjp151216 	int i;
842c5c4113dSnw141292 
8430dcc7149Snw141292 	if (*value == *new)
8440dcc7149Snw141292 		/* Nothing to do */
845349d5d8fSnw141292 		return (0);
846c8e26105Sjp151216 
8470dcc7149Snw141292 	if (*value != NULL && *new != NULL &&
8480dcc7149Snw141292 	    ad_disc_compare_ds(*value, *new) == 0) {
849c8e26105Sjp151216 		free(*new);
850c8e26105Sjp151216 		*new = NULL;
851349d5d8fSnw141292 		return (0);
852c8e26105Sjp151216 	}
853c8e26105Sjp151216 
8544d61c878SJulian Pullen 	if (*value != NULL)
855c8e26105Sjp151216 		free(*value);
856c8e26105Sjp151216 
857c8e26105Sjp151216 	*value = *new;
858c8e26105Sjp151216 	*new = NULL;
8590dcc7149Snw141292 
8600dcc7149Snw141292 	if (*value == NULL) {
8610dcc7149Snw141292 		/* We're unsetting this DS property */
862148c5f43SAlan Wright 		if (DBG(CONFIG, 1))
86371590c90Snw141292 			idmapdlog(LOG_INFO, "change %s=<none>", name);
864349d5d8fSnw141292 		return (1);
8650dcc7149Snw141292 	}
8660dcc7149Snw141292 
867148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
8680dcc7149Snw141292 		/* List all the new DSs */
869148c5f43SAlan Wright 		for (i = 0; (*value)[i].host[0] != '\0'; i++) {
87071590c90Snw141292 			idmapdlog(LOG_INFO, "change %s=%s port=%d", name,
8710dcc7149Snw141292 			    (*value)[i].host, (*value)[i].port);
872148c5f43SAlan Wright 		}
873148c5f43SAlan Wright 	}
874349d5d8fSnw141292 	return (1);
875c8e26105Sjp151216 }
876c8e26105Sjp151216 
8774d61c878SJulian Pullen /*
8784d61c878SJulian Pullen  * This function updates a trusted domains structure.
8794d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
8804d61c878SJulian Pullen  */
8814d61c878SJulian Pullen static int
update_trusted_domains(ad_disc_trusteddomains_t ** value,ad_disc_trusteddomains_t ** new,char * name)8824d61c878SJulian Pullen update_trusted_domains(ad_disc_trusteddomains_t **value,
8834d61c878SJulian Pullen 			ad_disc_trusteddomains_t **new, char *name)
8844d61c878SJulian Pullen {
8854d61c878SJulian Pullen 	int i;
8864d61c878SJulian Pullen 
8874d61c878SJulian Pullen 	if (*value == *new)
8884d61c878SJulian Pullen 		/* Nothing to do */
8894d61c878SJulian Pullen 		return (0);
8904d61c878SJulian Pullen 
8914d61c878SJulian Pullen 	if (*value != NULL && *new != NULL &&
8924d61c878SJulian Pullen 	    ad_disc_compare_trusteddomains(*value, *new) == 0) {
8934d61c878SJulian Pullen 		free(*new);
8944d61c878SJulian Pullen 		*new = NULL;
8954d61c878SJulian Pullen 		return (0);
8964d61c878SJulian Pullen 	}
8974d61c878SJulian Pullen 
8984d61c878SJulian Pullen 	if (*value != NULL)
8994d61c878SJulian Pullen 		free(*value);
9004d61c878SJulian Pullen 
9014d61c878SJulian Pullen 	*value = *new;
9024d61c878SJulian Pullen 	*new = NULL;
9034d61c878SJulian Pullen 
9044d61c878SJulian Pullen 	if (*value == NULL) {
9054d61c878SJulian Pullen 		/* We're unsetting this DS property */
906148c5f43SAlan Wright 		if (DBG(CONFIG, 1))
9074d61c878SJulian Pullen 			idmapdlog(LOG_INFO, "change %s=<none>", name);
9084d61c878SJulian Pullen 		return (1);
9094d61c878SJulian Pullen 	}
9104d61c878SJulian Pullen 
911148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
9124d61c878SJulian Pullen 		/* List all the new domains */
913148c5f43SAlan Wright 		for (i = 0; (*value)[i].domain[0] != '\0'; i++) {
9144d61c878SJulian Pullen 			idmapdlog(LOG_INFO, "change %s=%s direction=%s", name,
9154d61c878SJulian Pullen 			    (*value)[i].domain,
916148c5f43SAlan Wright 			    enum_lookup((*value)[i].direction, trust_dir_map));
917148c5f43SAlan Wright 		}
918148c5f43SAlan Wright 	}
9194d61c878SJulian Pullen 	return (1);
9204d61c878SJulian Pullen }
9214d61c878SJulian Pullen 
9224d61c878SJulian Pullen 
9234d61c878SJulian Pullen /*
9244d61c878SJulian Pullen  * This function updates a domains in a forest structure.
9254d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
9264d61c878SJulian Pullen  */
9274d61c878SJulian Pullen static int
update_domains_in_forest(ad_disc_domainsinforest_t ** value,ad_disc_domainsinforest_t ** new,char * name)9284d61c878SJulian Pullen update_domains_in_forest(ad_disc_domainsinforest_t **value,
9294d61c878SJulian Pullen 			ad_disc_domainsinforest_t **new, char *name)
9304d61c878SJulian Pullen {
9314d61c878SJulian Pullen 	int i;
9324d61c878SJulian Pullen 
9334d61c878SJulian Pullen 	if (*value == *new)
9344d61c878SJulian Pullen 		/* Nothing to do */
9354d61c878SJulian Pullen 		return (0);
9364d61c878SJulian Pullen 
9374d61c878SJulian Pullen 	if (*value != NULL && *new != NULL &&
9384d61c878SJulian Pullen 	    ad_disc_compare_domainsinforest(*value, *new) == 0) {
9394d61c878SJulian Pullen 		free(*new);
9404d61c878SJulian Pullen 		*new = NULL;
9414d61c878SJulian Pullen 		return (0);
9424d61c878SJulian Pullen 	}
9434d61c878SJulian Pullen 
9444d61c878SJulian Pullen 	if (*value != NULL)
9454d61c878SJulian Pullen 		free(*value);
9464d61c878SJulian Pullen 
9474d61c878SJulian Pullen 	*value = *new;
9484d61c878SJulian Pullen 	*new = NULL;
9494d61c878SJulian Pullen 
9504d61c878SJulian Pullen 	if (*value == NULL) {
9514d61c878SJulian Pullen 		/* We're unsetting this DS property */
952148c5f43SAlan Wright 		if (DBG(CONFIG, 1))
9534d61c878SJulian Pullen 			idmapdlog(LOG_INFO, "change %s=<none>", name);
9544d61c878SJulian Pullen 		return (1);
9554d61c878SJulian Pullen 	}
9564d61c878SJulian Pullen 
957148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
9584d61c878SJulian Pullen 		/* List all the new domains */
959148c5f43SAlan Wright 		for (i = 0; (*value)[i].domain[0] != '\0'; i++) {
9604d61c878SJulian Pullen 			idmapdlog(LOG_INFO, "change %s=%s", name,
9614d61c878SJulian Pullen 			    (*value)[i].domain);
962148c5f43SAlan Wright 		}
963148c5f43SAlan Wright 	}
9644d61c878SJulian Pullen 	return (1);
9654d61c878SJulian Pullen }
9664d61c878SJulian Pullen 
9674d61c878SJulian Pullen 
9684d61c878SJulian Pullen static void
free_trusted_forests(idmap_trustedforest_t ** value,int * num_values)9694d61c878SJulian Pullen free_trusted_forests(idmap_trustedforest_t **value, int *num_values)
9704d61c878SJulian Pullen {
9714d61c878SJulian Pullen 	int i;
9724d61c878SJulian Pullen 
9734d61c878SJulian Pullen 	for (i = 0; i < *num_values; i++) {
9744d61c878SJulian Pullen 		free((*value)[i].forest_name);
9754d61c878SJulian Pullen 		free((*value)[i].global_catalog);
9764d61c878SJulian Pullen 		free((*value)[i].domains_in_forest);
9774d61c878SJulian Pullen 	}
9784d61c878SJulian Pullen 	free(*value);
9794d61c878SJulian Pullen 	*value = NULL;
9804d61c878SJulian Pullen 	*num_values = 0;
9814d61c878SJulian Pullen }
9824d61c878SJulian Pullen 
9834d61c878SJulian Pullen 
9844d61c878SJulian Pullen static int
compare_trusteddomainsinforest(ad_disc_domainsinforest_t * df1,ad_disc_domainsinforest_t * df2)9854d61c878SJulian Pullen compare_trusteddomainsinforest(ad_disc_domainsinforest_t *df1,
9864d61c878SJulian Pullen 			ad_disc_domainsinforest_t *df2)
9874d61c878SJulian Pullen {
9884d61c878SJulian Pullen 	int		i, j;
9894d61c878SJulian Pullen 	int		num_df1 = 0;
9904d61c878SJulian Pullen 	int		num_df2 = 0;
9917a8a68f5SJulian Pullen 	boolean_t	match;
9924d61c878SJulian Pullen 
9934d61c878SJulian Pullen 	for (i = 0; df1[i].domain[0] != '\0'; i++)
9944d61c878SJulian Pullen 		if (df1[i].trusted)
9954d61c878SJulian Pullen 			num_df1++;
9964d61c878SJulian Pullen 
9974d61c878SJulian Pullen 	for (j = 0; df2[j].domain[0] != '\0'; j++)
9984d61c878SJulian Pullen 		if (df2[j].trusted)
9994d61c878SJulian Pullen 			num_df2++;
10004d61c878SJulian Pullen 
10014d61c878SJulian Pullen 	if (num_df1 != num_df2)
10024d61c878SJulian Pullen 		return (1);
10034d61c878SJulian Pullen 
10044d61c878SJulian Pullen 	for (i = 0; df1[i].domain[0] != '\0'; i++) {
10054d61c878SJulian Pullen 		if (df1[i].trusted) {
10067a8a68f5SJulian Pullen 			match = B_FALSE;
10074d61c878SJulian Pullen 			for (j = 0; df2[j].domain[0] != '\0'; j++) {
10084d61c878SJulian Pullen 				if (df2[j].trusted &&
10091fcced4cSJordan Brown 				    domain_eq(df1[i].domain, df2[j].domain) &&
10101fcced4cSJordan Brown 				    strcmp(df1[i].sid, df2[j].sid) == 0) {
10117a8a68f5SJulian Pullen 					match = B_TRUE;
10124d61c878SJulian Pullen 					break;
10134d61c878SJulian Pullen 				}
10144d61c878SJulian Pullen 			}
10154d61c878SJulian Pullen 			if (!match)
10164d61c878SJulian Pullen 				return (1);
10174d61c878SJulian Pullen 		}
10184d61c878SJulian Pullen 	}
10194d61c878SJulian Pullen 	return (0);
10204d61c878SJulian Pullen }
10214d61c878SJulian Pullen 
10224d61c878SJulian Pullen 
10234d61c878SJulian Pullen 
10244d61c878SJulian Pullen /*
10254d61c878SJulian Pullen  * This function updates trusted forest structure.
10264d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
10274d61c878SJulian Pullen  */
10284d61c878SJulian Pullen static int
update_trusted_forest(idmap_trustedforest_t ** value,int * num_value,idmap_trustedforest_t ** new,int * num_new,char * name)10294d61c878SJulian Pullen update_trusted_forest(idmap_trustedforest_t **value, int *num_value,
10304d61c878SJulian Pullen 			idmap_trustedforest_t **new, int *num_new, char *name)
10314d61c878SJulian Pullen {
10324d61c878SJulian Pullen 	int i, j;
10337a8a68f5SJulian Pullen 	boolean_t match;
10344d61c878SJulian Pullen 
10354d61c878SJulian Pullen 	if (*value == *new)
10364d61c878SJulian Pullen 		/* Nothing to do */
10374d61c878SJulian Pullen 		return (0);
10384d61c878SJulian Pullen 
10394d61c878SJulian Pullen 	if (*value != NULL && *new != NULL) {
10404d61c878SJulian Pullen 		if (*num_value != *num_new)
10414d61c878SJulian Pullen 			goto not_equal;
10424d61c878SJulian Pullen 		for (i = 0; i < *num_value; i++) {
10437a8a68f5SJulian Pullen 			match = B_FALSE;
10444d61c878SJulian Pullen 			for (j = 0; j < *num_new; j++) {
10454d61c878SJulian Pullen 				if (strcmp((*value)[i].forest_name,
10464d61c878SJulian Pullen 				    (*new)[j].forest_name) == 0 &&
10474d61c878SJulian Pullen 				    ad_disc_compare_ds(
10484d61c878SJulian Pullen 				    (*value)[i].global_catalog,
10491fcced4cSJordan Brown 				    (*new)[j].global_catalog) == 0 &&
10504d61c878SJulian Pullen 				    compare_trusteddomainsinforest(
10514d61c878SJulian Pullen 				    (*value)[i].domains_in_forest,
10521fcced4cSJordan Brown 				    (*new)[j].domains_in_forest) == 0) {
10537a8a68f5SJulian Pullen 					match = B_TRUE;
10544d61c878SJulian Pullen 					break;
10554d61c878SJulian Pullen 				}
10564d61c878SJulian Pullen 			}
10574d61c878SJulian Pullen 			if (!match)
10584d61c878SJulian Pullen 				goto not_equal;
10594d61c878SJulian Pullen 		}
10604d61c878SJulian Pullen 		free_trusted_forests(new, num_new);
10614d61c878SJulian Pullen 		return (0);
10624d61c878SJulian Pullen 	}
10634d61c878SJulian Pullen not_equal:
10644d61c878SJulian Pullen 	if (*value != NULL)
10654d61c878SJulian Pullen 		free_trusted_forests(value, num_value);
10664d61c878SJulian Pullen 	*value = *new;
10674d61c878SJulian Pullen 	*num_value = *num_new;
10684d61c878SJulian Pullen 	*new = NULL;
10694d61c878SJulian Pullen 	*num_new = 0;
10704d61c878SJulian Pullen 
10714d61c878SJulian Pullen 	if (*value == NULL) {
10724d61c878SJulian Pullen 		/* We're unsetting this DS property */
1073148c5f43SAlan Wright 		if (DBG(CONFIG, 1))
10744d61c878SJulian Pullen 			idmapdlog(LOG_INFO, "change %s=<none>", name);
10754d61c878SJulian Pullen 		return (1);
10764d61c878SJulian Pullen 	}
10774d61c878SJulian Pullen 
1078148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
10794d61c878SJulian Pullen 		/* List all the trusted forests */
10804d61c878SJulian Pullen 		for (i = 0; i < *num_value; i++) {
1081148c5f43SAlan Wright 			idmap_trustedforest_t *f = &(*value)[i];
1082148c5f43SAlan Wright 			for (j = 0;
1083148c5f43SAlan Wright 			    f->domains_in_forest[j].domain[0] != '\0';
10844d61c878SJulian Pullen 			    j++) {
10854d61c878SJulian Pullen 				/* List trusted Domains in the forest. */
1086148c5f43SAlan Wright 				if (f->domains_in_forest[j].trusted)
1087148c5f43SAlan Wright 					idmapdlog(LOG_INFO,
1088148c5f43SAlan Wright 					    "change %s=%s domain=%s",
1089148c5f43SAlan Wright 					    name, f->forest_name,
1090148c5f43SAlan Wright 					    f->domains_in_forest[j].domain);
10914d61c878SJulian Pullen 			}
10924d61c878SJulian Pullen 			/* List the hosts */
1093148c5f43SAlan Wright 			for (j = 0;
1094148c5f43SAlan Wright 			    f->global_catalog[j].host[0] != '\0';
1095148c5f43SAlan Wright 			    j++) {
1096148c5f43SAlan Wright 				idmapdlog(LOG_INFO,
1097148c5f43SAlan Wright 				    "change %s=%s host=%s port=%d",
1098148c5f43SAlan Wright 				    name, f->forest_name,
1099148c5f43SAlan Wright 				    f->global_catalog[j].host,
1100148c5f43SAlan Wright 				    f->global_catalog[j].port);
1101148c5f43SAlan Wright 			}
1102148c5f43SAlan Wright 		}
11034d61c878SJulian Pullen 	}
11044d61c878SJulian Pullen 	return (1);
11054d61c878SJulian Pullen }
11064d61c878SJulian Pullen 
1107e3f2c991SKeyur Desai const char *
enum_lookup(int value,struct enum_lookup_map * map)1108e3f2c991SKeyur Desai enum_lookup(int value, struct enum_lookup_map *map)
1109e3f2c991SKeyur Desai {
1110e3f2c991SKeyur Desai 	for (; map->string != NULL; map++) {
1111e3f2c991SKeyur Desai 		if (value == map->value) {
1112e3f2c991SKeyur Desai 			return (map->string);
1113e3f2c991SKeyur Desai 		}
1114e3f2c991SKeyur Desai 	}
1115e3f2c991SKeyur Desai 	return ("(invalid)");
1116e3f2c991SKeyur Desai }
1117c8e26105Sjp151216 
1118c5c4113dSnw141292 /*
11190dcc7149Snw141292  * Returns 1 if the PF_ROUTE socket event indicates that we should rescan the
11200dcc7149Snw141292  * interfaces.
1121c8e26105Sjp151216  *
11220dcc7149Snw141292  * Shamelessly based on smb_nics_changed() and other PF_ROUTE uses in ON.
11230dcc7149Snw141292  */
11240dcc7149Snw141292 static
1125c5866007SKeyur Desai boolean_t
pfroute_event_is_interesting(int rt_sock)11260dcc7149Snw141292 pfroute_event_is_interesting(int rt_sock)
11270dcc7149Snw141292 {
11280dcc7149Snw141292 	int nbytes;
11290dcc7149Snw141292 	int64_t msg[2048 / 8];
11300dcc7149Snw141292 	struct rt_msghdr *rtm;
1131c5866007SKeyur Desai 	boolean_t is_interesting = B_FALSE;
11320dcc7149Snw141292 
11330dcc7149Snw141292 	for (;;) {
11340dcc7149Snw141292 		if ((nbytes = read(rt_sock, msg, sizeof (msg))) <= 0)
11350dcc7149Snw141292 			break;
11360dcc7149Snw141292 		rtm = (struct rt_msghdr *)msg;
11370dcc7149Snw141292 		if (rtm->rtm_version != RTM_VERSION)
11380dcc7149Snw141292 			continue;
11390dcc7149Snw141292 		if (nbytes < rtm->rtm_msglen)
11400dcc7149Snw141292 			continue;
11410dcc7149Snw141292 		switch (rtm->rtm_type) {
11420dcc7149Snw141292 		case RTM_NEWADDR:
11430dcc7149Snw141292 		case RTM_DELADDR:
11440dcc7149Snw141292 		case RTM_IFINFO:
1145c5866007SKeyur Desai 			is_interesting = B_TRUE;
11460dcc7149Snw141292 			break;
11470dcc7149Snw141292 		default:
11480dcc7149Snw141292 			break;
11490dcc7149Snw141292 		}
11500dcc7149Snw141292 	}
11510dcc7149Snw141292 	return (is_interesting);
11520dcc7149Snw141292 }
11530dcc7149Snw141292 
11540dcc7149Snw141292 /*
1155c5866007SKeyur Desai  * Wait for an event, and report what kind of event occurred.
11560dcc7149Snw141292  *
1157c5866007SKeyur Desai  * Note that there are cases where we are awoken but don't care about
1158c5866007SKeyur Desai  * the lower-level event.  We can't just loop here because we can't
1159c5866007SKeyur Desai  * readily calculate how long to sleep the next time.  We return
1160c5866007SKeyur Desai  * EVENT_NOTHING and let the caller loop.
1161c5c4113dSnw141292  */
1162c8e26105Sjp151216 static
1163c5866007SKeyur Desai enum event_type
wait_for_event(struct timespec * timeoutp)1164c5866007SKeyur Desai wait_for_event(struct timespec *timeoutp)
1165c8e26105Sjp151216 {
1166c8e26105Sjp151216 	port_event_t pe;
1167c8e26105Sjp151216 
1168148c5f43SAlan Wright 	(void) memset(&pe, 0, sizeof (pe));
1169349d5d8fSnw141292 	if (port_get(idmapd_ev_port, &pe, timeoutp) != 0) {
1170c8e26105Sjp151216 		switch (errno) {
1171c8e26105Sjp151216 		case EINTR:
1172c5866007SKeyur Desai 			return (EVENT_NOTHING);
1173c8e26105Sjp151216 		case ETIME:
1174c8e26105Sjp151216 			/* Timeout */
1175c5866007SKeyur Desai 			return (EVENT_TIMEOUT);
1176c8e26105Sjp151216 		default:
11770dcc7149Snw141292 			/* EBADF, EBADFD, EFAULT, EINVAL (end of time?)? */
11780dcc7149Snw141292 			idmapdlog(LOG_ERR, "Event port failed: %s",
11790dcc7149Snw141292 			    strerror(errno));
11800dcc7149Snw141292 			exit(1);
11810dcc7149Snw141292 			/* NOTREACHED */
1182c5866007SKeyur Desai 		}
1183c5866007SKeyur Desai 	}
1184c5866007SKeyur Desai 
1185c5866007SKeyur Desai 
1186c5866007SKeyur Desai 	switch (pe.portev_source) {
1187c5866007SKeyur Desai 	case 0:
1188c5866007SKeyur Desai 		/*
1189c5866007SKeyur Desai 		 * This isn't documented, but seems to be what you get if
1190c5866007SKeyur Desai 		 * the timeout is zero seconds and there are no events
1191c5866007SKeyur Desai 		 * pending.
1192c5866007SKeyur Desai 		 */
1193c5866007SKeyur Desai 		return (EVENT_TIMEOUT);
1194c5866007SKeyur Desai 
1195c5866007SKeyur Desai 	case PORT_SOURCE_USER:
1196c5866007SKeyur Desai 		if (pe.portev_events == POKE_AUTO_DISCOVERY)
1197c5866007SKeyur Desai 			return (EVENT_DEGRADE);
1198c5866007SKeyur Desai 		if (pe.portev_events == RECONFIGURE)
1199c5866007SKeyur Desai 			return (EVENT_REFRESH);
1200c8e26105Sjp151216 		break;
1201c5c4113dSnw141292 
1202c5866007SKeyur Desai 	case PORT_SOURCE_FD:
1203c5866007SKeyur Desai 		if (pe.portev_object == rt_sock) {
1204c5866007SKeyur Desai 			/*
1205c5866007SKeyur Desai 			 * PF_ROUTE socket read event:
1206c5866007SKeyur Desai 			 *    re-associate fd
1207c5866007SKeyur Desai 			 *    handle event
1208c5866007SKeyur Desai 			 */
1209c5866007SKeyur Desai 			if (port_associate(idmapd_ev_port, PORT_SOURCE_FD,
1210c5866007SKeyur Desai 			    rt_sock, POLLIN, NULL) != 0) {
12110dcc7149Snw141292 				idmapdlog(LOG_ERR, "Failed to re-associate the "
12120dcc7149Snw141292 				    "routing socket with the event port: %s",
12130dcc7149Snw141292 				    strerror(errno));
1214c5866007SKeyur Desai 				abort();
12150dcc7149Snw141292 			}
12160dcc7149Snw141292 			/*
1217c5866007SKeyur Desai 			 * The network configuration may still be in flux.
1218c5866007SKeyur Desai 			 * No matter, the resolver will re-transmit and
1219c5866007SKeyur Desai 			 * timeout if need be.
12200dcc7149Snw141292 			 */
1221c5866007SKeyur Desai 			if (pfroute_event_is_interesting(rt_sock)) {
1222148c5f43SAlan Wright 				if (DBG(CONFIG, 1)) {
1223c5866007SKeyur Desai 					idmapdlog(LOG_DEBUG,
1224c5866007SKeyur Desai 					    "Interesting routing event");
1225148c5f43SAlan Wright 				}
1226c5866007SKeyur Desai 				return (EVENT_ROUTING);
1227c5866007SKeyur Desai 			} else {
1228148c5f43SAlan Wright 				if (DBG(CONFIG, 2)) {
1229c5866007SKeyur Desai 					idmapdlog(LOG_DEBUG,
1230c5866007SKeyur Desai 					    "Boring routing event");
1231148c5f43SAlan Wright 				}
1232c5866007SKeyur Desai 				return (EVENT_NOTHING);
1233c5866007SKeyur Desai 			}
1234c5866007SKeyur Desai 		}
1235c5866007SKeyur Desai 		/* Event on an FD other than the routing FD? Ignore it. */
1236c5866007SKeyur Desai 		break;
12370dcc7149Snw141292 	}
12380dcc7149Snw141292 
1239c5866007SKeyur Desai 	return (EVENT_NOTHING);
1240c8e26105Sjp151216 }
1241c8e26105Sjp151216 
1242c8e26105Sjp151216 void *
idmap_cfg_update_thread(void * arg)1243c8e26105Sjp151216 idmap_cfg_update_thread(void *arg)
1244c8e26105Sjp151216 {
1245148c5f43SAlan Wright 	NOTE(ARGUNUSED(arg))
1246c8e26105Sjp151216 
1247c5866007SKeyur Desai 	const ad_disc_t		ad_ctx = _idmapdstate.cfg->handles.ad_ctx;
1248c8e26105Sjp151216 
1249c5866007SKeyur Desai 	for (;;) {
1250c5866007SKeyur Desai 		struct timespec timeout;
1251c5866007SKeyur Desai 		struct timespec	*timeoutp;
1252c5866007SKeyur Desai 		int		rc;
1253c5866007SKeyur Desai 		int		ttl;
12540dcc7149Snw141292 
12550dcc7149Snw141292 		(void) ad_disc_SubnetChanged(ad_ctx);
1256c8e26105Sjp151216 
1257c5866007SKeyur Desai 		rc = idmap_cfg_load(_idmapdstate.cfg, CFG_DISCOVER);
1258c5866007SKeyur Desai 		if (rc < -1) {
12597a8a68f5SJulian Pullen 			idmapdlog(LOG_ERR, "Fatal errors while reading "
1260349d5d8fSnw141292 			    "SMF properties");
1261349d5d8fSnw141292 			exit(1);
1262c5866007SKeyur Desai 		} else if (rc == -1) {
1263c5866007SKeyur Desai 			idmapdlog(LOG_WARNING,
1264c5866007SKeyur Desai 			    "Errors re-loading configuration may cause AD "
1265c5866007SKeyur Desai 			    "lookups to fail");
1266349d5d8fSnw141292 		}
1267c8e26105Sjp151216 
1268c5866007SKeyur Desai 		/*
1269c5866007SKeyur Desai 		 * Wait for an interesting event.  Note that we might get
1270c5866007SKeyur Desai 		 * boring events between interesting events.  If so, we loop.
1271c5866007SKeyur Desai 		 */
1272c5866007SKeyur Desai 		for (;;) {
1273c5866007SKeyur Desai 			ttl = ad_disc_get_TTL(ad_ctx);
1274c5866007SKeyur Desai 
1275c5866007SKeyur Desai 			if (ttl < 0) {
1276c5866007SKeyur Desai 				timeoutp = NULL;
1277c5866007SKeyur Desai 			} else {
1278c5866007SKeyur Desai 				timeoutp = &timeout;
1279c5866007SKeyur Desai 				timeout.tv_sec = ttl;
1280c5866007SKeyur Desai 				timeout.tv_nsec = 0;
1281c8e26105Sjp151216 			}
1282c5866007SKeyur Desai 
1283c5866007SKeyur Desai 			switch (wait_for_event(timeoutp)) {
1284c5866007SKeyur Desai 			case EVENT_NOTHING:
1285148c5f43SAlan Wright 				if (DBG(CONFIG, 2))
1286c5866007SKeyur Desai 					idmapdlog(LOG_DEBUG, "Boring event.");
1287c5866007SKeyur Desai 				continue;
1288c5866007SKeyur Desai 			case EVENT_REFRESH:
1289148c5f43SAlan Wright 				if (DBG(CONFIG, 1))
1290c5866007SKeyur Desai 					idmapdlog(LOG_INFO, "SMF refresh");
1291c5866007SKeyur Desai 				/*
1292c5866007SKeyur Desai 				 * Blow away the ccache, we might have
1293c5866007SKeyur Desai 				 * re-joined the domain or joined a new one
1294c5866007SKeyur Desai 				 */
1295c5866007SKeyur Desai 				(void) unlink(IDMAP_CACHEDIR "/ccache");
1296c5866007SKeyur Desai 				break;
1297c5866007SKeyur Desai 			case EVENT_DEGRADE:
1298148c5f43SAlan Wright 				if (DBG(CONFIG, 1)) {
1299c5866007SKeyur Desai 					idmapdlog(LOG_DEBUG,
1300c5866007SKeyur Desai 					    "Service degraded");
1301148c5f43SAlan Wright 				}
1302c5866007SKeyur Desai 				break;
1303c5866007SKeyur Desai 			case EVENT_TIMEOUT:
1304148c5f43SAlan Wright 				if (DBG(CONFIG, 1))
1305c5866007SKeyur Desai 					idmapdlog(LOG_DEBUG, "TTL expired");
1306c5866007SKeyur Desai 				break;
1307c5866007SKeyur Desai 			case EVENT_ROUTING:
1308c5866007SKeyur Desai 				/* Already logged to DEBUG */
1309c5866007SKeyur Desai 				break;
1310c5866007SKeyur Desai 			}
1311c5866007SKeyur Desai 			/* An interesting event! */
1312c5866007SKeyur Desai 			break;
1313c5866007SKeyur Desai 		}
1314c5866007SKeyur Desai 	}
1315c5866007SKeyur Desai 	/*
1316c5866007SKeyur Desai 	 * Lint isn't happy with the concept of a function declared to
1317c5866007SKeyur Desai 	 * return something, that doesn't return.  Of course, merely adding
1318c5866007SKeyur Desai 	 * the return isn't enough, because it's never reached...
1319c5866007SKeyur Desai 	 */
1320c8e26105Sjp151216 	/*NOTREACHED*/
1321c8e26105Sjp151216 	return (NULL);
1322c8e26105Sjp151216 }
1323c8e26105Sjp151216 
1324c8e26105Sjp151216 int
idmap_cfg_start_updates(void)13250dcc7149Snw141292 idmap_cfg_start_updates(void)
1326c8e26105Sjp151216 {
13270dcc7149Snw141292 	if ((idmapd_ev_port = port_create()) < 0) {
132871590c90Snw141292 		idmapdlog(LOG_ERR, "Failed to create event port: %s",
132971590c90Snw141292 		    strerror(errno));
1330c5c4113dSnw141292 		return (-1);
1331c8e26105Sjp151216 	}
1332c8e26105Sjp151216 
13330dcc7149Snw141292 	if ((rt_sock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
133471590c90Snw141292 		idmapdlog(LOG_ERR, "Failed to open routing socket: %s",
133571590c90Snw141292 		    strerror(errno));
13360dcc7149Snw141292 		(void) close(idmapd_ev_port);
13370dcc7149Snw141292 		return (-1);
13380dcc7149Snw141292 	}
13390dcc7149Snw141292 
13400dcc7149Snw141292 	if (fcntl(rt_sock, F_SETFL, O_NDELAY|O_NONBLOCK) < 0) {
134171590c90Snw141292 		idmapdlog(LOG_ERR, "Failed to set routing socket flags: %s",
134271590c90Snw141292 		    strerror(errno));
13430dcc7149Snw141292 		(void) close(rt_sock);
13440dcc7149Snw141292 		(void) close(idmapd_ev_port);
13450dcc7149Snw141292 		return (-1);
13460dcc7149Snw141292 	}
13470dcc7149Snw141292 
13480dcc7149Snw141292 	if (port_associate(idmapd_ev_port, PORT_SOURCE_FD,
13490dcc7149Snw141292 	    rt_sock, POLLIN, NULL) != 0) {
135071590c90Snw141292 		idmapdlog(LOG_ERR, "Failed to associate the routing "
135171590c90Snw141292 		    "socket with the event port: %s", strerror(errno));
13520dcc7149Snw141292 		(void) close(rt_sock);
13530dcc7149Snw141292 		(void) close(idmapd_ev_port);
13540dcc7149Snw141292 		return (-1);
13550dcc7149Snw141292 	}
13560dcc7149Snw141292 
13570dcc7149Snw141292 	if ((errno = pthread_create(&update_thread_handle, NULL,
13580dcc7149Snw141292 	    idmap_cfg_update_thread, NULL)) != 0) {
135971590c90Snw141292 		idmapdlog(LOG_ERR, "Failed to start update thread: %s",
136071590c90Snw141292 		    strerror(errno));
13610dcc7149Snw141292 		(void) port_dissociate(idmapd_ev_port, PORT_SOURCE_FD, rt_sock);
13620dcc7149Snw141292 		(void) close(rt_sock);
13630dcc7149Snw141292 		(void) close(idmapd_ev_port);
13640dcc7149Snw141292 		return (-1);
13650dcc7149Snw141292 	}
13660dcc7149Snw141292 
13670dcc7149Snw141292 	return (0);
13680dcc7149Snw141292 }
13690dcc7149Snw141292 
1370349d5d8fSnw141292 /*
1371479ac375Sdm199847  * Reject attribute names with invalid characters.
1372479ac375Sdm199847  */
1373479ac375Sdm199847 static
1374479ac375Sdm199847 int
valid_ldap_attr(const char * attr)1375479ac375Sdm199847 valid_ldap_attr(const char *attr) {
1376479ac375Sdm199847 	for (; *attr; attr++) {
1377479ac375Sdm199847 		if (!isalnum(*attr) && *attr != '-' &&
1378479ac375Sdm199847 		    *attr != '_' && *attr != '.' && *attr != ';')
1379479ac375Sdm199847 			return (0);
1380479ac375Sdm199847 	}
1381479ac375Sdm199847 	return (1);
1382479ac375Sdm199847 }
1383479ac375Sdm199847 
1384349d5d8fSnw141292 static
1385148c5f43SAlan Wright void
idmapd_set_debug(idmap_cfg_handles_t * handles,enum idmapd_debug item,const char * name)1386148c5f43SAlan Wright idmapd_set_debug(
1387148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
1388148c5f43SAlan Wright     enum idmapd_debug item,
1389148c5f43SAlan Wright     const char *name)
1390148c5f43SAlan Wright {
1391148c5f43SAlan Wright 	int val;
1392148c5f43SAlan Wright 
1393148c5f43SAlan Wright 	if (item < 0 || item > IDMAPD_DEBUG_MAX)
1394148c5f43SAlan Wright 		return;
1395148c5f43SAlan Wright 
1396148c5f43SAlan Wright 	val = get_debug(handles, name);
1397148c5f43SAlan Wright 
1398148c5f43SAlan Wright 	if (val != _idmapdstate.debug[item])
1399148c5f43SAlan Wright 		idmapdlog(LOG_DEBUG, "%s/%s = %d", DEBUG_PG, name, val);
1400148c5f43SAlan Wright 
1401148c5f43SAlan Wright 	_idmapdstate.debug[item] = val;
1402148c5f43SAlan Wright }
1403148c5f43SAlan Wright 
1404148c5f43SAlan Wright static
1405148c5f43SAlan Wright void
check_smf_debug_mode(idmap_cfg_handles_t * handles)1406e3f2c991SKeyur Desai check_smf_debug_mode(idmap_cfg_handles_t *handles)
1407c8e26105Sjp151216 {
1408148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_ALL, "all");
1409148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_CONFIG, "config");
1410148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_MAPPING, "mapping");
1411148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_DISC, "discovery");
1412148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_DNS, "dns");
1413148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_LDAP, "ldap");
1414479ac375Sdm199847 
1415148c5f43SAlan Wright 	adutils_set_debug(AD_DEBUG_ALL, _idmapdstate.debug[IDMAPD_DEBUG_ALL]);
1416148c5f43SAlan Wright 	adutils_set_debug(AD_DEBUG_DISC, _idmapdstate.debug[IDMAPD_DEBUG_DISC]);
1417148c5f43SAlan Wright 	adutils_set_debug(AD_DEBUG_DNS, _idmapdstate.debug[IDMAPD_DEBUG_DNS]);
1418148c5f43SAlan Wright 	adutils_set_debug(AD_DEBUG_LDAP, _idmapdstate.debug[IDMAPD_DEBUG_LDAP]);
1419e3f2c991SKeyur Desai }
1420e3f2c991SKeyur Desai 
1421e3f2c991SKeyur Desai /*
1422e3f2c991SKeyur Desai  * This is the half of idmap_cfg_load() that loads property values from
1423e3f2c991SKeyur Desai  * SMF (using the config/ property group of the idmap FMRI).
1424e3f2c991SKeyur Desai  *
1425e3f2c991SKeyur Desai  * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
1426e3f2c991SKeyur Desai  *               -3 -> hard smf config failures
1427e3f2c991SKeyur Desai  * reading from SMF.
1428e3f2c991SKeyur Desai  */
1429e3f2c991SKeyur Desai static
1430e3f2c991SKeyur Desai int
idmap_cfg_load_smf(idmap_cfg_handles_t * handles,idmap_pg_config_t * pgcfg,int * const errors)1431e3f2c991SKeyur Desai idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
1432e3f2c991SKeyur Desai 	int * const errors)
1433e3f2c991SKeyur Desai {
1434e3f2c991SKeyur Desai 	int rc;
1435e3f2c991SKeyur Desai 	char *s;
1436e3f2c991SKeyur Desai 
1437e3f2c991SKeyur Desai 	*errors = 0;
1438e3f2c991SKeyur Desai 
1439e3f2c991SKeyur Desai 	if (scf_pg_update(handles->config_pg) < 0) {
1440e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
1441e3f2c991SKeyur Desai 		    scf_strerror(scf_error()));
1442e3f2c991SKeyur Desai 		return (-2);
1443e3f2c991SKeyur Desai 	}
1444e3f2c991SKeyur Desai 
1445148c5f43SAlan Wright 	if (scf_pg_update(handles->debug_pg) < 0) {
1446e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
1447e3f2c991SKeyur Desai 		    scf_strerror(scf_error()));
1448e3f2c991SKeyur Desai 		return (-2);
1449e3f2c991SKeyur Desai 	}
1450e3f2c991SKeyur Desai 
1451148c5f43SAlan Wright 	check_smf_debug_mode(handles);
1452148c5f43SAlan Wright 
1453148c5f43SAlan Wright 	rc = get_val_bool(handles, "unresolvable_sid_mapping",
1454148c5f43SAlan Wright 	    &pgcfg->eph_map_unres_sids, B_TRUE);
1455e3f2c991SKeyur Desai 	if (rc != 0)
1456e3f2c991SKeyur Desai 		(*errors)++;
1457e3f2c991SKeyur Desai 
1458*4f449947SGordon Ross 	rc = get_val_bool(handles, "use_ads",
1459*4f449947SGordon Ross 	    &pgcfg->use_ads, B_TRUE);
1460*4f449947SGordon Ross 	if (rc != 0)
1461*4f449947SGordon Ross 		(*errors)++;
1462*4f449947SGordon Ross 
1463148c5f43SAlan Wright 	rc = get_val_bool(handles, "use_lsa",
1464148c5f43SAlan Wright 	    &pgcfg->use_lsa, B_TRUE);
1465148c5f43SAlan Wright 	if (rc != 0)
1466148c5f43SAlan Wright 		(*errors)++;
1467148c5f43SAlan Wright 
1468148c5f43SAlan Wright 	rc = get_val_bool(handles, "disable_cross_forest_trusts",
1469148c5f43SAlan Wright 	    &pgcfg->disable_cross_forest_trusts, B_TRUE);
14704aa0a5e7Snw141292 	if (rc != 0)
1471e3f2c991SKeyur Desai 		(*errors)++;
1472e3f2c991SKeyur Desai 
1473e3f2c991SKeyur Desai 	rc = get_val_astring(handles, "directory_based_mapping", &s);
1474e3f2c991SKeyur Desai 	if (rc != 0)
1475e3f2c991SKeyur Desai 		(*errors)++;
1476e3f2c991SKeyur Desai 	else if (s == NULL || strcasecmp(s, "none") == 0)
1477e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1478e3f2c991SKeyur Desai 	else if (strcasecmp(s, "name") == 0)
1479e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NAME;
1480e3f2c991SKeyur Desai 	else if (strcasecmp(s, "idmu") == 0)
1481e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_IDMU;
1482e3f2c991SKeyur Desai 	else {
1483e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1484e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
1485e3f2c991SKeyur Desai 		"config/directory_based_mapping:  invalid value \"%s\" ignored",
1486e3f2c991SKeyur Desai 		    s);
1487e3f2c991SKeyur Desai 		(*errors)++;
1488e3f2c991SKeyur Desai 	}
1489e3f2c991SKeyur Desai 	free(s);
14904aa0a5e7Snw141292 
1491c8e26105Sjp151216 	rc = get_val_int(handles, "list_size_limit",
1492c8e26105Sjp151216 	    &pgcfg->list_size_limit, SCF_TYPE_COUNT);
14934aa0a5e7Snw141292 	if (rc != 0)
1494e3f2c991SKeyur Desai 		(*errors)++;
1495c8e26105Sjp151216 
149648cd229bSGordon Ross 	rc = get_val_int(handles, "id_cache_timeout",
149748cd229bSGordon Ross 	    &pgcfg->id_cache_timeout, SCF_TYPE_COUNT);
149848cd229bSGordon Ross 	if (rc != 0)
149948cd229bSGordon Ross 		(*errors)++;
150048cd229bSGordon Ross 	if (pgcfg->id_cache_timeout == 0)
150148cd229bSGordon Ross 		pgcfg->id_cache_timeout = ID_CACHE_TMO_DEFAULT;
150248cd229bSGordon Ross 
150348cd229bSGordon Ross 	rc = get_val_int(handles, "name_cache_timeout",
150448cd229bSGordon Ross 	    &pgcfg->name_cache_timeout, SCF_TYPE_COUNT);
150548cd229bSGordon Ross 	if (rc != 0)
150648cd229bSGordon Ross 		(*errors)++;
150748cd229bSGordon Ross 	if (pgcfg->name_cache_timeout == 0)
150848cd229bSGordon Ross 		pgcfg->name_cache_timeout = NAME_CACHE_TMO_DEFAULT;
150948cd229bSGordon Ross 
1510c8e26105Sjp151216 	rc = get_val_astring(handles, "domain_name",
1511c8e26105Sjp151216 	    &pgcfg->domain_name);
1512e3c2d6aaSnw141292 	if (rc != 0)
1513e3f2c991SKeyur Desai 		(*errors)++;
15144d61c878SJulian Pullen 	else {
1515148c5f43SAlan Wright 		if (pgcfg->domain_name != NULL &&
1516148c5f43SAlan Wright 		    pgcfg->domain_name[0] == '\0') {
1517148c5f43SAlan Wright 			free(pgcfg->domain_name);
1518148c5f43SAlan Wright 			pgcfg->domain_name = NULL;
1519148c5f43SAlan Wright 		}
1520349d5d8fSnw141292 		(void) ad_disc_set_DomainName(handles->ad_ctx,
1521349d5d8fSnw141292 		    pgcfg->domain_name);
15227a8a68f5SJulian Pullen 		pgcfg->domain_name_auto_disc = B_FALSE;
15234d61c878SJulian Pullen 	}
1524c8e26105Sjp151216 
1525c8e26105Sjp151216 	rc = get_val_astring(handles, "default_domain",
1526c8e26105Sjp151216 	    &pgcfg->default_domain);
1527c8e26105Sjp151216 	if (rc != 0) {
1528e3c2d6aaSnw141292 		/*
1529e3c2d6aaSnw141292 		 * SCF failures fetching config/default_domain we treat
1530e3c2d6aaSnw141292 		 * as fatal as they may leave ID mapping rules that
1531e3c2d6aaSnw141292 		 * match unqualified winnames flapping in the wind.
1532e3c2d6aaSnw141292 		 */
1533349d5d8fSnw141292 		return (-2);
1534c8e26105Sjp151216 	}
1535c8e26105Sjp151216 
1536e3f2c991SKeyur Desai 	if (pgcfg->default_domain == NULL && pgcfg->domain_name != NULL) {
1537c8e26105Sjp151216 		pgcfg->default_domain = strdup(pgcfg->domain_name);
1538c8e26105Sjp151216 	}
1539c8e26105Sjp151216 
1540c8e26105Sjp151216 	rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid);
1541e3c2d6aaSnw141292 	if (rc != 0)
1542e3f2c991SKeyur Desai 		(*errors)++;
1543c8e26105Sjp151216 	if (pgcfg->machine_sid == NULL) {
15448edda628Sbaban 		/* If machine_sid not configured, generate one */
1545349d5d8fSnw141292 		if (generate_machine_sid(&pgcfg->machine_sid) < 0)
1546349d5d8fSnw141292 			return (-2);
1547148c5f43SAlan Wright 		rc = set_val_astring(handles, handles->config_pg,
1548148c5f43SAlan Wright 		    "machine_sid", pgcfg->machine_sid);
1549e3c2d6aaSnw141292 		if (rc != 0)
1550e3f2c991SKeyur Desai 			(*errors)++;
15518edda628Sbaban 	}
1552c5c4113dSnw141292 
1553c8e26105Sjp151216 	rc = get_val_ds(handles, "domain_controller", 389,
1554c8e26105Sjp151216 	    &pgcfg->domain_controller);
1555e3c2d6aaSnw141292 	if (rc != 0)
1556e3f2c991SKeyur Desai 		(*errors)++;
15574d61c878SJulian Pullen 	else {
1558349d5d8fSnw141292 		(void) ad_disc_set_DomainController(handles->ad_ctx,
1559e3c2d6aaSnw141292 		    pgcfg->domain_controller);
15607a8a68f5SJulian Pullen 		pgcfg->domain_controller_auto_disc = B_FALSE;
15614d61c878SJulian Pullen 	}
1562c5c4113dSnw141292 
1563c8e26105Sjp151216 	rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name);
1564e3c2d6aaSnw141292 	if (rc != 0)
1565e3f2c991SKeyur Desai 		(*errors)++;
15664d61c878SJulian Pullen 	else {
1567349d5d8fSnw141292 		(void) ad_disc_set_ForestName(handles->ad_ctx,
1568349d5d8fSnw141292 		    pgcfg->forest_name);
15697a8a68f5SJulian Pullen 		pgcfg->forest_name_auto_disc = B_FALSE;
15704d61c878SJulian Pullen 	}
1571c8e26105Sjp151216 
1572c8e26105Sjp151216 	rc = get_val_astring(handles, "site_name", &pgcfg->site_name);
1573e3c2d6aaSnw141292 	if (rc != 0)
1574e3f2c991SKeyur Desai 		(*errors)++;
1575e3c2d6aaSnw141292 	else
1576349d5d8fSnw141292 		(void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name);
1577c8e26105Sjp151216 
1578c8e26105Sjp151216 	rc = get_val_ds(handles, "global_catalog", 3268,
1579c8e26105Sjp151216 	    &pgcfg->global_catalog);
1580e3c2d6aaSnw141292 	if (rc != 0)
1581e3f2c991SKeyur Desai 		(*errors)++;
15824d61c878SJulian Pullen 	else {
1583349d5d8fSnw141292 		(void) ad_disc_set_GlobalCatalog(handles->ad_ctx,
1584349d5d8fSnw141292 		    pgcfg->global_catalog);
15857a8a68f5SJulian Pullen 		pgcfg->global_catalog_auto_disc = B_FALSE;
15864d61c878SJulian Pullen 	}
1587c8e26105Sjp151216 
1588e3f2c991SKeyur Desai 	/* Unless we're doing directory-based name mapping, we're done. */
1589e3f2c991SKeyur Desai 	if (pgcfg->directory_based_mapping != DIRECTORY_MAPPING_NAME)
1590e3f2c991SKeyur Desai 		return (0);
1591349d5d8fSnw141292 
1592e8c27ec8Sbaban 	rc = get_val_astring(handles, "ad_unixuser_attr",
1593e8c27ec8Sbaban 	    &pgcfg->ad_unixuser_attr);
1594349d5d8fSnw141292 	if (rc != 0)
1595349d5d8fSnw141292 		return (-2);
1596479ac375Sdm199847 	if (pgcfg->ad_unixuser_attr != NULL &&
1597479ac375Sdm199847 	    !valid_ldap_attr(pgcfg->ad_unixuser_attr)) {
1598479ac375Sdm199847 		idmapdlog(LOG_ERR, "config/ad_unixuser_attr=%s is not a "
1599479ac375Sdm199847 		    "valid LDAP attribute name", pgcfg->ad_unixuser_attr);
1600479ac375Sdm199847 		return (-3);
1601479ac375Sdm199847 	}
1602e8c27ec8Sbaban 
1603e8c27ec8Sbaban 	rc = get_val_astring(handles, "ad_unixgroup_attr",
1604e8c27ec8Sbaban 	    &pgcfg->ad_unixgroup_attr);
1605349d5d8fSnw141292 	if (rc != 0)
1606349d5d8fSnw141292 		return (-2);
1607479ac375Sdm199847 	if (pgcfg->ad_unixgroup_attr != NULL &&
1608479ac375Sdm199847 	    !valid_ldap_attr(pgcfg->ad_unixgroup_attr)) {
1609479ac375Sdm199847 		idmapdlog(LOG_ERR, "config/ad_unixgroup_attr=%s is not a "
1610479ac375Sdm199847 		    "valid LDAP attribute name", pgcfg->ad_unixgroup_attr);
1611479ac375Sdm199847 		return (-3);
1612479ac375Sdm199847 	}
1613e8c27ec8Sbaban 
1614e8c27ec8Sbaban 	rc = get_val_astring(handles, "nldap_winname_attr",
1615e8c27ec8Sbaban 	    &pgcfg->nldap_winname_attr);
1616349d5d8fSnw141292 	if (rc != 0)
1617349d5d8fSnw141292 		return (-2);
1618479ac375Sdm199847 	if (pgcfg->nldap_winname_attr != NULL &&
1619479ac375Sdm199847 	    !valid_ldap_attr(pgcfg->nldap_winname_attr)) {
1620479ac375Sdm199847 		idmapdlog(LOG_ERR, "config/nldap_winname_attr=%s is not a "
1621479ac375Sdm199847 		    "valid LDAP attribute name", pgcfg->nldap_winname_attr);
1622349d5d8fSnw141292 		return (-3);
1623e8c27ec8Sbaban 	}
1624e8c27ec8Sbaban 	if (pgcfg->ad_unixuser_attr == NULL &&
1625479ac375Sdm199847 	    pgcfg->ad_unixgroup_attr == NULL &&
1626479ac375Sdm199847 	    pgcfg->nldap_winname_attr == NULL) {
1627e8c27ec8Sbaban 		idmapdlog(LOG_ERR,
1628e3f2c991SKeyur Desai 		    "If config/directory_based_mapping property is set to "
1629e3f2c991SKeyur Desai 		    "\"name\" then at least one of the following name mapping "
1630349d5d8fSnw141292 		    "attributes must be specified. (config/ad_unixuser_attr OR "
1631479ac375Sdm199847 		    "config/ad_unixgroup_attr OR config/nldap_winname_attr)");
1632349d5d8fSnw141292 		return (-3);
1633e8c27ec8Sbaban 	}
1634e8c27ec8Sbaban 
1635349d5d8fSnw141292 	return (rc);
1636c8e26105Sjp151216 
1637349d5d8fSnw141292 }
1638e3c2d6aaSnw141292 
1639349d5d8fSnw141292 static
1640349d5d8fSnw141292 void
log_if_unable(const void * val,const char * what)1641148c5f43SAlan Wright log_if_unable(const void *val, const char *what)
1642349d5d8fSnw141292 {
1643148c5f43SAlan Wright 	if (val == NULL) {
1644148c5f43SAlan Wright 		idmapdlog(LOG_DEBUG, "unable to discover %s", what);
1645148c5f43SAlan Wright 	}
1646148c5f43SAlan Wright }
1647148c5f43SAlan Wright 
1648148c5f43SAlan Wright static
1649148c5f43SAlan Wright void
discover_trusted_domains(idmap_pg_config_t * pgcfg,ad_disc_t ad_ctx)1650148c5f43SAlan Wright discover_trusted_domains(idmap_pg_config_t *pgcfg, ad_disc_t ad_ctx)
1651148c5f43SAlan Wright {
16524d61c878SJulian Pullen 	ad_disc_t trusted_ctx;
16534d61c878SJulian Pullen 	int i, j, k, l;
16544d61c878SJulian Pullen 	char *forestname;
16554d61c878SJulian Pullen 	int num_trusteddomains;
16567a8a68f5SJulian Pullen 	boolean_t new_forest;
16574d61c878SJulian Pullen 	char *trusteddomain;
16584d61c878SJulian Pullen 	idmap_ad_disc_ds_t *globalcatalog;
16594d61c878SJulian Pullen 	idmap_trustedforest_t *trustedforests;
16604d61c878SJulian Pullen 	ad_disc_domainsinforest_t *domainsinforest;
1661349d5d8fSnw141292 
16624d61c878SJulian Pullen 	pgcfg->trusted_domains =
16634d61c878SJulian Pullen 	    ad_disc_get_TrustedDomains(ad_ctx, NULL);
16644d61c878SJulian Pullen 
16654d61c878SJulian Pullen 	if (pgcfg->forest_name != NULL && pgcfg->trusted_domains != NULL &&
16664d61c878SJulian Pullen 	    pgcfg->trusted_domains[0].domain[0] != '\0') {
16674d61c878SJulian Pullen 		/*
16684d61c878SJulian Pullen 		 * We have trusted domains.  We need to go through every
16694d61c878SJulian Pullen 		 * one and find its forest. If it is a new forest we then need
16704d61c878SJulian Pullen 		 * to find its Global Catalog and the domains in the forest
16714d61c878SJulian Pullen 		 */
16724d61c878SJulian Pullen 		for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++)
16734d61c878SJulian Pullen 			continue;
16744d61c878SJulian Pullen 		num_trusteddomains = i;
16754d61c878SJulian Pullen 
16764d61c878SJulian Pullen 		trustedforests = calloc(num_trusteddomains,
16774d61c878SJulian Pullen 		    sizeof (idmap_trustedforest_t));
16784d61c878SJulian Pullen 		j = 0;
16794d61c878SJulian Pullen 		for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) {
16804d61c878SJulian Pullen 			trusteddomain = pgcfg->trusted_domains[i].domain;
16814d61c878SJulian Pullen 			trusted_ctx = ad_disc_init();
1682148c5f43SAlan Wright 			(void) ad_disc_set_DomainName(trusted_ctx,
16834d61c878SJulian Pullen 			    trusteddomain);
16844d61c878SJulian Pullen 			forestname =
16854d61c878SJulian Pullen 			    ad_disc_get_ForestName(trusted_ctx, NULL);
16864d61c878SJulian Pullen 			if (forestname == NULL) {
1687148c5f43SAlan Wright 				if (DBG(CONFIG, 1)) {
1688148c5f43SAlan Wright 					idmapdlog(LOG_DEBUG,
1689148c5f43SAlan Wright 					    "unable to discover Forest Name"
1690148c5f43SAlan Wright 					    " for the trusted domain %s",
16914d61c878SJulian Pullen 					    trusteddomain);
1692148c5f43SAlan Wright 				}
16934d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
16944d61c878SJulian Pullen 				continue;
16954d61c878SJulian Pullen 			}
16964d61c878SJulian Pullen 
16974d61c878SJulian Pullen 			if (strcasecmp(forestname, pgcfg->forest_name) == 0) {
16984d61c878SJulian Pullen 				/*
16994d61c878SJulian Pullen 				 * Ignore the domain as it is part of
17004d61c878SJulian Pullen 				 * the primary forest
17014d61c878SJulian Pullen 				 */
17024d61c878SJulian Pullen 				free(forestname);
17034d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
17044d61c878SJulian Pullen 				continue;
17054d61c878SJulian Pullen 			}
17064d61c878SJulian Pullen 
17074d61c878SJulian Pullen 			/* Is this a new forest? */
17087a8a68f5SJulian Pullen 			new_forest = B_TRUE;
17094d61c878SJulian Pullen 			for (k = 0; k < j; k++) {
17104d61c878SJulian Pullen 				if (strcasecmp(forestname,
17114d61c878SJulian Pullen 				    trustedforests[k].forest_name) == 0) {
17127a8a68f5SJulian Pullen 					new_forest = B_FALSE;
17134d61c878SJulian Pullen 					domainsinforest =
17144d61c878SJulian Pullen 					    trustedforests[k].domains_in_forest;
17154d61c878SJulian Pullen 					break;
17164d61c878SJulian Pullen 				}
17174d61c878SJulian Pullen 			}
17184d61c878SJulian Pullen 			if (!new_forest) {
17194d61c878SJulian Pullen 				/* Mark the domain as trusted */
17204d61c878SJulian Pullen 				for (l = 0;
17214d61c878SJulian Pullen 				    domainsinforest[l].domain[0] != '\0'; l++) {
17221fcced4cSJordan Brown 					if (domain_eq(trusteddomain,
17231fcced4cSJordan Brown 					    domainsinforest[l].domain)) {
17244d61c878SJulian Pullen 						domainsinforest[l].trusted =
17254d61c878SJulian Pullen 						    TRUE;
17264d61c878SJulian Pullen 						break;
17274d61c878SJulian Pullen 					}
17284d61c878SJulian Pullen 				}
17294d61c878SJulian Pullen 				free(forestname);
17304d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
17314d61c878SJulian Pullen 				continue;
17324d61c878SJulian Pullen 			}
17334d61c878SJulian Pullen 
17344d61c878SJulian Pullen 			/*
17354d61c878SJulian Pullen 			 * Get the Global Catalog and the domains in
17364d61c878SJulian Pullen 			 * this new forest.
17374d61c878SJulian Pullen 			 */
17384d61c878SJulian Pullen 			globalcatalog =
17394d61c878SJulian Pullen 			    ad_disc_get_GlobalCatalog(trusted_ctx,
17404d61c878SJulian Pullen 			    AD_DISC_PREFER_SITE, NULL);
17414d61c878SJulian Pullen 			if (globalcatalog == NULL) {
1742148c5f43SAlan Wright 				if (DBG(CONFIG, 1)) {
17434d61c878SJulian Pullen 					idmapdlog(LOG_DEBUG,
1744148c5f43SAlan Wright 					    "unable to discover Global Catalog"
1745148c5f43SAlan Wright 					    " for the trusted domain %s",
17464d61c878SJulian Pullen 					    trusteddomain);
1747148c5f43SAlan Wright 				}
17484d61c878SJulian Pullen 				free(forestname);
17494d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
17504d61c878SJulian Pullen 				continue;
17514d61c878SJulian Pullen 			}
17524d61c878SJulian Pullen 			domainsinforest =
17534d61c878SJulian Pullen 			    ad_disc_get_DomainsInForest(trusted_ctx,
17544d61c878SJulian Pullen 			    NULL);
17554d61c878SJulian Pullen 			if (domainsinforest == NULL) {
1756148c5f43SAlan Wright 				if (DBG(CONFIG, 1)) {
17574d61c878SJulian Pullen 					idmapdlog(LOG_DEBUG,
1758148c5f43SAlan Wright 					    "unable to discover Domains in the"
1759148c5f43SAlan Wright 					    " Forest for the trusted domain %s",
17604d61c878SJulian Pullen 					    trusteddomain);
1761148c5f43SAlan Wright 				}
17624d61c878SJulian Pullen 				free(globalcatalog);
17634d61c878SJulian Pullen 				free(forestname);
17644d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
17654d61c878SJulian Pullen 				continue;
17664d61c878SJulian Pullen 			}
17674d61c878SJulian Pullen 
17684d61c878SJulian Pullen 			trustedforests[j].forest_name = forestname;
17694d61c878SJulian Pullen 			trustedforests[j].global_catalog = globalcatalog;
17704d61c878SJulian Pullen 			trustedforests[j].domains_in_forest = domainsinforest;
17714d61c878SJulian Pullen 			j++;
17724d61c878SJulian Pullen 			/* Mark the domain as trusted */
17734d61c878SJulian Pullen 			for (l = 0; domainsinforest[l].domain[0] != '\0';
17744d61c878SJulian Pullen 			    l++) {
17751fcced4cSJordan Brown 				if (domain_eq(trusteddomain,
17761fcced4cSJordan Brown 				    domainsinforest[l].domain)) {
17774d61c878SJulian Pullen 					domainsinforest[l].trusted = TRUE;
17784d61c878SJulian Pullen 					break;
17794d61c878SJulian Pullen 				}
17804d61c878SJulian Pullen 			}
17814d61c878SJulian Pullen 			ad_disc_fini(trusted_ctx);
17824d61c878SJulian Pullen 		}
17834d61c878SJulian Pullen 		if (j > 0) {
17844d61c878SJulian Pullen 			pgcfg->num_trusted_forests = j;
17854d61c878SJulian Pullen 			pgcfg->trusted_forests = trustedforests;
17861fcced4cSJordan Brown 		} else {
17871fcced4cSJordan Brown 			free(trustedforests);
17884d61c878SJulian Pullen 		}
17894d61c878SJulian Pullen 	}
1790148c5f43SAlan Wright }
1791349d5d8fSnw141292 
1792148c5f43SAlan Wright /*
1793148c5f43SAlan Wright  * This is the half of idmap_cfg_load() that auto-discovers values of
1794148c5f43SAlan Wright  * discoverable properties that weren't already set via SMF properties.
1795148c5f43SAlan Wright  *
1796148c5f43SAlan Wright  * idmap_cfg_discover() is called *after* idmap_cfg_load_smf(), so it
1797148c5f43SAlan Wright  * needs to be careful not to overwrite any properties set in SMF.
1798148c5f43SAlan Wright  */
1799148c5f43SAlan Wright static
1800148c5f43SAlan Wright void
idmap_cfg_discover(idmap_cfg_handles_t * handles,idmap_pg_config_t * pgcfg)1801148c5f43SAlan Wright idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
1802148c5f43SAlan Wright {
1803148c5f43SAlan Wright 	ad_disc_t ad_ctx = handles->ad_ctx;
1804148c5f43SAlan Wright 
1805*4f449947SGordon Ross 	if (pgcfg->use_ads == B_FALSE) {
1806*4f449947SGordon Ross 		if (DBG(CONFIG, 1))
1807*4f449947SGordon Ross 			idmapdlog(LOG_DEBUG, "ADS disabled.");
1808*4f449947SGordon Ross 		return;
1809*4f449947SGordon Ross 	}
1810*4f449947SGordon Ross 
1811148c5f43SAlan Wright 	if (DBG(CONFIG, 1))
1812148c5f43SAlan Wright 		idmapdlog(LOG_DEBUG, "Running discovery.");
1813148c5f43SAlan Wright 
1814148c5f43SAlan Wright 	ad_disc_refresh(ad_ctx);
1815148c5f43SAlan Wright 
1816148c5f43SAlan Wright 	if (pgcfg->domain_name == NULL) {
1817148c5f43SAlan Wright 		idmapdlog(LOG_DEBUG, "No domain name specified.");
1818148c5f43SAlan Wright 	} else {
1819349d5d8fSnw141292 		if (pgcfg->domain_controller == NULL)
1820148c5f43SAlan Wright 			pgcfg->domain_controller =
1821148c5f43SAlan Wright 			    ad_disc_get_DomainController(ad_ctx,
1822148c5f43SAlan Wright 			    AD_DISC_PREFER_SITE,
1823148c5f43SAlan Wright 			    &pgcfg->domain_controller_auto_disc);
1824148c5f43SAlan Wright 
1825349d5d8fSnw141292 		if (pgcfg->forest_name == NULL)
1826148c5f43SAlan Wright 			pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx,
1827148c5f43SAlan Wright 			    &pgcfg->forest_name_auto_disc);
1828148c5f43SAlan Wright 
1829349d5d8fSnw141292 		if (pgcfg->site_name == NULL)
1830148c5f43SAlan Wright 			pgcfg->site_name = ad_disc_get_SiteName(ad_ctx,
1831148c5f43SAlan Wright 			    &pgcfg->site_name_auto_disc);
1832148c5f43SAlan Wright 
1833349d5d8fSnw141292 		if (pgcfg->global_catalog == NULL)
1834148c5f43SAlan Wright 			pgcfg->global_catalog =
1835148c5f43SAlan Wright 			    ad_disc_get_GlobalCatalog(ad_ctx,
1836148c5f43SAlan Wright 			    AD_DISC_PREFER_SITE,
1837148c5f43SAlan Wright 			    &pgcfg->global_catalog_auto_disc);
1838148c5f43SAlan Wright 
1839148c5f43SAlan Wright 		pgcfg->domains_in_forest =
1840148c5f43SAlan Wright 		    ad_disc_get_DomainsInForest(ad_ctx, NULL);
1841148c5f43SAlan Wright 
1842148c5f43SAlan Wright 		if (!pgcfg->disable_cross_forest_trusts)
1843148c5f43SAlan Wright 			discover_trusted_domains(pgcfg, ad_ctx);
1844148c5f43SAlan Wright 
1845148c5f43SAlan Wright 		if (DBG(CONFIG, 1)) {
1846148c5f43SAlan Wright 			log_if_unable(pgcfg->domain_name, "Domain Name");
1847148c5f43SAlan Wright 			log_if_unable(pgcfg->domain_controller,
1848148c5f43SAlan Wright 			    "Domain Controller");
1849148c5f43SAlan Wright 			log_if_unable(pgcfg->forest_name, "Forest Name");
1850148c5f43SAlan Wright 			log_if_unable(pgcfg->site_name, "Site Name");
1851148c5f43SAlan Wright 			log_if_unable(pgcfg->global_catalog, "Global Catalog");
1852148c5f43SAlan Wright 			log_if_unable(pgcfg->domains_in_forest,
1853148c5f43SAlan Wright 			    "Domains in the Forest");
1854148c5f43SAlan Wright 			if (!pgcfg->disable_cross_forest_trusts) {
1855148c5f43SAlan Wright 				log_if_unable(pgcfg->trusted_domains,
1856148c5f43SAlan Wright 				    "Trusted Domains");
1857148c5f43SAlan Wright 			}
1858148c5f43SAlan Wright 		}
1859148c5f43SAlan Wright 	}
1860c5866007SKeyur Desai 
1861c5866007SKeyur Desai 	ad_disc_done(ad_ctx);
1862148c5f43SAlan Wright 
1863148c5f43SAlan Wright 	if (DBG(CONFIG, 1))
1864c5866007SKeyur Desai 		idmapdlog(LOG_DEBUG, "Discovery done.");
1865c8e26105Sjp151216 }
1866e3c2d6aaSnw141292 
18674d61c878SJulian Pullen 
1868349d5d8fSnw141292 /*
1869349d5d8fSnw141292  * idmap_cfg_load() is called at startup, and periodically via the
1870349d5d8fSnw141292  * update thread when the auto-discovery TTLs expire, as well as part of
1871349d5d8fSnw141292  * the refresh method, to update the current configuration.  It always
1872349d5d8fSnw141292  * reads from SMF, but you still have to refresh the service after
1873349d5d8fSnw141292  * changing the config pg in order for the changes to take effect.
1874349d5d8fSnw141292  *
1875148c5f43SAlan Wright  * There is one flag:
1876349d5d8fSnw141292  *
1877349d5d8fSnw141292  *  - CFG_DISCOVER
1878349d5d8fSnw141292  *
1879349d5d8fSnw141292  * If CFG_DISCOVER is set then idmap_cfg_load() calls
1880349d5d8fSnw141292  * idmap_cfg_discover() to discover, via DNS and LDAP lookups, property
1881349d5d8fSnw141292  * values that weren't set in SMF.
1882349d5d8fSnw141292  *
1883148c5f43SAlan Wright  * idmap_cfg_load() will log (to LOG_NOTICE) whether the configuration
1884148c5f43SAlan Wright  * changed.
1885349d5d8fSnw141292  *
1886349d5d8fSnw141292  * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
1887349d5d8fSnw141292  * reading from SMF.
1888349d5d8fSnw141292  */
1889349d5d8fSnw141292 int
idmap_cfg_load(idmap_cfg_t * cfg,int flags)1890349d5d8fSnw141292 idmap_cfg_load(idmap_cfg_t *cfg, int flags)
1891349d5d8fSnw141292 {
1892349d5d8fSnw141292 	int rc = 0;
1893e3f2c991SKeyur Desai 	int errors;
1894349d5d8fSnw141292 	int changed = 0;
18954d61c878SJulian Pullen 	int ad_reload_required = 0;
1896349d5d8fSnw141292 	idmap_pg_config_t new_pgcfg, *live_pgcfg;
1897349d5d8fSnw141292 
1898148c5f43SAlan Wright 	if (DBG(CONFIG, 1))
1899148c5f43SAlan Wright 		idmapdlog(LOG_DEBUG, "Loading configuration.");
1900148c5f43SAlan Wright 
1901349d5d8fSnw141292 	live_pgcfg = &cfg->pgcfg;
1902349d5d8fSnw141292 	(void) memset(&new_pgcfg, 0, sizeof (new_pgcfg));
1903349d5d8fSnw141292 
1904148c5f43SAlan Wright 	(void) pthread_mutex_lock(&cfg->handles.mutex);
1905349d5d8fSnw141292 
1906349d5d8fSnw141292 	if ((rc = idmap_cfg_load_smf(&cfg->handles, &new_pgcfg, &errors)) < -1)
1907349d5d8fSnw141292 		goto err;
1908349d5d8fSnw141292 
1909349d5d8fSnw141292 	if (flags & CFG_DISCOVER)
1910349d5d8fSnw141292 		idmap_cfg_discover(&cfg->handles, &new_pgcfg);
1911349d5d8fSnw141292 
1912349d5d8fSnw141292 	WRLOCK_CONFIG();
1913349d5d8fSnw141292 	/* Non-discoverable props updated here */
191448cd229bSGordon Ross 
191548cd229bSGordon Ross 	changed += update_uint64(&live_pgcfg->list_size_limit,
191648cd229bSGordon Ross 	    &new_pgcfg.list_size_limit, "list_size_limit");
191748cd229bSGordon Ross 
191848cd229bSGordon Ross 	changed += update_uint64(&live_pgcfg->id_cache_timeout,
191948cd229bSGordon Ross 	    &new_pgcfg.id_cache_timeout, "id_cache_timeout");
192048cd229bSGordon Ross 
192148cd229bSGordon Ross 	changed += update_uint64(&live_pgcfg->name_cache_timeout,
192248cd229bSGordon Ross 	    &new_pgcfg.name_cache_timeout, "name_cache_timeout");
192348cd229bSGordon Ross 
19244aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->machine_sid,
1925349d5d8fSnw141292 	    &new_pgcfg.machine_sid, "machine_sid");
1926349d5d8fSnw141292 
19274aa0a5e7Snw141292 	changed += update_bool(&live_pgcfg->eph_map_unres_sids,
19284aa0a5e7Snw141292 	    &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping");
19294aa0a5e7Snw141292 
1930*4f449947SGordon Ross 	changed += update_bool(&live_pgcfg->use_ads,
1931*4f449947SGordon Ross 	    &new_pgcfg.use_ads, "use_ads");
1932*4f449947SGordon Ross 
1933148c5f43SAlan Wright 	changed += update_bool(&live_pgcfg->use_lsa,
1934148c5f43SAlan Wright 	    &new_pgcfg.use_lsa, "use_lsa");
1935148c5f43SAlan Wright 
1936148c5f43SAlan Wright 	changed += update_bool(&live_pgcfg->disable_cross_forest_trusts,
1937148c5f43SAlan Wright 	    &new_pgcfg.disable_cross_forest_trusts,
1938148c5f43SAlan Wright 	    "disable_cross_forest_trusts");
1939148c5f43SAlan Wright 
1940e3f2c991SKeyur Desai 	changed += update_enum(&live_pgcfg->directory_based_mapping,
1941e3f2c991SKeyur Desai 	    &new_pgcfg.directory_based_mapping, "directory_based_mapping",
1942e3f2c991SKeyur Desai 	    directory_mapping_map);
1943349d5d8fSnw141292 
19444aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->ad_unixuser_attr,
1945349d5d8fSnw141292 	    &new_pgcfg.ad_unixuser_attr, "ad_unixuser_attr");
1946349d5d8fSnw141292 
19474aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->ad_unixgroup_attr,
1948349d5d8fSnw141292 	    &new_pgcfg.ad_unixgroup_attr, "ad_unixgroup_attr");
1949349d5d8fSnw141292 
19504aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->nldap_winname_attr,
1951349d5d8fSnw141292 	    &new_pgcfg.nldap_winname_attr, "nldap_winname_attr");
1952349d5d8fSnw141292 
1953349d5d8fSnw141292 	/* Props that can be discovered and set in SMF updated here */
19544aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->default_domain,
1955349d5d8fSnw141292 	    &new_pgcfg.default_domain, "default_domain");
1956349d5d8fSnw141292 
19574aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->domain_name,
1958349d5d8fSnw141292 	    &new_pgcfg.domain_name, "domain_name");
19594d61c878SJulian Pullen 	live_pgcfg->domain_name_auto_disc = new_pgcfg.domain_name_auto_disc;
1960349d5d8fSnw141292 
1961349d5d8fSnw141292 	changed += update_dirs(&live_pgcfg->domain_controller,
1962349d5d8fSnw141292 	    &new_pgcfg.domain_controller, "domain_controller");
19634d61c878SJulian Pullen 	live_pgcfg->domain_controller_auto_disc =
19644d61c878SJulian Pullen 	    new_pgcfg.domain_controller_auto_disc;
1965349d5d8fSnw141292 
19664aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->forest_name,
1967349d5d8fSnw141292 	    &new_pgcfg.forest_name, "forest_name");
19684d61c878SJulian Pullen 	live_pgcfg->forest_name_auto_disc = new_pgcfg.forest_name_auto_disc;
1969349d5d8fSnw141292 
19704aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->site_name,
1971349d5d8fSnw141292 	    &new_pgcfg.site_name, "site_name");
19724d61c878SJulian Pullen 	live_pgcfg->site_name_auto_disc = new_pgcfg.site_name_auto_disc;
1973349d5d8fSnw141292 
1974349d5d8fSnw141292 	if (update_dirs(&live_pgcfg->global_catalog,
1975349d5d8fSnw141292 	    &new_pgcfg.global_catalog, "global_catalog")) {
1976349d5d8fSnw141292 		changed++;
1977349d5d8fSnw141292 		if (live_pgcfg->global_catalog != NULL &&
1978349d5d8fSnw141292 		    live_pgcfg->global_catalog[0].host[0] != '\0')
19794d61c878SJulian Pullen 			ad_reload_required = TRUE;
1980349d5d8fSnw141292 	}
19814d61c878SJulian Pullen 	live_pgcfg->global_catalog_auto_disc =
19824d61c878SJulian Pullen 	    new_pgcfg.global_catalog_auto_disc;
19834d61c878SJulian Pullen 
19844d61c878SJulian Pullen 	if (update_domains_in_forest(&live_pgcfg->domains_in_forest,
19854d61c878SJulian Pullen 	    &new_pgcfg.domains_in_forest, "domains_in_forest")) {
19864d61c878SJulian Pullen 		changed++;
19874d61c878SJulian Pullen 		ad_reload_required = TRUE;
19884d61c878SJulian Pullen 	}
19894d61c878SJulian Pullen 
19904d61c878SJulian Pullen 	if (update_trusted_domains(&live_pgcfg->trusted_domains,
19914d61c878SJulian Pullen 	    &new_pgcfg.trusted_domains, "trusted_domains")) {
19924d61c878SJulian Pullen 		changed++;
19934d61c878SJulian Pullen 		if (live_pgcfg->trusted_domains != NULL &&
19944d61c878SJulian Pullen 		    live_pgcfg->trusted_domains[0].domain[0] != '\0')
19954d61c878SJulian Pullen 			ad_reload_required = TRUE;
19964d61c878SJulian Pullen 	}
19974d61c878SJulian Pullen 
19984d61c878SJulian Pullen 	if (update_trusted_forest(&live_pgcfg->trusted_forests,
19994d61c878SJulian Pullen 	    &live_pgcfg->num_trusted_forests, &new_pgcfg.trusted_forests,
20004d61c878SJulian Pullen 	    &new_pgcfg.num_trusted_forests, "trusted_forest")) {
20014d61c878SJulian Pullen 		changed++;
20024d61c878SJulian Pullen 		if (live_pgcfg->trusted_forests != NULL)
20034d61c878SJulian Pullen 			ad_reload_required = TRUE;
20044d61c878SJulian Pullen 	}
20054d61c878SJulian Pullen 
20064d61c878SJulian Pullen 	if (ad_reload_required)
20074d61c878SJulian Pullen 		reload_ad();
2008349d5d8fSnw141292 
2009349d5d8fSnw141292 	idmap_cfg_unload(&new_pgcfg);
2010349d5d8fSnw141292 
2011148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
2012148c5f43SAlan Wright 		if (changed)
2013148c5f43SAlan Wright 			idmapdlog(LOG_NOTICE, "Configuration changed");
2014148c5f43SAlan Wright 		else
2015148c5f43SAlan Wright 			idmapdlog(LOG_NOTICE, "Configuration unchanged");
2016349d5d8fSnw141292 	}
2017349d5d8fSnw141292 
2018349d5d8fSnw141292 	UNLOCK_CONFIG();
2019349d5d8fSnw141292 
2020349d5d8fSnw141292 err:
2021148c5f43SAlan Wright 	(void) pthread_mutex_unlock(&cfg->handles.mutex);
2022c5c4113dSnw141292 
2023e8c27ec8Sbaban 	if (rc < -1)
2024c5c4113dSnw141292 		return (rc);
2025e3c2d6aaSnw141292 
2026e3c2d6aaSnw141292 	return ((errors == 0) ? 0 : -1);
2027c5c4113dSnw141292 }
2028c5c4113dSnw141292 
2029651c0131Sbaban /*
2030651c0131Sbaban  * Initialize 'cfg'.
2031651c0131Sbaban  */
2032c5c4113dSnw141292 idmap_cfg_t *
idmap_cfg_init()20334edd44c5Sjp151216 idmap_cfg_init()
20344edd44c5Sjp151216 {
2035c8e26105Sjp151216 	idmap_cfg_handles_t *handles;
2036c5c4113dSnw141292 
2037c5c4113dSnw141292 	/* First the smf repository handles: */
2038c5c4113dSnw141292 	idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t));
2039c5c4113dSnw141292 	if (!cfg) {
204071590c90Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
2041c5c4113dSnw141292 		return (NULL);
2042c5c4113dSnw141292 	}
2043c8e26105Sjp151216 	handles = &cfg->handles;
2044c5c4113dSnw141292 
2045c8e26105Sjp151216 	(void) pthread_mutex_init(&handles->mutex, NULL);
2046c8e26105Sjp151216 
2047c8e26105Sjp151216 	if (!(handles->main = scf_handle_create(SCF_VERSION))) {
204871590c90Snw141292 		idmapdlog(LOG_ERR, "scf_handle_create() failed: %s",
204971590c90Snw141292 		    scf_strerror(scf_error()));
2050c5c4113dSnw141292 		goto error;
2051c5c4113dSnw141292 	}
2052c5c4113dSnw141292 
2053c8e26105Sjp151216 	if (scf_handle_bind(handles->main) < 0) {
205471590c90Snw141292 		idmapdlog(LOG_ERR, "scf_handle_bind() failed: %s",
205571590c90Snw141292 		    scf_strerror(scf_error()));
2056c5c4113dSnw141292 		goto error;
2057c5c4113dSnw141292 	}
2058c5c4113dSnw141292 
2059c8e26105Sjp151216 	if (!(handles->service = scf_service_create(handles->main)) ||
2060c8e26105Sjp151216 	    !(handles->instance = scf_instance_create(handles->main)) ||
2061c8e26105Sjp151216 	    !(handles->config_pg = scf_pg_create(handles->main)) ||
2062148c5f43SAlan Wright 	    !(handles->debug_pg = scf_pg_create(handles->main))) {
206371590c90Snw141292 		idmapdlog(LOG_ERR, "scf handle creation failed: %s",
206471590c90Snw141292 		    scf_strerror(scf_error()));
2065c5c4113dSnw141292 		goto error;
2066c5c4113dSnw141292 	}
2067c5c4113dSnw141292 
2068c8e26105Sjp151216 	if (scf_handle_decode_fmri(handles->main,
2069c5c4113dSnw141292 	    FMRI_BASE "/:properties/" CONFIG_PG,
2070c5c4113dSnw141292 	    NULL,				/* scope */
2071c8e26105Sjp151216 	    handles->service,		/* service */
2072c8e26105Sjp151216 	    handles->instance,		/* instance */
2073c8e26105Sjp151216 	    handles->config_pg,		/* pg */
2074c5c4113dSnw141292 	    NULL,				/* prop */
2075c8e26105Sjp151216 	    SCF_DECODE_FMRI_EXACT) < 0) {
207671590c90Snw141292 		idmapdlog(LOG_ERR, "scf_handle_decode_fmri() failed: %s",
207771590c90Snw141292 		    scf_strerror(scf_error()));
2078c5c4113dSnw141292 		goto error;
2079c5c4113dSnw141292 	}
2080c5c4113dSnw141292 
2081c8e26105Sjp151216 	if (scf_service_get_pg(handles->service,
2082148c5f43SAlan Wright 	    DEBUG_PG, handles->debug_pg) < 0) {
2083148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "Property group \"%s\": %s",
2084148c5f43SAlan Wright 		    DEBUG_PG, scf_strerror(scf_error()));
2085c5c4113dSnw141292 		goto error;
2086c5c4113dSnw141292 	}
2087c5c4113dSnw141292 
2088148c5f43SAlan Wright 	check_smf_debug_mode(handles);
2089e3f2c991SKeyur Desai 
2090c8e26105Sjp151216 	/* Initialize AD Auto Discovery context */
2091c8e26105Sjp151216 	handles->ad_ctx = ad_disc_init();
2092c8e26105Sjp151216 	if (handles->ad_ctx == NULL)
2093c8e26105Sjp151216 		goto error;
2094c8e26105Sjp151216 
2095c5c4113dSnw141292 	return (cfg);
2096c5c4113dSnw141292 
2097c5c4113dSnw141292 error:
2098c5c4113dSnw141292 	(void) idmap_cfg_fini(cfg);
2099c5c4113dSnw141292 	return (NULL);
2100c5c4113dSnw141292 }
2101c5c4113dSnw141292 
2102c8e26105Sjp151216 void
idmap_cfg_unload(idmap_pg_config_t * pgcfg)21034edd44c5Sjp151216 idmap_cfg_unload(idmap_pg_config_t *pgcfg)
21044edd44c5Sjp151216 {
2105c8e26105Sjp151216 
2106c8e26105Sjp151216 	if (pgcfg->default_domain) {
2107c8e26105Sjp151216 		free(pgcfg->default_domain);
2108c8e26105Sjp151216 		pgcfg->default_domain = NULL;
2109c8e26105Sjp151216 	}
2110c8e26105Sjp151216 	if (pgcfg->domain_name) {
2111c8e26105Sjp151216 		free(pgcfg->domain_name);
2112c8e26105Sjp151216 		pgcfg->domain_name = NULL;
2113c8e26105Sjp151216 	}
2114c8e26105Sjp151216 	if (pgcfg->machine_sid) {
2115c8e26105Sjp151216 		free(pgcfg->machine_sid);
2116c8e26105Sjp151216 		pgcfg->machine_sid = NULL;
2117c8e26105Sjp151216 	}
2118c8e26105Sjp151216 	if (pgcfg->domain_controller) {
2119c5c4113dSnw141292 		free(pgcfg->domain_controller);
2120c8e26105Sjp151216 		pgcfg->domain_controller = NULL;
2121c8e26105Sjp151216 	}
2122c8e26105Sjp151216 	if (pgcfg->forest_name) {
2123c8e26105Sjp151216 		free(pgcfg->forest_name);
2124c8e26105Sjp151216 		pgcfg->forest_name = NULL;
2125c8e26105Sjp151216 	}
2126c8e26105Sjp151216 	if (pgcfg->site_name) {
2127c8e26105Sjp151216 		free(pgcfg->site_name);
2128c8e26105Sjp151216 		pgcfg->site_name = NULL;
2129c8e26105Sjp151216 	}
2130c8e26105Sjp151216 	if (pgcfg->global_catalog) {
2131c8e26105Sjp151216 		free(pgcfg->global_catalog);
2132c8e26105Sjp151216 		pgcfg->global_catalog = NULL;
2133c8e26105Sjp151216 	}
21344d61c878SJulian Pullen 	if (pgcfg->trusted_domains) {
21354d61c878SJulian Pullen 		free(pgcfg->trusted_domains);
21364d61c878SJulian Pullen 		pgcfg->trusted_domains = NULL;
21374d61c878SJulian Pullen 	}
21384d61c878SJulian Pullen 	if (pgcfg->trusted_forests)
21394d61c878SJulian Pullen 		free_trusted_forests(&pgcfg->trusted_forests,
21404d61c878SJulian Pullen 		    &pgcfg->num_trusted_forests);
21414d61c878SJulian Pullen 
2142e8c27ec8Sbaban 	if (pgcfg->ad_unixuser_attr) {
2143e8c27ec8Sbaban 		free(pgcfg->ad_unixuser_attr);
2144e8c27ec8Sbaban 		pgcfg->ad_unixuser_attr = NULL;
2145e8c27ec8Sbaban 	}
2146e8c27ec8Sbaban 	if (pgcfg->ad_unixgroup_attr) {
2147e8c27ec8Sbaban 		free(pgcfg->ad_unixgroup_attr);
2148e8c27ec8Sbaban 		pgcfg->ad_unixgroup_attr = NULL;
2149e8c27ec8Sbaban 	}
2150e8c27ec8Sbaban 	if (pgcfg->nldap_winname_attr) {
2151e8c27ec8Sbaban 		free(pgcfg->nldap_winname_attr);
2152e8c27ec8Sbaban 		pgcfg->nldap_winname_attr = NULL;
2153e8c27ec8Sbaban 	}
2154c5c4113dSnw141292 }
2155c5c4113dSnw141292 
2156c5c4113dSnw141292 int
idmap_cfg_fini(idmap_cfg_t * cfg)2157c5c4113dSnw141292 idmap_cfg_fini(idmap_cfg_t *cfg)
2158c5c4113dSnw141292 {
2159c8e26105Sjp151216 	idmap_cfg_handles_t *handles = &cfg->handles;
2160c8e26105Sjp151216 	idmap_cfg_unload(&cfg->pgcfg);
2161c5c4113dSnw141292 
2162c8e26105Sjp151216 	(void) pthread_mutex_destroy(&handles->mutex);
2163c8e26105Sjp151216 	scf_pg_destroy(handles->config_pg);
2164148c5f43SAlan Wright 	if (handles->debug_pg != NULL)
2165148c5f43SAlan Wright 		scf_pg_destroy(handles->debug_pg);
2166c8e26105Sjp151216 	scf_instance_destroy(handles->instance);
2167c8e26105Sjp151216 	scf_service_destroy(handles->service);
2168c8e26105Sjp151216 	scf_handle_destroy(handles->main);
2169e8c27ec8Sbaban 	if (handles->ad_ctx != NULL)
2170c8e26105Sjp151216 		ad_disc_fini(handles->ad_ctx);
2171c5c4113dSnw141292 	free(cfg);
2172c5c4113dSnw141292 
2173c5c4113dSnw141292 	return (0);
2174c5c4113dSnw141292 }
21750dcc7149Snw141292 
21760dcc7149Snw141292 void
idmap_cfg_poke_updates(void)21770dcc7149Snw141292 idmap_cfg_poke_updates(void)
21780dcc7149Snw141292 {
2179349d5d8fSnw141292 	if (idmapd_ev_port != -1)
21800dcc7149Snw141292 		(void) port_send(idmapd_ev_port, POKE_AUTO_DISCOVERY, NULL);
21810dcc7149Snw141292 }
21820dcc7149Snw141292 
21830dcc7149Snw141292 /*ARGSUSED*/
21840dcc7149Snw141292 void
idmap_cfg_hup_handler(int sig)2185349d5d8fSnw141292 idmap_cfg_hup_handler(int sig)
2186349d5d8fSnw141292 {
21870dcc7149Snw141292 	if (idmapd_ev_port >= 0)
21880dcc7149Snw141292 		(void) port_send(idmapd_ev_port, RECONFIGURE, NULL);
21890dcc7149Snw141292 }
2190e3f2c991SKeyur Desai 
2191e3f2c991SKeyur Desai /*
2192148c5f43SAlan Wright  * Upgrade the debug flags.
2193148c5f43SAlan Wright  *
2194148c5f43SAlan Wright  * We're replacing a single debug flag with a fine-grained mechanism that
2195148c5f43SAlan Wright  * is also capable of considerably more verbosity.  We'll take a stab at
2196148c5f43SAlan Wright  * producing roughly the same level of output.
2197148c5f43SAlan Wright  */
2198148c5f43SAlan Wright static
2199148c5f43SAlan Wright int
upgrade_debug(idmap_cfg_handles_t * handles)2200148c5f43SAlan Wright upgrade_debug(idmap_cfg_handles_t *handles)
2201148c5f43SAlan Wright {
2202148c5f43SAlan Wright 	boolean_t debug_present;
2203148c5f43SAlan Wright 	const char DEBUG_PROP[] = "debug";
2204148c5f43SAlan Wright 	int rc;
2205148c5f43SAlan Wright 
2206148c5f43SAlan Wright 	rc = prop_exists(handles, DEBUG_PROP, &debug_present);
2207148c5f43SAlan Wright 
2208148c5f43SAlan Wright 	if (rc != 0)
2209148c5f43SAlan Wright 		return (rc);
2210148c5f43SAlan Wright 
2211148c5f43SAlan Wright 	if (!debug_present)
2212148c5f43SAlan Wright 		return (0);
2213148c5f43SAlan Wright 
2214148c5f43SAlan Wright 	idmapdlog(LOG_INFO,
2215148c5f43SAlan Wright 	    "Upgrading old %s/%s setting to %s/* settings.",
2216148c5f43SAlan Wright 	    CONFIG_PG, DEBUG_PROP, DEBUG_PG);
2217148c5f43SAlan Wright 
2218148c5f43SAlan Wright 	rc = set_val_integer(handles, handles->debug_pg, "config", 1);
2219148c5f43SAlan Wright 	if (rc != 0)
2220148c5f43SAlan Wright 		return (rc);
2221148c5f43SAlan Wright 	rc = set_val_integer(handles, handles->debug_pg, "discovery", 1);
2222148c5f43SAlan Wright 	if (rc != 0)
2223148c5f43SAlan Wright 		return (rc);
2224148c5f43SAlan Wright 
2225148c5f43SAlan Wright 	rc = del_val(handles, handles->config_pg, DEBUG_PROP);
2226148c5f43SAlan Wright 	if (rc != 0)
2227148c5f43SAlan Wright 		return (rc);
2228148c5f43SAlan Wright 
2229148c5f43SAlan Wright 	return (0);
2230148c5f43SAlan Wright }
2231148c5f43SAlan Wright 
2232148c5f43SAlan Wright /*
2233e3f2c991SKeyur Desai  * Upgrade the DS mapping flags.
2234e3f2c991SKeyur Desai  *
2235e3f2c991SKeyur Desai  * If the old ds_name_mapping_enabled flag is present, then
2236e3f2c991SKeyur Desai  *     if the new directory_based_mapping value is present, then
2237e3f2c991SKeyur Desai  *         if the two are compatible, delete the old and note it
2238e3f2c991SKeyur Desai  *         else delete the old and warn
2239e3f2c991SKeyur Desai  *     else
2240e3f2c991SKeyur Desai  *         set the new based on the old, and note it
2241e3f2c991SKeyur Desai  *         delete the old
2242e3f2c991SKeyur Desai  */
2243e3f2c991SKeyur Desai static
2244e3f2c991SKeyur Desai int
upgrade_directory_mapping(idmap_cfg_handles_t * handles)2245e3f2c991SKeyur Desai upgrade_directory_mapping(idmap_cfg_handles_t *handles)
2246e3f2c991SKeyur Desai {
2247e3f2c991SKeyur Desai 	boolean_t legacy_ds_name_mapping_present;
2248e3f2c991SKeyur Desai 	const char DS_NAME_MAPPING_ENABLED[] = "ds_name_mapping_enabled";
2249e3f2c991SKeyur Desai 	const char DIRECTORY_BASED_MAPPING[] = "directory_based_mapping";
2250e3f2c991SKeyur Desai 	int rc;
2251e3f2c991SKeyur Desai 
2252e3f2c991SKeyur Desai 	rc = prop_exists(handles, DS_NAME_MAPPING_ENABLED,
2253e3f2c991SKeyur Desai 	    &legacy_ds_name_mapping_present);
2254e3f2c991SKeyur Desai 
2255e3f2c991SKeyur Desai 	if (rc != 0)
2256e3f2c991SKeyur Desai 		return (rc);
2257e3f2c991SKeyur Desai 
2258e3f2c991SKeyur Desai 	if (!legacy_ds_name_mapping_present)
2259e3f2c991SKeyur Desai 		return (0);
2260e3f2c991SKeyur Desai 
2261e3f2c991SKeyur Desai 	boolean_t legacy_ds_name_mapping_enabled;
2262148c5f43SAlan Wright 	rc = get_val_bool(handles, DS_NAME_MAPPING_ENABLED,
2263148c5f43SAlan Wright 	    &legacy_ds_name_mapping_enabled, B_FALSE);
2264e3f2c991SKeyur Desai 	if (rc != 0)
2265e3f2c991SKeyur Desai 		return (rc);
2266e3f2c991SKeyur Desai 
2267e3f2c991SKeyur Desai 	char *legacy_mode;
2268e3f2c991SKeyur Desai 	char *legacy_bool_string;
2269e3f2c991SKeyur Desai 	if (legacy_ds_name_mapping_enabled) {
2270e3f2c991SKeyur Desai 		legacy_mode = "name";
2271e3f2c991SKeyur Desai 		legacy_bool_string = "true";
2272e3f2c991SKeyur Desai 	} else {
2273e3f2c991SKeyur Desai 		legacy_mode = "none";
2274e3f2c991SKeyur Desai 		legacy_bool_string = "false";
2275e3f2c991SKeyur Desai 	}
2276e3f2c991SKeyur Desai 
2277e3f2c991SKeyur Desai 	char *directory_based_mapping;
2278e3f2c991SKeyur Desai 	rc = get_val_astring(handles, DIRECTORY_BASED_MAPPING,
2279e3f2c991SKeyur Desai 	    &directory_based_mapping);
2280e3f2c991SKeyur Desai 	if (rc != 0)
2281e3f2c991SKeyur Desai 		return (rc);
2282e3f2c991SKeyur Desai 
2283e3f2c991SKeyur Desai 	if (directory_based_mapping == NULL) {
2284e3f2c991SKeyur Desai 		idmapdlog(LOG_INFO,
2285e3f2c991SKeyur Desai 		    "Upgrading old %s=%s setting\n"
2286e3f2c991SKeyur Desai 		    "to %s=%s.",
2287e3f2c991SKeyur Desai 		    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
2288e3f2c991SKeyur Desai 		    DIRECTORY_BASED_MAPPING, legacy_mode);
2289148c5f43SAlan Wright 		rc = set_val_astring(handles, handles->config_pg,
2290148c5f43SAlan Wright 		    DIRECTORY_BASED_MAPPING, legacy_mode);
2291e3f2c991SKeyur Desai 		if (rc != 0)
2292e3f2c991SKeyur Desai 			return (rc);
2293e3f2c991SKeyur Desai 	} else {
2294e3f2c991SKeyur Desai 		boolean_t new_name_mapping;
2295e3f2c991SKeyur Desai 		if (strcasecmp(directory_based_mapping, "name") == 0)
2296e3f2c991SKeyur Desai 			new_name_mapping = B_TRUE;
2297e3f2c991SKeyur Desai 		else
2298e3f2c991SKeyur Desai 			new_name_mapping = B_FALSE;
2299e3f2c991SKeyur Desai 
2300e3f2c991SKeyur Desai 		if (legacy_ds_name_mapping_enabled == new_name_mapping) {
2301e3f2c991SKeyur Desai 			idmapdlog(LOG_INFO,
2302e3f2c991SKeyur Desai 			    "Automatically removing old %s=%s setting\n"
2303e3f2c991SKeyur Desai 			    "in favor of %s=%s.",
2304e3f2c991SKeyur Desai 			    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
2305e3f2c991SKeyur Desai 			    DIRECTORY_BASED_MAPPING, directory_based_mapping);
2306e3f2c991SKeyur Desai 		} else {
2307e3f2c991SKeyur Desai 			idmapdlog(LOG_WARNING,
2308e3f2c991SKeyur Desai 			    "Removing conflicting %s=%s setting\n"
2309e3f2c991SKeyur Desai 			    "in favor of %s=%s.",
2310e3f2c991SKeyur Desai 			    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
2311e3f2c991SKeyur Desai 			    DIRECTORY_BASED_MAPPING, directory_based_mapping);
2312e3f2c991SKeyur Desai 		}
2313e3f2c991SKeyur Desai 		free(directory_based_mapping);
2314e3f2c991SKeyur Desai 	}
2315e3f2c991SKeyur Desai 
2316148c5f43SAlan Wright 	rc = del_val(handles, handles->config_pg, DS_NAME_MAPPING_ENABLED);
2317e3f2c991SKeyur Desai 	if (rc != 0)
2318e3f2c991SKeyur Desai 		return (rc);
2319e3f2c991SKeyur Desai 
2320e3f2c991SKeyur Desai 	return (0);
2321e3f2c991SKeyur Desai }
2322e3f2c991SKeyur Desai 
2323e3f2c991SKeyur Desai /*
2324e3f2c991SKeyur Desai  * Do whatever is necessary to upgrade idmap's configuration before
2325e3f2c991SKeyur Desai  * we load it.
2326e3f2c991SKeyur Desai  */
2327e3f2c991SKeyur Desai int
idmap_cfg_upgrade(idmap_cfg_t * cfg)2328e3f2c991SKeyur Desai idmap_cfg_upgrade(idmap_cfg_t *cfg)
2329e3f2c991SKeyur Desai {
2330e3f2c991SKeyur Desai 	int rc;
2331e3f2c991SKeyur Desai 
2332e3f2c991SKeyur Desai 	rc = upgrade_directory_mapping(&cfg->handles);
2333e3f2c991SKeyur Desai 	if (rc != 0)
2334e3f2c991SKeyur Desai 		return (rc);
2335e3f2c991SKeyur Desai 
2336148c5f43SAlan Wright 	rc = upgrade_debug(&cfg->handles);
2337148c5f43SAlan Wright 	if (rc != 0)
2338148c5f43SAlan Wright 		return (rc);
2339148c5f43SAlan Wright 
2340e3f2c991SKeyur Desai 	return (0);
2341e3f2c991SKeyur Desai }
2342