17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5cb5caa98Sdjl * Common Development and Distribution License (the "License"). 6cb5caa98Sdjl * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*e0a5e15fSMilan Jurik * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate #include <assert.h> 267c478bd9Sstevel@tonic-gate #include <errno.h> 277c478bd9Sstevel@tonic-gate #include <memory.h> 287c478bd9Sstevel@tonic-gate #include <signal.h> 297c478bd9Sstevel@tonic-gate #include <stdlib.h> 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <string.h> 327c478bd9Sstevel@tonic-gate #include <libintl.h> 337c478bd9Sstevel@tonic-gate #include <syslog.h> 347c478bd9Sstevel@tonic-gate #include <sys/door.h> 357c478bd9Sstevel@tonic-gate #include <sys/stat.h> 367c478bd9Sstevel@tonic-gate #include <sys/time.h> 377c478bd9Sstevel@tonic-gate #include <sys/types.h> 387c478bd9Sstevel@tonic-gate #include <sys/wait.h> 397c478bd9Sstevel@tonic-gate #include <synch.h> 407c478bd9Sstevel@tonic-gate #include <pthread.h> 417c478bd9Sstevel@tonic-gate #include <unistd.h> 427c478bd9Sstevel@tonic-gate #include <lber.h> 437c478bd9Sstevel@tonic-gate #include <ldap.h> 447c478bd9Sstevel@tonic-gate #include <ctype.h> /* tolower */ 45cb5caa98Sdjl #include <sys/socket.h> 46cb5caa98Sdjl #include <netinet/in.h> 47cb5caa98Sdjl #include <arpa/inet.h> 48e1dd0a2fSth160488 #include <ucred.h> 497c478bd9Sstevel@tonic-gate #include "cachemgr.h" 507c478bd9Sstevel@tonic-gate #include "solaris-priv.h" 51e1dd0a2fSth160488 #include "ns_connmgmt.h" 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate static rwlock_t ldap_lock = DEFAULTRWLOCK; 547c478bd9Sstevel@tonic-gate static int sighup_update = FALSE; 557c478bd9Sstevel@tonic-gate extern admin_t current_admin; 567c478bd9Sstevel@tonic-gate 57b57459abSJulian Pullen extern int is_root_or_all_privs(char *dc_str, ucred_t **ucp); 58b57459abSJulian Pullen 597c478bd9Sstevel@tonic-gate /* variables used for SIGHUP wakeup on sleep */ 607c478bd9Sstevel@tonic-gate static mutex_t sighuplock; 617c478bd9Sstevel@tonic-gate static cond_t cond; 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate /* refresh time statistics */ 647c478bd9Sstevel@tonic-gate static time_t prev_refresh_time = 0; 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* variables used for signaling parent process */ 677c478bd9Sstevel@tonic-gate static mutex_t sig_mutex; 687c478bd9Sstevel@tonic-gate static int signal_done = FALSE; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* TCP connection timeout (in milliseconds) */ 717c478bd9Sstevel@tonic-gate static int tcptimeout = NS_DEFAULT_BIND_TIMEOUT * 1000; 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate #ifdef SLP 747c478bd9Sstevel@tonic-gate extern int use_slp; 757c478bd9Sstevel@tonic-gate #endif /* SLP */ 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* nis domain information */ 787c478bd9Sstevel@tonic-gate #define _NIS_FILTER "objectclass=nisDomainObject" 797c478bd9Sstevel@tonic-gate #define _NIS_DOMAIN "nisdomain" 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate #define CACHESLEEPTIME 600 827c478bd9Sstevel@tonic-gate /* 837c478bd9Sstevel@tonic-gate * server list refresh delay when in "no server" mode 847c478bd9Sstevel@tonic-gate * (1 second) 857c478bd9Sstevel@tonic-gate */ 867c478bd9Sstevel@tonic-gate #define REFRESH_DELAY_WHEN_NO_SERVER 1 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate typedef enum { 897c478bd9Sstevel@tonic-gate INFO_OP_CREATE = 0, 907c478bd9Sstevel@tonic-gate INFO_OP_DELETE = 1, 917c478bd9Sstevel@tonic-gate INFO_OP_REFRESH = 2, 927c478bd9Sstevel@tonic-gate INFO_OP_REFRESH_WAIT = 3, 937c478bd9Sstevel@tonic-gate INFO_OP_GETSERVER = 4, 94e1dd0a2fSth160488 INFO_OP_GETSTAT = 5, 95e1dd0a2fSth160488 INFO_OP_REMOVESERVER = 6 967c478bd9Sstevel@tonic-gate } info_op_t; 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate typedef enum { 997c478bd9Sstevel@tonic-gate INFO_RW_UNKNOWN = 0, 1007c478bd9Sstevel@tonic-gate INFO_RW_READONLY = 1, 1017c478bd9Sstevel@tonic-gate INFO_RW_WRITEABLE = 2 1027c478bd9Sstevel@tonic-gate } info_rw_t; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate typedef enum { 1057c478bd9Sstevel@tonic-gate INFO_SERVER_JUST_INITED = -1, 1067c478bd9Sstevel@tonic-gate INFO_SERVER_UNKNOWN = 0, 1077c478bd9Sstevel@tonic-gate INFO_SERVER_CONNECTING = 1, 1087c478bd9Sstevel@tonic-gate INFO_SERVER_UP = 2, 1097c478bd9Sstevel@tonic-gate INFO_SERVER_ERROR = 3, 1107c478bd9Sstevel@tonic-gate INFO_SERVER_REMOVED = 4 1117c478bd9Sstevel@tonic-gate } info_server_t; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate typedef enum { 1147c478bd9Sstevel@tonic-gate INFO_STATUS_UNKNOWN = 0, 1157c478bd9Sstevel@tonic-gate INFO_STATUS_ERROR = 1, 1167c478bd9Sstevel@tonic-gate INFO_STATUS_NEW = 2, 1177c478bd9Sstevel@tonic-gate INFO_STATUS_OLD = 3 1187c478bd9Sstevel@tonic-gate } info_status_t; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate typedef enum { 1217c478bd9Sstevel@tonic-gate CACHE_OP_CREATE = 0, 1227c478bd9Sstevel@tonic-gate CACHE_OP_DELETE = 1, 1237c478bd9Sstevel@tonic-gate CACHE_OP_FIND = 2, 1247c478bd9Sstevel@tonic-gate CACHE_OP_ADD = 3, 1257c478bd9Sstevel@tonic-gate CACHE_OP_GETSTAT = 4 1267c478bd9Sstevel@tonic-gate } cache_op_t; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate typedef enum { 1297c478bd9Sstevel@tonic-gate CACHE_MAP_UNKNOWN = 0, 1307c478bd9Sstevel@tonic-gate CACHE_MAP_DN2DOMAIN = 1 1317c478bd9Sstevel@tonic-gate } cache_type_t; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate typedef struct server_info_ext { 1347c478bd9Sstevel@tonic-gate char *addr; 135cb5caa98Sdjl char *hostname; 1367c478bd9Sstevel@tonic-gate char *rootDSE_data; 1377c478bd9Sstevel@tonic-gate char *errormsg; 1387c478bd9Sstevel@tonic-gate info_rw_t type; 1397c478bd9Sstevel@tonic-gate info_server_t server_status; 1407c478bd9Sstevel@tonic-gate info_server_t prev_server_status; 1417c478bd9Sstevel@tonic-gate info_status_t info_status; 142e1dd0a2fSth160488 ns_server_status_t change; 1437c478bd9Sstevel@tonic-gate } server_info_ext_t; 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate typedef struct server_info { 1467c478bd9Sstevel@tonic-gate struct server_info *next; 1477c478bd9Sstevel@tonic-gate mutex_t mutex[2]; /* 0: current copy lock */ 1487c478bd9Sstevel@tonic-gate /* 1: update copy lock */ 1497c478bd9Sstevel@tonic-gate server_info_ext_t sinfo[2]; /* 0: current, 1: update copy */ 1507c478bd9Sstevel@tonic-gate } server_info_t; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate typedef struct cache_hash { 1537c478bd9Sstevel@tonic-gate cache_type_t type; 1547c478bd9Sstevel@tonic-gate char *from; 1557c478bd9Sstevel@tonic-gate char *to; 1567c478bd9Sstevel@tonic-gate struct cache_hash *next; 1577c478bd9Sstevel@tonic-gate } cache_hash_t; 1587c478bd9Sstevel@tonic-gate 159e1dd0a2fSth160488 /* 160e1dd0a2fSth160488 * The status of a server to be removed. It can be up or down. 161e1dd0a2fSth160488 */ 162e1dd0a2fSth160488 typedef struct rm_svr { 163e1dd0a2fSth160488 char *addr; 164e1dd0a2fSth160488 int up; /* 1: up, 0: down */ 165e1dd0a2fSth160488 } rm_svr_t; 166e1dd0a2fSth160488 1677c478bd9Sstevel@tonic-gate static int getldap_destroy_serverInfo(server_info_t *head); 168e1dd0a2fSth160488 static void test_server_change(server_info_t *head); 169e1dd0a2fSth160488 static void remove_server(char *addr); 170e1dd0a2fSth160488 static ns_server_status_t set_server_status(char *input, server_info_t *head); 171e1dd0a2fSth160488 static void create_buf_and_notify(char *input, ns_server_status_t st); 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate /* 1747c478bd9Sstevel@tonic-gate * Load configuration 1757c478bd9Sstevel@tonic-gate * The code was in signal handler getldap_revalidate 1767c478bd9Sstevel@tonic-gate * It's moved out of the handler because it could cause deadlock 1777c478bd9Sstevel@tonic-gate * return: 1 SUCCESS 1787c478bd9Sstevel@tonic-gate * 0 FAIL 1797c478bd9Sstevel@tonic-gate */ 1807c478bd9Sstevel@tonic-gate static int 1817c478bd9Sstevel@tonic-gate load_config() { 1827c478bd9Sstevel@tonic-gate ns_ldap_error_t *error; 1837c478bd9Sstevel@tonic-gate int rc = 1; 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate (void) __ns_ldap_setServer(TRUE); 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ldap_lock); 1887c478bd9Sstevel@tonic-gate if ((error = __ns_ldap_LoadConfiguration()) != NULL) { 1897c478bd9Sstevel@tonic-gate logit("Error: Unable to read '%s': %s\n", 1907c478bd9Sstevel@tonic-gate NSCONFIGFILE, error->message); 1917c478bd9Sstevel@tonic-gate __ns_ldap_freeError(&error); 1927c478bd9Sstevel@tonic-gate rc = 0; /* FAIL */ 1937c478bd9Sstevel@tonic-gate } else 1947c478bd9Sstevel@tonic-gate sighup_update = TRUE; 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldap_lock); 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate return (rc); 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate /* 2027c478bd9Sstevel@tonic-gate * Calculate a hash for a string 2037c478bd9Sstevel@tonic-gate * Based on elf_hash algorithm, hash is case insensitive 2047c478bd9Sstevel@tonic-gate * Uses tolower instead of _tolower because of I18N 2057c478bd9Sstevel@tonic-gate */ 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate static unsigned long 2087c478bd9Sstevel@tonic-gate getldap_hash(const char *str) 2097c478bd9Sstevel@tonic-gate { 2107c478bd9Sstevel@tonic-gate unsigned int hval = 0; 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate while (*str) { 2137c478bd9Sstevel@tonic-gate unsigned int g; 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate hval = (hval << 4) + tolower(*str++); 2167c478bd9Sstevel@tonic-gate if ((g = (hval & 0xf0000000)) != 0) 2177c478bd9Sstevel@tonic-gate hval ^= g >> 24; 2187c478bd9Sstevel@tonic-gate hval &= ~g; 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate return ((unsigned long)hval); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate /* 2247c478bd9Sstevel@tonic-gate * Remove a hash table entry. 2257c478bd9Sstevel@tonic-gate * This function expects a lock in place when called. 2267c478bd9Sstevel@tonic-gate */ 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate static cache_hash_t * 2297c478bd9Sstevel@tonic-gate getldap_free_hash(cache_hash_t *p) 2307c478bd9Sstevel@tonic-gate { 2317c478bd9Sstevel@tonic-gate cache_hash_t *next; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate p->type = CACHE_MAP_UNKNOWN; 2347c478bd9Sstevel@tonic-gate if (p->from) 2357c478bd9Sstevel@tonic-gate free(p->from); 2367c478bd9Sstevel@tonic-gate if (p->to) 2377c478bd9Sstevel@tonic-gate free(p->to); 2387c478bd9Sstevel@tonic-gate next = p->next; 2397c478bd9Sstevel@tonic-gate p->next = NULL; 2407c478bd9Sstevel@tonic-gate free(p); 2417c478bd9Sstevel@tonic-gate return (next); 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate /* 2457c478bd9Sstevel@tonic-gate * Scan a hash table hit for a matching hash entry. 2467c478bd9Sstevel@tonic-gate * This function expects a lock in place when called. 2477c478bd9Sstevel@tonic-gate */ 2487c478bd9Sstevel@tonic-gate static cache_hash_t * 2497c478bd9Sstevel@tonic-gate getldap_scan_hash(cache_type_t type, char *from, 2507c478bd9Sstevel@tonic-gate cache_hash_t *idx) 2517c478bd9Sstevel@tonic-gate { 2527c478bd9Sstevel@tonic-gate while (idx) { 2537c478bd9Sstevel@tonic-gate if (idx->type == type && 2547c478bd9Sstevel@tonic-gate strcasecmp(from, idx->from) == 0) { 2557c478bd9Sstevel@tonic-gate return (idx); 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate idx = idx->next; 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate return ((cache_hash_t *)NULL); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* 2637c478bd9Sstevel@tonic-gate * Format and return the cache data statistics 2647c478bd9Sstevel@tonic-gate */ 2657c478bd9Sstevel@tonic-gate static int 2667c478bd9Sstevel@tonic-gate getldap_get_cacheData_stat(int max, int current, char **output) 2677c478bd9Sstevel@tonic-gate { 2687c478bd9Sstevel@tonic-gate #define C_HEADER0 "Cache data information: " 2697c478bd9Sstevel@tonic-gate #define C_HEADER1 " Maximum cache entries: " 2707c478bd9Sstevel@tonic-gate #define C_HEADER2 " Number of cache entries: " 2717c478bd9Sstevel@tonic-gate int hdr0_len = strlen(gettext(C_HEADER0)); 2727c478bd9Sstevel@tonic-gate int hdr1_len = strlen(gettext(C_HEADER1)); 2737c478bd9Sstevel@tonic-gate int hdr2_len = strlen(gettext(C_HEADER2)); 2747c478bd9Sstevel@tonic-gate int len; 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 2777c478bd9Sstevel@tonic-gate logit("getldap_get_cacheData_stat()...\n"); 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate *output = NULL; 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate len = hdr0_len + hdr1_len + hdr2_len + 2837c478bd9Sstevel@tonic-gate 3 * strlen(DOORLINESEP) + 21; 2847c478bd9Sstevel@tonic-gate *output = malloc(len); 2857c478bd9Sstevel@tonic-gate if (*output == NULL) 2867c478bd9Sstevel@tonic-gate return (-1); 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate (void) snprintf(*output, len, "%s%s%s%10d%s%s%10d%s", 2897c478bd9Sstevel@tonic-gate gettext(C_HEADER0), DOORLINESEP, 2907c478bd9Sstevel@tonic-gate gettext(C_HEADER1), max, DOORLINESEP, 2917c478bd9Sstevel@tonic-gate gettext(C_HEADER2), current, DOORLINESEP); 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate static int 2977c478bd9Sstevel@tonic-gate getldap_cache_op(cache_op_t op, cache_type_t type, 2987c478bd9Sstevel@tonic-gate char *from, char **to) 2997c478bd9Sstevel@tonic-gate { 3007c478bd9Sstevel@tonic-gate #define CACHE_HASH_MAX 257 3017c478bd9Sstevel@tonic-gate #define CACHE_HASH_MAX_ENTRY 256 3027c478bd9Sstevel@tonic-gate static cache_hash_t *hashTbl[CACHE_HASH_MAX]; 3037c478bd9Sstevel@tonic-gate cache_hash_t *next, *idx, *newp; 3047c478bd9Sstevel@tonic-gate unsigned long hash; 3057c478bd9Sstevel@tonic-gate static rwlock_t cache_lock = DEFAULTRWLOCK; 3067c478bd9Sstevel@tonic-gate int i; 307a506a34cSth160488 static int entry_num = 0; 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 3107c478bd9Sstevel@tonic-gate logit("getldap_cache_op()...\n"); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate switch (op) { 3137c478bd9Sstevel@tonic-gate case CACHE_OP_CREATE: 3147c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 3157c478bd9Sstevel@tonic-gate logit("operation is CACHE_OP_CREATE...\n"); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate (void) rw_wrlock(&cache_lock); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate for (i = 0; i < CACHE_HASH_MAX; i++) { 3207c478bd9Sstevel@tonic-gate hashTbl[i] = NULL; 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate entry_num = 0; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate (void) rw_unlock(&cache_lock); 3257c478bd9Sstevel@tonic-gate break; 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate case CACHE_OP_DELETE: 3287c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 3297c478bd9Sstevel@tonic-gate logit("operation is CACHE_OP_DELETE...\n"); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate (void) rw_wrlock(&cache_lock); 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate for (i = 0; i < CACHE_HASH_MAX; i++) { 3347c478bd9Sstevel@tonic-gate next = hashTbl[i]; 3357c478bd9Sstevel@tonic-gate while (next != NULL) { 3367c478bd9Sstevel@tonic-gate next = getldap_free_hash(next); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate hashTbl[i] = NULL; 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate entry_num = 0; 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate (void) rw_unlock(&cache_lock); 3437c478bd9Sstevel@tonic-gate break; 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate case CACHE_OP_ADD: 3467c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 3477c478bd9Sstevel@tonic-gate logit("operation is CACHE_OP_ADD...\n"); 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate if (from == NULL || to == NULL || *to == NULL) 3507c478bd9Sstevel@tonic-gate return (-1); 3517c478bd9Sstevel@tonic-gate hash = getldap_hash(from) % CACHE_HASH_MAX; 3527c478bd9Sstevel@tonic-gate (void) rw_wrlock(&cache_lock); 3537c478bd9Sstevel@tonic-gate idx = hashTbl[hash]; 3547c478bd9Sstevel@tonic-gate /* 3557c478bd9Sstevel@tonic-gate * replace old "to" value with new one 3567c478bd9Sstevel@tonic-gate * if an entry with same "from" 3577c478bd9Sstevel@tonic-gate * already exists 3587c478bd9Sstevel@tonic-gate */ 3597c478bd9Sstevel@tonic-gate if (idx) { 3607c478bd9Sstevel@tonic-gate newp = getldap_scan_hash(type, from, idx); 3617c478bd9Sstevel@tonic-gate if (newp) { 3627c478bd9Sstevel@tonic-gate free(newp->to); 3637c478bd9Sstevel@tonic-gate newp->to = strdup(*to); 3647c478bd9Sstevel@tonic-gate (void) rw_unlock(&cache_lock); 3657c478bd9Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate if (entry_num > CACHE_HASH_MAX_ENTRY) { 3707c478bd9Sstevel@tonic-gate (void) rw_unlock(&cache_lock); 3717c478bd9Sstevel@tonic-gate return (-1); 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate newp = (cache_hash_t *)malloc(sizeof (cache_hash_t)); 3757c478bd9Sstevel@tonic-gate if (newp == NULL) { 3767c478bd9Sstevel@tonic-gate (void) rw_unlock(&cache_lock); 3777c478bd9Sstevel@tonic-gate return (NS_LDAP_MEMORY); 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate newp->type = type; 3807c478bd9Sstevel@tonic-gate newp->from = strdup(from); 3817c478bd9Sstevel@tonic-gate newp->to = strdup(*to); 3827c478bd9Sstevel@tonic-gate newp->next = idx; 3837c478bd9Sstevel@tonic-gate hashTbl[hash] = newp; 3847c478bd9Sstevel@tonic-gate entry_num++; 3857c478bd9Sstevel@tonic-gate (void) rw_unlock(&cache_lock); 3867c478bd9Sstevel@tonic-gate break; 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate case CACHE_OP_FIND: 3897c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 3907c478bd9Sstevel@tonic-gate logit("operation is CACHE_OP_FIND...\n"); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate if (from == NULL || to == NULL) 3937c478bd9Sstevel@tonic-gate return (-1); 3947c478bd9Sstevel@tonic-gate *to = NULL; 3957c478bd9Sstevel@tonic-gate hash = getldap_hash(from) % CACHE_HASH_MAX; 3967c478bd9Sstevel@tonic-gate (void) rw_rdlock(&cache_lock); 3977c478bd9Sstevel@tonic-gate idx = hashTbl[hash]; 3987c478bd9Sstevel@tonic-gate idx = getldap_scan_hash(type, from, idx); 3997c478bd9Sstevel@tonic-gate if (idx) 4007c478bd9Sstevel@tonic-gate *to = strdup(idx->to); 4017c478bd9Sstevel@tonic-gate (void) rw_unlock(&cache_lock); 4027c478bd9Sstevel@tonic-gate if (idx == NULL) 4037c478bd9Sstevel@tonic-gate return (-1); 4047c478bd9Sstevel@tonic-gate break; 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate case CACHE_OP_GETSTAT: 4077c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 4087c478bd9Sstevel@tonic-gate logit("operation is CACHE_OP_GETSTAT...\n"); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate if (to == NULL) 4117c478bd9Sstevel@tonic-gate return (-1); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate return (getldap_get_cacheData_stat(CACHE_HASH_MAX_ENTRY, 4147c478bd9Sstevel@tonic-gate entry_num, to)); 4157c478bd9Sstevel@tonic-gate break; 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate default: 4187c478bd9Sstevel@tonic-gate logit("getldap_cache_op(): " 4197c478bd9Sstevel@tonic-gate "invalid operation code (%d).\n", op); 4207c478bd9Sstevel@tonic-gate return (-1); 4217c478bd9Sstevel@tonic-gate break; 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate /* 4267c478bd9Sstevel@tonic-gate * Function: sync_current_with_update_copy 4277c478bd9Sstevel@tonic-gate * 4287c478bd9Sstevel@tonic-gate * This function syncs up the 2 sinfo copies in info. 4297c478bd9Sstevel@tonic-gate * 4307c478bd9Sstevel@tonic-gate * The 2 copies are identical most of time. 4317c478bd9Sstevel@tonic-gate * The update copy(sinfo[1]) could be different when 4327c478bd9Sstevel@tonic-gate * getldap_serverInfo_refresh thread is refreshing the server list 4337c478bd9Sstevel@tonic-gate * and calls getldap_get_rootDSE to update info. getldap_get_rootDSE 4347c478bd9Sstevel@tonic-gate * calls sync_current_with_update_copy to sync up 2 copies before thr_exit. 4357c478bd9Sstevel@tonic-gate * The calling sequence is 4367c478bd9Sstevel@tonic-gate * getldap_serverInfo_refresh-> 4377c478bd9Sstevel@tonic-gate * getldap_get_serverInfo_op(INFO_OP_CREATE,...)-> 4387c478bd9Sstevel@tonic-gate * getldap_set_serverInfo-> 4397c478bd9Sstevel@tonic-gate * getldap_get_rootDSE 4407c478bd9Sstevel@tonic-gate * 4417c478bd9Sstevel@tonic-gate * The original server_info_t has one copy of server info. When libsldap 4427c478bd9Sstevel@tonic-gate * makes door call GETLDAPSERVER to get the server info and getldap_get_rootDSE 4437c478bd9Sstevel@tonic-gate * is updating the server info, it would hit a unprotected window in 4447c478bd9Sstevel@tonic-gate * getldap_rootDSE. The door call will not get server info and libsldap 4457c478bd9Sstevel@tonic-gate * fails at making ldap connection. 4467c478bd9Sstevel@tonic-gate * 4477c478bd9Sstevel@tonic-gate * The new server_info_t provides GETLDAPSERVER thread with a current 4487c478bd9Sstevel@tonic-gate * copy(sinfo[0]). getldap_get_rootDSE only works on the update copy(sinfo[1]) 4497c478bd9Sstevel@tonic-gate * and syncs up 2 copies before thr_exit. This will close the window in 4507c478bd9Sstevel@tonic-gate * getldap_get_rootDSE. 4517c478bd9Sstevel@tonic-gate * 4527c478bd9Sstevel@tonic-gate */ 4537c478bd9Sstevel@tonic-gate static void 4547c478bd9Sstevel@tonic-gate sync_current_with_update_copy(server_info_t *info) 4557c478bd9Sstevel@tonic-gate { 4567c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 4577c478bd9Sstevel@tonic-gate logit("sync_current_with_update_copy()...\n"); 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate (void) mutex_lock(&info->mutex[1]); 4617c478bd9Sstevel@tonic-gate (void) mutex_lock(&info->mutex[0]); 4627c478bd9Sstevel@tonic-gate 463e1dd0a2fSth160488 if (info->sinfo[1].server_status == INFO_SERVER_UP && 464e1dd0a2fSth160488 info->sinfo[0].server_status != INFO_SERVER_UP) 465e1dd0a2fSth160488 info->sinfo[1].change = NS_SERVER_UP; 466e1dd0a2fSth160488 else if (info->sinfo[1].server_status != INFO_SERVER_UP && 467e1dd0a2fSth160488 info->sinfo[0].server_status == INFO_SERVER_UP) 468e1dd0a2fSth160488 info->sinfo[1].change = NS_SERVER_DOWN; 469e1dd0a2fSth160488 else 470e1dd0a2fSth160488 info->sinfo[1].change = 0; 471e1dd0a2fSth160488 472e1dd0a2fSth160488 4737c478bd9Sstevel@tonic-gate /* free memory in current copy first */ 4747c478bd9Sstevel@tonic-gate if (info->sinfo[0].addr) 4757c478bd9Sstevel@tonic-gate free(info->sinfo[0].addr); 4767c478bd9Sstevel@tonic-gate info->sinfo[0].addr = NULL; 4777c478bd9Sstevel@tonic-gate 478cb5caa98Sdjl if (info->sinfo[0].hostname) 479cb5caa98Sdjl free(info->sinfo[0].hostname); 480cb5caa98Sdjl info->sinfo[0].hostname = NULL; 481cb5caa98Sdjl 4827c478bd9Sstevel@tonic-gate if (info->sinfo[0].rootDSE_data) 4837c478bd9Sstevel@tonic-gate free(info->sinfo[0].rootDSE_data); 4847c478bd9Sstevel@tonic-gate info->sinfo[0].rootDSE_data = NULL; 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate if (info->sinfo[0].errormsg) 4877c478bd9Sstevel@tonic-gate free(info->sinfo[0].errormsg); 4887c478bd9Sstevel@tonic-gate info->sinfo[0].errormsg = NULL; 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate /* 4917c478bd9Sstevel@tonic-gate * make current and update copy identical 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate info->sinfo[0] = info->sinfo[1]; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate /* 4967c478bd9Sstevel@tonic-gate * getldap_get_server_stat() reads the update copy sinfo[1] 4977c478bd9Sstevel@tonic-gate * so it can't be freed or nullified yet at this point. 4987c478bd9Sstevel@tonic-gate * 4997c478bd9Sstevel@tonic-gate * The sinfo[0] and sinfo[1] have identical string pointers. 5007c478bd9Sstevel@tonic-gate * strdup the strings to avoid the double free problem. 5017c478bd9Sstevel@tonic-gate * The strings of sinfo[1] are freed in 5027c478bd9Sstevel@tonic-gate * getldap_get_rootDSE() and the strings of sinfo[0] 5037c478bd9Sstevel@tonic-gate * are freed earlier in this function. If the pointers are the 5047c478bd9Sstevel@tonic-gate * same, they will be freed twice. 5057c478bd9Sstevel@tonic-gate */ 5067c478bd9Sstevel@tonic-gate if (info->sinfo[1].addr) 5077c478bd9Sstevel@tonic-gate info->sinfo[0].addr = strdup(info->sinfo[1].addr); 508cb5caa98Sdjl if (info->sinfo[1].hostname) 509cb5caa98Sdjl info->sinfo[0].hostname = strdup(info->sinfo[1].hostname); 5107c478bd9Sstevel@tonic-gate if (info->sinfo[1].rootDSE_data) 5117c478bd9Sstevel@tonic-gate info->sinfo[0].rootDSE_data = 5127c478bd9Sstevel@tonic-gate strdup(info->sinfo[1].rootDSE_data); 5137c478bd9Sstevel@tonic-gate if (info->sinfo[1].errormsg) 5147c478bd9Sstevel@tonic-gate info->sinfo[0].errormsg = strdup(info->sinfo[1].errormsg); 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info->mutex[0]); 5177c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info->mutex[1]); 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate static void * 5227c478bd9Sstevel@tonic-gate getldap_get_rootDSE(void *arg) 5237c478bd9Sstevel@tonic-gate { 5247c478bd9Sstevel@tonic-gate server_info_t *serverInfo = (server_info_t *)arg; 5257c478bd9Sstevel@tonic-gate char *rootDSE; 526e1dd0a2fSth160488 int exitrc = NS_LDAP_SUCCESS; 5277c478bd9Sstevel@tonic-gate pid_t ppid; 5287c478bd9Sstevel@tonic-gate int server_found = 0; 529*e0a5e15fSMilan Jurik char errmsg[MAXERROR]; 530*e0a5e15fSMilan Jurik ns_ldap_return_code rc; 531e1dd0a2fSth160488 ns_ldap_error_t *error = NULL; 532e1dd0a2fSth160488 5337c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 5347c478bd9Sstevel@tonic-gate logit("getldap_get_rootDSE()....\n"); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate /* initialize the server info element */ 5387c478bd9Sstevel@tonic-gate (void) mutex_lock(&serverInfo->mutex[1]); 5397c478bd9Sstevel@tonic-gate serverInfo->sinfo[1].type = INFO_RW_UNKNOWN; 5404a6b6ac4Schinlong serverInfo->sinfo[1].info_status = 5414a6b6ac4Schinlong INFO_STATUS_UNKNOWN; 5427c478bd9Sstevel@tonic-gate /* 5437c478bd9Sstevel@tonic-gate * When the sever list is refreshed over and over, 5447c478bd9Sstevel@tonic-gate * this function is called each time it is refreshed. 5457c478bd9Sstevel@tonic-gate * The previous server status of the update copy(sinfo[1]) 5467c478bd9Sstevel@tonic-gate * is the status of the current copy 5477c478bd9Sstevel@tonic-gate */ 5487c478bd9Sstevel@tonic-gate (void) mutex_lock(&serverInfo->mutex[0]); 5497c478bd9Sstevel@tonic-gate serverInfo->sinfo[1].prev_server_status = 5507c478bd9Sstevel@tonic-gate serverInfo->sinfo[0].server_status; 5517c478bd9Sstevel@tonic-gate (void) mutex_unlock(&serverInfo->mutex[0]); 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate serverInfo->sinfo[1].server_status = 5547c478bd9Sstevel@tonic-gate INFO_SERVER_UNKNOWN; 5557c478bd9Sstevel@tonic-gate if (serverInfo->sinfo[1].rootDSE_data) 5567c478bd9Sstevel@tonic-gate free(serverInfo->sinfo[1].rootDSE_data); 5577c478bd9Sstevel@tonic-gate serverInfo->sinfo[1].rootDSE_data = NULL; 5587c478bd9Sstevel@tonic-gate if (serverInfo->sinfo[1].errormsg) 5597c478bd9Sstevel@tonic-gate free(serverInfo->sinfo[1].errormsg); 5607c478bd9Sstevel@tonic-gate serverInfo->sinfo[1].errormsg = NULL; 5617c478bd9Sstevel@tonic-gate (void) mutex_unlock(&serverInfo->mutex[1]); 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate (void) mutex_lock(&serverInfo->mutex[1]); 5647c478bd9Sstevel@tonic-gate serverInfo->sinfo[1].server_status = INFO_SERVER_CONNECTING; 5657c478bd9Sstevel@tonic-gate (void) mutex_unlock(&serverInfo->mutex[1]); 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate /* 568e1dd0a2fSth160488 * WARNING: anon_fallback == 1 (last argument) means that when 569e1dd0a2fSth160488 * __ns_ldap_getRootDSE is unable to bind using the configured 570e1dd0a2fSth160488 * credentials, it will try to fall back to using anonymous, non-SSL 571e1dd0a2fSth160488 * mode of operation. 572e1dd0a2fSth160488 * 573e1dd0a2fSth160488 * This is for backward compatibility reasons - we might have machines 574e1dd0a2fSth160488 * in the field with broken configuration (invalid credentials) and we 575e1dd0a2fSth160488 * don't want them to be disturbed. 5767c478bd9Sstevel@tonic-gate */ 577*e0a5e15fSMilan Jurik if (rc = __ns_ldap_getRootDSE(serverInfo->sinfo[1].addr, 578e1dd0a2fSth160488 &rootDSE, 579e1dd0a2fSth160488 &error, 580e1dd0a2fSth160488 SA_ALLOW_FALLBACK) != NS_LDAP_SUCCESS) { 5817c478bd9Sstevel@tonic-gate (void) mutex_lock(&serverInfo->mutex[1]); 582e1dd0a2fSth160488 serverInfo->sinfo[1].server_status = INFO_SERVER_ERROR; 583e1dd0a2fSth160488 serverInfo->sinfo[1].info_status = INFO_STATUS_ERROR; 584*e0a5e15fSMilan Jurik if (error && error->message) { 585e1dd0a2fSth160488 serverInfo->sinfo[1].errormsg = strdup(error->message); 586*e0a5e15fSMilan Jurik } else { 587*e0a5e15fSMilan Jurik (void) snprintf(errmsg, sizeof (errmsg), "%s %s " 588*e0a5e15fSMilan Jurik "(rc = %d)", gettext("Can not get the root DSE from" 589*e0a5e15fSMilan Jurik " server"), serverInfo->sinfo[1].addr, rc); 590*e0a5e15fSMilan Jurik serverInfo->sinfo[1].errormsg = strdup(errmsg); 591*e0a5e15fSMilan Jurik } 592e1dd0a2fSth160488 593e1dd0a2fSth160488 if (error != NULL) { 594e1dd0a2fSth160488 (void) __ns_ldap_freeError(&error); 595e1dd0a2fSth160488 } 596e1dd0a2fSth160488 597e1dd0a2fSth160488 if (current_admin.debug_level >= DBG_ALL) { 598e1dd0a2fSth160488 logit("getldap_get_rootDSE: %s.\n", 599e1dd0a2fSth160488 serverInfo->sinfo[1].errormsg); 600e1dd0a2fSth160488 } 6017c478bd9Sstevel@tonic-gate (void) mutex_unlock(&serverInfo->mutex[1]); 6027c478bd9Sstevel@tonic-gate /* 6037c478bd9Sstevel@tonic-gate * sync sinfo copies in the serverInfo. 6047c478bd9Sstevel@tonic-gate * protected by mutex 6057c478bd9Sstevel@tonic-gate */ 6067c478bd9Sstevel@tonic-gate sync_current_with_update_copy(serverInfo); 6077c478bd9Sstevel@tonic-gate thr_exit((void *) -1); 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate (void) mutex_lock(&serverInfo->mutex[1]); 611e1dd0a2fSth160488 6127c478bd9Sstevel@tonic-gate /* assume writeable, i.e., can do modify */ 6137c478bd9Sstevel@tonic-gate serverInfo->sinfo[1].type = INFO_RW_WRITEABLE; 614e1dd0a2fSth160488 serverInfo->sinfo[1].server_status = INFO_SERVER_UP; 6157c478bd9Sstevel@tonic-gate serverInfo->sinfo[1].info_status = INFO_STATUS_NEW; 6167c478bd9Sstevel@tonic-gate /* remove the last DOORLINESEP */ 6177c478bd9Sstevel@tonic-gate *(rootDSE+strlen(rootDSE)-1) = '\0'; 6187c478bd9Sstevel@tonic-gate serverInfo->sinfo[1].rootDSE_data = rootDSE; 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate server_found = 1; 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate (void) mutex_unlock(&serverInfo->mutex[1]); 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate /* 6257c478bd9Sstevel@tonic-gate * sync sinfo copies in the serverInfo. 6267c478bd9Sstevel@tonic-gate * protected by mutex 6277c478bd9Sstevel@tonic-gate */ 6287c478bd9Sstevel@tonic-gate sync_current_with_update_copy(serverInfo); 6297c478bd9Sstevel@tonic-gate /* 6307c478bd9Sstevel@tonic-gate * signal that the ldap_cachemgr parent process 6317c478bd9Sstevel@tonic-gate * should exit now, if it is still waiting 6327c478bd9Sstevel@tonic-gate */ 6337c478bd9Sstevel@tonic-gate (void) mutex_lock(&sig_mutex); 6347c478bd9Sstevel@tonic-gate if (signal_done == FALSE && server_found) { 6357c478bd9Sstevel@tonic-gate ppid = getppid(); 6367c478bd9Sstevel@tonic-gate (void) kill(ppid, SIGUSR1); 6377c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 6387c478bd9Sstevel@tonic-gate logit("getldap_get_rootDSE(): " 6397c478bd9Sstevel@tonic-gate "SIGUSR1 signal sent to " 6407c478bd9Sstevel@tonic-gate "parent process(%ld).\n", ppid); 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate signal_done = TRUE; 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate (void) mutex_unlock(&sig_mutex); 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate thr_exit((void *) exitrc); 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate return ((void *) NULL); 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate static int 6527c478bd9Sstevel@tonic-gate getldap_init_serverInfo(server_info_t **head) 6537c478bd9Sstevel@tonic-gate { 6547c478bd9Sstevel@tonic-gate char **servers = NULL; 6557c478bd9Sstevel@tonic-gate int rc = 0, i, exitrc = NS_LDAP_SUCCESS; 6567c478bd9Sstevel@tonic-gate ns_ldap_error_t *errorp = NULL; 6577c478bd9Sstevel@tonic-gate server_info_t *info, *tail = NULL; 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate *head = NULL; 6607c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 6617c478bd9Sstevel@tonic-gate logit("getldap_init_serverInfo()...\n"); 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate rc = __s_api_getServers(&servers, &errorp); 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) { 6667c478bd9Sstevel@tonic-gate logit("getldap_init_serverInfo: " 6677c478bd9Sstevel@tonic-gate "__s_api_getServers failed.\n"); 6687c478bd9Sstevel@tonic-gate if (errorp) 6697c478bd9Sstevel@tonic-gate __ns_ldap_freeError(&errorp); 6707c478bd9Sstevel@tonic-gate return (-1); 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate for (i = 0; servers[i] != NULL; i++) { 6737c478bd9Sstevel@tonic-gate info = (server_info_t *)calloc(1, sizeof (server_info_t)); 6747c478bd9Sstevel@tonic-gate if (info == NULL) { 6757c478bd9Sstevel@tonic-gate logit("getldap_init_serverInfo: " 6767c478bd9Sstevel@tonic-gate "not enough memory.\n"); 6777c478bd9Sstevel@tonic-gate exitrc = NS_LDAP_MEMORY; 6787c478bd9Sstevel@tonic-gate break; 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate if (i == 0) { 6817c478bd9Sstevel@tonic-gate *head = info; 6827c478bd9Sstevel@tonic-gate tail = info; 6837c478bd9Sstevel@tonic-gate } else { 6847c478bd9Sstevel@tonic-gate tail->next = info; 6857c478bd9Sstevel@tonic-gate tail = info; 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate info->sinfo[0].addr = strdup(servers[i]); 6897c478bd9Sstevel@tonic-gate if (info->sinfo[0].addr == NULL) { 6907c478bd9Sstevel@tonic-gate logit("getldap_init_serverInfo: " 6917c478bd9Sstevel@tonic-gate "not enough memory.\n"); 6927c478bd9Sstevel@tonic-gate exitrc = NS_LDAP_MEMORY; 6937c478bd9Sstevel@tonic-gate break; 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate info->sinfo[1].addr = strdup(servers[i]); 6967c478bd9Sstevel@tonic-gate if (info->sinfo[1].addr == NULL) { 6977c478bd9Sstevel@tonic-gate logit("getldap_init_serverInfo: " 6987c478bd9Sstevel@tonic-gate "not enough memory.\n"); 6997c478bd9Sstevel@tonic-gate exitrc = NS_LDAP_MEMORY; 7007c478bd9Sstevel@tonic-gate break; 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate info->sinfo[0].type = INFO_RW_UNKNOWN; 7047c478bd9Sstevel@tonic-gate info->sinfo[1].type = INFO_RW_UNKNOWN; 7057c478bd9Sstevel@tonic-gate info->sinfo[0].info_status = INFO_STATUS_UNKNOWN; 7067c478bd9Sstevel@tonic-gate info->sinfo[1].info_status = INFO_STATUS_UNKNOWN; 7077c478bd9Sstevel@tonic-gate info->sinfo[0].server_status = INFO_SERVER_UNKNOWN; 7087c478bd9Sstevel@tonic-gate info->sinfo[1].server_status = INFO_SERVER_UNKNOWN; 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate /* 7117c478bd9Sstevel@tonic-gate * Assume at startup or after the configuration 7127c478bd9Sstevel@tonic-gate * profile is refreshed, all servers are good. 7137c478bd9Sstevel@tonic-gate */ 7147c478bd9Sstevel@tonic-gate info->sinfo[0].prev_server_status = 7157c478bd9Sstevel@tonic-gate INFO_SERVER_UP; 7167c478bd9Sstevel@tonic-gate info->sinfo[1].prev_server_status = 7177c478bd9Sstevel@tonic-gate INFO_SERVER_UP; 718cb5caa98Sdjl info->sinfo[0].hostname = NULL; 719cb5caa98Sdjl info->sinfo[1].hostname = NULL; 7207c478bd9Sstevel@tonic-gate info->sinfo[0].rootDSE_data = NULL; 7217c478bd9Sstevel@tonic-gate info->sinfo[1].rootDSE_data = NULL; 7227c478bd9Sstevel@tonic-gate info->sinfo[0].errormsg = NULL; 7237c478bd9Sstevel@tonic-gate info->sinfo[1].errormsg = NULL; 7247c478bd9Sstevel@tonic-gate info->next = NULL; 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate __s_api_free2dArray(servers); 7277c478bd9Sstevel@tonic-gate if (exitrc != NS_LDAP_SUCCESS) { 7287c478bd9Sstevel@tonic-gate if (head && *head) { 7297c478bd9Sstevel@tonic-gate (void) getldap_destroy_serverInfo(*head); 7307c478bd9Sstevel@tonic-gate *head = NULL; 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate return (exitrc); 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate static int 7377c478bd9Sstevel@tonic-gate getldap_destroy_serverInfo(server_info_t *head) 7387c478bd9Sstevel@tonic-gate { 7397c478bd9Sstevel@tonic-gate server_info_t *info, *next; 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 7427c478bd9Sstevel@tonic-gate logit("getldap_destroy_serverInfo()...\n"); 7437c478bd9Sstevel@tonic-gate } 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate if (head == NULL) { 7467c478bd9Sstevel@tonic-gate logit("getldap_destroy_serverInfo: " 7477c478bd9Sstevel@tonic-gate "invalid serverInfo list.\n"); 7487c478bd9Sstevel@tonic-gate return (-1); 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate for (info = head; info; info = next) { 7527c478bd9Sstevel@tonic-gate if (info->sinfo[0].addr) 7537c478bd9Sstevel@tonic-gate free(info->sinfo[0].addr); 7547c478bd9Sstevel@tonic-gate if (info->sinfo[1].addr) 7557c478bd9Sstevel@tonic-gate free(info->sinfo[1].addr); 756cb5caa98Sdjl if (info->sinfo[0].hostname) 757cb5caa98Sdjl free(info->sinfo[0].hostname); 758cb5caa98Sdjl if (info->sinfo[1].hostname) 759cb5caa98Sdjl free(info->sinfo[1].hostname); 7607c478bd9Sstevel@tonic-gate if (info->sinfo[0].rootDSE_data) 7617c478bd9Sstevel@tonic-gate free(info->sinfo[0].rootDSE_data); 7627c478bd9Sstevel@tonic-gate if (info->sinfo[1].rootDSE_data) 7637c478bd9Sstevel@tonic-gate free(info->sinfo[1].rootDSE_data); 7647c478bd9Sstevel@tonic-gate if (info->sinfo[0].errormsg) 7657c478bd9Sstevel@tonic-gate free(info->sinfo[0].errormsg); 7667c478bd9Sstevel@tonic-gate if (info->sinfo[1].errormsg) 7677c478bd9Sstevel@tonic-gate free(info->sinfo[1].errormsg); 7687c478bd9Sstevel@tonic-gate next = info->next; 7697c478bd9Sstevel@tonic-gate free(info); 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate static int 775e1dd0a2fSth160488 getldap_set_serverInfo(server_info_t *head, int reset_bindtime, info_op_t op) 7767c478bd9Sstevel@tonic-gate { 7777c478bd9Sstevel@tonic-gate server_info_t *info; 7787c478bd9Sstevel@tonic-gate int atleast1 = 0; 7797c478bd9Sstevel@tonic-gate thread_t *tid; 7807c478bd9Sstevel@tonic-gate int num_threads = 0, i, j; 7817c478bd9Sstevel@tonic-gate void *status; 7827c478bd9Sstevel@tonic-gate void **paramVal = NULL; 7837c478bd9Sstevel@tonic-gate ns_ldap_error_t *error = NULL; 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 7867c478bd9Sstevel@tonic-gate logit("getldap_set_serverInfo()...\n"); 7877c478bd9Sstevel@tonic-gate } 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate if (head == NULL) { 7907c478bd9Sstevel@tonic-gate logit("getldap_set_serverInfo: " 7917c478bd9Sstevel@tonic-gate "invalid serverInfo list.\n"); 7927c478bd9Sstevel@tonic-gate return (-1); 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate /* Get the bind timeout value */ 7967c478bd9Sstevel@tonic-gate if (reset_bindtime == 1) { 7977c478bd9Sstevel@tonic-gate tcptimeout = NS_DEFAULT_BIND_TIMEOUT * 1000; 7987c478bd9Sstevel@tonic-gate (void) __ns_ldap_getParam(NS_LDAP_BIND_TIME_P, 7997c478bd9Sstevel@tonic-gate ¶mVal, &error); 8007c478bd9Sstevel@tonic-gate if (paramVal != NULL && *paramVal != NULL) { 8017c478bd9Sstevel@tonic-gate /* convert to milliseconds */ 8027c478bd9Sstevel@tonic-gate tcptimeout = **((int **)paramVal); 8037c478bd9Sstevel@tonic-gate tcptimeout *= 1000; 8047c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶mVal); 8057c478bd9Sstevel@tonic-gate } 8067c478bd9Sstevel@tonic-gate if (error) 8077c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeError(&error); 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate for (info = head; info; info = info->next) 8117c478bd9Sstevel@tonic-gate num_threads++; 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate if (num_threads == 0) { 8147c478bd9Sstevel@tonic-gate logit("getldap_set_serverInfo: " 8157c478bd9Sstevel@tonic-gate "empty serverInfo list.\n"); 8167c478bd9Sstevel@tonic-gate return (-1); 8177c478bd9Sstevel@tonic-gate } 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate tid = (thread_t *) calloc(1, sizeof (thread_t) * num_threads); 8207c478bd9Sstevel@tonic-gate if (tid == NULL) { 8217c478bd9Sstevel@tonic-gate logit("getldap_set_serverInfo: " 8227c478bd9Sstevel@tonic-gate "No memory to create thread ID list.\n"); 8237c478bd9Sstevel@tonic-gate return (-1); 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate for (info = head, i = 0; info; info = info->next, i++) { 8277c478bd9Sstevel@tonic-gate if (thr_create(NULL, 0, 8287c478bd9Sstevel@tonic-gate (void *(*)(void*))getldap_get_rootDSE, 8297c478bd9Sstevel@tonic-gate (void *)info, 0, &tid[i])) { 8307c478bd9Sstevel@tonic-gate logit("getldap_set_serverInfo: " 8317c478bd9Sstevel@tonic-gate "can not create thread %d.\n", i + 1); 8327c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) 8337c478bd9Sstevel@tonic-gate (void) thr_join(tid[j], NULL, NULL); 8347c478bd9Sstevel@tonic-gate free(tid); 8357c478bd9Sstevel@tonic-gate return (-1); 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate for (i = 0; i < num_threads; i++) { 8407c478bd9Sstevel@tonic-gate if (thr_join(tid[i], NULL, &status) == 0) { 8417c478bd9Sstevel@tonic-gate if ((int)status == NS_LDAP_SUCCESS) 8427c478bd9Sstevel@tonic-gate atleast1 = 1; 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate } 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate free(tid); 8477c478bd9Sstevel@tonic-gate 848e1dd0a2fSth160488 if (op == INFO_OP_REFRESH) 849e1dd0a2fSth160488 test_server_change(head); 850e1dd0a2fSth160488 if (atleast1) { 8517c478bd9Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 852e1dd0a2fSth160488 } else 8537c478bd9Sstevel@tonic-gate return (-1); 8547c478bd9Sstevel@tonic-gate } 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate /* 8577c478bd9Sstevel@tonic-gate * getldap_get_serverInfo processes the GETLDAPSERVER door request passed 8587c478bd9Sstevel@tonic-gate * to this function from getldap_serverInfo_op(). 8597c478bd9Sstevel@tonic-gate * input: 8607c478bd9Sstevel@tonic-gate * a buffer containing an empty string (e.g., input[0]='\0';) or a string 861cb5caa98Sdjl * as the "input" in printf(input, "%s%s%s%s", req, addrtype, DOORLINESEP, 862cb5caa98Sdjl * addr); 8637c478bd9Sstevel@tonic-gate * where addr is the address of a server and 8647c478bd9Sstevel@tonic-gate * req is one of the following: 8657c478bd9Sstevel@tonic-gate * NS_CACHE_NEW: send a new server address, addr is ignored. 8667c478bd9Sstevel@tonic-gate * NS_CACHE_NORESP: send the next one, remove addr from list. 8677c478bd9Sstevel@tonic-gate * NS_CACHE_NEXT: send the next one, keep addr on list. 8687c478bd9Sstevel@tonic-gate * NS_CACHE_WRITE: send a non-replica server, if possible, if not, same 8697c478bd9Sstevel@tonic-gate * as NS_CACHE_NEXT. 870cb5caa98Sdjl * addrtype: 871cb5caa98Sdjl * NS_CACHE_ADDR_IP: return server address as is, this is default. 8724a6b6ac4Schinlong * NS_CACHE_ADDR_HOSTNAME: return both server address and its FQDN format, 8734a6b6ac4Schinlong * only self credential case requires such format. 8747c478bd9Sstevel@tonic-gate * output: 8757c478bd9Sstevel@tonic-gate * a buffer containing server info in the following format: 8764a6b6ac4Schinlong * serveraddress DOORLINESEP [ serveraddress FQDN DOORLINESEP ] 8774a6b6ac4Schinlong * [ attr=value [DOORLINESEP attr=value ]...] 8784a6b6ac4Schinlong * For example: ( here | used as DOORLINESEP for visual purposes) 8794a6b6ac4Schinlong * 1) simple bind and sasl/DIGEST-MD5 bind : 8804a6b6ac4Schinlong * 1.2.3.4|supportedControl=1.1.1.1|supportedSASLmechanisms=EXTERNAL| 8814a6b6ac4Schinlong * supportedSASLmechanisms=GSSAPI 8824a6b6ac4Schinlong * 2) sasl/GSSAPI bind (self credential): 8834a6b6ac4Schinlong * 1.2.3.4|foo.sun.com|supportedControl=1.1.1.1| 8844a6b6ac4Schinlong * supportedSASLmechanisms=EXTERNAL|supportedSASLmechanisms=GSSAPI 8857c478bd9Sstevel@tonic-gate * NOTE: caller should free this buffer when done using it 8867c478bd9Sstevel@tonic-gate */ 8877c478bd9Sstevel@tonic-gate static int 8887c478bd9Sstevel@tonic-gate getldap_get_serverInfo(server_info_t *head, char *input, 8897c478bd9Sstevel@tonic-gate char **output, int *svr_removed) 8907c478bd9Sstevel@tonic-gate { 8917c478bd9Sstevel@tonic-gate server_info_t *info = NULL; 8927c478bd9Sstevel@tonic-gate server_info_t *server = NULL; 8937c478bd9Sstevel@tonic-gate char *addr = NULL; 8947c478bd9Sstevel@tonic-gate char *req = NULL; 8957c478bd9Sstevel@tonic-gate char req_new[] = NS_CACHE_NEW; 896cb5caa98Sdjl char addr_type[] = NS_CACHE_ADDR_IP; 897e1dd0a2fSth160488 int matched = FALSE, len = 0, rc = 0; 8984a6b6ac4Schinlong char *ret_addr = NULL, *ret_addrFQDN = NULL; 899e1dd0a2fSth160488 char *new_addr = NULL; 900e1dd0a2fSth160488 pid_t pid; 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 9037c478bd9Sstevel@tonic-gate logit("getldap_get_serverInfo()...\n"); 9047c478bd9Sstevel@tonic-gate } 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate if (input == NULL || output == NULL) { 9077c478bd9Sstevel@tonic-gate logit("getldap_get_serverInfo: " 9087c478bd9Sstevel@tonic-gate "No input or output buffer.\n"); 9097c478bd9Sstevel@tonic-gate return (-1); 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gate *output = NULL; 9137c478bd9Sstevel@tonic-gate *svr_removed = FALSE; 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate if (head == NULL) { 9167c478bd9Sstevel@tonic-gate logit("getldap_get_serverInfo: " 9177c478bd9Sstevel@tonic-gate "invalid serverInfo list.\n"); 9187c478bd9Sstevel@tonic-gate return (-1); 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate /* 9217c478bd9Sstevel@tonic-gate * parse the input string to get req and addr, 9227c478bd9Sstevel@tonic-gate * if input is empty, i.e., input[0] == '\0', 9237c478bd9Sstevel@tonic-gate * treat it as an NS_CACHE_NEW request 9247c478bd9Sstevel@tonic-gate */ 9257c478bd9Sstevel@tonic-gate req = req_new; 9267c478bd9Sstevel@tonic-gate if (input[0] != '\0') { 9277c478bd9Sstevel@tonic-gate req = input; 928cb5caa98Sdjl /* Save addr type flag */ 929cb5caa98Sdjl addr_type[0] = input[1]; 9307c478bd9Sstevel@tonic-gate input[strlen(NS_CACHE_NEW)] = '\0'; 931cb5caa98Sdjl /* skip acion type flag, addr type flag and DOORLINESEP */ 932cb5caa98Sdjl addr = input + strlen(DOORLINESEP) + strlen(NS_CACHE_NEW) 933cb5caa98Sdjl + strlen(NS_CACHE_ADDR_IP); 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate /* 9367c478bd9Sstevel@tonic-gate * if NS_CACHE_NEW, 9377c478bd9Sstevel@tonic-gate * or the server info is new, 9387c478bd9Sstevel@tonic-gate * starts from the 9397c478bd9Sstevel@tonic-gate * beginning of the list 9407c478bd9Sstevel@tonic-gate */ 9417c478bd9Sstevel@tonic-gate if ((strcmp(req, NS_CACHE_NEW) == 0) || 9427c478bd9Sstevel@tonic-gate (head->sinfo[0].info_status == INFO_STATUS_NEW)) 9437c478bd9Sstevel@tonic-gate matched = TRUE; 9447c478bd9Sstevel@tonic-gate for (info = head; info; info = info->next) { 9457c478bd9Sstevel@tonic-gate /* 9467c478bd9Sstevel@tonic-gate * make sure the server info stays the same 9477c478bd9Sstevel@tonic-gate * while the data is being processed 9487c478bd9Sstevel@tonic-gate */ 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate /* 9517c478bd9Sstevel@tonic-gate * This function is called to get server info list 9527c478bd9Sstevel@tonic-gate * and pass it back to door call clients. 9537c478bd9Sstevel@tonic-gate * Access the current copy (sinfo[0]) to get such 9547c478bd9Sstevel@tonic-gate * information 9557c478bd9Sstevel@tonic-gate */ 9567c478bd9Sstevel@tonic-gate (void) mutex_lock(&info->mutex[0]); 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate if (matched == FALSE && 9597c478bd9Sstevel@tonic-gate strcmp(info->sinfo[0].addr, addr) == 0) { 9607c478bd9Sstevel@tonic-gate matched = TRUE; 9617c478bd9Sstevel@tonic-gate if (strcmp(req, NS_CACHE_NORESP) == 0) { 962e1dd0a2fSth160488 if (chg_is_called_from_nscd_or_peruser_nscd( 963e1dd0a2fSth160488 "REMOVE SERVER", &pid) == 0) { 9647c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info->mutex[0]); 965e1dd0a2fSth160488 if (current_admin.debug_level >= 966e1dd0a2fSth160488 DBG_ALL) 967e1dd0a2fSth160488 logit("Only nscd can remove " 968e1dd0a2fSth160488 "servers. pid %ld", pid); 9697c478bd9Sstevel@tonic-gate continue; 9707c478bd9Sstevel@tonic-gate } 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate /* 9737c478bd9Sstevel@tonic-gate * if the information is new, 9747c478bd9Sstevel@tonic-gate * give this server one more chance 9757c478bd9Sstevel@tonic-gate */ 9767c478bd9Sstevel@tonic-gate if (info->sinfo[0].info_status == 9777c478bd9Sstevel@tonic-gate INFO_STATUS_NEW && 9787c478bd9Sstevel@tonic-gate info->sinfo[0].server_status == 9797c478bd9Sstevel@tonic-gate INFO_SERVER_UP) { 9807c478bd9Sstevel@tonic-gate server = info; 9817c478bd9Sstevel@tonic-gate break; 9827c478bd9Sstevel@tonic-gate } else { 9837c478bd9Sstevel@tonic-gate /* 9847c478bd9Sstevel@tonic-gate * it is recommended that 9857c478bd9Sstevel@tonic-gate * before removing the 9867c478bd9Sstevel@tonic-gate * server from the list, 9877c478bd9Sstevel@tonic-gate * the server should be 9887c478bd9Sstevel@tonic-gate * contacted one more time 9897c478bd9Sstevel@tonic-gate * to make sure that it is 9907c478bd9Sstevel@tonic-gate * really unavailable. 9917c478bd9Sstevel@tonic-gate * For now, just trust the client 9927c478bd9Sstevel@tonic-gate * (i.e., the sldap library) 9937c478bd9Sstevel@tonic-gate * that it knows what it is 9947c478bd9Sstevel@tonic-gate * doing and would not try 9957c478bd9Sstevel@tonic-gate * to mess up the server 9967c478bd9Sstevel@tonic-gate * list. 9977c478bd9Sstevel@tonic-gate */ 9987c478bd9Sstevel@tonic-gate /* 999e1dd0a2fSth160488 * Make a copy of addr to contact 1000e1dd0a2fSth160488 * it later. It's not doing it here 1001e1dd0a2fSth160488 * to avoid long wait and possible 1002e1dd0a2fSth160488 * recursion to contact an LDAP server. 10037c478bd9Sstevel@tonic-gate */ 1004e1dd0a2fSth160488 new_addr = strdup(info->sinfo[0].addr); 1005e1dd0a2fSth160488 if (new_addr) 1006e1dd0a2fSth160488 remove_server(new_addr); 10077c478bd9Sstevel@tonic-gate *svr_removed = TRUE; 10087c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info->mutex[0]); 1009e1dd0a2fSth160488 break; 10107c478bd9Sstevel@tonic-gate } 10117c478bd9Sstevel@tonic-gate } else { 10127c478bd9Sstevel@tonic-gate /* 10137c478bd9Sstevel@tonic-gate * req == NS_CACHE_NEXT or NS_CACHE_WRITE 10147c478bd9Sstevel@tonic-gate */ 10157c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info->mutex[0]); 10167c478bd9Sstevel@tonic-gate continue; 10177c478bd9Sstevel@tonic-gate } 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate if (matched) { 10217c478bd9Sstevel@tonic-gate if (strcmp(req, NS_CACHE_WRITE) == 0) { 10227c478bd9Sstevel@tonic-gate if (info->sinfo[0].type == 10237c478bd9Sstevel@tonic-gate INFO_RW_WRITEABLE && 10247c478bd9Sstevel@tonic-gate info->sinfo[0].server_status == 10257c478bd9Sstevel@tonic-gate INFO_SERVER_UP) { 10267c478bd9Sstevel@tonic-gate server = info; 10277c478bd9Sstevel@tonic-gate break; 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate } else if (info->sinfo[0].server_status == 10307c478bd9Sstevel@tonic-gate INFO_SERVER_UP) { 10317c478bd9Sstevel@tonic-gate server = info; 10327c478bd9Sstevel@tonic-gate break; 10337c478bd9Sstevel@tonic-gate } 10347c478bd9Sstevel@tonic-gate } 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info->mutex[0]); 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate if (server) { 1040cb5caa98Sdjl if (strcmp(addr_type, NS_CACHE_ADDR_HOSTNAME) == 0) { 1041cb5caa98Sdjl /* 1042cb5caa98Sdjl * In SASL/GSSAPI case, a hostname is required for 1043cb5caa98Sdjl * Kerberos's service principal. 1044cb5caa98Sdjl * e.g. 1045cb5caa98Sdjl * ldap/foo.sun.com@SUN.COM 1046cb5caa98Sdjl */ 1047cb5caa98Sdjl if (server->sinfo[0].hostname == NULL) { 1048e1dd0a2fSth160488 rc = __s_api_ip2hostname(server->sinfo[0].addr, 1049cb5caa98Sdjl &server->sinfo[0].hostname); 1050cb5caa98Sdjl if (rc != NS_LDAP_SUCCESS) { 1051cb5caa98Sdjl (void) mutex_unlock(&info->mutex[0]); 1052cb5caa98Sdjl return (rc); 1053cb5caa98Sdjl } 1054cb5caa98Sdjl if (current_admin.debug_level >= DBG_ALL) { 1055cb5caa98Sdjl logit("getldap_get_serverInfo: " 1056cb5caa98Sdjl "%s is converted to %s\n", 1057cb5caa98Sdjl server->sinfo[0].addr, 1058cb5caa98Sdjl server->sinfo[0].hostname); 1059cb5caa98Sdjl } 1060cb5caa98Sdjl } 10614a6b6ac4Schinlong ret_addr = server->sinfo[0].addr; 10624a6b6ac4Schinlong ret_addrFQDN = server->sinfo[0].hostname; 1063cb5caa98Sdjl 1064cb5caa98Sdjl } else 1065cb5caa98Sdjl ret_addr = server->sinfo[0].addr; 1066cb5caa98Sdjl 1067cb5caa98Sdjl 1068cb5caa98Sdjl len = strlen(ret_addr) + 10697c478bd9Sstevel@tonic-gate strlen(server->sinfo[0].rootDSE_data) + 10707c478bd9Sstevel@tonic-gate strlen(DOORLINESEP) + 1; 10714a6b6ac4Schinlong if (ret_addrFQDN != NULL) 10724a6b6ac4Schinlong len += strlen(ret_addrFQDN) + strlen(DOORLINESEP); 10737c478bd9Sstevel@tonic-gate *output = (char *)malloc(len); 10747c478bd9Sstevel@tonic-gate if (*output == NULL) { 10757c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info->mutex[0]); 10767c478bd9Sstevel@tonic-gate return (NS_LDAP_MEMORY); 10777c478bd9Sstevel@tonic-gate } 10784a6b6ac4Schinlong if (ret_addrFQDN == NULL) 10797c478bd9Sstevel@tonic-gate (void) snprintf(*output, len, "%s%s%s", 1080cb5caa98Sdjl ret_addr, DOORLINESEP, 10817c478bd9Sstevel@tonic-gate server->sinfo[0].rootDSE_data); 10824a6b6ac4Schinlong else 10834a6b6ac4Schinlong (void) snprintf(*output, len, "%s%s%s%s%s", 10844a6b6ac4Schinlong ret_addr, DOORLINESEP, 10854a6b6ac4Schinlong ret_addrFQDN, DOORLINESEP, 10864a6b6ac4Schinlong server->sinfo[0].rootDSE_data); 10877c478bd9Sstevel@tonic-gate server->sinfo[0].info_status = INFO_STATUS_OLD; 10887c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info->mutex[0]); 10897c478bd9Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate else 10927c478bd9Sstevel@tonic-gate return (-99); 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate /* 10967c478bd9Sstevel@tonic-gate * Format previous and next refresh time 10977c478bd9Sstevel@tonic-gate */ 10987c478bd9Sstevel@tonic-gate static int 10997c478bd9Sstevel@tonic-gate getldap_format_refresh_time(char **output, time_t *prev, time_t *next) 11007c478bd9Sstevel@tonic-gate { 11017c478bd9Sstevel@tonic-gate #define TIME_FORMAT "%Y/%m/%d %H:%M:%S" 11027c478bd9Sstevel@tonic-gate #define TIME_HEADER1 " Previous refresh time: " 11037c478bd9Sstevel@tonic-gate #define TIME_HEADER2 " Next refresh time: " 11047c478bd9Sstevel@tonic-gate int hdr1_len = strlen(gettext(TIME_HEADER1)); 11057c478bd9Sstevel@tonic-gate int hdr2_len = strlen(gettext(TIME_HEADER2)); 11067c478bd9Sstevel@tonic-gate struct tm tm; 11077c478bd9Sstevel@tonic-gate char nbuf[256]; 11087c478bd9Sstevel@tonic-gate char pbuf[256]; 11097c478bd9Sstevel@tonic-gate int len; 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 11127c478bd9Sstevel@tonic-gate logit("getldap_format_refresh_time()...\n"); 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate *output = NULL; 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate /* format the time of previous refresh */ 11187c478bd9Sstevel@tonic-gate if (*prev != 0) { 11197c478bd9Sstevel@tonic-gate (void) localtime_r(prev, &tm); 11207c478bd9Sstevel@tonic-gate (void) strftime(pbuf, sizeof (pbuf) - 1, TIME_FORMAT, &tm); 11217c478bd9Sstevel@tonic-gate } else { 11227c478bd9Sstevel@tonic-gate (void) strcpy(pbuf, gettext("NOT DONE")); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate /* format the time of next refresh */ 11267c478bd9Sstevel@tonic-gate if (*next != 0) { 11277c478bd9Sstevel@tonic-gate (void) localtime_r(next, &tm); 11287c478bd9Sstevel@tonic-gate (void) strftime(nbuf, sizeof (nbuf) - 1, TIME_FORMAT, &tm); 11297c478bd9Sstevel@tonic-gate } else { 11307c478bd9Sstevel@tonic-gate (void) strcpy(nbuf, gettext("NOT SET")); 11317c478bd9Sstevel@tonic-gate } 11327c478bd9Sstevel@tonic-gate 11337c478bd9Sstevel@tonic-gate len = hdr1_len + hdr2_len + strlen(nbuf) + 11347c478bd9Sstevel@tonic-gate strlen(pbuf) + 2 * strlen(DOORLINESEP) + 1; 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate *output = malloc(len); 11377c478bd9Sstevel@tonic-gate if (*output == NULL) 11387c478bd9Sstevel@tonic-gate return (-1); 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate (void) snprintf(*output, len, "%s%s%s%s%s%s", 11417c478bd9Sstevel@tonic-gate gettext(TIME_HEADER1), pbuf, DOORLINESEP, 11427c478bd9Sstevel@tonic-gate gettext(TIME_HEADER2), nbuf, DOORLINESEP); 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate /* 11487c478bd9Sstevel@tonic-gate * getldap_get_server_stat processes the GETSTAT request passed 11497c478bd9Sstevel@tonic-gate * to this function from getldap_serverInfo_op(). 11507c478bd9Sstevel@tonic-gate * output: 11517c478bd9Sstevel@tonic-gate * a buffer containing info for all the servers. 11527c478bd9Sstevel@tonic-gate * For each server, the data is in the following format: 11537c478bd9Sstevel@tonic-gate * server: server address or name, status: unknown|up|down|removed DOORLINESEP 11547c478bd9Sstevel@tonic-gate * for example: ( here | used as DOORLINESEP for visual purposes) 11557c478bd9Sstevel@tonic-gate * server: 1.2.3.4, status: down|server: 2.2.2.2, status: up| 11567c478bd9Sstevel@tonic-gate * NOTE: caller should free this buffer when done using it 11577c478bd9Sstevel@tonic-gate */ 11587c478bd9Sstevel@tonic-gate static int 11597c478bd9Sstevel@tonic-gate getldap_get_server_stat(server_info_t *head, char **output, 11607c478bd9Sstevel@tonic-gate time_t *prev, time_t *next) 11617c478bd9Sstevel@tonic-gate { 11627c478bd9Sstevel@tonic-gate #define S_HEADER "Server information: " 11637c478bd9Sstevel@tonic-gate #define S_FORMAT " server: %s, status: %s%s" 11647c478bd9Sstevel@tonic-gate #define S_ERROR " error message: %s%s" 11657c478bd9Sstevel@tonic-gate server_info_t *info = NULL; 11667c478bd9Sstevel@tonic-gate int header_len = strlen(gettext(S_HEADER)); 11677c478bd9Sstevel@tonic-gate int format_len = strlen(gettext(S_FORMAT)); 11687c478bd9Sstevel@tonic-gate int error_len = strlen(gettext(S_ERROR)); 11697c478bd9Sstevel@tonic-gate int len = header_len + strlen(DOORLINESEP); 11707c478bd9Sstevel@tonic-gate int len1 = 0; 11717c478bd9Sstevel@tonic-gate char *status, *output1 = NULL, *tmpptr; 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate *output = NULL; 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 11767c478bd9Sstevel@tonic-gate logit("getldap_get_server_stat()...\n"); 11777c478bd9Sstevel@tonic-gate } 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate if (head == NULL) { 11807c478bd9Sstevel@tonic-gate logit("getldap_get_server_stat: " 11817c478bd9Sstevel@tonic-gate "invalid serverInfo list.\n"); 11827c478bd9Sstevel@tonic-gate return (-1); 11837c478bd9Sstevel@tonic-gate } 11847c478bd9Sstevel@tonic-gate 11857c478bd9Sstevel@tonic-gate /* format previous and next refresh time */ 11867c478bd9Sstevel@tonic-gate (void) getldap_format_refresh_time(&output1, prev, next); 11877c478bd9Sstevel@tonic-gate if (output1 == NULL) 11887c478bd9Sstevel@tonic-gate return (-1); 11897c478bd9Sstevel@tonic-gate len += strlen(output1); 11907c478bd9Sstevel@tonic-gate len1 = len + strlen(DOORLINESEP) + 1; 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate *output = (char *)calloc(1, len1); 11937c478bd9Sstevel@tonic-gate if (*output == NULL) { 11947c478bd9Sstevel@tonic-gate free(output1); 11957c478bd9Sstevel@tonic-gate return (-1); 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate /* insert header string and refresh time info */ 11997c478bd9Sstevel@tonic-gate (void) snprintf(*output, len1, "%s%s%s", 12007c478bd9Sstevel@tonic-gate gettext(S_HEADER), DOORLINESEP, output1); 12017c478bd9Sstevel@tonic-gate 12027c478bd9Sstevel@tonic-gate for (info = head; info; info = info->next) { 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate /* 12057c478bd9Sstevel@tonic-gate * make sure the server info stays the same 12067c478bd9Sstevel@tonic-gate * while the data is being processed 12077c478bd9Sstevel@tonic-gate */ 12087c478bd9Sstevel@tonic-gate (void) mutex_lock(&info->mutex[1]); 12097c478bd9Sstevel@tonic-gate 12107c478bd9Sstevel@tonic-gate /* 12117c478bd9Sstevel@tonic-gate * When the updating process is under way(getldap_get_rootDSE) 12127c478bd9Sstevel@tonic-gate * the update copy(sinfo[1] is the latest copy. 12137c478bd9Sstevel@tonic-gate * When the updating process 12147c478bd9Sstevel@tonic-gate * is done, the current copy (sinfo[0]) has the latest status, 12157c478bd9Sstevel@tonic-gate * which is still identical to the update copy. 12167c478bd9Sstevel@tonic-gate * So update copy has the latest status. 12177c478bd9Sstevel@tonic-gate * Use the update copy(sinfo[1]) to show status 12187c478bd9Sstevel@tonic-gate * (ldap_cachemgr -g). 12197c478bd9Sstevel@tonic-gate * 12207c478bd9Sstevel@tonic-gate */ 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate switch (info->sinfo[1].server_status) { 12237c478bd9Sstevel@tonic-gate case INFO_SERVER_UNKNOWN: 12247c478bd9Sstevel@tonic-gate status = gettext("UNKNOWN"); 12257c478bd9Sstevel@tonic-gate break; 12267c478bd9Sstevel@tonic-gate case INFO_SERVER_CONNECTING: 12277c478bd9Sstevel@tonic-gate status = gettext("CONNECTING"); 12287c478bd9Sstevel@tonic-gate break; 12297c478bd9Sstevel@tonic-gate case INFO_SERVER_UP: 12307c478bd9Sstevel@tonic-gate status = gettext("UP"); 12317c478bd9Sstevel@tonic-gate break; 12327c478bd9Sstevel@tonic-gate case INFO_SERVER_ERROR: 12337c478bd9Sstevel@tonic-gate status = gettext("ERROR"); 12347c478bd9Sstevel@tonic-gate break; 12357c478bd9Sstevel@tonic-gate case INFO_SERVER_REMOVED: 12367c478bd9Sstevel@tonic-gate status = gettext("REMOVED"); 12377c478bd9Sstevel@tonic-gate break; 12387c478bd9Sstevel@tonic-gate } 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate len += format_len + strlen(status) + 12417c478bd9Sstevel@tonic-gate strlen(info->sinfo[1].addr) + 12427c478bd9Sstevel@tonic-gate strlen(DOORLINESEP); 12437c478bd9Sstevel@tonic-gate if (info->sinfo[1].errormsg != NULL) 12447c478bd9Sstevel@tonic-gate len += error_len + 12457c478bd9Sstevel@tonic-gate strlen(info->sinfo[1].errormsg) + 12467c478bd9Sstevel@tonic-gate strlen(DOORLINESEP); 12477c478bd9Sstevel@tonic-gate 12487c478bd9Sstevel@tonic-gate tmpptr = (char *)realloc(*output, len); 12497c478bd9Sstevel@tonic-gate if (tmpptr == NULL) { 12507c478bd9Sstevel@tonic-gate free(output1); 12517c478bd9Sstevel@tonic-gate free(*output); 12527c478bd9Sstevel@tonic-gate *output = NULL; 12537c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info->mutex[1]); 12547c478bd9Sstevel@tonic-gate return (-1); 12557c478bd9Sstevel@tonic-gate } else 12567c478bd9Sstevel@tonic-gate *output = tmpptr; 12577c478bd9Sstevel@tonic-gate 12587c478bd9Sstevel@tonic-gate /* insert server IP addr or name and status */ 12597c478bd9Sstevel@tonic-gate len1 = len - strlen(*output); 12607c478bd9Sstevel@tonic-gate (void) snprintf(*output + strlen(*output), len1, 12617c478bd9Sstevel@tonic-gate gettext(S_FORMAT), info->sinfo[1].addr, 12627c478bd9Sstevel@tonic-gate status, DOORLINESEP); 12637c478bd9Sstevel@tonic-gate /* insert error message if any */ 12647c478bd9Sstevel@tonic-gate len1 = len - strlen(*output); 12657c478bd9Sstevel@tonic-gate if (info->sinfo[1].errormsg != NULL) 12667c478bd9Sstevel@tonic-gate (void) snprintf(*output + strlen(*output), len1, 12677c478bd9Sstevel@tonic-gate gettext(S_ERROR), 12687c478bd9Sstevel@tonic-gate info->sinfo[1].errormsg, 12697c478bd9Sstevel@tonic-gate DOORLINESEP); 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info->mutex[1]); 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate } 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate free(output1); 12767c478bd9Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 12777c478bd9Sstevel@tonic-gate } 12787c478bd9Sstevel@tonic-gate 12797c478bd9Sstevel@tonic-gate /* 12807c478bd9Sstevel@tonic-gate * Format and return the refresh time statistics 12817c478bd9Sstevel@tonic-gate */ 12827c478bd9Sstevel@tonic-gate static int 12837c478bd9Sstevel@tonic-gate getldap_get_refresh_stat(char **output) 12847c478bd9Sstevel@tonic-gate { 12857c478bd9Sstevel@tonic-gate #define R_HEADER0 "Configuration refresh information: " 12867c478bd9Sstevel@tonic-gate #define R_HEADER1 " Configured to NO REFRESH." 12877c478bd9Sstevel@tonic-gate int hdr0_len = strlen(gettext(R_HEADER0)); 12887c478bd9Sstevel@tonic-gate int hdr1_len = strlen(gettext(R_HEADER1)); 12897c478bd9Sstevel@tonic-gate int cache_ttl = -1, len = 0; 12907c478bd9Sstevel@tonic-gate time_t expire = 0; 12917c478bd9Sstevel@tonic-gate void **paramVal = NULL; 12927c478bd9Sstevel@tonic-gate ns_ldap_error_t *errorp = NULL; 12937c478bd9Sstevel@tonic-gate char *output1 = NULL; 12947c478bd9Sstevel@tonic-gate 12957c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 12967c478bd9Sstevel@tonic-gate logit("getldap_get_refresh_stat()...\n"); 12977c478bd9Sstevel@tonic-gate } 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate *output = NULL; 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate /* get configured cache TTL */ 13027c478bd9Sstevel@tonic-gate if ((__ns_ldap_getParam(NS_LDAP_CACHETTL_P, 13037c478bd9Sstevel@tonic-gate ¶mVal, &errorp) == NS_LDAP_SUCCESS) && 13047c478bd9Sstevel@tonic-gate paramVal != NULL && 13057c478bd9Sstevel@tonic-gate (char *)*paramVal != NULL) { 13067c478bd9Sstevel@tonic-gate cache_ttl = atol((char *)*paramVal); 13077c478bd9Sstevel@tonic-gate } else { 13087c478bd9Sstevel@tonic-gate if (errorp) 13097c478bd9Sstevel@tonic-gate __ns_ldap_freeError(&errorp); 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶mVal); 13127c478bd9Sstevel@tonic-gate 13137c478bd9Sstevel@tonic-gate /* cound not get cache TTL */ 13147c478bd9Sstevel@tonic-gate if (cache_ttl == -1) 13157c478bd9Sstevel@tonic-gate return (-1); 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate if (cache_ttl == 0) { 13187c478bd9Sstevel@tonic-gate len = hdr0_len + hdr1_len + 13197c478bd9Sstevel@tonic-gate 2 * strlen(DOORLINESEP) + 1; 13207c478bd9Sstevel@tonic-gate *output = malloc(len); 13217c478bd9Sstevel@tonic-gate if (*output == NULL) 13227c478bd9Sstevel@tonic-gate return (-1); 13237c478bd9Sstevel@tonic-gate (void) snprintf(*output, len, "%s%s%s%s", 13247c478bd9Sstevel@tonic-gate gettext(R_HEADER0), DOORLINESEP, 13257c478bd9Sstevel@tonic-gate gettext(R_HEADER1), DOORLINESEP); 13267c478bd9Sstevel@tonic-gate } else { 13277c478bd9Sstevel@tonic-gate 13287c478bd9Sstevel@tonic-gate /* get configuration expiration time */ 13297c478bd9Sstevel@tonic-gate if ((__ns_ldap_getParam(NS_LDAP_EXP_P, 13307c478bd9Sstevel@tonic-gate ¶mVal, &errorp) == NS_LDAP_SUCCESS) && 13317c478bd9Sstevel@tonic-gate paramVal != NULL && 13327c478bd9Sstevel@tonic-gate (char *)*paramVal != NULL) { 13337c478bd9Sstevel@tonic-gate expire = (time_t)atol((char *)*paramVal); 13347c478bd9Sstevel@tonic-gate } else { 13357c478bd9Sstevel@tonic-gate if (errorp) 13367c478bd9Sstevel@tonic-gate __ns_ldap_freeError(&errorp); 13377c478bd9Sstevel@tonic-gate } 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶mVal); 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate /* cound not get expiration time */ 13427c478bd9Sstevel@tonic-gate if (expire == -1) 13437c478bd9Sstevel@tonic-gate return (-1); 13447c478bd9Sstevel@tonic-gate 13457c478bd9Sstevel@tonic-gate /* format previous and next refresh time */ 13467c478bd9Sstevel@tonic-gate (void) getldap_format_refresh_time(&output1, 13477c478bd9Sstevel@tonic-gate &prev_refresh_time, &expire); 13487c478bd9Sstevel@tonic-gate if (output1 == NULL) 13497c478bd9Sstevel@tonic-gate return (-1); 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate len = hdr0_len + strlen(output1) + 13527c478bd9Sstevel@tonic-gate 2 * strlen(DOORLINESEP) + 1; 13537c478bd9Sstevel@tonic-gate *output = malloc(len); 13547c478bd9Sstevel@tonic-gate if (*output == NULL) { 13557c478bd9Sstevel@tonic-gate free(output1); 13567c478bd9Sstevel@tonic-gate return (-1); 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate (void) snprintf(*output, len, "%s%s%s%s", 13597c478bd9Sstevel@tonic-gate gettext(R_HEADER0), DOORLINESEP, 13607c478bd9Sstevel@tonic-gate output1, DOORLINESEP); 13617c478bd9Sstevel@tonic-gate free(output1); 13627c478bd9Sstevel@tonic-gate } 13637c478bd9Sstevel@tonic-gate 13647c478bd9Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 13657c478bd9Sstevel@tonic-gate } 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate static int 13687c478bd9Sstevel@tonic-gate getldap_get_cacheTTL() 13697c478bd9Sstevel@tonic-gate { 13707c478bd9Sstevel@tonic-gate void **paramVal = NULL; 13717c478bd9Sstevel@tonic-gate ns_ldap_error_t *error; 13727c478bd9Sstevel@tonic-gate int rc = 0, cachettl; 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate 13757c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 13767c478bd9Sstevel@tonic-gate logit("getldap_get_cacheTTL()....\n"); 13777c478bd9Sstevel@tonic-gate } 13787c478bd9Sstevel@tonic-gate 13797c478bd9Sstevel@tonic-gate if ((rc = __ns_ldap_getParam(NS_LDAP_CACHETTL_P, 13807c478bd9Sstevel@tonic-gate ¶mVal, &error)) != NS_LDAP_SUCCESS) { 13817c478bd9Sstevel@tonic-gate if (error != NULL && error->message != NULL) 13827c478bd9Sstevel@tonic-gate logit("Error: Unable to get configuration " 13837c478bd9Sstevel@tonic-gate "refresh TTL: %s\n", 13847c478bd9Sstevel@tonic-gate error->message); 13857c478bd9Sstevel@tonic-gate else { 13867c478bd9Sstevel@tonic-gate char *tmp; 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate __ns_ldap_err2str(rc, &tmp); 13897c478bd9Sstevel@tonic-gate logit("Error: Unable to get configuration " 13907c478bd9Sstevel@tonic-gate "refresh TTL: %s\n", tmp); 13917c478bd9Sstevel@tonic-gate } 13927c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶mVal); 13937c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeError(&error); 13947c478bd9Sstevel@tonic-gate return (-1); 13957c478bd9Sstevel@tonic-gate } 13967c478bd9Sstevel@tonic-gate if (paramVal == NULL || (char *)*paramVal == NULL) 13977c478bd9Sstevel@tonic-gate return (-1); 13987c478bd9Sstevel@tonic-gate cachettl = atol((char *)*paramVal); 13997c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶mVal); 14007c478bd9Sstevel@tonic-gate return (cachettl); 14017c478bd9Sstevel@tonic-gate } 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate 14047c478bd9Sstevel@tonic-gate /* 14057c478bd9Sstevel@tonic-gate * This function implements the adaptive server list refresh 14067c478bd9Sstevel@tonic-gate * algorithm used by ldap_cachemgr. The idea is to have the 14077c478bd9Sstevel@tonic-gate * refresh TTL adjust itself between maximum and minimum 14087c478bd9Sstevel@tonic-gate * values. If the server list has been walked three times 14097c478bd9Sstevel@tonic-gate * in a row without errors, the TTL will be doubled. This will 14107c478bd9Sstevel@tonic-gate * be done repeatedly until the maximum value is reached 14117c478bd9Sstevel@tonic-gate * or passed. If passed, the maximum value will be used. 14127c478bd9Sstevel@tonic-gate * If any time a server is found to be down/bad, either 14137c478bd9Sstevel@tonic-gate * after another server list walk or informed by libsldap via 14147c478bd9Sstevel@tonic-gate * the GETLDAPSERVER door calls, the TTL will be set to half 14157c478bd9Sstevel@tonic-gate * of its value, again repeatedly, but no less than the minimum 14167c478bd9Sstevel@tonic-gate * value. Also, at any time, if all the servers on the list 14177c478bd9Sstevel@tonic-gate * are found to be down/bad, the TTL will be set to minimum, 14187c478bd9Sstevel@tonic-gate * so that a "no-server" refresh loop should be entered to try 14197c478bd9Sstevel@tonic-gate * to find a good server as soon as possible. The caller 14207c478bd9Sstevel@tonic-gate * could check the no_gd_server flag for this situation. 14217c478bd9Sstevel@tonic-gate * The maximum and minimum values are initialized when the input 14227c478bd9Sstevel@tonic-gate * refresh_ttl is set to zero, this should occur during 14237c478bd9Sstevel@tonic-gate * ldap_cachemgr startup or every time the server list is 14247c478bd9Sstevel@tonic-gate * recreated after the configuration profile is refreshed 14257c478bd9Sstevel@tonic-gate * from an LDAP server. The maximum is set to the value of 14267c478bd9Sstevel@tonic-gate * the NS_LDAP_CACHETTL parameter (configuration profile 14277c478bd9Sstevel@tonic-gate * refresh TTL), but if it is zero (never refreshed) or can 14287c478bd9Sstevel@tonic-gate * not be retrieved, the maximum is set to the macro 14297c478bd9Sstevel@tonic-gate * REFRESHTTL_MAX (12 hours) defined below. The minimum is 14307c478bd9Sstevel@tonic-gate * set to REFRESHTTL_MIN, which is the TCP connection timeout 14317c478bd9Sstevel@tonic-gate * (tcptimeout) set via the LDAP API ldap_set_option() 14327c478bd9Sstevel@tonic-gate * with the new LDAP_X_OPT_CONNECT_TIMEOUT option plus 10 seconds. 14337c478bd9Sstevel@tonic-gate * This accounts for the maximum possible timeout value for an 14347c478bd9Sstevel@tonic-gate * LDAP TCP connect call.The first refresh TTL, initial value of 14357c478bd9Sstevel@tonic-gate * refresh_ttl, will be set to the smaller of the two, 14367c478bd9Sstevel@tonic-gate * REFRESHTTL_REGULAR (10 minutes) or (REFRESHTTL_MAX + REFRESHTTL_MIN)/2. 14377c478bd9Sstevel@tonic-gate * The idea is to have a low starting value and have the value 14387c478bd9Sstevel@tonic-gate * stay low if the network/server is unstable, but eventually 14397c478bd9Sstevel@tonic-gate * the value will move up to maximum and stay there if the 14407c478bd9Sstevel@tonic-gate * network/server is stable. 14417c478bd9Sstevel@tonic-gate */ 14427c478bd9Sstevel@tonic-gate static int 14437c478bd9Sstevel@tonic-gate getldap_set_refresh_ttl(server_info_t *head, int *refresh_ttl, 14447c478bd9Sstevel@tonic-gate int *no_gd_server) 14457c478bd9Sstevel@tonic-gate { 14467c478bd9Sstevel@tonic-gate #define REFRESHTTL_REGULAR 600 14477c478bd9Sstevel@tonic-gate #define REFRESHTTL_MAX 43200 14487c478bd9Sstevel@tonic-gate /* tcptimeout is in milliseconds */ 14497c478bd9Sstevel@tonic-gate #define REFRESHTTL_MIN (tcptimeout/1000) + 10 14507c478bd9Sstevel@tonic-gate #define UP_REFRESH_TTL_NUM 2 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate static mutex_t refresh_mutex; 14537c478bd9Sstevel@tonic-gate static int refresh_ttl_max = 0; 14547c478bd9Sstevel@tonic-gate static int refresh_ttl_min = 0; 14557c478bd9Sstevel@tonic-gate static int num_walked_ok = 0; 14567c478bd9Sstevel@tonic-gate int num_servers = 0; 14577c478bd9Sstevel@tonic-gate int num_good_servers = 0; 14587c478bd9Sstevel@tonic-gate int num_prev_good_servers = 0; 14597c478bd9Sstevel@tonic-gate server_info_t *info; 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate /* allow one thread at a time */ 14627c478bd9Sstevel@tonic-gate (void) mutex_lock(&refresh_mutex); 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 14657c478bd9Sstevel@tonic-gate logit("getldap_set_refresh_ttl()...\n"); 14667c478bd9Sstevel@tonic-gate } 14677c478bd9Sstevel@tonic-gate 14687c478bd9Sstevel@tonic-gate if (!head || !refresh_ttl || !no_gd_server) { 14697c478bd9Sstevel@tonic-gate logit("getldap_set_refresh_ttl: head is " 14707c478bd9Sstevel@tonic-gate "NULL or refresh_ttl is NULL or " 14717c478bd9Sstevel@tonic-gate "no_gd_server is NULL"); 14727c478bd9Sstevel@tonic-gate (void) mutex_unlock(&refresh_mutex); 14737c478bd9Sstevel@tonic-gate return (-1); 14747c478bd9Sstevel@tonic-gate } 14757c478bd9Sstevel@tonic-gate *no_gd_server = FALSE; 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate /* 14787c478bd9Sstevel@tonic-gate * init max. min. TTLs if first time through or a fresh one 14797c478bd9Sstevel@tonic-gate */ 14807c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) { 14817c478bd9Sstevel@tonic-gate logit("getldap_set_refresh_ttl:(1) refresh ttl is %d " 14827c478bd9Sstevel@tonic-gate "seconds\n", *refresh_ttl); 14837c478bd9Sstevel@tonic-gate } 14847c478bd9Sstevel@tonic-gate if (*refresh_ttl == 0) { 14857c478bd9Sstevel@tonic-gate num_walked_ok = 0; 14867c478bd9Sstevel@tonic-gate /* 14877c478bd9Sstevel@tonic-gate * init cache manager server list TTL: 14887c478bd9Sstevel@tonic-gate * 14897c478bd9Sstevel@tonic-gate * init the min. TTL to 14907c478bd9Sstevel@tonic-gate * REFRESHTTL_MIN ( 2*(TCP MSL) + 10 seconds) 14917c478bd9Sstevel@tonic-gate */ 14927c478bd9Sstevel@tonic-gate refresh_ttl_min = REFRESHTTL_MIN; 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate /* 14957c478bd9Sstevel@tonic-gate * try to set the max. TTL to 14967c478bd9Sstevel@tonic-gate * configuration refresh TTL (NS_LDAP_CACHETTL), 14977c478bd9Sstevel@tonic-gate * if error (-1), or never refreshed (0), 14987c478bd9Sstevel@tonic-gate * set it to REFRESHTTL_MAX (12 hours) 14997c478bd9Sstevel@tonic-gate */ 15007c478bd9Sstevel@tonic-gate refresh_ttl_max = getldap_get_cacheTTL(); 15017c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) { 15027c478bd9Sstevel@tonic-gate logit("getldap_set_refresh_ttl:(2) refresh ttl is %d " 15037c478bd9Sstevel@tonic-gate "seconds\n", *refresh_ttl); 15047c478bd9Sstevel@tonic-gate logit("getldap_set_refresh_ttl:(2) max ttl is %d, " 15057c478bd9Sstevel@tonic-gate "min ttl is %d seconds\n", 15067c478bd9Sstevel@tonic-gate refresh_ttl_max, refresh_ttl_min); 15077c478bd9Sstevel@tonic-gate } 15087c478bd9Sstevel@tonic-gate if (refresh_ttl_max <= 0) 15097c478bd9Sstevel@tonic-gate refresh_ttl_max = REFRESHTTL_MAX; 15107c478bd9Sstevel@tonic-gate else if (refresh_ttl_max < refresh_ttl_min) 15117c478bd9Sstevel@tonic-gate refresh_ttl_max = refresh_ttl_min; 15127c478bd9Sstevel@tonic-gate 15137c478bd9Sstevel@tonic-gate /* 15147c478bd9Sstevel@tonic-gate * init the first TTL to the smaller of the two: 15157c478bd9Sstevel@tonic-gate * REFRESHTTL_REGULAR ( 10 minutes), 15167c478bd9Sstevel@tonic-gate * (refresh_ttl_max + refresh_ttl_min)/2 15177c478bd9Sstevel@tonic-gate */ 15187c478bd9Sstevel@tonic-gate *refresh_ttl = REFRESHTTL_REGULAR; 15197c478bd9Sstevel@tonic-gate if (*refresh_ttl > (refresh_ttl_max + refresh_ttl_min) / 2) 15207c478bd9Sstevel@tonic-gate *refresh_ttl = (refresh_ttl_max + refresh_ttl_min) / 2; 15217c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) { 15227c478bd9Sstevel@tonic-gate logit("getldap_set_refresh_ttl:(3) refresh ttl is %d " 15237c478bd9Sstevel@tonic-gate "seconds\n", *refresh_ttl); 15247c478bd9Sstevel@tonic-gate logit("getldap_set_refresh_ttl:(3) max ttl is %d, " 15257c478bd9Sstevel@tonic-gate "min ttl is %d seconds\n", 15267c478bd9Sstevel@tonic-gate refresh_ttl_max, refresh_ttl_min); 15277c478bd9Sstevel@tonic-gate } 15287c478bd9Sstevel@tonic-gate } 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate /* 15317c478bd9Sstevel@tonic-gate * get the servers statistics: 15327c478bd9Sstevel@tonic-gate * number of servers on list 15337c478bd9Sstevel@tonic-gate * number of good servers on list 15347c478bd9Sstevel@tonic-gate * number of pevious good servers on list 15357c478bd9Sstevel@tonic-gate */ 15367c478bd9Sstevel@tonic-gate for (info = head; info; info = info->next) { 15377c478bd9Sstevel@tonic-gate num_servers++; 15387c478bd9Sstevel@tonic-gate (void) mutex_lock(&info->mutex[0]); 15397c478bd9Sstevel@tonic-gate if (info->sinfo[0].server_status == INFO_SERVER_UP) 15407c478bd9Sstevel@tonic-gate num_good_servers++; 15417c478bd9Sstevel@tonic-gate /* 15427c478bd9Sstevel@tonic-gate * Server's previous status could be UNKNOWN 15437c478bd9Sstevel@tonic-gate * only between the very first and second 15447c478bd9Sstevel@tonic-gate * refresh. Treat that UNKNOWN status as up 15457c478bd9Sstevel@tonic-gate */ 15467c478bd9Sstevel@tonic-gate if (info->sinfo[0].prev_server_status 15477c478bd9Sstevel@tonic-gate == INFO_SERVER_UP || 15487c478bd9Sstevel@tonic-gate info->sinfo[0].prev_server_status 15497c478bd9Sstevel@tonic-gate == INFO_SERVER_UNKNOWN) 15507c478bd9Sstevel@tonic-gate num_prev_good_servers++; 15517c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info->mutex[0]); 15527c478bd9Sstevel@tonic-gate } 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate /* 15557c478bd9Sstevel@tonic-gate * if the server list is walked three times in a row 15567c478bd9Sstevel@tonic-gate * without problems, double the refresh TTL but no more 15577c478bd9Sstevel@tonic-gate * than the max. refresh TTL 15587c478bd9Sstevel@tonic-gate */ 15597c478bd9Sstevel@tonic-gate if (num_good_servers == num_servers) { 15607c478bd9Sstevel@tonic-gate num_walked_ok++; 15617c478bd9Sstevel@tonic-gate if (num_walked_ok > UP_REFRESH_TTL_NUM) { 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate *refresh_ttl = *refresh_ttl * 2; 15647c478bd9Sstevel@tonic-gate if (*refresh_ttl > refresh_ttl_max) 15657c478bd9Sstevel@tonic-gate *refresh_ttl = refresh_ttl_max; 15667c478bd9Sstevel@tonic-gate 15677c478bd9Sstevel@tonic-gate num_walked_ok = 0; 15687c478bd9Sstevel@tonic-gate } 15697c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) { 15707c478bd9Sstevel@tonic-gate logit("getldap_set_refresh_ttl:(4) refresh ttl is %d " 15717c478bd9Sstevel@tonic-gate "seconds\n", *refresh_ttl); 15727c478bd9Sstevel@tonic-gate } 15737c478bd9Sstevel@tonic-gate } else if (num_good_servers == 0) { 15747c478bd9Sstevel@tonic-gate /* 15757c478bd9Sstevel@tonic-gate * if no good server found, 15767c478bd9Sstevel@tonic-gate * set refresh TTL to miminum 15777c478bd9Sstevel@tonic-gate */ 15787c478bd9Sstevel@tonic-gate *refresh_ttl = refresh_ttl_min; 15797c478bd9Sstevel@tonic-gate *no_gd_server = TRUE; 15807c478bd9Sstevel@tonic-gate num_walked_ok = 0; 15817c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) { 15827c478bd9Sstevel@tonic-gate logit("getldap_set_refresh_ttl:(5) refresh ttl is %d " 15837c478bd9Sstevel@tonic-gate "seconds\n", *refresh_ttl); 15847c478bd9Sstevel@tonic-gate } 15857c478bd9Sstevel@tonic-gate } else if (num_prev_good_servers > num_good_servers) { 15867c478bd9Sstevel@tonic-gate /* 15877c478bd9Sstevel@tonic-gate * if more down/bad servers found, 15887c478bd9Sstevel@tonic-gate * decrease the refresh TTL by half 15897c478bd9Sstevel@tonic-gate * but no less than the min. refresh TTL 15907c478bd9Sstevel@tonic-gate */ 15917c478bd9Sstevel@tonic-gate *refresh_ttl = *refresh_ttl / 2; 15927c478bd9Sstevel@tonic-gate if (*refresh_ttl < refresh_ttl_min) 15937c478bd9Sstevel@tonic-gate *refresh_ttl = refresh_ttl_min; 15947c478bd9Sstevel@tonic-gate num_walked_ok = 0; 15957c478bd9Sstevel@tonic-gate logit("getldap_set_refresh_ttl:(6) refresh ttl is %d " 15967c478bd9Sstevel@tonic-gate "seconds\n", *refresh_ttl); 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate } 15997c478bd9Sstevel@tonic-gate 16007c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) { 16017c478bd9Sstevel@tonic-gate logit("getldap_set_refresh_ttl:(7) refresh ttl is %d seconds\n", 16027c478bd9Sstevel@tonic-gate *refresh_ttl); 16037c478bd9Sstevel@tonic-gate } 16047c478bd9Sstevel@tonic-gate (void) mutex_unlock(&refresh_mutex); 16057c478bd9Sstevel@tonic-gate return (0); 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate 16087c478bd9Sstevel@tonic-gate static int 16097c478bd9Sstevel@tonic-gate getldap_serverInfo_op(info_op_t op, char *input, char **output) 16107c478bd9Sstevel@tonic-gate { 16117c478bd9Sstevel@tonic-gate 16127c478bd9Sstevel@tonic-gate static rwlock_t info_lock = DEFAULTRWLOCK; 16137c478bd9Sstevel@tonic-gate static rwlock_t info_lock_old = DEFAULTRWLOCK; 16147c478bd9Sstevel@tonic-gate static mutex_t info_mutex; 16157c478bd9Sstevel@tonic-gate static cond_t info_cond; 16167c478bd9Sstevel@tonic-gate static int creating = FALSE; 16177c478bd9Sstevel@tonic-gate static int refresh_ttl = 0; 16187c478bd9Sstevel@tonic-gate static int sec_to_refresh = 0; 16197c478bd9Sstevel@tonic-gate static int in_no_server_mode = FALSE; 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate static server_info_t *serverInfo = NULL; 16227c478bd9Sstevel@tonic-gate static server_info_t *serverInfo_old = NULL; 16237c478bd9Sstevel@tonic-gate server_info_t *serverInfo_1; 16247c478bd9Sstevel@tonic-gate int is_creating; 16257c478bd9Sstevel@tonic-gate int err, no_server_good = FALSE; 16267c478bd9Sstevel@tonic-gate int server_removed = FALSE; 1627e1dd0a2fSth160488 int fall_thru = FALSE; 16287c478bd9Sstevel@tonic-gate static struct timespec timeout; 16297c478bd9Sstevel@tonic-gate struct timespec new_timeout; 16307c478bd9Sstevel@tonic-gate struct timeval tp; 16317c478bd9Sstevel@tonic-gate static time_t prev_refresh = 0, next_refresh = 0; 1632e1dd0a2fSth160488 ns_server_status_t changed = 0; 16337c478bd9Sstevel@tonic-gate 16347c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 16357c478bd9Sstevel@tonic-gate logit("getldap_serverInfo_op()...\n"); 16367c478bd9Sstevel@tonic-gate } 16377c478bd9Sstevel@tonic-gate switch (op) { 16387c478bd9Sstevel@tonic-gate case INFO_OP_CREATE: 16397c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 16407c478bd9Sstevel@tonic-gate logit("operation is INFO_OP_CREATE...\n"); 16417c478bd9Sstevel@tonic-gate } 16427c478bd9Sstevel@tonic-gate 16437c478bd9Sstevel@tonic-gate /* 16447c478bd9Sstevel@tonic-gate * indicate that the server info is being 16457c478bd9Sstevel@tonic-gate * (re)created, so that the refresh thread 16467c478bd9Sstevel@tonic-gate * will not refresh the info list right 16477c478bd9Sstevel@tonic-gate * after the list got (re)created 16487c478bd9Sstevel@tonic-gate */ 16497c478bd9Sstevel@tonic-gate (void) mutex_lock(&info_mutex); 16507c478bd9Sstevel@tonic-gate is_creating = creating; 16517c478bd9Sstevel@tonic-gate creating = TRUE; 16527c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info_mutex); 16537c478bd9Sstevel@tonic-gate 16547c478bd9Sstevel@tonic-gate if (is_creating) 16557c478bd9Sstevel@tonic-gate break; 16567c478bd9Sstevel@tonic-gate /* 16577c478bd9Sstevel@tonic-gate * create an empty info list 16587c478bd9Sstevel@tonic-gate */ 16597c478bd9Sstevel@tonic-gate (void) getldap_init_serverInfo(&serverInfo_1); 16607c478bd9Sstevel@tonic-gate /* 16617c478bd9Sstevel@tonic-gate * exit if list not created 16627c478bd9Sstevel@tonic-gate */ 16637c478bd9Sstevel@tonic-gate if (serverInfo_1 == NULL) { 16647c478bd9Sstevel@tonic-gate (void) mutex_lock(&info_mutex); 16657c478bd9Sstevel@tonic-gate creating = FALSE; 16667c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info_mutex); 16677c478bd9Sstevel@tonic-gate break; 16687c478bd9Sstevel@tonic-gate } 16697c478bd9Sstevel@tonic-gate /* 16707c478bd9Sstevel@tonic-gate * make the new server info available: 16717c478bd9Sstevel@tonic-gate * use writer lock here, so that the switch 16727c478bd9Sstevel@tonic-gate * is done after all the reader locks have 16737c478bd9Sstevel@tonic-gate * been released. 16747c478bd9Sstevel@tonic-gate */ 16757c478bd9Sstevel@tonic-gate (void) rw_wrlock(&info_lock); 16767c478bd9Sstevel@tonic-gate serverInfo = serverInfo_1; 16777c478bd9Sstevel@tonic-gate /* 16787c478bd9Sstevel@tonic-gate * if this is the first time 16797c478bd9Sstevel@tonic-gate * the server list is being created, 16807c478bd9Sstevel@tonic-gate * (i.e., serverInfo_old is NULL) 16817c478bd9Sstevel@tonic-gate * make the old list same as the new 16827c478bd9Sstevel@tonic-gate * so the GETSERVER code can do its work 16837c478bd9Sstevel@tonic-gate */ 16847c478bd9Sstevel@tonic-gate if (serverInfo_old == NULL) 16857c478bd9Sstevel@tonic-gate serverInfo_old = serverInfo_1; 16867c478bd9Sstevel@tonic-gate (void) rw_unlock(&info_lock); 16877c478bd9Sstevel@tonic-gate 16887c478bd9Sstevel@tonic-gate /* 16897c478bd9Sstevel@tonic-gate * fill the new info list 16907c478bd9Sstevel@tonic-gate */ 16917c478bd9Sstevel@tonic-gate (void) rw_rdlock(&info_lock); 16927c478bd9Sstevel@tonic-gate /* reset bind time (tcptimeout) */ 1693e1dd0a2fSth160488 (void) getldap_set_serverInfo(serverInfo, 1, INFO_OP_CREATE); 16947c478bd9Sstevel@tonic-gate 16957c478bd9Sstevel@tonic-gate (void) mutex_lock(&info_mutex); 16967c478bd9Sstevel@tonic-gate /* 16977c478bd9Sstevel@tonic-gate * set cache manager server list TTL, 16987c478bd9Sstevel@tonic-gate * set refresh_ttl to zero to indicate a fresh one 16997c478bd9Sstevel@tonic-gate */ 17007c478bd9Sstevel@tonic-gate refresh_ttl = 0; 17017c478bd9Sstevel@tonic-gate (void) getldap_set_refresh_ttl(serverInfo, 17027c478bd9Sstevel@tonic-gate &refresh_ttl, &no_server_good); 17037c478bd9Sstevel@tonic-gate sec_to_refresh = refresh_ttl; 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate /* statistics: previous refresh time */ 17067c478bd9Sstevel@tonic-gate if (gettimeofday(&tp, NULL) == 0) 17077c478bd9Sstevel@tonic-gate prev_refresh = tp.tv_sec; 17087c478bd9Sstevel@tonic-gate 17097c478bd9Sstevel@tonic-gate creating = FALSE; 17107c478bd9Sstevel@tonic-gate 17117c478bd9Sstevel@tonic-gate /* 17127c478bd9Sstevel@tonic-gate * if no server found or available, 17137c478bd9Sstevel@tonic-gate * tell the server info refresh thread 17147c478bd9Sstevel@tonic-gate * to start the "no-server" refresh loop 17157c478bd9Sstevel@tonic-gate * otherwise reset the in_no_server_mode flag 17167c478bd9Sstevel@tonic-gate */ 17177c478bd9Sstevel@tonic-gate if (no_server_good) { 17187c478bd9Sstevel@tonic-gate sec_to_refresh = 0; 17197c478bd9Sstevel@tonic-gate in_no_server_mode = TRUE; 17207c478bd9Sstevel@tonic-gate } else 17217c478bd9Sstevel@tonic-gate in_no_server_mode = FALSE; 17227c478bd9Sstevel@tonic-gate /* 17237c478bd9Sstevel@tonic-gate * awake the sleeping refresh thread 17247c478bd9Sstevel@tonic-gate */ 17257c478bd9Sstevel@tonic-gate (void) cond_signal(&info_cond); 17267c478bd9Sstevel@tonic-gate 17277c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info_mutex); 17287c478bd9Sstevel@tonic-gate (void) rw_unlock(&info_lock); 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate /* 17317c478bd9Sstevel@tonic-gate * delete the old server info 17327c478bd9Sstevel@tonic-gate */ 17337c478bd9Sstevel@tonic-gate (void) rw_wrlock(&info_lock_old); 17347c478bd9Sstevel@tonic-gate if (serverInfo_old != serverInfo) 17357c478bd9Sstevel@tonic-gate (void) getldap_destroy_serverInfo(serverInfo_old); 17367c478bd9Sstevel@tonic-gate /* 17377c478bd9Sstevel@tonic-gate * serverInfo_old needs to be the same as 17387c478bd9Sstevel@tonic-gate * serverinfo now. 17397c478bd9Sstevel@tonic-gate * it will be used by GETSERVER processing. 17407c478bd9Sstevel@tonic-gate */ 17417c478bd9Sstevel@tonic-gate serverInfo_old = serverInfo; 17427c478bd9Sstevel@tonic-gate (void) rw_unlock(&info_lock_old); 17437c478bd9Sstevel@tonic-gate break; 17447c478bd9Sstevel@tonic-gate case INFO_OP_DELETE: 17457c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 17467c478bd9Sstevel@tonic-gate logit("operation is INFO_OP_DELETE...\n"); 17477c478bd9Sstevel@tonic-gate } 17487c478bd9Sstevel@tonic-gate /* 17497c478bd9Sstevel@tonic-gate * use writer lock here, so that the delete would 17507c478bd9Sstevel@tonic-gate * not start until all the reader locks have 17517c478bd9Sstevel@tonic-gate * been released. 17527c478bd9Sstevel@tonic-gate */ 17537c478bd9Sstevel@tonic-gate (void) rw_wrlock(&info_lock); 17547c478bd9Sstevel@tonic-gate if (serverInfo) 17557c478bd9Sstevel@tonic-gate (void) getldap_destroy_serverInfo(serverInfo); 17567c478bd9Sstevel@tonic-gate serverInfo = NULL; 17577c478bd9Sstevel@tonic-gate (void) rw_unlock(&info_lock); 17587c478bd9Sstevel@tonic-gate break; 17597c478bd9Sstevel@tonic-gate case INFO_OP_REFRESH: 17607c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) { 17617c478bd9Sstevel@tonic-gate logit("operation is INFO_OP_REFRESH...\n"); 17627c478bd9Sstevel@tonic-gate } 17637c478bd9Sstevel@tonic-gate /* 17647c478bd9Sstevel@tonic-gate * if server info is currently being 17657c478bd9Sstevel@tonic-gate * (re)created, do nothing 17667c478bd9Sstevel@tonic-gate */ 17677c478bd9Sstevel@tonic-gate (void) mutex_lock(&info_mutex); 17687c478bd9Sstevel@tonic-gate is_creating = creating; 17697c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info_mutex); 17707c478bd9Sstevel@tonic-gate if (is_creating) 17717c478bd9Sstevel@tonic-gate break; 17727c478bd9Sstevel@tonic-gate 17737c478bd9Sstevel@tonic-gate (void) rw_rdlock(&info_lock); 17747c478bd9Sstevel@tonic-gate if (serverInfo) { 17757c478bd9Sstevel@tonic-gate /* do not reset bind time (tcptimeout) */ 1776e1dd0a2fSth160488 (void) getldap_set_serverInfo(serverInfo, 0, 1777e1dd0a2fSth160488 INFO_OP_REFRESH); 17787c478bd9Sstevel@tonic-gate 17797c478bd9Sstevel@tonic-gate (void) mutex_lock(&info_mutex); 17807c478bd9Sstevel@tonic-gate 17817c478bd9Sstevel@tonic-gate /* statistics: previous refresh time */ 17827c478bd9Sstevel@tonic-gate if (gettimeofday(&tp, NULL) == 0) 17837c478bd9Sstevel@tonic-gate prev_refresh = tp.tv_sec; 17847c478bd9Sstevel@tonic-gate /* 17857c478bd9Sstevel@tonic-gate * set cache manager server list TTL 17867c478bd9Sstevel@tonic-gate */ 17877c478bd9Sstevel@tonic-gate (void) getldap_set_refresh_ttl(serverInfo, 17887c478bd9Sstevel@tonic-gate &refresh_ttl, &no_server_good); 17897c478bd9Sstevel@tonic-gate /* 17907c478bd9Sstevel@tonic-gate * if no good server found, 17917c478bd9Sstevel@tonic-gate * tell the server info refresh thread 17927c478bd9Sstevel@tonic-gate * to start the "no-server" refresh loop 17937c478bd9Sstevel@tonic-gate * otherwise reset the in_no_server_mode flag 17947c478bd9Sstevel@tonic-gate */ 17957c478bd9Sstevel@tonic-gate if (no_server_good) { 17967c478bd9Sstevel@tonic-gate in_no_server_mode = TRUE; 17977c478bd9Sstevel@tonic-gate sec_to_refresh = 0; 17987c478bd9Sstevel@tonic-gate } else { 17997c478bd9Sstevel@tonic-gate in_no_server_mode = FALSE; 18007c478bd9Sstevel@tonic-gate sec_to_refresh = refresh_ttl; 18017c478bd9Sstevel@tonic-gate } 18027c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= 18037c478bd9Sstevel@tonic-gate DBG_SERVER_LIST_REFRESH) { 18047c478bd9Sstevel@tonic-gate logit("getldap_serverInfo_op(" 18057c478bd9Sstevel@tonic-gate "INFO_OP_REFRESH):" 18067c478bd9Sstevel@tonic-gate " seconds refresh: %d second(s)....\n", 18077c478bd9Sstevel@tonic-gate sec_to_refresh); 18087c478bd9Sstevel@tonic-gate } 18097c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info_mutex); 18107c478bd9Sstevel@tonic-gate } 18117c478bd9Sstevel@tonic-gate (void) rw_unlock(&info_lock); 18127c478bd9Sstevel@tonic-gate 18137c478bd9Sstevel@tonic-gate break; 18147c478bd9Sstevel@tonic-gate case INFO_OP_REFRESH_WAIT: 18157c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_SERVER_LIST_REFRESH) { 18167c478bd9Sstevel@tonic-gate logit("operation is INFO_OP_REFRESH_WAIT...\n"); 18177c478bd9Sstevel@tonic-gate } 18187c478bd9Sstevel@tonic-gate (void) cond_init(&info_cond, NULL, NULL); 18197c478bd9Sstevel@tonic-gate (void) mutex_lock(&info_mutex); 18207c478bd9Sstevel@tonic-gate err = 0; 18217c478bd9Sstevel@tonic-gate while (err != ETIME) { 18227c478bd9Sstevel@tonic-gate int sleeptime; 18237c478bd9Sstevel@tonic-gate /* 18247c478bd9Sstevel@tonic-gate * if need to go into the "no-server" refresh 18257c478bd9Sstevel@tonic-gate * loop, set timout value to 18267c478bd9Sstevel@tonic-gate * REFRESH_DELAY_WHEN_NO_SERVER 18277c478bd9Sstevel@tonic-gate */ 18287c478bd9Sstevel@tonic-gate if (sec_to_refresh == 0) { 18297c478bd9Sstevel@tonic-gate sec_to_refresh = refresh_ttl; 18307c478bd9Sstevel@tonic-gate timeout.tv_sec = time(NULL) + 18317c478bd9Sstevel@tonic-gate REFRESH_DELAY_WHEN_NO_SERVER; 18327c478bd9Sstevel@tonic-gate sleeptime = REFRESH_DELAY_WHEN_NO_SERVER; 18337c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= 18347c478bd9Sstevel@tonic-gate DBG_SERVER_LIST_REFRESH) { 18357c478bd9Sstevel@tonic-gate logit("getldap_serverInfo_op(" 18367c478bd9Sstevel@tonic-gate "INFO_OP_REFRESH_WAIT):" 18377c478bd9Sstevel@tonic-gate " entering no-server " 18387c478bd9Sstevel@tonic-gate "refresh loop...\n"); 18397c478bd9Sstevel@tonic-gate } 18407c478bd9Sstevel@tonic-gate } else { 18417c478bd9Sstevel@tonic-gate timeout.tv_sec = time(NULL) + sec_to_refresh; 18427c478bd9Sstevel@tonic-gate sleeptime = sec_to_refresh; 18437c478bd9Sstevel@tonic-gate } 18447c478bd9Sstevel@tonic-gate timeout.tv_nsec = 0; 18457c478bd9Sstevel@tonic-gate 18467c478bd9Sstevel@tonic-gate /* statistics: next refresh time */ 18477c478bd9Sstevel@tonic-gate next_refresh = timeout.tv_sec; 18487c478bd9Sstevel@tonic-gate 18497c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= 18507c478bd9Sstevel@tonic-gate DBG_SERVER_LIST_REFRESH) { 18517c478bd9Sstevel@tonic-gate logit("getldap_serverInfo_op(" 18527c478bd9Sstevel@tonic-gate "INFO_OP_REFRESH_WAIT):" 18537c478bd9Sstevel@tonic-gate " about to sleep for %d second(s)...\n", 18547c478bd9Sstevel@tonic-gate sleeptime); 18557c478bd9Sstevel@tonic-gate } 18567c478bd9Sstevel@tonic-gate err = cond_timedwait(&info_cond, 18577c478bd9Sstevel@tonic-gate &info_mutex, &timeout); 18587c478bd9Sstevel@tonic-gate } 18597c478bd9Sstevel@tonic-gate (void) cond_destroy(&info_cond); 18607c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info_mutex); 18617c478bd9Sstevel@tonic-gate break; 18627c478bd9Sstevel@tonic-gate case INFO_OP_GETSERVER: 18637c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 18647c478bd9Sstevel@tonic-gate logit("operation is INFO_OP_GETSERVER...\n"); 18657c478bd9Sstevel@tonic-gate } 18667c478bd9Sstevel@tonic-gate *output = NULL; 18677c478bd9Sstevel@tonic-gate /* 18687c478bd9Sstevel@tonic-gate * GETSERVER processing always use 18697c478bd9Sstevel@tonic-gate * serverInfo_old to retrieve server infomation. 18707c478bd9Sstevel@tonic-gate * serverInfo_old is equal to serverInfo 18717c478bd9Sstevel@tonic-gate * most of the time, except when a new 18727c478bd9Sstevel@tonic-gate * server list is being created. 18737c478bd9Sstevel@tonic-gate * This is why the check for is_creating 18747c478bd9Sstevel@tonic-gate * is needed below. 18757c478bd9Sstevel@tonic-gate */ 18767c478bd9Sstevel@tonic-gate (void) rw_rdlock(&info_lock_old); 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate if (serverInfo_old == NULL) { 18797c478bd9Sstevel@tonic-gate (void) rw_unlock(&info_lock_old); 18807c478bd9Sstevel@tonic-gate break; 18817c478bd9Sstevel@tonic-gate } else 18827c478bd9Sstevel@tonic-gate (void) getldap_get_serverInfo(serverInfo_old, 18837c478bd9Sstevel@tonic-gate input, output, &server_removed); 18847c478bd9Sstevel@tonic-gate (void) rw_unlock(&info_lock_old); 18857c478bd9Sstevel@tonic-gate 18867c478bd9Sstevel@tonic-gate /* 1887e1dd0a2fSth160488 * Return here and let remove server thread do its job in 1888e1dd0a2fSth160488 * another thread. It executes INFO_OP_REMOVESERVER code later. 1889e1dd0a2fSth160488 */ 1890e1dd0a2fSth160488 if (server_removed) 1891e1dd0a2fSth160488 break; 1892e1dd0a2fSth160488 1893e1dd0a2fSth160488 fall_thru = TRUE; 1894e1dd0a2fSth160488 1895e1dd0a2fSth160488 /* FALL THROUGH */ 1896e1dd0a2fSth160488 1897e1dd0a2fSth160488 case INFO_OP_REMOVESERVER: 1898e1dd0a2fSth160488 /* 1899e1dd0a2fSth160488 * INFO_OP_GETSERVER and INFO_OP_REMOVESERVER share the 1900e1dd0a2fSth160488 * following code except (!fall thru) part. 1901e1dd0a2fSth160488 */ 1902e1dd0a2fSth160488 1903e1dd0a2fSth160488 /* 19047c478bd9Sstevel@tonic-gate * if server info is currently being 19057c478bd9Sstevel@tonic-gate * (re)created, do nothing 19067c478bd9Sstevel@tonic-gate */ 19077c478bd9Sstevel@tonic-gate 19087c478bd9Sstevel@tonic-gate (void) mutex_lock(&info_mutex); 19097c478bd9Sstevel@tonic-gate is_creating = creating; 19107c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info_mutex); 19117c478bd9Sstevel@tonic-gate if (is_creating) 19127c478bd9Sstevel@tonic-gate break; 19137c478bd9Sstevel@tonic-gate 1914e1dd0a2fSth160488 if (!fall_thru) { 1915e1dd0a2fSth160488 if (current_admin.debug_level >= DBG_ALL) 1916e1dd0a2fSth160488 logit("operation is INFO_OP_REMOVESERVER...\n"); 1917e1dd0a2fSth160488 (void) rw_rdlock(&info_lock_old); 1918e1dd0a2fSth160488 changed = set_server_status(input, serverInfo_old); 1919e1dd0a2fSth160488 (void) rw_unlock(&info_lock_old); 1920e1dd0a2fSth160488 if (changed) 1921e1dd0a2fSth160488 create_buf_and_notify(input, changed); 1922e1dd0a2fSth160488 else 1923e1dd0a2fSth160488 break; 1924e1dd0a2fSth160488 } 1925e1dd0a2fSth160488 19267c478bd9Sstevel@tonic-gate /* 19277c478bd9Sstevel@tonic-gate * set cache manager server list TTL if necessary 19287c478bd9Sstevel@tonic-gate */ 1929e1dd0a2fSth160488 if (*output == NULL || changed) { 19307c478bd9Sstevel@tonic-gate (void) rw_rdlock(&info_lock); 19317c478bd9Sstevel@tonic-gate (void) mutex_lock(&info_mutex); 19327c478bd9Sstevel@tonic-gate 19337c478bd9Sstevel@tonic-gate (void) getldap_set_refresh_ttl(serverInfo, 19347c478bd9Sstevel@tonic-gate &refresh_ttl, &no_server_good); 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate /* 19377c478bd9Sstevel@tonic-gate * if no good server found, need to go into 19387c478bd9Sstevel@tonic-gate * the "no-server" refresh loop 19397c478bd9Sstevel@tonic-gate * to find a server as soon as possible 19407c478bd9Sstevel@tonic-gate * otherwise reset the in_no_server_mode flag 19417c478bd9Sstevel@tonic-gate */ 19427c478bd9Sstevel@tonic-gate if (no_server_good) { 19437c478bd9Sstevel@tonic-gate /* 19447c478bd9Sstevel@tonic-gate * if already in no-server mode, 19457c478bd9Sstevel@tonic-gate * don't brother 19467c478bd9Sstevel@tonic-gate */ 19477c478bd9Sstevel@tonic-gate if (in_no_server_mode == FALSE) { 19487c478bd9Sstevel@tonic-gate sec_to_refresh = 0; 19497c478bd9Sstevel@tonic-gate in_no_server_mode = TRUE; 19507c478bd9Sstevel@tonic-gate (void) cond_signal(&info_cond); 19517c478bd9Sstevel@tonic-gate } 19527c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info_mutex); 19537c478bd9Sstevel@tonic-gate (void) rw_unlock(&info_lock); 19547c478bd9Sstevel@tonic-gate break; 19557c478bd9Sstevel@tonic-gate } else { 19567c478bd9Sstevel@tonic-gate in_no_server_mode = FALSE; 19577c478bd9Sstevel@tonic-gate sec_to_refresh = refresh_ttl; 19587c478bd9Sstevel@tonic-gate } 19597c478bd9Sstevel@tonic-gate /* 19607c478bd9Sstevel@tonic-gate * if the refresh thread will be timed out 19617c478bd9Sstevel@tonic-gate * longer than refresh_ttl seconds, 19627c478bd9Sstevel@tonic-gate * wake it up to make it wait on the new 19637c478bd9Sstevel@tonic-gate * time out value 19647c478bd9Sstevel@tonic-gate */ 19657c478bd9Sstevel@tonic-gate new_timeout.tv_sec = time(NULL) + refresh_ttl; 19667c478bd9Sstevel@tonic-gate if (new_timeout.tv_sec < timeout.tv_sec) 19677c478bd9Sstevel@tonic-gate (void) cond_signal(&info_cond); 19687c478bd9Sstevel@tonic-gate 19697c478bd9Sstevel@tonic-gate (void) mutex_unlock(&info_mutex); 19707c478bd9Sstevel@tonic-gate (void) rw_unlock(&info_lock); 19717c478bd9Sstevel@tonic-gate } 19727c478bd9Sstevel@tonic-gate break; 19737c478bd9Sstevel@tonic-gate case INFO_OP_GETSTAT: 19747c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 19757c478bd9Sstevel@tonic-gate logit("operation is INFO_OP_GETSTAT...\n"); 19767c478bd9Sstevel@tonic-gate } 19777c478bd9Sstevel@tonic-gate *output = NULL; 19787c478bd9Sstevel@tonic-gate (void) rw_rdlock(&info_lock); 19797c478bd9Sstevel@tonic-gate if (serverInfo) { 19807c478bd9Sstevel@tonic-gate (void) getldap_get_server_stat(serverInfo, 19817c478bd9Sstevel@tonic-gate output, &prev_refresh, &next_refresh); 19827c478bd9Sstevel@tonic-gate } 19837c478bd9Sstevel@tonic-gate (void) rw_unlock(&info_lock); 19847c478bd9Sstevel@tonic-gate break; 19857c478bd9Sstevel@tonic-gate default: 19867c478bd9Sstevel@tonic-gate logit("getldap_serverInfo_op(): " 19877c478bd9Sstevel@tonic-gate "invalid operation code (%d).\n", op); 19887c478bd9Sstevel@tonic-gate return (-1); 19897c478bd9Sstevel@tonic-gate break; 19907c478bd9Sstevel@tonic-gate } 19917c478bd9Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 19927c478bd9Sstevel@tonic-gate } 19937c478bd9Sstevel@tonic-gate 19947c478bd9Sstevel@tonic-gate void 19957c478bd9Sstevel@tonic-gate getldap_serverInfo_refresh() 19967c478bd9Sstevel@tonic-gate { 19977c478bd9Sstevel@tonic-gate int always = 1; 19987c478bd9Sstevel@tonic-gate 19997c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 20007c478bd9Sstevel@tonic-gate logit("getldap_serverInfo_refresh()...\n"); 20017c478bd9Sstevel@tonic-gate } 20027c478bd9Sstevel@tonic-gate 20037c478bd9Sstevel@tonic-gate /* create the server info list */ 20047c478bd9Sstevel@tonic-gate (void) getldap_serverInfo_op(INFO_OP_CREATE, NULL, NULL); 20057c478bd9Sstevel@tonic-gate 20067c478bd9Sstevel@tonic-gate while (always) { 20077c478bd9Sstevel@tonic-gate /* 20087c478bd9Sstevel@tonic-gate * the operation INFO_OP_REFRESH_WAIT 20097c478bd9Sstevel@tonic-gate * causes this thread to wait until 20107c478bd9Sstevel@tonic-gate * it is time to do refresh, 20117c478bd9Sstevel@tonic-gate * see getldap_serverInfo_op() for details 20127c478bd9Sstevel@tonic-gate */ 20137c478bd9Sstevel@tonic-gate (void) getldap_serverInfo_op(INFO_OP_REFRESH_WAIT, NULL, NULL); 20147c478bd9Sstevel@tonic-gate (void) getldap_serverInfo_op(INFO_OP_REFRESH, NULL, NULL); 20157c478bd9Sstevel@tonic-gate } 20167c478bd9Sstevel@tonic-gate } 20177c478bd9Sstevel@tonic-gate 20187c478bd9Sstevel@tonic-gate void 20197ddae043Siz202018 getldap_getserver(LineBuf *config_info, ldap_call_t *in) 20207c478bd9Sstevel@tonic-gate { 20217c478bd9Sstevel@tonic-gate char req[] = "0"; 20227c478bd9Sstevel@tonic-gate 20237c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 20247c478bd9Sstevel@tonic-gate logit("getldap_getserver()...\n"); 20257c478bd9Sstevel@tonic-gate } 20267c478bd9Sstevel@tonic-gate 20277ddae043Siz202018 config_info->len = 0; 20287c478bd9Sstevel@tonic-gate 20297c478bd9Sstevel@tonic-gate /* make sure the request is valid */ 20307c478bd9Sstevel@tonic-gate req[0] = (in->ldap_u.servername)[0]; 20317c478bd9Sstevel@tonic-gate if ((req[0] != '\0') && 20327c478bd9Sstevel@tonic-gate (strcmp(req, NS_CACHE_NEW) != 0) && 20337c478bd9Sstevel@tonic-gate (strcmp(req, NS_CACHE_NORESP) != 0) && 20347c478bd9Sstevel@tonic-gate (strcmp(req, NS_CACHE_NEXT) != 0) && 20357c478bd9Sstevel@tonic-gate (strcmp(req, NS_CACHE_WRITE) != 0)) { 20367c478bd9Sstevel@tonic-gate return; 20377c478bd9Sstevel@tonic-gate } 20387c478bd9Sstevel@tonic-gate 20397c478bd9Sstevel@tonic-gate (void) getldap_serverInfo_op(INFO_OP_GETSERVER, 20407ddae043Siz202018 in->ldap_u.domainname, &config_info->str); 20417c478bd9Sstevel@tonic-gate 20427ddae043Siz202018 if (config_info->str == NULL) 20437c478bd9Sstevel@tonic-gate return; 20447c478bd9Sstevel@tonic-gate 20457ddae043Siz202018 config_info->len = strlen(config_info->str) + 1; 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_PROFILE_REFRESH) { 20487c478bd9Sstevel@tonic-gate /* Log server IP */ 20497ddae043Siz202018 char *ptr, 20507ddae043Siz202018 separator; 20517ddae043Siz202018 ptr = strstr(config_info->str, DOORLINESEP); 20527c478bd9Sstevel@tonic-gate if (ptr) { 20537ddae043Siz202018 separator = *ptr; 20547c478bd9Sstevel@tonic-gate *ptr = '\0'; 20557ddae043Siz202018 logit("getldap_getserver: got server %s\n", 20567ddae043Siz202018 config_info->str); 20577ddae043Siz202018 *ptr = separator; 20587c478bd9Sstevel@tonic-gate } else 20597c478bd9Sstevel@tonic-gate logit("getldap_getserver: Missing %s." 20607c478bd9Sstevel@tonic-gate " Internal error\n", DOORLINESEP); 20617c478bd9Sstevel@tonic-gate } 20627c478bd9Sstevel@tonic-gate } 20637c478bd9Sstevel@tonic-gate 20647c478bd9Sstevel@tonic-gate void 20657ddae043Siz202018 getldap_get_cacheData(LineBuf *config_info, ldap_call_t *in) 20667c478bd9Sstevel@tonic-gate { 20677ddae043Siz202018 char *instr = NULL; 20687c478bd9Sstevel@tonic-gate int datatype = CACHE_MAP_UNKNOWN; 20697c478bd9Sstevel@tonic-gate 20707c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 20717c478bd9Sstevel@tonic-gate logit("getldap_get_cacheData()...\n"); 20727c478bd9Sstevel@tonic-gate } 20737c478bd9Sstevel@tonic-gate 20747ddae043Siz202018 config_info->len = 0; 20757ddae043Siz202018 config_info->str = NULL; 20767c478bd9Sstevel@tonic-gate 20777c478bd9Sstevel@tonic-gate /* make sure the request is valid */ 20787c478bd9Sstevel@tonic-gate if (strncmp(in->ldap_u.servername, 20797c478bd9Sstevel@tonic-gate NS_CACHE_DN2DOMAIN, strlen(NS_CACHE_DN2DOMAIN)) == 0) 20807c478bd9Sstevel@tonic-gate datatype = CACHE_MAP_DN2DOMAIN; 20817c478bd9Sstevel@tonic-gate 20827c478bd9Sstevel@tonic-gate if (datatype == CACHE_MAP_UNKNOWN) 20837c478bd9Sstevel@tonic-gate return; 20847c478bd9Sstevel@tonic-gate 20857c478bd9Sstevel@tonic-gate instr = strstr(in->ldap_u.servername, DOORLINESEP); 20867c478bd9Sstevel@tonic-gate if (instr == NULL) 20877c478bd9Sstevel@tonic-gate return; 20887c478bd9Sstevel@tonic-gate instr += strlen(DOORLINESEP); 20897c478bd9Sstevel@tonic-gate if (*instr == '\0') 20907c478bd9Sstevel@tonic-gate return; 20917c478bd9Sstevel@tonic-gate 20927c478bd9Sstevel@tonic-gate (void) getldap_cache_op(CACHE_OP_FIND, datatype, 20937ddae043Siz202018 instr, &config_info->str); 20947c478bd9Sstevel@tonic-gate 20957ddae043Siz202018 if (config_info->str != NULL) { 20967ddae043Siz202018 config_info->len = strlen(config_info->str) + 1; 20977ddae043Siz202018 } 20987c478bd9Sstevel@tonic-gate } 20997c478bd9Sstevel@tonic-gate 21007ddae043Siz202018 int 21017ddae043Siz202018 getldap_set_cacheData(ldap_call_t *in) 21027c478bd9Sstevel@tonic-gate { 21037c478bd9Sstevel@tonic-gate char *instr1 = NULL; 21047c478bd9Sstevel@tonic-gate char *instr2 = NULL; 21057c478bd9Sstevel@tonic-gate int datatype = CACHE_MAP_UNKNOWN; 21067c478bd9Sstevel@tonic-gate int rc = 0; 21077c478bd9Sstevel@tonic-gate 21087c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 21097c478bd9Sstevel@tonic-gate logit("getldap_set_cacheData()...\n"); 21107c478bd9Sstevel@tonic-gate } 21117c478bd9Sstevel@tonic-gate 21127c478bd9Sstevel@tonic-gate /* make sure the request is valid */ 21137c478bd9Sstevel@tonic-gate if (strncmp(in->ldap_u.servername, 21147c478bd9Sstevel@tonic-gate NS_CACHE_DN2DOMAIN, strlen(NS_CACHE_DN2DOMAIN)) == 0) 21157c478bd9Sstevel@tonic-gate datatype = CACHE_MAP_DN2DOMAIN; 21167c478bd9Sstevel@tonic-gate 21177c478bd9Sstevel@tonic-gate if (datatype == CACHE_MAP_UNKNOWN) 21187ddae043Siz202018 return (-1); 21197c478bd9Sstevel@tonic-gate 21207c478bd9Sstevel@tonic-gate instr1 = strstr(in->ldap_u.servername, DOORLINESEP); 21217c478bd9Sstevel@tonic-gate if (instr1 == NULL) 21227ddae043Siz202018 return (-1); 21237c478bd9Sstevel@tonic-gate *instr1 = '\0'; 21247c478bd9Sstevel@tonic-gate instr1 += strlen(DOORLINESEP); 21257c478bd9Sstevel@tonic-gate if (*instr1 == '\0') 21267ddae043Siz202018 return (-1); 21277c478bd9Sstevel@tonic-gate instr2 = strstr(instr1, DOORLINESEP); 21287c478bd9Sstevel@tonic-gate if (instr2 == NULL) 21297ddae043Siz202018 return (-1); 21307c478bd9Sstevel@tonic-gate *instr2 = '\0'; 21317c478bd9Sstevel@tonic-gate instr2 += strlen(DOORLINESEP); 21327c478bd9Sstevel@tonic-gate if (*instr2 == '\0') 21337ddae043Siz202018 return (-1); 21347c478bd9Sstevel@tonic-gate 21357c478bd9Sstevel@tonic-gate rc = getldap_cache_op(CACHE_OP_ADD, datatype, 21367c478bd9Sstevel@tonic-gate instr1, &instr2); 21377c478bd9Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) 21387ddae043Siz202018 return (-1); 21397c478bd9Sstevel@tonic-gate 21407ddae043Siz202018 return (0); 21417c478bd9Sstevel@tonic-gate } 21427c478bd9Sstevel@tonic-gate 21437c478bd9Sstevel@tonic-gate void 21447ddae043Siz202018 getldap_get_cacheStat(LineBuf *stat_info) 21457c478bd9Sstevel@tonic-gate { 21467c478bd9Sstevel@tonic-gate char *foutstr = NULL; 21477c478bd9Sstevel@tonic-gate char *soutstr = NULL; 21487c478bd9Sstevel@tonic-gate char *coutstr = NULL; 21497ddae043Siz202018 int infoSize; 21507c478bd9Sstevel@tonic-gate 21517c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 21527c478bd9Sstevel@tonic-gate logit("getldap_get_cacheStat()...\n"); 21537c478bd9Sstevel@tonic-gate } 21547c478bd9Sstevel@tonic-gate 21557ddae043Siz202018 stat_info->str = NULL; 21567ddae043Siz202018 stat_info->len = 0; 21577c478bd9Sstevel@tonic-gate 21587c478bd9Sstevel@tonic-gate /* get refersh statisitcs */ 21597c478bd9Sstevel@tonic-gate (void) getldap_get_refresh_stat(&foutstr); 21607c478bd9Sstevel@tonic-gate if (foutstr == NULL) 21617c478bd9Sstevel@tonic-gate return; 21627c478bd9Sstevel@tonic-gate 21637c478bd9Sstevel@tonic-gate /* get server statisitcs */ 21647c478bd9Sstevel@tonic-gate (void) getldap_serverInfo_op(INFO_OP_GETSTAT, NULL, &soutstr); 21657c478bd9Sstevel@tonic-gate if (soutstr == NULL) { 21667c478bd9Sstevel@tonic-gate free(foutstr); 21677c478bd9Sstevel@tonic-gate return; 21687c478bd9Sstevel@tonic-gate } 21697c478bd9Sstevel@tonic-gate /* get cache data statisitcs */ 21707c478bd9Sstevel@tonic-gate (void) getldap_cache_op(CACHE_OP_GETSTAT, NULL, NULL, &coutstr); 21717c478bd9Sstevel@tonic-gate if (coutstr == NULL) { 21727c478bd9Sstevel@tonic-gate free(foutstr); 21737c478bd9Sstevel@tonic-gate free(soutstr); 21747c478bd9Sstevel@tonic-gate return; 21757c478bd9Sstevel@tonic-gate } 21767c478bd9Sstevel@tonic-gate 21777ddae043Siz202018 infoSize = strlen(foutstr) + strlen(soutstr) + strlen(coutstr) + 3; 21787ddae043Siz202018 stat_info->str = calloc(infoSize, sizeof (char)); 21797ddae043Siz202018 if (stat_info->str != NULL) { 21807ddae043Siz202018 (void) strncpy(stat_info->str, 21817ddae043Siz202018 foutstr, 21827ddae043Siz202018 strlen(foutstr) + 1); 21837ddae043Siz202018 (void) strncat(stat_info->str, 21847ddae043Siz202018 soutstr, 21857ddae043Siz202018 strlen(soutstr) + 1); 21867ddae043Siz202018 (void) strncat(stat_info->str, 21877ddae043Siz202018 coutstr, 21887ddae043Siz202018 strlen(coutstr) + 1); 21897ddae043Siz202018 stat_info->len = infoSize; 21907ddae043Siz202018 } 21917c478bd9Sstevel@tonic-gate 21927c478bd9Sstevel@tonic-gate free(foutstr); 21937c478bd9Sstevel@tonic-gate free(soutstr); 21947c478bd9Sstevel@tonic-gate free(coutstr); 21957c478bd9Sstevel@tonic-gate } 21967c478bd9Sstevel@tonic-gate 21977c478bd9Sstevel@tonic-gate static int 21987c478bd9Sstevel@tonic-gate checkupdate(int sighup) 21997c478bd9Sstevel@tonic-gate { 22007c478bd9Sstevel@tonic-gate int value; 22017c478bd9Sstevel@tonic-gate 22027c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ldap_lock); 22037c478bd9Sstevel@tonic-gate value = sighup; 22047c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldap_lock); 22057c478bd9Sstevel@tonic-gate 22067c478bd9Sstevel@tonic-gate return (value == TRUE); 22077c478bd9Sstevel@tonic-gate } 22087c478bd9Sstevel@tonic-gate 22097c478bd9Sstevel@tonic-gate 22107c478bd9Sstevel@tonic-gate static int 2211e1dd0a2fSth160488 update_from_profile(int *change_status) 22127c478bd9Sstevel@tonic-gate { 22137c478bd9Sstevel@tonic-gate ns_ldap_result_t *result = NULL; 22147c478bd9Sstevel@tonic-gate char searchfilter[BUFSIZ]; 22157c478bd9Sstevel@tonic-gate ns_ldap_error_t *error; 22167c478bd9Sstevel@tonic-gate int rc; 22177c478bd9Sstevel@tonic-gate void **paramVal = NULL; 22187c478bd9Sstevel@tonic-gate ns_config_t *ptr = NULL; 22197c478bd9Sstevel@tonic-gate char *profile = NULL; 22207c478bd9Sstevel@tonic-gate char errstr[MAXERROR]; 22217c478bd9Sstevel@tonic-gate 22227c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 22237c478bd9Sstevel@tonic-gate logit("update_from_profile....\n"); 22247c478bd9Sstevel@tonic-gate } 22257c478bd9Sstevel@tonic-gate do { 22267c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ldap_lock); 22277c478bd9Sstevel@tonic-gate sighup_update = FALSE; 22287c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldap_lock); 22297c478bd9Sstevel@tonic-gate 22307c478bd9Sstevel@tonic-gate if ((rc = __ns_ldap_getParam(NS_LDAP_PROFILE_P, 22317c478bd9Sstevel@tonic-gate ¶mVal, &error)) != NS_LDAP_SUCCESS) { 22327c478bd9Sstevel@tonic-gate if (error != NULL && error->message != NULL) 22337c478bd9Sstevel@tonic-gate logit("Error: Unable to profile name: %s\n", 22347c478bd9Sstevel@tonic-gate error->message); 22357c478bd9Sstevel@tonic-gate else { 22367c478bd9Sstevel@tonic-gate char *tmp; 22377c478bd9Sstevel@tonic-gate 22387c478bd9Sstevel@tonic-gate __ns_ldap_err2str(rc, &tmp); 22397c478bd9Sstevel@tonic-gate logit("Error: Unable to profile name: %s\n", 22407c478bd9Sstevel@tonic-gate tmp); 22417c478bd9Sstevel@tonic-gate } 22427c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶mVal); 22437c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeError(&error); 22447c478bd9Sstevel@tonic-gate return (-1); 22457c478bd9Sstevel@tonic-gate } 22467c478bd9Sstevel@tonic-gate 22477c478bd9Sstevel@tonic-gate if (paramVal && *paramVal) 22487c478bd9Sstevel@tonic-gate profile = strdup((char *)*paramVal); 22497c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶mVal); 22507c478bd9Sstevel@tonic-gate 22517c478bd9Sstevel@tonic-gate if (profile == NULL) { 22527c478bd9Sstevel@tonic-gate return (-1); 22537c478bd9Sstevel@tonic-gate } 22547c478bd9Sstevel@tonic-gate 22557c478bd9Sstevel@tonic-gate (void) snprintf(searchfilter, BUFSIZ, _PROFILE_FILTER, 22567c478bd9Sstevel@tonic-gate _PROFILE1_OBJECTCLASS, _PROFILE2_OBJECTCLASS, profile); 22577c478bd9Sstevel@tonic-gate 22587c478bd9Sstevel@tonic-gate if ((rc = __ns_ldap_list(_PROFILE_CONTAINER, 22597c478bd9Sstevel@tonic-gate (const char *)searchfilter, NULL, 22607c478bd9Sstevel@tonic-gate NULL, NULL, 0, 22617c478bd9Sstevel@tonic-gate &result, &error, NULL, NULL)) != NS_LDAP_SUCCESS) { 22627c478bd9Sstevel@tonic-gate 22637c478bd9Sstevel@tonic-gate /* 22647c478bd9Sstevel@tonic-gate * Is profile name the DEFAULTCONFIGNAME? 22657c478bd9Sstevel@tonic-gate * syslog Warning, otherwise syslog error. 22667c478bd9Sstevel@tonic-gate */ 22677c478bd9Sstevel@tonic-gate if (strcmp(profile, DEFAULTCONFIGNAME) == 0) { 22687c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, 22697c478bd9Sstevel@tonic-gate "Ignoring attempt to refresh nonexistent " 22707c478bd9Sstevel@tonic-gate "default profile: %s.\n", 22717c478bd9Sstevel@tonic-gate profile); 22727c478bd9Sstevel@tonic-gate logit("Ignoring attempt to refresh nonexistent " 22737c478bd9Sstevel@tonic-gate "default profile: %s.\n", 22747c478bd9Sstevel@tonic-gate profile); 22757c478bd9Sstevel@tonic-gate } else if ((error != NULL) && 22767c478bd9Sstevel@tonic-gate (error->message != NULL)) { 22777c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 22787c478bd9Sstevel@tonic-gate "Error: Unable to refresh profile:%s:" 22797c478bd9Sstevel@tonic-gate " %s\n", profile, error->message); 22807c478bd9Sstevel@tonic-gate logit("Error: Unable to refresh profile:" 22817c478bd9Sstevel@tonic-gate "%s:%s\n", profile, error->message); 22827c478bd9Sstevel@tonic-gate } else { 22837c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "Error: Unable to refresh " 22847c478bd9Sstevel@tonic-gate "from profile:%s. (error=%d)\n", 22857c478bd9Sstevel@tonic-gate profile, rc); 22867c478bd9Sstevel@tonic-gate logit("Error: Unable to refresh from profile " 22877c478bd9Sstevel@tonic-gate "%s (error=%d)\n", profile, rc); 22887c478bd9Sstevel@tonic-gate } 22897c478bd9Sstevel@tonic-gate 22907c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeError(&error); 22917c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeResult(&result); 22927c478bd9Sstevel@tonic-gate free(profile); 22937c478bd9Sstevel@tonic-gate return (-1); 22947c478bd9Sstevel@tonic-gate } 22957c478bd9Sstevel@tonic-gate free(profile); 22967c478bd9Sstevel@tonic-gate 22977c478bd9Sstevel@tonic-gate 22987c478bd9Sstevel@tonic-gate } while (checkupdate(sighup_update) == TRUE); 22997c478bd9Sstevel@tonic-gate 23007c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ldap_lock); 23017c478bd9Sstevel@tonic-gate 23027c478bd9Sstevel@tonic-gate ptr = __ns_ldap_make_config(result); 23037c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeResult(&result); 23047c478bd9Sstevel@tonic-gate 23057c478bd9Sstevel@tonic-gate if (ptr == NULL) { 23067c478bd9Sstevel@tonic-gate logit("Error: __ns_ldap_make_config failed.\n"); 23077c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldap_lock); 23087c478bd9Sstevel@tonic-gate return (-1); 23097c478bd9Sstevel@tonic-gate } 23107c478bd9Sstevel@tonic-gate 23117c478bd9Sstevel@tonic-gate /* 23127c478bd9Sstevel@tonic-gate * cross check the config parameters 23137c478bd9Sstevel@tonic-gate */ 23147c478bd9Sstevel@tonic-gate if (__s_api_crosscheck(ptr, errstr, B_TRUE) == NS_SUCCESS) { 23157c478bd9Sstevel@tonic-gate /* 23167c478bd9Sstevel@tonic-gate * reset the local profile TTL 23177c478bd9Sstevel@tonic-gate */ 23187c478bd9Sstevel@tonic-gate if (ptr->paramList[NS_LDAP_CACHETTL_P].ns_pc) 23197c478bd9Sstevel@tonic-gate current_admin.ldap_stat.ldap_ttl = 23207c478bd9Sstevel@tonic-gate atol(ptr->paramList[NS_LDAP_CACHETTL_P].ns_pc); 23217c478bd9Sstevel@tonic-gate 23227c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_PROFILE_REFRESH) { 23237c478bd9Sstevel@tonic-gate logit("update_from_profile: reset profile TTL to %d" 23247c478bd9Sstevel@tonic-gate " seconds\n", 23257c478bd9Sstevel@tonic-gate current_admin.ldap_stat.ldap_ttl); 2326cb5caa98Sdjl logit("update_from_profile: expire time %ld " 23277c478bd9Sstevel@tonic-gate "seconds\n", 2328cb5caa98Sdjl ptr->paramList[NS_LDAP_EXP_P].ns_tm); 23297c478bd9Sstevel@tonic-gate } 23307c478bd9Sstevel@tonic-gate 2331e1dd0a2fSth160488 /* set ptr as current_config if the config is changed */ 2332e1dd0a2fSth160488 chg_test_config_change(ptr, change_status); 23337c478bd9Sstevel@tonic-gate rc = 0; 23347c478bd9Sstevel@tonic-gate } else { 23357c478bd9Sstevel@tonic-gate __s_api_destroy_config(ptr); 23367c478bd9Sstevel@tonic-gate logit("Error: downloaded profile failed to pass " 23377c478bd9Sstevel@tonic-gate "crosscheck (%s).\n", errstr); 23387c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "ldap_cachemgr: %s", errstr); 23397c478bd9Sstevel@tonic-gate rc = -1; 23407c478bd9Sstevel@tonic-gate } 23417c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldap_lock); 2342cb5caa98Sdjl 23437c478bd9Sstevel@tonic-gate return (rc); 23447c478bd9Sstevel@tonic-gate } 23457c478bd9Sstevel@tonic-gate 23467c478bd9Sstevel@tonic-gate int 23477c478bd9Sstevel@tonic-gate getldap_init() 23487c478bd9Sstevel@tonic-gate { 23497c478bd9Sstevel@tonic-gate ns_ldap_error_t *error; 23507c478bd9Sstevel@tonic-gate struct timeval tp; 2351e1dd0a2fSth160488 ldap_get_chg_cookie_t cookie; 23527c478bd9Sstevel@tonic-gate 23537c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 23547c478bd9Sstevel@tonic-gate logit("getldap_init()...\n"); 23557c478bd9Sstevel@tonic-gate } 23567c478bd9Sstevel@tonic-gate 23577c478bd9Sstevel@tonic-gate (void) __ns_ldap_setServer(TRUE); 23587c478bd9Sstevel@tonic-gate 23597c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ldap_lock); 23607c478bd9Sstevel@tonic-gate if ((error = __ns_ldap_LoadConfiguration()) != NULL) { 23617c478bd9Sstevel@tonic-gate logit("Error: Unable to read '%s': %s\n", 23627c478bd9Sstevel@tonic-gate NSCONFIGFILE, error->message); 23637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 23647c478bd9Sstevel@tonic-gate gettext("\nError: Unable to read '%s': %s\n"), 23657c478bd9Sstevel@tonic-gate NSCONFIGFILE, error->message); 23667c478bd9Sstevel@tonic-gate __ns_ldap_freeError(&error); 23677c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldap_lock); 23687c478bd9Sstevel@tonic-gate return (-1); 23697c478bd9Sstevel@tonic-gate } 23707c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldap_lock); 23717c478bd9Sstevel@tonic-gate 23727c478bd9Sstevel@tonic-gate if (gettimeofday(&tp, NULL) == 0) { 23737c478bd9Sstevel@tonic-gate /* statistics: previous refresh time */ 23747c478bd9Sstevel@tonic-gate prev_refresh_time = tp.tv_sec; 23757c478bd9Sstevel@tonic-gate } 23767c478bd9Sstevel@tonic-gate 23777c478bd9Sstevel@tonic-gate /* initialize the data cache */ 23787c478bd9Sstevel@tonic-gate (void) getldap_cache_op(CACHE_OP_CREATE, 23797c478bd9Sstevel@tonic-gate 0, NULL, NULL); 23807c478bd9Sstevel@tonic-gate 2381e1dd0a2fSth160488 cookie.mgr_pid = getpid(); 2382e1dd0a2fSth160488 cookie.seq_num = 0; 2383e1dd0a2fSth160488 chg_config_cookie_set(&cookie); 23847c478bd9Sstevel@tonic-gate return (0); 23857c478bd9Sstevel@tonic-gate } 23867c478bd9Sstevel@tonic-gate 23877c478bd9Sstevel@tonic-gate static void 23887c478bd9Sstevel@tonic-gate perform_update(void) 23897c478bd9Sstevel@tonic-gate { 23905f6e3a12Sjs198686 ns_ldap_error_t *error = NULL; 23917c478bd9Sstevel@tonic-gate struct timeval tp; 23927c478bd9Sstevel@tonic-gate char buf[20]; 2393cb5caa98Sdjl int rc, rc1; 2394e1dd0a2fSth160488 int changed = 0; 23955f6e3a12Sjs198686 void **paramVal = NULL; 2396cb5caa98Sdjl ns_ldap_self_gssapi_config_t config; 23977c478bd9Sstevel@tonic-gate 23987c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 23997c478bd9Sstevel@tonic-gate logit("perform_update()...\n"); 24007c478bd9Sstevel@tonic-gate } 24017c478bd9Sstevel@tonic-gate 24027c478bd9Sstevel@tonic-gate (void) __ns_ldap_setServer(TRUE); 24037c478bd9Sstevel@tonic-gate 24047c478bd9Sstevel@tonic-gate if (gettimeofday(&tp, NULL) != 0) 24057c478bd9Sstevel@tonic-gate return; 24067c478bd9Sstevel@tonic-gate 24075f6e3a12Sjs198686 rc = __ns_ldap_getParam(NS_LDAP_CACHETTL_P, ¶mVal, &error); 24085f6e3a12Sjs198686 24095f6e3a12Sjs198686 if (rc == NS_LDAP_SUCCESS && paramVal != NULL) { 24105f6e3a12Sjs198686 current_admin.ldap_stat.ldap_ttl = atol((char *)*paramVal); 24115f6e3a12Sjs198686 } 24125f6e3a12Sjs198686 24135f6e3a12Sjs198686 if (error != NULL) 24145f6e3a12Sjs198686 (void) __ns_ldap_freeError(&error); 24155f6e3a12Sjs198686 24165f6e3a12Sjs198686 if (paramVal != NULL) 24175f6e3a12Sjs198686 (void) __ns_ldap_freeParam(¶mVal); 24185f6e3a12Sjs198686 24195f6e3a12Sjs198686 if (current_admin.debug_level >= DBG_PROFILE_REFRESH) { 24205f6e3a12Sjs198686 logit("perform_update: current profile TTL is %d seconds\n", 24215f6e3a12Sjs198686 current_admin.ldap_stat.ldap_ttl); 24225f6e3a12Sjs198686 } 24235f6e3a12Sjs198686 24245f6e3a12Sjs198686 if (current_admin.ldap_stat.ldap_ttl > 0) { 24257c478bd9Sstevel@tonic-gate /* 24267c478bd9Sstevel@tonic-gate * set the profile TTL parameter, just 24277c478bd9Sstevel@tonic-gate * in case that the downloading of 24287c478bd9Sstevel@tonic-gate * the profile from server would fail 24297c478bd9Sstevel@tonic-gate */ 24305f6e3a12Sjs198686 24317c478bd9Sstevel@tonic-gate /* 24327c478bd9Sstevel@tonic-gate * NS_LDAP_EXP_P is a no op for __ns_ldap_setParam 24337c478bd9Sstevel@tonic-gate * It depends on NS_LDAP_CACHETTL_P to set it's value 24347c478bd9Sstevel@tonic-gate * Set NS_LDAP_CACHETTL_P here so NS_LDAP_EXP_P value 24357c478bd9Sstevel@tonic-gate * can be set. 24367c478bd9Sstevel@tonic-gate * NS_LDAP_CACHETTL_P value can be reset after the profile is 24377c478bd9Sstevel@tonic-gate * downloaded from the server, so is NS_LDAP_EXP_P. 24387c478bd9Sstevel@tonic-gate */ 24397c478bd9Sstevel@tonic-gate buf[19] = '\0'; /* null terminated the buffer */ 24407c478bd9Sstevel@tonic-gate if (__ns_ldap_setParam(NS_LDAP_CACHETTL_P, 24415f6e3a12Sjs198686 lltostr((long long)current_admin.ldap_stat.ldap_ttl, 24425f6e3a12Sjs198686 &buf[19]), 24437c478bd9Sstevel@tonic-gate &error) != NS_LDAP_SUCCESS) { 24447c478bd9Sstevel@tonic-gate logit("Error: __ns_ldap_setParam failed, status: %d " 24457c478bd9Sstevel@tonic-gate "message: %s\n", error->status, error->message); 2446cb5caa98Sdjl (void) __ns_ldap_freeError(&error); 24477c478bd9Sstevel@tonic-gate return; 24487c478bd9Sstevel@tonic-gate } 24497c478bd9Sstevel@tonic-gate 24507c478bd9Sstevel@tonic-gate (void) rw_wrlock(&ldap_lock); 24517c478bd9Sstevel@tonic-gate sighup_update = FALSE; 24527c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldap_lock); 24537c478bd9Sstevel@tonic-gate 24547c478bd9Sstevel@tonic-gate do { 2455e1dd0a2fSth160488 rc = update_from_profile(&changed); 24567c478bd9Sstevel@tonic-gate if (rc != 0) { 24577c478bd9Sstevel@tonic-gate logit("Error: Unable to update from profile\n"); 24587c478bd9Sstevel@tonic-gate } 24597c478bd9Sstevel@tonic-gate } while (checkupdate(sighup_update) == TRUE); 24605f6e3a12Sjs198686 } else { 24615f6e3a12Sjs198686 rc = 0; 24625f6e3a12Sjs198686 } 24637c478bd9Sstevel@tonic-gate 24647c478bd9Sstevel@tonic-gate /* 24657c478bd9Sstevel@tonic-gate * recreate the server info list 24667c478bd9Sstevel@tonic-gate */ 24677c478bd9Sstevel@tonic-gate if (rc == 0) { 24687c478bd9Sstevel@tonic-gate (void) getldap_serverInfo_op(INFO_OP_CREATE, NULL, NULL); 24697c478bd9Sstevel@tonic-gate 24707c478bd9Sstevel@tonic-gate /* flush the data cache */ 24717c478bd9Sstevel@tonic-gate (void) getldap_cache_op(CACHE_OP_DELETE, 24727c478bd9Sstevel@tonic-gate 0, NULL, NULL); 24737c478bd9Sstevel@tonic-gate 24747c478bd9Sstevel@tonic-gate /* statistics: previous refresh time */ 24757c478bd9Sstevel@tonic-gate prev_refresh_time = tp.tv_sec; 24767c478bd9Sstevel@tonic-gate } 2477cb5caa98Sdjl rc1 = __ns_ldap_self_gssapi_config(&config); 2478cb5caa98Sdjl if (rc1 == NS_LDAP_SUCCESS) { 2479cb5caa98Sdjl if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE) { 2480cb5caa98Sdjl rc1 = __ns_ldap_check_all_preq(0, 0, 0, config, &error); 2481cb5caa98Sdjl (void) __ns_ldap_freeError(&error); 2482cb5caa98Sdjl if (rc1 != NS_LDAP_SUCCESS) { 2483cb5caa98Sdjl logit("Error: Check on self credential " 2484cb5caa98Sdjl "prerquesites failed: %d\n", 2485cb5caa98Sdjl rc1); 2486cb5caa98Sdjl exit(rc1); 2487cb5caa98Sdjl } 2488cb5caa98Sdjl } 2489cb5caa98Sdjl } else { 2490cb5caa98Sdjl logit("Error: Failed to get self credential configuration %d\n", 2491cb5caa98Sdjl rc1); 2492cb5caa98Sdjl exit(rc1); 2493cb5caa98Sdjl } 24947c478bd9Sstevel@tonic-gate 2495e1dd0a2fSth160488 if (!changed) 2496e1dd0a2fSth160488 return; 2497e1dd0a2fSth160488 24987c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ldap_lock); 249982c6b8c6Smj162486 if (((error = __ns_ldap_DumpConfiguration(NSCONFIGREFRESH)) != NULL) || 250082c6b8c6Smj162486 ((error = __ns_ldap_DumpConfiguration(NSCREDREFRESH)) != NULL)) { 250182c6b8c6Smj162486 logit("Error: __ns_ldap_DumpConfiguration failed, " 250282c6b8c6Smj162486 "status: %d message: %s\n", error->status, error->message); 25037c478bd9Sstevel@tonic-gate __ns_ldap_freeError(&error); 250482c6b8c6Smj162486 (void) rw_unlock(&ldap_lock); 250582c6b8c6Smj162486 return; 25067c478bd9Sstevel@tonic-gate } 250782c6b8c6Smj162486 if (rename(NSCONFIGREFRESH, NSCONFIGFILE) != 0) { 250882c6b8c6Smj162486 logit("Error: unlink failed - errno: %s\n", strerror(errno)); 250982c6b8c6Smj162486 syslog(LOG_ERR, "Unable to refresh profile, LDAP configuration" 251082c6b8c6Smj162486 "files not written"); 251182c6b8c6Smj162486 (void) rw_unlock(&ldap_lock); 251282c6b8c6Smj162486 return; 25137c478bd9Sstevel@tonic-gate } 251482c6b8c6Smj162486 if (rename(NSCREDREFRESH, NSCREDFILE) != 0) { 251582c6b8c6Smj162486 /* 251682c6b8c6Smj162486 * We probably have inconsistent configuration at this point. 251782c6b8c6Smj162486 * If we were to create a backup file and rename it here, that 251882c6b8c6Smj162486 * operation might also fail. Consequently there is no safe way 251982c6b8c6Smj162486 * to roll back. 252082c6b8c6Smj162486 */ 252182c6b8c6Smj162486 logit("Error: unlink failed - errno: %s\n", strerror(errno)); 252282c6b8c6Smj162486 syslog(LOG_ERR, "Unable to refresh profile consistently, " 252382c6b8c6Smj162486 "LDAP configuration files inconsistent"); 252482c6b8c6Smj162486 (void) rw_unlock(&ldap_lock); 252582c6b8c6Smj162486 return; 252682c6b8c6Smj162486 } 2527cb5caa98Sdjl 25287c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldap_lock); 25297c478bd9Sstevel@tonic-gate } 25307c478bd9Sstevel@tonic-gate 25317c478bd9Sstevel@tonic-gate void 25327c478bd9Sstevel@tonic-gate getldap_refresh() 25337c478bd9Sstevel@tonic-gate { 25347c478bd9Sstevel@tonic-gate struct timespec timeout; 25357c478bd9Sstevel@tonic-gate int sleeptime; 25367c478bd9Sstevel@tonic-gate struct timeval tp; 25377c478bd9Sstevel@tonic-gate long expire = 0; 25387c478bd9Sstevel@tonic-gate void **paramVal = NULL; 25397c478bd9Sstevel@tonic-gate ns_ldap_error_t *errorp; 25407c478bd9Sstevel@tonic-gate int always = 1, err; 25417c478bd9Sstevel@tonic-gate int first_time = 1; 25427c478bd9Sstevel@tonic-gate int sig_done = 0; 25437c478bd9Sstevel@tonic-gate int dbg_level; 25447c478bd9Sstevel@tonic-gate 25457c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 25467c478bd9Sstevel@tonic-gate logit("getldap_refresh()...\n"); 25477c478bd9Sstevel@tonic-gate } 25487c478bd9Sstevel@tonic-gate 25497c478bd9Sstevel@tonic-gate /* 25507c478bd9Sstevel@tonic-gate * wait for an available server 25517c478bd9Sstevel@tonic-gate */ 25527c478bd9Sstevel@tonic-gate while (sig_done == 0) { 25537c478bd9Sstevel@tonic-gate (void) mutex_lock(&sig_mutex); 25547c478bd9Sstevel@tonic-gate sig_done = signal_done; 25557c478bd9Sstevel@tonic-gate (void) mutex_unlock(&sig_mutex); 25567c478bd9Sstevel@tonic-gate } 25577c478bd9Sstevel@tonic-gate 25587c478bd9Sstevel@tonic-gate (void) __ns_ldap_setServer(TRUE); 25597c478bd9Sstevel@tonic-gate while (always) { 25607c478bd9Sstevel@tonic-gate dbg_level = current_admin.debug_level; 25617c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ldap_lock); 25627c478bd9Sstevel@tonic-gate sleeptime = current_admin.ldap_stat.ldap_ttl; 25637c478bd9Sstevel@tonic-gate if (dbg_level >= DBG_PROFILE_REFRESH) { 25647c478bd9Sstevel@tonic-gate logit("getldap_refresh: current profile TTL is %d " 25657c478bd9Sstevel@tonic-gate "seconds\n", current_admin.ldap_stat.ldap_ttl); 25667c478bd9Sstevel@tonic-gate } 25677c478bd9Sstevel@tonic-gate if (gettimeofday(&tp, NULL) == 0) { 25687c478bd9Sstevel@tonic-gate if ((__ns_ldap_getParam(NS_LDAP_EXP_P, 25697c478bd9Sstevel@tonic-gate ¶mVal, &errorp) == NS_LDAP_SUCCESS) && 25707c478bd9Sstevel@tonic-gate paramVal != NULL && 25717c478bd9Sstevel@tonic-gate (char *)*paramVal != NULL) { 25727c478bd9Sstevel@tonic-gate errno = 0; 25737c478bd9Sstevel@tonic-gate expire = atol((char *)*paramVal); 25747c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶mVal); 25757c478bd9Sstevel@tonic-gate if (errno == 0) { 25767c478bd9Sstevel@tonic-gate if (expire == 0) { 25777c478bd9Sstevel@tonic-gate first_time = 0; 25787c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldap_lock); 25797c478bd9Sstevel@tonic-gate (void) cond_init(&cond, 25807c478bd9Sstevel@tonic-gate NULL, NULL); 25817c478bd9Sstevel@tonic-gate (void) mutex_lock(&sighuplock); 25827c478bd9Sstevel@tonic-gate timeout.tv_sec = 25837c478bd9Sstevel@tonic-gate CACHESLEEPTIME; 25847c478bd9Sstevel@tonic-gate timeout.tv_nsec = 0; 25857c478bd9Sstevel@tonic-gate if (dbg_level >= 25867c478bd9Sstevel@tonic-gate DBG_PROFILE_REFRESH) { 25877c478bd9Sstevel@tonic-gate logit("getldap_refresh:" 25884a6b6ac4Schinlong "(1)about to sleep" 25894a6b6ac4Schinlong " for %d seconds\n", 25907c478bd9Sstevel@tonic-gate CACHESLEEPTIME); 25917c478bd9Sstevel@tonic-gate } 25927c478bd9Sstevel@tonic-gate err = cond_reltimedwait(&cond, 25937c478bd9Sstevel@tonic-gate &sighuplock, &timeout); 25947c478bd9Sstevel@tonic-gate (void) cond_destroy(&cond); 25957c478bd9Sstevel@tonic-gate (void) mutex_unlock( 25967c478bd9Sstevel@tonic-gate &sighuplock); 25977c478bd9Sstevel@tonic-gate /* 25987c478bd9Sstevel@tonic-gate * if woke up by 25997c478bd9Sstevel@tonic-gate * getldap_revalidate(), 26007c478bd9Sstevel@tonic-gate * do update right away 26017c478bd9Sstevel@tonic-gate */ 26027c478bd9Sstevel@tonic-gate if (err == ETIME) 26037c478bd9Sstevel@tonic-gate continue; 26047c478bd9Sstevel@tonic-gate else { 26057c478bd9Sstevel@tonic-gate /* 26067c478bd9Sstevel@tonic-gate * if load 26077c478bd9Sstevel@tonic-gate * configuration failed 26087c478bd9Sstevel@tonic-gate * don't do update 26097c478bd9Sstevel@tonic-gate */ 26107c478bd9Sstevel@tonic-gate if (load_config()) 26114a6b6ac4Schinlong perform_update 26124a6b6ac4Schinlong (); 26137c478bd9Sstevel@tonic-gate continue; 26147c478bd9Sstevel@tonic-gate } 26157c478bd9Sstevel@tonic-gate } 26167c478bd9Sstevel@tonic-gate sleeptime = expire - tp.tv_sec; 26177c478bd9Sstevel@tonic-gate if (dbg_level >= DBG_PROFILE_REFRESH) { 26184a6b6ac4Schinlong logit("getldap_refresh: expire " 26194a6b6ac4Schinlong "time = %ld\n", expire); 26207c478bd9Sstevel@tonic-gate } 26217c478bd9Sstevel@tonic-gate 26227c478bd9Sstevel@tonic-gate } 26237c478bd9Sstevel@tonic-gate } 26247c478bd9Sstevel@tonic-gate } 26257c478bd9Sstevel@tonic-gate 26267c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldap_lock); 26277c478bd9Sstevel@tonic-gate 26287c478bd9Sstevel@tonic-gate /* 26297c478bd9Sstevel@tonic-gate * if this is the first time downloading 26307c478bd9Sstevel@tonic-gate * the profile or expire time already passed, 26317c478bd9Sstevel@tonic-gate * do not wait, do update 26327c478bd9Sstevel@tonic-gate */ 26337c478bd9Sstevel@tonic-gate if (first_time == 0 && sleeptime > 0) { 26347c478bd9Sstevel@tonic-gate if (dbg_level >= DBG_PROFILE_REFRESH) { 26357c478bd9Sstevel@tonic-gate logit("getldap_refresh: (2)about to sleep " 26367c478bd9Sstevel@tonic-gate "for %d seconds\n", sleeptime); 26377c478bd9Sstevel@tonic-gate } 26387c478bd9Sstevel@tonic-gate (void) cond_init(&cond, NULL, NULL); 26397c478bd9Sstevel@tonic-gate (void) mutex_lock(&sighuplock); 26407c478bd9Sstevel@tonic-gate timeout.tv_sec = sleeptime; 26417c478bd9Sstevel@tonic-gate timeout.tv_nsec = 0; 26427c478bd9Sstevel@tonic-gate err = cond_reltimedwait(&cond, 26437c478bd9Sstevel@tonic-gate &sighuplock, &timeout); 26447c478bd9Sstevel@tonic-gate (void) cond_destroy(&cond); 26457c478bd9Sstevel@tonic-gate (void) mutex_unlock(&sighuplock); 26467c478bd9Sstevel@tonic-gate } 26477c478bd9Sstevel@tonic-gate /* 26487c478bd9Sstevel@tonic-gate * if load concfiguration failed 26497c478bd9Sstevel@tonic-gate * don't do update 26507c478bd9Sstevel@tonic-gate */ 26517c478bd9Sstevel@tonic-gate if (load_config()) 26527c478bd9Sstevel@tonic-gate perform_update(); 26537c478bd9Sstevel@tonic-gate first_time = 0; 26547c478bd9Sstevel@tonic-gate } 26557c478bd9Sstevel@tonic-gate } 26567c478bd9Sstevel@tonic-gate 26577c478bd9Sstevel@tonic-gate void 26587c478bd9Sstevel@tonic-gate getldap_revalidate() 26597c478bd9Sstevel@tonic-gate { 26607c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 26617c478bd9Sstevel@tonic-gate logit("getldap_revalidate()...\n"); 26627c478bd9Sstevel@tonic-gate } 26637c478bd9Sstevel@tonic-gate /* block signal SIGHUP */ 26647c478bd9Sstevel@tonic-gate (void) sighold(SIGHUP); 26657c478bd9Sstevel@tonic-gate 26667c478bd9Sstevel@tonic-gate /* now awake the sleeping refresh thread */ 26677c478bd9Sstevel@tonic-gate (void) cond_signal(&cond); 26687c478bd9Sstevel@tonic-gate 26697c478bd9Sstevel@tonic-gate /* release signal SIGHUP */ 26707c478bd9Sstevel@tonic-gate (void) sigrelse(SIGHUP); 26717c478bd9Sstevel@tonic-gate 26727c478bd9Sstevel@tonic-gate } 26737c478bd9Sstevel@tonic-gate 26747c478bd9Sstevel@tonic-gate void 2675b57459abSJulian Pullen getldap_admincred(LineBuf *config_info, ldap_call_t *in) 2676b57459abSJulian Pullen { 2677b57459abSJulian Pullen ns_ldap_error_t *error; 2678b57459abSJulian Pullen ldap_config_out_t *cout; 2679b57459abSJulian Pullen ucred_t *uc = NULL; 2680b57459abSJulian Pullen 2681b57459abSJulian Pullen if (current_admin.debug_level >= DBG_ALL) { 2682b57459abSJulian Pullen logit("getldap_admincred()...\n"); 2683b57459abSJulian Pullen } 2684b57459abSJulian Pullen /* check privileges */ 2685b57459abSJulian Pullen if (is_root_or_all_privs("GETADMINCRED", &uc) == 0) { 2686b57459abSJulian Pullen logit("admin credential requested by a non-root and no ALL " 2687b57459abSJulian Pullen "privilege user not allowed"); 2688b57459abSJulian Pullen config_info->str = NULL; 2689b57459abSJulian Pullen config_info->len = 0; 2690b57459abSJulian Pullen } else { 2691b57459abSJulian Pullen (void) rw_rdlock(&ldap_lock); 2692b57459abSJulian Pullen if ((error = __ns_ldap_LoadDoorInfo(config_info, 2693b57459abSJulian Pullen in->ldap_u.domainname, NULL, 1)) != NULL) { 2694b57459abSJulian Pullen if (error != NULL && error->message != NULL) 2695b57459abSJulian Pullen logit("Error: ldap_lookup: %s\n", 2696b57459abSJulian Pullen error->message); 2697b57459abSJulian Pullen (void) __ns_ldap_freeError(&error); 2698b57459abSJulian Pullen 2699b57459abSJulian Pullen config_info->str = NULL; 2700b57459abSJulian Pullen config_info->len = 0; 2701b57459abSJulian Pullen } 2702b57459abSJulian Pullen /* set change cookie */ 2703b57459abSJulian Pullen cout = (ldap_config_out_t *)config_info->str; 2704b57459abSJulian Pullen if (cout) 2705b57459abSJulian Pullen cout->cookie = chg_config_cookie_get(); 2706b57459abSJulian Pullen (void) rw_unlock(&ldap_lock); 2707b57459abSJulian Pullen } 2708b57459abSJulian Pullen } 2709b57459abSJulian Pullen 2710b57459abSJulian Pullen void 27117ddae043Siz202018 getldap_lookup(LineBuf *config_info, ldap_call_t *in) 27127c478bd9Sstevel@tonic-gate { 27137c478bd9Sstevel@tonic-gate ns_ldap_error_t *error; 2714e1dd0a2fSth160488 ldap_config_out_t *cout; 27157c478bd9Sstevel@tonic-gate 27167c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 27177c478bd9Sstevel@tonic-gate logit("getldap_lookup()...\n"); 27187c478bd9Sstevel@tonic-gate } 27197c478bd9Sstevel@tonic-gate (void) rw_rdlock(&ldap_lock); 27207ddae043Siz202018 if ((error = __ns_ldap_LoadDoorInfo(config_info, 2721b57459abSJulian Pullen in->ldap_u.domainname, NULL, 0)) != NULL) { 27227c478bd9Sstevel@tonic-gate if (error != NULL && error->message != NULL) 27237c478bd9Sstevel@tonic-gate logit("Error: ldap_lookup: %s\n", error->message); 27247c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeError(&error); 27257c478bd9Sstevel@tonic-gate 27267ddae043Siz202018 config_info->str = NULL; 27277ddae043Siz202018 config_info->len = 0; 27287c478bd9Sstevel@tonic-gate } 2729e1dd0a2fSth160488 /* set change cookie */ 2730e1dd0a2fSth160488 cout = (ldap_config_out_t *)config_info->str; 2731e1dd0a2fSth160488 if (cout) 2732e1dd0a2fSth160488 cout->cookie = chg_config_cookie_get(); 27337c478bd9Sstevel@tonic-gate (void) rw_unlock(&ldap_lock); 27347c478bd9Sstevel@tonic-gate } 2735e1dd0a2fSth160488 /* 2736e1dd0a2fSth160488 * It creates the header and data stream to be door returned and notify 2737e1dd0a2fSth160488 * chg_get_statusChange() threads. 2738e1dd0a2fSth160488 * This is called after all getldap_get_rootDSE() threads are joined. 2739e1dd0a2fSth160488 */ 2740e1dd0a2fSth160488 void 2741e1dd0a2fSth160488 test_server_change(server_info_t *head) 2742e1dd0a2fSth160488 { 2743e1dd0a2fSth160488 server_info_t *info; 2744e1dd0a2fSth160488 int len = 0, num = 0, ds_len = 0, new_len = 0, tlen = 0; 2745e1dd0a2fSth160488 char *tmp_buf = NULL, *ptr = NULL, *status = NULL; 2746e1dd0a2fSth160488 ldap_get_change_out_t *cout; 2747e1dd0a2fSth160488 2748e1dd0a2fSth160488 ds_len = strlen(DOORLINESEP); 2749e1dd0a2fSth160488 2750e1dd0a2fSth160488 for (info = head; info; info = info->next) { 2751e1dd0a2fSth160488 (void) mutex_lock(&info->mutex[0]); 2752e1dd0a2fSth160488 if (info->sinfo[0].change != 0) { 2753e1dd0a2fSth160488 /* "9.9.9.9|NS_SERVER_CHANGE_UP|" */ 2754e1dd0a2fSth160488 len += 2 * ds_len + strlen(info->sinfo[0].addr) + 2755e1dd0a2fSth160488 strlen(NS_SERVER_CHANGE_UP); 2756e1dd0a2fSth160488 num++; 2757e1dd0a2fSth160488 } 2758e1dd0a2fSth160488 (void) mutex_unlock(&info->mutex[0]); 2759e1dd0a2fSth160488 } 2760e1dd0a2fSth160488 2761e1dd0a2fSth160488 if (len == 0) 2762e1dd0a2fSth160488 return; 2763e1dd0a2fSth160488 2764e1dd0a2fSth160488 len++; /* '\0' */ 2765e1dd0a2fSth160488 2766e1dd0a2fSth160488 tlen = sizeof (ldap_get_change_out_t) - sizeof (int) + len; 2767e1dd0a2fSth160488 if ((tmp_buf = malloc(tlen)) == NULL) 2768e1dd0a2fSth160488 return; 2769e1dd0a2fSth160488 2770e1dd0a2fSth160488 cout = (ldap_get_change_out_t *)tmp_buf; 2771e1dd0a2fSth160488 cout->type = NS_STATUS_CHANGE_TYPE_SERVER; 2772e1dd0a2fSth160488 /* cout->cookie is set by chg_notify_statusChange */ 2773e1dd0a2fSth160488 cout->server_count = num; 2774e1dd0a2fSth160488 cout->data_size = len; 2775e1dd0a2fSth160488 2776e1dd0a2fSth160488 /* Create IP|UP or DOWN|IP|UP or DOWN| ... */ 2777e1dd0a2fSth160488 ptr = cout->data; 2778e1dd0a2fSth160488 new_len = len; 2779e1dd0a2fSth160488 for (info = head; info; info = info->next) { 2780e1dd0a2fSth160488 (void) mutex_lock(&info->mutex[0]); 2781e1dd0a2fSth160488 if (info->sinfo[0].change == 0) { 2782e1dd0a2fSth160488 (void) mutex_unlock(&info->mutex[0]); 2783e1dd0a2fSth160488 continue; 2784e1dd0a2fSth160488 } 2785e1dd0a2fSth160488 2786e1dd0a2fSth160488 if (info->sinfo[0].change == NS_SERVER_UP) 2787e1dd0a2fSth160488 status = NS_SERVER_CHANGE_UP; 2788e1dd0a2fSth160488 else if (info->sinfo[0].change == NS_SERVER_DOWN) 2789e1dd0a2fSth160488 status = NS_SERVER_CHANGE_DOWN; 2790e1dd0a2fSth160488 else { 2791e1dd0a2fSth160488 syslog(LOG_WARNING, gettext("Bad change value %d"), 2792e1dd0a2fSth160488 info->sinfo[0].change); 2793e1dd0a2fSth160488 (void) mutex_unlock(&info->mutex[0]); 2794e1dd0a2fSth160488 free(tmp_buf); 2795e1dd0a2fSth160488 return; 2796e1dd0a2fSth160488 } 2797e1dd0a2fSth160488 2798e1dd0a2fSth160488 if ((snprintf(ptr, new_len, "%s%s%s%s", 2799e1dd0a2fSth160488 info->sinfo[0].addr, DOORLINESEP, 2800e1dd0a2fSth160488 status, DOORLINESEP)) >= new_len) { 2801e1dd0a2fSth160488 (void) mutex_unlock(&info->mutex[0]); 2802e1dd0a2fSth160488 break; 2803e1dd0a2fSth160488 } 2804e1dd0a2fSth160488 new_len -= strlen(ptr); 2805e1dd0a2fSth160488 ptr += strlen(ptr); 2806e1dd0a2fSth160488 2807e1dd0a2fSth160488 (void) mutex_unlock(&info->mutex[0]); 2808e1dd0a2fSth160488 } 2809e1dd0a2fSth160488 (void) chg_notify_statusChange(tmp_buf); 2810e1dd0a2fSth160488 } 2811e1dd0a2fSth160488 /* 2812e1dd0a2fSth160488 * It creates the header and data stream to be door returned and notify 2813e1dd0a2fSth160488 * chg_get_statusChange() threads. 2814e1dd0a2fSth160488 * This is called in removing server case. 2815e1dd0a2fSth160488 */ 2816e1dd0a2fSth160488 static void 2817e1dd0a2fSth160488 create_buf_and_notify(char *input, ns_server_status_t st) 2818e1dd0a2fSth160488 { 2819e1dd0a2fSth160488 rm_svr_t *rms = (rm_svr_t *)input; 2820e1dd0a2fSth160488 char *tmp_buf, *ptr, *status; 2821e1dd0a2fSth160488 int len, tlen; 2822e1dd0a2fSth160488 ldap_get_change_out_t *cout; 2823e1dd0a2fSth160488 2824e1dd0a2fSth160488 /* IP|UP or DOWN| */ 2825e1dd0a2fSth160488 len = 2 * strlen(DOORLINESEP) + strlen(rms->addr) + 2826e1dd0a2fSth160488 strlen(NS_SERVER_CHANGE_UP) + 1; 2827e1dd0a2fSth160488 2828e1dd0a2fSth160488 tlen = sizeof (ldap_get_change_out_t) - sizeof (int) + len; 2829e1dd0a2fSth160488 2830e1dd0a2fSth160488 if ((tmp_buf = malloc(tlen)) == NULL) 2831e1dd0a2fSth160488 return; 2832e1dd0a2fSth160488 2833e1dd0a2fSth160488 cout = (ldap_get_change_out_t *)tmp_buf; 2834e1dd0a2fSth160488 cout->type = NS_STATUS_CHANGE_TYPE_SERVER; 2835e1dd0a2fSth160488 /* cout->cookie is set by chg_notify_statusChange */ 2836e1dd0a2fSth160488 cout->server_count = 1; 2837e1dd0a2fSth160488 cout->data_size = len; 2838e1dd0a2fSth160488 2839e1dd0a2fSth160488 /* Create IP|DOWN| */ 2840e1dd0a2fSth160488 ptr = cout->data; 2841e1dd0a2fSth160488 if (st == NS_SERVER_UP) 2842e1dd0a2fSth160488 status = NS_SERVER_CHANGE_UP; 2843e1dd0a2fSth160488 else if (st == NS_SERVER_DOWN) 2844e1dd0a2fSth160488 status = NS_SERVER_CHANGE_DOWN; 2845e1dd0a2fSth160488 2846e1dd0a2fSth160488 (void) snprintf(ptr, len, "%s%s%s%s", 2847e1dd0a2fSth160488 rms->addr, DOORLINESEP, status, DOORLINESEP); 2848e1dd0a2fSth160488 2849e1dd0a2fSth160488 (void) chg_notify_statusChange(tmp_buf); 2850e1dd0a2fSth160488 2851e1dd0a2fSth160488 } 2852e1dd0a2fSth160488 2853e1dd0a2fSth160488 /* 2854e1dd0a2fSth160488 * Return: 0 server is down, 1 server is up 2855e1dd0a2fSth160488 */ 2856e1dd0a2fSth160488 static int 2857e1dd0a2fSth160488 contact_server(char *addr) 2858e1dd0a2fSth160488 { 2859e1dd0a2fSth160488 char *rootDSE = NULL; 2860e1dd0a2fSth160488 ns_ldap_error_t *error = NULL; 2861e1dd0a2fSth160488 int rc; 2862e1dd0a2fSth160488 2863e1dd0a2fSth160488 if (__ns_ldap_getRootDSE(addr, &rootDSE, &error, 2864e1dd0a2fSth160488 SA_ALLOW_FALLBACK) != NS_LDAP_SUCCESS) { 2865e1dd0a2fSth160488 if (current_admin.debug_level >= DBG_ALL) 2866e1dd0a2fSth160488 logit("get rootDSE %s failed. %s", addr, 2867e1dd0a2fSth160488 error->message ? error->message : ""); 2868e1dd0a2fSth160488 rc = 0; 2869e1dd0a2fSth160488 } else 2870e1dd0a2fSth160488 rc = 1; 2871e1dd0a2fSth160488 2872e1dd0a2fSth160488 if (rootDSE) 2873e1dd0a2fSth160488 free(rootDSE); 2874e1dd0a2fSth160488 if (error) 2875e1dd0a2fSth160488 (void) __ns_ldap_freeError(&error); 2876e1dd0a2fSth160488 2877e1dd0a2fSth160488 return (rc); 2878e1dd0a2fSth160488 } 2879e1dd0a2fSth160488 2880e1dd0a2fSth160488 /* 2881e1dd0a2fSth160488 * The thread is spawned to do contact_server() so it won't be blocking 2882e1dd0a2fSth160488 * getldap_serverInfo_op(INFO_OP_GETSERVER, ...) case. 2883e1dd0a2fSth160488 * After contact_server() is done, it calls 2884e1dd0a2fSth160488 * getldap_serverInfo_op(INFO_OP_REMOVESERVER, ...) to return to the remaining 2885e1dd0a2fSth160488 * program flow. It's meant to maintain the original program flow yet be 2886e1dd0a2fSth160488 * non-blocking when it's contacting server. 2887e1dd0a2fSth160488 */ 2888e1dd0a2fSth160488 static void * 2889e1dd0a2fSth160488 remove_server_thread(void *arg) 2890e1dd0a2fSth160488 { 2891e1dd0a2fSth160488 char *addr = (char *)arg, *out = NULL; 2892e1dd0a2fSth160488 int up; 2893e1dd0a2fSth160488 rm_svr_t rms; 2894e1dd0a2fSth160488 2895e1dd0a2fSth160488 up = contact_server(addr); 2896e1dd0a2fSth160488 2897e1dd0a2fSth160488 rms.addr = addr; 2898e1dd0a2fSth160488 rms.up = up; 2899e1dd0a2fSth160488 2900e1dd0a2fSth160488 (void) getldap_serverInfo_op(INFO_OP_REMOVESERVER, (char *)&rms, &out); 2901e1dd0a2fSth160488 2902e1dd0a2fSth160488 free(addr); 2903e1dd0a2fSth160488 2904e1dd0a2fSth160488 thr_exit(NULL); 2905e1dd0a2fSth160488 return (NULL); 2906e1dd0a2fSth160488 } 2907e1dd0a2fSth160488 /* 2908e1dd0a2fSth160488 * addr is allocated and is freed by remove_server_thread 2909e1dd0a2fSth160488 * It starts a thread to contact server and remove server to avoid long wait 2910e1dd0a2fSth160488 * or recursion. 2911e1dd0a2fSth160488 */ 2912e1dd0a2fSth160488 static void 2913e1dd0a2fSth160488 remove_server(char *addr) 2914e1dd0a2fSth160488 { 2915e1dd0a2fSth160488 if (thr_create(NULL, 0, remove_server_thread, 2916e1dd0a2fSth160488 (void *)addr, THR_BOUND|THR_DETACHED, NULL) != 0) { 2917e1dd0a2fSth160488 free(addr); 2918e1dd0a2fSth160488 syslog(LOG_ERR, "thr_create failed for remove_server_thread"); 2919e1dd0a2fSth160488 } 2920e1dd0a2fSth160488 } 2921e1dd0a2fSth160488 /* 2922e1dd0a2fSth160488 * Compare the server_status and mark it up or down accordingly. 2923e1dd0a2fSth160488 * This is called in removing server case. 2924e1dd0a2fSth160488 */ 2925e1dd0a2fSth160488 static ns_server_status_t 2926e1dd0a2fSth160488 set_server_status(char *input, server_info_t *head) 2927e1dd0a2fSth160488 { 2928e1dd0a2fSth160488 rm_svr_t *rms = (rm_svr_t *)input; 2929e1dd0a2fSth160488 ns_server_status_t changed = 0; 2930e1dd0a2fSth160488 server_info_t *info; 2931e1dd0a2fSth160488 2932e1dd0a2fSth160488 for (info = head; info != NULL; info = info->next) { 2933e1dd0a2fSth160488 (void) mutex_lock(&info->mutex[0]); 2934e1dd0a2fSth160488 if (strcmp(info->sinfo[0].addr, rms->addr) == 0) { 2935e1dd0a2fSth160488 if (info->sinfo[0].server_status == INFO_SERVER_UP && 2936e1dd0a2fSth160488 rms->up == FALSE) { 2937e1dd0a2fSth160488 info->sinfo[0].prev_server_status = 2938e1dd0a2fSth160488 info->sinfo[0].server_status; 2939e1dd0a2fSth160488 info->sinfo[0].server_status = 2940e1dd0a2fSth160488 INFO_SERVER_ERROR; 2941e1dd0a2fSth160488 info->sinfo[0].change = NS_SERVER_DOWN; 2942e1dd0a2fSth160488 changed = NS_SERVER_DOWN; 2943e1dd0a2fSth160488 2944e1dd0a2fSth160488 } else if (info->sinfo[0].server_status == 2945e1dd0a2fSth160488 INFO_SERVER_ERROR && rms->up == TRUE) { 2946e1dd0a2fSth160488 /* 2947e1dd0a2fSth160488 * It should be INFO_SERVER_UP, but check here 2948e1dd0a2fSth160488 */ 2949e1dd0a2fSth160488 info->sinfo[0].prev_server_status = 2950e1dd0a2fSth160488 info->sinfo[0].server_status; 2951e1dd0a2fSth160488 info->sinfo[0].server_status = 2952e1dd0a2fSth160488 INFO_SERVER_UP; 2953e1dd0a2fSth160488 info->sinfo[0].change = NS_SERVER_UP; 2954e1dd0a2fSth160488 changed = NS_SERVER_UP; 2955e1dd0a2fSth160488 } 2956e1dd0a2fSth160488 (void) mutex_unlock(&info->mutex[0]); 2957e1dd0a2fSth160488 break; 2958e1dd0a2fSth160488 } 2959e1dd0a2fSth160488 (void) mutex_unlock(&info->mutex[0]); 2960e1dd0a2fSth160488 } 2961e1dd0a2fSth160488 if (changed) { 2962e1dd0a2fSth160488 /* ldap_cachemgr -g option looks up [1] */ 2963e1dd0a2fSth160488 (void) mutex_lock(&info->mutex[1]); 2964e1dd0a2fSth160488 info->sinfo[1].prev_server_status = 2965e1dd0a2fSth160488 info->sinfo[1].server_status; 2966e1dd0a2fSth160488 if (changed == NS_SERVER_DOWN) 2967e1dd0a2fSth160488 info->sinfo[1].server_status = INFO_SERVER_ERROR; 2968e1dd0a2fSth160488 else if (changed == NS_SERVER_UP) 2969e1dd0a2fSth160488 info->sinfo[1].server_status = INFO_SERVER_UP; 2970e1dd0a2fSth160488 (void) mutex_unlock(&info->mutex[1]); 2971e1dd0a2fSth160488 } 2972e1dd0a2fSth160488 return (changed); 2973e1dd0a2fSth160488 } 2974