xref: /titanic_51/usr/src/cmd/idmap/idmapd/idmap_config.c (revision b3700b074e637f8c6991b70754c88a2cfffb246b)
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*b3700b07SGordon Ross  * Copyright 2014 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>
36c5c4113dSnw141292 #include <stdio.h>
37c5c4113dSnw141292 #include <stdarg.h>
388edda628Sbaban #include <uuid/uuid.h>
39c8e26105Sjp151216 #include <pthread.h>
40c8e26105Sjp151216 #include <port.h>
41*b3700b07SGordon Ross #include <sys/socket.h>
420dcc7149Snw141292 #include <net/route.h>
434d61c878SJulian Pullen #include <sys/u8_textprep.h>
44*b3700b07SGordon Ross #include <netinet/in.h>
45*b3700b07SGordon Ross #include <arpa/inet.h>
46*b3700b07SGordon Ross #include <netdb.h>
47148c5f43SAlan Wright #include <note.h>
48*b3700b07SGordon Ross #include "idmapd.h"
49c8e26105Sjp151216 #include "addisc.h"
50c5c4113dSnw141292 
514aa0a5e7Snw141292 #define	MACHINE_SID_LEN		(9 + 3 * 11)
52c5c4113dSnw141292 #define	FMRI_BASE		"svc:/system/idmap"
53c5c4113dSnw141292 #define	CONFIG_PG		"config"
54148c5f43SAlan Wright #define	DEBUG_PG		"debug"
550dcc7149Snw141292 #define	RECONFIGURE		1
560dcc7149Snw141292 #define	POKE_AUTO_DISCOVERY	2
57*b3700b07SGordon Ross #define	KICK_AUTO_DISCOVERY	3
58c5c4113dSnw141292 
5948cd229bSGordon Ross /*
6048cd229bSGordon Ross  * Default cache timeouts.  Can override via svccfg
6148cd229bSGordon Ross  * config/id_cache_timeout = count: seconds
6248cd229bSGordon Ross  * config/name_cache_timeout = count: seconds
6348cd229bSGordon Ross  */
643f1de28dSBayard Bell #define	ID_CACHE_TMO_DEFAULT	86400
653f1de28dSBayard Bell #define	NAME_CACHE_TMO_DEFAULT	604800
6648cd229bSGordon Ross 
67*b3700b07SGordon Ross /*
68*b3700b07SGordon Ross  * Default maximum time between rediscovery runs.
69*b3700b07SGordon Ross  * config/rediscovery_interval = count: seconds
70*b3700b07SGordon Ross  */
71*b3700b07SGordon Ross #define	REDISCOVERY_INTERVAL_DEFAULT	3600
72*b3700b07SGordon Ross 
73*b3700b07SGordon Ross /*
74*b3700b07SGordon Ross  * Mininum time between rediscovery runs, in case adutils gives us a
75*b3700b07SGordon Ross  * really short TTL (which it never should, but be defensive)
76*b3700b07SGordon Ross  * (not configurable) seconds.
77*b3700b07SGordon Ross  */
78*b3700b07SGordon Ross #define	MIN_REDISCOVERY_INTERVAL	60
79*b3700b07SGordon Ross 
80c5866007SKeyur Desai enum event_type {
81c5866007SKeyur Desai 	EVENT_NOTHING,	/* Woke up for no good reason */
82c5866007SKeyur Desai 	EVENT_TIMEOUT,	/* Timeout expired */
83c5866007SKeyur Desai 	EVENT_ROUTING,	/* An interesting routing event happened */
84*b3700b07SGordon Ross 	EVENT_POKED,	/* Requested from degrade_svc() */
85*b3700b07SGordon Ross 	EVENT_KICKED,	/* Force rediscovery, i.e. DC failed. */
86c5866007SKeyur Desai 	EVENT_REFRESH,	/* SMF refresh */
87c5866007SKeyur Desai };
88c5866007SKeyur Desai 
89c8e26105Sjp151216 
90*b3700b07SGordon Ross static void idmapd_set_krb5_realm(char *);
91c8e26105Sjp151216 
92c8e26105Sjp151216 static pthread_t update_thread_handle = 0;
93c8e26105Sjp151216 
940dcc7149Snw141292 static int idmapd_ev_port = -1;
950dcc7149Snw141292 static int rt_sock = -1;
96c8e26105Sjp151216 
97e3f2c991SKeyur Desai struct enum_lookup_map directory_mapping_map[] = {
98e3f2c991SKeyur Desai 	{ DIRECTORY_MAPPING_NONE, "none" },
99e3f2c991SKeyur Desai 	{ DIRECTORY_MAPPING_NAME, "name" },
100e3f2c991SKeyur Desai 	{ DIRECTORY_MAPPING_IDMU, "idmu" },
101e3f2c991SKeyur Desai 	{ 0, NULL },
102e3f2c991SKeyur Desai };
103e3f2c991SKeyur Desai 
104148c5f43SAlan Wright struct enum_lookup_map trust_dir_map[] = {
105148c5f43SAlan Wright 	{ 1, "they trust us" },
106148c5f43SAlan Wright 	{ 2, "we trust them" },
107148c5f43SAlan Wright 	{ 3, "we trust each other" },
108148c5f43SAlan Wright 	{ 0, NULL },
109148c5f43SAlan Wright };
110148c5f43SAlan Wright 
1118edda628Sbaban static int
11212b65585SGordon Ross generate_machine_uuid(char **machine_uuid)
1134edd44c5Sjp151216 {
1148edda628Sbaban 	uuid_t uu;
1158edda628Sbaban 
11612b65585SGordon Ross 	*machine_uuid = calloc(1, UUID_PRINTABLE_STRING_LENGTH + 1);
11712b65585SGordon Ross 	if (*machine_uuid == NULL) {
11871590c90Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
1198edda628Sbaban 		return (-1);
1208edda628Sbaban 	}
1218edda628Sbaban 
1228edda628Sbaban 	uuid_clear(uu);
12312b65585SGordon Ross 	uuid_generate_time(uu);
12412b65585SGordon Ross 	uuid_unparse(uu, *machine_uuid);
1258edda628Sbaban 
12612b65585SGordon Ross 	return (0);
12712b65585SGordon Ross }
1284aa0a5e7Snw141292 
12912b65585SGordon Ross static int
13012b65585SGordon Ross generate_machine_sid(char **machine_sid, char *machine_uuid)
13112b65585SGordon Ross {
13212b65585SGordon Ross 	union {
13312b65585SGordon Ross 		uuid_t uu;
13412b65585SGordon Ross 		uint32_t v[4];
13512b65585SGordon Ross 	} uv;
13612b65585SGordon Ross 	int len;
13712b65585SGordon Ross 
13812b65585SGordon Ross 	/*
13912b65585SGordon Ross 	 * Split the 128-bit machine UUID into three 32-bit values
14012b65585SGordon Ross 	 * we'll use as the "sub-authorities" of the machine SID.
14112b65585SGordon Ross 	 * The machine_sid will have the form S-1-5-21-J-K-L
14212b65585SGordon Ross 	 * (that's four sub-authorities altogether) where:
14312b65585SGordon Ross 	 *	J = last 4 bytes of node_addr,
14412b65585SGordon Ross 	 *	K = time_mid, time_hi_and_version
14512b65585SGordon Ross 	 *	L = time_low
14612b65585SGordon Ross 	 * (see struct uuid)
14712b65585SGordon Ross 	 */
14812b65585SGordon Ross 
14912b65585SGordon Ross 	(void) memset(&uv, 0, sizeof (uv));
15012b65585SGordon Ross 	(void) uuid_parse(machine_uuid, uv.uu);
15112b65585SGordon Ross 
15212b65585SGordon Ross 	len = asprintf(machine_sid, "S-1-5-21-%u-%u-%u",
15312b65585SGordon Ross 	    uv.v[3], uv.v[0], uv.v[1]);
15412b65585SGordon Ross 
15512b65585SGordon Ross 	if (len == -1 || *machine_sid == NULL) {
15612b65585SGordon Ross 		idmapdlog(LOG_ERR, "Out of memory");
15712b65585SGordon Ross 		return (-1);
1588edda628Sbaban 	}
1598edda628Sbaban 
1608edda628Sbaban 	return (0);
1618edda628Sbaban }
1628edda628Sbaban 
16371590c90Snw141292 
164479ac375Sdm199847 /* In the case of error, exists is set to FALSE anyway */
165479ac375Sdm199847 static int
166e3f2c991SKeyur Desai prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists)
167479ac375Sdm199847 {
168479ac375Sdm199847 
169479ac375Sdm199847 	scf_property_t *scf_prop;
170479ac375Sdm199847 
1717a8a68f5SJulian Pullen 	*exists = B_FALSE;
172479ac375Sdm199847 
173479ac375Sdm199847 	scf_prop = scf_property_create(handles->main);
174479ac375Sdm199847 	if (scf_prop == NULL) {
175479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
176479ac375Sdm199847 		    scf_strerror(scf_error()));
177479ac375Sdm199847 		return (-1);
178479ac375Sdm199847 	}
179148c5f43SAlan Wright 
180148c5f43SAlan Wright 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) == 0)
181148c5f43SAlan Wright 		*exists = B_TRUE;
182148c5f43SAlan Wright 
183148c5f43SAlan Wright 	scf_property_destroy(scf_prop);
184148c5f43SAlan Wright 
185148c5f43SAlan Wright 	return (0);
186148c5f43SAlan Wright }
187148c5f43SAlan Wright 
188148c5f43SAlan Wright static int
189148c5f43SAlan Wright get_debug(idmap_cfg_handles_t *handles, const char *name)
190148c5f43SAlan Wright {
191148c5f43SAlan Wright 	int64_t i64 = 0;
192148c5f43SAlan Wright 
193148c5f43SAlan Wright 	scf_property_t *scf_prop;
194148c5f43SAlan Wright 	scf_value_t *value;
195148c5f43SAlan Wright 
196148c5f43SAlan Wright 	scf_prop = scf_property_create(handles->main);
197148c5f43SAlan Wright 	if (scf_prop == NULL) {
198148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
199148c5f43SAlan Wright 		    scf_strerror(scf_error()));
200148c5f43SAlan Wright 		abort();
201148c5f43SAlan Wright 	}
202148c5f43SAlan Wright 	value = scf_value_create(handles->main);
203148c5f43SAlan Wright 	if (value == NULL) {
204148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
205148c5f43SAlan Wright 		    scf_strerror(scf_error()));
206148c5f43SAlan Wright 		abort();
207148c5f43SAlan Wright 	}
208148c5f43SAlan Wright 
209148c5f43SAlan Wright 	if (scf_pg_get_property(handles->debug_pg, name, scf_prop) < 0) {
210148c5f43SAlan Wright 		/* this is OK: the property is just undefined */
211148c5f43SAlan Wright 		goto destruction;
212148c5f43SAlan Wright 	}
213148c5f43SAlan Wright 
214148c5f43SAlan Wright 
215148c5f43SAlan Wright 	if (scf_property_get_value(scf_prop, value) < 0) {
216148c5f43SAlan Wright 		/* It is still OK when a property doesn't have any value */
217148c5f43SAlan Wright 		goto destruction;
218148c5f43SAlan Wright 	}
219148c5f43SAlan Wright 
220148c5f43SAlan Wright 	if (scf_value_get_integer(value, &i64) != 0) {
221148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "Can not retrieve %s/%s:  %s",
222148c5f43SAlan Wright 		    DEBUG_PG, name, scf_strerror(scf_error()));
223148c5f43SAlan Wright 		abort();
224148c5f43SAlan Wright 	}
225148c5f43SAlan Wright 
226148c5f43SAlan Wright destruction:
227148c5f43SAlan Wright 	scf_value_destroy(value);
228148c5f43SAlan Wright 	scf_property_destroy(scf_prop);
229148c5f43SAlan Wright 
230148c5f43SAlan Wright 	return ((int)i64);
231148c5f43SAlan Wright }
232148c5f43SAlan Wright 
233148c5f43SAlan Wright static int
234148c5f43SAlan Wright get_val_bool(idmap_cfg_handles_t *handles, const char *name,
235148c5f43SAlan Wright 	boolean_t *val, boolean_t default_val)
236148c5f43SAlan Wright {
237148c5f43SAlan Wright 	int rc = 0;
238148c5f43SAlan Wright 
239148c5f43SAlan Wright 	scf_property_t *scf_prop;
240148c5f43SAlan Wright 	scf_value_t *value;
241148c5f43SAlan Wright 
242148c5f43SAlan Wright 	*val = default_val;
243148c5f43SAlan Wright 
244148c5f43SAlan Wright 	scf_prop = scf_property_create(handles->main);
245148c5f43SAlan Wright 	if (scf_prop == NULL) {
246148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
247148c5f43SAlan Wright 		    scf_strerror(scf_error()));
248148c5f43SAlan Wright 		return (-1);
249148c5f43SAlan Wright 	}
250479ac375Sdm199847 	value = scf_value_create(handles->main);
251479ac375Sdm199847 	if (value == NULL) {
252479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
253479ac375Sdm199847 		    scf_strerror(scf_error()));
254479ac375Sdm199847 		scf_property_destroy(scf_prop);
255479ac375Sdm199847 		return (-1);
256479ac375Sdm199847 	}
25771590c90Snw141292 
258148c5f43SAlan Wright 	/* It is OK if the property is undefined */
259148c5f43SAlan Wright 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
260148c5f43SAlan Wright 		goto destruction;
26171590c90Snw141292 
262148c5f43SAlan Wright 
263148c5f43SAlan Wright 	/* It is still OK when a property doesn't have any value */
264148c5f43SAlan Wright 	if (scf_property_get_value(scf_prop, value) < 0)
265148c5f43SAlan Wright 		goto destruction;
266148c5f43SAlan Wright 
267148c5f43SAlan Wright 	uint8_t b;
268148c5f43SAlan Wright 	rc = scf_value_get_boolean(value, &b);
269148c5f43SAlan Wright 
270148c5f43SAlan Wright 	if (rc == 0)
271148c5f43SAlan Wright 		*val = (boolean_t)b;
272148c5f43SAlan Wright 
273148c5f43SAlan Wright destruction:
27471590c90Snw141292 	scf_value_destroy(value);
27571590c90Snw141292 	scf_property_destroy(scf_prop);
27671590c90Snw141292 
277148c5f43SAlan Wright 	return (rc);
27871590c90Snw141292 }
27971590c90Snw141292 
280c5c4113dSnw141292 static int
281e3f2c991SKeyur Desai get_val_int(idmap_cfg_handles_t *handles, const char *name,
282c8e26105Sjp151216 	void *val, scf_type_t type)
283c5c4113dSnw141292 {
284c5c4113dSnw141292 	int rc = 0;
285c5c4113dSnw141292 
286479ac375Sdm199847 	scf_property_t *scf_prop;
287479ac375Sdm199847 	scf_value_t *value;
288479ac375Sdm199847 
2894aa0a5e7Snw141292 	switch (type) {
2904aa0a5e7Snw141292 	case SCF_TYPE_COUNT:
2914aa0a5e7Snw141292 		*(uint64_t *)val = 0;
2924aa0a5e7Snw141292 		break;
2934aa0a5e7Snw141292 	case SCF_TYPE_INTEGER:
2944aa0a5e7Snw141292 		*(int64_t *)val = 0;
2954aa0a5e7Snw141292 		break;
2964aa0a5e7Snw141292 	default:
2974aa0a5e7Snw141292 		idmapdlog(LOG_ERR, "Invalid scf integer type (%d)",
2984aa0a5e7Snw141292 		    type);
2994aa0a5e7Snw141292 		abort();
3004aa0a5e7Snw141292 	}
3014aa0a5e7Snw141292 
302479ac375Sdm199847 	scf_prop = scf_property_create(handles->main);
303479ac375Sdm199847 	if (scf_prop == NULL) {
304479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
305479ac375Sdm199847 		    scf_strerror(scf_error()));
306479ac375Sdm199847 		return (-1);
307479ac375Sdm199847 	}
308479ac375Sdm199847 	value = scf_value_create(handles->main);
309479ac375Sdm199847 	if (value == NULL) {
310479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
311479ac375Sdm199847 		    scf_strerror(scf_error()));
312479ac375Sdm199847 		scf_property_destroy(scf_prop);
313479ac375Sdm199847 		return (-1);
314479ac375Sdm199847 	}
315c5c4113dSnw141292 
316c8e26105Sjp151216 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
317c5c4113dSnw141292 	/* this is OK: the property is just undefined */
318c5c4113dSnw141292 		goto destruction;
319c5c4113dSnw141292 
320c5c4113dSnw141292 
321c8e26105Sjp151216 	if (scf_property_get_value(scf_prop, value) < 0)
322c5c4113dSnw141292 	/* It is still OK when a property doesn't have any value */
323c5c4113dSnw141292 		goto destruction;
324c5c4113dSnw141292 
325c5c4113dSnw141292 	switch (type) {
326c5c4113dSnw141292 	case SCF_TYPE_COUNT:
327c5c4113dSnw141292 		rc = scf_value_get_count(value, val);
328c5c4113dSnw141292 		break;
329c5c4113dSnw141292 	case SCF_TYPE_INTEGER:
330c5c4113dSnw141292 		rc = scf_value_get_integer(value, val);
331c5c4113dSnw141292 		break;
332e3f2c991SKeyur Desai 	default:
333e3f2c991SKeyur Desai 		abort();	/* tested above */
334e3f2c991SKeyur Desai 		/* NOTREACHED */
335c5c4113dSnw141292 	}
336c5c4113dSnw141292 
337e3f2c991SKeyur Desai 	if (rc != 0) {
338e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "Can not retrieve config/%s:  %s",
339e3f2c991SKeyur Desai 		    name, scf_strerror(scf_error()));
340e3f2c991SKeyur Desai 	}
341c5c4113dSnw141292 
342c5c4113dSnw141292 destruction:
343c5c4113dSnw141292 	scf_value_destroy(value);
344c5c4113dSnw141292 	scf_property_destroy(scf_prop);
345c5c4113dSnw141292 
346c5c4113dSnw141292 	return (rc);
347c5c4113dSnw141292 }
348c5c4113dSnw141292 
349c5c4113dSnw141292 static char *
350e3f2c991SKeyur Desai scf_value2string(const char *name, scf_value_t *value)
3514edd44c5Sjp151216 {
352e3f2c991SKeyur Desai 	static size_t max_val = 0;
353c5c4113dSnw141292 
354e3f2c991SKeyur Desai 	if (max_val == 0)
355e3f2c991SKeyur Desai 		max_val = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
356e3f2c991SKeyur Desai 
357e3f2c991SKeyur Desai 	char buf[max_val + 1];
358e3f2c991SKeyur Desai 	if (scf_value_get_astring(value, buf, max_val + 1) < 0) {
359e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "Can not retrieve config/%s:  %s",
360e3f2c991SKeyur Desai 		    name, scf_strerror(scf_error()));
361e3f2c991SKeyur Desai 		return (NULL);
362c5c4113dSnw141292 	}
363c5c4113dSnw141292 
364e3f2c991SKeyur Desai 	char *s = strdup(buf);
365e3f2c991SKeyur Desai 	if (s == NULL)
36671590c90Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
367c5c4113dSnw141292 
368e3f2c991SKeyur Desai 	return (s);
369c5c4113dSnw141292 }
370c5c4113dSnw141292 
371c5c4113dSnw141292 static int
372c8e26105Sjp151216 get_val_ds(idmap_cfg_handles_t *handles, const char *name, int defport,
373*b3700b07SGordon Ross 		ad_disc_ds_t **val)
374c5c4113dSnw141292 {
375*b3700b07SGordon Ross 	char port_str[8];
376*b3700b07SGordon Ross 	struct addrinfo hints;
377*b3700b07SGordon Ross 	struct addrinfo *ai;
378*b3700b07SGordon Ross 	ad_disc_ds_t *servers = NULL;
379c8e26105Sjp151216 	scf_property_t *scf_prop;
380c8e26105Sjp151216 	scf_value_t *value;
381c8e26105Sjp151216 	scf_iter_t *iter;
382c8e26105Sjp151216 	char *host, *portstr;
383*b3700b07SGordon Ross 	int err, len, i;
384c8e26105Sjp151216 	int count = 0;
385e3c2d6aaSnw141292 	int rc = -1;
386c5c4113dSnw141292 
387c8e26105Sjp151216 	*val = NULL;
388c5c4113dSnw141292 
389c8e26105Sjp151216 restart:
390c8e26105Sjp151216 	scf_prop = scf_property_create(handles->main);
391479ac375Sdm199847 	if (scf_prop == NULL) {
392479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
393479ac375Sdm199847 		    scf_strerror(scf_error()));
394479ac375Sdm199847 		return (-1);
395479ac375Sdm199847 	}
396479ac375Sdm199847 
397c8e26105Sjp151216 	value = scf_value_create(handles->main);
398479ac375Sdm199847 	if (value == NULL) {
399479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
400479ac375Sdm199847 		    scf_strerror(scf_error()));
401479ac375Sdm199847 		scf_property_destroy(scf_prop);
402479ac375Sdm199847 		return (-1);
403479ac375Sdm199847 	}
404479ac375Sdm199847 
405c8e26105Sjp151216 	iter = scf_iter_create(handles->main);
406479ac375Sdm199847 	if (iter == NULL) {
407479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_iter_create() failed: %s",
408479ac375Sdm199847 		    scf_strerror(scf_error()));
409479ac375Sdm199847 		scf_value_destroy(value);
410479ac375Sdm199847 		scf_property_destroy(scf_prop);
411479ac375Sdm199847 		return (-1);
412479ac375Sdm199847 	}
413c5c4113dSnw141292 
414e3c2d6aaSnw141292 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) {
415c5c4113dSnw141292 		/* this is OK: the property is just undefined */
416e3c2d6aaSnw141292 		rc = 0;
417c5c4113dSnw141292 		goto destruction;
418e3c2d6aaSnw141292 	}
419c5c4113dSnw141292 
420c8e26105Sjp151216 	if (scf_iter_property_values(iter, scf_prop) < 0) {
421c8e26105Sjp151216 		idmapdlog(LOG_ERR,
42271590c90Snw141292 		    "scf_iter_property_values(%s) failed: %s",
42371590c90Snw141292 		    name, scf_strerror(scf_error()));
424c8e26105Sjp151216 		goto destruction;
425c8e26105Sjp151216 	}
426c8e26105Sjp151216 
427c8e26105Sjp151216 	/* Workaround scf bugs -- can't reset an iteration */
428c8e26105Sjp151216 	if (count == 0) {
429c8e26105Sjp151216 		while (scf_iter_next_value(iter, value) > 0)
430c8e26105Sjp151216 			count++;
431c8e26105Sjp151216 
432e3c2d6aaSnw141292 		if (count == 0) {
433c8e26105Sjp151216 			/* no values */
434e3c2d6aaSnw141292 			rc = 0;
435c8e26105Sjp151216 			goto destruction;
436e3c2d6aaSnw141292 		}
437c8e26105Sjp151216 
438c8e26105Sjp151216 		scf_value_destroy(value);
439c8e26105Sjp151216 		scf_iter_destroy(iter);
440c8e26105Sjp151216 		scf_property_destroy(scf_prop);
441c8e26105Sjp151216 		goto restart;
442c8e26105Sjp151216 	}
443c8e26105Sjp151216 
444c8e26105Sjp151216 	if ((servers = calloc(count + 1, sizeof (*servers))) == NULL) {
44571590c90Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
446c8e26105Sjp151216 		goto destruction;
447c8e26105Sjp151216 	}
448c8e26105Sjp151216 
449*b3700b07SGordon Ross 	(void) memset(&hints, 0, sizeof (hints));
450*b3700b07SGordon Ross 	hints.ai_protocol = IPPROTO_TCP;
451*b3700b07SGordon Ross 	hints.ai_socktype = SOCK_STREAM;
452*b3700b07SGordon Ross 	host = NULL;
453*b3700b07SGordon Ross 
454e3c2d6aaSnw141292 	i = 0;
455e3c2d6aaSnw141292 	while (i < count && scf_iter_next_value(iter, value) > 0) {
456*b3700b07SGordon Ross 		if (host) {
457*b3700b07SGordon Ross 			free(host);
458*b3700b07SGordon Ross 			host = NULL;
459*b3700b07SGordon Ross 		}
460e3c2d6aaSnw141292 		servers[i].priority = 0;
461e3c2d6aaSnw141292 		servers[i].weight = 100;
462e3c2d6aaSnw141292 		servers[i].port = defport;
463*b3700b07SGordon Ross 		if ((host = scf_value2string(name, value)) == NULL)
464*b3700b07SGordon Ross 			continue;
465c8e26105Sjp151216 		if ((portstr = strchr(host, ':')) != NULL) {
466c8e26105Sjp151216 			*portstr++ = '\0';
467e3c2d6aaSnw141292 			servers[i].port = strtol(portstr,
468c8e26105Sjp151216 			    (char **)NULL, 10);
469e3c2d6aaSnw141292 			if (servers[i].port == 0)
470e3c2d6aaSnw141292 				servers[i].port = defport;
471c8e26105Sjp151216 		}
472c8e26105Sjp151216 
473*b3700b07SGordon Ross 		/*
474*b3700b07SGordon Ross 		 * Ignore this server if the hostname is too long
475*b3700b07SGordon Ross 		 * or empty (continue without i++)
476*b3700b07SGordon Ross 		 */
477*b3700b07SGordon Ross 		len = strlen(host);
478*b3700b07SGordon Ross 		if (len == 0) {
479*b3700b07SGordon Ross 			if (DBG(CONFIG, 1)) {
480*b3700b07SGordon Ross 				idmapdlog(LOG_INFO, "%s host=\"\"", name);
481*b3700b07SGordon Ross 			}
482*b3700b07SGordon Ross 			continue;
483*b3700b07SGordon Ross 		}
484*b3700b07SGordon Ross 		if (len >= sizeof (servers->host)) {
485*b3700b07SGordon Ross 			idmapdlog(LOG_ERR, "Host name too long: %s", host);
486*b3700b07SGordon Ross 			idmapdlog(LOG_ERR, "ignoring %s value", name);
487*b3700b07SGordon Ross 			continue;
488c8e26105Sjp151216 		}
489c8e26105Sjp151216 
490*b3700b07SGordon Ross 		/*
491*b3700b07SGordon Ross 		 * Get the host address too.  If we can't, then
492*b3700b07SGordon Ross 		 * log an error and skip this host.
493*b3700b07SGordon Ross 		 */
494*b3700b07SGordon Ross 		(void) snprintf(port_str, sizeof (port_str),
495*b3700b07SGordon Ross 		    "%d", servers[i].port);
496*b3700b07SGordon Ross 		ai = NULL;
497*b3700b07SGordon Ross 		err = getaddrinfo(host, port_str, &hints, &ai);
498*b3700b07SGordon Ross 		if (err != 0) {
499*b3700b07SGordon Ross 			idmapdlog(LOG_ERR, "No address for host: %s (%s)",
500*b3700b07SGordon Ross 			    host, gai_strerror(err));
501*b3700b07SGordon Ross 			idmapdlog(LOG_ERR, "ignoring %s value", name);
502*b3700b07SGordon Ross 			continue;
503*b3700b07SGordon Ross 		}
504*b3700b07SGordon Ross 
505*b3700b07SGordon Ross 		(void) strlcpy(servers[i].host, host,
506*b3700b07SGordon Ross 		    sizeof (servers->host));
507*b3700b07SGordon Ross 		(void) memcpy(&servers[i].addr, ai->ai_addr, ai->ai_addrlen);
508*b3700b07SGordon Ross 		freeaddrinfo(ai);
509*b3700b07SGordon Ross 
510*b3700b07SGordon Ross 		/* Added a DS to the array. */
511*b3700b07SGordon Ross 		i++;
512*b3700b07SGordon Ross 	}
513*b3700b07SGordon Ross 	free(host);
514*b3700b07SGordon Ross 
515*b3700b07SGordon Ross 	if (i == 0) {
516*b3700b07SGordon Ross 		if (DBG(CONFIG, 1)) {
517*b3700b07SGordon Ross 			idmapdlog(LOG_INFO, "%s is empty", name);
518*b3700b07SGordon Ross 		}
519*b3700b07SGordon Ross 		free(servers);
520*b3700b07SGordon Ross 		servers = NULL;
521*b3700b07SGordon Ross 	}
522c8e26105Sjp151216 	*val = servers;
523c8e26105Sjp151216 
524e3c2d6aaSnw141292 	rc = 0;
525e3c2d6aaSnw141292 
526c8e26105Sjp151216 destruction:
527c8e26105Sjp151216 	scf_value_destroy(value);
528c8e26105Sjp151216 	scf_iter_destroy(iter);
529c8e26105Sjp151216 	scf_property_destroy(scf_prop);
530c8e26105Sjp151216 
531c8e26105Sjp151216 	if (rc < 0) {
532c8e26105Sjp151216 		if (servers)
533c8e26105Sjp151216 			free(servers);
534c8e26105Sjp151216 		*val = NULL;
535c8e26105Sjp151216 	}
536c8e26105Sjp151216 
537c8e26105Sjp151216 	return (rc);
538c8e26105Sjp151216 }
539c8e26105Sjp151216 
540c8e26105Sjp151216 static int
541e3f2c991SKeyur Desai get_val_astring(idmap_cfg_handles_t *handles, const char *name, char **val)
542c8e26105Sjp151216 {
543c8e26105Sjp151216 	int rc = 0;
544c8e26105Sjp151216 
545479ac375Sdm199847 	scf_property_t *scf_prop;
546479ac375Sdm199847 	scf_value_t *value;
547479ac375Sdm199847 
548479ac375Sdm199847 	scf_prop = scf_property_create(handles->main);
549479ac375Sdm199847 	if (scf_prop == NULL) {
550479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
551479ac375Sdm199847 		    scf_strerror(scf_error()));
552479ac375Sdm199847 		return (-1);
553479ac375Sdm199847 	}
554479ac375Sdm199847 	value = scf_value_create(handles->main);
555479ac375Sdm199847 	if (value == NULL) {
556479ac375Sdm199847 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
557479ac375Sdm199847 		    scf_strerror(scf_error()));
558479ac375Sdm199847 		scf_property_destroy(scf_prop);
559479ac375Sdm199847 		return (-1);
560479ac375Sdm199847 	}
561c8e26105Sjp151216 
562c8e26105Sjp151216 	*val = NULL;
563c8e26105Sjp151216 
564c8e26105Sjp151216 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
565c8e26105Sjp151216 	/* this is OK: the property is just undefined */
566c8e26105Sjp151216 		goto destruction;
567c8e26105Sjp151216 
568c8e26105Sjp151216 	if (scf_property_get_value(scf_prop, value) < 0) {
569651c0131Sbaban 		idmapdlog(LOG_ERR,
57071590c90Snw141292 		    "scf_property_get_value(%s) failed: %s",
57171590c90Snw141292 		    name, scf_strerror(scf_error()));
572c5c4113dSnw141292 		rc = -1;
573c5c4113dSnw141292 		goto destruction;
574c5c4113dSnw141292 	}
575c5c4113dSnw141292 
576e3f2c991SKeyur Desai 	*val = scf_value2string(name, value);
577e3f2c991SKeyur Desai 	if (*val == NULL)
578c5c4113dSnw141292 		rc = -1;
579c5c4113dSnw141292 
580c5c4113dSnw141292 destruction:
581c5c4113dSnw141292 	scf_value_destroy(value);
582c5c4113dSnw141292 	scf_property_destroy(scf_prop);
583c5c4113dSnw141292 
584c5c4113dSnw141292 	if (rc < 0) {
585c5c4113dSnw141292 		if (*val)
586c5c4113dSnw141292 			free(*val);
587c5c4113dSnw141292 		*val = NULL;
588c5c4113dSnw141292 	}
589c5c4113dSnw141292 
590c5c4113dSnw141292 	return (rc);
591c5c4113dSnw141292 }
592c5c4113dSnw141292 
593c8e26105Sjp151216 
5948edda628Sbaban static int
595148c5f43SAlan Wright del_val(
596148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
597148c5f43SAlan Wright     scf_propertygroup_t *pg,
598148c5f43SAlan Wright     const char *name)
599e3f2c991SKeyur Desai {
600e3f2c991SKeyur Desai 	int			rc = -1;
601e3f2c991SKeyur Desai 	int			ret;
602e3f2c991SKeyur Desai 	scf_transaction_t	*tx = NULL;
603e3f2c991SKeyur Desai 	scf_transaction_entry_t	*ent = NULL;
604e3f2c991SKeyur Desai 
605e3f2c991SKeyur Desai 	if ((tx = scf_transaction_create(handles->main)) == NULL) {
606e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
607e3f2c991SKeyur Desai 		    "scf_transaction_create() failed: %s",
608e3f2c991SKeyur Desai 		    scf_strerror(scf_error()));
609e3f2c991SKeyur Desai 		goto destruction;
610e3f2c991SKeyur Desai 	}
611e3f2c991SKeyur Desai 	if ((ent = scf_entry_create(handles->main)) == NULL) {
612e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
613e3f2c991SKeyur Desai 		    "scf_entry_create() failed: %s",
614e3f2c991SKeyur Desai 		    scf_strerror(scf_error()));
615e3f2c991SKeyur Desai 		goto destruction;
616e3f2c991SKeyur Desai 	}
617e3f2c991SKeyur Desai 
618e3f2c991SKeyur Desai 	do {
619148c5f43SAlan Wright 		if (scf_pg_update(pg) == -1) {
620e3f2c991SKeyur Desai 			idmapdlog(LOG_ERR,
621e3f2c991SKeyur Desai 			    "scf_pg_update(%s) failed: %s",
622e3f2c991SKeyur Desai 			    name, scf_strerror(scf_error()));
623e3f2c991SKeyur Desai 			goto destruction;
624e3f2c991SKeyur Desai 		}
625148c5f43SAlan Wright 		if (scf_transaction_start(tx, pg) != 0) {
626e3f2c991SKeyur Desai 			idmapdlog(LOG_ERR,
627e3f2c991SKeyur Desai 			    "scf_transaction_start(%s) failed: %s",
628e3f2c991SKeyur Desai 			    name, scf_strerror(scf_error()));
629e3f2c991SKeyur Desai 			goto destruction;
630e3f2c991SKeyur Desai 		}
631e3f2c991SKeyur Desai 
632e3f2c991SKeyur Desai 		if (scf_transaction_property_delete(tx, ent, name) != 0) {
633e3f2c991SKeyur Desai 			/* Don't complain if it already doesn't exist. */
634e3f2c991SKeyur Desai 			if (scf_error() != SCF_ERROR_NOT_FOUND) {
635e3f2c991SKeyur Desai 				idmapdlog(LOG_ERR,
636e3f2c991SKeyur Desai 				    "scf_transaction_property_delete() failed:"
637e3f2c991SKeyur Desai 				    " %s",
638e3f2c991SKeyur Desai 				    scf_strerror(scf_error()));
639e3f2c991SKeyur Desai 			}
640e3f2c991SKeyur Desai 			goto destruction;
641e3f2c991SKeyur Desai 		}
642e3f2c991SKeyur Desai 
643e3f2c991SKeyur Desai 		ret = scf_transaction_commit(tx);
644e3f2c991SKeyur Desai 
645e3f2c991SKeyur Desai 		if (ret == 0)
646e3f2c991SKeyur Desai 			scf_transaction_reset(tx);
647e3f2c991SKeyur Desai 	} while (ret == 0);
648e3f2c991SKeyur Desai 
649e3f2c991SKeyur Desai 	if (ret == -1) {
650e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
651e3f2c991SKeyur Desai 		    "scf_transaction_commit(%s) failed: %s",
652e3f2c991SKeyur Desai 		    name, scf_strerror(scf_error()));
653e3f2c991SKeyur Desai 		goto destruction;
654e3f2c991SKeyur Desai 	}
655e3f2c991SKeyur Desai 
656e3f2c991SKeyur Desai 	rc = 0;
657e3f2c991SKeyur Desai 
658e3f2c991SKeyur Desai destruction:
659e3f2c991SKeyur Desai 	if (ent != NULL)
660e3f2c991SKeyur Desai 		scf_entry_destroy(ent);
661e3f2c991SKeyur Desai 	if (tx != NULL)
662e3f2c991SKeyur Desai 		scf_transaction_destroy(tx);
663e3f2c991SKeyur Desai 	return (rc);
664e3f2c991SKeyur Desai }
665e3f2c991SKeyur Desai 
666e3f2c991SKeyur Desai 
667e3f2c991SKeyur Desai static int
668148c5f43SAlan Wright set_val(
669148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
670148c5f43SAlan Wright     scf_propertygroup_t *pg,
671148c5f43SAlan Wright     const char *name,
672148c5f43SAlan Wright     scf_value_t *value)
6738edda628Sbaban {
674e3c2d6aaSnw141292 	int			rc = -1;
675e3c2d6aaSnw141292 	int			i;
676148c5f43SAlan Wright 	scf_property_t		*prop = NULL;
6778edda628Sbaban 	scf_transaction_t	*tx = NULL;
6788edda628Sbaban 	scf_transaction_entry_t	*ent = NULL;
6798edda628Sbaban 
680148c5f43SAlan Wright 	if ((prop = scf_property_create(handles->main)) == NULL ||
681c8e26105Sjp151216 	    (tx = scf_transaction_create(handles->main)) == NULL ||
682c8e26105Sjp151216 	    (ent = scf_entry_create(handles->main)) == NULL) {
68371590c90Snw141292 		idmapdlog(LOG_ERR, "Unable to set property %s",
68471590c90Snw141292 		    name, scf_strerror(scf_error()));
6858edda628Sbaban 		goto destruction;
6868edda628Sbaban 	}
6878edda628Sbaban 
688148c5f43SAlan Wright 	for (i = 0; i < MAX_TRIES; i++) {
689148c5f43SAlan Wright 		int ret;
690148c5f43SAlan Wright 
691148c5f43SAlan Wright 		if (scf_pg_update(pg) == -1) {
692148c5f43SAlan Wright 			idmapdlog(LOG_ERR,
693148c5f43SAlan Wright 			    "scf_pg_update() failed: %s",
694148c5f43SAlan Wright 			    scf_strerror(scf_error()));
695148c5f43SAlan Wright 			goto destruction;
696148c5f43SAlan Wright 		}
697148c5f43SAlan Wright 
698148c5f43SAlan Wright 		if (scf_transaction_start(tx, pg) == -1) {
6998edda628Sbaban 			idmapdlog(LOG_ERR,
70071590c90Snw141292 			    "scf_transaction_start(%s) failed: %s",
70171590c90Snw141292 			    name, scf_strerror(scf_error()));
7028edda628Sbaban 			goto destruction;
7038edda628Sbaban 		}
7048edda628Sbaban 
705148c5f43SAlan Wright 		ret = scf_pg_get_property(pg, name, prop);
706148c5f43SAlan Wright 		if (ret == SCF_SUCCESS) {
707148c5f43SAlan Wright 			if (scf_transaction_property_change_type(tx, ent, name,
708148c5f43SAlan Wright 			    scf_value_type(value)) < 0) {
709148c5f43SAlan Wright 				idmapdlog(LOG_ERR,
710148c5f43SAlan Wright 				    "scf_transaction_property_change_type(%s)"
711148c5f43SAlan Wright 				    " failed: %s",
712148c5f43SAlan Wright 				    name, scf_strerror(scf_error()));
713148c5f43SAlan Wright 				goto destruction;
714148c5f43SAlan Wright 			}
715148c5f43SAlan Wright 		} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
716e3c2d6aaSnw141292 			if (scf_transaction_property_new(tx, ent, name,
717148c5f43SAlan Wright 			    scf_value_type(value)) < 0) {
7188edda628Sbaban 				idmapdlog(LOG_ERR,
71971590c90Snw141292 				    "scf_transaction_property_new() failed: %s",
72071590c90Snw141292 				    scf_strerror(scf_error()));
7218edda628Sbaban 				goto destruction;
7228edda628Sbaban 			}
723148c5f43SAlan Wright 		} else {
7248edda628Sbaban 			idmapdlog(LOG_ERR,
725148c5f43SAlan Wright 			    "scf_pg_get_property(%s) failed: %s",
726148c5f43SAlan Wright 			    name, scf_strerror(scf_error()));
7278edda628Sbaban 			goto destruction;
7288edda628Sbaban 		}
7298edda628Sbaban 
7308edda628Sbaban 		if (scf_entry_add_value(ent, value) == -1) {
7318edda628Sbaban 			idmapdlog(LOG_ERR,
73271590c90Snw141292 			    "scf_entry_add_value() failed: %s",
73371590c90Snw141292 			    scf_strerror(scf_error()));
7348edda628Sbaban 			goto destruction;
7358edda628Sbaban 		}
7368edda628Sbaban 
737148c5f43SAlan Wright 		ret = scf_transaction_commit(tx);
738148c5f43SAlan Wright 		if (ret == 0) {
7398edda628Sbaban 			/*
7408edda628Sbaban 			 * Property group set in scf_transaction_start()
7418edda628Sbaban 			 * is not the most recent. Update pg, reset tx and
7428edda628Sbaban 			 * retry tx.
7438edda628Sbaban 			 */
7448edda628Sbaban 			idmapdlog(LOG_WARNING,
745148c5f43SAlan Wright 			    "scf_transaction_commit(%s) failed: %s",
74671590c90Snw141292 			    name, scf_strerror(scf_error()));
7478edda628Sbaban 			scf_transaction_reset(tx);
748148c5f43SAlan Wright 			continue;
7498edda628Sbaban 		}
750148c5f43SAlan Wright 		if (ret != 1) {
7518edda628Sbaban 			idmapdlog(LOG_ERR,
75271590c90Snw141292 			    "scf_transaction_commit(%s) failed: %s",
75371590c90Snw141292 			    name, scf_strerror(scf_error()));
754148c5f43SAlan Wright 			goto destruction;
755148c5f43SAlan Wright 		}
756148c5f43SAlan Wright 		/* Success! */
757148c5f43SAlan Wright 		rc = 0;
758148c5f43SAlan Wright 		break;
759148c5f43SAlan Wright 	}
7608edda628Sbaban 
7618edda628Sbaban destruction:
7628edda628Sbaban 	scf_entry_destroy(ent);
7638edda628Sbaban 	scf_transaction_destroy(tx);
764148c5f43SAlan Wright 	scf_property_destroy(prop);
765148c5f43SAlan Wright 	return (rc);
766148c5f43SAlan Wright }
767148c5f43SAlan Wright 
768148c5f43SAlan Wright static int
769148c5f43SAlan Wright set_val_integer(
770148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
771148c5f43SAlan Wright     scf_propertygroup_t *pg,
772148c5f43SAlan Wright     const char *name,
773148c5f43SAlan Wright     int64_t val)
774148c5f43SAlan Wright {
775148c5f43SAlan Wright 	scf_value_t		*value = NULL;
776148c5f43SAlan Wright 	int			rc;
777148c5f43SAlan Wright 
778148c5f43SAlan Wright 	if ((value = scf_value_create(handles->main)) == NULL) {
779148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "Unable to set property %s",
780148c5f43SAlan Wright 		    name, scf_strerror(scf_error()));
781148c5f43SAlan Wright 		return (-1);
782148c5f43SAlan Wright 	}
783148c5f43SAlan Wright 
784148c5f43SAlan Wright 	scf_value_set_integer(value, val);
785148c5f43SAlan Wright 
786148c5f43SAlan Wright 	rc = set_val(handles, pg, name, value);
787148c5f43SAlan Wright 
788148c5f43SAlan Wright 	scf_value_destroy(value);
789148c5f43SAlan Wright 
790148c5f43SAlan Wright 	return (rc);
791148c5f43SAlan Wright }
792148c5f43SAlan Wright 
793148c5f43SAlan Wright 
794148c5f43SAlan Wright static int
795148c5f43SAlan Wright set_val_astring(
796148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
797148c5f43SAlan Wright     scf_propertygroup_t *pg,
798148c5f43SAlan Wright     const char *name,
799148c5f43SAlan Wright     const char *val)
800148c5f43SAlan Wright {
801148c5f43SAlan Wright 	scf_value_t		*value = NULL;
802148c5f43SAlan Wright 	int			rc = -1;
803148c5f43SAlan Wright 
804148c5f43SAlan Wright 	if ((value = scf_value_create(handles->main)) == NULL) {
805148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "Unable to set property %s",
806148c5f43SAlan Wright 		    name, scf_strerror(scf_error()));
807148c5f43SAlan Wright 		goto out;
808148c5f43SAlan Wright 	}
809148c5f43SAlan Wright 
810148c5f43SAlan Wright 	if (scf_value_set_astring(value, val) == -1) {
811148c5f43SAlan Wright 		idmapdlog(LOG_ERR,
812148c5f43SAlan Wright 		    "scf_value_set_astring() failed: %s",
813148c5f43SAlan Wright 		    scf_strerror(scf_error()));
814148c5f43SAlan Wright 		goto out;
815148c5f43SAlan Wright 	}
816148c5f43SAlan Wright 
817148c5f43SAlan Wright 	rc = set_val(handles, pg, name, value);
818148c5f43SAlan Wright 
819148c5f43SAlan Wright out:
820148c5f43SAlan Wright 	scf_value_destroy(value);
8218edda628Sbaban 	return (rc);
8228edda628Sbaban }
8238edda628Sbaban 
8244d61c878SJulian Pullen 
8254d61c878SJulian Pullen 
8264d61c878SJulian Pullen /*
8274d61c878SJulian Pullen  * This function updates a boolean value.
8284d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
8294d61c878SJulian Pullen  */
830c8e26105Sjp151216 static int
8317a8a68f5SJulian Pullen update_bool(boolean_t *value, boolean_t *new, char *name)
8324aa0a5e7Snw141292 {
8334aa0a5e7Snw141292 	if (*value == *new)
8344aa0a5e7Snw141292 		return (0);
8354aa0a5e7Snw141292 
836148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
837148c5f43SAlan Wright 		idmapdlog(LOG_INFO, "change %s=%s", name,
838148c5f43SAlan Wright 		    *new ? "true" : "false");
839148c5f43SAlan Wright 	}
840148c5f43SAlan Wright 
8414aa0a5e7Snw141292 	*value = *new;
8424aa0a5e7Snw141292 	return (1);
8434aa0a5e7Snw141292 }
8444aa0a5e7Snw141292 
8454d61c878SJulian Pullen /*
84648cd229bSGordon Ross  * This function updates a uint64_t value.
84748cd229bSGordon Ross  * If nothing has changed it returns 0 else 1
84848cd229bSGordon Ross  */
84948cd229bSGordon Ross static int
85048cd229bSGordon Ross update_uint64(uint64_t *value, uint64_t *new, char *name)
85148cd229bSGordon Ross {
85248cd229bSGordon Ross 	if (*value == *new)
85348cd229bSGordon Ross 		return (0);
85448cd229bSGordon Ross 
85548cd229bSGordon Ross 	if (DBG(CONFIG, 1))
85648cd229bSGordon Ross 		idmapdlog(LOG_INFO, "change %s=%llu", name, *new);
85748cd229bSGordon Ross 
85848cd229bSGordon Ross 	*value = *new;
85948cd229bSGordon Ross 	return (1);
86048cd229bSGordon Ross }
86148cd229bSGordon Ross 
86248cd229bSGordon Ross /*
8634d61c878SJulian Pullen  * This function updates a string value.
8644d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
8654d61c878SJulian Pullen  */
8664aa0a5e7Snw141292 static int
8674aa0a5e7Snw141292 update_string(char **value, char **new, char *name)
868c5c4113dSnw141292 {
869148c5f43SAlan Wright 	int changed;
870c5c4113dSnw141292 
871148c5f43SAlan Wright 	if (*new == NULL && *value != NULL)
872148c5f43SAlan Wright 		changed = 1;
873148c5f43SAlan Wright 	else if (*new != NULL && *value == NULL)
874148c5f43SAlan Wright 		changed = 1;
875148c5f43SAlan Wright 	else if (*new != NULL && *value != NULL && strcmp(*new, *value) != 0)
876148c5f43SAlan Wright 		changed = 1;
877148c5f43SAlan Wright 	else
878148c5f43SAlan Wright 		changed = 0;
879c5c4113dSnw141292 
880148c5f43SAlan Wright 	/*
881148c5f43SAlan Wright 	 * Note that even if unchanged we can't just return; we must free one
882148c5f43SAlan Wright 	 * of the values.
883148c5f43SAlan Wright 	 */
884148c5f43SAlan Wright 
885148c5f43SAlan Wright 	if (DBG(CONFIG, 1) && changed)
88671590c90Snw141292 		idmapdlog(LOG_INFO, "change %s=%s", name, CHECK_NULL(*new));
887148c5f43SAlan Wright 
888c8e26105Sjp151216 	free(*value);
889c8e26105Sjp151216 	*value = *new;
890c8e26105Sjp151216 	*new = NULL;
891148c5f43SAlan Wright 	return (changed);
892c5c4113dSnw141292 }
893c5c4113dSnw141292 
894e3f2c991SKeyur Desai static int
895e3f2c991SKeyur Desai update_enum(int *value, int *new, char *name, struct enum_lookup_map *map)
896e3f2c991SKeyur Desai {
897e3f2c991SKeyur Desai 	if (*value == *new)
898e3f2c991SKeyur Desai 		return (0);
899e3f2c991SKeyur Desai 
900148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
901148c5f43SAlan Wright 		idmapdlog(LOG_INFO, "change %s=%s", name,
902148c5f43SAlan Wright 		    enum_lookup(*new, map));
903148c5f43SAlan Wright 	}
904e3f2c991SKeyur Desai 
905e3f2c991SKeyur Desai 	*value = *new;
906e3f2c991SKeyur Desai 
907e3f2c991SKeyur Desai 	return (1);
908e3f2c991SKeyur Desai }
9094d61c878SJulian Pullen 
9104d61c878SJulian Pullen /*
9114d61c878SJulian Pullen  * This function updates a directory service structure.
9124d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
9134d61c878SJulian Pullen  */
914c8e26105Sjp151216 static int
915*b3700b07SGordon Ross update_dirs(ad_disc_ds_t **value, ad_disc_ds_t **new, char *name)
916c8e26105Sjp151216 {
917c5c4113dSnw141292 
9180dcc7149Snw141292 	if (*value == *new)
9190dcc7149Snw141292 		/* Nothing to do */
920349d5d8fSnw141292 		return (0);
921c8e26105Sjp151216 
9220dcc7149Snw141292 	if (*value != NULL && *new != NULL &&
9230dcc7149Snw141292 	    ad_disc_compare_ds(*value, *new) == 0) {
924c8e26105Sjp151216 		free(*new);
925c8e26105Sjp151216 		*new = NULL;
926349d5d8fSnw141292 		return (0);
927c8e26105Sjp151216 	}
928c8e26105Sjp151216 
9294d61c878SJulian Pullen 	if (*value != NULL)
930c8e26105Sjp151216 		free(*value);
931c8e26105Sjp151216 
932c8e26105Sjp151216 	*value = *new;
933c8e26105Sjp151216 	*new = NULL;
9340dcc7149Snw141292 
9350dcc7149Snw141292 	if (*value == NULL) {
9360dcc7149Snw141292 		/* We're unsetting this DS property */
937148c5f43SAlan Wright 		if (DBG(CONFIG, 1))
93871590c90Snw141292 			idmapdlog(LOG_INFO, "change %s=<none>", name);
939349d5d8fSnw141292 		return (1);
9400dcc7149Snw141292 	}
9410dcc7149Snw141292 
942148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
9430dcc7149Snw141292 		/* List all the new DSs */
944*b3700b07SGordon Ross 		char buf[64];
945*b3700b07SGordon Ross 		ad_disc_ds_t *ds;
946*b3700b07SGordon Ross 		for (ds = *value; ds->host[0] != '\0'; ds++) {
947*b3700b07SGordon Ross 			if (ad_disc_getnameinfo(buf, sizeof (buf), &ds->addr))
948*b3700b07SGordon Ross 				(void) strlcpy(buf, "?", sizeof (buf));
949*b3700b07SGordon Ross 			idmapdlog(LOG_INFO, "change %s=%s addr=%s port=%d",
950*b3700b07SGordon Ross 			    name, ds->host, buf, ds->port);
951148c5f43SAlan Wright 		}
952148c5f43SAlan Wright 	}
953349d5d8fSnw141292 	return (1);
954c8e26105Sjp151216 }
955c8e26105Sjp151216 
9564d61c878SJulian Pullen /*
9574d61c878SJulian Pullen  * This function updates a trusted domains structure.
9584d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
9594d61c878SJulian Pullen  */
9604d61c878SJulian Pullen static int
9614d61c878SJulian Pullen update_trusted_domains(ad_disc_trusteddomains_t **value,
9624d61c878SJulian Pullen 			ad_disc_trusteddomains_t **new, char *name)
9634d61c878SJulian Pullen {
9644d61c878SJulian Pullen 	int i;
9654d61c878SJulian Pullen 
9664d61c878SJulian Pullen 	if (*value == *new)
9674d61c878SJulian Pullen 		/* Nothing to do */
9684d61c878SJulian Pullen 		return (0);
9694d61c878SJulian Pullen 
9704d61c878SJulian Pullen 	if (*value != NULL && *new != NULL &&
9714d61c878SJulian Pullen 	    ad_disc_compare_trusteddomains(*value, *new) == 0) {
9724d61c878SJulian Pullen 		free(*new);
9734d61c878SJulian Pullen 		*new = NULL;
9744d61c878SJulian Pullen 		return (0);
9754d61c878SJulian Pullen 	}
9764d61c878SJulian Pullen 
9774d61c878SJulian Pullen 	if (*value != NULL)
9784d61c878SJulian Pullen 		free(*value);
9794d61c878SJulian Pullen 
9804d61c878SJulian Pullen 	*value = *new;
9814d61c878SJulian Pullen 	*new = NULL;
9824d61c878SJulian Pullen 
9834d61c878SJulian Pullen 	if (*value == NULL) {
9844d61c878SJulian Pullen 		/* We're unsetting this DS property */
985148c5f43SAlan Wright 		if (DBG(CONFIG, 1))
9864d61c878SJulian Pullen 			idmapdlog(LOG_INFO, "change %s=<none>", name);
9874d61c878SJulian Pullen 		return (1);
9884d61c878SJulian Pullen 	}
9894d61c878SJulian Pullen 
990148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
9914d61c878SJulian Pullen 		/* List all the new domains */
992148c5f43SAlan Wright 		for (i = 0; (*value)[i].domain[0] != '\0'; i++) {
9934d61c878SJulian Pullen 			idmapdlog(LOG_INFO, "change %s=%s direction=%s", name,
9944d61c878SJulian Pullen 			    (*value)[i].domain,
995148c5f43SAlan Wright 			    enum_lookup((*value)[i].direction, trust_dir_map));
996148c5f43SAlan Wright 		}
997148c5f43SAlan Wright 	}
9984d61c878SJulian Pullen 	return (1);
9994d61c878SJulian Pullen }
10004d61c878SJulian Pullen 
10014d61c878SJulian Pullen 
10024d61c878SJulian Pullen /*
10034d61c878SJulian Pullen  * This function updates a domains in a forest structure.
10044d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
10054d61c878SJulian Pullen  */
10064d61c878SJulian Pullen static int
10074d61c878SJulian Pullen update_domains_in_forest(ad_disc_domainsinforest_t **value,
10084d61c878SJulian Pullen 			ad_disc_domainsinforest_t **new, char *name)
10094d61c878SJulian Pullen {
10104d61c878SJulian Pullen 	int i;
10114d61c878SJulian Pullen 
10124d61c878SJulian Pullen 	if (*value == *new)
10134d61c878SJulian Pullen 		/* Nothing to do */
10144d61c878SJulian Pullen 		return (0);
10154d61c878SJulian Pullen 
10164d61c878SJulian Pullen 	if (*value != NULL && *new != NULL &&
10174d61c878SJulian Pullen 	    ad_disc_compare_domainsinforest(*value, *new) == 0) {
10184d61c878SJulian Pullen 		free(*new);
10194d61c878SJulian Pullen 		*new = NULL;
10204d61c878SJulian Pullen 		return (0);
10214d61c878SJulian Pullen 	}
10224d61c878SJulian Pullen 
10234d61c878SJulian Pullen 	if (*value != NULL)
10244d61c878SJulian Pullen 		free(*value);
10254d61c878SJulian Pullen 
10264d61c878SJulian Pullen 	*value = *new;
10274d61c878SJulian Pullen 	*new = NULL;
10284d61c878SJulian Pullen 
10294d61c878SJulian Pullen 	if (*value == NULL) {
10304d61c878SJulian Pullen 		/* We're unsetting this DS property */
1031148c5f43SAlan Wright 		if (DBG(CONFIG, 1))
10324d61c878SJulian Pullen 			idmapdlog(LOG_INFO, "change %s=<none>", name);
10334d61c878SJulian Pullen 		return (1);
10344d61c878SJulian Pullen 	}
10354d61c878SJulian Pullen 
1036148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
10374d61c878SJulian Pullen 		/* List all the new domains */
1038148c5f43SAlan Wright 		for (i = 0; (*value)[i].domain[0] != '\0'; i++) {
10394d61c878SJulian Pullen 			idmapdlog(LOG_INFO, "change %s=%s", name,
10404d61c878SJulian Pullen 			    (*value)[i].domain);
1041148c5f43SAlan Wright 		}
1042148c5f43SAlan Wright 	}
10434d61c878SJulian Pullen 	return (1);
10444d61c878SJulian Pullen }
10454d61c878SJulian Pullen 
10464d61c878SJulian Pullen 
10474d61c878SJulian Pullen static void
10484d61c878SJulian Pullen free_trusted_forests(idmap_trustedforest_t **value, int *num_values)
10494d61c878SJulian Pullen {
10504d61c878SJulian Pullen 	int i;
10514d61c878SJulian Pullen 
10524d61c878SJulian Pullen 	for (i = 0; i < *num_values; i++) {
10534d61c878SJulian Pullen 		free((*value)[i].forest_name);
10544d61c878SJulian Pullen 		free((*value)[i].global_catalog);
10554d61c878SJulian Pullen 		free((*value)[i].domains_in_forest);
10564d61c878SJulian Pullen 	}
10574d61c878SJulian Pullen 	free(*value);
10584d61c878SJulian Pullen 	*value = NULL;
10594d61c878SJulian Pullen 	*num_values = 0;
10604d61c878SJulian Pullen }
10614d61c878SJulian Pullen 
10624d61c878SJulian Pullen 
10634d61c878SJulian Pullen static int
10644d61c878SJulian Pullen compare_trusteddomainsinforest(ad_disc_domainsinforest_t *df1,
10654d61c878SJulian Pullen 			ad_disc_domainsinforest_t *df2)
10664d61c878SJulian Pullen {
10674d61c878SJulian Pullen 	int		i, j;
10684d61c878SJulian Pullen 	int		num_df1 = 0;
10694d61c878SJulian Pullen 	int		num_df2 = 0;
10707a8a68f5SJulian Pullen 	boolean_t	match;
10714d61c878SJulian Pullen 
10724d61c878SJulian Pullen 	for (i = 0; df1[i].domain[0] != '\0'; i++)
10734d61c878SJulian Pullen 		if (df1[i].trusted)
10744d61c878SJulian Pullen 			num_df1++;
10754d61c878SJulian Pullen 
10764d61c878SJulian Pullen 	for (j = 0; df2[j].domain[0] != '\0'; j++)
10774d61c878SJulian Pullen 		if (df2[j].trusted)
10784d61c878SJulian Pullen 			num_df2++;
10794d61c878SJulian Pullen 
10804d61c878SJulian Pullen 	if (num_df1 != num_df2)
10814d61c878SJulian Pullen 		return (1);
10824d61c878SJulian Pullen 
10834d61c878SJulian Pullen 	for (i = 0; df1[i].domain[0] != '\0'; i++) {
10844d61c878SJulian Pullen 		if (df1[i].trusted) {
10857a8a68f5SJulian Pullen 			match = B_FALSE;
10864d61c878SJulian Pullen 			for (j = 0; df2[j].domain[0] != '\0'; j++) {
10874d61c878SJulian Pullen 				if (df2[j].trusted &&
10881fcced4cSJordan Brown 				    domain_eq(df1[i].domain, df2[j].domain) &&
10891fcced4cSJordan Brown 				    strcmp(df1[i].sid, df2[j].sid) == 0) {
10907a8a68f5SJulian Pullen 					match = B_TRUE;
10914d61c878SJulian Pullen 					break;
10924d61c878SJulian Pullen 				}
10934d61c878SJulian Pullen 			}
10944d61c878SJulian Pullen 			if (!match)
10954d61c878SJulian Pullen 				return (1);
10964d61c878SJulian Pullen 		}
10974d61c878SJulian Pullen 	}
10984d61c878SJulian Pullen 	return (0);
10994d61c878SJulian Pullen }
11004d61c878SJulian Pullen 
11014d61c878SJulian Pullen 
11024d61c878SJulian Pullen 
11034d61c878SJulian Pullen /*
11044d61c878SJulian Pullen  * This function updates trusted forest structure.
11054d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
11064d61c878SJulian Pullen  */
11074d61c878SJulian Pullen static int
11084d61c878SJulian Pullen update_trusted_forest(idmap_trustedforest_t **value, int *num_value,
11094d61c878SJulian Pullen 			idmap_trustedforest_t **new, int *num_new, char *name)
11104d61c878SJulian Pullen {
11114d61c878SJulian Pullen 	int i, j;
11127a8a68f5SJulian Pullen 	boolean_t match;
11134d61c878SJulian Pullen 
11144d61c878SJulian Pullen 	if (*value == *new)
11154d61c878SJulian Pullen 		/* Nothing to do */
11164d61c878SJulian Pullen 		return (0);
11174d61c878SJulian Pullen 
11184d61c878SJulian Pullen 	if (*value != NULL && *new != NULL) {
11194d61c878SJulian Pullen 		if (*num_value != *num_new)
11204d61c878SJulian Pullen 			goto not_equal;
11214d61c878SJulian Pullen 		for (i = 0; i < *num_value; i++) {
11227a8a68f5SJulian Pullen 			match = B_FALSE;
11234d61c878SJulian Pullen 			for (j = 0; j < *num_new; j++) {
11244d61c878SJulian Pullen 				if (strcmp((*value)[i].forest_name,
11254d61c878SJulian Pullen 				    (*new)[j].forest_name) == 0 &&
11264d61c878SJulian Pullen 				    ad_disc_compare_ds(
11274d61c878SJulian Pullen 				    (*value)[i].global_catalog,
11281fcced4cSJordan Brown 				    (*new)[j].global_catalog) == 0 &&
11294d61c878SJulian Pullen 				    compare_trusteddomainsinforest(
11304d61c878SJulian Pullen 				    (*value)[i].domains_in_forest,
11311fcced4cSJordan Brown 				    (*new)[j].domains_in_forest) == 0) {
11327a8a68f5SJulian Pullen 					match = B_TRUE;
11334d61c878SJulian Pullen 					break;
11344d61c878SJulian Pullen 				}
11354d61c878SJulian Pullen 			}
11364d61c878SJulian Pullen 			if (!match)
11374d61c878SJulian Pullen 				goto not_equal;
11384d61c878SJulian Pullen 		}
11394d61c878SJulian Pullen 		free_trusted_forests(new, num_new);
11404d61c878SJulian Pullen 		return (0);
11414d61c878SJulian Pullen 	}
11424d61c878SJulian Pullen not_equal:
11434d61c878SJulian Pullen 	if (*value != NULL)
11444d61c878SJulian Pullen 		free_trusted_forests(value, num_value);
11454d61c878SJulian Pullen 	*value = *new;
11464d61c878SJulian Pullen 	*num_value = *num_new;
11474d61c878SJulian Pullen 	*new = NULL;
11484d61c878SJulian Pullen 	*num_new = 0;
11494d61c878SJulian Pullen 
11504d61c878SJulian Pullen 	if (*value == NULL) {
11514d61c878SJulian Pullen 		/* We're unsetting this DS property */
1152148c5f43SAlan Wright 		if (DBG(CONFIG, 1))
11534d61c878SJulian Pullen 			idmapdlog(LOG_INFO, "change %s=<none>", name);
11544d61c878SJulian Pullen 		return (1);
11554d61c878SJulian Pullen 	}
11564d61c878SJulian Pullen 
1157148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
11584d61c878SJulian Pullen 		/* List all the trusted forests */
11594d61c878SJulian Pullen 		for (i = 0; i < *num_value; i++) {
1160148c5f43SAlan Wright 			idmap_trustedforest_t *f = &(*value)[i];
1161148c5f43SAlan Wright 			for (j = 0;
1162148c5f43SAlan Wright 			    f->domains_in_forest[j].domain[0] != '\0';
11634d61c878SJulian Pullen 			    j++) {
11644d61c878SJulian Pullen 				/* List trusted Domains in the forest. */
1165148c5f43SAlan Wright 				if (f->domains_in_forest[j].trusted)
1166148c5f43SAlan Wright 					idmapdlog(LOG_INFO,
1167148c5f43SAlan Wright 					    "change %s=%s domain=%s",
1168148c5f43SAlan Wright 					    name, f->forest_name,
1169148c5f43SAlan Wright 					    f->domains_in_forest[j].domain);
11704d61c878SJulian Pullen 			}
11714d61c878SJulian Pullen 			/* List the hosts */
1172148c5f43SAlan Wright 			for (j = 0;
1173148c5f43SAlan Wright 			    f->global_catalog[j].host[0] != '\0';
1174148c5f43SAlan Wright 			    j++) {
1175148c5f43SAlan Wright 				idmapdlog(LOG_INFO,
1176148c5f43SAlan Wright 				    "change %s=%s host=%s port=%d",
1177148c5f43SAlan Wright 				    name, f->forest_name,
1178148c5f43SAlan Wright 				    f->global_catalog[j].host,
1179148c5f43SAlan Wright 				    f->global_catalog[j].port);
1180148c5f43SAlan Wright 			}
1181148c5f43SAlan Wright 		}
11824d61c878SJulian Pullen 	}
11834d61c878SJulian Pullen 	return (1);
11844d61c878SJulian Pullen }
11854d61c878SJulian Pullen 
1186e3f2c991SKeyur Desai const char *
1187e3f2c991SKeyur Desai enum_lookup(int value, struct enum_lookup_map *map)
1188e3f2c991SKeyur Desai {
1189e3f2c991SKeyur Desai 	for (; map->string != NULL; map++) {
1190e3f2c991SKeyur Desai 		if (value == map->value) {
1191e3f2c991SKeyur Desai 			return (map->string);
1192e3f2c991SKeyur Desai 		}
1193e3f2c991SKeyur Desai 	}
1194e3f2c991SKeyur Desai 	return ("(invalid)");
1195e3f2c991SKeyur Desai }
1196c8e26105Sjp151216 
1197c5c4113dSnw141292 /*
11980dcc7149Snw141292  * Returns 1 if the PF_ROUTE socket event indicates that we should rescan the
11990dcc7149Snw141292  * interfaces.
1200c8e26105Sjp151216  *
12010dcc7149Snw141292  * Shamelessly based on smb_nics_changed() and other PF_ROUTE uses in ON.
12020dcc7149Snw141292  */
12030dcc7149Snw141292 static
1204c5866007SKeyur Desai boolean_t
12050dcc7149Snw141292 pfroute_event_is_interesting(int rt_sock)
12060dcc7149Snw141292 {
12070dcc7149Snw141292 	int nbytes;
12080dcc7149Snw141292 	int64_t msg[2048 / 8];
12090dcc7149Snw141292 	struct rt_msghdr *rtm;
1210c5866007SKeyur Desai 	boolean_t is_interesting = B_FALSE;
12110dcc7149Snw141292 
12120dcc7149Snw141292 	for (;;) {
12130dcc7149Snw141292 		if ((nbytes = read(rt_sock, msg, sizeof (msg))) <= 0)
12140dcc7149Snw141292 			break;
12150dcc7149Snw141292 		rtm = (struct rt_msghdr *)msg;
12160dcc7149Snw141292 		if (rtm->rtm_version != RTM_VERSION)
12170dcc7149Snw141292 			continue;
12180dcc7149Snw141292 		if (nbytes < rtm->rtm_msglen)
12190dcc7149Snw141292 			continue;
12200dcc7149Snw141292 		switch (rtm->rtm_type) {
12210dcc7149Snw141292 		case RTM_NEWADDR:
12220dcc7149Snw141292 		case RTM_DELADDR:
12230dcc7149Snw141292 		case RTM_IFINFO:
1224c5866007SKeyur Desai 			is_interesting = B_TRUE;
12250dcc7149Snw141292 			break;
12260dcc7149Snw141292 		default:
12270dcc7149Snw141292 			break;
12280dcc7149Snw141292 		}
12290dcc7149Snw141292 	}
12300dcc7149Snw141292 	return (is_interesting);
12310dcc7149Snw141292 }
12320dcc7149Snw141292 
12330dcc7149Snw141292 /*
1234c5866007SKeyur Desai  * Wait for an event, and report what kind of event occurred.
12350dcc7149Snw141292  *
1236c5866007SKeyur Desai  * Note that there are cases where we are awoken but don't care about
1237c5866007SKeyur Desai  * the lower-level event.  We can't just loop here because we can't
1238c5866007SKeyur Desai  * readily calculate how long to sleep the next time.  We return
1239c5866007SKeyur Desai  * EVENT_NOTHING and let the caller loop.
1240c5c4113dSnw141292  */
1241c8e26105Sjp151216 static
1242c5866007SKeyur Desai enum event_type
1243c5866007SKeyur Desai wait_for_event(struct timespec *timeoutp)
1244c8e26105Sjp151216 {
1245c8e26105Sjp151216 	port_event_t pe;
1246c8e26105Sjp151216 
1247148c5f43SAlan Wright 	(void) memset(&pe, 0, sizeof (pe));
1248349d5d8fSnw141292 	if (port_get(idmapd_ev_port, &pe, timeoutp) != 0) {
1249c8e26105Sjp151216 		switch (errno) {
1250c8e26105Sjp151216 		case EINTR:
1251c5866007SKeyur Desai 			return (EVENT_NOTHING);
1252c8e26105Sjp151216 		case ETIME:
1253c8e26105Sjp151216 			/* Timeout */
1254c5866007SKeyur Desai 			return (EVENT_TIMEOUT);
1255c8e26105Sjp151216 		default:
12560dcc7149Snw141292 			/* EBADF, EBADFD, EFAULT, EINVAL (end of time?)? */
12570dcc7149Snw141292 			idmapdlog(LOG_ERR, "Event port failed: %s",
12580dcc7149Snw141292 			    strerror(errno));
12590dcc7149Snw141292 			exit(1);
12600dcc7149Snw141292 			/* NOTREACHED */
1261c5866007SKeyur Desai 		}
1262c5866007SKeyur Desai 	}
1263c5866007SKeyur Desai 
1264c5866007SKeyur Desai 
1265c5866007SKeyur Desai 	switch (pe.portev_source) {
1266c5866007SKeyur Desai 	case 0:
1267c5866007SKeyur Desai 		/*
1268c5866007SKeyur Desai 		 * This isn't documented, but seems to be what you get if
1269c5866007SKeyur Desai 		 * the timeout is zero seconds and there are no events
1270c5866007SKeyur Desai 		 * pending.
1271c5866007SKeyur Desai 		 */
1272c5866007SKeyur Desai 		return (EVENT_TIMEOUT);
1273c5866007SKeyur Desai 
1274c5866007SKeyur Desai 	case PORT_SOURCE_USER:
1275*b3700b07SGordon Ross 		switch (pe.portev_events) {
1276*b3700b07SGordon Ross 		case RECONFIGURE:
1277c5866007SKeyur Desai 			return (EVENT_REFRESH);
1278*b3700b07SGordon Ross 		case POKE_AUTO_DISCOVERY:
1279*b3700b07SGordon Ross 			return (EVENT_POKED);
1280*b3700b07SGordon Ross 		case KICK_AUTO_DISCOVERY:
1281*b3700b07SGordon Ross 			return (EVENT_KICKED);
1282*b3700b07SGordon Ross 		}
1283*b3700b07SGordon Ross 		return (EVENT_NOTHING);
1284c5c4113dSnw141292 
1285c5866007SKeyur Desai 	case PORT_SOURCE_FD:
1286c5866007SKeyur Desai 		if (pe.portev_object == rt_sock) {
1287c5866007SKeyur Desai 			/*
1288c5866007SKeyur Desai 			 * PF_ROUTE socket read event:
1289c5866007SKeyur Desai 			 *    re-associate fd
1290c5866007SKeyur Desai 			 *    handle event
1291c5866007SKeyur Desai 			 */
1292c5866007SKeyur Desai 			if (port_associate(idmapd_ev_port, PORT_SOURCE_FD,
1293c5866007SKeyur Desai 			    rt_sock, POLLIN, NULL) != 0) {
12940dcc7149Snw141292 				idmapdlog(LOG_ERR, "Failed to re-associate the "
12950dcc7149Snw141292 				    "routing socket with the event port: %s",
12960dcc7149Snw141292 				    strerror(errno));
1297c5866007SKeyur Desai 				abort();
12980dcc7149Snw141292 			}
12990dcc7149Snw141292 			/*
1300c5866007SKeyur Desai 			 * The network configuration may still be in flux.
1301c5866007SKeyur Desai 			 * No matter, the resolver will re-transmit and
1302c5866007SKeyur Desai 			 * timeout if need be.
13030dcc7149Snw141292 			 */
1304c5866007SKeyur Desai 			if (pfroute_event_is_interesting(rt_sock)) {
1305148c5f43SAlan Wright 				if (DBG(CONFIG, 1)) {
1306c5866007SKeyur Desai 					idmapdlog(LOG_DEBUG,
1307c5866007SKeyur Desai 					    "Interesting routing event");
1308148c5f43SAlan Wright 				}
1309c5866007SKeyur Desai 				return (EVENT_ROUTING);
1310c5866007SKeyur Desai 			} else {
1311148c5f43SAlan Wright 				if (DBG(CONFIG, 2)) {
1312c5866007SKeyur Desai 					idmapdlog(LOG_DEBUG,
1313c5866007SKeyur Desai 					    "Boring routing event");
1314148c5f43SAlan Wright 				}
1315c5866007SKeyur Desai 				return (EVENT_NOTHING);
1316c5866007SKeyur Desai 			}
1317c5866007SKeyur Desai 		}
1318c5866007SKeyur Desai 		/* Event on an FD other than the routing FD? Ignore it. */
1319c5866007SKeyur Desai 		break;
13200dcc7149Snw141292 	}
13210dcc7149Snw141292 
1322c5866007SKeyur Desai 	return (EVENT_NOTHING);
1323c8e26105Sjp151216 }
1324c8e26105Sjp151216 
1325c8e26105Sjp151216 void *
1326c8e26105Sjp151216 idmap_cfg_update_thread(void *arg)
1327c8e26105Sjp151216 {
1328148c5f43SAlan Wright 	NOTE(ARGUNUSED(arg))
1329*b3700b07SGordon Ross 	idmap_pg_config_t *pgcfg = &_idmapdstate.cfg->pgcfg;
1330c5866007SKeyur Desai 	const ad_disc_t		ad_ctx = _idmapdstate.cfg->handles.ad_ctx;
1331*b3700b07SGordon Ross 	int flags = CFG_DISCOVER;
1332c8e26105Sjp151216 
1333c5866007SKeyur Desai 	for (;;) {
1334c5866007SKeyur Desai 		struct timespec timeout;
1335c5866007SKeyur Desai 		struct timespec	*timeoutp;
1336c5866007SKeyur Desai 		int		rc;
1337*b3700b07SGordon Ross 		int		ttl, max_ttl;
13380dcc7149Snw141292 
13390dcc7149Snw141292 		(void) ad_disc_SubnetChanged(ad_ctx);
1340c8e26105Sjp151216 
1341*b3700b07SGordon Ross 		rc = idmap_cfg_load(_idmapdstate.cfg, flags);
1342c5866007SKeyur Desai 		if (rc < -1) {
13437a8a68f5SJulian Pullen 			idmapdlog(LOG_ERR, "Fatal errors while reading "
1344349d5d8fSnw141292 			    "SMF properties");
1345349d5d8fSnw141292 			exit(1);
1346c5866007SKeyur Desai 		} else if (rc == -1) {
1347c5866007SKeyur Desai 			idmapdlog(LOG_WARNING,
1348c5866007SKeyur Desai 			    "Errors re-loading configuration may cause AD "
1349c5866007SKeyur Desai 			    "lookups to fail");
1350349d5d8fSnw141292 		}
1351c8e26105Sjp151216 
1352c5866007SKeyur Desai 		/*
1353c5866007SKeyur Desai 		 * Wait for an interesting event.  Note that we might get
1354c5866007SKeyur Desai 		 * boring events between interesting events.  If so, we loop.
1355c5866007SKeyur Desai 		 */
1356*b3700b07SGordon Ross 		flags = CFG_DISCOVER;
1357c5866007SKeyur Desai 		for (;;) {
1358*b3700b07SGordon Ross 			/*
1359*b3700b07SGordon Ross 			 * If we don't know our domain name, don't bother
1360*b3700b07SGordon Ross 			 * with rediscovery until the next config change.
1361*b3700b07SGordon Ross 			 * Avoids hourly noise in workgroup mode.
1362*b3700b07SGordon Ross 			 */
1363*b3700b07SGordon Ross 			if (pgcfg->domain_name == NULL)
1364*b3700b07SGordon Ross 				ttl = -1;
1365*b3700b07SGordon Ross 			else
1366c5866007SKeyur Desai 				ttl = ad_disc_get_TTL(ad_ctx);
1367c5866007SKeyur Desai 			if (ttl < 0) {
1368c5866007SKeyur Desai 				timeoutp = NULL;
1369c5866007SKeyur Desai 			} else {
1370*b3700b07SGordon Ross 				max_ttl = (int)pgcfg->rediscovery_interval;
1371*b3700b07SGordon Ross 				if (ttl > max_ttl)
1372*b3700b07SGordon Ross 					ttl = max_ttl;
1373*b3700b07SGordon Ross 				if (ttl < MIN_REDISCOVERY_INTERVAL)
1374*b3700b07SGordon Ross 					ttl = MIN_REDISCOVERY_INTERVAL;
1375c5866007SKeyur Desai 				timeout.tv_sec = ttl;
1376c5866007SKeyur Desai 				timeout.tv_nsec = 0;
1377*b3700b07SGordon Ross 				timeoutp = &timeout;
1378c8e26105Sjp151216 			}
1379c5866007SKeyur Desai 
1380*b3700b07SGordon Ross 			if (DBG(CONFIG, 1))
1381*b3700b07SGordon Ross 				idmapdlog(LOG_DEBUG,
1382*b3700b07SGordon Ross 				    "_cfg_update_thread waiting");
1383*b3700b07SGordon Ross 
1384c5866007SKeyur Desai 			switch (wait_for_event(timeoutp)) {
1385c5866007SKeyur Desai 			case EVENT_NOTHING:
1386148c5f43SAlan Wright 				if (DBG(CONFIG, 2))
1387c5866007SKeyur Desai 					idmapdlog(LOG_DEBUG, "Boring event.");
1388c5866007SKeyur Desai 				continue;
1389c5866007SKeyur Desai 			case EVENT_REFRESH:
1390148c5f43SAlan Wright 				if (DBG(CONFIG, 1))
1391c5866007SKeyur Desai 					idmapdlog(LOG_INFO, "SMF refresh");
1392c5866007SKeyur Desai 				/*
1393*b3700b07SGordon Ross 				 * Forget any DC we had previously.
1394*b3700b07SGordon Ross 				 */
1395*b3700b07SGordon Ross 				flags |= CFG_FORGET_DC;
1396*b3700b07SGordon Ross 
1397*b3700b07SGordon Ross 				/*
1398c5866007SKeyur Desai 				 * Blow away the ccache, we might have
1399c5866007SKeyur Desai 				 * re-joined the domain or joined a new one
1400c5866007SKeyur Desai 				 */
1401c5866007SKeyur Desai 				(void) unlink(IDMAP_CACHEDIR "/ccache");
1402c5866007SKeyur Desai 				break;
1403*b3700b07SGordon Ross 			case EVENT_POKED:
1404*b3700b07SGordon Ross 				if (DBG(CONFIG, 1))
1405*b3700b07SGordon Ross 					idmapdlog(LOG_DEBUG, "poked");
1406*b3700b07SGordon Ross 				break;
1407*b3700b07SGordon Ross 			case EVENT_KICKED:
1408*b3700b07SGordon Ross 				if (DBG(CONFIG, 1))
1409*b3700b07SGordon Ross 					idmapdlog(LOG_DEBUG, "kicked");
1410*b3700b07SGordon Ross 				flags |= CFG_FORGET_DC;
1411c5866007SKeyur Desai 				break;
1412c5866007SKeyur Desai 			case EVENT_TIMEOUT:
1413148c5f43SAlan Wright 				if (DBG(CONFIG, 1))
1414c5866007SKeyur Desai 					idmapdlog(LOG_DEBUG, "TTL expired");
1415c5866007SKeyur Desai 				break;
1416c5866007SKeyur Desai 			case EVENT_ROUTING:
1417c5866007SKeyur Desai 				/* Already logged to DEBUG */
1418c5866007SKeyur Desai 				break;
1419c5866007SKeyur Desai 			}
1420c5866007SKeyur Desai 			/* An interesting event! */
1421c5866007SKeyur Desai 			break;
1422c5866007SKeyur Desai 		}
1423c5866007SKeyur Desai 	}
1424c5866007SKeyur Desai 	/*
1425c5866007SKeyur Desai 	 * Lint isn't happy with the concept of a function declared to
1426c5866007SKeyur Desai 	 * return something, that doesn't return.  Of course, merely adding
1427c5866007SKeyur Desai 	 * the return isn't enough, because it's never reached...
1428c5866007SKeyur Desai 	 */
1429c8e26105Sjp151216 	/*NOTREACHED*/
1430c8e26105Sjp151216 	return (NULL);
1431c8e26105Sjp151216 }
1432c8e26105Sjp151216 
1433c8e26105Sjp151216 int
14340dcc7149Snw141292 idmap_cfg_start_updates(void)
1435c8e26105Sjp151216 {
14360dcc7149Snw141292 	if ((idmapd_ev_port = port_create()) < 0) {
143771590c90Snw141292 		idmapdlog(LOG_ERR, "Failed to create event port: %s",
143871590c90Snw141292 		    strerror(errno));
1439c5c4113dSnw141292 		return (-1);
1440c8e26105Sjp151216 	}
1441c8e26105Sjp151216 
14420dcc7149Snw141292 	if ((rt_sock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
144371590c90Snw141292 		idmapdlog(LOG_ERR, "Failed to open routing socket: %s",
144471590c90Snw141292 		    strerror(errno));
14450dcc7149Snw141292 		(void) close(idmapd_ev_port);
14460dcc7149Snw141292 		return (-1);
14470dcc7149Snw141292 	}
14480dcc7149Snw141292 
14490dcc7149Snw141292 	if (fcntl(rt_sock, F_SETFL, O_NDELAY|O_NONBLOCK) < 0) {
145071590c90Snw141292 		idmapdlog(LOG_ERR, "Failed to set routing socket flags: %s",
145171590c90Snw141292 		    strerror(errno));
14520dcc7149Snw141292 		(void) close(rt_sock);
14530dcc7149Snw141292 		(void) close(idmapd_ev_port);
14540dcc7149Snw141292 		return (-1);
14550dcc7149Snw141292 	}
14560dcc7149Snw141292 
14570dcc7149Snw141292 	if (port_associate(idmapd_ev_port, PORT_SOURCE_FD,
14580dcc7149Snw141292 	    rt_sock, POLLIN, NULL) != 0) {
145971590c90Snw141292 		idmapdlog(LOG_ERR, "Failed to associate the routing "
146071590c90Snw141292 		    "socket with the event port: %s", strerror(errno));
14610dcc7149Snw141292 		(void) close(rt_sock);
14620dcc7149Snw141292 		(void) close(idmapd_ev_port);
14630dcc7149Snw141292 		return (-1);
14640dcc7149Snw141292 	}
14650dcc7149Snw141292 
14660dcc7149Snw141292 	if ((errno = pthread_create(&update_thread_handle, NULL,
14670dcc7149Snw141292 	    idmap_cfg_update_thread, NULL)) != 0) {
146871590c90Snw141292 		idmapdlog(LOG_ERR, "Failed to start update thread: %s",
146971590c90Snw141292 		    strerror(errno));
14700dcc7149Snw141292 		(void) port_dissociate(idmapd_ev_port, PORT_SOURCE_FD, rt_sock);
14710dcc7149Snw141292 		(void) close(rt_sock);
14720dcc7149Snw141292 		(void) close(idmapd_ev_port);
14730dcc7149Snw141292 		return (-1);
14740dcc7149Snw141292 	}
14750dcc7149Snw141292 
14760dcc7149Snw141292 	return (0);
14770dcc7149Snw141292 }
14780dcc7149Snw141292 
1479349d5d8fSnw141292 /*
1480479ac375Sdm199847  * Reject attribute names with invalid characters.
1481479ac375Sdm199847  */
1482479ac375Sdm199847 static
1483479ac375Sdm199847 int
1484479ac375Sdm199847 valid_ldap_attr(const char *attr) {
1485479ac375Sdm199847 	for (; *attr; attr++) {
1486479ac375Sdm199847 		if (!isalnum(*attr) && *attr != '-' &&
1487479ac375Sdm199847 		    *attr != '_' && *attr != '.' && *attr != ';')
1488479ac375Sdm199847 			return (0);
1489479ac375Sdm199847 	}
1490479ac375Sdm199847 	return (1);
1491479ac375Sdm199847 }
1492479ac375Sdm199847 
1493349d5d8fSnw141292 static
1494148c5f43SAlan Wright void
1495148c5f43SAlan Wright idmapd_set_debug(
1496148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
1497148c5f43SAlan Wright     enum idmapd_debug item,
1498148c5f43SAlan Wright     const char *name)
1499148c5f43SAlan Wright {
1500148c5f43SAlan Wright 	int val;
1501148c5f43SAlan Wright 
1502148c5f43SAlan Wright 	if (item < 0 || item > IDMAPD_DEBUG_MAX)
1503148c5f43SAlan Wright 		return;
1504148c5f43SAlan Wright 
1505148c5f43SAlan Wright 	val = get_debug(handles, name);
1506148c5f43SAlan Wright 
1507148c5f43SAlan Wright 	if (val != _idmapdstate.debug[item])
1508148c5f43SAlan Wright 		idmapdlog(LOG_DEBUG, "%s/%s = %d", DEBUG_PG, name, val);
1509148c5f43SAlan Wright 
1510148c5f43SAlan Wright 	_idmapdstate.debug[item] = val;
1511148c5f43SAlan Wright }
1512148c5f43SAlan Wright 
1513148c5f43SAlan Wright static
1514148c5f43SAlan Wright void
1515e3f2c991SKeyur Desai check_smf_debug_mode(idmap_cfg_handles_t *handles)
1516c8e26105Sjp151216 {
1517148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_ALL, "all");
1518148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_CONFIG, "config");
1519148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_MAPPING, "mapping");
1520148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_DISC, "discovery");
1521148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_DNS, "dns");
1522148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_LDAP, "ldap");
1523479ac375Sdm199847 
1524148c5f43SAlan Wright 	adutils_set_debug(AD_DEBUG_ALL, _idmapdstate.debug[IDMAPD_DEBUG_ALL]);
1525148c5f43SAlan Wright 	adutils_set_debug(AD_DEBUG_DISC, _idmapdstate.debug[IDMAPD_DEBUG_DISC]);
1526148c5f43SAlan Wright 	adutils_set_debug(AD_DEBUG_DNS, _idmapdstate.debug[IDMAPD_DEBUG_DNS]);
1527148c5f43SAlan Wright 	adutils_set_debug(AD_DEBUG_LDAP, _idmapdstate.debug[IDMAPD_DEBUG_LDAP]);
1528e3f2c991SKeyur Desai }
1529e3f2c991SKeyur Desai 
1530e3f2c991SKeyur Desai /*
1531e3f2c991SKeyur Desai  * This is the half of idmap_cfg_load() that loads property values from
1532e3f2c991SKeyur Desai  * SMF (using the config/ property group of the idmap FMRI).
1533e3f2c991SKeyur Desai  *
1534e3f2c991SKeyur Desai  * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
1535e3f2c991SKeyur Desai  *               -3 -> hard smf config failures
1536e3f2c991SKeyur Desai  * reading from SMF.
1537e3f2c991SKeyur Desai  */
1538*b3700b07SGordon Ross static int
1539e3f2c991SKeyur Desai idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
1540e3f2c991SKeyur Desai 	int * const errors)
1541e3f2c991SKeyur Desai {
1542e3f2c991SKeyur Desai 	int rc;
1543e3f2c991SKeyur Desai 	char *s;
1544e3f2c991SKeyur Desai 
1545e3f2c991SKeyur Desai 	*errors = 0;
1546e3f2c991SKeyur Desai 
1547e3f2c991SKeyur Desai 	if (scf_pg_update(handles->config_pg) < 0) {
1548e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
1549e3f2c991SKeyur Desai 		    scf_strerror(scf_error()));
1550e3f2c991SKeyur Desai 		return (-2);
1551e3f2c991SKeyur Desai 	}
1552e3f2c991SKeyur Desai 
1553148c5f43SAlan Wright 	if (scf_pg_update(handles->debug_pg) < 0) {
1554e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
1555e3f2c991SKeyur Desai 		    scf_strerror(scf_error()));
1556e3f2c991SKeyur Desai 		return (-2);
1557e3f2c991SKeyur Desai 	}
1558e3f2c991SKeyur Desai 
1559148c5f43SAlan Wright 	check_smf_debug_mode(handles);
1560148c5f43SAlan Wright 
1561148c5f43SAlan Wright 	rc = get_val_bool(handles, "unresolvable_sid_mapping",
1562148c5f43SAlan Wright 	    &pgcfg->eph_map_unres_sids, B_TRUE);
1563e3f2c991SKeyur Desai 	if (rc != 0)
1564e3f2c991SKeyur Desai 		(*errors)++;
1565e3f2c991SKeyur Desai 
15661ed6b69aSGordon Ross 	rc = get_val_bool(handles, "use_ads",
15671ed6b69aSGordon Ross 	    &pgcfg->use_ads, B_TRUE);
15681ed6b69aSGordon Ross 	if (rc != 0)
15691ed6b69aSGordon Ross 		(*errors)++;
15701ed6b69aSGordon Ross 
1571148c5f43SAlan Wright 	rc = get_val_bool(handles, "use_lsa",
1572148c5f43SAlan Wright 	    &pgcfg->use_lsa, B_TRUE);
1573148c5f43SAlan Wright 	if (rc != 0)
1574148c5f43SAlan Wright 		(*errors)++;
1575148c5f43SAlan Wright 
1576148c5f43SAlan Wright 	rc = get_val_bool(handles, "disable_cross_forest_trusts",
1577148c5f43SAlan Wright 	    &pgcfg->disable_cross_forest_trusts, B_TRUE);
15784aa0a5e7Snw141292 	if (rc != 0)
1579e3f2c991SKeyur Desai 		(*errors)++;
1580e3f2c991SKeyur Desai 
1581e3f2c991SKeyur Desai 	rc = get_val_astring(handles, "directory_based_mapping", &s);
1582e3f2c991SKeyur Desai 	if (rc != 0)
1583e3f2c991SKeyur Desai 		(*errors)++;
1584e3f2c991SKeyur Desai 	else if (s == NULL || strcasecmp(s, "none") == 0)
1585e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1586e3f2c991SKeyur Desai 	else if (strcasecmp(s, "name") == 0)
1587e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NAME;
1588e3f2c991SKeyur Desai 	else if (strcasecmp(s, "idmu") == 0)
1589e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_IDMU;
1590e3f2c991SKeyur Desai 	else {
1591e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1592e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
1593e3f2c991SKeyur Desai 		"config/directory_based_mapping:  invalid value \"%s\" ignored",
1594e3f2c991SKeyur Desai 		    s);
1595e3f2c991SKeyur Desai 		(*errors)++;
1596e3f2c991SKeyur Desai 	}
1597e3f2c991SKeyur Desai 	free(s);
15984aa0a5e7Snw141292 
1599c8e26105Sjp151216 	rc = get_val_int(handles, "list_size_limit",
1600c8e26105Sjp151216 	    &pgcfg->list_size_limit, SCF_TYPE_COUNT);
16014aa0a5e7Snw141292 	if (rc != 0)
1602e3f2c991SKeyur Desai 		(*errors)++;
1603c8e26105Sjp151216 
160448cd229bSGordon Ross 	rc = get_val_int(handles, "id_cache_timeout",
160548cd229bSGordon Ross 	    &pgcfg->id_cache_timeout, SCF_TYPE_COUNT);
160648cd229bSGordon Ross 	if (rc != 0)
160748cd229bSGordon Ross 		(*errors)++;
160848cd229bSGordon Ross 	if (pgcfg->id_cache_timeout == 0)
160948cd229bSGordon Ross 		pgcfg->id_cache_timeout = ID_CACHE_TMO_DEFAULT;
161048cd229bSGordon Ross 
161148cd229bSGordon Ross 	rc = get_val_int(handles, "name_cache_timeout",
161248cd229bSGordon Ross 	    &pgcfg->name_cache_timeout, SCF_TYPE_COUNT);
161348cd229bSGordon Ross 	if (rc != 0)
161448cd229bSGordon Ross 		(*errors)++;
161548cd229bSGordon Ross 	if (pgcfg->name_cache_timeout == 0)
161648cd229bSGordon Ross 		pgcfg->name_cache_timeout = NAME_CACHE_TMO_DEFAULT;
161748cd229bSGordon Ross 
1618*b3700b07SGordon Ross 	rc = get_val_int(handles, "rediscovery_interval",
1619*b3700b07SGordon Ross 	    &pgcfg->rediscovery_interval, SCF_TYPE_COUNT);
1620*b3700b07SGordon Ross 	if (rc != 0)
1621*b3700b07SGordon Ross 		(*errors)++;
1622*b3700b07SGordon Ross 	if (pgcfg->rediscovery_interval == 0)
1623*b3700b07SGordon Ross 		pgcfg->rediscovery_interval = REDISCOVERY_INTERVAL_DEFAULT;
1624*b3700b07SGordon Ross 
1625c8e26105Sjp151216 	rc = get_val_astring(handles, "domain_name",
1626c8e26105Sjp151216 	    &pgcfg->domain_name);
1627e3c2d6aaSnw141292 	if (rc != 0)
1628e3f2c991SKeyur Desai 		(*errors)++;
16294d61c878SJulian Pullen 	else {
1630148c5f43SAlan Wright 		if (pgcfg->domain_name != NULL &&
1631148c5f43SAlan Wright 		    pgcfg->domain_name[0] == '\0') {
1632148c5f43SAlan Wright 			free(pgcfg->domain_name);
1633148c5f43SAlan Wright 			pgcfg->domain_name = NULL;
1634148c5f43SAlan Wright 		}
1635349d5d8fSnw141292 		(void) ad_disc_set_DomainName(handles->ad_ctx,
1636349d5d8fSnw141292 		    pgcfg->domain_name);
16377a8a68f5SJulian Pullen 		pgcfg->domain_name_auto_disc = B_FALSE;
16384d61c878SJulian Pullen 	}
1639c8e26105Sjp151216 
1640c8e26105Sjp151216 	rc = get_val_astring(handles, "default_domain",
1641c8e26105Sjp151216 	    &pgcfg->default_domain);
1642c8e26105Sjp151216 	if (rc != 0) {
1643e3c2d6aaSnw141292 		/*
1644e3c2d6aaSnw141292 		 * SCF failures fetching config/default_domain we treat
1645e3c2d6aaSnw141292 		 * as fatal as they may leave ID mapping rules that
1646e3c2d6aaSnw141292 		 * match unqualified winnames flapping in the wind.
1647e3c2d6aaSnw141292 		 */
1648349d5d8fSnw141292 		return (-2);
1649c8e26105Sjp151216 	}
1650c8e26105Sjp151216 
1651e3f2c991SKeyur Desai 	if (pgcfg->default_domain == NULL && pgcfg->domain_name != NULL) {
1652c8e26105Sjp151216 		pgcfg->default_domain = strdup(pgcfg->domain_name);
1653c8e26105Sjp151216 	}
1654c8e26105Sjp151216 
1655*b3700b07SGordon Ross 	rc = get_val_astring(handles, "domain_guid", &s);
1656*b3700b07SGordon Ross 	if (rc != 0) {
1657*b3700b07SGordon Ross 		(*errors)++;
1658*b3700b07SGordon Ross 	} else if (s == NULL || s[0] == '\0') {
1659*b3700b07SGordon Ross 		/* OK, not set. */
1660*b3700b07SGordon Ross 		free(s);
1661*b3700b07SGordon Ross 	} else {
1662*b3700b07SGordon Ross 		uuid_t u;
1663*b3700b07SGordon Ross 
1664*b3700b07SGordon Ross 		if (uuid_parse(s, u) != 0) {
1665*b3700b07SGordon Ross 			idmapdlog(LOG_ERR,
1666*b3700b07SGordon Ross 		"config/domain_guid: invalid value \"%s\" ignored", s);
1667*b3700b07SGordon Ross 			free(s);
1668*b3700b07SGordon Ross 			(*errors)++;
1669*b3700b07SGordon Ross 		} else {
1670*b3700b07SGordon Ross 			pgcfg->domain_guid = s;
1671*b3700b07SGordon Ross 			pgcfg->domain_guid_auto_disc = B_FALSE;
1672*b3700b07SGordon Ross 			(void) ad_disc_set_DomainGUID(handles->ad_ctx, u);
1673*b3700b07SGordon Ross 		}
1674*b3700b07SGordon Ross 	}
1675*b3700b07SGordon Ross 
167612b65585SGordon Ross 	rc = get_val_astring(handles, "machine_uuid", &pgcfg->machine_uuid);
167712b65585SGordon Ross 	if (rc != 0)
167812b65585SGordon Ross 		(*errors)++;
167912b65585SGordon Ross 	if (pgcfg->machine_uuid == NULL) {
168012b65585SGordon Ross 		/* If machine_uuid not configured, generate one */
168112b65585SGordon Ross 		if (generate_machine_uuid(&pgcfg->machine_uuid) < 0)
168212b65585SGordon Ross 			return (-2);
168312b65585SGordon Ross 		rc = set_val_astring(handles, handles->config_pg,
168412b65585SGordon Ross 		    "machine_uuid", pgcfg->machine_uuid);
168512b65585SGordon Ross 		if (rc != 0)
168612b65585SGordon Ross 			(*errors)++;
168712b65585SGordon Ross 	}
168812b65585SGordon Ross 
1689c8e26105Sjp151216 	rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid);
1690e3c2d6aaSnw141292 	if (rc != 0)
1691e3f2c991SKeyur Desai 		(*errors)++;
1692c8e26105Sjp151216 	if (pgcfg->machine_sid == NULL) {
169312b65585SGordon Ross 		/*
169412b65585SGordon Ross 		 * If machine_sid not configured, generate one
169512b65585SGordon Ross 		 * from the machine UUID.
169612b65585SGordon Ross 		 */
169712b65585SGordon Ross 		if (generate_machine_sid(&pgcfg->machine_sid,
169812b65585SGordon Ross 		    pgcfg->machine_uuid) < 0)
1699349d5d8fSnw141292 			return (-2);
1700148c5f43SAlan Wright 		rc = set_val_astring(handles, handles->config_pg,
1701148c5f43SAlan Wright 		    "machine_sid", pgcfg->machine_sid);
1702e3c2d6aaSnw141292 		if (rc != 0)
1703e3f2c991SKeyur Desai 			(*errors)++;
17048edda628Sbaban 	}
1705c5c4113dSnw141292 
1706c8e26105Sjp151216 	rc = get_val_ds(handles, "domain_controller", 389,
1707c8e26105Sjp151216 	    &pgcfg->domain_controller);
1708e3c2d6aaSnw141292 	if (rc != 0)
1709e3f2c991SKeyur Desai 		(*errors)++;
17104d61c878SJulian Pullen 	else {
1711349d5d8fSnw141292 		(void) ad_disc_set_DomainController(handles->ad_ctx,
1712e3c2d6aaSnw141292 		    pgcfg->domain_controller);
17137a8a68f5SJulian Pullen 		pgcfg->domain_controller_auto_disc = B_FALSE;
17144d61c878SJulian Pullen 	}
1715c5c4113dSnw141292 
1716*b3700b07SGordon Ross 	rc = get_val_ds(handles, "preferred_dc", 389,
1717*b3700b07SGordon Ross 	    &pgcfg->preferred_dc);
1718*b3700b07SGordon Ross 	if (rc != 0)
1719*b3700b07SGordon Ross 		(*errors)++;
1720*b3700b07SGordon Ross 	else {
1721*b3700b07SGordon Ross 		(void) ad_disc_set_PreferredDC(handles->ad_ctx,
1722*b3700b07SGordon Ross 		    pgcfg->preferred_dc);
1723*b3700b07SGordon Ross 		pgcfg->preferred_dc_auto_disc = B_FALSE;
1724*b3700b07SGordon Ross 	}
1725*b3700b07SGordon Ross 
1726c8e26105Sjp151216 	rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name);
1727e3c2d6aaSnw141292 	if (rc != 0)
1728e3f2c991SKeyur Desai 		(*errors)++;
17294d61c878SJulian Pullen 	else {
1730349d5d8fSnw141292 		(void) ad_disc_set_ForestName(handles->ad_ctx,
1731349d5d8fSnw141292 		    pgcfg->forest_name);
17327a8a68f5SJulian Pullen 		pgcfg->forest_name_auto_disc = B_FALSE;
17334d61c878SJulian Pullen 	}
1734c8e26105Sjp151216 
1735c8e26105Sjp151216 	rc = get_val_astring(handles, "site_name", &pgcfg->site_name);
1736e3c2d6aaSnw141292 	if (rc != 0)
1737e3f2c991SKeyur Desai 		(*errors)++;
1738e3c2d6aaSnw141292 	else
1739349d5d8fSnw141292 		(void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name);
1740c8e26105Sjp151216 
1741c8e26105Sjp151216 	rc = get_val_ds(handles, "global_catalog", 3268,
1742c8e26105Sjp151216 	    &pgcfg->global_catalog);
1743e3c2d6aaSnw141292 	if (rc != 0)
1744e3f2c991SKeyur Desai 		(*errors)++;
17454d61c878SJulian Pullen 	else {
1746349d5d8fSnw141292 		(void) ad_disc_set_GlobalCatalog(handles->ad_ctx,
1747349d5d8fSnw141292 		    pgcfg->global_catalog);
17487a8a68f5SJulian Pullen 		pgcfg->global_catalog_auto_disc = B_FALSE;
17494d61c878SJulian Pullen 	}
1750c8e26105Sjp151216 
1751e3f2c991SKeyur Desai 	/* Unless we're doing directory-based name mapping, we're done. */
1752e3f2c991SKeyur Desai 	if (pgcfg->directory_based_mapping != DIRECTORY_MAPPING_NAME)
1753e3f2c991SKeyur Desai 		return (0);
1754349d5d8fSnw141292 
1755e8c27ec8Sbaban 	rc = get_val_astring(handles, "ad_unixuser_attr",
1756e8c27ec8Sbaban 	    &pgcfg->ad_unixuser_attr);
1757349d5d8fSnw141292 	if (rc != 0)
1758349d5d8fSnw141292 		return (-2);
1759479ac375Sdm199847 	if (pgcfg->ad_unixuser_attr != NULL &&
1760479ac375Sdm199847 	    !valid_ldap_attr(pgcfg->ad_unixuser_attr)) {
1761479ac375Sdm199847 		idmapdlog(LOG_ERR, "config/ad_unixuser_attr=%s is not a "
1762479ac375Sdm199847 		    "valid LDAP attribute name", pgcfg->ad_unixuser_attr);
1763479ac375Sdm199847 		return (-3);
1764479ac375Sdm199847 	}
1765e8c27ec8Sbaban 
1766e8c27ec8Sbaban 	rc = get_val_astring(handles, "ad_unixgroup_attr",
1767e8c27ec8Sbaban 	    &pgcfg->ad_unixgroup_attr);
1768349d5d8fSnw141292 	if (rc != 0)
1769349d5d8fSnw141292 		return (-2);
1770479ac375Sdm199847 	if (pgcfg->ad_unixgroup_attr != NULL &&
1771479ac375Sdm199847 	    !valid_ldap_attr(pgcfg->ad_unixgroup_attr)) {
1772479ac375Sdm199847 		idmapdlog(LOG_ERR, "config/ad_unixgroup_attr=%s is not a "
1773479ac375Sdm199847 		    "valid LDAP attribute name", pgcfg->ad_unixgroup_attr);
1774479ac375Sdm199847 		return (-3);
1775479ac375Sdm199847 	}
1776e8c27ec8Sbaban 
1777e8c27ec8Sbaban 	rc = get_val_astring(handles, "nldap_winname_attr",
1778e8c27ec8Sbaban 	    &pgcfg->nldap_winname_attr);
1779349d5d8fSnw141292 	if (rc != 0)
1780349d5d8fSnw141292 		return (-2);
1781479ac375Sdm199847 	if (pgcfg->nldap_winname_attr != NULL &&
1782479ac375Sdm199847 	    !valid_ldap_attr(pgcfg->nldap_winname_attr)) {
1783479ac375Sdm199847 		idmapdlog(LOG_ERR, "config/nldap_winname_attr=%s is not a "
1784479ac375Sdm199847 		    "valid LDAP attribute name", pgcfg->nldap_winname_attr);
1785349d5d8fSnw141292 		return (-3);
1786e8c27ec8Sbaban 	}
1787e8c27ec8Sbaban 	if (pgcfg->ad_unixuser_attr == NULL &&
1788479ac375Sdm199847 	    pgcfg->ad_unixgroup_attr == NULL &&
1789479ac375Sdm199847 	    pgcfg->nldap_winname_attr == NULL) {
1790e8c27ec8Sbaban 		idmapdlog(LOG_ERR,
1791e3f2c991SKeyur Desai 		    "If config/directory_based_mapping property is set to "
1792e3f2c991SKeyur Desai 		    "\"name\" then at least one of the following name mapping "
1793349d5d8fSnw141292 		    "attributes must be specified. (config/ad_unixuser_attr OR "
1794479ac375Sdm199847 		    "config/ad_unixgroup_attr OR config/nldap_winname_attr)");
1795349d5d8fSnw141292 		return (-3);
1796e8c27ec8Sbaban 	}
1797e8c27ec8Sbaban 
1798349d5d8fSnw141292 	return (rc);
1799349d5d8fSnw141292 }
1800e3c2d6aaSnw141292 
1801349d5d8fSnw141292 static
1802349d5d8fSnw141292 void
1803148c5f43SAlan Wright log_if_unable(const void *val, const char *what)
1804349d5d8fSnw141292 {
1805148c5f43SAlan Wright 	if (val == NULL) {
1806148c5f43SAlan Wright 		idmapdlog(LOG_DEBUG, "unable to discover %s", what);
1807148c5f43SAlan Wright 	}
1808148c5f43SAlan Wright }
1809148c5f43SAlan Wright 
1810148c5f43SAlan Wright static
1811148c5f43SAlan Wright void
1812148c5f43SAlan Wright discover_trusted_domains(idmap_pg_config_t *pgcfg, ad_disc_t ad_ctx)
1813148c5f43SAlan Wright {
18144d61c878SJulian Pullen 	ad_disc_t trusted_ctx;
18154d61c878SJulian Pullen 	int i, j, k, l;
18164d61c878SJulian Pullen 	char *forestname;
18174d61c878SJulian Pullen 	int num_trusteddomains;
18187a8a68f5SJulian Pullen 	boolean_t new_forest;
18194d61c878SJulian Pullen 	char *trusteddomain;
1820*b3700b07SGordon Ross 	ad_disc_ds_t *globalcatalog;
18214d61c878SJulian Pullen 	idmap_trustedforest_t *trustedforests;
18224d61c878SJulian Pullen 	ad_disc_domainsinforest_t *domainsinforest;
1823349d5d8fSnw141292 
18244d61c878SJulian Pullen 	pgcfg->trusted_domains =
18254d61c878SJulian Pullen 	    ad_disc_get_TrustedDomains(ad_ctx, NULL);
18264d61c878SJulian Pullen 
18274d61c878SJulian Pullen 	if (pgcfg->forest_name != NULL && pgcfg->trusted_domains != NULL &&
18284d61c878SJulian Pullen 	    pgcfg->trusted_domains[0].domain[0] != '\0') {
18294d61c878SJulian Pullen 		/*
18304d61c878SJulian Pullen 		 * We have trusted domains.  We need to go through every
18314d61c878SJulian Pullen 		 * one and find its forest. If it is a new forest we then need
18324d61c878SJulian Pullen 		 * to find its Global Catalog and the domains in the forest
18334d61c878SJulian Pullen 		 */
18344d61c878SJulian Pullen 		for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++)
18354d61c878SJulian Pullen 			continue;
18364d61c878SJulian Pullen 		num_trusteddomains = i;
18374d61c878SJulian Pullen 
18384d61c878SJulian Pullen 		trustedforests = calloc(num_trusteddomains,
18394d61c878SJulian Pullen 		    sizeof (idmap_trustedforest_t));
18404d61c878SJulian Pullen 		j = 0;
18414d61c878SJulian Pullen 		for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) {
18424d61c878SJulian Pullen 			trusteddomain = pgcfg->trusted_domains[i].domain;
18434d61c878SJulian Pullen 			trusted_ctx = ad_disc_init();
1844148c5f43SAlan Wright 			(void) ad_disc_set_DomainName(trusted_ctx,
18454d61c878SJulian Pullen 			    trusteddomain);
18464d61c878SJulian Pullen 			forestname =
18474d61c878SJulian Pullen 			    ad_disc_get_ForestName(trusted_ctx, NULL);
18484d61c878SJulian Pullen 			if (forestname == NULL) {
1849148c5f43SAlan Wright 				if (DBG(CONFIG, 1)) {
1850148c5f43SAlan Wright 					idmapdlog(LOG_DEBUG,
1851148c5f43SAlan Wright 					    "unable to discover Forest Name"
1852148c5f43SAlan Wright 					    " for the trusted domain %s",
18534d61c878SJulian Pullen 					    trusteddomain);
1854148c5f43SAlan Wright 				}
18554d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
18564d61c878SJulian Pullen 				continue;
18574d61c878SJulian Pullen 			}
18584d61c878SJulian Pullen 
18594d61c878SJulian Pullen 			if (strcasecmp(forestname, pgcfg->forest_name) == 0) {
18604d61c878SJulian Pullen 				/*
18614d61c878SJulian Pullen 				 * Ignore the domain as it is part of
18624d61c878SJulian Pullen 				 * the primary forest
18634d61c878SJulian Pullen 				 */
18644d61c878SJulian Pullen 				free(forestname);
18654d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
18664d61c878SJulian Pullen 				continue;
18674d61c878SJulian Pullen 			}
18684d61c878SJulian Pullen 
18694d61c878SJulian Pullen 			/* Is this a new forest? */
18707a8a68f5SJulian Pullen 			new_forest = B_TRUE;
18714d61c878SJulian Pullen 			for (k = 0; k < j; k++) {
18724d61c878SJulian Pullen 				if (strcasecmp(forestname,
18734d61c878SJulian Pullen 				    trustedforests[k].forest_name) == 0) {
18747a8a68f5SJulian Pullen 					new_forest = B_FALSE;
18754d61c878SJulian Pullen 					domainsinforest =
18764d61c878SJulian Pullen 					    trustedforests[k].domains_in_forest;
18774d61c878SJulian Pullen 					break;
18784d61c878SJulian Pullen 				}
18794d61c878SJulian Pullen 			}
18804d61c878SJulian Pullen 			if (!new_forest) {
18814d61c878SJulian Pullen 				/* Mark the domain as trusted */
18824d61c878SJulian Pullen 				for (l = 0;
18834d61c878SJulian Pullen 				    domainsinforest[l].domain[0] != '\0'; l++) {
18841fcced4cSJordan Brown 					if (domain_eq(trusteddomain,
18851fcced4cSJordan Brown 					    domainsinforest[l].domain)) {
18864d61c878SJulian Pullen 						domainsinforest[l].trusted =
18874d61c878SJulian Pullen 						    TRUE;
18884d61c878SJulian Pullen 						break;
18894d61c878SJulian Pullen 					}
18904d61c878SJulian Pullen 				}
18914d61c878SJulian Pullen 				free(forestname);
18924d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
18934d61c878SJulian Pullen 				continue;
18944d61c878SJulian Pullen 			}
18954d61c878SJulian Pullen 
18964d61c878SJulian Pullen 			/*
18974d61c878SJulian Pullen 			 * Get the Global Catalog and the domains in
18984d61c878SJulian Pullen 			 * this new forest.
18994d61c878SJulian Pullen 			 */
19004d61c878SJulian Pullen 			globalcatalog =
19014d61c878SJulian Pullen 			    ad_disc_get_GlobalCatalog(trusted_ctx,
19024d61c878SJulian Pullen 			    AD_DISC_PREFER_SITE, NULL);
19034d61c878SJulian Pullen 			if (globalcatalog == NULL) {
1904148c5f43SAlan Wright 				if (DBG(CONFIG, 1)) {
19054d61c878SJulian Pullen 					idmapdlog(LOG_DEBUG,
1906148c5f43SAlan Wright 					    "unable to discover Global Catalog"
1907148c5f43SAlan Wright 					    " for the trusted domain %s",
19084d61c878SJulian Pullen 					    trusteddomain);
1909148c5f43SAlan Wright 				}
19104d61c878SJulian Pullen 				free(forestname);
19114d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
19124d61c878SJulian Pullen 				continue;
19134d61c878SJulian Pullen 			}
19144d61c878SJulian Pullen 			domainsinforest =
1915*b3700b07SGordon Ross 			    ad_disc_get_DomainsInForest(trusted_ctx, NULL);
19164d61c878SJulian Pullen 			if (domainsinforest == NULL) {
1917148c5f43SAlan Wright 				if (DBG(CONFIG, 1)) {
19184d61c878SJulian Pullen 					idmapdlog(LOG_DEBUG,
1919148c5f43SAlan Wright 					    "unable to discover Domains in the"
1920148c5f43SAlan Wright 					    " Forest for the trusted domain %s",
19214d61c878SJulian Pullen 					    trusteddomain);
1922148c5f43SAlan Wright 				}
19234d61c878SJulian Pullen 				free(globalcatalog);
19244d61c878SJulian Pullen 				free(forestname);
19254d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
19264d61c878SJulian Pullen 				continue;
19274d61c878SJulian Pullen 			}
19284d61c878SJulian Pullen 
19294d61c878SJulian Pullen 			trustedforests[j].forest_name = forestname;
19304d61c878SJulian Pullen 			trustedforests[j].global_catalog = globalcatalog;
19314d61c878SJulian Pullen 			trustedforests[j].domains_in_forest = domainsinforest;
19324d61c878SJulian Pullen 			j++;
19334d61c878SJulian Pullen 			/* Mark the domain as trusted */
19344d61c878SJulian Pullen 			for (l = 0; domainsinforest[l].domain[0] != '\0';
19354d61c878SJulian Pullen 			    l++) {
19361fcced4cSJordan Brown 				if (domain_eq(trusteddomain,
19371fcced4cSJordan Brown 				    domainsinforest[l].domain)) {
19384d61c878SJulian Pullen 					domainsinforest[l].trusted = TRUE;
19394d61c878SJulian Pullen 					break;
19404d61c878SJulian Pullen 				}
19414d61c878SJulian Pullen 			}
19424d61c878SJulian Pullen 			ad_disc_fini(trusted_ctx);
19434d61c878SJulian Pullen 		}
19444d61c878SJulian Pullen 		if (j > 0) {
19454d61c878SJulian Pullen 			pgcfg->num_trusted_forests = j;
19464d61c878SJulian Pullen 			pgcfg->trusted_forests = trustedforests;
19471fcced4cSJordan Brown 		} else {
19481fcced4cSJordan Brown 			free(trustedforests);
19494d61c878SJulian Pullen 		}
19504d61c878SJulian Pullen 	}
1951148c5f43SAlan Wright }
1952349d5d8fSnw141292 
1953148c5f43SAlan Wright /*
1954148c5f43SAlan Wright  * This is the half of idmap_cfg_load() that auto-discovers values of
1955148c5f43SAlan Wright  * discoverable properties that weren't already set via SMF properties.
1956148c5f43SAlan Wright  *
1957148c5f43SAlan Wright  * idmap_cfg_discover() is called *after* idmap_cfg_load_smf(), so it
1958148c5f43SAlan Wright  * needs to be careful not to overwrite any properties set in SMF.
1959148c5f43SAlan Wright  */
1960*b3700b07SGordon Ross static void
1961*b3700b07SGordon Ross idmap_cfg_discover1(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
1962148c5f43SAlan Wright {
1963148c5f43SAlan Wright 	ad_disc_t ad_ctx = handles->ad_ctx;
1964*b3700b07SGordon Ross 	FILE *status_fp = NULL;
1965*b3700b07SGordon Ross 	time_t t0, t1;
1966148c5f43SAlan Wright 
1967*b3700b07SGordon Ross 	t0 = time(NULL);
19681ed6b69aSGordon Ross 	if (DBG(CONFIG, 1))
1969*b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "Running domain discovery.");
1970*b3700b07SGordon Ross 
1971*b3700b07SGordon Ross 	(void) unlink(IDMAP_CACHEDIR "/discovery.log");
1972*b3700b07SGordon Ross 	status_fp = fopen(IDMAP_CACHEDIR "/discovery.log", "w");
1973*b3700b07SGordon Ross 	if (status_fp) {
1974*b3700b07SGordon Ross 		(void) fchmod(fileno(status_fp), 0644);
1975*b3700b07SGordon Ross 		ad_disc_set_StatusFP(ad_ctx, status_fp);
19761ed6b69aSGordon Ross 	}
19771ed6b69aSGordon Ross 
1978148c5f43SAlan Wright 	if (pgcfg->domain_name == NULL) {
1979148c5f43SAlan Wright 		idmapdlog(LOG_DEBUG, "No domain name specified.");
1980*b3700b07SGordon Ross 		if (status_fp)
1981*b3700b07SGordon Ross 			(void) fprintf(status_fp, "(no domain name)\n");
1982*b3700b07SGordon Ross 		goto out;
1983*b3700b07SGordon Ross 	}
1984*b3700b07SGordon Ross 
1985349d5d8fSnw141292 	if (pgcfg->domain_controller == NULL)
1986148c5f43SAlan Wright 		pgcfg->domain_controller =
1987148c5f43SAlan Wright 		    ad_disc_get_DomainController(ad_ctx,
1988148c5f43SAlan Wright 		    AD_DISC_PREFER_SITE,
1989148c5f43SAlan Wright 		    &pgcfg->domain_controller_auto_disc);
1990148c5f43SAlan Wright 
1991*b3700b07SGordon Ross 	if (pgcfg->domain_guid == NULL) {
1992*b3700b07SGordon Ross 		char buf[UUID_PRINTABLE_STRING_LENGTH];
1993*b3700b07SGordon Ross 		uchar_t *u = ad_disc_get_DomainGUID(ad_ctx,
1994*b3700b07SGordon Ross 		    &pgcfg->domain_guid_auto_disc);
1995*b3700b07SGordon Ross 		(void) memset(buf, 0, sizeof (buf));
1996*b3700b07SGordon Ross 		if (u != NULL) {
1997*b3700b07SGordon Ross 			uuid_unparse(u, buf);
1998*b3700b07SGordon Ross 			pgcfg->domain_guid = strdup(buf);
1999*b3700b07SGordon Ross 		}
2000*b3700b07SGordon Ross 	}
2001*b3700b07SGordon Ross 
2002349d5d8fSnw141292 	if (pgcfg->forest_name == NULL)
2003148c5f43SAlan Wright 		pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx,
2004148c5f43SAlan Wright 		    &pgcfg->forest_name_auto_disc);
2005148c5f43SAlan Wright 
2006349d5d8fSnw141292 	if (pgcfg->site_name == NULL)
2007148c5f43SAlan Wright 		pgcfg->site_name = ad_disc_get_SiteName(ad_ctx,
2008148c5f43SAlan Wright 		    &pgcfg->site_name_auto_disc);
2009148c5f43SAlan Wright 
2010*b3700b07SGordon Ross 	if (DBG(CONFIG, 1)) {
2011*b3700b07SGordon Ross 		log_if_unable(pgcfg->domain_name, "Domain Name");
2012*b3700b07SGordon Ross 		log_if_unable(pgcfg->domain_controller,
2013*b3700b07SGordon Ross 		    "Domain Controller");
2014*b3700b07SGordon Ross 		log_if_unable(pgcfg->domain_guid, "Domain GUID");
2015*b3700b07SGordon Ross 		log_if_unable(pgcfg->forest_name, "Forest Name");
2016*b3700b07SGordon Ross 		log_if_unable(pgcfg->site_name, "Site Name");
2017*b3700b07SGordon Ross 	}
2018*b3700b07SGordon Ross 
2019*b3700b07SGordon Ross out:
2020*b3700b07SGordon Ross 	if (status_fp) {
2021*b3700b07SGordon Ross 		ad_disc_set_StatusFP(ad_ctx, NULL);
2022*b3700b07SGordon Ross 		(void) fclose(status_fp);
2023*b3700b07SGordon Ross 		status_fp = NULL;
2024*b3700b07SGordon Ross 	}
2025*b3700b07SGordon Ross 
2026*b3700b07SGordon Ross 	if (DBG(CONFIG, 1))
2027*b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "Domain discovery done.");
2028*b3700b07SGordon Ross 
2029*b3700b07SGordon Ross 	/*
2030*b3700b07SGordon Ross 	 * Log when this took more than 15 sec.
2031*b3700b07SGordon Ross 	 */
2032*b3700b07SGordon Ross 	t1 = time(NULL);
2033*b3700b07SGordon Ross 	if (t1 > (t0 + 15)) {
2034*b3700b07SGordon Ross 		idmapdlog(LOG_NOTICE, "Domain discovery took %d sec.",
2035*b3700b07SGordon Ross 		    (int)(t1 - t0));
2036*b3700b07SGordon Ross 		idmapdlog(LOG_NOTICE, "Check the DNS configuration.");
2037*b3700b07SGordon Ross 	}
2038*b3700b07SGordon Ross }
2039*b3700b07SGordon Ross 
2040*b3700b07SGordon Ross /*
2041*b3700b07SGordon Ross  * This is the second part of discovery, which can take a while.
2042*b3700b07SGordon Ross  * We don't want to hold up parties who just want to know what
2043*b3700b07SGordon Ross  * domain controller we're using (like smbd), so this part runs
2044*b3700b07SGordon Ross  * after we've updated that info in the "live" config and told
2045*b3700b07SGordon Ross  * such consumers to go ahead.
2046*b3700b07SGordon Ross  *
2047*b3700b07SGordon Ross  * This is a lot like idmap_cfg_discover(), but used LDAP queries
2048*b3700b07SGordon Ross  * get the forest information from the global catalog servers.
2049*b3700b07SGordon Ross  *
2050*b3700b07SGordon Ross  * Note: the previous update_* calls have usually nuked any
2051*b3700b07SGordon Ross  * useful information from pgcfg before we get here, so we
2052*b3700b07SGordon Ross  * can only use it store discovery results, not to read.
2053*b3700b07SGordon Ross  */
2054*b3700b07SGordon Ross static void
2055*b3700b07SGordon Ross idmap_cfg_discover2(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
2056*b3700b07SGordon Ross {
2057*b3700b07SGordon Ross 	ad_disc_t ad_ctx = handles->ad_ctx;
2058*b3700b07SGordon Ross 	FILE *status_fp = NULL;
2059*b3700b07SGordon Ross 	time_t t0, t1;
2060*b3700b07SGordon Ross 
2061*b3700b07SGordon Ross 	t0 = time(NULL);
2062*b3700b07SGordon Ross 	if (DBG(CONFIG, 1))
2063*b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "Running forest discovery.");
2064*b3700b07SGordon Ross 
2065*b3700b07SGordon Ross 	status_fp = fopen(IDMAP_CACHEDIR "/discovery.log", "a");
2066*b3700b07SGordon Ross 	if (status_fp)
2067*b3700b07SGordon Ross 		ad_disc_set_StatusFP(ad_ctx, status_fp);
2068*b3700b07SGordon Ross 
2069349d5d8fSnw141292 	if (pgcfg->global_catalog == NULL)
2070148c5f43SAlan Wright 		pgcfg->global_catalog =
2071148c5f43SAlan Wright 		    ad_disc_get_GlobalCatalog(ad_ctx,
2072148c5f43SAlan Wright 		    AD_DISC_PREFER_SITE,
2073148c5f43SAlan Wright 		    &pgcfg->global_catalog_auto_disc);
2074148c5f43SAlan Wright 
2075*b3700b07SGordon Ross 	if (pgcfg->global_catalog != NULL) {
2076148c5f43SAlan Wright 		pgcfg->domains_in_forest =
2077148c5f43SAlan Wright 		    ad_disc_get_DomainsInForest(ad_ctx, NULL);
2078148c5f43SAlan Wright 
2079148c5f43SAlan Wright 		if (!pgcfg->disable_cross_forest_trusts)
2080148c5f43SAlan Wright 			discover_trusted_domains(pgcfg, ad_ctx);
2081*b3700b07SGordon Ross 	}
2082148c5f43SAlan Wright 
2083148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
2084148c5f43SAlan Wright 		log_if_unable(pgcfg->global_catalog, "Global Catalog");
2085148c5f43SAlan Wright 		log_if_unable(pgcfg->domains_in_forest,
2086148c5f43SAlan Wright 		    "Domains in the Forest");
2087*b3700b07SGordon Ross 		/* Empty trusted domains list is OK. */
2088148c5f43SAlan Wright 	}
2089c5866007SKeyur Desai 
2090*b3700b07SGordon Ross 	if (status_fp) {
2091*b3700b07SGordon Ross 		ad_disc_set_StatusFP(ad_ctx, NULL);
2092*b3700b07SGordon Ross 		(void) fclose(status_fp);
2093*b3700b07SGordon Ross 		status_fp = NULL;
2094*b3700b07SGordon Ross 	}
2095148c5f43SAlan Wright 
2096148c5f43SAlan Wright 	if (DBG(CONFIG, 1))
2097*b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "Forest discovery done.");
2098*b3700b07SGordon Ross 
2099*b3700b07SGordon Ross 	/*
2100*b3700b07SGordon Ross 	 * Log when this took more than 30 sec.
2101*b3700b07SGordon Ross 	 */
2102*b3700b07SGordon Ross 	t1 = time(NULL);
2103*b3700b07SGordon Ross 	if (t1 > (t0 + 30)) {
2104*b3700b07SGordon Ross 		idmapdlog(LOG_NOTICE, "Forest discovery took %d sec.",
2105*b3700b07SGordon Ross 		    (int)(t1 - t0));
2106*b3700b07SGordon Ross 		idmapdlog(LOG_NOTICE, "Check AD join status.");
2107*b3700b07SGordon Ross 	}
2108c8e26105Sjp151216 }
2109e3c2d6aaSnw141292 
21104d61c878SJulian Pullen 
2111349d5d8fSnw141292 /*
2112349d5d8fSnw141292  * idmap_cfg_load() is called at startup, and periodically via the
2113349d5d8fSnw141292  * update thread when the auto-discovery TTLs expire, as well as part of
2114349d5d8fSnw141292  * the refresh method, to update the current configuration.  It always
2115349d5d8fSnw141292  * reads from SMF, but you still have to refresh the service after
2116349d5d8fSnw141292  * changing the config pg in order for the changes to take effect.
2117349d5d8fSnw141292  *
2118148c5f43SAlan Wright  * There is one flag:
2119349d5d8fSnw141292  *
2120349d5d8fSnw141292  *  - CFG_DISCOVER
2121349d5d8fSnw141292  *
2122349d5d8fSnw141292  * If CFG_DISCOVER is set then idmap_cfg_load() calls
2123349d5d8fSnw141292  * idmap_cfg_discover() to discover, via DNS and LDAP lookups, property
2124349d5d8fSnw141292  * values that weren't set in SMF.
2125349d5d8fSnw141292  *
2126148c5f43SAlan Wright  * idmap_cfg_load() will log (to LOG_NOTICE) whether the configuration
2127148c5f43SAlan Wright  * changed.
2128349d5d8fSnw141292  *
2129349d5d8fSnw141292  * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
2130349d5d8fSnw141292  * reading from SMF.
2131349d5d8fSnw141292  */
2132349d5d8fSnw141292 int
2133349d5d8fSnw141292 idmap_cfg_load(idmap_cfg_t *cfg, int flags)
2134349d5d8fSnw141292 {
2135*b3700b07SGordon Ross 	const ad_disc_t ad_ctx = cfg->handles.ad_ctx;
2136349d5d8fSnw141292 	int rc = 0;
2137e3f2c991SKeyur Desai 	int errors;
2138349d5d8fSnw141292 	int changed = 0;
2139*b3700b07SGordon Ross 	int dc_changed = 0;
21404d61c878SJulian Pullen 	int ad_reload_required = 0;
2141349d5d8fSnw141292 	idmap_pg_config_t new_pgcfg, *live_pgcfg;
2142349d5d8fSnw141292 
2143148c5f43SAlan Wright 	if (DBG(CONFIG, 1))
2144148c5f43SAlan Wright 		idmapdlog(LOG_DEBUG, "Loading configuration.");
2145148c5f43SAlan Wright 
2146349d5d8fSnw141292 	live_pgcfg = &cfg->pgcfg;
2147349d5d8fSnw141292 	(void) memset(&new_pgcfg, 0, sizeof (new_pgcfg));
2148349d5d8fSnw141292 
2149148c5f43SAlan Wright 	(void) pthread_mutex_lock(&cfg->handles.mutex);
2150349d5d8fSnw141292 
2151349d5d8fSnw141292 	if ((rc = idmap_cfg_load_smf(&cfg->handles, &new_pgcfg, &errors)) < -1)
2152349d5d8fSnw141292 		goto err;
2153349d5d8fSnw141292 
2154*b3700b07SGordon Ross 	if (flags & CFG_DISCOVER) {
2155*b3700b07SGordon Ross 
2156*b3700b07SGordon Ross 		ad_disc_refresh(ad_ctx);
2157*b3700b07SGordon Ross 
2158*b3700b07SGordon Ross 		/*
2159*b3700b07SGordon Ross 		 * Unless we've been asked to forget the current DC,
2160*b3700b07SGordon Ross 		 * give preference (in order) to the preferred DC if
2161*b3700b07SGordon Ross 		 * configured, or the current DC.  These preferences
2162*b3700b07SGordon Ross 		 * reduce undesirable DC changes.
2163*b3700b07SGordon Ross 		 */
2164*b3700b07SGordon Ross 		if (flags & CFG_FORGET_DC) {
2165*b3700b07SGordon Ross 			(void) ad_disc_set_PreferredDC(ad_ctx, NULL);
2166*b3700b07SGordon Ross 		} else if (new_pgcfg.preferred_dc != NULL) {
2167*b3700b07SGordon Ross 			(void) ad_disc_set_PreferredDC(ad_ctx,
2168*b3700b07SGordon Ross 			    new_pgcfg.preferred_dc);
2169*b3700b07SGordon Ross 		} else if (live_pgcfg->domain_controller != NULL) {
2170*b3700b07SGordon Ross 			(void) ad_disc_set_PreferredDC(ad_ctx,
2171*b3700b07SGordon Ross 			    live_pgcfg->domain_controller);
2172*b3700b07SGordon Ross 		} else {
2173*b3700b07SGordon Ross 			(void) ad_disc_set_PreferredDC(ad_ctx, NULL);
2174*b3700b07SGordon Ross 		}
2175*b3700b07SGordon Ross 
2176*b3700b07SGordon Ross 		/*
2177*b3700b07SGordon Ross 		 * We want a way to tell adspriv_getdcname_1_svc()
2178*b3700b07SGordon Ross 		 * (and others) that discovery is running and therefore
2179*b3700b07SGordon Ross 		 * they may want to wait a bit or return an error...
2180*b3700b07SGordon Ross 		 */
2181*b3700b07SGordon Ross 		(void) mutex_lock(&_idmapdstate.addisc_lk);
2182*b3700b07SGordon Ross 		_idmapdstate.addisc_st |= ADDISC_ST_RUNNING;
2183*b3700b07SGordon Ross 		(void) mutex_unlock(&_idmapdstate.addisc_lk);
2184*b3700b07SGordon Ross 
2185*b3700b07SGordon Ross 		idmap_cfg_discover1(&cfg->handles, &new_pgcfg);
2186349d5d8fSnw141292 
2187349d5d8fSnw141292 		WRLOCK_CONFIG();
2188*b3700b07SGordon Ross 		(void) mutex_lock(&_idmapdstate.addisc_lk);
2189*b3700b07SGordon Ross 		_idmapdstate.addisc_st = 0;
2190*b3700b07SGordon Ross 		(void) cond_broadcast(&_idmapdstate.addisc_cv);
2191*b3700b07SGordon Ross 		(void) mutex_unlock(&_idmapdstate.addisc_lk);
2192*b3700b07SGordon Ross 	} else {
2193*b3700b07SGordon Ross 		WRLOCK_CONFIG();
2194*b3700b07SGordon Ross 	}
2195*b3700b07SGordon Ross 
2196349d5d8fSnw141292 	/* Non-discoverable props updated here */
219748cd229bSGordon Ross 
219848cd229bSGordon Ross 	changed += update_uint64(&live_pgcfg->list_size_limit,
219948cd229bSGordon Ross 	    &new_pgcfg.list_size_limit, "list_size_limit");
220048cd229bSGordon Ross 
220148cd229bSGordon Ross 	changed += update_uint64(&live_pgcfg->id_cache_timeout,
220248cd229bSGordon Ross 	    &new_pgcfg.id_cache_timeout, "id_cache_timeout");
220348cd229bSGordon Ross 
220448cd229bSGordon Ross 	changed += update_uint64(&live_pgcfg->name_cache_timeout,
220548cd229bSGordon Ross 	    &new_pgcfg.name_cache_timeout, "name_cache_timeout");
220648cd229bSGordon Ross 
2207*b3700b07SGordon Ross 	changed += update_uint64(&live_pgcfg->rediscovery_interval,
2208*b3700b07SGordon Ross 	    &new_pgcfg.rediscovery_interval, "rediscovery_interval");
2209*b3700b07SGordon Ross 
22104aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->machine_sid,
2211349d5d8fSnw141292 	    &new_pgcfg.machine_sid, "machine_sid");
2212349d5d8fSnw141292 
22134aa0a5e7Snw141292 	changed += update_bool(&live_pgcfg->eph_map_unres_sids,
22144aa0a5e7Snw141292 	    &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping");
22154aa0a5e7Snw141292 
22161ed6b69aSGordon Ross 	changed += update_bool(&live_pgcfg->use_ads,
22171ed6b69aSGordon Ross 	    &new_pgcfg.use_ads, "use_ads");
22181ed6b69aSGordon Ross 
2219148c5f43SAlan Wright 	changed += update_bool(&live_pgcfg->use_lsa,
2220148c5f43SAlan Wright 	    &new_pgcfg.use_lsa, "use_lsa");
2221148c5f43SAlan Wright 
2222148c5f43SAlan Wright 	changed += update_bool(&live_pgcfg->disable_cross_forest_trusts,
2223148c5f43SAlan Wright 	    &new_pgcfg.disable_cross_forest_trusts,
2224148c5f43SAlan Wright 	    "disable_cross_forest_trusts");
2225148c5f43SAlan Wright 
2226e3f2c991SKeyur Desai 	changed += update_enum(&live_pgcfg->directory_based_mapping,
2227e3f2c991SKeyur Desai 	    &new_pgcfg.directory_based_mapping, "directory_based_mapping",
2228e3f2c991SKeyur Desai 	    directory_mapping_map);
2229349d5d8fSnw141292 
22304aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->ad_unixuser_attr,
2231349d5d8fSnw141292 	    &new_pgcfg.ad_unixuser_attr, "ad_unixuser_attr");
2232349d5d8fSnw141292 
22334aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->ad_unixgroup_attr,
2234349d5d8fSnw141292 	    &new_pgcfg.ad_unixgroup_attr, "ad_unixgroup_attr");
2235349d5d8fSnw141292 
22364aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->nldap_winname_attr,
2237349d5d8fSnw141292 	    &new_pgcfg.nldap_winname_attr, "nldap_winname_attr");
2238349d5d8fSnw141292 
22394aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->default_domain,
2240349d5d8fSnw141292 	    &new_pgcfg.default_domain, "default_domain");
2241349d5d8fSnw141292 
2242*b3700b07SGordon Ross 	changed += update_dirs(&live_pgcfg->preferred_dc,
2243*b3700b07SGordon Ross 	    &new_pgcfg.preferred_dc, "preferred_dc");
2244*b3700b07SGordon Ross 
2245*b3700b07SGordon Ross 	/* Props that can be discovered or set in SMF updated here */
2246*b3700b07SGordon Ross 
2247*b3700b07SGordon Ross 	if (update_string(&live_pgcfg->domain_name,
2248*b3700b07SGordon Ross 	    &new_pgcfg.domain_name, "domain_name")) {
2249*b3700b07SGordon Ross 		changed++;
2250*b3700b07SGordon Ross 		ad_reload_required = TRUE;
2251*b3700b07SGordon Ross 		idmapd_set_krb5_realm(live_pgcfg->domain_name);
2252*b3700b07SGordon Ross 	}
22534d61c878SJulian Pullen 	live_pgcfg->domain_name_auto_disc = new_pgcfg.domain_name_auto_disc;
2254349d5d8fSnw141292 
2255*b3700b07SGordon Ross 	changed += update_string(&live_pgcfg->domain_guid,
2256*b3700b07SGordon Ross 	    &new_pgcfg.domain_guid, "domain_guid");
2257*b3700b07SGordon Ross 	live_pgcfg->domain_guid_auto_disc = new_pgcfg.domain_guid_auto_disc;
2258*b3700b07SGordon Ross 
2259*b3700b07SGordon Ross 	dc_changed = update_dirs(&live_pgcfg->domain_controller,
2260349d5d8fSnw141292 	    &new_pgcfg.domain_controller, "domain_controller");
2261*b3700b07SGordon Ross 	changed += dc_changed;
22624d61c878SJulian Pullen 	live_pgcfg->domain_controller_auto_disc =
22634d61c878SJulian Pullen 	    new_pgcfg.domain_controller_auto_disc;
2264349d5d8fSnw141292 
22654aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->forest_name,
2266349d5d8fSnw141292 	    &new_pgcfg.forest_name, "forest_name");
22674d61c878SJulian Pullen 	live_pgcfg->forest_name_auto_disc = new_pgcfg.forest_name_auto_disc;
2268349d5d8fSnw141292 
22694aa0a5e7Snw141292 	changed += update_string(&live_pgcfg->site_name,
2270349d5d8fSnw141292 	    &new_pgcfg.site_name, "site_name");
22714d61c878SJulian Pullen 	live_pgcfg->site_name_auto_disc = new_pgcfg.site_name_auto_disc;
2272349d5d8fSnw141292 
2273*b3700b07SGordon Ross 	if (DBG(CONFIG, 1)) {
2274*b3700b07SGordon Ross 		if (changed)
2275*b3700b07SGordon Ross 			idmapdlog(LOG_NOTICE, "Configuration changed");
2276*b3700b07SGordon Ross 		else
2277*b3700b07SGordon Ross 			idmapdlog(LOG_NOTICE, "Configuration unchanged");
2278349d5d8fSnw141292 	}
2279*b3700b07SGordon Ross 
2280*b3700b07SGordon Ross 	UNLOCK_CONFIG();
2281*b3700b07SGordon Ross 
2282*b3700b07SGordon Ross 	if (dc_changed != 0) {
2283*b3700b07SGordon Ross 		notify_dc_changed();
2284*b3700b07SGordon Ross 	}
2285*b3700b07SGordon Ross 
2286*b3700b07SGordon Ross 	/*
2287*b3700b07SGordon Ross 	 * Discovery2 can take a while.
2288*b3700b07SGordon Ross 	 */
2289*b3700b07SGordon Ross 	if (flags & CFG_DISCOVER) {
2290*b3700b07SGordon Ross 		if (live_pgcfg->domain_name != NULL &&
2291*b3700b07SGordon Ross 		    live_pgcfg->forest_name != NULL)
2292*b3700b07SGordon Ross 			idmap_cfg_discover2(&cfg->handles, &new_pgcfg);
2293*b3700b07SGordon Ross 		ad_disc_done(ad_ctx);
2294*b3700b07SGordon Ross 	}
2295*b3700b07SGordon Ross 
2296*b3700b07SGordon Ross 	WRLOCK_CONFIG();
2297*b3700b07SGordon Ross 
2298*b3700b07SGordon Ross 	/* More props that can be discovered or set in SMF */
2299*b3700b07SGordon Ross 
2300*b3700b07SGordon Ross 	changed += update_dirs(&live_pgcfg->global_catalog,
2301*b3700b07SGordon Ross 	    &new_pgcfg.global_catalog, "global_catalog");
23024d61c878SJulian Pullen 	live_pgcfg->global_catalog_auto_disc =
23034d61c878SJulian Pullen 	    new_pgcfg.global_catalog_auto_disc;
23044d61c878SJulian Pullen 
2305*b3700b07SGordon Ross 	/* Props that are only discovered (never in SMF) */
2306*b3700b07SGordon Ross 
23074d61c878SJulian Pullen 	if (update_domains_in_forest(&live_pgcfg->domains_in_forest,
23084d61c878SJulian Pullen 	    &new_pgcfg.domains_in_forest, "domains_in_forest")) {
23094d61c878SJulian Pullen 		changed++;
23104d61c878SJulian Pullen 		ad_reload_required = TRUE;
23114d61c878SJulian Pullen 	}
23124d61c878SJulian Pullen 
23134d61c878SJulian Pullen 	if (update_trusted_domains(&live_pgcfg->trusted_domains,
23144d61c878SJulian Pullen 	    &new_pgcfg.trusted_domains, "trusted_domains")) {
23154d61c878SJulian Pullen 		changed++;
23164d61c878SJulian Pullen 		if (live_pgcfg->trusted_domains != NULL &&
23174d61c878SJulian Pullen 		    live_pgcfg->trusted_domains[0].domain[0] != '\0')
23184d61c878SJulian Pullen 			ad_reload_required = TRUE;
23194d61c878SJulian Pullen 	}
23204d61c878SJulian Pullen 
23214d61c878SJulian Pullen 	if (update_trusted_forest(&live_pgcfg->trusted_forests,
23224d61c878SJulian Pullen 	    &live_pgcfg->num_trusted_forests, &new_pgcfg.trusted_forests,
23234d61c878SJulian Pullen 	    &new_pgcfg.num_trusted_forests, "trusted_forest")) {
23244d61c878SJulian Pullen 		changed++;
23254d61c878SJulian Pullen 		if (live_pgcfg->trusted_forests != NULL)
23264d61c878SJulian Pullen 			ad_reload_required = TRUE;
23274d61c878SJulian Pullen 	}
23284d61c878SJulian Pullen 
2329148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
2330148c5f43SAlan Wright 		if (changed)
2331148c5f43SAlan Wright 			idmapdlog(LOG_NOTICE, "Configuration changed");
2332148c5f43SAlan Wright 		else
2333148c5f43SAlan Wright 			idmapdlog(LOG_NOTICE, "Configuration unchanged");
2334349d5d8fSnw141292 	}
2335349d5d8fSnw141292 
2336349d5d8fSnw141292 	UNLOCK_CONFIG();
2337349d5d8fSnw141292 
2338*b3700b07SGordon Ross 	if (ad_reload_required)
2339*b3700b07SGordon Ross 		reload_ad();
2340*b3700b07SGordon Ross 
2341*b3700b07SGordon Ross 	idmap_cfg_unload(&new_pgcfg);
2342*b3700b07SGordon Ross 
2343349d5d8fSnw141292 err:
2344148c5f43SAlan Wright 	(void) pthread_mutex_unlock(&cfg->handles.mutex);
2345c5c4113dSnw141292 
2346e8c27ec8Sbaban 	if (rc < -1)
2347c5c4113dSnw141292 		return (rc);
2348e3c2d6aaSnw141292 
2349e3c2d6aaSnw141292 	return ((errors == 0) ? 0 : -1);
2350c5c4113dSnw141292 }
2351c5c4113dSnw141292 
2352651c0131Sbaban /*
2353651c0131Sbaban  * Initialize 'cfg'.
2354651c0131Sbaban  */
2355c5c4113dSnw141292 idmap_cfg_t *
23564edd44c5Sjp151216 idmap_cfg_init()
23574edd44c5Sjp151216 {
2358c8e26105Sjp151216 	idmap_cfg_handles_t *handles;
2359c5c4113dSnw141292 
2360c5c4113dSnw141292 	/* First the smf repository handles: */
2361c5c4113dSnw141292 	idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t));
2362c5c4113dSnw141292 	if (!cfg) {
236371590c90Snw141292 		idmapdlog(LOG_ERR, "Out of memory");
2364c5c4113dSnw141292 		return (NULL);
2365c5c4113dSnw141292 	}
2366c8e26105Sjp151216 	handles = &cfg->handles;
2367c5c4113dSnw141292 
2368c8e26105Sjp151216 	(void) pthread_mutex_init(&handles->mutex, NULL);
2369c8e26105Sjp151216 
2370c8e26105Sjp151216 	if (!(handles->main = scf_handle_create(SCF_VERSION))) {
237171590c90Snw141292 		idmapdlog(LOG_ERR, "scf_handle_create() failed: %s",
237271590c90Snw141292 		    scf_strerror(scf_error()));
2373c5c4113dSnw141292 		goto error;
2374c5c4113dSnw141292 	}
2375c5c4113dSnw141292 
2376c8e26105Sjp151216 	if (scf_handle_bind(handles->main) < 0) {
237771590c90Snw141292 		idmapdlog(LOG_ERR, "scf_handle_bind() failed: %s",
237871590c90Snw141292 		    scf_strerror(scf_error()));
2379c5c4113dSnw141292 		goto error;
2380c5c4113dSnw141292 	}
2381c5c4113dSnw141292 
2382c8e26105Sjp151216 	if (!(handles->service = scf_service_create(handles->main)) ||
2383c8e26105Sjp151216 	    !(handles->instance = scf_instance_create(handles->main)) ||
2384c8e26105Sjp151216 	    !(handles->config_pg = scf_pg_create(handles->main)) ||
2385148c5f43SAlan Wright 	    !(handles->debug_pg = scf_pg_create(handles->main))) {
238671590c90Snw141292 		idmapdlog(LOG_ERR, "scf handle creation failed: %s",
238771590c90Snw141292 		    scf_strerror(scf_error()));
2388c5c4113dSnw141292 		goto error;
2389c5c4113dSnw141292 	}
2390c5c4113dSnw141292 
2391c8e26105Sjp151216 	if (scf_handle_decode_fmri(handles->main,
2392c5c4113dSnw141292 	    FMRI_BASE "/:properties/" CONFIG_PG,
2393c5c4113dSnw141292 	    NULL,				/* scope */
2394c8e26105Sjp151216 	    handles->service,		/* service */
2395c8e26105Sjp151216 	    handles->instance,		/* instance */
2396c8e26105Sjp151216 	    handles->config_pg,		/* pg */
2397c5c4113dSnw141292 	    NULL,				/* prop */
2398c8e26105Sjp151216 	    SCF_DECODE_FMRI_EXACT) < 0) {
239971590c90Snw141292 		idmapdlog(LOG_ERR, "scf_handle_decode_fmri() failed: %s",
240071590c90Snw141292 		    scf_strerror(scf_error()));
2401c5c4113dSnw141292 		goto error;
2402c5c4113dSnw141292 	}
2403c5c4113dSnw141292 
2404c8e26105Sjp151216 	if (scf_service_get_pg(handles->service,
2405148c5f43SAlan Wright 	    DEBUG_PG, handles->debug_pg) < 0) {
2406148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "Property group \"%s\": %s",
2407148c5f43SAlan Wright 		    DEBUG_PG, scf_strerror(scf_error()));
2408c5c4113dSnw141292 		goto error;
2409c5c4113dSnw141292 	}
2410c5c4113dSnw141292 
2411148c5f43SAlan Wright 	check_smf_debug_mode(handles);
2412e3f2c991SKeyur Desai 
2413c8e26105Sjp151216 	/* Initialize AD Auto Discovery context */
2414c8e26105Sjp151216 	handles->ad_ctx = ad_disc_init();
2415c8e26105Sjp151216 	if (handles->ad_ctx == NULL)
2416c8e26105Sjp151216 		goto error;
2417c8e26105Sjp151216 
2418c5c4113dSnw141292 	return (cfg);
2419c5c4113dSnw141292 
2420c5c4113dSnw141292 error:
2421c5c4113dSnw141292 	(void) idmap_cfg_fini(cfg);
2422c5c4113dSnw141292 	return (NULL);
2423c5c4113dSnw141292 }
2424c5c4113dSnw141292 
2425c8e26105Sjp151216 void
24264edd44c5Sjp151216 idmap_cfg_unload(idmap_pg_config_t *pgcfg)
24274edd44c5Sjp151216 {
2428c8e26105Sjp151216 
2429c8e26105Sjp151216 	if (pgcfg->default_domain) {
2430c8e26105Sjp151216 		free(pgcfg->default_domain);
2431c8e26105Sjp151216 		pgcfg->default_domain = NULL;
2432c8e26105Sjp151216 	}
2433c8e26105Sjp151216 	if (pgcfg->domain_name) {
2434c8e26105Sjp151216 		free(pgcfg->domain_name);
2435c8e26105Sjp151216 		pgcfg->domain_name = NULL;
2436c8e26105Sjp151216 	}
2437*b3700b07SGordon Ross 	if (pgcfg->domain_guid) {
2438*b3700b07SGordon Ross 		free(pgcfg->domain_guid);
2439*b3700b07SGordon Ross 		pgcfg->domain_guid = NULL;
2440*b3700b07SGordon Ross 	}
2441c8e26105Sjp151216 	if (pgcfg->machine_sid) {
2442c8e26105Sjp151216 		free(pgcfg->machine_sid);
2443c8e26105Sjp151216 		pgcfg->machine_sid = NULL;
2444c8e26105Sjp151216 	}
2445c8e26105Sjp151216 	if (pgcfg->domain_controller) {
2446c5c4113dSnw141292 		free(pgcfg->domain_controller);
2447c8e26105Sjp151216 		pgcfg->domain_controller = NULL;
2448c8e26105Sjp151216 	}
2449c8e26105Sjp151216 	if (pgcfg->forest_name) {
2450c8e26105Sjp151216 		free(pgcfg->forest_name);
2451c8e26105Sjp151216 		pgcfg->forest_name = NULL;
2452c8e26105Sjp151216 	}
2453c8e26105Sjp151216 	if (pgcfg->site_name) {
2454c8e26105Sjp151216 		free(pgcfg->site_name);
2455c8e26105Sjp151216 		pgcfg->site_name = NULL;
2456c8e26105Sjp151216 	}
2457c8e26105Sjp151216 	if (pgcfg->global_catalog) {
2458c8e26105Sjp151216 		free(pgcfg->global_catalog);
2459c8e26105Sjp151216 		pgcfg->global_catalog = NULL;
2460c8e26105Sjp151216 	}
24614d61c878SJulian Pullen 	if (pgcfg->trusted_domains) {
24624d61c878SJulian Pullen 		free(pgcfg->trusted_domains);
24634d61c878SJulian Pullen 		pgcfg->trusted_domains = NULL;
24644d61c878SJulian Pullen 	}
24654d61c878SJulian Pullen 	if (pgcfg->trusted_forests)
24664d61c878SJulian Pullen 		free_trusted_forests(&pgcfg->trusted_forests,
24674d61c878SJulian Pullen 		    &pgcfg->num_trusted_forests);
24684d61c878SJulian Pullen 
2469e8c27ec8Sbaban 	if (pgcfg->ad_unixuser_attr) {
2470e8c27ec8Sbaban 		free(pgcfg->ad_unixuser_attr);
2471e8c27ec8Sbaban 		pgcfg->ad_unixuser_attr = NULL;
2472e8c27ec8Sbaban 	}
2473e8c27ec8Sbaban 	if (pgcfg->ad_unixgroup_attr) {
2474e8c27ec8Sbaban 		free(pgcfg->ad_unixgroup_attr);
2475e8c27ec8Sbaban 		pgcfg->ad_unixgroup_attr = NULL;
2476e8c27ec8Sbaban 	}
2477e8c27ec8Sbaban 	if (pgcfg->nldap_winname_attr) {
2478e8c27ec8Sbaban 		free(pgcfg->nldap_winname_attr);
2479e8c27ec8Sbaban 		pgcfg->nldap_winname_attr = NULL;
2480e8c27ec8Sbaban 	}
2481c5c4113dSnw141292 }
2482c5c4113dSnw141292 
2483c5c4113dSnw141292 int
2484c5c4113dSnw141292 idmap_cfg_fini(idmap_cfg_t *cfg)
2485c5c4113dSnw141292 {
2486c8e26105Sjp151216 	idmap_cfg_handles_t *handles = &cfg->handles;
2487c8e26105Sjp151216 	idmap_cfg_unload(&cfg->pgcfg);
2488c5c4113dSnw141292 
2489c8e26105Sjp151216 	(void) pthread_mutex_destroy(&handles->mutex);
2490c8e26105Sjp151216 	scf_pg_destroy(handles->config_pg);
2491148c5f43SAlan Wright 	if (handles->debug_pg != NULL)
2492148c5f43SAlan Wright 		scf_pg_destroy(handles->debug_pg);
2493c8e26105Sjp151216 	scf_instance_destroy(handles->instance);
2494c8e26105Sjp151216 	scf_service_destroy(handles->service);
2495c8e26105Sjp151216 	scf_handle_destroy(handles->main);
2496e8c27ec8Sbaban 	if (handles->ad_ctx != NULL)
2497c8e26105Sjp151216 		ad_disc_fini(handles->ad_ctx);
2498c5c4113dSnw141292 	free(cfg);
2499c5c4113dSnw141292 
2500c5c4113dSnw141292 	return (0);
2501c5c4113dSnw141292 }
25020dcc7149Snw141292 
25030dcc7149Snw141292 void
25040dcc7149Snw141292 idmap_cfg_poke_updates(void)
25050dcc7149Snw141292 {
2506*b3700b07SGordon Ross 	int prev_st;
2507*b3700b07SGordon Ross 
2508*b3700b07SGordon Ross 	if (DBG(CONFIG, 1)) {
2509*b3700b07SGordon Ross 		idmapdlog(LOG_INFO, "idmap_cfg_poke_updates");
2510*b3700b07SGordon Ross 	}
2511*b3700b07SGordon Ross 
2512*b3700b07SGordon Ross 	(void) mutex_lock(&_idmapdstate.addisc_lk);
2513*b3700b07SGordon Ross 	prev_st = _idmapdstate.addisc_st;
2514*b3700b07SGordon Ross 	_idmapdstate.addisc_st |= ADDISC_ST_REQUESTED;
2515*b3700b07SGordon Ross 	(void) mutex_unlock(&_idmapdstate.addisc_lk);
2516*b3700b07SGordon Ross 
2517*b3700b07SGordon Ross 	if (prev_st & ADDISC_ST_REQUESTED) {
2518*b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "already poked");
2519*b3700b07SGordon Ross 	} else {
2520*b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "port send poke");
25210dcc7149Snw141292 		(void) port_send(idmapd_ev_port, POKE_AUTO_DISCOVERY, NULL);
25220dcc7149Snw141292 	}
2523*b3700b07SGordon Ross }
2524*b3700b07SGordon Ross 
2525*b3700b07SGordon Ross void
2526*b3700b07SGordon Ross idmap_cfg_force_rediscovery(void)
2527*b3700b07SGordon Ross {
2528*b3700b07SGordon Ross 	int prev_st;
2529*b3700b07SGordon Ross 
2530*b3700b07SGordon Ross 	if (DBG(CONFIG, 1)) {
2531*b3700b07SGordon Ross 		idmapdlog(LOG_INFO, "idmap_cfg_force_rediscovery");
2532*b3700b07SGordon Ross 	}
2533*b3700b07SGordon Ross 
2534*b3700b07SGordon Ross 	(void) mutex_lock(&_idmapdstate.addisc_lk);
2535*b3700b07SGordon Ross 	prev_st = _idmapdstate.addisc_st;
2536*b3700b07SGordon Ross 	_idmapdstate.addisc_st |= ADDISC_ST_REQUESTED;
2537*b3700b07SGordon Ross 	(void) mutex_unlock(&_idmapdstate.addisc_lk);
2538*b3700b07SGordon Ross 
2539*b3700b07SGordon Ross 	if (prev_st & ADDISC_ST_REQUESTED) {
2540*b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "already kicked");
2541*b3700b07SGordon Ross 	} else {
2542*b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "port send kick");
2543*b3700b07SGordon Ross 		(void) port_send(idmapd_ev_port, KICK_AUTO_DISCOVERY, NULL);
2544*b3700b07SGordon Ross 	}
2545*b3700b07SGordon Ross }
25460dcc7149Snw141292 
25470dcc7149Snw141292 /*ARGSUSED*/
25480dcc7149Snw141292 void
2549349d5d8fSnw141292 idmap_cfg_hup_handler(int sig)
2550349d5d8fSnw141292 {
25510dcc7149Snw141292 	if (idmapd_ev_port >= 0)
25520dcc7149Snw141292 		(void) port_send(idmapd_ev_port, RECONFIGURE, NULL);
25530dcc7149Snw141292 }
2554e3f2c991SKeyur Desai 
2555e3f2c991SKeyur Desai /*
2556148c5f43SAlan Wright  * Upgrade the debug flags.
2557148c5f43SAlan Wright  *
2558148c5f43SAlan Wright  * We're replacing a single debug flag with a fine-grained mechanism that
2559148c5f43SAlan Wright  * is also capable of considerably more verbosity.  We'll take a stab at
2560148c5f43SAlan Wright  * producing roughly the same level of output.
2561148c5f43SAlan Wright  */
2562148c5f43SAlan Wright static
2563148c5f43SAlan Wright int
2564148c5f43SAlan Wright upgrade_debug(idmap_cfg_handles_t *handles)
2565148c5f43SAlan Wright {
2566148c5f43SAlan Wright 	boolean_t debug_present;
2567148c5f43SAlan Wright 	const char DEBUG_PROP[] = "debug";
2568148c5f43SAlan Wright 	int rc;
2569148c5f43SAlan Wright 
2570148c5f43SAlan Wright 	rc = prop_exists(handles, DEBUG_PROP, &debug_present);
2571148c5f43SAlan Wright 
2572148c5f43SAlan Wright 	if (rc != 0)
2573148c5f43SAlan Wright 		return (rc);
2574148c5f43SAlan Wright 
2575148c5f43SAlan Wright 	if (!debug_present)
2576148c5f43SAlan Wright 		return (0);
2577148c5f43SAlan Wright 
2578148c5f43SAlan Wright 	idmapdlog(LOG_INFO,
2579148c5f43SAlan Wright 	    "Upgrading old %s/%s setting to %s/* settings.",
2580148c5f43SAlan Wright 	    CONFIG_PG, DEBUG_PROP, DEBUG_PG);
2581148c5f43SAlan Wright 
2582148c5f43SAlan Wright 	rc = set_val_integer(handles, handles->debug_pg, "config", 1);
2583148c5f43SAlan Wright 	if (rc != 0)
2584148c5f43SAlan Wright 		return (rc);
2585148c5f43SAlan Wright 	rc = set_val_integer(handles, handles->debug_pg, "discovery", 1);
2586148c5f43SAlan Wright 	if (rc != 0)
2587148c5f43SAlan Wright 		return (rc);
2588148c5f43SAlan Wright 
2589148c5f43SAlan Wright 	rc = del_val(handles, handles->config_pg, DEBUG_PROP);
2590148c5f43SAlan Wright 	if (rc != 0)
2591148c5f43SAlan Wright 		return (rc);
2592148c5f43SAlan Wright 
2593148c5f43SAlan Wright 	return (0);
2594148c5f43SAlan Wright }
2595148c5f43SAlan Wright 
2596148c5f43SAlan Wright /*
2597e3f2c991SKeyur Desai  * Upgrade the DS mapping flags.
2598e3f2c991SKeyur Desai  *
2599e3f2c991SKeyur Desai  * If the old ds_name_mapping_enabled flag is present, then
2600e3f2c991SKeyur Desai  *     if the new directory_based_mapping value is present, then
2601e3f2c991SKeyur Desai  *         if the two are compatible, delete the old and note it
2602e3f2c991SKeyur Desai  *         else delete the old and warn
2603e3f2c991SKeyur Desai  *     else
2604e3f2c991SKeyur Desai  *         set the new based on the old, and note it
2605e3f2c991SKeyur Desai  *         delete the old
2606e3f2c991SKeyur Desai  */
2607e3f2c991SKeyur Desai static
2608e3f2c991SKeyur Desai int
2609e3f2c991SKeyur Desai upgrade_directory_mapping(idmap_cfg_handles_t *handles)
2610e3f2c991SKeyur Desai {
2611e3f2c991SKeyur Desai 	boolean_t legacy_ds_name_mapping_present;
2612e3f2c991SKeyur Desai 	const char DS_NAME_MAPPING_ENABLED[] = "ds_name_mapping_enabled";
2613e3f2c991SKeyur Desai 	const char DIRECTORY_BASED_MAPPING[] = "directory_based_mapping";
2614e3f2c991SKeyur Desai 	int rc;
2615e3f2c991SKeyur Desai 
2616e3f2c991SKeyur Desai 	rc = prop_exists(handles, DS_NAME_MAPPING_ENABLED,
2617e3f2c991SKeyur Desai 	    &legacy_ds_name_mapping_present);
2618e3f2c991SKeyur Desai 
2619e3f2c991SKeyur Desai 	if (rc != 0)
2620e3f2c991SKeyur Desai 		return (rc);
2621e3f2c991SKeyur Desai 
2622e3f2c991SKeyur Desai 	if (!legacy_ds_name_mapping_present)
2623e3f2c991SKeyur Desai 		return (0);
2624e3f2c991SKeyur Desai 
2625e3f2c991SKeyur Desai 	boolean_t legacy_ds_name_mapping_enabled;
2626148c5f43SAlan Wright 	rc = get_val_bool(handles, DS_NAME_MAPPING_ENABLED,
2627148c5f43SAlan Wright 	    &legacy_ds_name_mapping_enabled, B_FALSE);
2628e3f2c991SKeyur Desai 	if (rc != 0)
2629e3f2c991SKeyur Desai 		return (rc);
2630e3f2c991SKeyur Desai 
2631e3f2c991SKeyur Desai 	char *legacy_mode;
2632e3f2c991SKeyur Desai 	char *legacy_bool_string;
2633e3f2c991SKeyur Desai 	if (legacy_ds_name_mapping_enabled) {
2634e3f2c991SKeyur Desai 		legacy_mode = "name";
2635e3f2c991SKeyur Desai 		legacy_bool_string = "true";
2636e3f2c991SKeyur Desai 	} else {
2637e3f2c991SKeyur Desai 		legacy_mode = "none";
2638e3f2c991SKeyur Desai 		legacy_bool_string = "false";
2639e3f2c991SKeyur Desai 	}
2640e3f2c991SKeyur Desai 
2641e3f2c991SKeyur Desai 	char *directory_based_mapping;
2642e3f2c991SKeyur Desai 	rc = get_val_astring(handles, DIRECTORY_BASED_MAPPING,
2643e3f2c991SKeyur Desai 	    &directory_based_mapping);
2644e3f2c991SKeyur Desai 	if (rc != 0)
2645e3f2c991SKeyur Desai 		return (rc);
2646e3f2c991SKeyur Desai 
2647e3f2c991SKeyur Desai 	if (directory_based_mapping == NULL) {
2648e3f2c991SKeyur Desai 		idmapdlog(LOG_INFO,
2649e3f2c991SKeyur Desai 		    "Upgrading old %s=%s setting\n"
2650e3f2c991SKeyur Desai 		    "to %s=%s.",
2651e3f2c991SKeyur Desai 		    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
2652e3f2c991SKeyur Desai 		    DIRECTORY_BASED_MAPPING, legacy_mode);
2653148c5f43SAlan Wright 		rc = set_val_astring(handles, handles->config_pg,
2654148c5f43SAlan Wright 		    DIRECTORY_BASED_MAPPING, legacy_mode);
2655e3f2c991SKeyur Desai 		if (rc != 0)
2656e3f2c991SKeyur Desai 			return (rc);
2657e3f2c991SKeyur Desai 	} else {
2658e3f2c991SKeyur Desai 		boolean_t new_name_mapping;
2659e3f2c991SKeyur Desai 		if (strcasecmp(directory_based_mapping, "name") == 0)
2660e3f2c991SKeyur Desai 			new_name_mapping = B_TRUE;
2661e3f2c991SKeyur Desai 		else
2662e3f2c991SKeyur Desai 			new_name_mapping = B_FALSE;
2663e3f2c991SKeyur Desai 
2664e3f2c991SKeyur Desai 		if (legacy_ds_name_mapping_enabled == new_name_mapping) {
2665e3f2c991SKeyur Desai 			idmapdlog(LOG_INFO,
2666e3f2c991SKeyur Desai 			    "Automatically removing old %s=%s setting\n"
2667e3f2c991SKeyur Desai 			    "in favor of %s=%s.",
2668e3f2c991SKeyur Desai 			    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
2669e3f2c991SKeyur Desai 			    DIRECTORY_BASED_MAPPING, directory_based_mapping);
2670e3f2c991SKeyur Desai 		} else {
2671e3f2c991SKeyur Desai 			idmapdlog(LOG_WARNING,
2672e3f2c991SKeyur Desai 			    "Removing conflicting %s=%s setting\n"
2673e3f2c991SKeyur Desai 			    "in favor of %s=%s.",
2674e3f2c991SKeyur Desai 			    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
2675e3f2c991SKeyur Desai 			    DIRECTORY_BASED_MAPPING, directory_based_mapping);
2676e3f2c991SKeyur Desai 		}
2677e3f2c991SKeyur Desai 		free(directory_based_mapping);
2678e3f2c991SKeyur Desai 	}
2679e3f2c991SKeyur Desai 
2680148c5f43SAlan Wright 	rc = del_val(handles, handles->config_pg, DS_NAME_MAPPING_ENABLED);
2681e3f2c991SKeyur Desai 	if (rc != 0)
2682e3f2c991SKeyur Desai 		return (rc);
2683e3f2c991SKeyur Desai 
2684e3f2c991SKeyur Desai 	return (0);
2685e3f2c991SKeyur Desai }
2686e3f2c991SKeyur Desai 
2687e3f2c991SKeyur Desai /*
2688e3f2c991SKeyur Desai  * Do whatever is necessary to upgrade idmap's configuration before
2689e3f2c991SKeyur Desai  * we load it.
2690e3f2c991SKeyur Desai  */
2691e3f2c991SKeyur Desai int
2692e3f2c991SKeyur Desai idmap_cfg_upgrade(idmap_cfg_t *cfg)
2693e3f2c991SKeyur Desai {
2694e3f2c991SKeyur Desai 	int rc;
2695e3f2c991SKeyur Desai 
2696e3f2c991SKeyur Desai 	rc = upgrade_directory_mapping(&cfg->handles);
2697e3f2c991SKeyur Desai 	if (rc != 0)
2698e3f2c991SKeyur Desai 		return (rc);
2699e3f2c991SKeyur Desai 
2700148c5f43SAlan Wright 	rc = upgrade_debug(&cfg->handles);
2701148c5f43SAlan Wright 	if (rc != 0)
2702148c5f43SAlan Wright 		return (rc);
2703148c5f43SAlan Wright 
2704e3f2c991SKeyur Desai 	return (0);
2705e3f2c991SKeyur Desai }
2706*b3700b07SGordon Ross 
2707*b3700b07SGordon Ross /*
2708*b3700b07SGordon Ross  * The LDAP code passes principal names lacking any
2709*b3700b07SGordon Ross  * realm information, which causes mech_krb5 to do
2710*b3700b07SGordon Ross  * awful things trying to figure out the realm.
2711*b3700b07SGordon Ross  * Avoid that by making sure it has a default,
2712*b3700b07SGordon Ross  * even when krb5.conf is not configured.
2713*b3700b07SGordon Ross  */
2714*b3700b07SGordon Ross static void
2715*b3700b07SGordon Ross idmapd_set_krb5_realm(char *domain)
2716*b3700b07SGordon Ross {
2717*b3700b07SGordon Ross 	static char realm[MAXHOSTNAMELEN];
2718*b3700b07SGordon Ross 	size_t ilen, olen;
2719*b3700b07SGordon Ross 	int err;
2720*b3700b07SGordon Ross 
2721*b3700b07SGordon Ross 	if (domain == NULL) {
2722*b3700b07SGordon Ross 		(void) unsetenv("KRB5_DEFAULT_REALM");
2723*b3700b07SGordon Ross 		return;
2724*b3700b07SGordon Ross 	}
2725*b3700b07SGordon Ross 
2726*b3700b07SGordon Ross 	/* Convert to upper case, in place. */
2727*b3700b07SGordon Ross 	(void) strlcpy(realm, domain, sizeof (realm));
2728*b3700b07SGordon Ross 	olen = ilen = strlen(realm);
2729*b3700b07SGordon Ross 	(void) u8_textprep_str(realm, &ilen, realm, &olen,
2730*b3700b07SGordon Ross 	    U8_TEXTPREP_TOUPPER, U8_UNICODE_LATEST, &err);
2731*b3700b07SGordon Ross 
2732*b3700b07SGordon Ross 	(void) setenv("KRB5_DEFAULT_REALM", realm, 1);
2733*b3700b07SGordon Ross }
2734