1c5c4113dSnw /*
2c5c4113dSnw  * CDDL HEADER START
3c5c4113dSnw  *
4c5c4113dSnw  * The contents of this file are subject to the terms of the
5c5c4113dSnw  * Common Development and Distribution License (the "License").
6c5c4113dSnw  * You may not use this file except in compliance with the License.
7c5c4113dSnw  *
8c5c4113dSnw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c5c4113dSnw  * or http://www.opensolaris.org/os/licensing.
10c5c4113dSnw  * See the License for the specific language governing permissions
11c5c4113dSnw  * and limitations under the License.
12c5c4113dSnw  *
13c5c4113dSnw  * When distributing Covered Code, include this CDDL HEADER in each
14c5c4113dSnw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c5c4113dSnw  * If applicable, add the following below this CDDL HEADER, with the
16c5c4113dSnw  * fields enclosed by brackets "[]" replaced with your own identifying
17c5c4113dSnw  * information: Portions Copyright [yyyy] [name of copyright owner]
18c5c4113dSnw  *
19c5c4113dSnw  * CDDL HEADER END
20c5c4113dSnw  */
21c5c4113dSnw /*
22c5866007SKeyur Desai  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*a774f103SGordon Ross  * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
24c5c4113dSnw  */
25c5c4113dSnw 
26c5c4113dSnw 
27c5c4113dSnw /*
28c5c4113dSnw  * Config routines common to idmap(1M) and idmapd(1M)
29c5c4113dSnw  */
30c5c4113dSnw 
31c5c4113dSnw #include <stdlib.h>
32c5c4113dSnw #include <strings.h>
33c5c4113dSnw #include <libintl.h>
34c5c4113dSnw #include <ctype.h>
35c5c4113dSnw #include <errno.h>
36c5c4113dSnw #include <stdio.h>
37c5c4113dSnw #include <stdarg.h>
388edda628Sbaban #include <uuid/uuid.h>
39c8e26105Sjp #include <pthread.h>
40c8e26105Sjp #include <port.h>
41b3700b07SGordon Ross #include <sys/socket.h>
420dcc7149Snw #include <net/route.h>
434d61c878SJulian Pullen #include <sys/u8_textprep.h>
44b3700b07SGordon Ross #include <netinet/in.h>
45b3700b07SGordon Ross #include <arpa/inet.h>
46b3700b07SGordon Ross #include <netdb.h>
47148c5f43SAlan Wright #include <note.h>
48fea136a0SMatt Barden #include <limits.h>
49b3700b07SGordon Ross #include "idmapd.h"
50c8e26105Sjp #include "addisc.h"
51c5c4113dSnw 
524aa0a5e7Snw #define	MACHINE_SID_LEN		(9 + 3 * 11)
530dcc7149Snw #define	FMRI_BASE		"svc:/system/idmap"
540dcc7149Snw #define	CONFIG_PG		"config"
55148c5f43SAlan Wright #define	DEBUG_PG		"debug"
560dcc7149Snw #define	RECONFIGURE		1
570dcc7149Snw #define	POKE_AUTO_DISCOVERY	2
58b3700b07SGordon Ross #define	KICK_AUTO_DISCOVERY	3
59c5c4113dSnw 
6048cd229bSGordon Ross /*
6148cd229bSGordon Ross  * Default cache timeouts.  Can override via svccfg
6248cd229bSGordon Ross  * config/id_cache_timeout = count: seconds
6348cd229bSGordon Ross  * config/name_cache_timeout = count: seconds
6448cd229bSGordon Ross  */
653f1de28dSBayard Bell #define	ID_CACHE_TMO_DEFAULT	86400
663f1de28dSBayard Bell #define	NAME_CACHE_TMO_DEFAULT	604800
6748cd229bSGordon Ross 
68b3700b07SGordon Ross /*
69b3700b07SGordon Ross  * Default maximum time between rediscovery runs.
70b3700b07SGordon Ross  * config/rediscovery_interval = count: seconds
71b3700b07SGordon Ross  */
72b3700b07SGordon Ross #define	REDISCOVERY_INTERVAL_DEFAULT	3600
73b3700b07SGordon Ross 
74b3700b07SGordon Ross /*
75b3700b07SGordon Ross  * Mininum time between rediscovery runs, in case adutils gives us a
76b3700b07SGordon Ross  * really short TTL (which it never should, but be defensive)
77b3700b07SGordon Ross  * (not configurable) seconds.
78b3700b07SGordon Ross  */
79b3700b07SGordon Ross #define	MIN_REDISCOVERY_INTERVAL	60
80b3700b07SGordon Ross 
81fea136a0SMatt Barden /*
82fea136a0SMatt Barden  * Max number of concurrent door calls
83fea136a0SMatt Barden  */
84fea136a0SMatt Barden #define	MAX_THREADS_DEFAULT	40
85fea136a0SMatt Barden 
86c5866007SKeyur Desai enum event_type {
87c5866007SKeyur Desai 	EVENT_NOTHING,	/* Woke up for no good reason */
88c5866007SKeyur Desai 	EVENT_TIMEOUT,	/* Timeout expired */
89c5866007SKeyur Desai 	EVENT_ROUTING,	/* An interesting routing event happened */
90b3700b07SGordon Ross 	EVENT_POKED,	/* Requested from degrade_svc() */
91b3700b07SGordon Ross 	EVENT_KICKED,	/* Force rediscovery, i.e. DC failed. */
92c5866007SKeyur Desai 	EVENT_REFRESH,	/* SMF refresh */
93c5866007SKeyur Desai };
94c5866007SKeyur Desai 
95c8e26105Sjp 
96b3700b07SGordon Ross static void idmapd_set_krb5_realm(char *);
97c8e26105Sjp 
98c8e26105Sjp static pthread_t update_thread_handle = 0;
99c8e26105Sjp 
1000dcc7149Snw static int idmapd_ev_port = -1;
1010dcc7149Snw static int rt_sock = -1;
102c8e26105Sjp 
103e3f2c991SKeyur Desai struct enum_lookup_map directory_mapping_map[] = {
104e3f2c991SKeyur Desai 	{ DIRECTORY_MAPPING_NONE, "none" },
105e3f2c991SKeyur Desai 	{ DIRECTORY_MAPPING_NAME, "name" },
106e3f2c991SKeyur Desai 	{ DIRECTORY_MAPPING_IDMU, "idmu" },
107e3f2c991SKeyur Desai 	{ 0, NULL },
108e3f2c991SKeyur Desai };
109e3f2c991SKeyur Desai 
110148c5f43SAlan Wright struct enum_lookup_map trust_dir_map[] = {
111148c5f43SAlan Wright 	{ 1, "they trust us" },
112148c5f43SAlan Wright 	{ 2, "we trust them" },
113148c5f43SAlan Wright 	{ 3, "we trust each other" },
114148c5f43SAlan Wright 	{ 0, NULL },
115148c5f43SAlan Wright };
116148c5f43SAlan Wright 
1178edda628Sbaban static int
11812b65585SGordon Ross generate_machine_uuid(char **machine_uuid)
1194edd44c5Sjp {
1208edda628Sbaban 	uuid_t uu;
1218edda628Sbaban 
12212b65585SGordon Ross 	*machine_uuid = calloc(1, UUID_PRINTABLE_STRING_LENGTH + 1);
12312b65585SGordon Ross 	if (*machine_uuid == NULL) {
12471590c90Snw 		idmapdlog(LOG_ERR, "Out of memory");
1258edda628Sbaban 		return (-1);
1268edda628Sbaban 	}
1278edda628Sbaban 
1288edda628Sbaban 	uuid_clear(uu);
12912b65585SGordon Ross 	uuid_generate_time(uu);
13012b65585SGordon Ross 	uuid_unparse(uu, *machine_uuid);
13112b65585SGordon Ross 
13212b65585SGordon Ross 	return (0);
13312b65585SGordon Ross }
13412b65585SGordon Ross 
13512b65585SGordon Ross static int
13612b65585SGordon Ross generate_machine_sid(char **machine_sid, char *machine_uuid)
13712b65585SGordon Ross {
13812b65585SGordon Ross 	union {
13912b65585SGordon Ross 		uuid_t uu;
14012b65585SGordon Ross 		uint32_t v[4];
14112b65585SGordon Ross 	} uv;
14212b65585SGordon Ross 	int len;
14312b65585SGordon Ross 
14412b65585SGordon Ross 	/*
14512b65585SGordon Ross 	 * Split the 128-bit machine UUID into three 32-bit values
14612b65585SGordon Ross 	 * we'll use as the "sub-authorities" of the machine SID.
14712b65585SGordon Ross 	 * The machine_sid will have the form S-1-5-21-J-K-L
14812b65585SGordon Ross 	 * (that's four sub-authorities altogether) where:
14912b65585SGordon Ross 	 *	J = last 4 bytes of node_addr,
15012b65585SGordon Ross 	 *	K = time_mid, time_hi_and_version
15112b65585SGordon Ross 	 *	L = time_low
15212b65585SGordon Ross 	 * (see struct uuid)
15312b65585SGordon Ross 	 */
15412b65585SGordon Ross 
15512b65585SGordon Ross 	(void) memset(&uv, 0, sizeof (uv));
15612b65585SGordon Ross 	(void) uuid_parse(machine_uuid, uv.uu);
1578edda628Sbaban 
15812b65585SGordon Ross 	len = asprintf(machine_sid, "S-1-5-21-%u-%u-%u",
15912b65585SGordon Ross 	    uv.v[3], uv.v[0], uv.v[1]);
1604aa0a5e7Snw 
16112b65585SGordon Ross 	if (len == -1 || *machine_sid == NULL) {
16212b65585SGordon Ross 		idmapdlog(LOG_ERR, "Out of memory");
16312b65585SGordon Ross 		return (-1);
1648edda628Sbaban 	}
1658edda628Sbaban 
1668edda628Sbaban 	return (0);
1678edda628Sbaban }
1688edda628Sbaban 
169479ac375Sdm 
170479ac375Sdm /* In the case of error, exists is set to FALSE anyway */
171479ac375Sdm static int
172e3f2c991SKeyur Desai prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists)
17371590c90Snw {
17471590c90Snw 
175479ac375Sdm 	scf_property_t *scf_prop;
176479ac375Sdm 
1777a8a68f5SJulian Pullen 	*exists = B_FALSE;
178479ac375Sdm 
179148c5f43SAlan Wright 	scf_prop = scf_property_create(handles->main);
180148c5f43SAlan Wright 	if (scf_prop == NULL) {
181148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
182148c5f43SAlan Wright 		    scf_strerror(scf_error()));
183148c5f43SAlan Wright 		return (-1);
184148c5f43SAlan Wright 	}
185148c5f43SAlan Wright 
186148c5f43SAlan Wright 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) == 0)
187148c5f43SAlan Wright 		*exists = B_TRUE;
188148c5f43SAlan Wright 
189148c5f43SAlan Wright 	scf_property_destroy(scf_prop);
190148c5f43SAlan Wright 
191148c5f43SAlan Wright 	return (0);
192148c5f43SAlan Wright }
193148c5f43SAlan Wright 
194148c5f43SAlan Wright static int
195148c5f43SAlan Wright get_debug(idmap_cfg_handles_t *handles, const char *name)
196148c5f43SAlan Wright {
197148c5f43SAlan Wright 	int64_t i64 = 0;
198148c5f43SAlan Wright 
199148c5f43SAlan Wright 	scf_property_t *scf_prop;
200148c5f43SAlan Wright 	scf_value_t *value;
201148c5f43SAlan Wright 
202148c5f43SAlan Wright 	scf_prop = scf_property_create(handles->main);
203148c5f43SAlan Wright 	if (scf_prop == NULL) {
204148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
205148c5f43SAlan Wright 		    scf_strerror(scf_error()));
206148c5f43SAlan Wright 		abort();
207148c5f43SAlan Wright 	}
208148c5f43SAlan Wright 	value = scf_value_create(handles->main);
209148c5f43SAlan Wright 	if (value == NULL) {
210148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
211148c5f43SAlan Wright 		    scf_strerror(scf_error()));
212148c5f43SAlan Wright 		abort();
213148c5f43SAlan Wright 	}
214148c5f43SAlan Wright 
215148c5f43SAlan Wright 	if (scf_pg_get_property(handles->debug_pg, name, scf_prop) < 0) {
216148c5f43SAlan Wright 		/* this is OK: the property is just undefined */
217148c5f43SAlan Wright 		goto destruction;
218148c5f43SAlan Wright 	}
219148c5f43SAlan Wright 
220148c5f43SAlan Wright 
221148c5f43SAlan Wright 	if (scf_property_get_value(scf_prop, value) < 0) {
222148c5f43SAlan Wright 		/* It is still OK when a property doesn't have any value */
223148c5f43SAlan Wright 		goto destruction;
224148c5f43SAlan Wright 	}
225148c5f43SAlan Wright 
226148c5f43SAlan Wright 	if (scf_value_get_integer(value, &i64) != 0) {
227148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "Can not retrieve %s/%s:  %s",
228148c5f43SAlan Wright 		    DEBUG_PG, name, scf_strerror(scf_error()));
229148c5f43SAlan Wright 		abort();
230148c5f43SAlan Wright 	}
231148c5f43SAlan Wright 
232148c5f43SAlan Wright destruction:
233148c5f43SAlan Wright 	scf_value_destroy(value);
234148c5f43SAlan Wright 	scf_property_destroy(scf_prop);
235148c5f43SAlan Wright 
236148c5f43SAlan Wright 	return ((int)i64);
237148c5f43SAlan Wright }
238148c5f43SAlan Wright 
239148c5f43SAlan Wright static int
240148c5f43SAlan Wright get_val_bool(idmap_cfg_handles_t *handles, const char *name,
241148c5f43SAlan Wright 	boolean_t *val, boolean_t default_val)
242148c5f43SAlan Wright {
243148c5f43SAlan Wright 	int rc = 0;
244148c5f43SAlan Wright 
245148c5f43SAlan Wright 	scf_property_t *scf_prop;
246148c5f43SAlan Wright 	scf_value_t *value;
247148c5f43SAlan Wright 
248148c5f43SAlan Wright 	*val = default_val;
249148c5f43SAlan Wright 
250479ac375Sdm 	scf_prop = scf_property_create(handles->main);
251479ac375Sdm 	if (scf_prop == NULL) {
252479ac375Sdm 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
253479ac375Sdm 		    scf_strerror(scf_error()));
254479ac375Sdm 		return (-1);
255479ac375Sdm 	}
256479ac375Sdm 	value = scf_value_create(handles->main);
257479ac375Sdm 	if (value == NULL) {
258479ac375Sdm 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
259479ac375Sdm 		    scf_strerror(scf_error()));
260479ac375Sdm 		scf_property_destroy(scf_prop);
261479ac375Sdm 		return (-1);
262479ac375Sdm 	}
26371590c90Snw 
264148c5f43SAlan Wright 	/* It is OK if the property is undefined */
265148c5f43SAlan Wright 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
266148c5f43SAlan Wright 		goto destruction;
267148c5f43SAlan Wright 
268148c5f43SAlan Wright 
269148c5f43SAlan Wright 	/* It is still OK when a property doesn't have any value */
270148c5f43SAlan Wright 	if (scf_property_get_value(scf_prop, value) < 0)
271148c5f43SAlan Wright 		goto destruction;
272148c5f43SAlan Wright 
273148c5f43SAlan Wright 	uint8_t b;
274148c5f43SAlan Wright 	rc = scf_value_get_boolean(value, &b);
27571590c90Snw 
276148c5f43SAlan Wright 	if (rc == 0)
277148c5f43SAlan Wright 		*val = (boolean_t)b;
278148c5f43SAlan Wright 
279148c5f43SAlan Wright destruction:
28071590c90Snw 	scf_value_destroy(value);
28171590c90Snw 	scf_property_destroy(scf_prop);
28271590c90Snw 
283148c5f43SAlan Wright 	return (rc);
28471590c90Snw }
28571590c90Snw 
286c5c4113dSnw static int
287e3f2c991SKeyur Desai get_val_int(idmap_cfg_handles_t *handles, const char *name,
288c8e26105Sjp 	void *val, scf_type_t type)
289c5c4113dSnw {
290c5c4113dSnw 	int rc = 0;
291c5c4113dSnw 
292479ac375Sdm 	scf_property_t *scf_prop;
293479ac375Sdm 	scf_value_t *value;
294479ac375Sdm 
2954aa0a5e7Snw 	switch (type) {
2964aa0a5e7Snw 	case SCF_TYPE_COUNT:
2974aa0a5e7Snw 		*(uint64_t *)val = 0;
2984aa0a5e7Snw 		break;
2994aa0a5e7Snw 	case SCF_TYPE_INTEGER:
3004aa0a5e7Snw 		*(int64_t *)val = 0;
3014aa0a5e7Snw 		break;
3024aa0a5e7Snw 	default:
3034aa0a5e7Snw 		idmapdlog(LOG_ERR, "Invalid scf integer type (%d)",
3044aa0a5e7Snw 		    type);
3054aa0a5e7Snw 		abort();
3064aa0a5e7Snw 	}
3074aa0a5e7Snw 
308479ac375Sdm 	scf_prop = scf_property_create(handles->main);
309479ac375Sdm 	if (scf_prop == NULL) {
310479ac375Sdm 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
311479ac375Sdm 		    scf_strerror(scf_error()));
312479ac375Sdm 		return (-1);
313479ac375Sdm 	}
314479ac375Sdm 	value = scf_value_create(handles->main);
315479ac375Sdm 	if (value == NULL) {
316479ac375Sdm 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
317479ac375Sdm 		    scf_strerror(scf_error()));
318479ac375Sdm 		scf_property_destroy(scf_prop);
319479ac375Sdm 		return (-1);
320479ac375Sdm 	}
321c5c4113dSnw 
322c8e26105Sjp 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
323c5c4113dSnw 	/* this is OK: the property is just undefined */
324c5c4113dSnw 		goto destruction;
325c5c4113dSnw 
326c5c4113dSnw 
327c8e26105Sjp 	if (scf_property_get_value(scf_prop, value) < 0)
328c5c4113dSnw 	/* It is still OK when a property doesn't have any value */
329c5c4113dSnw 		goto destruction;
330c5c4113dSnw 
331c5c4113dSnw 	switch (type) {
332c5c4113dSnw 	case SCF_TYPE_COUNT:
333c5c4113dSnw 		rc = scf_value_get_count(value, val);
334c5c4113dSnw 		break;
335c5c4113dSnw 	case SCF_TYPE_INTEGER:
336c5c4113dSnw 		rc = scf_value_get_integer(value, val);
337c5c4113dSnw 		break;
338e3f2c991SKeyur Desai 	default:
339e3f2c991SKeyur Desai 		abort();	/* tested above */
340e3f2c991SKeyur Desai 		/* NOTREACHED */
341c5c4113dSnw 	}
342c5c4113dSnw 
343e3f2c991SKeyur Desai 	if (rc != 0) {
344e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "Can not retrieve config/%s:  %s",
345e3f2c991SKeyur Desai 		    name, scf_strerror(scf_error()));
346e3f2c991SKeyur Desai 	}
347c5c4113dSnw 
348c5c4113dSnw destruction:
349c5c4113dSnw 	scf_value_destroy(value);
350c5c4113dSnw 	scf_property_destroy(scf_prop);
351c5c4113dSnw 
352c5c4113dSnw 	return (rc);
353c5c4113dSnw }
354c5c4113dSnw 
355c5c4113dSnw static char *
356e3f2c991SKeyur Desai scf_value2string(const char *name, scf_value_t *value)
3574edd44c5Sjp {
358e3f2c991SKeyur Desai 	static size_t max_val = 0;
359c5c4113dSnw 
360e3f2c991SKeyur Desai 	if (max_val == 0)
361e3f2c991SKeyur Desai 		max_val = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
362c5c4113dSnw 
363e3f2c991SKeyur Desai 	char buf[max_val + 1];
364e3f2c991SKeyur Desai 	if (scf_value_get_astring(value, buf, max_val + 1) < 0) {
365e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "Can not retrieve config/%s:  %s",
366e3f2c991SKeyur Desai 		    name, scf_strerror(scf_error()));
367e3f2c991SKeyur Desai 		return (NULL);
368c5c4113dSnw 	}
369c5c4113dSnw 
370e3f2c991SKeyur Desai 	char *s = strdup(buf);
371e3f2c991SKeyur Desai 	if (s == NULL)
372e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "Out of memory");
373c5c4113dSnw 
374e3f2c991SKeyur Desai 	return (s);
375c5c4113dSnw }
376c5c4113dSnw 
377c8e26105Sjp static int
378c8e26105Sjp get_val_ds(idmap_cfg_handles_t *handles, const char *name, int defport,
379b3700b07SGordon Ross 		ad_disc_ds_t **val)
380c8e26105Sjp {
381b3700b07SGordon Ross 	char port_str[8];
382b3700b07SGordon Ross 	struct addrinfo hints;
383b3700b07SGordon Ross 	struct addrinfo *ai;
384b3700b07SGordon Ross 	ad_disc_ds_t *servers = NULL;
385c8e26105Sjp 	scf_property_t *scf_prop;
386c8e26105Sjp 	scf_value_t *value;
387c8e26105Sjp 	scf_iter_t *iter;
388c8e26105Sjp 	char *host, *portstr;
389b3700b07SGordon Ross 	int err, len, i;
390c8e26105Sjp 	int count = 0;
391e3c2d6aaSnw 	int rc = -1;
392c8e26105Sjp 
393c8e26105Sjp 	*val = NULL;
394c8e26105Sjp 
395c8e26105Sjp restart:
396c8e26105Sjp 	scf_prop = scf_property_create(handles->main);
397479ac375Sdm 	if (scf_prop == NULL) {
398479ac375Sdm 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
399479ac375Sdm 		    scf_strerror(scf_error()));
400479ac375Sdm 		return (-1);
401479ac375Sdm 	}
402479ac375Sdm 
403c8e26105Sjp 	value = scf_value_create(handles->main);
404479ac375Sdm 	if (value == NULL) {
405479ac375Sdm 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
406479ac375Sdm 		    scf_strerror(scf_error()));
407479ac375Sdm 		scf_property_destroy(scf_prop);
408479ac375Sdm 		return (-1);
409479ac375Sdm 	}
410479ac375Sdm 
411c8e26105Sjp 	iter = scf_iter_create(handles->main);
412479ac375Sdm 	if (iter == NULL) {
413479ac375Sdm 		idmapdlog(LOG_ERR, "scf_iter_create() failed: %s",
414479ac375Sdm 		    scf_strerror(scf_error()));
415479ac375Sdm 		scf_value_destroy(value);
416479ac375Sdm 		scf_property_destroy(scf_prop);
417479ac375Sdm 		return (-1);
418479ac375Sdm 	}
419c8e26105Sjp 
420e3c2d6aaSnw 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) {
421c8e26105Sjp 		/* this is OK: the property is just undefined */
422e3c2d6aaSnw 		rc = 0;
423c8e26105Sjp 		goto destruction;
424e3c2d6aaSnw 	}
425c8e26105Sjp 
426c8e26105Sjp 	if (scf_iter_property_values(iter, scf_prop) < 0) {
427c8e26105Sjp 		idmapdlog(LOG_ERR,
42871590c90Snw 		    "scf_iter_property_values(%s) failed: %s",
42971590c90Snw 		    name, scf_strerror(scf_error()));
430c8e26105Sjp 		goto destruction;
431c8e26105Sjp 	}
432c8e26105Sjp 
433c8e26105Sjp 	/* Workaround scf bugs -- can't reset an iteration */
434c8e26105Sjp 	if (count == 0) {
435c8e26105Sjp 		while (scf_iter_next_value(iter, value) > 0)
436c8e26105Sjp 			count++;
437c8e26105Sjp 
438e3c2d6aaSnw 		if (count == 0) {
439c8e26105Sjp 			/* no values */
440e3c2d6aaSnw 			rc = 0;
441c8e26105Sjp 			goto destruction;
442e3c2d6aaSnw 		}
443c8e26105Sjp 
444c8e26105Sjp 		scf_value_destroy(value);
445c8e26105Sjp 		scf_iter_destroy(iter);
446c8e26105Sjp 		scf_property_destroy(scf_prop);
447c8e26105Sjp 		goto restart;
448c8e26105Sjp 	}
449c8e26105Sjp 
450c8e26105Sjp 	if ((servers = calloc(count + 1, sizeof (*servers))) == NULL) {
45171590c90Snw 		idmapdlog(LOG_ERR, "Out of memory");
452c8e26105Sjp 		goto destruction;
453c8e26105Sjp 	}
454c8e26105Sjp 
455b3700b07SGordon Ross 	(void) memset(&hints, 0, sizeof (hints));
456b3700b07SGordon Ross 	hints.ai_protocol = IPPROTO_TCP;
457b3700b07SGordon Ross 	hints.ai_socktype = SOCK_STREAM;
458b3700b07SGordon Ross 	host = NULL;
459b3700b07SGordon Ross 
460e3c2d6aaSnw 	i = 0;
461e3c2d6aaSnw 	while (i < count && scf_iter_next_value(iter, value) > 0) {
462b3700b07SGordon Ross 		if (host) {
463b3700b07SGordon Ross 			free(host);
464b3700b07SGordon Ross 			host = NULL;
465b3700b07SGordon Ross 		}
466e3c2d6aaSnw 		servers[i].priority = 0;
467e3c2d6aaSnw 		servers[i].weight = 100;
468e3c2d6aaSnw 		servers[i].port = defport;
469b3700b07SGordon Ross 		if ((host = scf_value2string(name, value)) == NULL)
470b3700b07SGordon Ross 			continue;
471c8e26105Sjp 		if ((portstr = strchr(host, ':')) != NULL) {
472c8e26105Sjp 			*portstr++ = '\0';
473e3c2d6aaSnw 			servers[i].port = strtol(portstr,
474c8e26105Sjp 			    (char **)NULL, 10);
475e3c2d6aaSnw 			if (servers[i].port == 0)
476e3c2d6aaSnw 				servers[i].port = defport;
477c8e26105Sjp 		}
478c8e26105Sjp 
479b3700b07SGordon Ross 		/*
480b3700b07SGordon Ross 		 * Ignore this server if the hostname is too long
481b3700b07SGordon Ross 		 * or empty (continue without i++)
482b3700b07SGordon Ross 		 */
483b3700b07SGordon Ross 		len = strlen(host);
484b3700b07SGordon Ross 		if (len == 0) {
485b3700b07SGordon Ross 			if (DBG(CONFIG, 1)) {
486b3700b07SGordon Ross 				idmapdlog(LOG_INFO, "%s host=\"\"", name);
487b3700b07SGordon Ross 			}
488b3700b07SGordon Ross 			continue;
489b3700b07SGordon Ross 		}
490b3700b07SGordon Ross 		if (len >= sizeof (servers->host)) {
491b3700b07SGordon Ross 			idmapdlog(LOG_ERR, "Host name too long: %s", host);
492b3700b07SGordon Ross 			idmapdlog(LOG_ERR, "ignoring %s value", name);
493b3700b07SGordon Ross 			continue;
494b3700b07SGordon Ross 		}
495b3700b07SGordon Ross 
496b3700b07SGordon Ross 		/*
497b3700b07SGordon Ross 		 * Get the host address too.  If we can't, then
498b3700b07SGordon Ross 		 * log an error and skip this host.
499b3700b07SGordon Ross 		 */
500b3700b07SGordon Ross 		(void) snprintf(port_str, sizeof (port_str),
501b3700b07SGordon Ross 		    "%d", servers[i].port);
502b3700b07SGordon Ross 		ai = NULL;
503b3700b07SGordon Ross 		err = getaddrinfo(host, port_str, &hints, &ai);
504b3700b07SGordon Ross 		if (err != 0) {
505b3700b07SGordon Ross 			idmapdlog(LOG_ERR, "No address for host: %s (%s)",
506b3700b07SGordon Ross 			    host, gai_strerror(err));
507b3700b07SGordon Ross 			idmapdlog(LOG_ERR, "ignoring %s value", name);
508b3700b07SGordon Ross 			continue;
509b3700b07SGordon Ross 		}
510b3700b07SGordon Ross 
511b3700b07SGordon Ross 		(void) strlcpy(servers[i].host, host,
512b3700b07SGordon Ross 		    sizeof (servers->host));
513b3700b07SGordon Ross 		(void) memcpy(&servers[i].addr, ai->ai_addr, ai->ai_addrlen);
514b3700b07SGordon Ross 		freeaddrinfo(ai);
515c8e26105Sjp 
516b3700b07SGordon Ross 		/* Added a DS to the array. */
517b3700b07SGordon Ross 		i++;
518c8e26105Sjp 	}
519b3700b07SGordon Ross 	free(host);
520c8e26105Sjp 
521b3700b07SGordon Ross 	if (i == 0) {
522b3700b07SGordon Ross 		if (DBG(CONFIG, 1)) {
523b3700b07SGordon Ross 			idmapdlog(LOG_INFO, "%s is empty", name);
524b3700b07SGordon Ross 		}
525b3700b07SGordon Ross 		free(servers);
526b3700b07SGordon Ross 		servers = NULL;
527b3700b07SGordon Ross 	}
528c8e26105Sjp 	*val = servers;
529c8e26105Sjp 
530e3c2d6aaSnw 	rc = 0;
531e3c2d6aaSnw 
532c8e26105Sjp destruction:
533c8e26105Sjp 	scf_value_destroy(value);
534c8e26105Sjp 	scf_iter_destroy(iter);
535c8e26105Sjp 	scf_property_destroy(scf_prop);
536c8e26105Sjp 
537c8e26105Sjp 	if (rc < 0) {
538c8e26105Sjp 		if (servers)
539c8e26105Sjp 			free(servers);
540c8e26105Sjp 		*val = NULL;
541c8e26105Sjp 	}
542c8e26105Sjp 
543c8e26105Sjp 	return (rc);
544c8e26105Sjp }
545c8e26105Sjp 
546c5c4113dSnw static int
547e3f2c991SKeyur Desai get_val_astring(idmap_cfg_handles_t *handles, const char *name, char **val)
548c5c4113dSnw {
549c5c4113dSnw 	int rc = 0;
550c5c4113dSnw 
551479ac375Sdm 	scf_property_t *scf_prop;
552479ac375Sdm 	scf_value_t *value;
553479ac375Sdm 
554479ac375Sdm 	scf_prop = scf_property_create(handles->main);
555479ac375Sdm 	if (scf_prop == NULL) {
556479ac375Sdm 		idmapdlog(LOG_ERR, "scf_property_create() failed: %s",
557479ac375Sdm 		    scf_strerror(scf_error()));
558479ac375Sdm 		return (-1);
559479ac375Sdm 	}
560479ac375Sdm 	value = scf_value_create(handles->main);
561479ac375Sdm 	if (value == NULL) {
562479ac375Sdm 		idmapdlog(LOG_ERR, "scf_value_create() failed: %s",
563479ac375Sdm 		    scf_strerror(scf_error()));
564479ac375Sdm 		scf_property_destroy(scf_prop);
565479ac375Sdm 		return (-1);
566479ac375Sdm 	}
567c5c4113dSnw 
568c8e26105Sjp 	*val = NULL;
569c5c4113dSnw 
570c8e26105Sjp 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
571c5c4113dSnw 	/* this is OK: the property is just undefined */
572c5c4113dSnw 		goto destruction;
573c5c4113dSnw 
574c8e26105Sjp 	if (scf_property_get_value(scf_prop, value) < 0) {
575651c0131Sbaban 		idmapdlog(LOG_ERR,
57671590c90Snw 		    "scf_property_get_value(%s) failed: %s",
57771590c90Snw 		    name, scf_strerror(scf_error()));
578c5c4113dSnw 		rc = -1;
579c5c4113dSnw 		goto destruction;
580c5c4113dSnw 	}
581c5c4113dSnw 
582e3f2c991SKeyur Desai 	*val = scf_value2string(name, value);
583e3f2c991SKeyur Desai 	if (*val == NULL)
584c5c4113dSnw 		rc = -1;
585c5c4113dSnw 
586c5c4113dSnw destruction:
587c5c4113dSnw 	scf_value_destroy(value);
588c5c4113dSnw 	scf_property_destroy(scf_prop);
589c5c4113dSnw 
590c5c4113dSnw 	if (rc < 0) {
591c5c4113dSnw 		if (*val)
592c5c4113dSnw 			free(*val);
593c5c4113dSnw 		*val = NULL;
594c5c4113dSnw 	}
595c5c4113dSnw 
596c5c4113dSnw 	return (rc);
597c5c4113dSnw }
598c5c4113dSnw 
599c8e26105Sjp 
6008edda628Sbaban static int
601148c5f43SAlan Wright del_val(
602148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
603148c5f43SAlan Wright     scf_propertygroup_t *pg,
604148c5f43SAlan Wright     const char *name)
605e3f2c991SKeyur Desai {
606e3f2c991SKeyur Desai 	int			rc = -1;
607e3f2c991SKeyur Desai 	int			ret;
608e3f2c991SKeyur Desai 	scf_transaction_t	*tx = NULL;
609e3f2c991SKeyur Desai 	scf_transaction_entry_t	*ent = NULL;
610e3f2c991SKeyur Desai 
611e3f2c991SKeyur Desai 	if ((tx = scf_transaction_create(handles->main)) == NULL) {
612e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
613e3f2c991SKeyur Desai 		    "scf_transaction_create() failed: %s",
614e3f2c991SKeyur Desai 		    scf_strerror(scf_error()));
615e3f2c991SKeyur Desai 		goto destruction;
616e3f2c991SKeyur Desai 	}
617e3f2c991SKeyur Desai 	if ((ent = scf_entry_create(handles->main)) == NULL) {
618e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
619e3f2c991SKeyur Desai 		    "scf_entry_create() failed: %s",
620e3f2c991SKeyur Desai 		    scf_strerror(scf_error()));
621e3f2c991SKeyur Desai 		goto destruction;
622e3f2c991SKeyur Desai 	}
623e3f2c991SKeyur Desai 
624e3f2c991SKeyur Desai 	do {
625148c5f43SAlan Wright 		if (scf_pg_update(pg) == -1) {
626e3f2c991SKeyur Desai 			idmapdlog(LOG_ERR,
627e3f2c991SKeyur Desai 			    "scf_pg_update(%s) failed: %s",
628e3f2c991SKeyur Desai 			    name, scf_strerror(scf_error()));
629e3f2c991SKeyur Desai 			goto destruction;
630e3f2c991SKeyur Desai 		}
631148c5f43SAlan Wright 		if (scf_transaction_start(tx, pg) != 0) {
632e3f2c991SKeyur Desai 			idmapdlog(LOG_ERR,
633e3f2c991SKeyur Desai 			    "scf_transaction_start(%s) failed: %s",
634e3f2c991SKeyur Desai 			    name, scf_strerror(scf_error()));
635e3f2c991SKeyur Desai 			goto destruction;
636e3f2c991SKeyur Desai 		}
637e3f2c991SKeyur Desai 
638e3f2c991SKeyur Desai 		if (scf_transaction_property_delete(tx, ent, name) != 0) {
639e3f2c991SKeyur Desai 			/* Don't complain if it already doesn't exist. */
640e3f2c991SKeyur Desai 			if (scf_error() != SCF_ERROR_NOT_FOUND) {
641e3f2c991SKeyur Desai 				idmapdlog(LOG_ERR,
642e3f2c991SKeyur Desai 				    "scf_transaction_property_delete() failed:"
643e3f2c991SKeyur Desai 				    " %s",
644e3f2c991SKeyur Desai 				    scf_strerror(scf_error()));
645e3f2c991SKeyur Desai 			}
646e3f2c991SKeyur Desai 			goto destruction;
647e3f2c991SKeyur Desai 		}
648e3f2c991SKeyur Desai 
649e3f2c991SKeyur Desai 		ret = scf_transaction_commit(tx);
650e3f2c991SKeyur Desai 
651e3f2c991SKeyur Desai 		if (ret == 0)
652e3f2c991SKeyur Desai 			scf_transaction_reset(tx);
653e3f2c991SKeyur Desai 	} while (ret == 0);
654e3f2c991SKeyur Desai 
655e3f2c991SKeyur Desai 	if (ret == -1) {
656e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
657e3f2c991SKeyur Desai 		    "scf_transaction_commit(%s) failed: %s",
658e3f2c991SKeyur Desai 		    name, scf_strerror(scf_error()));
659e3f2c991SKeyur Desai 		goto destruction;
660e3f2c991SKeyur Desai 	}
661e3f2c991SKeyur Desai 
662e3f2c991SKeyur Desai 	rc = 0;
663e3f2c991SKeyur Desai 
664e3f2c991SKeyur Desai destruction:
665e3f2c991SKeyur Desai 	if (ent != NULL)
666e3f2c991SKeyur Desai 		scf_entry_destroy(ent);
667e3f2c991SKeyur Desai 	if (tx != NULL)
668e3f2c991SKeyur Desai 		scf_transaction_destroy(tx);
669e3f2c991SKeyur Desai 	return (rc);
670e3f2c991SKeyur Desai }
671e3f2c991SKeyur Desai 
672e3f2c991SKeyur Desai 
673e3f2c991SKeyur Desai static int
674148c5f43SAlan Wright set_val(
675148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
676148c5f43SAlan Wright     scf_propertygroup_t *pg,
677148c5f43SAlan Wright     const char *name,
678148c5f43SAlan Wright     scf_value_t *value)
6798edda628Sbaban {
680e3c2d6aaSnw 	int			rc = -1;
681e3c2d6aaSnw 	int			i;
682148c5f43SAlan Wright 	scf_property_t		*prop = NULL;
6838edda628Sbaban 	scf_transaction_t	*tx = NULL;
6848edda628Sbaban 	scf_transaction_entry_t	*ent = NULL;
6858edda628Sbaban 
686148c5f43SAlan Wright 	if ((prop = scf_property_create(handles->main)) == NULL ||
687c8e26105Sjp 	    (tx = scf_transaction_create(handles->main)) == NULL ||
688c8e26105Sjp 	    (ent = scf_entry_create(handles->main)) == NULL) {
68971590c90Snw 		idmapdlog(LOG_ERR, "Unable to set property %s",
69071590c90Snw 		    name, scf_strerror(scf_error()));
6918edda628Sbaban 		goto destruction;
6928edda628Sbaban 	}
6938edda628Sbaban 
694148c5f43SAlan Wright 	for (i = 0; i < MAX_TRIES; i++) {
695148c5f43SAlan Wright 		int ret;
696148c5f43SAlan Wright 
697148c5f43SAlan Wright 		if (scf_pg_update(pg) == -1) {
6988edda628Sbaban 			idmapdlog(LOG_ERR,
699148c5f43SAlan Wright 			    "scf_pg_update() failed: %s",
700148c5f43SAlan Wright 			    scf_strerror(scf_error()));
7018edda628Sbaban 			goto destruction;
7028edda628Sbaban 		}
7038edda628Sbaban 
704148c5f43SAlan Wright 		if (scf_transaction_start(tx, pg) == -1) {
7058edda628Sbaban 			idmapdlog(LOG_ERR,
706148c5f43SAlan Wright 			    "scf_transaction_start(%s) failed: %s",
707148c5f43SAlan Wright 			    name, scf_strerror(scf_error()));
7088edda628Sbaban 			goto destruction;
7098edda628Sbaban 		}
7108edda628Sbaban 
711148c5f43SAlan Wright 		ret = scf_pg_get_property(pg, name, prop);
712148c5f43SAlan Wright 		if (ret == SCF_SUCCESS) {
713148c5f43SAlan Wright 			if (scf_transaction_property_change_type(tx, ent, name,
714148c5f43SAlan Wright 			    scf_value_type(value)) < 0) {
715148c5f43SAlan Wright 				idmapdlog(LOG_ERR,
716148c5f43SAlan Wright 				    "scf_transaction_property_change_type(%s)"
717148c5f43SAlan Wright 				    " failed: %s",
718148c5f43SAlan Wright 				    name, scf_strerror(scf_error()));
719148c5f43SAlan Wright 				goto destruction;
720148c5f43SAlan Wright 			}
721148c5f43SAlan Wright 		} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
722148c5f43SAlan Wright 			if (scf_transaction_property_new(tx, ent, name,
723148c5f43SAlan Wright 			    scf_value_type(value)) < 0) {
724148c5f43SAlan Wright 				idmapdlog(LOG_ERR,
725148c5f43SAlan Wright 				    "scf_transaction_property_new() failed: %s",
726148c5f43SAlan Wright 				    scf_strerror(scf_error()));
727148c5f43SAlan Wright 				goto destruction;
728148c5f43SAlan Wright 			}
729148c5f43SAlan Wright 		} else {
7308edda628Sbaban 			idmapdlog(LOG_ERR,
731148c5f43SAlan Wright 			    "scf_pg_get_property(%s) failed: %s",
732148c5f43SAlan Wright 			    name, scf_strerror(scf_error()));
7338edda628Sbaban 			goto destruction;
7348edda628Sbaban 		}
7358edda628Sbaban 
7368edda628Sbaban 		if (scf_entry_add_value(ent, value) == -1) {
7378edda628Sbaban 			idmapdlog(LOG_ERR,
73871590c90Snw 			    "scf_entry_add_value() failed: %s",
73971590c90Snw 			    scf_strerror(scf_error()));
7408edda628Sbaban 			goto destruction;
7418edda628Sbaban 		}
7428edda628Sbaban 
743148c5f43SAlan Wright 		ret = scf_transaction_commit(tx);
744148c5f43SAlan Wright 		if (ret == 0) {
7458edda628Sbaban 			/*
7468edda628Sbaban 			 * Property group set in scf_transaction_start()
7478edda628Sbaban 			 * is not the most recent. Update pg, reset tx and
7488edda628Sbaban 			 * retry tx.
7498edda628Sbaban 			 */
7508edda628Sbaban 			idmapdlog(LOG_WARNING,
751148c5f43SAlan Wright 			    "scf_transaction_commit(%s) failed: %s",
75271590c90Snw 			    name, scf_strerror(scf_error()));
7538edda628Sbaban 			scf_transaction_reset(tx);
754148c5f43SAlan Wright 			continue;
755148c5f43SAlan Wright 		}
756148c5f43SAlan Wright 		if (ret != 1) {
757148c5f43SAlan Wright 			idmapdlog(LOG_ERR,
758148c5f43SAlan Wright 			    "scf_transaction_commit(%s) failed: %s",
759148c5f43SAlan Wright 			    name, scf_strerror(scf_error()));
760148c5f43SAlan Wright 			goto destruction;
7618edda628Sbaban 		}
762148c5f43SAlan Wright 		/* Success! */
763148c5f43SAlan Wright 		rc = 0;
764148c5f43SAlan Wright 		break;
7658edda628Sbaban 	}
7668edda628Sbaban 
767148c5f43SAlan Wright destruction:
768148c5f43SAlan Wright 	scf_entry_destroy(ent);
769148c5f43SAlan Wright 	scf_transaction_destroy(tx);
770148c5f43SAlan Wright 	scf_property_destroy(prop);
771148c5f43SAlan Wright 	return (rc);
772148c5f43SAlan Wright }
773e3c2d6aaSnw 
774148c5f43SAlan Wright static int
775148c5f43SAlan Wright set_val_integer(
776148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
777148c5f43SAlan Wright     scf_propertygroup_t *pg,
778148c5f43SAlan Wright     const char *name,
779148c5f43SAlan Wright     int64_t val)
780148c5f43SAlan Wright {
781148c5f43SAlan Wright 	scf_value_t		*value = NULL;
782148c5f43SAlan Wright 	int			rc;
783148c5f43SAlan Wright 
784148c5f43SAlan Wright 	if ((value = scf_value_create(handles->main)) == NULL) {
785148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "Unable to set property %s",
78671590c90Snw 		    name, scf_strerror(scf_error()));
787148c5f43SAlan Wright 		return (-1);
788148c5f43SAlan Wright 	}
789148c5f43SAlan Wright 
790148c5f43SAlan Wright 	scf_value_set_integer(value, val);
791148c5f43SAlan Wright 
792148c5f43SAlan Wright 	rc = set_val(handles, pg, name, value);
7938edda628Sbaban 
7948edda628Sbaban 	scf_value_destroy(value);
795148c5f43SAlan Wright 
796148c5f43SAlan Wright 	return (rc);
797148c5f43SAlan Wright }
798148c5f43SAlan Wright 
799148c5f43SAlan Wright 
800148c5f43SAlan Wright static int
801148c5f43SAlan Wright set_val_astring(
802148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
803148c5f43SAlan Wright     scf_propertygroup_t *pg,
804148c5f43SAlan Wright     const char *name,
805148c5f43SAlan Wright     const char *val)
806148c5f43SAlan Wright {
807148c5f43SAlan Wright 	scf_value_t		*value = NULL;
808148c5f43SAlan Wright 	int			rc = -1;
809148c5f43SAlan Wright 
810148c5f43SAlan Wright 	if ((value = scf_value_create(handles->main)) == NULL) {
811148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "Unable to set property %s",
812148c5f43SAlan Wright 		    name, scf_strerror(scf_error()));
813148c5f43SAlan Wright 		goto out;
814148c5f43SAlan Wright 	}
815148c5f43SAlan Wright 
816148c5f43SAlan Wright 	if (scf_value_set_astring(value, val) == -1) {
817148c5f43SAlan Wright 		idmapdlog(LOG_ERR,
818148c5f43SAlan Wright 		    "scf_value_set_astring() failed: %s",
819148c5f43SAlan Wright 		    scf_strerror(scf_error()));
820148c5f43SAlan Wright 		goto out;
821148c5f43SAlan Wright 	}
822148c5f43SAlan Wright 
823148c5f43SAlan Wright 	rc = set_val(handles, pg, name, value);
824148c5f43SAlan Wright 
825148c5f43SAlan Wright out:
826148c5f43SAlan Wright 	scf_value_destroy(value);
8278edda628Sbaban 	return (rc);
8288edda628Sbaban }
8298edda628Sbaban 
8304d61c878SJulian Pullen 
8314d61c878SJulian Pullen 
8324d61c878SJulian Pullen /*
8334d61c878SJulian Pullen  * This function updates a boolean value.
8344d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
8354d61c878SJulian Pullen  */
836c8e26105Sjp static int
8377a8a68f5SJulian Pullen update_bool(boolean_t *value, boolean_t *new, char *name)
8384aa0a5e7Snw {
8394aa0a5e7Snw 	if (*value == *new)
8404aa0a5e7Snw 		return (0);
8414aa0a5e7Snw 
842148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
843148c5f43SAlan Wright 		idmapdlog(LOG_INFO, "change %s=%s", name,
844148c5f43SAlan Wright 		    *new ? "true" : "false");
845148c5f43SAlan Wright 	}
846148c5f43SAlan Wright 
8474aa0a5e7Snw 	*value = *new;
8484aa0a5e7Snw 	return (1);
8494aa0a5e7Snw }
8504aa0a5e7Snw 
85148cd229bSGordon Ross /*
85248cd229bSGordon Ross  * This function updates a uint64_t value.
85348cd229bSGordon Ross  * If nothing has changed it returns 0 else 1
85448cd229bSGordon Ross  */
85548cd229bSGordon Ross static int
85648cd229bSGordon Ross update_uint64(uint64_t *value, uint64_t *new, char *name)
85748cd229bSGordon Ross {
85848cd229bSGordon Ross 	if (*value == *new)
85948cd229bSGordon Ross 		return (0);
86048cd229bSGordon Ross 
86148cd229bSGordon Ross 	if (DBG(CONFIG, 1))
86248cd229bSGordon Ross 		idmapdlog(LOG_INFO, "change %s=%llu", name, *new);
86348cd229bSGordon Ross 
86448cd229bSGordon Ross 	*value = *new;
86548cd229bSGordon Ross 	return (1);
86648cd229bSGordon Ross }
86748cd229bSGordon Ross 
8684d61c878SJulian Pullen /*
8694d61c878SJulian Pullen  * This function updates a string value.
8704d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
8714d61c878SJulian Pullen  */
8724aa0a5e7Snw static int
8734aa0a5e7Snw update_string(char **value, char **new, char *name)
874c8e26105Sjp {
875148c5f43SAlan Wright 	int changed;
876148c5f43SAlan Wright 
877148c5f43SAlan Wright 	if (*new == NULL && *value != NULL)
878148c5f43SAlan Wright 		changed = 1;
879148c5f43SAlan Wright 	else if (*new != NULL && *value == NULL)
880148c5f43SAlan Wright 		changed = 1;
881148c5f43SAlan Wright 	else if (*new != NULL && *value != NULL && strcmp(*new, *value) != 0)
882148c5f43SAlan Wright 		changed = 1;
883148c5f43SAlan Wright 	else
884148c5f43SAlan Wright 		changed = 0;
885c8e26105Sjp 
886148c5f43SAlan Wright 	/*
887148c5f43SAlan Wright 	 * Note that even if unchanged we can't just return; we must free one
888148c5f43SAlan Wright 	 * of the values.
889148c5f43SAlan Wright 	 */
890c8e26105Sjp 
891148c5f43SAlan Wright 	if (DBG(CONFIG, 1) && changed)
892148c5f43SAlan Wright 		idmapdlog(LOG_INFO, "change %s=%s", name, CHECK_NULL(*new));
893148c5f43SAlan Wright 
894148c5f43SAlan Wright 	free(*value);
895c8e26105Sjp 	*value = *new;
896c8e26105Sjp 	*new = NULL;
897148c5f43SAlan Wright 	return (changed);
898c8e26105Sjp }
899c8e26105Sjp 
900e3f2c991SKeyur Desai static int
901e3f2c991SKeyur Desai update_enum(int *value, int *new, char *name, struct enum_lookup_map *map)
902e3f2c991SKeyur Desai {
903e3f2c991SKeyur Desai 	if (*value == *new)
904e3f2c991SKeyur Desai 		return (0);
905e3f2c991SKeyur Desai 
906148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
907148c5f43SAlan Wright 		idmapdlog(LOG_INFO, "change %s=%s", name,
908148c5f43SAlan Wright 		    enum_lookup(*new, map));
909148c5f43SAlan Wright 	}
910e3f2c991SKeyur Desai 
911e3f2c991SKeyur Desai 	*value = *new;
912e3f2c991SKeyur Desai 
913e3f2c991SKeyur Desai 	return (1);
914e3f2c991SKeyur Desai }
9154d61c878SJulian Pullen 
9164d61c878SJulian Pullen /*
9174d61c878SJulian Pullen  * This function updates a directory service structure.
9184d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
9194d61c878SJulian Pullen  */
920c8e26105Sjp static int
921b3700b07SGordon Ross update_dirs(ad_disc_ds_t **value, ad_disc_ds_t **new, char *name)
922c8e26105Sjp {
923c8e26105Sjp 
9240dcc7149Snw 	if (*value == *new)
9250dcc7149Snw 		/* Nothing to do */
926349d5d8fSnw 		return (0);
927c8e26105Sjp 
9280dcc7149Snw 	if (*value != NULL && *new != NULL &&
9290dcc7149Snw 	    ad_disc_compare_ds(*value, *new) == 0) {
930c8e26105Sjp 		free(*new);
931c8e26105Sjp 		*new = NULL;
932349d5d8fSnw 		return (0);
933c8e26105Sjp 	}
934c8e26105Sjp 
9354d61c878SJulian Pullen 	if (*value != NULL)
936c8e26105Sjp 		free(*value);
937c8e26105Sjp 
938c8e26105Sjp 	*value = *new;
939c8e26105Sjp 	*new = NULL;
9400dcc7149Snw 
9410dcc7149Snw 	if (*value == NULL) {
9420dcc7149Snw 		/* We're unsetting this DS property */
943148c5f43SAlan Wright 		if (DBG(CONFIG, 1))
944148c5f43SAlan Wright 			idmapdlog(LOG_INFO, "change %s=<none>", name);
945349d5d8fSnw 		return (1);
9460dcc7149Snw 	}
9470dcc7149Snw 
948148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
949148c5f43SAlan Wright 		/* List all the new DSs */
950b3700b07SGordon Ross 		char buf[64];
951b3700b07SGordon Ross 		ad_disc_ds_t *ds;
952b3700b07SGordon Ross 		for (ds = *value; ds->host[0] != '\0'; ds++) {
953b3700b07SGordon Ross 			if (ad_disc_getnameinfo(buf, sizeof (buf), &ds->addr))
954b3700b07SGordon Ross 				(void) strlcpy(buf, "?", sizeof (buf));
955b3700b07SGordon Ross 			idmapdlog(LOG_INFO, "change %s=%s addr=%s port=%d",
956b3700b07SGordon Ross 			    name, ds->host, buf, ds->port);
957148c5f43SAlan Wright 		}
958148c5f43SAlan Wright 	}
959349d5d8fSnw 	return (1);
960c8e26105Sjp }
961c8e26105Sjp 
9624d61c878SJulian Pullen /*
9634d61c878SJulian Pullen  * This function updates a trusted domains structure.
9644d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
9654d61c878SJulian Pullen  */
9664d61c878SJulian Pullen static int
9674d61c878SJulian Pullen update_trusted_domains(ad_disc_trusteddomains_t **value,
9684d61c878SJulian Pullen 			ad_disc_trusteddomains_t **new, char *name)
9694d61c878SJulian Pullen {
9704d61c878SJulian Pullen 	int i;
9714d61c878SJulian Pullen 
9724d61c878SJulian Pullen 	if (*value == *new)
9734d61c878SJulian Pullen 		/* Nothing to do */
9744d61c878SJulian Pullen 		return (0);
9754d61c878SJulian Pullen 
9764d61c878SJulian Pullen 	if (*value != NULL && *new != NULL &&
9774d61c878SJulian Pullen 	    ad_disc_compare_trusteddomains(*value, *new) == 0) {
9784d61c878SJulian Pullen 		free(*new);
9794d61c878SJulian Pullen 		*new = NULL;
9804d61c878SJulian Pullen 		return (0);
9814d61c878SJulian Pullen 	}
9824d61c878SJulian Pullen 
9834d61c878SJulian Pullen 	if (*value != NULL)
9844d61c878SJulian Pullen 		free(*value);
9854d61c878SJulian Pullen 
9864d61c878SJulian Pullen 	*value = *new;
9874d61c878SJulian Pullen 	*new = NULL;
9884d61c878SJulian Pullen 
9894d61c878SJulian Pullen 	if (*value == NULL) {
9904d61c878SJulian Pullen 		/* We're unsetting this DS property */
991148c5f43SAlan Wright 		if (DBG(CONFIG, 1))
992148c5f43SAlan Wright 			idmapdlog(LOG_INFO, "change %s=<none>", name);
9934d61c878SJulian Pullen 		return (1);
9944d61c878SJulian Pullen 	}
9954d61c878SJulian Pullen 
996148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
997148c5f43SAlan Wright 		/* List all the new domains */
998148c5f43SAlan Wright 		for (i = 0; (*value)[i].domain[0] != '\0'; i++) {
999148c5f43SAlan Wright 			idmapdlog(LOG_INFO, "change %s=%s direction=%s", name,
1000148c5f43SAlan Wright 			    (*value)[i].domain,
1001148c5f43SAlan Wright 			    enum_lookup((*value)[i].direction, trust_dir_map));
1002148c5f43SAlan Wright 		}
1003148c5f43SAlan Wright 	}
10044d61c878SJulian Pullen 	return (1);
10054d61c878SJulian Pullen }
10064d61c878SJulian Pullen 
10074d61c878SJulian Pullen 
10084d61c878SJulian Pullen /*
10094d61c878SJulian Pullen  * This function updates a domains in a forest structure.
10104d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
10114d61c878SJulian Pullen  */
10124d61c878SJulian Pullen static int
10134d61c878SJulian Pullen update_domains_in_forest(ad_disc_domainsinforest_t **value,
10144d61c878SJulian Pullen 			ad_disc_domainsinforest_t **new, char *name)
10154d61c878SJulian Pullen {
10164d61c878SJulian Pullen 	int i;
10174d61c878SJulian Pullen 
10184d61c878SJulian Pullen 	if (*value == *new)
10194d61c878SJulian Pullen 		/* Nothing to do */
10204d61c878SJulian Pullen 		return (0);
10214d61c878SJulian Pullen 
10224d61c878SJulian Pullen 	if (*value != NULL && *new != NULL &&
10234d61c878SJulian Pullen 	    ad_disc_compare_domainsinforest(*value, *new) == 0) {
10244d61c878SJulian Pullen 		free(*new);
10254d61c878SJulian Pullen 		*new = NULL;
10264d61c878SJulian Pullen 		return (0);
10274d61c878SJulian Pullen 	}
10284d61c878SJulian Pullen 
10294d61c878SJulian Pullen 	if (*value != NULL)
10304d61c878SJulian Pullen 		free(*value);
10314d61c878SJulian Pullen 
10324d61c878SJulian Pullen 	*value = *new;
10334d61c878SJulian Pullen 	*new = NULL;
10344d61c878SJulian Pullen 
10354d61c878SJulian Pullen 	if (*value == NULL) {
10364d61c878SJulian Pullen 		/* We're unsetting this DS property */
1037148c5f43SAlan Wright 		if (DBG(CONFIG, 1))
1038148c5f43SAlan Wright 			idmapdlog(LOG_INFO, "change %s=<none>", name);
10394d61c878SJulian Pullen 		return (1);
10404d61c878SJulian Pullen 	}
10414d61c878SJulian Pullen 
1042148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
1043148c5f43SAlan Wright 		/* List all the new domains */
1044148c5f43SAlan Wright 		for (i = 0; (*value)[i].domain[0] != '\0'; i++) {
1045148c5f43SAlan Wright 			idmapdlog(LOG_INFO, "change %s=%s", name,
1046148c5f43SAlan Wright 			    (*value)[i].domain);
1047148c5f43SAlan Wright 		}
1048148c5f43SAlan Wright 	}
10494d61c878SJulian Pullen 	return (1);
10504d61c878SJulian Pullen }
10514d61c878SJulian Pullen 
10524d61c878SJulian Pullen 
10534d61c878SJulian Pullen static void
10544d61c878SJulian Pullen free_trusted_forests(idmap_trustedforest_t **value, int *num_values)
10554d61c878SJulian Pullen {
10564d61c878SJulian Pullen 	int i;
10574d61c878SJulian Pullen 
10584d61c878SJulian Pullen 	for (i = 0; i < *num_values; i++) {
10594d61c878SJulian Pullen 		free((*value)[i].forest_name);
10604d61c878SJulian Pullen 		free((*value)[i].global_catalog);
10614d61c878SJulian Pullen 		free((*value)[i].domains_in_forest);
10624d61c878SJulian Pullen 	}
10634d61c878SJulian Pullen 	free(*value);
10644d61c878SJulian Pullen 	*value = NULL;
10654d61c878SJulian Pullen 	*num_values = 0;
10664d61c878SJulian Pullen }
10674d61c878SJulian Pullen 
10684d61c878SJulian Pullen 
10694d61c878SJulian Pullen static int
10704d61c878SJulian Pullen compare_trusteddomainsinforest(ad_disc_domainsinforest_t *df1,
10714d61c878SJulian Pullen 			ad_disc_domainsinforest_t *df2)
10724d61c878SJulian Pullen {
10737a8a68f5SJulian Pullen 	int		i, j;
10747a8a68f5SJulian Pullen 	int		num_df1 = 0;
10757a8a68f5SJulian Pullen 	int		num_df2 = 0;
10767a8a68f5SJulian Pullen 	boolean_t	match;
10774d61c878SJulian Pullen 
10784d61c878SJulian Pullen 	for (i = 0; df1[i].domain[0] != '\0'; i++)
10794d61c878SJulian Pullen 		if (df1[i].trusted)
10804d61c878SJulian Pullen 			num_df1++;
10814d61c878SJulian Pullen 
10824d61c878SJulian Pullen 	for (j = 0; df2[j].domain[0] != '\0'; j++)
10834d61c878SJulian Pullen 		if (df2[j].trusted)
10844d61c878SJulian Pullen 			num_df2++;
10854d61c878SJulian Pullen 
10864d61c878SJulian Pullen 	if (num_df1 != num_df2)
10874d61c878SJulian Pullen 		return (1);
10884d61c878SJulian Pullen 
10894d61c878SJulian Pullen 	for (i = 0; df1[i].domain[0] != '\0'; i++) {
10904d61c878SJulian Pullen 		if (df1[i].trusted) {
10917a8a68f5SJulian Pullen 			match = B_FALSE;
10924d61c878SJulian Pullen 			for (j = 0; df2[j].domain[0] != '\0'; j++) {
10934d61c878SJulian Pullen 				if (df2[j].trusted &&
10941fcced4cSJordan Brown 				    domain_eq(df1[i].domain, df2[j].domain) &&
10951fcced4cSJordan Brown 				    strcmp(df1[i].sid, df2[j].sid) == 0) {
10967a8a68f5SJulian Pullen 					match = B_TRUE;
10974d61c878SJulian Pullen 					break;
10984d61c878SJulian Pullen 				}
10994d61c878SJulian Pullen 			}
11004d61c878SJulian Pullen 			if (!match)
11014d61c878SJulian Pullen 				return (1);
11024d61c878SJulian Pullen 		}
11034d61c878SJulian Pullen 	}
11044d61c878SJulian Pullen 	return (0);
11054d61c878SJulian Pullen }
11064d61c878SJulian Pullen 
11074d61c878SJulian Pullen 
11084d61c878SJulian Pullen 
11094d61c878SJulian Pullen /*
11104d61c878SJulian Pullen  * This function updates trusted forest structure.
11114d61c878SJulian Pullen  * If nothing has changed it returns 0 else 1
11124d61c878SJulian Pullen  */
11134d61c878SJulian Pullen static int
11144d61c878SJulian Pullen update_trusted_forest(idmap_trustedforest_t **value, int *num_value,
11154d61c878SJulian Pullen 			idmap_trustedforest_t **new, int *num_new, char *name)
11164d61c878SJulian Pullen {
11174d61c878SJulian Pullen 	int i, j;
11187a8a68f5SJulian Pullen 	boolean_t match;
11194d61c878SJulian Pullen 
11204d61c878SJulian Pullen 	if (*value == *new)
11214d61c878SJulian Pullen 		/* Nothing to do */
11224d61c878SJulian Pullen 		return (0);
11234d61c878SJulian Pullen 
11244d61c878SJulian Pullen 	if (*value != NULL && *new != NULL) {
11254d61c878SJulian Pullen 		if (*num_value != *num_new)
11264d61c878SJulian Pullen 			goto not_equal;
11274d61c878SJulian Pullen 		for (i = 0; i < *num_value; i++) {
11287a8a68f5SJulian Pullen 			match = B_FALSE;
11294d61c878SJulian Pullen 			for (j = 0; j < *num_new; j++) {
11304d61c878SJulian Pullen 				if (strcmp((*value)[i].forest_name,
11314d61c878SJulian Pullen 				    (*new)[j].forest_name) == 0 &&
11324d61c878SJulian Pullen 				    ad_disc_compare_ds(
11334d61c878SJulian Pullen 				    (*value)[i].global_catalog,
11341fcced4cSJordan Brown 				    (*new)[j].global_catalog) == 0 &&
11354d61c878SJulian Pullen 				    compare_trusteddomainsinforest(
11364d61c878SJulian Pullen 				    (*value)[i].domains_in_forest,
11371fcced4cSJordan Brown 				    (*new)[j].domains_in_forest) == 0) {
11387a8a68f5SJulian Pullen 					match = B_TRUE;
11394d61c878SJulian Pullen 					break;
11404d61c878SJulian Pullen 				}
11414d61c878SJulian Pullen 			}
11424d61c878SJulian Pullen 			if (!match)
11434d61c878SJulian Pullen 				goto not_equal;
11444d61c878SJulian Pullen 		}
11454d61c878SJulian Pullen 		free_trusted_forests(new, num_new);
11464d61c878SJulian Pullen 		return (0);
11474d61c878SJulian Pullen 	}
11484d61c878SJulian Pullen not_equal:
11494d61c878SJulian Pullen 	if (*value != NULL)
11504d61c878SJulian Pullen 		free_trusted_forests(value, num_value);
11514d61c878SJulian Pullen 	*value = *new;
11524d61c878SJulian Pullen 	*num_value = *num_new;
11534d61c878SJulian Pullen 	*new = NULL;
11544d61c878SJulian Pullen 	*num_new = 0;
11554d61c878SJulian Pullen 
11564d61c878SJulian Pullen 	if (*value == NULL) {
11574d61c878SJulian Pullen 		/* We're unsetting this DS property */
1158148c5f43SAlan Wright 		if (DBG(CONFIG, 1))
1159148c5f43SAlan Wright 			idmapdlog(LOG_INFO, "change %s=<none>", name);
11604d61c878SJulian Pullen 		return (1);
11614d61c878SJulian Pullen 	}
11624d61c878SJulian Pullen 
1163148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
1164148c5f43SAlan Wright 		/* List all the trusted forests */
1165148c5f43SAlan Wright 		for (i = 0; i < *num_value; i++) {
1166148c5f43SAlan Wright 			idmap_trustedforest_t *f = &(*value)[i];
1167148c5f43SAlan Wright 			for (j = 0;
1168148c5f43SAlan Wright 			    f->domains_in_forest[j].domain[0] != '\0';
1169148c5f43SAlan Wright 			    j++) {
1170148c5f43SAlan Wright 				/* List trusted Domains in the forest. */
1171148c5f43SAlan Wright 				if (f->domains_in_forest[j].trusted)
1172148c5f43SAlan Wright 					idmapdlog(LOG_INFO,
1173148c5f43SAlan Wright 					    "change %s=%s domain=%s",
1174148c5f43SAlan Wright 					    name, f->forest_name,
1175148c5f43SAlan Wright 					    f->domains_in_forest[j].domain);
1176148c5f43SAlan Wright 			}
1177148c5f43SAlan Wright 			/* List the hosts */
1178148c5f43SAlan Wright 			for (j = 0;
1179148c5f43SAlan Wright 			    f->global_catalog[j].host[0] != '\0';
1180148c5f43SAlan Wright 			    j++) {
1181148c5f43SAlan Wright 				idmapdlog(LOG_INFO,
1182148c5f43SAlan Wright 				    "change %s=%s host=%s port=%d",
1183148c5f43SAlan Wright 				    name, f->forest_name,
1184148c5f43SAlan Wright 				    f->global_catalog[j].host,
1185148c5f43SAlan Wright 				    f->global_catalog[j].port);
1186148c5f43SAlan Wright 			}
11874d61c878SJulian Pullen 		}
11884d61c878SJulian Pullen 	}
11894d61c878SJulian Pullen 	return (1);
11904d61c878SJulian Pullen }
11914d61c878SJulian Pullen 
1192e3f2c991SKeyur Desai const char *
1193e3f2c991SKeyur Desai enum_lookup(int value, struct enum_lookup_map *map)
1194e3f2c991SKeyur Desai {
1195e3f2c991SKeyur Desai 	for (; map->string != NULL; map++) {
1196e3f2c991SKeyur Desai 		if (value == map->value) {
1197e3f2c991SKeyur Desai 			return (map->string);
1198e3f2c991SKeyur Desai 		}
1199e3f2c991SKeyur Desai 	}
1200e3f2c991SKeyur Desai 	return ("(invalid)");
1201e3f2c991SKeyur Desai }
1202c8e26105Sjp 
1203c8e26105Sjp /*
12040dcc7149Snw  * Returns 1 if the PF_ROUTE socket event indicates that we should rescan the
12050dcc7149Snw  * interfaces.
1206c8e26105Sjp  *
12070dcc7149Snw  * Shamelessly based on smb_nics_changed() and other PF_ROUTE uses in ON.
1208c8e26105Sjp  */
1209c8e26105Sjp static
1210c5866007SKeyur Desai boolean_t
12110dcc7149Snw pfroute_event_is_interesting(int rt_sock)
1212c8e26105Sjp {
12130dcc7149Snw 	int nbytes;
12140dcc7149Snw 	int64_t msg[2048 / 8];
12150dcc7149Snw 	struct rt_msghdr *rtm;
1216c5866007SKeyur Desai 	boolean_t is_interesting = B_FALSE;
1217c8e26105Sjp 
12180dcc7149Snw 	for (;;) {
12190dcc7149Snw 		if ((nbytes = read(rt_sock, msg, sizeof (msg))) <= 0)
12200dcc7149Snw 			break;
12210dcc7149Snw 		rtm = (struct rt_msghdr *)msg;
12220dcc7149Snw 		if (rtm->rtm_version != RTM_VERSION)
12230dcc7149Snw 			continue;
12240dcc7149Snw 		if (nbytes < rtm->rtm_msglen)
12250dcc7149Snw 			continue;
12260dcc7149Snw 		switch (rtm->rtm_type) {
12270dcc7149Snw 		case RTM_NEWADDR:
12280dcc7149Snw 		case RTM_DELADDR:
12290dcc7149Snw 		case RTM_IFINFO:
1230c5866007SKeyur Desai 			is_interesting = B_TRUE;
12310dcc7149Snw 			break;
12320dcc7149Snw 		default:
12330dcc7149Snw 			break;
12340dcc7149Snw 		}
1235c8e26105Sjp 	}
12360dcc7149Snw 	return (is_interesting);
12370dcc7149Snw }
12380dcc7149Snw 
12390dcc7149Snw /*
1240c5866007SKeyur Desai  * Wait for an event, and report what kind of event occurred.
12410dcc7149Snw  *
1242c5866007SKeyur Desai  * Note that there are cases where we are awoken but don't care about
1243c5866007SKeyur Desai  * the lower-level event.  We can't just loop here because we can't
1244c5866007SKeyur Desai  * readily calculate how long to sleep the next time.  We return
1245c5866007SKeyur Desai  * EVENT_NOTHING and let the caller loop.
12460dcc7149Snw  */
12470dcc7149Snw static
1248c5866007SKeyur Desai enum event_type
1249c5866007SKeyur Desai wait_for_event(struct timespec *timeoutp)
12500dcc7149Snw {
12510dcc7149Snw 	port_event_t pe;
1252c8e26105Sjp 
1253148c5f43SAlan Wright 	(void) memset(&pe, 0, sizeof (pe));
1254349d5d8fSnw 	if (port_get(idmapd_ev_port, &pe, timeoutp) != 0) {
1255c8e26105Sjp 		switch (errno) {
1256c8e26105Sjp 		case EINTR:
1257c5866007SKeyur Desai 			return (EVENT_NOTHING);
1258c8e26105Sjp 		case ETIME:
1259c8e26105Sjp 			/* Timeout */
1260c5866007SKeyur Desai 			return (EVENT_TIMEOUT);
1261c8e26105Sjp 		default:
12620dcc7149Snw 			/* EBADF, EBADFD, EFAULT, EINVAL (end of time?)? */
12630dcc7149Snw 			idmapdlog(LOG_ERR, "Event port failed: %s",
12640dcc7149Snw 			    strerror(errno));
12650dcc7149Snw 			exit(1);
12660dcc7149Snw 			/* NOTREACHED */
1267c8e26105Sjp 		}
1268c8e26105Sjp 	}
1269c8e26105Sjp 
12700dcc7149Snw 
1271c5866007SKeyur Desai 	switch (pe.portev_source) {
1272c5866007SKeyur Desai 	case 0:
12730dcc7149Snw 		/*
1274c5866007SKeyur Desai 		 * This isn't documented, but seems to be what you get if
1275c5866007SKeyur Desai 		 * the timeout is zero seconds and there are no events
1276c5866007SKeyur Desai 		 * pending.
12770dcc7149Snw 		 */
1278c5866007SKeyur Desai 		return (EVENT_TIMEOUT);
1279c8e26105Sjp 
1280c5866007SKeyur Desai 	case PORT_SOURCE_USER:
1281b3700b07SGordon Ross 		switch (pe.portev_events) {
1282b3700b07SGordon Ross 		case RECONFIGURE:
1283c5866007SKeyur Desai 			return (EVENT_REFRESH);
1284b3700b07SGordon Ross 		case POKE_AUTO_DISCOVERY:
1285b3700b07SGordon Ross 			return (EVENT_POKED);
1286b3700b07SGordon Ross 		case KICK_AUTO_DISCOVERY:
1287b3700b07SGordon Ross 			return (EVENT_KICKED);
1288b3700b07SGordon Ross 		}
1289b3700b07SGordon Ross 		return (EVENT_NOTHING);
1290e3c2d6aaSnw 
1291c5866007SKeyur Desai 	case PORT_SOURCE_FD:
1292c5866007SKeyur Desai 		if (pe.portev_object == rt_sock) {
1293c5866007SKeyur Desai 			/*
1294c5866007SKeyur Desai 			 * PF_ROUTE socket read event:
1295c5866007SKeyur Desai 			 *    re-associate fd
1296c5866007SKeyur Desai 			 *    handle event
1297c5866007SKeyur Desai 			 */
1298c5866007SKeyur Desai 			if (port_associate(idmapd_ev_port, PORT_SOURCE_FD,
1299c5866007SKeyur Desai 			    rt_sock, POLLIN, NULL) != 0) {
1300c5866007SKeyur Desai 				idmapdlog(LOG_ERR, "Failed to re-associate the "
1301c5866007SKeyur Desai 				    "routing socket with the event port: %s",
1302c5866007SKeyur Desai 				    strerror(errno));
1303c5866007SKeyur Desai 				abort();
1304c5866007SKeyur Desai 			}
1305c5866007SKeyur Desai 			/*
1306c5866007SKeyur Desai 			 * The network configuration may still be in flux.
1307c5866007SKeyur Desai 			 * No matter, the resolver will re-transmit and
1308c5866007SKeyur Desai 			 * timeout if need be.
1309c5866007SKeyur Desai 			 */
1310c5866007SKeyur Desai 			if (pfroute_event_is_interesting(rt_sock)) {
1311148c5f43SAlan Wright 				if (DBG(CONFIG, 1)) {
1312148c5f43SAlan Wright 					idmapdlog(LOG_DEBUG,
1313148c5f43SAlan Wright 					    "Interesting routing event");
1314148c5f43SAlan Wright 				}
1315c5866007SKeyur Desai 				return (EVENT_ROUTING);
1316c5866007SKeyur Desai 			} else {
1317148c5f43SAlan Wright 				if (DBG(CONFIG, 2)) {
1318148c5f43SAlan Wright 					idmapdlog(LOG_DEBUG,
1319148c5f43SAlan Wright 					    "Boring routing event");
1320148c5f43SAlan Wright 				}
1321c5866007SKeyur Desai 				return (EVENT_NOTHING);
1322c5866007SKeyur Desai 			}
1323349d5d8fSnw 		}
1324c5866007SKeyur Desai 		/* Event on an FD other than the routing FD? Ignore it. */
1325c5866007SKeyur Desai 		break;
1326c8e26105Sjp 	}
1327c8e26105Sjp 
1328c5866007SKeyur Desai 	return (EVENT_NOTHING);
1329c8e26105Sjp }
1330c8e26105Sjp 
1331c8e26105Sjp void *
1332c8e26105Sjp idmap_cfg_update_thread(void *arg)
1333c8e26105Sjp {
1334148c5f43SAlan Wright 	NOTE(ARGUNUSED(arg))
1335b3700b07SGordon Ross 	idmap_pg_config_t *pgcfg = &_idmapdstate.cfg->pgcfg;
1336c5866007SKeyur Desai 	const ad_disc_t		ad_ctx = _idmapdstate.cfg->handles.ad_ctx;
1337b3700b07SGordon Ross 	int flags = CFG_DISCOVER;
13380dcc7149Snw 
1339c5866007SKeyur Desai 	for (;;) {
1340c5866007SKeyur Desai 		struct timespec timeout;
1341c5866007SKeyur Desai 		struct timespec	*timeoutp;
1342c5866007SKeyur Desai 		int		rc;
1343b3700b07SGordon Ross 		int		ttl, max_ttl;
13440dcc7149Snw 
13450dcc7149Snw 		(void) ad_disc_SubnetChanged(ad_ctx);
1346c8e26105Sjp 
1347b3700b07SGordon Ross 		rc = idmap_cfg_load(_idmapdstate.cfg, flags);
1348c5866007SKeyur Desai 		if (rc < -1) {
13497a8a68f5SJulian Pullen 			idmapdlog(LOG_ERR, "Fatal errors while reading "
1350349d5d8fSnw 			    "SMF properties");
1351349d5d8fSnw 			exit(1);
1352c5866007SKeyur Desai 		} else if (rc == -1) {
1353c5866007SKeyur Desai 			idmapdlog(LOG_WARNING,
1354c5866007SKeyur Desai 			    "Errors re-loading configuration may cause AD "
1355c5866007SKeyur Desai 			    "lookups to fail");
1356349d5d8fSnw 		}
1357c8e26105Sjp 
1358c5866007SKeyur Desai 		/*
1359c5866007SKeyur Desai 		 * Wait for an interesting event.  Note that we might get
1360c5866007SKeyur Desai 		 * boring events between interesting events.  If so, we loop.
1361c5866007SKeyur Desai 		 */
1362b3700b07SGordon Ross 		flags = CFG_DISCOVER;
1363c5866007SKeyur Desai 		for (;;) {
1364b3700b07SGordon Ross 			/*
1365b3700b07SGordon Ross 			 * If we don't know our domain name, don't bother
1366b3700b07SGordon Ross 			 * with rediscovery until the next config change.
1367b3700b07SGordon Ross 			 * Avoids hourly noise in workgroup mode.
1368b3700b07SGordon Ross 			 */
1369b3700b07SGordon Ross 			if (pgcfg->domain_name == NULL)
1370b3700b07SGordon Ross 				ttl = -1;
1371b3700b07SGordon Ross 			else
1372b3700b07SGordon Ross 				ttl = ad_disc_get_TTL(ad_ctx);
1373c5866007SKeyur Desai 			if (ttl < 0) {
1374c5866007SKeyur Desai 				timeoutp = NULL;
1375c5866007SKeyur Desai 			} else {
1376b3700b07SGordon Ross 				max_ttl = (int)pgcfg->rediscovery_interval;
1377b3700b07SGordon Ross 				if (ttl > max_ttl)
1378b3700b07SGordon Ross 					ttl = max_ttl;
1379b3700b07SGordon Ross 				if (ttl < MIN_REDISCOVERY_INTERVAL)
1380b3700b07SGordon Ross 					ttl = MIN_REDISCOVERY_INTERVAL;
1381c5866007SKeyur Desai 				timeout.tv_sec = ttl;
1382c5866007SKeyur Desai 				timeout.tv_nsec = 0;
1383b3700b07SGordon Ross 				timeoutp = &timeout;
1384c5866007SKeyur Desai 			}
1385c5866007SKeyur Desai 
1386b3700b07SGordon Ross 			if (DBG(CONFIG, 1))
1387b3700b07SGordon Ross 				idmapdlog(LOG_DEBUG,
1388b3700b07SGordon Ross 				    "_cfg_update_thread waiting");
1389b3700b07SGordon Ross 
1390c5866007SKeyur Desai 			switch (wait_for_event(timeoutp)) {
1391c5866007SKeyur Desai 			case EVENT_NOTHING:
1392148c5f43SAlan Wright 				if (DBG(CONFIG, 2))
1393148c5f43SAlan Wright 					idmapdlog(LOG_DEBUG, "Boring event.");
1394c5866007SKeyur Desai 				continue;
1395c5866007SKeyur Desai 			case EVENT_REFRESH:
1396148c5f43SAlan Wright 				if (DBG(CONFIG, 1))
1397148c5f43SAlan Wright 					idmapdlog(LOG_INFO, "SMF refresh");
1398b3700b07SGordon Ross 				/*
1399b3700b07SGordon Ross 				 * Forget any DC we had previously.
1400b3700b07SGordon Ross 				 */
1401b3700b07SGordon Ross 				flags |= CFG_FORGET_DC;
1402b3700b07SGordon Ross 
1403c5866007SKeyur Desai 				/*
1404c5866007SKeyur Desai 				 * Blow away the ccache, we might have
1405c5866007SKeyur Desai 				 * re-joined the domain or joined a new one
1406c5866007SKeyur Desai 				 */
1407c5866007SKeyur Desai 				(void) unlink(IDMAP_CACHEDIR "/ccache");
1408c5866007SKeyur Desai 				break;
1409b3700b07SGordon Ross 			case EVENT_POKED:
1410b3700b07SGordon Ross 				if (DBG(CONFIG, 1))
1411b3700b07SGordon Ross 					idmapdlog(LOG_DEBUG, "poked");
1412b3700b07SGordon Ross 				break;
1413b3700b07SGordon Ross 			case EVENT_KICKED:
1414b3700b07SGordon Ross 				if (DBG(CONFIG, 1))
1415b3700b07SGordon Ross 					idmapdlog(LOG_DEBUG, "kicked");
1416b3700b07SGordon Ross 				flags |= CFG_FORGET_DC;
1417c5866007SKeyur Desai 				break;
1418c5866007SKeyur Desai 			case EVENT_TIMEOUT:
1419148c5f43SAlan Wright 				if (DBG(CONFIG, 1))
1420148c5f43SAlan Wright 					idmapdlog(LOG_DEBUG, "TTL expired");
1421c5866007SKeyur Desai 				break;
1422c5866007SKeyur Desai 			case EVENT_ROUTING:
1423c5866007SKeyur Desai 				/* Already logged to DEBUG */
1424c5866007SKeyur Desai 				break;
1425c5866007SKeyur Desai 			}
1426c5866007SKeyur Desai 			/* An interesting event! */
1427c5866007SKeyur Desai 			break;
1428c5866007SKeyur Desai 		}
1429c8e26105Sjp 	}
1430c5866007SKeyur Desai 	/*
1431c5866007SKeyur Desai 	 * Lint isn't happy with the concept of a function declared to
1432c5866007SKeyur Desai 	 * return something, that doesn't return.  Of course, merely adding
1433c5866007SKeyur Desai 	 * the return isn't enough, because it's never reached...
1434c5866007SKeyur Desai 	 */
1435c8e26105Sjp 	/*NOTREACHED*/
1436c8e26105Sjp 	return (NULL);
1437c8e26105Sjp }
1438c8e26105Sjp 
1439c8e26105Sjp int
14400dcc7149Snw idmap_cfg_start_updates(void)
1441c8e26105Sjp {
14420dcc7149Snw 	if ((idmapd_ev_port = port_create()) < 0) {
144371590c90Snw 		idmapdlog(LOG_ERR, "Failed to create event port: %s",
144471590c90Snw 		    strerror(errno));
1445c8e26105Sjp 		return (-1);
14460dcc7149Snw 	}
14470dcc7149Snw 
14480dcc7149Snw 	if ((rt_sock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
144971590c90Snw 		idmapdlog(LOG_ERR, "Failed to open routing socket: %s",
145071590c90Snw 		    strerror(errno));
14510dcc7149Snw 		(void) close(idmapd_ev_port);
14520dcc7149Snw 		return (-1);
14530dcc7149Snw 	}
14540dcc7149Snw 
14550dcc7149Snw 	if (fcntl(rt_sock, F_SETFL, O_NDELAY|O_NONBLOCK) < 0) {
145671590c90Snw 		idmapdlog(LOG_ERR, "Failed to set routing socket flags: %s",
145771590c90Snw 		    strerror(errno));
14580dcc7149Snw 		(void) close(rt_sock);
14590dcc7149Snw 		(void) close(idmapd_ev_port);
14600dcc7149Snw 		return (-1);
14610dcc7149Snw 	}
14620dcc7149Snw 
14630dcc7149Snw 	if (port_associate(idmapd_ev_port, PORT_SOURCE_FD,
14640dcc7149Snw 	    rt_sock, POLLIN, NULL) != 0) {
146571590c90Snw 		idmapdlog(LOG_ERR, "Failed to associate the routing "
146671590c90Snw 		    "socket with the event port: %s", strerror(errno));
14670dcc7149Snw 		(void) close(rt_sock);
14680dcc7149Snw 		(void) close(idmapd_ev_port);
14690dcc7149Snw 		return (-1);
14700dcc7149Snw 	}
14710dcc7149Snw 
14720dcc7149Snw 	if ((errno = pthread_create(&update_thread_handle, NULL,
14730dcc7149Snw 	    idmap_cfg_update_thread, NULL)) != 0) {
147471590c90Snw 		idmapdlog(LOG_ERR, "Failed to start update thread: %s",
147571590c90Snw 		    strerror(errno));
14760dcc7149Snw 		(void) port_dissociate(idmapd_ev_port, PORT_SOURCE_FD, rt_sock);
14770dcc7149Snw 		(void) close(rt_sock);
14780dcc7149Snw 		(void) close(idmapd_ev_port);
14790dcc7149Snw 		return (-1);
14800dcc7149Snw 	}
14810dcc7149Snw 
14820dcc7149Snw 	return (0);
1483c8e26105Sjp }
1484c8e26105Sjp 
1485479ac375Sdm /*
1486479ac375Sdm  * Reject attribute names with invalid characters.
1487479ac375Sdm  */
1488479ac375Sdm static
1489479ac375Sdm int
1490*a774f103SGordon Ross valid_ldap_attr(const char *attr)
1491*a774f103SGordon Ross {
1492479ac375Sdm 	for (; *attr; attr++) {
1493479ac375Sdm 		if (!isalnum(*attr) && *attr != '-' &&
1494479ac375Sdm 		    *attr != '_' && *attr != '.' && *attr != ';')
1495479ac375Sdm 			return (0);
1496479ac375Sdm 	}
1497479ac375Sdm 	return (1);
1498479ac375Sdm }
1499479ac375Sdm 
1500e3f2c991SKeyur Desai static
1501148c5f43SAlan Wright void
1502148c5f43SAlan Wright idmapd_set_debug(
1503148c5f43SAlan Wright     idmap_cfg_handles_t *handles,
1504148c5f43SAlan Wright     enum idmapd_debug item,
1505148c5f43SAlan Wright     const char *name)
1506e3f2c991SKeyur Desai {
1507148c5f43SAlan Wright 	int val;
1508e3f2c991SKeyur Desai 
1509148c5f43SAlan Wright 	if (item < 0 || item > IDMAPD_DEBUG_MAX)
1510148c5f43SAlan Wright 		return;
1511e3f2c991SKeyur Desai 
1512148c5f43SAlan Wright 	val = get_debug(handles, name);
1513e3f2c991SKeyur Desai 
1514148c5f43SAlan Wright 	if (val != _idmapdstate.debug[item])
1515148c5f43SAlan Wright 		idmapdlog(LOG_DEBUG, "%s/%s = %d", DEBUG_PG, name, val);
1516148c5f43SAlan Wright 
1517148c5f43SAlan Wright 	_idmapdstate.debug[item] = val;
1518148c5f43SAlan Wright }
1519148c5f43SAlan Wright 
1520148c5f43SAlan Wright static
1521148c5f43SAlan Wright void
1522148c5f43SAlan Wright check_smf_debug_mode(idmap_cfg_handles_t *handles)
1523148c5f43SAlan Wright {
1524148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_ALL, "all");
1525148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_CONFIG, "config");
1526148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_MAPPING, "mapping");
1527148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_DISC, "discovery");
1528148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_DNS, "dns");
1529148c5f43SAlan Wright 	idmapd_set_debug(handles, IDMAPD_DEBUG_LDAP, "ldap");
1530148c5f43SAlan Wright 
1531148c5f43SAlan Wright 	adutils_set_debug(AD_DEBUG_ALL, _idmapdstate.debug[IDMAPD_DEBUG_ALL]);
1532148c5f43SAlan Wright 	adutils_set_debug(AD_DEBUG_DISC, _idmapdstate.debug[IDMAPD_DEBUG_DISC]);
1533148c5f43SAlan Wright 	adutils_set_debug(AD_DEBUG_DNS, _idmapdstate.debug[IDMAPD_DEBUG_DNS]);
1534148c5f43SAlan Wright 	adutils_set_debug(AD_DEBUG_LDAP, _idmapdstate.debug[IDMAPD_DEBUG_LDAP]);
1535e3f2c991SKeyur Desai }
1536e3f2c991SKeyur Desai 
1537349d5d8fSnw /*
1538349d5d8fSnw  * This is the half of idmap_cfg_load() that loads property values from
1539349d5d8fSnw  * SMF (using the config/ property group of the idmap FMRI).
1540349d5d8fSnw  *
1541349d5d8fSnw  * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
1542479ac375Sdm  *               -3 -> hard smf config failures
1543349d5d8fSnw  * reading from SMF.
1544349d5d8fSnw  */
1545b3700b07SGordon Ross static int
1546349d5d8fSnw idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg,
1547e3f2c991SKeyur Desai 	int * const errors)
1548c5c4113dSnw {
1549e3c2d6aaSnw 	int rc;
1550e3f2c991SKeyur Desai 	char *s;
1551e3f2c991SKeyur Desai 
1552e3f2c991SKeyur Desai 	*errors = 0;
1553c8e26105Sjp 
1554c8e26105Sjp 	if (scf_pg_update(handles->config_pg) < 0) {
155571590c90Snw 		idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
155671590c90Snw 		    scf_strerror(scf_error()));
1557349d5d8fSnw 		return (-2);
1558c5c4113dSnw 	}
1559c5c4113dSnw 
1560148c5f43SAlan Wright 	if (scf_pg_update(handles->debug_pg) < 0) {
156171590c90Snw 		idmapdlog(LOG_ERR, "scf_pg_update() failed: %s",
156271590c90Snw 		    scf_strerror(scf_error()));
1563349d5d8fSnw 		return (-2);
1564c5c4113dSnw 	}
1565c5c4113dSnw 
1566148c5f43SAlan Wright 	check_smf_debug_mode(handles);
1567148c5f43SAlan Wright 
1568148c5f43SAlan Wright 	rc = get_val_bool(handles, "unresolvable_sid_mapping",
1569148c5f43SAlan Wright 	    &pgcfg->eph_map_unres_sids, B_TRUE);
1570479ac375Sdm 	if (rc != 0)
1571e3f2c991SKeyur Desai 		(*errors)++;
157271590c90Snw 
15731ed6b69aSGordon Ross 	rc = get_val_bool(handles, "use_ads",
15741ed6b69aSGordon Ross 	    &pgcfg->use_ads, B_TRUE);
15751ed6b69aSGordon Ross 	if (rc != 0)
15761ed6b69aSGordon Ross 		(*errors)++;
15771ed6b69aSGordon Ross 
1578148c5f43SAlan Wright 	rc = get_val_bool(handles, "use_lsa",
1579148c5f43SAlan Wright 	    &pgcfg->use_lsa, B_TRUE);
1580148c5f43SAlan Wright 	if (rc != 0)
1581148c5f43SAlan Wright 		(*errors)++;
1582148c5f43SAlan Wright 
1583148c5f43SAlan Wright 	rc = get_val_bool(handles, "disable_cross_forest_trusts",
1584148c5f43SAlan Wright 	    &pgcfg->disable_cross_forest_trusts, B_TRUE);
15854aa0a5e7Snw 	if (rc != 0)
1586e3f2c991SKeyur Desai 		(*errors)++;
1587e3f2c991SKeyur Desai 
1588e3f2c991SKeyur Desai 	rc = get_val_astring(handles, "directory_based_mapping", &s);
1589e3f2c991SKeyur Desai 	if (rc != 0)
1590e3f2c991SKeyur Desai 		(*errors)++;
1591e3f2c991SKeyur Desai 	else if (s == NULL || strcasecmp(s, "none") == 0)
1592e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1593e3f2c991SKeyur Desai 	else if (strcasecmp(s, "name") == 0)
1594e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NAME;
1595e3f2c991SKeyur Desai 	else if (strcasecmp(s, "idmu") == 0)
1596e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_IDMU;
1597e3f2c991SKeyur Desai 	else {
1598e3f2c991SKeyur Desai 		pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE;
1599e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR,
1600e3f2c991SKeyur Desai 		"config/directory_based_mapping:  invalid value \"%s\" ignored",
1601e3f2c991SKeyur Desai 		    s);
1602e3f2c991SKeyur Desai 		(*errors)++;
1603e3f2c991SKeyur Desai 	}
1604e3f2c991SKeyur Desai 	free(s);
16054aa0a5e7Snw 
1606c8e26105Sjp 	rc = get_val_int(handles, "list_size_limit",
1607c8e26105Sjp 	    &pgcfg->list_size_limit, SCF_TYPE_COUNT);
16084aa0a5e7Snw 	if (rc != 0)
1609e3f2c991SKeyur Desai 		(*errors)++;
1610c5c4113dSnw 
1611fea136a0SMatt Barden 	rc = get_val_int(handles, "max_threads",
1612fea136a0SMatt Barden 	    &pgcfg->max_threads, SCF_TYPE_COUNT);
1613fea136a0SMatt Barden 	if (rc != 0)
1614fea136a0SMatt Barden 		(*errors)++;
1615fea136a0SMatt Barden 	if (pgcfg->max_threads == 0)
1616fea136a0SMatt Barden 		pgcfg->max_threads = MAX_THREADS_DEFAULT;
1617fea136a0SMatt Barden 	if (pgcfg->max_threads > UINT_MAX)
1618fea136a0SMatt Barden 		pgcfg->max_threads = UINT_MAX;
1619fea136a0SMatt Barden 
162048cd229bSGordon Ross 	rc = get_val_int(handles, "id_cache_timeout",
162148cd229bSGordon Ross 	    &pgcfg->id_cache_timeout, SCF_TYPE_COUNT);
162248cd229bSGordon Ross 	if (rc != 0)
162348cd229bSGordon Ross 		(*errors)++;
162448cd229bSGordon Ross 	if (pgcfg->id_cache_timeout == 0)
162548cd229bSGordon Ross 		pgcfg->id_cache_timeout = ID_CACHE_TMO_DEFAULT;
162648cd229bSGordon Ross 
162748cd229bSGordon Ross 	rc = get_val_int(handles, "name_cache_timeout",
162848cd229bSGordon Ross 	    &pgcfg->name_cache_timeout, SCF_TYPE_COUNT);
162948cd229bSGordon Ross 	if (rc != 0)
163048cd229bSGordon Ross 		(*errors)++;
163148cd229bSGordon Ross 	if (pgcfg->name_cache_timeout == 0)
163248cd229bSGordon Ross 		pgcfg->name_cache_timeout = NAME_CACHE_TMO_DEFAULT;
163348cd229bSGordon Ross 
1634b3700b07SGordon Ross 	rc = get_val_int(handles, "rediscovery_interval",
1635b3700b07SGordon Ross 	    &pgcfg->rediscovery_interval, SCF_TYPE_COUNT);
1636b3700b07SGordon Ross 	if (rc != 0)
1637b3700b07SGordon Ross 		(*errors)++;
1638b3700b07SGordon Ross 	if (pgcfg->rediscovery_interval == 0)
1639b3700b07SGordon Ross 		pgcfg->rediscovery_interval = REDISCOVERY_INTERVAL_DEFAULT;
1640b3700b07SGordon Ross 
1641c8e26105Sjp 	rc = get_val_astring(handles, "domain_name",
1642c8e26105Sjp 	    &pgcfg->domain_name);
1643e3c2d6aaSnw 	if (rc != 0)
1644e3f2c991SKeyur Desai 		(*errors)++;
16454d61c878SJulian Pullen 	else {
1646148c5f43SAlan Wright 		if (pgcfg->domain_name != NULL &&
1647148c5f43SAlan Wright 		    pgcfg->domain_name[0] == '\0') {
1648148c5f43SAlan Wright 			free(pgcfg->domain_name);
1649148c5f43SAlan Wright 			pgcfg->domain_name = NULL;
1650148c5f43SAlan Wright 		}
1651*a774f103SGordon Ross 		if (pgcfg->domain_name != NULL)
1652*a774f103SGordon Ross 			pgcfg->domain_name_auto_disc = B_FALSE;
1653349d5d8fSnw 		(void) ad_disc_set_DomainName(handles->ad_ctx,
1654349d5d8fSnw 		    pgcfg->domain_name);
16554d61c878SJulian Pullen 	}
1656c8e26105Sjp 
1657c8e26105Sjp 	rc = get_val_astring(handles, "default_domain",
1658c8e26105Sjp 	    &pgcfg->default_domain);
1659c8e26105Sjp 	if (rc != 0) {
1660e3c2d6aaSnw 		/*
1661e3c2d6aaSnw 		 * SCF failures fetching config/default_domain we treat
1662e3c2d6aaSnw 		 * as fatal as they may leave ID mapping rules that
1663e3c2d6aaSnw 		 * match unqualified winnames flapping in the wind.
1664e3c2d6aaSnw 		 */
1665349d5d8fSnw 		return (-2);
1666c8e26105Sjp 	}
1667c8e26105Sjp 
1668e3f2c991SKeyur Desai 	if (pgcfg->default_domain == NULL && pgcfg->domain_name != NULL) {
1669e3f2c991SKeyur Desai 		pgcfg->default_domain = strdup(pgcfg->domain_name);
1670c5c4113dSnw 	}
1671c5c4113dSnw 
1672b3700b07SGordon Ross 	rc = get_val_astring(handles, "domain_guid", &s);
1673b3700b07SGordon Ross 	if (rc != 0) {
1674b3700b07SGordon Ross 		(*errors)++;
1675b3700b07SGordon Ross 	} else if (s == NULL || s[0] == '\0') {
1676b3700b07SGordon Ross 		/* OK, not set. */
1677b3700b07SGordon Ross 		free(s);
1678b3700b07SGordon Ross 	} else {
1679b3700b07SGordon Ross 		uuid_t u;
1680b3700b07SGordon Ross 
1681b3700b07SGordon Ross 		if (uuid_parse(s, u) != 0) {
1682b3700b07SGordon Ross 			idmapdlog(LOG_ERR,
1683b3700b07SGordon Ross 		"config/domain_guid: invalid value \"%s\" ignored", s);
1684b3700b07SGordon Ross 			free(s);
1685b3700b07SGordon Ross 			(*errors)++;
1686b3700b07SGordon Ross 		} else {
1687b3700b07SGordon Ross 			pgcfg->domain_guid = s;
1688b3700b07SGordon Ross 			pgcfg->domain_guid_auto_disc = B_FALSE;
1689b3700b07SGordon Ross 			(void) ad_disc_set_DomainGUID(handles->ad_ctx, u);
1690b3700b07SGordon Ross 		}
1691b3700b07SGordon Ross 	}
1692b3700b07SGordon Ross 
169312b65585SGordon Ross 	rc = get_val_astring(handles, "machine_uuid", &pgcfg->machine_uuid);
169412b65585SGordon Ross 	if (rc != 0)
169512b65585SGordon Ross 		(*errors)++;
169612b65585SGordon Ross 	if (pgcfg->machine_uuid == NULL) {
169712b65585SGordon Ross 		/* If machine_uuid not configured, generate one */
169812b65585SGordon Ross 		if (generate_machine_uuid(&pgcfg->machine_uuid) < 0)
169912b65585SGordon Ross 			return (-2);
170012b65585SGordon Ross 		rc = set_val_astring(handles, handles->config_pg,
170112b65585SGordon Ross 		    "machine_uuid", pgcfg->machine_uuid);
170212b65585SGordon Ross 		if (rc != 0)
170312b65585SGordon Ross 			(*errors)++;
170412b65585SGordon Ross 	}
170512b65585SGordon Ross 
1706c8e26105Sjp 	rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid);
1707e3c2d6aaSnw 	if (rc != 0)
1708e3f2c991SKeyur Desai 		(*errors)++;
1709c8e26105Sjp 	if (pgcfg->machine_sid == NULL) {
171012b65585SGordon Ross 		/*
171112b65585SGordon Ross 		 * If machine_sid not configured, generate one
171212b65585SGordon Ross 		 * from the machine UUID.
171312b65585SGordon Ross 		 */
171412b65585SGordon Ross 		if (generate_machine_sid(&pgcfg->machine_sid,
171512b65585SGordon Ross 		    pgcfg->machine_uuid) < 0)
1716349d5d8fSnw 			return (-2);
1717148c5f43SAlan Wright 		rc = set_val_astring(handles, handles->config_pg,
1718148c5f43SAlan Wright 		    "machine_sid", pgcfg->machine_sid);
1719e3c2d6aaSnw 		if (rc != 0)
1720e3f2c991SKeyur Desai 			(*errors)++;
17218edda628Sbaban 	}
1722c5c4113dSnw 
1723c8e26105Sjp 	rc = get_val_ds(handles, "domain_controller", 389,
1724c8e26105Sjp 	    &pgcfg->domain_controller);
1725e3c2d6aaSnw 	if (rc != 0)
1726e3f2c991SKeyur Desai 		(*errors)++;
17274d61c878SJulian Pullen 	else {
1728349d5d8fSnw 		(void) ad_disc_set_DomainController(handles->ad_ctx,
1729e3c2d6aaSnw 		    pgcfg->domain_controller);
17307a8a68f5SJulian Pullen 		pgcfg->domain_controller_auto_disc = B_FALSE;
17314d61c878SJulian Pullen 	}
1732c5c4113dSnw 
1733b3700b07SGordon Ross 	rc = get_val_ds(handles, "preferred_dc", 389,
1734b3700b07SGordon Ross 	    &pgcfg->preferred_dc);
1735b3700b07SGordon Ross 	if (rc != 0)
1736b3700b07SGordon Ross 		(*errors)++;
1737b3700b07SGordon Ross 	else {
1738b3700b07SGordon Ross 		(void) ad_disc_set_PreferredDC(handles->ad_ctx,
1739b3700b07SGordon Ross 		    pgcfg->preferred_dc);
1740b3700b07SGordon Ross 		pgcfg->preferred_dc_auto_disc = B_FALSE;
1741b3700b07SGordon Ross 	}
1742b3700b07SGordon Ross 
1743c8e26105Sjp 	rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name);
1744e3c2d6aaSnw 	if (rc != 0)
1745e3f2c991SKeyur Desai 		(*errors)++;
17464d61c878SJulian Pullen 	else {
1747*a774f103SGordon Ross 		if (pgcfg->forest_name != NULL &&
1748*a774f103SGordon Ross 		    pgcfg->forest_name[0] == '\0') {
1749*a774f103SGordon Ross 			free(pgcfg->forest_name);
1750*a774f103SGordon Ross 			pgcfg->forest_name = NULL;
1751*a774f103SGordon Ross 		}
1752*a774f103SGordon Ross 		if (pgcfg->forest_name != NULL)
1753*a774f103SGordon Ross 			pgcfg->forest_name_auto_disc = B_FALSE;
1754349d5d8fSnw 		(void) ad_disc_set_ForestName(handles->ad_ctx,
1755349d5d8fSnw 		    pgcfg->forest_name);
17564d61c878SJulian Pullen 	}
1757c8e26105Sjp 
1758c8e26105Sjp 	rc = get_val_astring(handles, "site_name", &pgcfg->site_name);
1759e3c2d6aaSnw 	if (rc != 0)
1760e3f2c991SKeyur Desai 		(*errors)++;
1761*a774f103SGordon Ross 	else {
1762*a774f103SGordon Ross 		if (pgcfg->site_name != NULL &&
1763*a774f103SGordon Ross 		    pgcfg->site_name[0] == '\0') {
1764*a774f103SGordon Ross 			free(pgcfg->site_name);
1765*a774f103SGordon Ross 			pgcfg->site_name = NULL;
1766*a774f103SGordon Ross 		}
1767*a774f103SGordon Ross 		if (pgcfg->site_name != NULL)
1768*a774f103SGordon Ross 			pgcfg->site_name_auto_disc = B_FALSE;
1769349d5d8fSnw 		(void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name);
1770*a774f103SGordon Ross 	}
1771c8e26105Sjp 
1772c8e26105Sjp 	rc = get_val_ds(handles, "global_catalog", 3268,
1773c8e26105Sjp 	    &pgcfg->global_catalog);
1774e3c2d6aaSnw 	if (rc != 0)
1775e3f2c991SKeyur Desai 		(*errors)++;
17764d61c878SJulian Pullen 	else {
1777349d5d8fSnw 		(void) ad_disc_set_GlobalCatalog(handles->ad_ctx,
1778349d5d8fSnw 		    pgcfg->global_catalog);
17797a8a68f5SJulian Pullen 		pgcfg->global_catalog_auto_disc = B_FALSE;
17804d61c878SJulian Pullen 	}
1781c8e26105Sjp 
1782e3f2c991SKeyur Desai 	/* Unless we're doing directory-based name mapping, we're done. */
1783e3f2c991SKeyur Desai 	if (pgcfg->directory_based_mapping != DIRECTORY_MAPPING_NAME)
1784e3f2c991SKeyur Desai 		return (0);
1785e8c27ec8Sbaban 
1786349d5d8fSnw 	rc = get_val_astring(handles, "ad_unixuser_attr",
1787349d5d8fSnw 	    &pgcfg->ad_unixuser_attr);
1788349d5d8fSnw 	if (rc != 0)
1789349d5d8fSnw 		return (-2);
1790479ac375Sdm 	if (pgcfg->ad_unixuser_attr != NULL &&
1791479ac375Sdm 	    !valid_ldap_attr(pgcfg->ad_unixuser_attr)) {
1792479ac375Sdm 		idmapdlog(LOG_ERR, "config/ad_unixuser_attr=%s is not a "
1793479ac375Sdm 		    "valid LDAP attribute name", pgcfg->ad_unixuser_attr);
1794479ac375Sdm 		return (-3);
1795479ac375Sdm 	}
1796e8c27ec8Sbaban 
1797349d5d8fSnw 	rc = get_val_astring(handles, "ad_unixgroup_attr",
1798349d5d8fSnw 	    &pgcfg->ad_unixgroup_attr);
1799349d5d8fSnw 	if (rc != 0)
1800349d5d8fSnw 		return (-2);
1801479ac375Sdm 	if (pgcfg->ad_unixgroup_attr != NULL &&
1802479ac375Sdm 	    !valid_ldap_attr(pgcfg->ad_unixgroup_attr)) {
1803479ac375Sdm 		idmapdlog(LOG_ERR, "config/ad_unixgroup_attr=%s is not a "
1804479ac375Sdm 		    "valid LDAP attribute name", pgcfg->ad_unixgroup_attr);
1805479ac375Sdm 		return (-3);
1806479ac375Sdm 	}
1807e8c27ec8Sbaban 
1808349d5d8fSnw 	rc = get_val_astring(handles, "nldap_winname_attr",
1809349d5d8fSnw 	    &pgcfg->nldap_winname_attr);
1810349d5d8fSnw 	if (rc != 0)
1811349d5d8fSnw 		return (-2);
1812479ac375Sdm 	if (pgcfg->nldap_winname_attr != NULL &&
1813479ac375Sdm 	    !valid_ldap_attr(pgcfg->nldap_winname_attr)) {
1814479ac375Sdm 		idmapdlog(LOG_ERR, "config/nldap_winname_attr=%s is not a "
1815479ac375Sdm 		    "valid LDAP attribute name", pgcfg->nldap_winname_attr);
1816349d5d8fSnw 		return (-3);
1817e8c27ec8Sbaban 	}
1818349d5d8fSnw 	if (pgcfg->ad_unixuser_attr == NULL &&
1819479ac375Sdm 	    pgcfg->ad_unixgroup_attr == NULL &&
1820479ac375Sdm 	    pgcfg->nldap_winname_attr == NULL) {
1821349d5d8fSnw 		idmapdlog(LOG_ERR,
1822e3f2c991SKeyur Desai 		    "If config/directory_based_mapping property is set to "
1823e3f2c991SKeyur Desai 		    "\"name\" then at least one of the following name mapping "
1824349d5d8fSnw 		    "attributes must be specified. (config/ad_unixuser_attr OR "
1825479ac375Sdm 		    "config/ad_unixgroup_attr OR config/nldap_winname_attr)");
1826349d5d8fSnw 		return (-3);
1827349d5d8fSnw 	}
1828c8e26105Sjp 
1829349d5d8fSnw 	return (rc);
1830349d5d8fSnw }
1831349d5d8fSnw 
1832148c5f43SAlan Wright static
1833148c5f43SAlan Wright void
1834148c5f43SAlan Wright log_if_unable(const void *val, const char *what)
1835148c5f43SAlan Wright {
1836148c5f43SAlan Wright 	if (val == NULL) {
1837148c5f43SAlan Wright 		idmapdlog(LOG_DEBUG, "unable to discover %s", what);
1838148c5f43SAlan Wright 	}
1839148c5f43SAlan Wright }
18404d61c878SJulian Pullen 
1841349d5d8fSnw static
1842349d5d8fSnw void
1843148c5f43SAlan Wright discover_trusted_domains(idmap_pg_config_t *pgcfg, ad_disc_t ad_ctx)
1844349d5d8fSnw {
18454d61c878SJulian Pullen 	ad_disc_t trusted_ctx;
18464d61c878SJulian Pullen 	int i, j, k, l;
18474d61c878SJulian Pullen 	char *forestname;
18484d61c878SJulian Pullen 	int num_trusteddomains;
18497a8a68f5SJulian Pullen 	boolean_t new_forest;
18504d61c878SJulian Pullen 	char *trusteddomain;
1851b3700b07SGordon Ross 	ad_disc_ds_t *globalcatalog;
18524d61c878SJulian Pullen 	idmap_trustedforest_t *trustedforests;
18534d61c878SJulian Pullen 	ad_disc_domainsinforest_t *domainsinforest;
1854349d5d8fSnw 
18554d61c878SJulian Pullen 	pgcfg->trusted_domains =
18564d61c878SJulian Pullen 	    ad_disc_get_TrustedDomains(ad_ctx, NULL);
18574d61c878SJulian Pullen 
18584d61c878SJulian Pullen 	if (pgcfg->forest_name != NULL && pgcfg->trusted_domains != NULL &&
18594d61c878SJulian Pullen 	    pgcfg->trusted_domains[0].domain[0] != '\0') {
18604d61c878SJulian Pullen 		/*
18614d61c878SJulian Pullen 		 * We have trusted domains.  We need to go through every
18624d61c878SJulian Pullen 		 * one and find its forest. If it is a new forest we then need
18634d61c878SJulian Pullen 		 * to find its Global Catalog and the domains in the forest
18644d61c878SJulian Pullen 		 */
18654d61c878SJulian Pullen 		for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++)
18664d61c878SJulian Pullen 			continue;
18674d61c878SJulian Pullen 		num_trusteddomains = i;
18684d61c878SJulian Pullen 
18694d61c878SJulian Pullen 		trustedforests = calloc(num_trusteddomains,
18704d61c878SJulian Pullen 		    sizeof (idmap_trustedforest_t));
18714d61c878SJulian Pullen 		j = 0;
18724d61c878SJulian Pullen 		for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) {
18734d61c878SJulian Pullen 			trusteddomain = pgcfg->trusted_domains[i].domain;
18744d61c878SJulian Pullen 			trusted_ctx = ad_disc_init();
1875148c5f43SAlan Wright 			(void) ad_disc_set_DomainName(trusted_ctx,
18764d61c878SJulian Pullen 			    trusteddomain);
18774d61c878SJulian Pullen 			forestname =
18784d61c878SJulian Pullen 			    ad_disc_get_ForestName(trusted_ctx, NULL);
18794d61c878SJulian Pullen 			if (forestname == NULL) {
1880148c5f43SAlan Wright 				if (DBG(CONFIG, 1)) {
1881148c5f43SAlan Wright 					idmapdlog(LOG_DEBUG,
1882148c5f43SAlan Wright 					    "unable to discover Forest Name"
1883148c5f43SAlan Wright 					    " for the trusted domain %s",
1884148c5f43SAlan Wright 					    trusteddomain);
1885148c5f43SAlan Wright 				}
18864d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
18874d61c878SJulian Pullen 				continue;
18884d61c878SJulian Pullen 			}
18894d61c878SJulian Pullen 
18904d61c878SJulian Pullen 			if (strcasecmp(forestname, pgcfg->forest_name) == 0) {
18914d61c878SJulian Pullen 				/*
18924d61c878SJulian Pullen 				 * Ignore the domain as it is part of
18934d61c878SJulian Pullen 				 * the primary forest
18944d61c878SJulian Pullen 				 */
18954d61c878SJulian Pullen 				free(forestname);
18964d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
18974d61c878SJulian Pullen 				continue;
18984d61c878SJulian Pullen 			}
18994d61c878SJulian Pullen 
19004d61c878SJulian Pullen 			/* Is this a new forest? */
19017a8a68f5SJulian Pullen 			new_forest = B_TRUE;
19024d61c878SJulian Pullen 			for (k = 0; k < j; k++) {
19034d61c878SJulian Pullen 				if (strcasecmp(forestname,
19044d61c878SJulian Pullen 				    trustedforests[k].forest_name) == 0) {
19057a8a68f5SJulian Pullen 					new_forest = B_FALSE;
19064d61c878SJulian Pullen 					domainsinforest =
19074d61c878SJulian Pullen 					    trustedforests[k].domains_in_forest;
19084d61c878SJulian Pullen 					break;
19094d61c878SJulian Pullen 				}
19104d61c878SJulian Pullen 			}
19114d61c878SJulian Pullen 			if (!new_forest) {
19124d61c878SJulian Pullen 				/* Mark the domain as trusted */
19134d61c878SJulian Pullen 				for (l = 0;
19144d61c878SJulian Pullen 				    domainsinforest[l].domain[0] != '\0'; l++) {
19151fcced4cSJordan Brown 					if (domain_eq(trusteddomain,
19161fcced4cSJordan Brown 					    domainsinforest[l].domain)) {
19174d61c878SJulian Pullen 						domainsinforest[l].trusted =
19184d61c878SJulian Pullen 						    TRUE;
19194d61c878SJulian Pullen 						break;
19204d61c878SJulian Pullen 					}
19214d61c878SJulian Pullen 				}
19224d61c878SJulian Pullen 				free(forestname);
19234d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
19244d61c878SJulian Pullen 				continue;
19254d61c878SJulian Pullen 			}
19264d61c878SJulian Pullen 
19274d61c878SJulian Pullen 			/*
19284d61c878SJulian Pullen 			 * Get the Global Catalog and the domains in
19294d61c878SJulian Pullen 			 * this new forest.
19304d61c878SJulian Pullen 			 */
19314d61c878SJulian Pullen 			globalcatalog =
19324d61c878SJulian Pullen 			    ad_disc_get_GlobalCatalog(trusted_ctx,
19334d61c878SJulian Pullen 			    AD_DISC_PREFER_SITE, NULL);
19344d61c878SJulian Pullen 			if (globalcatalog == NULL) {
1935148c5f43SAlan Wright 				if (DBG(CONFIG, 1)) {
1936148c5f43SAlan Wright 					idmapdlog(LOG_DEBUG,
1937148c5f43SAlan Wright 					    "unable to discover Global Catalog"
1938148c5f43SAlan Wright 					    " for the trusted domain %s",
1939148c5f43SAlan Wright 					    trusteddomain);
1940148c5f43SAlan Wright 				}
19414d61c878SJulian Pullen 				free(forestname);
19424d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
19434d61c878SJulian Pullen 				continue;
19444d61c878SJulian Pullen 			}
19454d61c878SJulian Pullen 			domainsinforest =
1946b3700b07SGordon Ross 			    ad_disc_get_DomainsInForest(trusted_ctx, NULL);
19474d61c878SJulian Pullen 			if (domainsinforest == NULL) {
1948148c5f43SAlan Wright 				if (DBG(CONFIG, 1)) {
1949148c5f43SAlan Wright 					idmapdlog(LOG_DEBUG,
1950148c5f43SAlan Wright 					    "unable to discover Domains in the"
1951148c5f43SAlan Wright 					    " Forest for the trusted domain %s",
1952148c5f43SAlan Wright 					    trusteddomain);
1953148c5f43SAlan Wright 				}
19544d61c878SJulian Pullen 				free(globalcatalog);
19554d61c878SJulian Pullen 				free(forestname);
19564d61c878SJulian Pullen 				ad_disc_fini(trusted_ctx);
19574d61c878SJulian Pullen 				continue;
19584d61c878SJulian Pullen 			}
19594d61c878SJulian Pullen 
19604d61c878SJulian Pullen 			trustedforests[j].forest_name = forestname;
19614d61c878SJulian Pullen 			trustedforests[j].global_catalog = globalcatalog;
19624d61c878SJulian Pullen 			trustedforests[j].domains_in_forest = domainsinforest;
19634d61c878SJulian Pullen 			j++;
19644d61c878SJulian Pullen 			/* Mark the domain as trusted */
19654d61c878SJulian Pullen 			for (l = 0; domainsinforest[l].domain[0] != '\0';
19664d61c878SJulian Pullen 			    l++) {
19671fcced4cSJordan Brown 				if (domain_eq(trusteddomain,
19681fcced4cSJordan Brown 				    domainsinforest[l].domain)) {
19694d61c878SJulian Pullen 					domainsinforest[l].trusted = TRUE;
19704d61c878SJulian Pullen 					break;
19714d61c878SJulian Pullen 				}
19724d61c878SJulian Pullen 			}
19734d61c878SJulian Pullen 			ad_disc_fini(trusted_ctx);
19744d61c878SJulian Pullen 		}
19754d61c878SJulian Pullen 		if (j > 0) {
19764d61c878SJulian Pullen 			pgcfg->num_trusted_forests = j;
19774d61c878SJulian Pullen 			pgcfg->trusted_forests = trustedforests;
19781fcced4cSJordan Brown 		} else {
19791fcced4cSJordan Brown 			free(trustedforests);
19804d61c878SJulian Pullen 		}
19814d61c878SJulian Pullen 	}
1982148c5f43SAlan Wright }
1983349d5d8fSnw 
1984148c5f43SAlan Wright /*
1985148c5f43SAlan Wright  * This is the half of idmap_cfg_load() that auto-discovers values of
1986148c5f43SAlan Wright  * discoverable properties that weren't already set via SMF properties.
1987148c5f43SAlan Wright  *
1988148c5f43SAlan Wright  * idmap_cfg_discover() is called *after* idmap_cfg_load_smf(), so it
1989148c5f43SAlan Wright  * needs to be careful not to overwrite any properties set in SMF.
1990148c5f43SAlan Wright  */
1991b3700b07SGordon Ross static void
1992b3700b07SGordon Ross idmap_cfg_discover1(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
1993148c5f43SAlan Wright {
1994148c5f43SAlan Wright 	ad_disc_t ad_ctx = handles->ad_ctx;
1995b3700b07SGordon Ross 	FILE *status_fp = NULL;
1996b3700b07SGordon Ross 	time_t t0, t1;
1997148c5f43SAlan Wright 
1998b3700b07SGordon Ross 	t0 = time(NULL);
1999148c5f43SAlan Wright 	if (DBG(CONFIG, 1))
2000b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "Running domain discovery.");
2001148c5f43SAlan Wright 
2002b3700b07SGordon Ross 	(void) unlink(IDMAP_CACHEDIR "/discovery.log");
2003b3700b07SGordon Ross 	status_fp = fopen(IDMAP_CACHEDIR "/discovery.log", "w");
2004b3700b07SGordon Ross 	if (status_fp) {
2005b3700b07SGordon Ross 		(void) fchmod(fileno(status_fp), 0644);
2006b3700b07SGordon Ross 		ad_disc_set_StatusFP(ad_ctx, status_fp);
2007b3700b07SGordon Ross 	}
2008148c5f43SAlan Wright 
2009148c5f43SAlan Wright 	if (pgcfg->domain_name == NULL) {
2010148c5f43SAlan Wright 		idmapdlog(LOG_DEBUG, "No domain name specified.");
2011b3700b07SGordon Ross 		if (status_fp)
2012b3700b07SGordon Ross 			(void) fprintf(status_fp, "(no domain name)\n");
2013b3700b07SGordon Ross 		goto out;
2014b3700b07SGordon Ross 	}
2015148c5f43SAlan Wright 
2016b3700b07SGordon Ross 	if (pgcfg->domain_controller == NULL)
2017b3700b07SGordon Ross 		pgcfg->domain_controller =
2018b3700b07SGordon Ross 		    ad_disc_get_DomainController(ad_ctx,
2019b3700b07SGordon Ross 		    AD_DISC_PREFER_SITE,
2020b3700b07SGordon Ross 		    &pgcfg->domain_controller_auto_disc);
2021b3700b07SGordon Ross 
2022b3700b07SGordon Ross 	if (pgcfg->domain_guid == NULL) {
2023b3700b07SGordon Ross 		char buf[UUID_PRINTABLE_STRING_LENGTH];
2024b3700b07SGordon Ross 		uchar_t *u = ad_disc_get_DomainGUID(ad_ctx,
2025b3700b07SGordon Ross 		    &pgcfg->domain_guid_auto_disc);
2026b3700b07SGordon Ross 		(void) memset(buf, 0, sizeof (buf));
2027b3700b07SGordon Ross 		if (u != NULL) {
2028b3700b07SGordon Ross 			uuid_unparse(u, buf);
2029b3700b07SGordon Ross 			pgcfg->domain_guid = strdup(buf);
2030b3700b07SGordon Ross 		}
2031b3700b07SGordon Ross 	}
2032b3700b07SGordon Ross 
2033b3700b07SGordon Ross 	if (pgcfg->forest_name == NULL)
2034b3700b07SGordon Ross 		pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx,
2035b3700b07SGordon Ross 		    &pgcfg->forest_name_auto_disc);
2036b3700b07SGordon Ross 
2037b3700b07SGordon Ross 	if (pgcfg->site_name == NULL)
2038b3700b07SGordon Ross 		pgcfg->site_name = ad_disc_get_SiteName(ad_ctx,
2039b3700b07SGordon Ross 		    &pgcfg->site_name_auto_disc);
2040b3700b07SGordon Ross 
2041b3700b07SGordon Ross 	if (DBG(CONFIG, 1)) {
2042b3700b07SGordon Ross 		log_if_unable(pgcfg->domain_name, "Domain Name");
2043b3700b07SGordon Ross 		log_if_unable(pgcfg->domain_controller,
2044b3700b07SGordon Ross 		    "Domain Controller");
2045b3700b07SGordon Ross 		log_if_unable(pgcfg->domain_guid, "Domain GUID");
2046b3700b07SGordon Ross 		log_if_unable(pgcfg->forest_name, "Forest Name");
2047b3700b07SGordon Ross 		log_if_unable(pgcfg->site_name, "Site Name");
2048b3700b07SGordon Ross 	}
2049b3700b07SGordon Ross 
2050b3700b07SGordon Ross out:
2051b3700b07SGordon Ross 	if (status_fp) {
2052b3700b07SGordon Ross 		ad_disc_set_StatusFP(ad_ctx, NULL);
2053b3700b07SGordon Ross 		(void) fclose(status_fp);
2054b3700b07SGordon Ross 		status_fp = NULL;
2055b3700b07SGordon Ross 	}
2056b3700b07SGordon Ross 
2057b3700b07SGordon Ross 	if (DBG(CONFIG, 1))
2058b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "Domain discovery done.");
2059b3700b07SGordon Ross 
2060b3700b07SGordon Ross 	/*
2061b3700b07SGordon Ross 	 * Log when this took more than 15 sec.
2062b3700b07SGordon Ross 	 */
2063b3700b07SGordon Ross 	t1 = time(NULL);
2064b3700b07SGordon Ross 	if (t1 > (t0 + 15)) {
2065b3700b07SGordon Ross 		idmapdlog(LOG_NOTICE, "Domain discovery took %d sec.",
2066b3700b07SGordon Ross 		    (int)(t1 - t0));
2067b3700b07SGordon Ross 		idmapdlog(LOG_NOTICE, "Check the DNS configuration.");
2068b3700b07SGordon Ross 	}
2069b3700b07SGordon Ross }
2070b3700b07SGordon Ross 
2071b3700b07SGordon Ross /*
2072b3700b07SGordon Ross  * This is the second part of discovery, which can take a while.
2073b3700b07SGordon Ross  * We don't want to hold up parties who just want to know what
2074b3700b07SGordon Ross  * domain controller we're using (like smbd), so this part runs
2075b3700b07SGordon Ross  * after we've updated that info in the "live" config and told
2076b3700b07SGordon Ross  * such consumers to go ahead.
2077b3700b07SGordon Ross  *
2078b3700b07SGordon Ross  * This is a lot like idmap_cfg_discover(), but used LDAP queries
2079b3700b07SGordon Ross  * get the forest information from the global catalog servers.
2080b3700b07SGordon Ross  *
2081b3700b07SGordon Ross  * Note: the previous update_* calls have usually nuked any
2082b3700b07SGordon Ross  * useful information from pgcfg before we get here, so we
2083b3700b07SGordon Ross  * can only use it store discovery results, not to read.
2084b3700b07SGordon Ross  */
2085b3700b07SGordon Ross static void
2086b3700b07SGordon Ross idmap_cfg_discover2(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
2087b3700b07SGordon Ross {
2088b3700b07SGordon Ross 	ad_disc_t ad_ctx = handles->ad_ctx;
2089b3700b07SGordon Ross 	FILE *status_fp = NULL;
2090b3700b07SGordon Ross 	time_t t0, t1;
2091b3700b07SGordon Ross 
2092b3700b07SGordon Ross 	t0 = time(NULL);
2093b3700b07SGordon Ross 	if (DBG(CONFIG, 1))
2094b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "Running forest discovery.");
2095b3700b07SGordon Ross 
2096b3700b07SGordon Ross 	status_fp = fopen(IDMAP_CACHEDIR "/discovery.log", "a");
2097b3700b07SGordon Ross 	if (status_fp)
2098b3700b07SGordon Ross 		ad_disc_set_StatusFP(ad_ctx, status_fp);
2099b3700b07SGordon Ross 
2100b3700b07SGordon Ross 	if (pgcfg->global_catalog == NULL)
2101b3700b07SGordon Ross 		pgcfg->global_catalog =
2102b3700b07SGordon Ross 		    ad_disc_get_GlobalCatalog(ad_ctx,
2103b3700b07SGordon Ross 		    AD_DISC_PREFER_SITE,
2104b3700b07SGordon Ross 		    &pgcfg->global_catalog_auto_disc);
2105b3700b07SGordon Ross 
2106b3700b07SGordon Ross 	if (pgcfg->global_catalog != NULL) {
2107148c5f43SAlan Wright 		pgcfg->domains_in_forest =
2108148c5f43SAlan Wright 		    ad_disc_get_DomainsInForest(ad_ctx, NULL);
2109148c5f43SAlan Wright 
2110148c5f43SAlan Wright 		if (!pgcfg->disable_cross_forest_trusts)
2111148c5f43SAlan Wright 			discover_trusted_domains(pgcfg, ad_ctx);
2112b3700b07SGordon Ross 	}
2113148c5f43SAlan Wright 
2114b3700b07SGordon Ross 	if (DBG(CONFIG, 1)) {
2115b3700b07SGordon Ross 		log_if_unable(pgcfg->global_catalog, "Global Catalog");
2116b3700b07SGordon Ross 		log_if_unable(pgcfg->domains_in_forest,
2117b3700b07SGordon Ross 		    "Domains in the Forest");
2118b3700b07SGordon Ross 		/* Empty trusted domains list is OK. */
2119148c5f43SAlan Wright 	}
2120c5866007SKeyur Desai 
2121b3700b07SGordon Ross 	if (status_fp) {
2122b3700b07SGordon Ross 		ad_disc_set_StatusFP(ad_ctx, NULL);
2123b3700b07SGordon Ross 		(void) fclose(status_fp);
2124b3700b07SGordon Ross 		status_fp = NULL;
2125b3700b07SGordon Ross 	}
2126148c5f43SAlan Wright 
2127148c5f43SAlan Wright 	if (DBG(CONFIG, 1))
2128b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "Forest discovery done.");
2129b3700b07SGordon Ross 
2130b3700b07SGordon Ross 	/*
2131b3700b07SGordon Ross 	 * Log when this took more than 30 sec.
2132b3700b07SGordon Ross 	 */
2133b3700b07SGordon Ross 	t1 = time(NULL);
2134b3700b07SGordon Ross 	if (t1 > (t0 + 30)) {
2135b3700b07SGordon Ross 		idmapdlog(LOG_NOTICE, "Forest discovery took %d sec.",
2136b3700b07SGordon Ross 		    (int)(t1 - t0));
2137b3700b07SGordon Ross 		idmapdlog(LOG_NOTICE, "Check AD join status.");
2138b3700b07SGordon Ross 	}
2139349d5d8fSnw }
2140349d5d8fSnw 
21414d61c878SJulian Pullen 
2142349d5d8fSnw /*
2143349d5d8fSnw  * idmap_cfg_load() is called at startup, and periodically via the
2144349d5d8fSnw  * update thread when the auto-discovery TTLs expire, as well as part of
2145349d5d8fSnw  * the refresh method, to update the current configuration.  It always
2146349d5d8fSnw  * reads from SMF, but you still have to refresh the service after
2147349d5d8fSnw  * changing the config pg in order for the changes to take effect.
2148349d5d8fSnw  *
2149148c5f43SAlan Wright  * There is one flag:
2150349d5d8fSnw  *
2151349d5d8fSnw  *  - CFG_DISCOVER
2152349d5d8fSnw  *
2153349d5d8fSnw  * If CFG_DISCOVER is set then idmap_cfg_load() calls
2154349d5d8fSnw  * idmap_cfg_discover() to discover, via DNS and LDAP lookups, property
2155349d5d8fSnw  * values that weren't set in SMF.
2156349d5d8fSnw  *
2157148c5f43SAlan Wright  * idmap_cfg_load() will log (to LOG_NOTICE) whether the configuration
2158148c5f43SAlan Wright  * changed.
2159349d5d8fSnw  *
2160349d5d8fSnw  * Return values: 0 -> success, -1 -> failure, -2 -> hard failures
2161349d5d8fSnw  * reading from SMF.
2162349d5d8fSnw  */
2163349d5d8fSnw int
2164349d5d8fSnw idmap_cfg_load(idmap_cfg_t *cfg, int flags)
2165349d5d8fSnw {
2166b3700b07SGordon Ross 	const ad_disc_t ad_ctx = cfg->handles.ad_ctx;
2167349d5d8fSnw 	int rc = 0;
2168e3f2c991SKeyur Desai 	int errors;
2169349d5d8fSnw 	int changed = 0;
2170b3700b07SGordon Ross 	int dc_changed = 0;
21714d61c878SJulian Pullen 	int ad_reload_required = 0;
2172349d5d8fSnw 	idmap_pg_config_t new_pgcfg, *live_pgcfg;
2173349d5d8fSnw 
2174148c5f43SAlan Wright 	if (DBG(CONFIG, 1))
2175148c5f43SAlan Wright 		idmapdlog(LOG_DEBUG, "Loading configuration.");
2176148c5f43SAlan Wright 
2177349d5d8fSnw 	live_pgcfg = &cfg->pgcfg;
2178349d5d8fSnw 	(void) memset(&new_pgcfg, 0, sizeof (new_pgcfg));
2179349d5d8fSnw 
2180148c5f43SAlan Wright 	(void) pthread_mutex_lock(&cfg->handles.mutex);
2181349d5d8fSnw 
2182349d5d8fSnw 	if ((rc = idmap_cfg_load_smf(&cfg->handles, &new_pgcfg, &errors)) < -1)
2183349d5d8fSnw 		goto err;
2184349d5d8fSnw 
2185b3700b07SGordon Ross 	if (flags & CFG_DISCOVER) {
2186b3700b07SGordon Ross 
2187b3700b07SGordon Ross 		ad_disc_refresh(ad_ctx);
2188b3700b07SGordon Ross 
2189b3700b07SGordon Ross 		/*
2190b3700b07SGordon Ross 		 * Unless we've been asked to forget the current DC,
2191b3700b07SGordon Ross 		 * give preference (in order) to the preferred DC if
2192b3700b07SGordon Ross 		 * configured, or the current DC.  These preferences
2193b3700b07SGordon Ross 		 * reduce undesirable DC changes.
2194b3700b07SGordon Ross 		 */
2195b3700b07SGordon Ross 		if (flags & CFG_FORGET_DC) {
2196b3700b07SGordon Ross 			(void) ad_disc_set_PreferredDC(ad_ctx, NULL);
2197b3700b07SGordon Ross 		} else if (new_pgcfg.preferred_dc != NULL) {
2198b3700b07SGordon Ross 			(void) ad_disc_set_PreferredDC(ad_ctx,
2199b3700b07SGordon Ross 			    new_pgcfg.preferred_dc);
2200b3700b07SGordon Ross 		} else if (live_pgcfg->domain_controller != NULL) {
2201b3700b07SGordon Ross 			(void) ad_disc_set_PreferredDC(ad_ctx,
2202b3700b07SGordon Ross 			    live_pgcfg->domain_controller);
2203b3700b07SGordon Ross 		} else {
2204b3700b07SGordon Ross 			(void) ad_disc_set_PreferredDC(ad_ctx, NULL);
2205b3700b07SGordon Ross 		}
2206b3700b07SGordon Ross 
2207b3700b07SGordon Ross 		/*
2208b3700b07SGordon Ross 		 * We want a way to tell adspriv_getdcname_1_svc()
2209b3700b07SGordon Ross 		 * (and others) that discovery is running and therefore
2210b3700b07SGordon Ross 		 * they may want to wait a bit or return an error...
2211b3700b07SGordon Ross 		 */
2212b3700b07SGordon Ross 		(void) mutex_lock(&_idmapdstate.addisc_lk);
2213b3700b07SGordon Ross 		_idmapdstate.addisc_st |= ADDISC_ST_RUNNING;
2214b3700b07SGordon Ross 		(void) mutex_unlock(&_idmapdstate.addisc_lk);
2215b3700b07SGordon Ross 
2216b3700b07SGordon Ross 		idmap_cfg_discover1(&cfg->handles, &new_pgcfg);
2217b3700b07SGordon Ross 
2218b3700b07SGordon Ross 		WRLOCK_CONFIG();
2219b3700b07SGordon Ross 		(void) mutex_lock(&_idmapdstate.addisc_lk);
2220b3700b07SGordon Ross 		_idmapdstate.addisc_st = 0;
2221b3700b07SGordon Ross 		(void) cond_broadcast(&_idmapdstate.addisc_cv);
2222b3700b07SGordon Ross 		(void) mutex_unlock(&_idmapdstate.addisc_lk);
2223b3700b07SGordon Ross 	} else {
2224b3700b07SGordon Ross 		WRLOCK_CONFIG();
2225b3700b07SGordon Ross 	}
2226349d5d8fSnw 
2227349d5d8fSnw 	/* Non-discoverable props updated here */
222848cd229bSGordon Ross 
222948cd229bSGordon Ross 	changed += update_uint64(&live_pgcfg->list_size_limit,
223048cd229bSGordon Ross 	    &new_pgcfg.list_size_limit, "list_size_limit");
223148cd229bSGordon Ross 
2232fea136a0SMatt Barden 	changed += update_uint64(&live_pgcfg->max_threads,
2233fea136a0SMatt Barden 	    &new_pgcfg.max_threads, "max_threads");
2234fea136a0SMatt Barden 
223548cd229bSGordon Ross 	changed += update_uint64(&live_pgcfg->id_cache_timeout,
223648cd229bSGordon Ross 	    &new_pgcfg.id_cache_timeout, "id_cache_timeout");
223748cd229bSGordon Ross 
223848cd229bSGordon Ross 	changed += update_uint64(&live_pgcfg->name_cache_timeout,
223948cd229bSGordon Ross 	    &new_pgcfg.name_cache_timeout, "name_cache_timeout");
224048cd229bSGordon Ross 
2241b3700b07SGordon Ross 	changed += update_uint64(&live_pgcfg->rediscovery_interval,
2242b3700b07SGordon Ross 	    &new_pgcfg.rediscovery_interval, "rediscovery_interval");
2243b3700b07SGordon Ross 
22444aa0a5e7Snw 	changed += update_string(&live_pgcfg->machine_sid,
2245349d5d8fSnw 	    &new_pgcfg.machine_sid, "machine_sid");
2246349d5d8fSnw 
22474aa0a5e7Snw 	changed += update_bool(&live_pgcfg->eph_map_unres_sids,
22484aa0a5e7Snw 	    &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping");
22494aa0a5e7Snw 
22501ed6b69aSGordon Ross 	changed += update_bool(&live_pgcfg->use_ads,
22511ed6b69aSGordon Ross 	    &new_pgcfg.use_ads, "use_ads");
22521ed6b69aSGordon Ross 
2253148c5f43SAlan Wright 	changed += update_bool(&live_pgcfg->use_lsa,
2254148c5f43SAlan Wright 	    &new_pgcfg.use_lsa, "use_lsa");
2255148c5f43SAlan Wright 
2256148c5f43SAlan Wright 	changed += update_bool(&live_pgcfg->disable_cross_forest_trusts,
2257148c5f43SAlan Wright 	    &new_pgcfg.disable_cross_forest_trusts,
2258148c5f43SAlan Wright 	    "disable_cross_forest_trusts");
2259148c5f43SAlan Wright 
2260e3f2c991SKeyur Desai 	changed += update_enum(&live_pgcfg->directory_based_mapping,
2261e3f2c991SKeyur Desai 	    &new_pgcfg.directory_based_mapping, "directory_based_mapping",
2262e3f2c991SKeyur Desai 	    directory_mapping_map);
2263349d5d8fSnw 
22644aa0a5e7Snw 	changed += update_string(&live_pgcfg->ad_unixuser_attr,
2265349d5d8fSnw 	    &new_pgcfg.ad_unixuser_attr, "ad_unixuser_attr");
2266349d5d8fSnw 
22674aa0a5e7Snw 	changed += update_string(&live_pgcfg->ad_unixgroup_attr,
2268349d5d8fSnw 	    &new_pgcfg.ad_unixgroup_attr, "ad_unixgroup_attr");
2269349d5d8fSnw 
22704aa0a5e7Snw 	changed += update_string(&live_pgcfg->nldap_winname_attr,
2271349d5d8fSnw 	    &new_pgcfg.nldap_winname_attr, "nldap_winname_attr");
2272349d5d8fSnw 
2273e3f2c991SKeyur Desai 	changed += update_string(&live_pgcfg->default_domain,
2274e3f2c991SKeyur Desai 	    &new_pgcfg.default_domain, "default_domain");
2275349d5d8fSnw 
2276b3700b07SGordon Ross 	changed += update_dirs(&live_pgcfg->preferred_dc,
2277b3700b07SGordon Ross 	    &new_pgcfg.preferred_dc, "preferred_dc");
2278b3700b07SGordon Ross 
2279b3700b07SGordon Ross 	/* Props that can be discovered or set in SMF updated here */
2280b3700b07SGordon Ross 
2281b3700b07SGordon Ross 	if (update_string(&live_pgcfg->domain_name,
2282b3700b07SGordon Ross 	    &new_pgcfg.domain_name, "domain_name")) {
2283b3700b07SGordon Ross 		changed++;
2284b3700b07SGordon Ross 		ad_reload_required = TRUE;
2285b3700b07SGordon Ross 		idmapd_set_krb5_realm(live_pgcfg->domain_name);
2286b3700b07SGordon Ross 	}
22874d61c878SJulian Pullen 	live_pgcfg->domain_name_auto_disc = new_pgcfg.domain_name_auto_disc;
2288349d5d8fSnw 
2289b3700b07SGordon Ross 	changed += update_string(&live_pgcfg->domain_guid,
2290b3700b07SGordon Ross 	    &new_pgcfg.domain_guid, "domain_guid");
2291b3700b07SGordon Ross 	live_pgcfg->domain_guid_auto_disc = new_pgcfg.domain_guid_auto_disc;
2292b3700b07SGordon Ross 
2293b3700b07SGordon Ross 	dc_changed = update_dirs(&live_pgcfg->domain_controller,
2294349d5d8fSnw 	    &new_pgcfg.domain_controller, "domain_controller");
2295b3700b07SGordon Ross 	changed += dc_changed;
22964d61c878SJulian Pullen 	live_pgcfg->domain_controller_auto_disc =
22974d61c878SJulian Pullen 	    new_pgcfg.domain_controller_auto_disc;
2298349d5d8fSnw 
22994aa0a5e7Snw 	changed += update_string(&live_pgcfg->forest_name,
2300349d5d8fSnw 	    &new_pgcfg.forest_name, "forest_name");
23014d61c878SJulian Pullen 	live_pgcfg->forest_name_auto_disc = new_pgcfg.forest_name_auto_disc;
2302349d5d8fSnw 
23034aa0a5e7Snw 	changed += update_string(&live_pgcfg->site_name,
2304349d5d8fSnw 	    &new_pgcfg.site_name, "site_name");
23054d61c878SJulian Pullen 	live_pgcfg->site_name_auto_disc = new_pgcfg.site_name_auto_disc;
2306349d5d8fSnw 
2307b3700b07SGordon Ross 	if (DBG(CONFIG, 1)) {
2308b3700b07SGordon Ross 		if (changed)
2309b3700b07SGordon Ross 			idmapdlog(LOG_NOTICE, "Configuration changed");
2310b3700b07SGordon Ross 		else
2311b3700b07SGordon Ross 			idmapdlog(LOG_NOTICE, "Configuration unchanged");
2312b3700b07SGordon Ross 	}
2313b3700b07SGordon Ross 
2314b3700b07SGordon Ross 	UNLOCK_CONFIG();
2315b3700b07SGordon Ross 
2316b3700b07SGordon Ross 	if (dc_changed != 0) {
2317b3700b07SGordon Ross 		notify_dc_changed();
2318349d5d8fSnw 	}
2319b3700b07SGordon Ross 
2320b3700b07SGordon Ross 	/*
2321b3700b07SGordon Ross 	 * Discovery2 can take a while.
2322b3700b07SGordon Ross 	 */
2323b3700b07SGordon Ross 	if (flags & CFG_DISCOVER) {
2324b3700b07SGordon Ross 		if (live_pgcfg->domain_name != NULL &&
2325b3700b07SGordon Ross 		    live_pgcfg->forest_name != NULL)
2326b3700b07SGordon Ross 			idmap_cfg_discover2(&cfg->handles, &new_pgcfg);
2327b3700b07SGordon Ross 		ad_disc_done(ad_ctx);
2328b3700b07SGordon Ross 	}
2329b3700b07SGordon Ross 
2330b3700b07SGordon Ross 	WRLOCK_CONFIG();
2331b3700b07SGordon Ross 
2332b3700b07SGordon Ross 	/* More props that can be discovered or set in SMF */
2333b3700b07SGordon Ross 
2334b3700b07SGordon Ross 	changed += update_dirs(&live_pgcfg->global_catalog,
2335b3700b07SGordon Ross 	    &new_pgcfg.global_catalog, "global_catalog");
23364d61c878SJulian Pullen 	live_pgcfg->global_catalog_auto_disc =
23374d61c878SJulian Pullen 	    new_pgcfg.global_catalog_auto_disc;
23384d61c878SJulian Pullen 
2339b3700b07SGordon Ross 	/* Props that are only discovered (never in SMF) */
2340b3700b07SGordon Ross 
23414d61c878SJulian Pullen 	if (update_domains_in_forest(&live_pgcfg->domains_in_forest,
23424d61c878SJulian Pullen 	    &new_pgcfg.domains_in_forest, "domains_in_forest")) {
23434d61c878SJulian Pullen 		changed++;
23444d61c878SJulian Pullen 		ad_reload_required = TRUE;
23454d61c878SJulian Pullen 	}
23464d61c878SJulian Pullen 
23474d61c878SJulian Pullen 	if (update_trusted_domains(&live_pgcfg->trusted_domains,
23484d61c878SJulian Pullen 	    &new_pgcfg.trusted_domains, "trusted_domains")) {
23494d61c878SJulian Pullen 		changed++;
23504d61c878SJulian Pullen 		if (live_pgcfg->trusted_domains != NULL &&
23514d61c878SJulian Pullen 		    live_pgcfg->trusted_domains[0].domain[0] != '\0')
23524d61c878SJulian Pullen 			ad_reload_required = TRUE;
23534d61c878SJulian Pullen 	}
23544d61c878SJulian Pullen 
23554d61c878SJulian Pullen 	if (update_trusted_forest(&live_pgcfg->trusted_forests,
23564d61c878SJulian Pullen 	    &live_pgcfg->num_trusted_forests, &new_pgcfg.trusted_forests,
23574d61c878SJulian Pullen 	    &new_pgcfg.num_trusted_forests, "trusted_forest")) {
23584d61c878SJulian Pullen 		changed++;
23594d61c878SJulian Pullen 		if (live_pgcfg->trusted_forests != NULL)
23604d61c878SJulian Pullen 			ad_reload_required = TRUE;
23614d61c878SJulian Pullen 	}
23624d61c878SJulian Pullen 
2363148c5f43SAlan Wright 	if (DBG(CONFIG, 1)) {
2364148c5f43SAlan Wright 		if (changed)
2365148c5f43SAlan Wright 			idmapdlog(LOG_NOTICE, "Configuration changed");
2366148c5f43SAlan Wright 		else
2367148c5f43SAlan Wright 			idmapdlog(LOG_NOTICE, "Configuration unchanged");
2368c8e26105Sjp 	}
2369e3c2d6aaSnw 
2370349d5d8fSnw 	UNLOCK_CONFIG();
2371349d5d8fSnw 
2372b3700b07SGordon Ross 	if (ad_reload_required)
2373b3700b07SGordon Ross 		reload_ad();
2374b3700b07SGordon Ross 
2375b3700b07SGordon Ross 	idmap_cfg_unload(&new_pgcfg);
2376b3700b07SGordon Ross 
2377349d5d8fSnw err:
2378148c5f43SAlan Wright 	(void) pthread_mutex_unlock(&cfg->handles.mutex);
2379c5c4113dSnw 
2380e8c27ec8Sbaban 	if (rc < -1)
2381e3c2d6aaSnw 		return (rc);
2382e3c2d6aaSnw 
2383e3c2d6aaSnw 	return ((errors == 0) ? 0 : -1);
2384c5c4113dSnw }
2385c5c4113dSnw 
2386651c0131Sbaban /*
2387651c0131Sbaban  * Initialize 'cfg'.
2388651c0131Sbaban  */
2389c5c4113dSnw idmap_cfg_t *
23904edd44c5Sjp idmap_cfg_init()
23914edd44c5Sjp {
2392c8e26105Sjp 	idmap_cfg_handles_t *handles;
2393c5c4113dSnw 
2394c5c4113dSnw 	/* First the smf repository handles: */
2395c5c4113dSnw 	idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t));
2396c5c4113dSnw 	if (!cfg) {
239771590c90Snw 		idmapdlog(LOG_ERR, "Out of memory");
2398c5c4113dSnw 		return (NULL);
2399c5c4113dSnw 	}
2400c8e26105Sjp 	handles = &cfg->handles;
2401c5c4113dSnw 
2402c8e26105Sjp 	(void) pthread_mutex_init(&handles->mutex, NULL);
2403c8e26105Sjp 
2404c8e26105Sjp 	if (!(handles->main = scf_handle_create(SCF_VERSION))) {
240571590c90Snw 		idmapdlog(LOG_ERR, "scf_handle_create() failed: %s",
240671590c90Snw 		    scf_strerror(scf_error()));
2407c5c4113dSnw 		goto error;
2408c5c4113dSnw 	}
2409c5c4113dSnw 
2410c8e26105Sjp 	if (scf_handle_bind(handles->main) < 0) {
241171590c90Snw 		idmapdlog(LOG_ERR, "scf_handle_bind() failed: %s",
241271590c90Snw 		    scf_strerror(scf_error()));
2413c5c4113dSnw 		goto error;
2414c5c4113dSnw 	}
2415c5c4113dSnw 
2416c8e26105Sjp 	if (!(handles->service = scf_service_create(handles->main)) ||
2417c8e26105Sjp 	    !(handles->instance = scf_instance_create(handles->main)) ||
2418c8e26105Sjp 	    !(handles->config_pg = scf_pg_create(handles->main)) ||
2419148c5f43SAlan Wright 	    !(handles->debug_pg = scf_pg_create(handles->main))) {
242071590c90Snw 		idmapdlog(LOG_ERR, "scf handle creation failed: %s",
242171590c90Snw 		    scf_strerror(scf_error()));
2422c5c4113dSnw 		goto error;
2423c5c4113dSnw 	}
2424c5c4113dSnw 
2425c8e26105Sjp 	if (scf_handle_decode_fmri(handles->main,
24264edd44c5Sjp 	    FMRI_BASE "/:properties/" CONFIG_PG,
24274edd44c5Sjp 	    NULL,				/* scope */
24284edd44c5Sjp 	    handles->service,		/* service */
24294edd44c5Sjp 	    handles->instance,		/* instance */
24304edd44c5Sjp 	    handles->config_pg,		/* pg */
24314edd44c5Sjp 	    NULL,				/* prop */
24324edd44c5Sjp 	    SCF_DECODE_FMRI_EXACT) < 0) {
243371590c90Snw 		idmapdlog(LOG_ERR, "scf_handle_decode_fmri() failed: %s",
243471590c90Snw 		    scf_strerror(scf_error()));
2435c5c4113dSnw 		goto error;
2436c5c4113dSnw 	}
2437c5c4113dSnw 
2438c8e26105Sjp 	if (scf_service_get_pg(handles->service,
2439148c5f43SAlan Wright 	    DEBUG_PG, handles->debug_pg) < 0) {
2440148c5f43SAlan Wright 		idmapdlog(LOG_ERR, "Property group \"%s\": %s",
2441148c5f43SAlan Wright 		    DEBUG_PG, scf_strerror(scf_error()));
2442c5c4113dSnw 		goto error;
2443c5c4113dSnw 	}
2444c5c4113dSnw 
2445148c5f43SAlan Wright 	check_smf_debug_mode(handles);
2446e3f2c991SKeyur Desai 
2447c8e26105Sjp 	/* Initialize AD Auto Discovery context */
2448c8e26105Sjp 	handles->ad_ctx = ad_disc_init();
2449c8e26105Sjp 	if (handles->ad_ctx == NULL)
2450c8e26105Sjp 		goto error;
2451c8e26105Sjp 
2452c5c4113dSnw 	return (cfg);
2453c5c4113dSnw 
2454c5c4113dSnw error:
2455c5c4113dSnw 	(void) idmap_cfg_fini(cfg);
2456c5c4113dSnw 	return (NULL);
2457c5c4113dSnw }
2458c5c4113dSnw 
2459c8e26105Sjp void
24604edd44c5Sjp idmap_cfg_unload(idmap_pg_config_t *pgcfg)
24614edd44c5Sjp {
2462c8e26105Sjp 
2463c8e26105Sjp 	if (pgcfg->default_domain) {
2464c8e26105Sjp 		free(pgcfg->default_domain);
2465c8e26105Sjp 		pgcfg->default_domain = NULL;
2466c8e26105Sjp 	}
2467c8e26105Sjp 	if (pgcfg->domain_name) {
2468c8e26105Sjp 		free(pgcfg->domain_name);
2469c8e26105Sjp 		pgcfg->domain_name = NULL;
2470c8e26105Sjp 	}
2471b3700b07SGordon Ross 	if (pgcfg->domain_guid) {
2472b3700b07SGordon Ross 		free(pgcfg->domain_guid);
2473b3700b07SGordon Ross 		pgcfg->domain_guid = NULL;
2474b3700b07SGordon Ross 	}
2475c8e26105Sjp 	if (pgcfg->machine_sid) {
2476c8e26105Sjp 		free(pgcfg->machine_sid);
2477c8e26105Sjp 		pgcfg->machine_sid = NULL;
2478c8e26105Sjp 	}
2479c8e26105Sjp 	if (pgcfg->domain_controller) {
2480c5c4113dSnw 		free(pgcfg->domain_controller);
2481c8e26105Sjp 		pgcfg->domain_controller = NULL;
2482c8e26105Sjp 	}
2483c8e26105Sjp 	if (pgcfg->forest_name) {
2484c8e26105Sjp 		free(pgcfg->forest_name);
2485c8e26105Sjp 		pgcfg->forest_name = NULL;
2486c8e26105Sjp 	}
2487c8e26105Sjp 	if (pgcfg->site_name) {
2488c8e26105Sjp 		free(pgcfg->site_name);
2489c8e26105Sjp 		pgcfg->site_name = NULL;
2490c8e26105Sjp 	}
2491c8e26105Sjp 	if (pgcfg->global_catalog) {
2492c8e26105Sjp 		free(pgcfg->global_catalog);
2493c8e26105Sjp 		pgcfg->global_catalog = NULL;
2494c8e26105Sjp 	}
24954d61c878SJulian Pullen 	if (pgcfg->trusted_domains) {
24964d61c878SJulian Pullen 		free(pgcfg->trusted_domains);
24974d61c878SJulian Pullen 		pgcfg->trusted_domains = NULL;
24984d61c878SJulian Pullen 	}
24994d61c878SJulian Pullen 	if (pgcfg->trusted_forests)
25004d61c878SJulian Pullen 		free_trusted_forests(&pgcfg->trusted_forests,
25014d61c878SJulian Pullen 		    &pgcfg->num_trusted_forests);
25024d61c878SJulian Pullen 
2503e8c27ec8Sbaban 	if (pgcfg->ad_unixuser_attr) {
2504e8c27ec8Sbaban 		free(pgcfg->ad_unixuser_attr);
2505e8c27ec8Sbaban 		pgcfg->ad_unixuser_attr = NULL;
2506e8c27ec8Sbaban 	}
2507e8c27ec8Sbaban 	if (pgcfg->ad_unixgroup_attr) {
2508e8c27ec8Sbaban 		free(pgcfg->ad_unixgroup_attr);
2509e8c27ec8Sbaban 		pgcfg->ad_unixgroup_attr = NULL;
2510e8c27ec8Sbaban 	}
2511e8c27ec8Sbaban 	if (pgcfg->nldap_winname_attr) {
2512e8c27ec8Sbaban 		free(pgcfg->nldap_winname_attr);
2513e8c27ec8Sbaban 		pgcfg->nldap_winname_attr = NULL;
2514e8c27ec8Sbaban 	}
2515c5c4113dSnw }
2516c5c4113dSnw 
2517c5c4113dSnw int
2518c5c4113dSnw idmap_cfg_fini(idmap_cfg_t *cfg)
2519c5c4113dSnw {
2520c8e26105Sjp 	idmap_cfg_handles_t *handles = &cfg->handles;
2521c8e26105Sjp 	idmap_cfg_unload(&cfg->pgcfg);
2522c8e26105Sjp 
2523c8e26105Sjp 	(void) pthread_mutex_destroy(&handles->mutex);
2524c8e26105Sjp 	scf_pg_destroy(handles->config_pg);
2525148c5f43SAlan Wright 	if (handles->debug_pg != NULL)
2526148c5f43SAlan Wright 		scf_pg_destroy(handles->debug_pg);
2527c8e26105Sjp 	scf_instance_destroy(handles->instance);
2528c8e26105Sjp 	scf_service_destroy(handles->service);
2529c8e26105Sjp 	scf_handle_destroy(handles->main);
2530e8c27ec8Sbaban 	if (handles->ad_ctx != NULL)
2531e8c27ec8Sbaban 		ad_disc_fini(handles->ad_ctx);
2532c5c4113dSnw 	free(cfg);
2533c5c4113dSnw 
2534c5c4113dSnw 	return (0);
2535c5c4113dSnw }
25360dcc7149Snw 
25370dcc7149Snw void
25380dcc7149Snw idmap_cfg_poke_updates(void)
25390dcc7149Snw {
2540b3700b07SGordon Ross 	int prev_st;
2541b3700b07SGordon Ross 
2542b3700b07SGordon Ross 	if (DBG(CONFIG, 1)) {
2543b3700b07SGordon Ross 		idmapdlog(LOG_INFO, "idmap_cfg_poke_updates");
2544b3700b07SGordon Ross 	}
2545b3700b07SGordon Ross 
2546b3700b07SGordon Ross 	(void) mutex_lock(&_idmapdstate.addisc_lk);
2547b3700b07SGordon Ross 	prev_st = _idmapdstate.addisc_st;
2548b3700b07SGordon Ross 	_idmapdstate.addisc_st |= ADDISC_ST_REQUESTED;
2549b3700b07SGordon Ross 	(void) mutex_unlock(&_idmapdstate.addisc_lk);
2550b3700b07SGordon Ross 
2551b3700b07SGordon Ross 	if (prev_st & ADDISC_ST_REQUESTED) {
2552b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "already poked");
2553b3700b07SGordon Ross 	} else {
2554b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "port send poke");
2555349d5d8fSnw 		(void) port_send(idmapd_ev_port, POKE_AUTO_DISCOVERY, NULL);
2556b3700b07SGordon Ross 	}
2557b3700b07SGordon Ross }
2558b3700b07SGordon Ross 
2559b3700b07SGordon Ross void
2560b3700b07SGordon Ross idmap_cfg_force_rediscovery(void)
2561b3700b07SGordon Ross {
2562b3700b07SGordon Ross 	int prev_st;
2563b3700b07SGordon Ross 
2564b3700b07SGordon Ross 	if (DBG(CONFIG, 1)) {
2565b3700b07SGordon Ross 		idmapdlog(LOG_INFO, "idmap_cfg_force_rediscovery");
2566b3700b07SGordon Ross 	}
2567b3700b07SGordon Ross 
2568b3700b07SGordon Ross 	(void) mutex_lock(&_idmapdstate.addisc_lk);
2569b3700b07SGordon Ross 	prev_st = _idmapdstate.addisc_st;
2570b3700b07SGordon Ross 	_idmapdstate.addisc_st |= ADDISC_ST_REQUESTED;
2571b3700b07SGordon Ross 	(void) mutex_unlock(&_idmapdstate.addisc_lk);
2572b3700b07SGordon Ross 
2573b3700b07SGordon Ross 	if (prev_st & ADDISC_ST_REQUESTED) {
2574b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "already kicked");
2575b3700b07SGordon Ross 	} else {
2576b3700b07SGordon Ross 		idmapdlog(LOG_DEBUG, "port send kick");
2577b3700b07SGordon Ross 		(void) port_send(idmapd_ev_port, KICK_AUTO_DISCOVERY, NULL);
2578b3700b07SGordon Ross 	}
25790dcc7149Snw }
25800dcc7149Snw 
25810dcc7149Snw /*ARGSUSED*/
25820dcc7149Snw void
2583349d5d8fSnw idmap_cfg_hup_handler(int sig)
2584349d5d8fSnw {
25850dcc7149Snw 	if (idmapd_ev_port >= 0)
25860dcc7149Snw 		(void) port_send(idmapd_ev_port, RECONFIGURE, NULL);
25870dcc7149Snw }
2588e3f2c991SKeyur Desai 
2589148c5f43SAlan Wright /*
2590148c5f43SAlan Wright  * Upgrade the debug flags.
2591148c5f43SAlan Wright  *
2592148c5f43SAlan Wright  * We're replacing a single debug flag with a fine-grained mechanism that
2593148c5f43SAlan Wright  * is also capable of considerably more verbosity.  We'll take a stab at
2594148c5f43SAlan Wright  * producing roughly the same level of output.
2595148c5f43SAlan Wright  */
2596148c5f43SAlan Wright static
2597148c5f43SAlan Wright int
2598148c5f43SAlan Wright upgrade_debug(idmap_cfg_handles_t *handles)
2599148c5f43SAlan Wright {
2600148c5f43SAlan Wright 	boolean_t debug_present;
2601148c5f43SAlan Wright 	const char DEBUG_PROP[] = "debug";
2602148c5f43SAlan Wright 	int rc;
2603148c5f43SAlan Wright 
2604148c5f43SAlan Wright 	rc = prop_exists(handles, DEBUG_PROP, &debug_present);
2605148c5f43SAlan Wright 
2606148c5f43SAlan Wright 	if (rc != 0)
2607148c5f43SAlan Wright 		return (rc);
2608148c5f43SAlan Wright 
2609148c5f43SAlan Wright 	if (!debug_present)
2610148c5f43SAlan Wright 		return (0);
2611148c5f43SAlan Wright 
2612148c5f43SAlan Wright 	idmapdlog(LOG_INFO,
2613148c5f43SAlan Wright 	    "Upgrading old %s/%s setting to %s/* settings.",
2614148c5f43SAlan Wright 	    CONFIG_PG, DEBUG_PROP, DEBUG_PG);
2615148c5f43SAlan Wright 
2616148c5f43SAlan Wright 	rc = set_val_integer(handles, handles->debug_pg, "config", 1);
2617148c5f43SAlan Wright 	if (rc != 0)
2618148c5f43SAlan Wright 		return (rc);
2619148c5f43SAlan Wright 	rc = set_val_integer(handles, handles->debug_pg, "discovery", 1);
2620148c5f43SAlan Wright 	if (rc != 0)
2621148c5f43SAlan Wright 		return (rc);
2622148c5f43SAlan Wright 
2623148c5f43SAlan Wright 	rc = del_val(handles, handles->config_pg, DEBUG_PROP);
2624148c5f43SAlan Wright 	if (rc != 0)
2625148c5f43SAlan Wright 		return (rc);
2626148c5f43SAlan Wright 
2627148c5f43SAlan Wright 	return (0);
2628148c5f43SAlan Wright }
2629148c5f43SAlan Wright 
2630e3f2c991SKeyur Desai /*
2631e3f2c991SKeyur Desai  * Upgrade the DS mapping flags.
2632e3f2c991SKeyur Desai  *
2633e3f2c991SKeyur Desai  * If the old ds_name_mapping_enabled flag is present, then
2634e3f2c991SKeyur Desai  *     if the new directory_based_mapping value is present, then
2635e3f2c991SKeyur Desai  *         if the two are compatible, delete the old and note it
2636e3f2c991SKeyur Desai  *         else delete the old and warn
2637e3f2c991SKeyur Desai  *     else
2638e3f2c991SKeyur Desai  *         set the new based on the old, and note it
2639e3f2c991SKeyur Desai  *         delete the old
2640e3f2c991SKeyur Desai  */
2641e3f2c991SKeyur Desai static
2642e3f2c991SKeyur Desai int
2643e3f2c991SKeyur Desai upgrade_directory_mapping(idmap_cfg_handles_t *handles)
2644e3f2c991SKeyur Desai {
2645e3f2c991SKeyur Desai 	boolean_t legacy_ds_name_mapping_present;
2646e3f2c991SKeyur Desai 	const char DS_NAME_MAPPING_ENABLED[] = "ds_name_mapping_enabled";
2647e3f2c991SKeyur Desai 	const char DIRECTORY_BASED_MAPPING[] = "directory_based_mapping";
2648e3f2c991SKeyur Desai 	int rc;
2649e3f2c991SKeyur Desai 
2650e3f2c991SKeyur Desai 	rc = prop_exists(handles, DS_NAME_MAPPING_ENABLED,
2651e3f2c991SKeyur Desai 	    &legacy_ds_name_mapping_present);
2652e3f2c991SKeyur Desai 
2653e3f2c991SKeyur Desai 	if (rc != 0)
2654e3f2c991SKeyur Desai 		return (rc);
2655e3f2c991SKeyur Desai 
2656e3f2c991SKeyur Desai 	if (!legacy_ds_name_mapping_present)
2657e3f2c991SKeyur Desai 		return (0);
2658e3f2c991SKeyur Desai 
2659e3f2c991SKeyur Desai 	boolean_t legacy_ds_name_mapping_enabled;
2660148c5f43SAlan Wright 	rc = get_val_bool(handles, DS_NAME_MAPPING_ENABLED,
2661148c5f43SAlan Wright 	    &legacy_ds_name_mapping_enabled, B_FALSE);
2662e3f2c991SKeyur Desai 	if (rc != 0)
2663e3f2c991SKeyur Desai 		return (rc);
2664e3f2c991SKeyur Desai 
2665e3f2c991SKeyur Desai 	char *legacy_mode;
2666e3f2c991SKeyur Desai 	char *legacy_bool_string;
2667e3f2c991SKeyur Desai 	if (legacy_ds_name_mapping_enabled) {
2668e3f2c991SKeyur Desai 		legacy_mode = "name";
2669e3f2c991SKeyur Desai 		legacy_bool_string = "true";
2670e3f2c991SKeyur Desai 	} else {
2671e3f2c991SKeyur Desai 		legacy_mode = "none";
2672e3f2c991SKeyur Desai 		legacy_bool_string = "false";
2673e3f2c991SKeyur Desai 	}
2674e3f2c991SKeyur Desai 
2675e3f2c991SKeyur Desai 	char *directory_based_mapping;
2676e3f2c991SKeyur Desai 	rc = get_val_astring(handles, DIRECTORY_BASED_MAPPING,
2677e3f2c991SKeyur Desai 	    &directory_based_mapping);
2678e3f2c991SKeyur Desai 	if (rc != 0)
2679e3f2c991SKeyur Desai 		return (rc);
2680e3f2c991SKeyur Desai 
2681e3f2c991SKeyur Desai 	if (directory_based_mapping == NULL) {
2682e3f2c991SKeyur Desai 		idmapdlog(LOG_INFO,
2683e3f2c991SKeyur Desai 		    "Upgrading old %s=%s setting\n"
2684e3f2c991SKeyur Desai 		    "to %s=%s.",
2685e3f2c991SKeyur Desai 		    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
2686e3f2c991SKeyur Desai 		    DIRECTORY_BASED_MAPPING, legacy_mode);
2687148c5f43SAlan Wright 		rc = set_val_astring(handles, handles->config_pg,
2688148c5f43SAlan Wright 		    DIRECTORY_BASED_MAPPING, legacy_mode);
2689e3f2c991SKeyur Desai 		if (rc != 0)
2690e3f2c991SKeyur Desai 			return (rc);
2691e3f2c991SKeyur Desai 	} else {
2692e3f2c991SKeyur Desai 		boolean_t new_name_mapping;
2693e3f2c991SKeyur Desai 		if (strcasecmp(directory_based_mapping, "name") == 0)
2694e3f2c991SKeyur Desai 			new_name_mapping = B_TRUE;
2695e3f2c991SKeyur Desai 		else
2696e3f2c991SKeyur Desai 			new_name_mapping = B_FALSE;
2697e3f2c991SKeyur Desai 
2698e3f2c991SKeyur Desai 		if (legacy_ds_name_mapping_enabled == new_name_mapping) {
2699e3f2c991SKeyur Desai 			idmapdlog(LOG_INFO,
2700e3f2c991SKeyur Desai 			    "Automatically removing old %s=%s setting\n"
2701e3f2c991SKeyur Desai 			    "in favor of %s=%s.",
2702e3f2c991SKeyur Desai 			    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
2703e3f2c991SKeyur Desai 			    DIRECTORY_BASED_MAPPING, directory_based_mapping);
2704e3f2c991SKeyur Desai 		} else {
2705e3f2c991SKeyur Desai 			idmapdlog(LOG_WARNING,
2706e3f2c991SKeyur Desai 			    "Removing conflicting %s=%s setting\n"
2707e3f2c991SKeyur Desai 			    "in favor of %s=%s.",
2708e3f2c991SKeyur Desai 			    DS_NAME_MAPPING_ENABLED, legacy_bool_string,
2709e3f2c991SKeyur Desai 			    DIRECTORY_BASED_MAPPING, directory_based_mapping);
2710e3f2c991SKeyur Desai 		}
2711e3f2c991SKeyur Desai 		free(directory_based_mapping);
2712e3f2c991SKeyur Desai 	}
2713e3f2c991SKeyur Desai 
2714148c5f43SAlan Wright 	rc = del_val(handles, handles->config_pg, DS_NAME_MAPPING_ENABLED);
2715e3f2c991SKeyur Desai 	if (rc != 0)
2716e3f2c991SKeyur Desai 		return (rc);
2717e3f2c991SKeyur Desai 
2718e3f2c991SKeyur Desai 	return (0);
2719e3f2c991SKeyur Desai }
2720e3f2c991SKeyur Desai 
2721e3f2c991SKeyur Desai /*
2722e3f2c991SKeyur Desai  * Do whatever is necessary to upgrade idmap's configuration before
2723e3f2c991SKeyur Desai  * we load it.
2724e3f2c991SKeyur Desai  */
2725e3f2c991SKeyur Desai int
2726e3f2c991SKeyur Desai idmap_cfg_upgrade(idmap_cfg_t *cfg)
2727e3f2c991SKeyur Desai {
2728e3f2c991SKeyur Desai 	int rc;
2729e3f2c991SKeyur Desai 
2730e3f2c991SKeyur Desai 	rc = upgrade_directory_mapping(&cfg->handles);
2731e3f2c991SKeyur Desai 	if (rc != 0)
2732e3f2c991SKeyur Desai 		return (rc);
2733e3f2c991SKeyur Desai 
2734148c5f43SAlan Wright 	rc = upgrade_debug(&cfg->handles);
2735148c5f43SAlan Wright 	if (rc != 0)
2736148c5f43SAlan Wright 		return (rc);
2737148c5f43SAlan Wright 
2738e3f2c991SKeyur Desai 	return (0);
2739e3f2c991SKeyur Desai }
2740b3700b07SGordon Ross 
2741b3700b07SGordon Ross /*
2742b3700b07SGordon Ross  * The LDAP code passes principal names lacking any
2743b3700b07SGordon Ross  * realm information, which causes mech_krb5 to do
2744b3700b07SGordon Ross  * awful things trying to figure out the realm.
2745b3700b07SGordon Ross  * Avoid that by making sure it has a default,
2746b3700b07SGordon Ross  * even when krb5.conf is not configured.
2747b3700b07SGordon Ross  */
2748b3700b07SGordon Ross static void
2749b3700b07SGordon Ross idmapd_set_krb5_realm(char *domain)
2750b3700b07SGordon Ross {
2751b3700b07SGordon Ross 	static char realm[MAXHOSTNAMELEN];
2752b3700b07SGordon Ross 	size_t ilen, olen;
2753b3700b07SGordon Ross 	int err;
2754b3700b07SGordon Ross 
2755b3700b07SGordon Ross 	if (domain == NULL) {
2756b3700b07SGordon Ross 		(void) unsetenv("KRB5_DEFAULT_REALM");
2757b3700b07SGordon Ross 		return;
2758b3700b07SGordon Ross 	}
2759b3700b07SGordon Ross 
2760b3700b07SGordon Ross 	/* Convert to upper case, in place. */
2761b3700b07SGordon Ross 	(void) strlcpy(realm, domain, sizeof (realm));
2762b3700b07SGordon Ross 	olen = ilen = strlen(realm);
2763b3700b07SGordon Ross 	(void) u8_textprep_str(realm, &ilen, realm, &olen,
2764b3700b07SGordon Ross 	    U8_TEXTPREP_TOUPPER, U8_UNICODE_LATEST, &err);
2765b3700b07SGordon Ross 
2766b3700b07SGordon Ross 	(void) setenv("KRB5_DEFAULT_REALM", realm, 1);
2767b3700b07SGordon Ross }
2768