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