xref: /onnv-gate/usr/src/cmd/idmap/idmapd/idmap_config.c (revision 5317:8c62b0b138cf)
14520Snw141292 /*
24520Snw141292  * CDDL HEADER START
34520Snw141292  *
44520Snw141292  * The contents of this file are subject to the terms of the
54520Snw141292  * Common Development and Distribution License (the "License").
64520Snw141292  * You may not use this file except in compliance with the License.
74520Snw141292  *
84520Snw141292  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94520Snw141292  * or http://www.opensolaris.org/os/licensing.
104520Snw141292  * See the License for the specific language governing permissions
114520Snw141292  * and limitations under the License.
124520Snw141292  *
134520Snw141292  * When distributing Covered Code, include this CDDL HEADER in each
144520Snw141292  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154520Snw141292  * If applicable, add the following below this CDDL HEADER, with the
164520Snw141292  * fields enclosed by brackets "[]" replaced with your own identifying
174520Snw141292  * information: Portions Copyright [yyyy] [name of copyright owner]
184520Snw141292  *
194520Snw141292  * CDDL HEADER END
204520Snw141292  */
214520Snw141292 /*
224520Snw141292  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
234520Snw141292  * Use is subject to license terms.
244520Snw141292  */
254520Snw141292 
264520Snw141292 #pragma ident	"%Z%%M%	%I%	%E% SMI"
274520Snw141292 
284520Snw141292 /*
294520Snw141292  * Config routines common to idmap(1M) and idmapd(1M)
304520Snw141292  */
314520Snw141292 
324520Snw141292 #include <stdlib.h>
334520Snw141292 #include <strings.h>
344520Snw141292 #include <libintl.h>
354520Snw141292 #include <ctype.h>
364520Snw141292 #include <errno.h>
374644Sbaban #include "idmapd.h"
384520Snw141292 #include <stdio.h>
394520Snw141292 #include <stdarg.h>
404695Sbaban #include <uuid/uuid.h>
41*5317Sjp151216 #include <pthread.h>
42*5317Sjp151216 #include <port.h>
43*5317Sjp151216 #include "addisc.h"
444520Snw141292 
454695Sbaban #define	MACHINE_SID_LEN	(9 + UUID_LEN/4 * 11)
464520Snw141292 #define	FMRI_BASE "svc:/system/idmap"
474520Snw141292 #define	CONFIG_PG "config"
484520Snw141292 #define	GENERAL_PG "general"
494520Snw141292 /* initial length of the array for policy options/attributes: */
504520Snw141292 #define	DEF_ARRAY_LENGTH 16
514520Snw141292 
52*5317Sjp151216 /*LINTLIBRARY*/
53*5317Sjp151216 
54*5317Sjp151216 
554644Sbaban static const char *me = "idmapd";
564520Snw141292 
57*5317Sjp151216 
58*5317Sjp151216 static pthread_t update_thread_handle = 0;
59*5317Sjp151216 
60*5317Sjp151216 int hup_ev_port = -1;
61*5317Sjp151216 extern int hupped;
62*5317Sjp151216 
634695Sbaban static int
644695Sbaban generate_machine_sid(char **machine_sid) {
654695Sbaban 	char *p;
664695Sbaban 	uuid_t uu;
674695Sbaban 	int i, j, len, rlen;
684695Sbaban 	uint32_t rid;
694695Sbaban 
704695Sbaban 	/*
714695Sbaban 	 * Generate and split 128-bit UUID into four 32-bit RIDs
724695Sbaban 	 * The machine_sid will be of the form S-1-5-N1-N2-N3-N4
734695Sbaban 	 * We depart from Windows here, which instead of 128
744695Sbaban 	 * bits worth of random numbers uses 96 bits.
754695Sbaban 	 */
764695Sbaban 
774695Sbaban 	*machine_sid = calloc(1, MACHINE_SID_LEN);
784695Sbaban 	if (*machine_sid == NULL) {
794695Sbaban 		idmapdlog(LOG_ERR, "%s: Out of memory", me);
804695Sbaban 		return (-1);
814695Sbaban 	}
824695Sbaban 	(void) strcpy(*machine_sid, "S-1-5-21");
834695Sbaban 	p = *machine_sid + strlen("S-1-5-21");
844695Sbaban 	len = MACHINE_SID_LEN - strlen("S-1-5-21");
854695Sbaban 
864695Sbaban 	uuid_clear(uu);
874695Sbaban 	uuid_generate_random(uu);
884695Sbaban 
894695Sbaban 	for (i = 0; i < UUID_LEN/4; i++) {
904695Sbaban 		j = i * 4;
914695Sbaban 		rid = (uu[j] << 24) | (uu[j + 1] << 16) |
924695Sbaban 			(uu[j + 2] << 8) | (uu[j + 3]);
934695Sbaban 		rlen = snprintf(p, len, "-%u", rid);
944695Sbaban 		p += rlen;
954695Sbaban 		len -= rlen;
964695Sbaban 	}
974695Sbaban 
984695Sbaban 	return (0);
994695Sbaban }
1004695Sbaban 
1014520Snw141292 /* Check if in the case of failure the original value of *val is preserved */
1024520Snw141292 static int
103*5317Sjp151216 get_val_int(idmap_cfg_handles_t *handles, char *name,
104*5317Sjp151216 	void *val, scf_type_t type)
1054520Snw141292 {
1064520Snw141292 	int rc = 0;
1074520Snw141292 
108*5317Sjp151216 	scf_property_t *scf_prop = scf_property_create(handles->main);
109*5317Sjp151216 	scf_value_t *value = scf_value_create(handles->main);
1104520Snw141292 
111*5317Sjp151216 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
1124520Snw141292 	/* this is OK: the property is just undefined */
1134520Snw141292 		goto destruction;
1144520Snw141292 
1154520Snw141292 
116*5317Sjp151216 	if (scf_property_get_value(scf_prop, value) < 0)
1174520Snw141292 	/* It is still OK when a property doesn't have any value */
1184520Snw141292 		goto destruction;
1194520Snw141292 
1204520Snw141292 	switch (type) {
1214520Snw141292 	case SCF_TYPE_BOOLEAN:
1224520Snw141292 		rc = scf_value_get_boolean(value, val);
1234520Snw141292 		break;
1244520Snw141292 	case SCF_TYPE_COUNT:
1254520Snw141292 		rc = scf_value_get_count(value, val);
1264520Snw141292 		break;
1274520Snw141292 	case SCF_TYPE_INTEGER:
1284520Snw141292 		rc = scf_value_get_integer(value, val);
1294520Snw141292 		break;
1304520Snw141292 	default:
1314644Sbaban 		idmapdlog(LOG_ERR, "%s: Invalid scf integer type (%d)",
1324644Sbaban 		    me, type);
1334520Snw141292 		rc = -1;
1344520Snw141292 		break;
1354520Snw141292 	}
1364520Snw141292 
1374520Snw141292 
1384520Snw141292 destruction:
1394520Snw141292 	scf_value_destroy(value);
1404520Snw141292 	scf_property_destroy(scf_prop);
1414520Snw141292 
1424520Snw141292 	return (rc);
1434520Snw141292 }
1444520Snw141292 
1454520Snw141292 static char *
1464520Snw141292 scf_value2string(scf_value_t *value) {
1474520Snw141292 	int rc = -1;
1484520Snw141292 	char buf_size = 127;
1494520Snw141292 	int length;
1504520Snw141292 	char *buf = NULL;
1514520Snw141292 	buf = (char *) malloc(sizeof (char) * buf_size);
1524520Snw141292 
1534520Snw141292 	for (;;) {
1544520Snw141292 		length = scf_value_get_astring(value, buf, buf_size);
1554520Snw141292 		if (length < 0) {
1564520Snw141292 			rc = -1;
1574520Snw141292 			goto destruction;
1584520Snw141292 		}
1594520Snw141292 
1604520Snw141292 		if (length == buf_size - 1) {
1614520Snw141292 			buf_size *= 2;
1624520Snw141292 			buf = (char *)realloc(buf, buf_size * sizeof (char));
1634520Snw141292 			if (!buf) {
1644644Sbaban 				idmapdlog(LOG_ERR, "%s: Out of memory", me);
1654520Snw141292 				rc = -1;
1664520Snw141292 				goto destruction;
1674520Snw141292 			}
1684520Snw141292 		} else {
1694520Snw141292 			rc = 0;
170*5317Sjp151216 		    break;
171*5317Sjp151216 	    }
1724520Snw141292 	}
1734520Snw141292 
1744520Snw141292 destruction:
1754520Snw141292 	if (rc < 0) {
1764520Snw141292 		if (buf)
1774520Snw141292 			free(buf);
1784520Snw141292 		buf = NULL;
1794520Snw141292 	}
1804520Snw141292 
1814520Snw141292 	return (buf);
1824520Snw141292 }
1834520Snw141292 
184*5317Sjp151216 static int
185*5317Sjp151216 get_val_ds(idmap_cfg_handles_t *handles, const char *name, int defport,
186*5317Sjp151216 		ad_disc_ds_t **val)
187*5317Sjp151216 {
188*5317Sjp151216 	ad_disc_ds_t *servers = NULL;
189*5317Sjp151216 	scf_property_t *scf_prop;
190*5317Sjp151216 	scf_value_t *value;
191*5317Sjp151216 	scf_iter_t *iter;
192*5317Sjp151216 	char *host, *portstr;
193*5317Sjp151216 	int len;
194*5317Sjp151216 	int count = 0;
195*5317Sjp151216 	int rc = 0;
196*5317Sjp151216 
197*5317Sjp151216 	*val = NULL;
198*5317Sjp151216 
199*5317Sjp151216 restart:
200*5317Sjp151216 	scf_prop = scf_property_create(handles->main);
201*5317Sjp151216 	value = scf_value_create(handles->main);
202*5317Sjp151216 	iter = scf_iter_create(handles->main);
203*5317Sjp151216 
204*5317Sjp151216 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
205*5317Sjp151216 		/* this is OK: the property is just undefined */
206*5317Sjp151216 		goto destruction;
207*5317Sjp151216 
208*5317Sjp151216 	if (scf_iter_property_values(iter, scf_prop) < 0) {
209*5317Sjp151216 		idmapdlog(LOG_ERR,
210*5317Sjp151216 		    "%s: scf_iter_property_values(%s) failed: %s",
211*5317Sjp151216 		    me, name, scf_strerror(scf_error()));
212*5317Sjp151216 		rc = -1;
213*5317Sjp151216 		goto destruction;
214*5317Sjp151216 	}
215*5317Sjp151216 
216*5317Sjp151216 	/* Workaround scf bugs -- can't reset an iteration */
217*5317Sjp151216 	if (count == 0) {
218*5317Sjp151216 		while (scf_iter_next_value(iter, value) > 0)
219*5317Sjp151216 			count++;
220*5317Sjp151216 
221*5317Sjp151216 		if (count == 0)
222*5317Sjp151216 			/* no values */
223*5317Sjp151216 			goto destruction;
224*5317Sjp151216 
225*5317Sjp151216 		scf_value_destroy(value);
226*5317Sjp151216 		scf_iter_destroy(iter);
227*5317Sjp151216 		scf_property_destroy(scf_prop);
228*5317Sjp151216 		goto restart;
229*5317Sjp151216 	}
230*5317Sjp151216 
231*5317Sjp151216 	if ((servers = calloc(count + 1, sizeof (*servers))) == NULL) {
232*5317Sjp151216 		idmapdlog(LOG_ERR, "%s: Out of memory", me);
233*5317Sjp151216 		goto destruction;
234*5317Sjp151216 	}
235*5317Sjp151216 
236*5317Sjp151216 	count = 0;
237*5317Sjp151216 	while (scf_iter_next_value(iter, value) > 0) {
238*5317Sjp151216 		servers[count].priority = 0;
239*5317Sjp151216 		servers[count].weight = 100;
240*5317Sjp151216 		servers[count].port = defport;
241*5317Sjp151216 		if ((host = scf_value2string(value)) == NULL) {
242*5317Sjp151216 			rc = -1;
243*5317Sjp151216 			goto destruction;
244*5317Sjp151216 		}
245*5317Sjp151216 		if ((portstr = strchr(host, ':')) != NULL) {
246*5317Sjp151216 			*portstr++ = '\0';
247*5317Sjp151216 			servers[count].port = strtol(portstr,
248*5317Sjp151216 			    (char **)NULL, 10);
249*5317Sjp151216 			if (servers[count].port == 0)
250*5317Sjp151216 				servers[count].port = defport;
251*5317Sjp151216 		}
252*5317Sjp151216 		len = strlcpy(servers[count].host, host,
253*5317Sjp151216 		    sizeof (servers->host));
254*5317Sjp151216 
255*5317Sjp151216 		free(host);
256*5317Sjp151216 
257*5317Sjp151216 		/* Ignore this server if the hostname is too long */
258*5317Sjp151216 		if (len < sizeof (servers->host))
259*5317Sjp151216 			count++;
260*5317Sjp151216 	}
261*5317Sjp151216 
262*5317Sjp151216 	*val = servers;
263*5317Sjp151216 
264*5317Sjp151216 destruction:
265*5317Sjp151216 	scf_value_destroy(value);
266*5317Sjp151216 	scf_iter_destroy(iter);
267*5317Sjp151216 	scf_property_destroy(scf_prop);
268*5317Sjp151216 
269*5317Sjp151216 	if (rc < 0) {
270*5317Sjp151216 		if (servers)
271*5317Sjp151216 			free(servers);
272*5317Sjp151216 		*val = NULL;
273*5317Sjp151216 	}
274*5317Sjp151216 
275*5317Sjp151216 	return (rc);
276*5317Sjp151216 }
277*5317Sjp151216 
2784520Snw141292 
2794520Snw141292 static int
280*5317Sjp151216 get_val_astring(idmap_cfg_handles_t *handles, char *name, char **val)
2814520Snw141292 {
2824520Snw141292 	int rc = 0;
2834520Snw141292 
284*5317Sjp151216 	scf_property_t *scf_prop = scf_property_create(handles->main);
285*5317Sjp151216 	scf_value_t *value = scf_value_create(handles->main);
2864520Snw141292 
287*5317Sjp151216 	*val = NULL;
2884520Snw141292 
289*5317Sjp151216 	if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0)
2904520Snw141292 	/* this is OK: the property is just undefined */
2914520Snw141292 		goto destruction;
2924520Snw141292 
293*5317Sjp151216 	if (scf_property_get_value(scf_prop, value) < 0) {
2944644Sbaban 		idmapdlog(LOG_ERR,
2954644Sbaban 		    "%s: scf_property_get_value(%s) failed: %s",
2964644Sbaban 		    me, name, scf_strerror(scf_error()));
2974520Snw141292 		rc = -1;
2984520Snw141292 		goto destruction;
2994520Snw141292 	}
3004520Snw141292 
301*5317Sjp151216 	if (!(*val = scf_value2string(value)))
3024520Snw141292 		rc = -1;
3034520Snw141292 
3044520Snw141292 destruction:
3054520Snw141292 	scf_value_destroy(value);
3064520Snw141292 	scf_property_destroy(scf_prop);
3074520Snw141292 
3084520Snw141292 	if (rc < 0) {
3094520Snw141292 		if (*val)
3104520Snw141292 			free(*val);
3114520Snw141292 		*val = NULL;
3124520Snw141292 	}
3134520Snw141292 
3144520Snw141292 	return (rc);
3154520Snw141292 }
3164520Snw141292 
317*5317Sjp151216 
3184695Sbaban static int
319*5317Sjp151216 set_val_astring(idmap_cfg_handles_t *handles, char *name, const char *val)
3204695Sbaban {
3214695Sbaban 	int			rc = 0, i;
3224695Sbaban 	scf_property_t		*scf_prop = NULL;
3234695Sbaban 	scf_value_t		*value = NULL;
3244695Sbaban 	scf_transaction_t	*tx = NULL;
3254695Sbaban 	scf_transaction_entry_t	*ent = NULL;
3264695Sbaban 
327*5317Sjp151216 	if ((scf_prop = scf_property_create(handles->main)) == NULL ||
328*5317Sjp151216 	    (value = scf_value_create(handles->main)) == NULL ||
329*5317Sjp151216 	    (tx = scf_transaction_create(handles->main)) == NULL ||
330*5317Sjp151216 	    (ent = scf_entry_create(handles->main)) == NULL) {
3314695Sbaban 		idmapdlog(LOG_ERR, "%s: Unable to set property %s: %s",
3324695Sbaban 		    me, name, scf_strerror(scf_error()));
3334695Sbaban 		rc = -1;
3344695Sbaban 		goto destruction;
3354695Sbaban 	}
3364695Sbaban 
3374695Sbaban 	for (i = 0; i < MAX_TRIES && rc == 0; i++) {
338*5317Sjp151216 		if (scf_transaction_start(tx, handles->config_pg) == -1) {
3394695Sbaban 			idmapdlog(LOG_ERR,
3404695Sbaban 			    "%s: scf_transaction_start(%s) failed: %s",
3414695Sbaban 			    me, name, scf_strerror(scf_error()));
3424695Sbaban 			rc = -1;
3434695Sbaban 			goto destruction;
3444695Sbaban 		}
3454695Sbaban 
3464695Sbaban 		rc = scf_transaction_property_new(tx, ent, name,
3474695Sbaban 		    SCF_TYPE_ASTRING);
3484695Sbaban 		if (rc == -1) {
3494695Sbaban 			idmapdlog(LOG_ERR,
3504695Sbaban 			    "%s: scf_transaction_property_new() failed: %s",
3514695Sbaban 			    me, scf_strerror(scf_error()));
3524695Sbaban 			goto destruction;
3534695Sbaban 		}
3544695Sbaban 
3554695Sbaban 		if (scf_value_set_astring(value, val) == -1) {
3564695Sbaban 			idmapdlog(LOG_ERR,
3574695Sbaban 			    "%s: scf_value_set_astring() failed: %s",
3584695Sbaban 			    me, scf_strerror(scf_error()));
3594695Sbaban 			rc = -1;
3604695Sbaban 			goto destruction;
3614695Sbaban 		}
3624695Sbaban 
3634695Sbaban 		if (scf_entry_add_value(ent, value) == -1) {
3644695Sbaban 			idmapdlog(LOG_ERR,
3654695Sbaban 			    "%s: scf_entry_add_value() failed: %s",
3664695Sbaban 			    me, scf_strerror(scf_error()));
3674695Sbaban 			rc = -1;
3684695Sbaban 			goto destruction;
3694695Sbaban 		}
3704695Sbaban 
3714695Sbaban 		rc = scf_transaction_commit(tx);
3724695Sbaban 		if (rc == 0 && i < MAX_TRIES - 1) {
3734695Sbaban 			/*
3744695Sbaban 			 * Property group set in scf_transaction_start()
3754695Sbaban 			 * is not the most recent. Update pg, reset tx and
3764695Sbaban 			 * retry tx.
3774695Sbaban 			 */
3784695Sbaban 			idmapdlog(LOG_WARNING,
3794695Sbaban 			    "%s: scf_transaction_commit(%s) failed - Retry: %s",
3804695Sbaban 			    me, name, scf_strerror(scf_error()));
381*5317Sjp151216 			if (scf_pg_update(handles->config_pg) == -1) {
3824695Sbaban 				idmapdlog(LOG_ERR,
3834695Sbaban 				    "%s: scf_pg_update() failed: %s",
3844695Sbaban 				    me, scf_strerror(scf_error()));
3854695Sbaban 				rc = -1;
3864695Sbaban 				goto destruction;
3874695Sbaban 			}
3884695Sbaban 			scf_transaction_reset(tx);
3894695Sbaban 		}
3904695Sbaban 	}
3914695Sbaban 
3924695Sbaban 	/* Log failure message if all retries failed */
3934695Sbaban 	if (rc == 0) {
3944695Sbaban 		idmapdlog(LOG_ERR,
3954695Sbaban 		    "%s: scf_transaction_commit(%s) failed: %s",
3964695Sbaban 		    me, name, scf_strerror(scf_error()));
3974695Sbaban 		rc = -1;
3984695Sbaban 	}
3994695Sbaban 
4004695Sbaban destruction:
4014695Sbaban 	scf_value_destroy(value);
4024695Sbaban 	scf_entry_destroy(ent);
4034695Sbaban 	scf_transaction_destroy(tx);
4044695Sbaban 	scf_property_destroy(scf_prop);
4054695Sbaban 	return (rc);
4064695Sbaban }
4074695Sbaban 
408*5317Sjp151216 static int
409*5317Sjp151216 update_value(char **value, char **new, char *name)
4104520Snw141292 {
411*5317Sjp151216 	if (*new == NULL)
412*5317Sjp151216 		return (FALSE);
4134520Snw141292 
414*5317Sjp151216 	if (*value != NULL && strcmp(*new, *value) == 0) {
415*5317Sjp151216 		free(*new);
416*5317Sjp151216 		*new = NULL;
417*5317Sjp151216 		return (FALSE);
4184520Snw141292 	}
4194520Snw141292 
420*5317Sjp151216 	idmapdlog(LOG_INFO, "%s: change %s=%s", me, name, CHECK_NULL(*new));
421*5317Sjp151216 	if (*value != NULL)
422*5317Sjp151216 		free(*value);
423*5317Sjp151216 	*value = *new;
424*5317Sjp151216 	*new = NULL;
425*5317Sjp151216 	return (TRUE);
426*5317Sjp151216 }
427*5317Sjp151216 
428*5317Sjp151216 static int
429*5317Sjp151216 update_dirs(ad_disc_ds_t **value, ad_disc_ds_t **new, char *name)
430*5317Sjp151216 {
431*5317Sjp151216 	int i;
432*5317Sjp151216 
433*5317Sjp151216 	if (*new == NULL)
434*5317Sjp151216 		return (FALSE);
435*5317Sjp151216 
436*5317Sjp151216 	if (*value != NULL && ad_disc_compare_ds(*value, *new) == 0) {
437*5317Sjp151216 		free(*new);
438*5317Sjp151216 		*new = NULL;
439*5317Sjp151216 		return (FALSE);
4404520Snw141292 	}
4414520Snw141292 
442*5317Sjp151216 	if (*value)
443*5317Sjp151216 		free(*value);
444*5317Sjp151216 
445*5317Sjp151216 	for (i = 0; (*new)[i].host[0] != '\0'; i++)
446*5317Sjp151216 		idmapdlog(LOG_INFO, "%s: change %s=%s port=%d", me, name,
447*5317Sjp151216 		    (*new)[i].host, (*new)[i].port);
448*5317Sjp151216 	*value = *new;
449*5317Sjp151216 	*new = NULL;
450*5317Sjp151216 	return (TRUE);
451*5317Sjp151216 }
452*5317Sjp151216 
453*5317Sjp151216 
454*5317Sjp151216 #define	SUBNET_CHECK_TIME	(2 * 60)
455*5317Sjp151216 #define	MAX_CHECK_TIME		(10 * 60)
4564520Snw141292 
457*5317Sjp151216 /*
458*5317Sjp151216  * Returns 1 if SIGHUP has been received (see hup_handler elsewhere), 0
459*5317Sjp151216  * otherwise.  Uses an event port and a user-defined event.
460*5317Sjp151216  *
461*5317Sjp151216  * Note that port_get() does not update its timeout argument when EINTR,
462*5317Sjp151216  * unlike nanosleep().  We probably don't care very much here because
463*5317Sjp151216  * the only signals we expect are ones that will lead to idmapd dying or
464*5317Sjp151216  * SIGHUP, and we intend for the latter to cause this function to
465*5317Sjp151216  * return.  But if we did care then we could always use a timer event
466*5317Sjp151216  * (see timer_create(3RT)) and associate it with the same event port,
467*5317Sjp151216  * then we could get accurate waiting regardless of EINTRs.
468*5317Sjp151216  */
469*5317Sjp151216 static
470*5317Sjp151216 int
471*5317Sjp151216 wait_for_ttl(struct timespec *timeout)
472*5317Sjp151216 {
473*5317Sjp151216 	port_event_t pe;
474*5317Sjp151216 	int retries = 1;
4754520Snw141292 
4764520Snw141292 	/*
477*5317Sjp151216 	 * If event port creation failed earlier and fails now then we
478*5317Sjp151216 	 * simply don't learn about SIGHUPs in a timely fashion.  No big
479*5317Sjp151216 	 * deal
4804520Snw141292 	 */
481*5317Sjp151216 	if (hup_ev_port == -1 && (hup_ev_port = port_create()) < 0) {
482*5317Sjp151216 		(void) nanosleep(timeout, NULL);
483*5317Sjp151216 		return (0);
484*5317Sjp151216 	}
485*5317Sjp151216 
486*5317Sjp151216 retry:
487*5317Sjp151216 	if (port_get(hup_ev_port, &pe, timeout) != 0) {
488*5317Sjp151216 		switch (errno) {
489*5317Sjp151216 		case EBADF:
490*5317Sjp151216 		case EBADFD:
491*5317Sjp151216 			hup_ev_port = -1;
492*5317Sjp151216 			(void) nanosleep(timeout, NULL);
493*5317Sjp151216 			break;
494*5317Sjp151216 		case EINVAL:
495*5317Sjp151216 			/*
496*5317Sjp151216 			 * Shouldn't happen, except, perhaps, near the
497*5317Sjp151216 			 * end of time
498*5317Sjp151216 			 */
499*5317Sjp151216 			timeout->tv_nsec = 0;
500*5317Sjp151216 			timeout->tv_sec = MAX_CHECK_TIME;
501*5317Sjp151216 			if (retries-- > 0)
502*5317Sjp151216 				goto retry;
503*5317Sjp151216 			/* NOTREACHED */
504*5317Sjp151216 			break;
505*5317Sjp151216 		case EINTR:
506*5317Sjp151216 			if (!hupped)
507*5317Sjp151216 				goto retry;
508*5317Sjp151216 			break;
509*5317Sjp151216 		case ETIME:
510*5317Sjp151216 			/* Timeout */
511*5317Sjp151216 			break;
512*5317Sjp151216 		default:
513*5317Sjp151216 			/* EFAULT */
514*5317Sjp151216 			(void) nanosleep(timeout, NULL);
515*5317Sjp151216 			break;
5164520Snw141292 		}
5174520Snw141292 	}
5184520Snw141292 
519*5317Sjp151216 	/*
520*5317Sjp151216 	 * We only have one event that we care about, a user event, so
521*5317Sjp151216 	 * there's nothing to check or clean up about pe.
522*5317Sjp151216 	 *
523*5317Sjp151216 	 * If we get here it's either because we had a SIGHUP and a user
524*5317Sjp151216 	 * event was sent to our port, or because the port_get() timed
525*5317Sjp151216 	 * out (or even both!).
526*5317Sjp151216 	 */
527*5317Sjp151216 
528*5317Sjp151216 	if (hupped) {
529*5317Sjp151216 		hupped = 0;
530*5317Sjp151216 		/* Got SIGHUP, re-read SMF config */
531*5317Sjp151216 		(void) idmapdlog(LOG_INFO, "idmapd: SMF refresh");
532*5317Sjp151216 		WRLOCK_CONFIG();
533*5317Sjp151216 		(void) idmap_cfg_unload(&_idmapdstate.cfg->pgcfg);
534*5317Sjp151216 		if (idmap_cfg_load(&_idmapdstate.cfg->handles,
535*5317Sjp151216 		    &_idmapdstate.cfg->pgcfg) < 0)
536*5317Sjp151216 			(void) idmapdlog(LOG_NOTICE,
537*5317Sjp151216 			    "idmapd: Failed to reload config");
538*5317Sjp151216 		UNLOCK_CONFIG();
539*5317Sjp151216 		return (1);
540*5317Sjp151216 	}
541*5317Sjp151216 
542*5317Sjp151216 	return (0);
543*5317Sjp151216 }
544*5317Sjp151216 
545*5317Sjp151216 void *
546*5317Sjp151216 idmap_cfg_update_thread(void *arg)
547*5317Sjp151216 {
548*5317Sjp151216 
549*5317Sjp151216 	idmap_pg_config_t	new_cfg;
550*5317Sjp151216 	int			ttl;
551*5317Sjp151216 	idmap_cfg_handles_t	*handles = &_idmapdstate.cfg->handles;
552*5317Sjp151216 	idmap_pg_config_t	*live_cfg = &_idmapdstate.cfg->pgcfg;
553*5317Sjp151216 	ad_disc_t		ad_ctx = handles->ad_ctx;
554*5317Sjp151216 	struct timespec		delay;
555*5317Sjp151216 	int			changed;
556*5317Sjp151216 
557*5317Sjp151216 	(void) memset(&new_cfg, 0, sizeof (new_cfg));
558*5317Sjp151216 
559*5317Sjp151216 	for (;;) {
560*5317Sjp151216 		changed = FALSE;
561*5317Sjp151216 		ttl = ad_disc_get_TTL(ad_ctx);
562*5317Sjp151216 		if (ttl > MAX_CHECK_TIME)
563*5317Sjp151216 			ttl = MAX_CHECK_TIME;
564*5317Sjp151216 		while (ttl > 0 || ttl == -1) {
565*5317Sjp151216 			if (ttl == -1) {
566*5317Sjp151216 				wait_for_ttl(NULL);
567*5317Sjp151216 			} else if (ttl > SUBNET_CHECK_TIME) {
568*5317Sjp151216 				/*
569*5317Sjp151216 				 * We really ought to just monitor
570*5317Sjp151216 				 * network interfaces with a PF_ROUTE
571*5317Sjp151216 				 * socket...  This crude method of
572*5317Sjp151216 				 * discovering subnet changes will do
573*5317Sjp151216 				 * for now.  Though might even not want
574*5317Sjp151216 				 * to bother: subnet changes leading to
575*5317Sjp151216 				 * sitename changes ought never happen,
576*5317Sjp151216 				 * and requiring a refresh when they do
577*5317Sjp151216 				 * should be no problem (SMF/NWAM ought
578*5317Sjp151216 				 * to be able to refresh us).
579*5317Sjp151216 				 */
580*5317Sjp151216 				delay.tv_sec = SUBNET_CHECK_TIME;
581*5317Sjp151216 				delay.tv_nsec = 0;
582*5317Sjp151216 				if (wait_for_ttl(&delay)) {
583*5317Sjp151216 					/* Got SIGHUP, re-discover */
584*5317Sjp151216 					ttl = 0;
585*5317Sjp151216 					changed = TRUE;
586*5317Sjp151216 					break;
587*5317Sjp151216 				}
588*5317Sjp151216 				ttl -= SUBNET_CHECK_TIME;
589*5317Sjp151216 				if (ad_disc_SubnetChanged(ad_ctx))
590*5317Sjp151216 					break;
591*5317Sjp151216 			} else {
592*5317Sjp151216 				delay.tv_sec = ttl;
593*5317Sjp151216 				delay.tv_nsec = 0;
594*5317Sjp151216 				if (wait_for_ttl(&delay))
595*5317Sjp151216 					changed = TRUE;
596*5317Sjp151216 				ttl = 0;
597*5317Sjp151216 			}
598*5317Sjp151216 		}
599*5317Sjp151216 
600*5317Sjp151216 		/*
601*5317Sjp151216 		 * Load configuration data into a private copy.
602*5317Sjp151216 		 *
603*5317Sjp151216 		 * The fixed values (i.e., from SMF) have already been
604*5317Sjp151216 		 * set in AD auto discovery, so if all values have been
605*5317Sjp151216 		 * set in SMF and they haven't been changed or the
606*5317Sjp151216 		 * service been refreshed then the rest of this loop's
607*5317Sjp151216 		 * body is one big no-op.
608*5317Sjp151216 		 */
609*5317Sjp151216 		pthread_mutex_lock(&handles->mutex);
610*5317Sjp151216 
611*5317Sjp151216 		new_cfg.default_domain = ad_disc_get_DomainName(ad_ctx);
612*5317Sjp151216 		if (new_cfg.default_domain == NULL) {
613*5317Sjp151216 			idmapdlog(LOG_INFO,
614*5317Sjp151216 			    "%s: unable to discover Default Domain", me);
615*5317Sjp151216 		}
616*5317Sjp151216 
617*5317Sjp151216 		new_cfg.domain_name = ad_disc_get_DomainName(ad_ctx);
618*5317Sjp151216 		if (new_cfg.domain_name == NULL) {
619*5317Sjp151216 			idmapdlog(LOG_INFO,
620*5317Sjp151216 			    "%s: unable to discover Domain Name", me);
621*5317Sjp151216 		}
622*5317Sjp151216 
623*5317Sjp151216 		new_cfg.domain_controller =
624*5317Sjp151216 		    ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE);
625*5317Sjp151216 		if (new_cfg.domain_controller == NULL) {
626*5317Sjp151216 			idmapdlog(LOG_INFO,
627*5317Sjp151216 			    "%s: unable to discover Domain Controller", me);
628*5317Sjp151216 		}
629*5317Sjp151216 
630*5317Sjp151216 		new_cfg.forest_name = ad_disc_get_ForestName(ad_ctx);
631*5317Sjp151216 		if (new_cfg.forest_name == NULL) {
632*5317Sjp151216 			idmapdlog(LOG_INFO,
633*5317Sjp151216 			    "%s: unable to discover Forest Name", me);
634*5317Sjp151216 		}
635*5317Sjp151216 
636*5317Sjp151216 		new_cfg.site_name = ad_disc_get_SiteName(ad_ctx);
637*5317Sjp151216 		if (new_cfg.site_name == NULL) {
638*5317Sjp151216 			idmapdlog(LOG_INFO,
639*5317Sjp151216 			    "%s: unable to discover Site Name", me);
640*5317Sjp151216 		}
641*5317Sjp151216 
642*5317Sjp151216 		new_cfg.global_catalog =
643*5317Sjp151216 		    ad_disc_get_GlobalCatalog(ad_ctx, AD_DISC_PREFER_SITE);
644*5317Sjp151216 		if (new_cfg.global_catalog == NULL) {
645*5317Sjp151216 			idmapdlog(LOG_INFO,
646*5317Sjp151216 			    "%s: unable to discover Global Catalog", me);
647*5317Sjp151216 		}
648*5317Sjp151216 
649*5317Sjp151216 		pthread_mutex_unlock(&handles->mutex);
650*5317Sjp151216 
651*5317Sjp151216 		if (new_cfg.default_domain == NULL &&
652*5317Sjp151216 		    new_cfg.domain_name == NULL &&
653*5317Sjp151216 		    new_cfg.domain_controller == NULL &&
654*5317Sjp151216 		    new_cfg.forest_name == NULL &&
655*5317Sjp151216 		    new_cfg.global_catalog == NULL) {
656*5317Sjp151216 			idmapdlog(LOG_NOTICE, "%s: Could not auto-discover AD "
657*5317Sjp151216 			    "domain and forest names nor domain controllers "
658*5317Sjp151216 			    "and global catalog servers", me);
659*5317Sjp151216 			idmap_cfg_unload(&new_cfg);
660*5317Sjp151216 			continue;
661*5317Sjp151216 		}
662*5317Sjp151216 
663*5317Sjp151216 		/*
664*5317Sjp151216 		 * Update the live configuration
665*5317Sjp151216 		 */
666*5317Sjp151216 		WRLOCK_CONFIG();
667*5317Sjp151216 
668*5317Sjp151216 		if (live_cfg->list_size_limit != new_cfg.list_size_limit) {
669*5317Sjp151216 			idmapdlog(LOG_INFO, "%s: change list_size=%d", me,
670*5317Sjp151216 			    new_cfg.list_size_limit);
671*5317Sjp151216 			live_cfg->list_size_limit = new_cfg.list_size_limit;
672*5317Sjp151216 		}
673*5317Sjp151216 
674*5317Sjp151216 		/*
675*5317Sjp151216 		 * If default_domain came from SMF then we must not
676*5317Sjp151216 		 * auto-discover it.
677*5317Sjp151216 		 */
678*5317Sjp151216 		if (live_cfg->dflt_dom_set_in_smf == FALSE &&
679*5317Sjp151216 		    update_value(&live_cfg->default_domain,
680*5317Sjp151216 		    &new_cfg.default_domain, "default_domain") == TRUE)
681*5317Sjp151216 			changed = TRUE;
682*5317Sjp151216 
683*5317Sjp151216 		(void) update_value(&live_cfg->domain_name,
684*5317Sjp151216 		    &new_cfg.domain_name, "domain_name");
685*5317Sjp151216 
686*5317Sjp151216 		(void) update_dirs(&live_cfg->domain_controller,
687*5317Sjp151216 		    &new_cfg.domain_controller, "domain_controller");
688*5317Sjp151216 
689*5317Sjp151216 		(void) update_value(&live_cfg->forest_name,
690*5317Sjp151216 		    &new_cfg.forest_name, "forest_name");
691*5317Sjp151216 
692*5317Sjp151216 		(void) update_value(&live_cfg->site_name,
693*5317Sjp151216 		    &new_cfg.site_name, "site_name");
694*5317Sjp151216 
695*5317Sjp151216 		if (update_dirs(&live_cfg->global_catalog,
696*5317Sjp151216 		    &new_cfg.global_catalog, "global_catalog") == TRUE)
697*5317Sjp151216 			changed = TRUE;
698*5317Sjp151216 		UNLOCK_CONFIG();
699*5317Sjp151216 
700*5317Sjp151216 		idmap_cfg_unload(&new_cfg);
701*5317Sjp151216 
702*5317Sjp151216 
703*5317Sjp151216 		/*
704*5317Sjp151216 		 * Re-create the ad_t/ad_host_t objects if
705*5317Sjp151216 		 * either the default domain or the global
706*5317Sjp151216 		 * catalog server list changed.
707*5317Sjp151216 		 */
708*5317Sjp151216 
709*5317Sjp151216 		if (changed) {
710*5317Sjp151216 			RDLOCK_CONFIG();
711*5317Sjp151216 			(void) reload_ad();
712*5317Sjp151216 			UNLOCK_CONFIG();
713*5317Sjp151216 			print_idmapdstate();
714*5317Sjp151216 		}
715*5317Sjp151216 	}
716*5317Sjp151216 	/*NOTREACHED*/
717*5317Sjp151216 	return (NULL);
718*5317Sjp151216 }
719*5317Sjp151216 
720*5317Sjp151216 
721*5317Sjp151216 int
722*5317Sjp151216 idmap_cfg_start_updates(idmap_cfg_t *cfg)
723*5317Sjp151216 {
724*5317Sjp151216 	/* Don't check for failure -- see wait_for_ttl() */
725*5317Sjp151216 	hup_ev_port = port_create();
726*5317Sjp151216 
727*5317Sjp151216 	errno = pthread_create(&update_thread_handle, NULL,
728*5317Sjp151216 	    idmap_cfg_update_thread, NULL);
729*5317Sjp151216 	if (errno == 0)
730*5317Sjp151216 		return (0);
731*5317Sjp151216 	else
7324520Snw141292 		return (-1);
733*5317Sjp151216 }
734*5317Sjp151216 
735*5317Sjp151216 
736*5317Sjp151216 int
737*5317Sjp151216 idmap_cfg_load(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg)
738*5317Sjp151216 {
739*5317Sjp151216 	int rc = 0;
740*5317Sjp151216 	char *str = NULL;
741*5317Sjp151216 	ad_disc_t ad_ctx = handles->ad_ctx;
742*5317Sjp151216 
743*5317Sjp151216 	pgcfg->list_size_limit = 0;
744*5317Sjp151216 	pgcfg->default_domain = NULL;
745*5317Sjp151216 	pgcfg->domain_name = NULL;
746*5317Sjp151216 	pgcfg->machine_sid = NULL;
747*5317Sjp151216 	pgcfg->domain_controller = NULL;
748*5317Sjp151216 	pgcfg->forest_name = NULL;
749*5317Sjp151216 	pgcfg->site_name = NULL;
750*5317Sjp151216 	pgcfg->global_catalog = NULL;
751*5317Sjp151216 
752*5317Sjp151216 	pthread_mutex_lock(&handles->mutex);
753*5317Sjp151216 
754*5317Sjp151216 	ad_disc_refresh(handles->ad_ctx);
755*5317Sjp151216 
756*5317Sjp151216 	if (scf_pg_update(handles->config_pg) < 0) {
757*5317Sjp151216 		idmapdlog(LOG_ERR, "%s: scf_pg_update() failed: %s",
758*5317Sjp151216 		    me, scf_strerror(scf_error()));
759*5317Sjp151216 		rc = -1;
760*5317Sjp151216 		goto exit;
761*5317Sjp151216 	}
762*5317Sjp151216 
763*5317Sjp151216 	if (scf_pg_update(handles->general_pg) < 0) {
764*5317Sjp151216 		idmapdlog(LOG_ERR, "%s: scf_pg_update() failed: %s",
765*5317Sjp151216 		    me, scf_strerror(scf_error()));
766*5317Sjp151216 		rc = -1;
767*5317Sjp151216 		goto exit;
768*5317Sjp151216 	}
769*5317Sjp151216 
770*5317Sjp151216 	rc = get_val_int(handles, "list_size_limit",
771*5317Sjp151216 	    &pgcfg->list_size_limit, SCF_TYPE_COUNT);
772*5317Sjp151216 	if (rc != 0) {
773*5317Sjp151216 		rc = -1;
774*5317Sjp151216 		goto exit;
775*5317Sjp151216 	}
776*5317Sjp151216 
777*5317Sjp151216 	rc = get_val_astring(handles, "domain_name",
778*5317Sjp151216 	    &pgcfg->domain_name);
779*5317Sjp151216 	if (rc != 0) {
780*5317Sjp151216 		rc = -1;
781*5317Sjp151216 		goto exit;
782*5317Sjp151216 	}
783*5317Sjp151216 	(void) ad_disc_set_DomainName(ad_ctx, pgcfg->domain_name);
784*5317Sjp151216 
785*5317Sjp151216 	rc = get_val_astring(handles, "default_domain",
786*5317Sjp151216 	    &pgcfg->default_domain);
787*5317Sjp151216 	if (rc != 0) {
788*5317Sjp151216 		rc = -1;
789*5317Sjp151216 		goto exit;
790*5317Sjp151216 	}
791*5317Sjp151216 
792*5317Sjp151216 	rc = get_val_astring(handles, "mapping_domain", &str);
793*5317Sjp151216 	if (rc != 0) {
794*5317Sjp151216 		rc = -1;
795*5317Sjp151216 		goto exit;
796*5317Sjp151216 	}
797*5317Sjp151216 
798*5317Sjp151216 	/*
799*5317Sjp151216 	 * We treat default_domain as having been specified in SMF IFF
800*5317Sjp151216 	 * either (the config/default_domain property was set) or (the
801*5317Sjp151216 	 * old, obsolete, never documented config/mapping_domain
802*5317Sjp151216 	 * property was set and the new config/domain_name property was
803*5317Sjp151216 	 * not set).
804*5317Sjp151216 	 */
805*5317Sjp151216 	pgcfg->dflt_dom_set_in_smf = TRUE;
806*5317Sjp151216 	if (pgcfg->default_domain == NULL) {
807*5317Sjp151216 
808*5317Sjp151216 		pgcfg->dflt_dom_set_in_smf = FALSE;
809*5317Sjp151216 
810*5317Sjp151216 		if (pgcfg->domain_name != NULL) {
811*5317Sjp151216 			pgcfg->default_domain = strdup(pgcfg->domain_name);
812*5317Sjp151216 			if (str != NULL) {
813*5317Sjp151216 				idmapdlog(LOG_WARNING,
814*5317Sjp151216 				    "%s: Ignoring obsolete, undocumented "
815*5317Sjp151216 				    "config/mapping_domain property", me);
816*5317Sjp151216 			}
817*5317Sjp151216 		} else if (str != NULL) {
818*5317Sjp151216 			pgcfg->default_domain = strdup(str);
819*5317Sjp151216 			pgcfg->dflt_dom_set_in_smf = TRUE;
820*5317Sjp151216 			idmapdlog(LOG_WARNING,
821*5317Sjp151216 			    "%s: The config/mapping_domain property is "
822*5317Sjp151216 			    "obsolete; support for it will be removed, "
823*5317Sjp151216 			    "please use config/default_domain instead",
824*5317Sjp151216 			    me);
8254695Sbaban 		}
8264695Sbaban 	}
8274520Snw141292 
828*5317Sjp151216 	if (str != NULL)
829*5317Sjp151216 		free(str);
830*5317Sjp151216 
831*5317Sjp151216 	rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid);
832*5317Sjp151216 	if (rc != 0) {
833*5317Sjp151216 		rc = -1;
834*5317Sjp151216 		goto exit;
835*5317Sjp151216 	}
836*5317Sjp151216 	if (pgcfg->machine_sid == NULL) {
837*5317Sjp151216 		/* If machine_sid not configured, generate one */
838*5317Sjp151216 		if (generate_machine_sid(&pgcfg->machine_sid) < 0) {
839*5317Sjp151216 			rc =  -1;
840*5317Sjp151216 			goto exit;
841*5317Sjp151216 		}
842*5317Sjp151216 		rc = set_val_astring(handles, "machine_sid",
843*5317Sjp151216 		    pgcfg->machine_sid);
844*5317Sjp151216 		if (rc < 0) {
845*5317Sjp151216 			free(pgcfg->machine_sid);
846*5317Sjp151216 			pgcfg->machine_sid = NULL;
847*5317Sjp151216 			rc = -1;
848*5317Sjp151216 			goto exit;
849*5317Sjp151216 		}
850*5317Sjp151216 	}
851*5317Sjp151216 
852*5317Sjp151216 	str = NULL;
853*5317Sjp151216 	rc = get_val_ds(handles, "domain_controller", 389,
854*5317Sjp151216 	    &pgcfg->domain_controller);
855*5317Sjp151216 	if (rc != 0) {
856*5317Sjp151216 		rc = -1;
857*5317Sjp151216 		goto exit;
858*5317Sjp151216 	}
859*5317Sjp151216 	(void) ad_disc_set_DomainController(ad_ctx, pgcfg->domain_controller);
860*5317Sjp151216 
861*5317Sjp151216 	rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name);
862*5317Sjp151216 	if (rc != 0) {
863*5317Sjp151216 		rc = -1;
864*5317Sjp151216 		goto exit;
865*5317Sjp151216 	}
866*5317Sjp151216 	(void) ad_disc_set_ForestName(ad_ctx, pgcfg->forest_name);
867*5317Sjp151216 
868*5317Sjp151216 	rc = get_val_astring(handles, "site_name", &pgcfg->site_name);
869*5317Sjp151216 	if (rc != 0) {
870*5317Sjp151216 		rc = -1;
871*5317Sjp151216 		goto exit;
872*5317Sjp151216 	}
873*5317Sjp151216 	(void) ad_disc_set_SiteName(ad_ctx, pgcfg->site_name);
874*5317Sjp151216 
875*5317Sjp151216 	str = NULL;
876*5317Sjp151216 	rc = get_val_ds(handles, "global_catalog", 3268,
877*5317Sjp151216 	    &pgcfg->global_catalog);
878*5317Sjp151216 	if (rc != 0) {
879*5317Sjp151216 		rc = -1;
880*5317Sjp151216 		goto exit;
881*5317Sjp151216 	}
882*5317Sjp151216 	(void) ad_disc_set_GlobalCatalog(ad_ctx, pgcfg->global_catalog);
8834520Snw141292 
884*5317Sjp151216 
885*5317Sjp151216 	/*
886*5317Sjp151216 	 * Auto Discover the rest
887*5317Sjp151216 	 */
888*5317Sjp151216 	if (pgcfg->default_domain == NULL) {
889*5317Sjp151216 		pgcfg->default_domain = ad_disc_get_DomainName(ad_ctx);
890*5317Sjp151216 		if (pgcfg->default_domain == NULL) {
891*5317Sjp151216 			idmapdlog(LOG_INFO,
892*5317Sjp151216 			    "%s: unable to discover Default Domain", me);
893*5317Sjp151216 		}
894*5317Sjp151216 	}
895*5317Sjp151216 
896*5317Sjp151216 	if (pgcfg->domain_name == NULL) {
897*5317Sjp151216 		pgcfg->domain_name = ad_disc_get_DomainName(ad_ctx);
898*5317Sjp151216 		if (pgcfg->domain_name == NULL) {
899*5317Sjp151216 			idmapdlog(LOG_INFO,
900*5317Sjp151216 			    "%s: unable to discover Domain Name", me);
901*5317Sjp151216 		}
902*5317Sjp151216 	}
903*5317Sjp151216 
904*5317Sjp151216 	if (pgcfg->domain_controller == NULL) {
905*5317Sjp151216 		pgcfg->domain_controller =
906*5317Sjp151216 		    ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE);
907*5317Sjp151216 		if (pgcfg->domain_controller == NULL) {
908*5317Sjp151216 			idmapdlog(LOG_INFO,
909*5317Sjp151216 			    "%s: unable to discover Domain Controller", me);
910*5317Sjp151216 		}
911*5317Sjp151216 	}
912*5317Sjp151216 
913*5317Sjp151216 	if (pgcfg->forest_name == NULL) {
914*5317Sjp151216 		pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx);
915*5317Sjp151216 		if (pgcfg->forest_name == NULL) {
916*5317Sjp151216 			idmapdlog(LOG_INFO,
917*5317Sjp151216 			    "%s: unable to discover Forest Name", me);
918*5317Sjp151216 		}
919*5317Sjp151216 	}
920*5317Sjp151216 
921*5317Sjp151216 	if (pgcfg->site_name == NULL) {
922*5317Sjp151216 		pgcfg->site_name = ad_disc_get_SiteName(ad_ctx);
923*5317Sjp151216 		if (pgcfg->site_name == NULL) {
924*5317Sjp151216 			idmapdlog(LOG_INFO,
925*5317Sjp151216 			    "%s: unable to discover Site Name", me);
926*5317Sjp151216 		}
927*5317Sjp151216 	}
928*5317Sjp151216 
929*5317Sjp151216 	if (pgcfg->global_catalog == NULL) {
930*5317Sjp151216 		pgcfg->global_catalog =
931*5317Sjp151216 		    ad_disc_get_GlobalCatalog(ad_ctx, AD_DISC_PREFER_SITE);
932*5317Sjp151216 		if (pgcfg->global_catalog == NULL) {
933*5317Sjp151216 			idmapdlog(LOG_INFO,
934*5317Sjp151216 			    "%s: unable to discover Global Catalog", me);
935*5317Sjp151216 		}
936*5317Sjp151216 	}
937*5317Sjp151216 exit:
938*5317Sjp151216 	pthread_mutex_unlock(&handles->mutex);
9394520Snw141292 
9404520Snw141292 	return (rc);
9414520Snw141292 }
9424520Snw141292 
9434644Sbaban /*
9444644Sbaban  * Initialize 'cfg'.
9454644Sbaban  */
9464520Snw141292 idmap_cfg_t *
9474520Snw141292 idmap_cfg_init() {
948*5317Sjp151216 	idmap_cfg_handles_t *handles;
9494520Snw141292 
9504520Snw141292 	/* First the smf repository handles: */
9514520Snw141292 	idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t));
9524520Snw141292 	if (!cfg) {
9534644Sbaban 		idmapdlog(LOG_ERR, "%s: Out of memory", me);
9544520Snw141292 		return (NULL);
9554520Snw141292 	}
956*5317Sjp151216 	handles = &cfg->handles;
9574520Snw141292 
958*5317Sjp151216 	(void) pthread_mutex_init(&handles->mutex, NULL);
959*5317Sjp151216 
960*5317Sjp151216 	if (!(handles->main = scf_handle_create(SCF_VERSION))) {
9614644Sbaban 		idmapdlog(LOG_ERR, "%s: scf_handle_create() failed: %s",
9624644Sbaban 		    me, scf_strerror(scf_error()));
9634520Snw141292 		goto error;
9644520Snw141292 	}
9654520Snw141292 
966*5317Sjp151216 	if (scf_handle_bind(handles->main) < 0) {
9674644Sbaban 		idmapdlog(LOG_ERR, "%s: scf_handle_bind() failed: %s",
9684644Sbaban 		    me, scf_strerror(scf_error()));
9694520Snw141292 		goto error;
9704520Snw141292 	}
9714520Snw141292 
972*5317Sjp151216 	if (!(handles->service = scf_service_create(handles->main)) ||
973*5317Sjp151216 	    !(handles->instance = scf_instance_create(handles->main)) ||
974*5317Sjp151216 	    !(handles->config_pg = scf_pg_create(handles->main)) ||
975*5317Sjp151216 	    !(handles->general_pg = scf_pg_create(handles->main))) {
9764644Sbaban 		idmapdlog(LOG_ERR, "%s: scf handle creation failed: %s",
9774644Sbaban 		    me, scf_strerror(scf_error()));
9784520Snw141292 		goto error;
9794520Snw141292 	}
9804520Snw141292 
981*5317Sjp151216 	if (scf_handle_decode_fmri(handles->main,
9824520Snw141292 		FMRI_BASE "/:properties/" CONFIG_PG,
9834520Snw141292 		NULL,				/* scope */
984*5317Sjp151216 		handles->service,		/* service */
985*5317Sjp151216 		handles->instance,		/* instance */
986*5317Sjp151216 		handles->config_pg,		/* pg */
9874520Snw141292 		NULL,				/* prop */
988*5317Sjp151216 		SCF_DECODE_FMRI_EXACT) < 0) {
9894644Sbaban 		idmapdlog(LOG_ERR, "%s: scf_handle_decode_fmri() failed: %s",
9904644Sbaban 		    me, scf_strerror(scf_error()));
9914520Snw141292 		goto error;
9924520Snw141292 
9934520Snw141292 	}
9944520Snw141292 
995*5317Sjp151216 	if (scf_service_get_pg(handles->service,
996*5317Sjp151216 		GENERAL_PG, handles->general_pg) < 0) {
9974644Sbaban 		idmapdlog(LOG_ERR, "%s: scf_service_get_pg() failed: %s",
9984644Sbaban 		    me, scf_strerror(scf_error()));
9994520Snw141292 		goto error;
10004520Snw141292 	}
10014520Snw141292 
1002*5317Sjp151216 	/* Initialize AD Auto Discovery context */
1003*5317Sjp151216 	handles->ad_ctx = ad_disc_init();
1004*5317Sjp151216 	if (handles->ad_ctx == NULL)
1005*5317Sjp151216 		goto error;
1006*5317Sjp151216 
10074520Snw141292 	return (cfg);
10084520Snw141292 
10094520Snw141292 error:
10104520Snw141292 	(void) idmap_cfg_fini(cfg);
10114520Snw141292 	return (NULL);
10124520Snw141292 }
10134520Snw141292 
1014*5317Sjp151216 void
1015*5317Sjp151216 idmap_cfg_unload(idmap_pg_config_t *pgcfg) {
1016*5317Sjp151216 
1017*5317Sjp151216 	if (pgcfg->default_domain) {
1018*5317Sjp151216 		free(pgcfg->default_domain);
1019*5317Sjp151216 		pgcfg->default_domain = NULL;
1020*5317Sjp151216 	}
1021*5317Sjp151216 	if (pgcfg->domain_name) {
1022*5317Sjp151216 		free(pgcfg->domain_name);
1023*5317Sjp151216 		pgcfg->domain_name = NULL;
1024*5317Sjp151216 	}
1025*5317Sjp151216 	if (pgcfg->machine_sid) {
1026*5317Sjp151216 		free(pgcfg->machine_sid);
1027*5317Sjp151216 		pgcfg->machine_sid = NULL;
1028*5317Sjp151216 	}
1029*5317Sjp151216 	if (pgcfg->domain_controller) {
1030*5317Sjp151216 		free(pgcfg->domain_controller);
1031*5317Sjp151216 		pgcfg->domain_controller = NULL;
1032*5317Sjp151216 	}
1033*5317Sjp151216 	if (pgcfg->forest_name) {
1034*5317Sjp151216 		free(pgcfg->forest_name);
1035*5317Sjp151216 		pgcfg->forest_name = NULL;
1036*5317Sjp151216 	}
1037*5317Sjp151216 	if (pgcfg->site_name) {
1038*5317Sjp151216 		free(pgcfg->site_name);
1039*5317Sjp151216 		pgcfg->site_name = NULL;
1040*5317Sjp151216 	}
1041*5317Sjp151216 	if (pgcfg->global_catalog) {
10424520Snw141292 		free(pgcfg->global_catalog);
1043*5317Sjp151216 		pgcfg->global_catalog = NULL;
1044*5317Sjp151216 	}
10454520Snw141292 }
10464520Snw141292 
10474520Snw141292 int
10484520Snw141292 idmap_cfg_fini(idmap_cfg_t *cfg)
10494520Snw141292 {
1050*5317Sjp151216 	idmap_cfg_handles_t *handles = &cfg->handles;
1051*5317Sjp151216 	idmap_cfg_unload(&cfg->pgcfg);
10524520Snw141292 
1053*5317Sjp151216 	(void) pthread_mutex_destroy(&handles->mutex);
1054*5317Sjp151216 	scf_pg_destroy(handles->config_pg);
1055*5317Sjp151216 	scf_pg_destroy(handles->general_pg);
1056*5317Sjp151216 	scf_instance_destroy(handles->instance);
1057*5317Sjp151216 	scf_service_destroy(handles->service);
1058*5317Sjp151216 	scf_handle_destroy(handles->main);
1059*5317Sjp151216 	ad_disc_fini(handles->ad_ctx);
10604520Snw141292 	free(cfg);
10614520Snw141292 
10624520Snw141292 	return (0);
10634520Snw141292 }
1064