e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * CDDL HEADER START
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * The contents of this file are subject to the terms of the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Common Development and Distribution License (the "License").
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * You may not use this file except in compliance with the License.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * or http://www.opensolaris.org/os/licensing.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * See the License for the specific language governing permissions
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * and limitations under the License.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * When distributing Covered Code, include this CDDL HEADER in each
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If applicable, add the following below this CDDL HEADER, with the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * fields enclosed by brackets "[]" replaced with your own identifying
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * information: Portions Copyright [yyyy] [name of copyright owner]
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * CDDL HEADER END
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Use is subject to license terms.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#pragma ident "%Z%%M% %I% %E% SMI"
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <string.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <errno.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <syslog.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <procfs.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <unistd.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <fcntl.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <libintl.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <atomic.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <pthread.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <sys/mman.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <time.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include "solaris-int.h"
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include "ns_connmgmt.h"
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include "ns_cache_door.h"
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include "ns_internal.h"
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Access (reference, shutdown, or reload) the current connection
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * management control structure conn_mgmt_t.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MGMT_OP_REF 1
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MGMT_OP_SHUTDOWN 2
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MGMT_OP_RELOAD_CONFIG 3
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MGMT_OP_NEW_CONFIG 4
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MGMT_OP_LIB_INIT 5
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic ns_conn_mgmt_t *access_conn_mgmt(int);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic ns_conn_mgmt_t *release_conn_mgmt(ns_conn_mgmt_t *, boolean_t);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int close_conn_mt(ns_conn_mt_t *, int, ns_ldap_error_t **,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_user_t *);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int close_conn_mt_when_nouser(ns_conn_mt_t *cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid shutdown_all_conn_mt(ns_conn_mgmt_t *cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int conn_signal(ns_conn_mt_t *);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int conn_wait(ns_conn_mt_t *, ns_conn_user_t *);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void close_conn_mt_by_procchg(ns_conn_mt_t *cm, int rc, char *errmsg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic ns_conn_mgmt_t *proc_server_change(ns_server_status_change_t *chg,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void get_preferred_servers(boolean_t, boolean_t, ns_conn_mgmt_t *);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void start_thread();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic ns_conn_mgmt_t *ns_connmgmt = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic ns_conn_mgmt_t *ns_connmgmt_parent = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic mutex_t ns_connmgmt_lock = DEFAULTMUTEX;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic boolean_t ns_connmgmt_shutting_down = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MSG_NO_CONN_MGMT gettext( \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: unable to allocate the connection management control")
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MSG_NO_MTC_KEY gettext( \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: unable to allocate the TSD key for per-thread ldap error")
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MSG_NO_CMG_KEY gettext( \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: unable to allocate the TSD key for connection management")
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MSG_SHUTDOWN gettext("libsldap: library is being unloaded")
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MSG_RELOADED gettext( \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: configuration has been reloaded")
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MSG_SHUTDOWN_RELOADED gettext( \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: library unloaded or configuration has been reloaded")
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MSG_BAD_CACHEMGR_DATA gettext( \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: received incorrect data from ldap_cachemgr")
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MSG_MEMORY_ERROR gettext( \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: unable to allocate memory")
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MSG_NO_PROCCHG_THREAD gettext( \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: unable to start the server monitor thread (%s)")
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MSG_DOWN_FROM_CACHEMGR gettext( \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: server down reported by ldap_cachemgr")
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int ns_conn_free = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_UNLOCK_AND_FREE(free, cm, cmg) \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{ \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&(cm)->lock); \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (free == 1) \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = free_conn_mt((cm), 1); \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg != NULL) \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&(cmg)->lock); \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_CHECK_ABORT_AND_LOCK(cmg, cu, errp) \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{ \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char *msg = NULL; \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&(cmg)->lock); \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((cmg)->shutting_down == B_TRUE) \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth msg = NS_CONN_MSG_SHUTDOWN; \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else if ((cmg)->cfg_reloaded == B_TRUE) \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth msg = NS_CONN_MSG_RELOADED; \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (msg != NULL) { \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (*errp) = __s_api_make_error(NS_LDAP_OP_FAILED, msg); \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&(cmg)->lock); \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_OP_FAILED); \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } \
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * TSD keys ns_mtckey and ns_cmgkey are for sharing ldap connections
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * and their associated connection management structure among
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * multiple threads. The pointers to the per-thread ldap error
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * information and the connection management structure are
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * saved in ns_mtckey and ns_cmgkey.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eththread_key_t ns_mtckey = THR_ONCE_KEY;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eththread_key_t ns_cmgkey = THR_ONCE_KEY;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* Per thread LDAP error resides in thread-specific data (ns_mtckey) */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstruct ldap_error {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int le_errno;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char *le_matched;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char *le_errmsg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth};
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* NULL struct ldap_error */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic struct ldap_error ldap_error_NULL = { LDAP_SUCCESS, NULL, NULL};
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* destructor: free the ldap error data in the thread specific area */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethns_mtckey_cleanup(void *key) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth struct ldap_error *le = (struct ldap_error *)key;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (le == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (le->le_matched != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_memfree(le->le_matched);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (le->le_errmsg != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_memfree(le->le_errmsg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(le);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* Free/detach the thread specific data structures */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethconn_tsd_free() {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth void *tsd = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* free the per-thread ldap error info */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = thr_getspecific(ns_mtckey, &tsd);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc == 0 && tsd != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_mtckey_cleanup(tsd);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) thr_setspecific(ns_mtckey, NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* detach the connection management control */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) thr_setspecific(ns_cmgkey, NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* per-thread callback function for allocating a mutex */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethns_mutex_alloc(void)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth mutex_t *mutexp = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((mutexp = malloc(sizeof (mutex_t))) != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (mutex_init(mutexp, USYNC_THREAD, NULL) != 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(mutexp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth mutexp = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (mutexp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* per-thread callback function for freeing a mutex */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethns_mutex_free(void *mutexp)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_destroy((mutex_t *)mutexp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(mutexp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Function for setting up thread-specific data
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * where per thread LDAP error and the pointer
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * to the active connection management control
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * are stored.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethconn_tsd_setup(ns_conn_mgmt_t *cmg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth void *tsd;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = thr_setspecific(ns_cmgkey, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc != 0) /* must be ENOMEM */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (-1);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* return success if the ns_mtckey TSD is already set */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = thr_getspecific(ns_mtckey, &tsd);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc == 0 && tsd != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* allocate and set the ns_mtckey TSD */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth tsd = (void *) calloc(1, sizeof (struct ldap_error));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (tsd == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (-1);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = thr_setspecific(ns_mtckey, tsd);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc != 0) { /* must be ENOMEM */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(tsd);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (-1);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* Callback function for setting the per thread LDAP error */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*ARGSUSED*/
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethset_ld_error(int err, char *matched, char *errmsg, void *dummy)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth struct ldap_error *le;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int eno;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((eno = thr_getspecific(ns_mtckey, (void **)&le)) != 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_ERR, gettext(
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: set_ld_error: thr_getspecific failed (%s)."),
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth strerror(eno));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* play safe, do nothing if TSD pointer is NULL */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (le == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_INFO, gettext(
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: set_ld_error: TSD pointer is NULL."));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth le->le_errno = err;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (le->le_matched != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_memfree(le->le_matched);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth le->le_matched = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth le->le_matched = matched;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (le->le_errmsg != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_memfree(le->le_errmsg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth le->le_errmsg = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth le->le_errmsg = errmsg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* check and allocate the thread-specific data for using a MT connection */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethconn_tsd_check(ns_conn_mgmt_t *cmg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (conn_tsd_setup(cmg) != 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_MEMORY);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_SUCCESS);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* Callback function for getting the per thread LDAP error */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*ARGSUSED*/
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethget_ld_error(char **matched, char **errmsg, void *dummy)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth struct ldap_error *le;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int eno;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((eno = thr_getspecific(ns_mtckey, (void **)&le)) != 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_ERR, gettext(
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: get_ld_error: thr_getspecific failed (%s)"),
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth strerror(eno));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (eno);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* play safe, return NULL error data, if TSD pointer is NULL */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (le == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth le = &ldap_error_NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (matched != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *matched = le->le_matched;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (errmsg != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *errmsg = le->le_errmsg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (le->le_errno);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* Callback function for setting per thread errno */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethset_errno(int err)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth errno = err;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* Callback function for getting per thread errno */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethget_errno(void)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (errno);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* set up an ldap session 'ld' for sharing among multiple threads */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethsetup_mt_conn(LDAP *ld)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth struct ldap_thread_fns tfns;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth struct ldap_extra_thread_fns extrafns;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Set the function pointers for dealing with mutexes
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * and error information
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) memset(&tfns, '\0', sizeof (struct ldap_thread_fns));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth tfns.ltf_mutex_alloc = (void *(*)(void)) ns_mutex_alloc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth tfns.ltf_mutex_free = (void (*)(void *)) ns_mutex_free;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth tfns.ltf_mutex_lock = (int (*)(void *)) mutex_lock;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth tfns.ltf_mutex_unlock = (int (*)(void *)) mutex_unlock;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth tfns.ltf_get_errno = get_errno;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth tfns.ltf_set_errno = set_errno;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth tfns.ltf_get_lderrno = get_ld_error;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth tfns.ltf_set_lderrno = set_ld_error;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth tfns.ltf_lderrno_arg = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Set up the ld to use those function pointers
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = ldap_set_option(ld, LDAP_OPT_THREAD_FN_PTRS,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void *) &tfns);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc < 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_INFO, gettext("libsldap: ldap_set_option "
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "(LDAP_OPT_THREAD_FN_PTRS)"));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Set the function pointers for working with semaphores
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) memset(&extrafns, '\0',
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth sizeof (struct ldap_extra_thread_fns));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth extrafns.ltf_threadid_fn = (void * (*)(void))thr_self;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth extrafns.ltf_mutex_trylock = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth extrafns.ltf_sema_alloc = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth extrafns.ltf_sema_free = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth extrafns.ltf_sema_wait = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth extrafns.ltf_sema_post = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* Set up the ld to use those function pointers */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = ldap_set_option(ld, LDAP_OPT_EXTRA_THREAD_FN_PTRS,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void *) &extrafns);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc < 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_INFO, gettext("libsldap: ldap_set_option "
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "(LDAP_OPT_EXTRA_THREAD_FN_PTRS)"));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (1);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* set up an MT connection for sharing among multiple threads */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethsetup_mt_ld(LDAP *ld, ns_conn_mgmt_t *cmg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth thread_t t = thr_self();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* set up the per-thread data for using the MT connection */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (conn_tsd_setup(cmg) == -1) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_WARNING,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth gettext("libsldap: tid= %d: unable to set up TSD\n"), t);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (-1);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (setup_mt_conn(ld) == 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* multiple threads per connection not supported */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_WARNING, gettext("libsldap: tid= %d: multiple "
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "threads per connection not supported\n"), t);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth conn_tsd_free();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (-1);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Check name and UID of process, if it is nscd.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Input:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * pid : PID of checked process
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * check_uid : check if UID == 0
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Output:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * B_TRUE : nscd detected
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * B_FALSE : nscd not confirmed
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic boolean_t
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethcheck_nscd_proc(pid_t pid, boolean_t check_uid)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth psinfo_t pinfo;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char fname[MAXPATHLEN];
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ssize_t ret;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int fd;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (snprintf(fname, MAXPATHLEN, "/proc/%d/psinfo", pid) > 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((fd = open(fname, O_RDONLY)) >= 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ret = read(fd, &pinfo, sizeof (psinfo_t));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) close(fd);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((ret == sizeof (psinfo_t)) &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (strcmp(pinfo.pr_fname, "nscd") == 0)) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (check_uid && (pinfo.pr_uid != 0))
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_TRUE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Check if this process is peruser nscd.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethboolean_t
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_peruser_proc(void)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid_t my_ppid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth static mutex_t nscdLock = DEFAULTMUTEX;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth static pid_t checkedPpid = (pid_t)-1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth static boolean_t isPeruserNscd = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth my_ppid = getppid();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Already checked before for this process? If yes, return cached
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * response.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (my_ppid == checkedPpid) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (isPeruserNscd);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&nscdLock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* Check once more incase another thread has just complete this. */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (my_ppid == checkedPpid) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&nscdLock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (isPeruserNscd);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* Reinitialize to be sure there is no residue after fork. */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth isPeruserNscd = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* Am I the nscd process? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (check_nscd_proc(getpid(), B_FALSE)) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* Is my parent the nscd process with UID == 0. */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth isPeruserNscd = check_nscd_proc(my_ppid, B_TRUE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
ca190d8debe6672d99069a376a987adee0765d6cmichen /* Remember for whom isPeruserNscd is. */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth checkedPpid = my_ppid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&nscdLock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (isPeruserNscd);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Check if this process is main nscd.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethboolean_t
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_nscd_proc(void)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid_t my_pid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth static mutex_t nscdLock = DEFAULTMUTEX;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth static pid_t checkedPid = (pid_t)-1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth static boolean_t isMainNscd = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Don't bother checking if this process isn't root, this cannot
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * be main nscd.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (getuid() != 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth my_pid = getpid();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Already checked before for this process? If yes, return cached
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * response.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (my_pid == checkedPid) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (isMainNscd);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&nscdLock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* Check once more incase another thread has just done this. */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (my_pid == checkedPid) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&nscdLock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (isMainNscd);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Am I the nscd process? UID is already checked, not needed from
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * psinfo.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth isMainNscd = check_nscd_proc(my_pid, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
ca190d8debe6672d99069a376a987adee0765d6cmichen /* Remember for whom isMainNscd is. */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth checkedPid = my_pid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&nscdLock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (isMainNscd);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * initialize a connection management control structure conn_mgmt_t
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethns_conn_mgmt_t *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethinit_conn_mgmt()
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = (ns_conn_mgmt_t *)calloc(1, sizeof (*cmg));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_ERR, NS_CONN_MSG_NO_CONN_MGMT);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* is this process nscd or peruser nscd ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->is_nscd = __s_api_nscd_proc();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->is_peruser_nscd = __s_api_peruser_proc();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * assume the underlying libldap allows multiple threads sharing
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the same ldap connection (MT connection)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->ldap_mt = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* state is inactive until MT connection is required/requested */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->state = NS_CONN_MGMT_INACTIVE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_init(&cmg->lock, USYNC_THREAD, NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_init(&cmg->cfg_lock, USYNC_THREAD, NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->pid = getpid();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* for nscd or peruser nscd, MT connection is required */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->is_nscd == B_TRUE || cmg->is_peruser_nscd == B_TRUE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->state = NS_CONN_MGMT_ACTIVE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * reference (or initialize) the current Native LDAP configuration and
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * if in nscd process, make it never refreshed
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->config = __s_api_get_default_config_global();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->config == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->config = __s_api_loadrefresh_config_global();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->config != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * main nscd get config change notice from ldap_cachemgr
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * so won't times out and refresh the config
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->is_nscd == B_TRUE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (cmg->config)->paramList[NS_LDAP_EXP_P].ns_tm = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cfg_cookie = cmg->config->config_cookie;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
ca190d8debe6672d99069a376a987adee0765d6cmichenmark_shutdown_or_reloaded(int op)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg = ns_connmgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (op == NS_CONN_MGMT_OP_SHUTDOWN)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->shutting_down = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cfg_reloaded = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth atomic_inc_uint(&cmg->ref_cnt);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->state = NS_CONN_MGMT_DETACHED;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (op == NS_CONN_MGMT_OP_RELOAD_CONFIG)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_init_config_global(NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Return a pointer to the current connection management. If
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * it has not been created, or is requested to recreate, then
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * create and return the pointer. It is possible, the current
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * one is created by the parent before fork, create a new
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * one too in such a case.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic ns_conn_mgmt_t *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethget_current_conn_mgmt(int op)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg = ns_connmgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth static pid_t checked_pid = (pid_t)-1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid_t mypid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth mypid = getpid();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg == NULL || checked_pid != mypid) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth checked_pid = mypid;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * if current conn_mgmt not created yet or is from parent
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * or is requested to recreate, create it
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg == NULL || cmg->pid != mypid) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * We don't want to free the conn_mgmt
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * allocated by the parent, since
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * there may be ldap connections
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * still being used. So leave it
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * alone but keep it referenced,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * so that it will not be flagged
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * as a piece of leaked memory.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_connmgmt_parent = cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * avoid lint warning; does not
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * change the conn_mgmt in parent
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_connmgmt_parent->state =
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MGMT_DETACHED;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_connmgmt = init_conn_mgmt();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = ns_connmgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * ensure it will not be destroyed until explicitly
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * shut down or reloaded
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (op == NS_CONN_MGMT_OP_REF)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth atomic_inc_uint(&cmg->ref_cnt);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic ns_conn_mgmt_t *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethaccess_conn_mgmt(int op)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg_prev;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&ns_connmgmt_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * connection management is not available when the libsldap is being
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * unloaded or shut down
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (ns_connmgmt_shutting_down == B_TRUE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&ns_connmgmt_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (op == NS_CONN_MGMT_OP_SHUTDOWN) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_connmgmt_shutting_down = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (ns_connmgmt != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = ns_connmgmt;
ca190d8debe6672d99069a376a987adee0765d6cmichen mark_shutdown_or_reloaded(op);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_connmgmt = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&ns_connmgmt_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (op == NS_CONN_MGMT_OP_RELOAD_CONFIG ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth op == NS_CONN_MGMT_OP_NEW_CONFIG) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg_prev = ns_connmgmt;
ca190d8debe6672d99069a376a987adee0765d6cmichen mark_shutdown_or_reloaded(op);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the previous cmg (cmg_prev) will be freed later
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * when its ref count reaches zero
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_connmgmt = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = get_current_conn_mgmt(op);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&ns_connmgmt_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth atomic_inc_uint(&cmg->ref_cnt);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (op == NS_CONN_MGMT_OP_RELOAD_CONFIG ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth op == NS_CONN_MGMT_OP_NEW_CONFIG)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = cmg_prev;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else { /* op is NS_CONN_MGMT_OP_REF or NS_CONN_MGMT_OP_LIB_INIT */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->config == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->config = __s_api_get_default_config();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&ns_connmgmt_lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * free a connection management control
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethfree_conn_mgmt(ns_conn_mgmt_t *cmg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth union {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_data_t s_d;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char s_b[1024];
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } space;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_data_t *sptr;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int ndata;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int adata;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_get_chg_cookie_t cookie;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cookie = cmg->cfg_cookie;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_free2dArray(cmg->pservers);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* destroy the previous config or release the current one */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->config != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->state == NS_CONN_MGMT_DETACHED)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_destroy_config(cmg->config);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_release_config(cmg->config);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* stop the server status/config-change monitor thread */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->procchg_started == B_TRUE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->procchg_tid != thr_self()) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->procchg_door_call == B_TRUE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth adata = sizeof (ldap_call_t) + 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ndata = sizeof (space);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth space.s_d.ldap_call.ldap_callnumber =
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth GETSTATUSCHANGE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth space.s_d.ldap_call.ldap_u.get_change.op =
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_STATUS_CHANGE_OP_STOP;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth space.s_d.ldap_call.ldap_u.get_change.cookie =
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cookie;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth sptr = &space.s_d;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = __ns_ldap_trydoorcall(&sptr, &ndata,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth &adata);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc != NS_CACHE_SUCCESS)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_INFO,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth gettext("libsldap: "
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "free_conn_mgmt():"
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth " stopping door call "
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth " GETSTATUSCHANGE failed "
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth " (rc = %d)"), rc);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) pthread_cancel(cmg->procchg_tid);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->procchg_started = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic ns_conn_mgmt_t *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethrelease_conn_mgmt(ns_conn_mgmt_t *cmg, boolean_t unlock_cmg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (atomic_dec_uint_nv(&cmg->ref_cnt) == 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->state == NS_CONN_MGMT_DETACHED) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (unlock_cmg == B_TRUE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free_conn_mgmt(cmg);
29836b1990ff03408750301a4ad20cfd233444b9michen __s_api_free_sessionPool();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_WARNING,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth gettext("libsldap: connection management "
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth " has a refcount of zero but the state "
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth " is not DETACHED (%d)"), cmg->state);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * exposed function for initializing a connection management control structure
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethns_conn_mgmt_t *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_conn_mgmt_init()
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (thr_keycreate_once(&ns_mtckey, ns_mtckey_cleanup) != 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_WARNING, NS_CONN_MSG_NO_MTC_KEY);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (thr_keycreate_once(&ns_cmgkey, NULL) != 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_WARNING, NS_CONN_MSG_NO_CMG_KEY);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (access_conn_mgmt(NS_CONN_MGMT_OP_LIB_INIT));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* initialize a connection user */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethns_conn_user_t *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_conn_user_init(int type, void *userinfo, boolean_t referral)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_user_t *cu;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* delete the reference to the previously used conn_mgmt */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) thr_setspecific(ns_cmgkey, NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = access_conn_mgmt(NS_CONN_MGMT_OP_REF);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->state != NS_CONN_MGMT_ACTIVE &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->state != NS_CONN_MGMT_INACTIVE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth atomic_dec_uint(&cmg->ref_cnt);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu = (ns_conn_user_t *)calloc(1, sizeof (*cu));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth atomic_dec_uint(&cmg->ref_cnt);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->type = type;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->state = NS_CONN_USER_ALLOCATED;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->tid = thr_self();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->userinfo = userinfo;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->referral = referral;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->ns_rc = NS_LDAP_SUCCESS;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->conn_mgmt = cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) conn_tsd_setup(cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (cu);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Free the resources used by a connection user.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * The caller should ensure this conn_user is
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * not associated with any conn_mt, i.e.,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * not in any conn_mt's linked list of conn_users.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * The caller needs to free the userinfo member
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * as well.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_conn_user_free(ns_conn_user_t *cu)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->state = NS_CONN_USER_FREED;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu->ns_error != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) __ns_ldap_freeError(&cu->ns_error);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = cu->conn_mgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth conn_tsd_free();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) release_conn_mgmt(cmg, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) free(cu);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Initialize an MT connection control structure
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * that will be used to represent an ldap connection
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * to be shared among multiple threads and to hold
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * and manage all the conn_users using the ldap
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * connection.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic ns_conn_mt_t *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethinit_conn_mt(ns_conn_mgmt_t *cmg, ns_ldap_error_t **ep)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg_a;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm = (ns_conn_mt_t *)calloc(1, sizeof (*cm));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (ep != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *ep = __s_api_make_error(NS_LDAP_MEMORY, NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg_a = access_conn_mgmt(NS_CONN_MGMT_OP_REF);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg_a != cmg) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg_a != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) release_conn_mgmt(cmg_a, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (ep != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *ep = __s_api_make_error(NS_LDAP_OP_FAILED,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MSG_SHUTDOWN_RELOADED);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_init(&cm->lock, USYNC_THREAD, NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->state = NS_CONN_MT_CONNECTING;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->tid = thr_self();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->pid = getpid();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->next = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_head = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_tail = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->conn = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->conn_mgmt = cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Free an MT connection control structure, assume conn_mgmt is locked.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * 'unlock_cmg' is passed to release_conn_mgmt() to indicate the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * cmg needs to be unlocked or not.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic ns_conn_mgmt_t *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethfree_conn_mt(ns_conn_mt_t *cm, int unlock_cmg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->ns_error != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) __ns_ldap_freeError(&cm->ns_error);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->conn != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->conn->ld != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) ldap_unbind(cm->conn->ld);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_freeConnection(cm->conn);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = cm->conn_mgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (release_conn_mgmt(cmg, unlock_cmg));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* add a connection user to an MT connection */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethadd_cu2cm(ns_conn_user_t *cu, ns_conn_mt_t *cm)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->cu_head == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_head = cu;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_tail = cu;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_tail->next = cu;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_tail = cu;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_cnt++;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* add an MT connection to the connection management */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethadd_cm2cmg(ns_conn_mt_t *cm, ns_conn_mgmt_t *cmg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * add connection opened for WRITE to top of list
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * for garbage collection purpose. This is to
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * ensure the connection will be closed after a
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * certain amount of time (60 seconds).
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->cm_head == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cm_head = cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cm_tail = cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->opened_for == NS_CONN_USER_WRITE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->next = cmg->cm_head;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cm_head = cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cm_tail->next = cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cm_tail = cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cm_cnt++;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* delete a connection user from an MT connection */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethdel_cu4cm(ns_conn_user_t *cu, ns_conn_mt_t *cm)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_user_t *pu, *u;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu == NULL || cm->cu_head == NULL || cm->cu_cnt == 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* only one conn_user on list */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->cu_head == cm->cu_tail) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu == cm->cu_head) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_head = cm->cu_tail = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_cnt = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->next = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* more than one and cu is the first one */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu == cm->cu_head) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_head = cu->next;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_cnt--;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->next = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pu = cm->cu_head;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (u = cm->cu_head->next; u; u = u->next) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu == u)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pu = u;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (pu != cm->cu_tail) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pu->next = cu->next;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (pu->next == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_tail = pu;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_cnt--;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->next = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_INFO, gettext(
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: del_cu4cm(): connection user not found"));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* delete an MT connection from the connection management control structure */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethdel_cm4cmg(ns_conn_mt_t *cm, ns_conn_mgmt_t *cmg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *pm, *m;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm == NULL || cmg->cm_head == NULL || cmg->cm_cnt == 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* only one conn_mt on list */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->cm_head == cmg->cm_tail) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm == cmg->cm_head) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cm_head = cmg->cm_tail = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cm_cnt = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->next = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* more than one and cm is the first one */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm == cmg->cm_head) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cm_head = cm->next;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cm_cnt--;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->next = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pm = cmg->cm_head;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (m = cmg->cm_head->next; m; m = m->next) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm == m)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pm = m;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (pm != cmg->cm_tail) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pm->next = cm->next;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (pm->next == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cm_tail = pm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->cm_cnt--;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->next = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_INFO, gettext(
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth "libsldap: del_cm4cmg(): MT connection not found"));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * compare to see if the server and credential for authentication match
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * those used by an MT connection
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic boolean_t
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethis_server_cred_matched(const char *server, const ns_cred_t *cred,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *cm)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth Connection *cp = cm->conn;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* check server first */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (server != NULL && *server != 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (strcasecmp(server, cp->serverAddr) != 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cred == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_TRUE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* then check cred */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (__s_api_is_auth_matched(cp->auth, cred));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Wait until a pending MT connection becomes available.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Return 1 if so, 0 if error.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Assume the current conn_mgmt and the input conn_mt
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * are locked.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethwait_for_conn_mt(ns_conn_user_t *cu, ns_conn_mt_t *cm)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->state = NS_CONN_USER_WAITING;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth add_cu2cm(cu, cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->conn_mt = cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * It could take some time so we don't want to hold
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * cm->conn_mgmt across the wait
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&(cm->conn_mgmt)->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* check one more time see if need to wait */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->state == NS_CONN_MT_CONNECTING) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) conn_wait(cm, cu);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* cm->lock is locked again at this point */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->state = NS_CONN_USER_WOKEUP;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->state == NS_CONN_MT_CONNECTED)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (1);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth del_cu4cm(cu, cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->conn_mt = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->bad_mt_conn = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Check and see if the input MT connection '*cm' should be closed.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * In two cases, it should be closed. If a preferred server is
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * found to be up when ldap_cachemgr is queried and reported back.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Or when the server being used for the connection is found to
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * be down. Return B_FALSE if the connection is not closed (or not marked
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * to be closed), otherwise unlock mutex (*cm)->lock and return B_TRUE.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * This function assumes conn_mgmt cmg and conn_mt *cm are locked.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic boolean_t
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethcheck_and_close_conn(ns_conn_mgmt_t *cmg, ns_conn_mt_t **cm,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_user_t *cu) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int j;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int svridx = -1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int upidx = -1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int free_cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_server_info_t sinfo;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t *errorp = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * check only if preferred servers are defined
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->pservers_loaded == B_FALSE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth get_preferred_servers(B_FALSE, B_FALSE, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->pservers == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * ask ldap_cachemgr for the first available server
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = __s_api_requestServer(NS_CACHE_NEW, NULL,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth &sinfo, &errorp, NS_CACHE_ADDR_IP);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc != NS_LDAP_SUCCESS || sinfo.server == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) __ns_ldap_freeError(&errorp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Did ldap_cachemgr return a preferred server ?
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (j = 0; cmg->pservers[j] != NULL; j++) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (strcasecmp(sinfo.server, cmg->pservers[j]) != 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth upidx = j;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Is the server being used a preferred one ?
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (j = 0; cmg->pservers[j] != NULL; j++) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (strcasecmp(cmg->pservers[j], (*cm)->conn->serverAddr) != 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth svridx = j;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Need to fall back to a down-but-now-up preferred server ?
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * A preferred server falls back to a more preferred one.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * A regular one falls back to any preferred ones. So if
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * both are preferred ones and same index, or both
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * are not preferred ones, then no need to close the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * connection.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((upidx == -1 && svridx == -1) ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (upidx != -1 && svridx != -1 && upidx == svridx)) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_free_server_info(&sinfo);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * otherwise, 4 cases, all may need to close the connection:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * For case 1 and 2, both servers are preferred ones:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * 1. ldap_cachemgr returned a better one to use (upidx < svridx)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * 2. the server being used is down (upidx > svridx)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * 3. ldap_cachemgr returned a preferred one, but the server
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * being used is not, so need to fall back to the preferred server
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * 4. ldap_cachemgr returned a non-preferred one, but the server
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * being used is a preferred one, so it must be down (since
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * ldap_cachemgr always returns a preferred one when possible).
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * For case 1 & 3, close the READ connection when no user uses it.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * For 2 and 4, close the connection with error rc, LDAP_SERVER_DOWN.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (upidx != -1 && (svridx == -1 || upidx < svridx)) { /* case 1 & 3 */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* fallback does not make sense for WRITE/referred connection */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((*cm)->opened_for == NS_CONN_USER_WRITE ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (*cm)->referral == B_TRUE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_free_server_info(&sinfo);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free_cm = close_conn_mt_when_nouser(*cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->shutting_down == B_FALSE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->retry = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t *ep;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ep = __s_api_make_error(LDAP_SERVER_DOWN,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MSG_DOWN_FROM_CACHEMGR);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* cu has not been attached to cm yet, use NULL as cu pointer */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free_cm = close_conn_mt(*cm, LDAP_SERVER_DOWN, &ep, NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->shutting_down == B_FALSE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->retry = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) __ns_ldap_freeError(&ep);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&(*cm)->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (free_cm == 1) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) free_conn_mt(*cm, 0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *cm = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_free_server_info(&sinfo);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_TRUE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Check to see if a conn_mt matches the connection criteria from
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * a conn_user. Return B_TRUE if yes, B_FALSE, otherwise. The input
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * conn_mt pointer (*cmt) may be freed and *cmt will be set to NULL
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * to indicate so.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * conn_mt *cmt and conn_mgmt cm->conn_mgmt are assumed locked.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * cm->lock is unlocked at exit if rc is B_FALSE.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic boolean_t
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethmatch_conn_mt(ns_conn_user_t *cu, ns_conn_mt_t **cmt,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_state_t st, const char *server,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth const ns_cred_t *cred)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t matched = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t drop_conn;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int free_cm = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *cm = *cmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg = cm->conn_mgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->state != st || cm->close_when_nouser == B_TRUE ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->detached == B_TRUE || cm->pid != getpid() ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->referral != cu->referral) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * if a conn_mt opened for WRITE is idle
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * long enough, then close it. To improve
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the performance of applications, such
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * as ldapaddent, a WRITE connection is
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * given a short time to live in the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * connection pool, expecting the write
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * requests to come in a quick succession.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * To save resource, the connection will
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * be closed if idle more than 60 seconds.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->opened_for == NS_CONN_USER_WRITE &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->type != NS_CONN_USER_WRITE && cm->cu_cnt == 0 &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ((time(NULL) - cm->access_time) > 60)) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * NS_LDAP_INTERNAL is irrelevant here. There no
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * conn_user to consume the rc
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free_cm = close_conn_mt(cm, NS_LDAP_INTERNAL, NULL, NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (free_cm == 1) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) free_conn_mt(cm, 0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *cmt = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth switch (cu->type) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth case NS_CONN_USER_SEARCH:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth case NS_CONN_USER_GETENT:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->opened_for == NS_CONN_USER_SEARCH ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->opened_for == NS_CONN_USER_GETENT)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth matched = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth case NS_CONN_USER_WRITE:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->opened_for == NS_CONN_USER_WRITE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth matched = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth default:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth matched = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (matched == B_TRUE && ((server != NULL || cred != NULL) &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth is_server_cred_matched(server, cred, cm) == B_FALSE))
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth matched = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (matched != B_FALSE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Check and drop the 'connected' connection if
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * necessary. Main nscd gets status changes from
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the ldap_cachemgr daemon directly via the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * GETSTATUSCHANGE door call, the standalone
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * function works in a no ldap_cachemgr environment,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * so no need to check and drop connections.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->state == NS_CONN_MT_CONNECTED &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->is_nscd == B_FALSE && !__s_api_isStandalone()) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth drop_conn = check_and_close_conn(cmg, &cm, cu);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (drop_conn == B_TRUE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *cmt = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* check if max. users using or waiting for the connection */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((cm->state == NS_CONN_MT_CONNECTED &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_max != NS_CONN_MT_USER_NO_MAX &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_cnt >= cm->cu_max) ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (cm->state == NS_CONN_MT_CONNECTING &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_max != NS_CONN_MT_USER_NO_MAX &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->waiter_cnt >= cm->cu_max - 1))
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth matched = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (matched == B_FALSE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (matched);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * obtain an MT connection from the connection management for a conn_user
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Input:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * server : server name or IP address
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * flags : libsldap API flags
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * cred : pointer to the user credential
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * cu : pointer to the conn_user structure
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Output:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * session : hold pointer to the Connection structure
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * errorp : hold pointer to error info (ns_ldap_error_t)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_conn_mt_get(const char *server, const int flags, const ns_cred_t *cred,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth Connection **session, ns_ldap_error_t **errorp, ns_conn_user_t *cu)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int i;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *cn;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_state_t st;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (errorp == NULL || cu == NULL || session == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_INVALID_PARAM);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *session = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = cu->conn_mgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * for pam_ldap, always try opening a new connection
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu->type == NS_CONN_USER_AUTH)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_NOTFOUND);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* if need a new conn, then don't reuse */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (flags & NS_LDAP_NEW_CONN)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_NOTFOUND);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (flags & NS_LDAP_KEEP_CONN)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->keep_conn = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * We want to use MT connection only if keep-connection flag is
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * set or if MT was requested (or active)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (!((cmg->state == NS_CONN_MGMT_INACTIVE &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->keep_conn == B_TRUE) || cmg->state == NS_CONN_MGMT_ACTIVE))
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_NOTFOUND);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* MT connection will be used now (if possible/available) */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->use_mt_conn = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_CHECK_ABORT_AND_LOCK(cmg, cu, errorp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* first look for a connection already open */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth st = NS_CONN_MT_CONNECTED;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->state = NS_CONN_USER_FINDING;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (i = 0; i < 2; i++) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (cn = cmg->cm_head; cn; cn = cn->next) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cn->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = match_conn_mt(cu, &cn, st, server, cred);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc == B_FALSE && cn != NULL) /* not found */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cn == NULL) { /* not found and cn freed */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * as the conn_mt list could
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * be different due to cn's
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * deletion, scan the entire
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * conn_mt list again
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth st = NS_CONN_MT_CONNECTED;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth i = -1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* return a connected one if found */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cn->state == NS_CONN_MT_CONNECTED) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *session = cn->conn;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth add_cu2cm(cu, cn);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->conn_mt = cn;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->state = NS_CONN_USER_CONNECTED;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cn->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_SUCCESS);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * if cn is not connecting, or allow only
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * one user, skip it
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cn->state != NS_CONN_MT_CONNECTING ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cn->cu_max == 1) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cn->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* wait for the connecting conn_mt */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (wait_for_conn_mt(cu, cn) != 1) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * NS_LDAP_NOTFOUND signals that the function
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * __s_api_check_libldap_MT_conn_support()
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * detected that the lower libldap library
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * does not support MT connection, so return
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * NS_LDAP_NOTFOUND to let the caller to
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * open a non-MT conneciton. Otherwise,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * connect error occurred, return
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * NS_CONN_USER_CONNECT_ERROR
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cn->ns_rc != NS_LDAP_NOTFOUND)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->state = NS_CONN_USER_CONNECT_ERROR;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->state = NS_CONN_USER_FINDING;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->use_mt_conn = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cn->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* cmg->lock unlocked by wait_for_conn_mt() */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (cn->ns_rc);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* return the newly available conn_mt */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *session = cn->conn;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->state = NS_CONN_USER_CONNECTED;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cn->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* cmg->lock unlocked by wait_for_conn_mt() */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_SUCCESS);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* next, look for a connecting conn_mt */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (i == 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth st = NS_CONN_MT_CONNECTING;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* no connection found, start opening one */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cn = init_conn_mt(cmg, errorp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cn == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return ((*errorp)->status);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->conn_mt = cn;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cn->opened_for = cu->type;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cn->referral = cu->referral;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->ldap_mt == B_TRUE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cn->cu_max = NS_CONN_MT_USER_MAX;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cn->cu_max = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth add_cm2cmg(cn, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_NOTFOUND);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * add an MT connection to the connection management
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Input:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * con : pointer to the Connection info
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * cu : pointer to the conn_user structure
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Output:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * ep : hold pointer to error info (ns_ldap_error_t)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_conn_mt_add(Connection *con, ns_conn_user_t *cu, ns_ldap_error_t **ep)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg = cu->conn_mgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *cm = cu->conn_mt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* if the conn_mgmt is being shut down, return error */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_CHECK_ABORT_AND_LOCK(cmg, cu, ep);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * start the change monitor thread only if it
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * hasn't been started and the process is the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * main nscd (not peruser nscd)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->procchg_started == B_FALSE && cmg->is_nscd == B_TRUE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth start_thread(cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->procchg_started = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->conn = con;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->state = NS_CONN_MT_CONNECTED;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->pid = getpid();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->create_time = time(NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->access_time = cm->create_time;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->opened_for = cu->type;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth add_cu2cm(cu, cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->conn_mt = cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->state = NS_CONN_USER_CONNECTED;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->ldap_mt == B_TRUE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_max = NS_CONN_MT_USER_MAX;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->cu_max = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* wake up the waiters if any */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) conn_signal(cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_SUCCESS);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
ca190d8debe6672d99069a376a987adee0765d6cmichen * return an MT connection to the pool when a conn user is done using it
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Input:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * cu : pointer to the conn_user structure
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Output: NONE
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_conn_mt_return(ns_conn_user_t *cu)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu == NULL || cu->use_mt_conn == B_FALSE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm = cu->conn_mt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = cu->conn_mgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth del_cu4cm(cu, cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->state = NS_CONN_USER_DISCONNECTED;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->conn_mt = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->bad_mt_conn = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * if this MT connection is no longer needed, or not usable, and
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * no more conn_user uses it, then close it.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((cm->close_when_nouser == B_TRUE ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->state != NS_CONN_MT_CONNECTED) && cm->cu_cnt == 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth del_cm4cmg(cm, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* use ns_conn_free (instead of 1) to avoid lint warning */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_UNLOCK_AND_FREE(ns_conn_free, cm, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->state == NS_CONN_MT_CONNECTED && cm->cu_cnt == 0 &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->conn != NULL && cm->conn->ld != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth struct timeval zerotime;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth LDAPMessage *res;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth zerotime.tv_sec = zerotime.tv_usec = 0L;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* clean up remaining results just in case */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth while (ldap_result(cm->conn->ld, LDAP_RES_ANY,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth LDAP_MSG_ALL, &zerotime, &res) > 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (res != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) ldap_msgfree(res);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* save error info (rc and ns_ldap_error_t) in the conn_mt */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57etherr2cm(ns_conn_mt_t *cm, int rc, ns_ldap_error_t **errorp) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t *ep;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->ns_rc = rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->ns_error = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (errorp != NULL && *errorp != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ep = __s_api_copy_error(*errorp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (ep == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->ns_rc = NS_LDAP_MEMORY;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->ns_error = ep;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* copy error info (rc and ns_ldap_error_t) from conn_mt to conn_user */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57etherr_from_cm(ns_conn_user_t *cu, ns_conn_mt_t *cm) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t *ep;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->ns_rc = cm->ns_rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu->ns_error != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) __ns_ldap_freeError(&cu->ns_error);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->ns_error = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->ns_rc != NS_LDAP_SUCCESS && cm->ns_error != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ep = __s_api_copy_error(cm->ns_error);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (ep == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->ns_rc = NS_LDAP_MEMORY;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->ns_error = ep;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* copy error info (rc and ns_ldap_error_t) from caller to conn_user */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57etherr_from_caller(ns_conn_user_t *cu, int rc, ns_ldap_error_t **errorp) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->ns_rc = rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (errorp != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu->ns_error != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) __ns_ldap_freeError(&cu->ns_error);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->ns_error = *errorp;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *errorp = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->ns_error = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * remove an MT connection from the connection management when failed to open
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Input:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * cu : pointer to the conn_user structure
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * rc : error code
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * errorp : pointer to pointer to error info (ns_ldap_error_t)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Output:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * errorp : set to NULL, if none NULL cm, callers do not need to free it
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_conn_mt_remove(ns_conn_user_t *cu, int rc, ns_ldap_error_t **errorp)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int free_cm = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu == NULL || cu->use_mt_conn == B_FALSE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((cm = cu->conn_mt) == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = cu->conn_mgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->state != NS_CONN_MT_CONNECT_ERROR) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->state = NS_CONN_MT_CONNECT_ERROR;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->ns_rc = rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (errorp != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->ns_error = *errorp;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *errorp = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* all the conn_users share the same error rc and ns_ldap_error_t */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth err_from_cm(cu, cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* wake up the waiters if any */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) conn_signal(cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth del_cu4cm(cu, cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->conn_mt = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->bad_mt_conn = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->cu_cnt == 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth del_cm4cmg(cm, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free_cm = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_UNLOCK_AND_FREE(free_cm, cm, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * check to see if the underlying libldap supports multi-threaded client
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * (MT connections)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_check_libldap_MT_conn_support(ns_conn_user_t *cu, LDAP *ld,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t **ep)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* if no need to check, just return success */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu->conn_mt == NULL || cu->use_mt_conn == B_FALSE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_SUCCESS);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = cu->conn_mgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = setup_mt_ld(ld, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->do_mt_conn == B_FALSE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If the conn_mgmt is being shut down, return error.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * if cmg is usable, cmg->lock will be locked. Otherwise,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * this function will return with rc NS_LDAP_OP_FAILED.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_CHECK_ABORT_AND_LOCK(cmg, cu, ep);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->do_mt_conn == B_FALSE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc < 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->ldap_mt = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->ldap_mt = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->is_nscd == B_TRUE ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->is_peruser_nscd == B_TRUE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->do_mt_conn = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->state = NS_CONN_MGMT_ACTIVE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc < 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_conn_mt_remove(cu, NS_LDAP_NOTFOUND, NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_SUCCESS);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Close an MT connection.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Assume cm not null and locked, assume conn_mgmt is also locked.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Return -1 if error, 1 if the cm should be freed, otherwise 0.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethclose_conn_mt(ns_conn_mt_t *cm, int rc, ns_ldap_error_t **errorp,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_user_t *cu)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg = cm->conn_mgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *m;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_user_t *u;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((cm->state != NS_CONN_MT_CONNECTED && cm->state !=
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MT_CLOSING) || cmg->cm_head == NULL || cmg->cm_cnt == 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (-1);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* if the conn_mt is not in the MT connection pool, nothing to do */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (m = cmg->cm_head; m; m = m->next) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm == m)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (m == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (-1);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->state == NS_CONN_MT_CONNECTED) { /* first time in here */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->state = NS_CONN_MT_CLOSING;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If more cu exist to consume the error info, copy
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * it to the cm. If the caller calls on behalf of
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * a cu, cu won't be NULL. Check to see if there's
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * more cu that needs the error info. If caller does
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * not have a specific cu attached to it (e.g.,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * shutdown_all_conn_mt()), cu is NULL, check if at
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * least one cu exists.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((cu != NULL && cm->cu_cnt > 1) ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (cu == NULL && cm->cu_cnt > 0)) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth err2cm(cm, rc, errorp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* wake up waiter (conn_user) if any */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) conn_signal(cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* for each conn_user using the conn_mt, set bad_mt_conn flag */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->cu_head != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (u = cm->cu_head; u; u = u->next) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth u->bad_mt_conn = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->shutting_down == B_FALSE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth u->retry = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* detach the conn_mt if no more conn_user left */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((cu != NULL && cm->cu_cnt == 1) ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (cu == NULL && cm->cu_cnt == 0)) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth del_cm4cmg(cm, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->detached = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (1);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * An MT connection becomes bad, close it and free resources.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * This function is called with a ns_conn_user_t representing
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * a user of the MT connection.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Input:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * cu : pointer to the conn_user structure
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * rc : error code
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * errorp : pointer to pointer to error info (ns_ldap_error_t)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Output:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * errorp : set to NULL (if no error), callers do not need to free it
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_conn_mt_close(ns_conn_user_t *cu, int rc, ns_ldap_error_t **errorp)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int free_cm = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu == NULL || cu->use_mt_conn == B_FALSE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu->state != NS_CONN_USER_CONNECTED || (cm = cu->conn_mt) == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = cu->conn_mgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* close the MT connection if possible */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free_cm = close_conn_mt(cm, rc, errorp, cu);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (free_cm == -1) { /* error case */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc != NS_LDAP_SUCCESS) { /* error info passed in, use it */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth err_from_caller(cu, rc, errorp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else { /* error not passed in, use those saved in the conn_mt */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth err_from_cm(cu, cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* detach the conn_user from the conn_mt */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth del_cu4cm(cu, cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->conn_mt = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->bad_mt_conn = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->shutting_down == B_FALSE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->retry = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_UNLOCK_AND_FREE(free_cm, cm, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Close an MT connection when the associated server is known to be
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * down. This function is called with a ns_conn_mt_t representing
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the MT connection. That is, the caller is not a conn_user
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * thread but rather the procchg thread.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethclose_conn_mt_by_procchg(ns_conn_mt_t *cm, int rc, char *errmsg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int free_cm = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t *ep;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = cm->conn_mgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ep = (ns_ldap_error_t *)calloc(1, sizeof (*ep));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (ep != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ep->status = rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (errmsg != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ep->message = strdup(errmsg); /* OK if returns NULL */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* close the MT connection if possible */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free_cm = close_conn_mt(cm, LDAP_SERVER_DOWN, &ep, NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (free_cm == -1) { /* error case */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) __ns_ldap_freeError(&ep);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_UNLOCK_AND_FREE(free_cm, cm, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Close an MT connection when there is a better server to connect to.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Mark the connection as to-be-closed-when-no-one-using so that
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * any outstanding ldap operations can run to completion.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Assume that both the conn_mt and conn_mgmt are locked.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Return 1 if the conn_mt should be freed.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethclose_conn_mt_when_nouser(ns_conn_mt_t *cm)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int free_cm = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->cu_cnt == 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth del_cm4cmg(cm, cm->conn_mgmt);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free_cm = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->close_when_nouser = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (free_cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Retrieve the configured preferred server list.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * This function locked the conn_mgmt and does not
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * unlock at exit.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethget_preferred_servers(boolean_t lock, boolean_t reload, ns_conn_mgmt_t *cmg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t *errorp = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth void **pservers = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (lock == B_TRUE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* if already done, and no reload, then return */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->pservers_loaded == B_TRUE && reload == B_FALSE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->pservers != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) __ns_ldap_freeParam((void ***)&cmg->pservers);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->pservers = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (__ns_ldap_getParam(NS_LDAP_SERVER_PREF_P,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth &pservers, &errorp) == NS_LDAP_SUCCESS) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->pservers = (char **)pservers;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->pservers_loaded = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) __ns_ldap_freeError(&errorp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) __ns_ldap_freeParam(&pservers);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * This function handles the config or server status change notification
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * from the ldap_cachemgr.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic ns_conn_mgmt_t *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethproc_server_change(ns_server_status_change_t *chg, ns_conn_mgmt_t *cmg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int cnt, i, j, k, n;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t loop = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t cmg_locked = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char *s;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *ocmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* if config changed, reload the configuration */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (chg->config_changed == B_TRUE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* reload the conn_mgmt and Native LDAP config */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ocmg = access_conn_mgmt(NS_CONN_MGMT_OP_RELOAD_CONFIG);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth shutdown_all_conn_mt(ocmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* release the one obtained from access_conn_mgmt(RELOAD) */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) release_conn_mgmt(ocmg, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* release the one obtained when ocmg was created */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) release_conn_mgmt(ocmg, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (ocmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if ((cnt = chg->num_server) == 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* handle down servers first */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (i = 0; i < cnt; i++) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (chg->changes[i] != NS_SERVER_DOWN)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth s = chg->servers[i];
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * look for a CONNECTED MT connection using
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the same server s, and close it
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth while (loop) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg_locked == B_FALSE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg_locked = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (cm = cmg->cm_head; cm; cm = cm->next) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->state == NS_CONN_MT_CONNECTED &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->conn != NULL &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth strcasecmp(cm->conn->serverAddr, s) == 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg_locked = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth close_conn_mt_by_procchg(cm, LDAP_SERVER_DOWN,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MSG_DOWN_FROM_CACHEMGR);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Process the next cm using server s.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Start from the head of the cm linked
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * list again, as the cm list may change
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * after close_conn_mt_by_procchg() is done.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * No (more) MT connection using the down server s.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Process the next server on the list.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } /* while loop */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Next handle servers whose status changed to up.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Get the preferred server list first if not done yet.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * get_preferred_servers() leaves conn_mgmt locked.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth get_preferred_servers(cmg_locked == B_FALSE ? B_TRUE : B_FALSE,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth B_FALSE, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg_locked = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * if no preferred server configured, we don't switch MT connection
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * to a more preferred server (i.e., fallback), so just return
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->pservers == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* for each server that is up now */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (i = 0; i < cnt; i++) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (chg->changes[i] != NS_SERVER_UP)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth s = chg->servers[i];
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * look for a CONNECTED MT connection which uses
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * a server less preferred than s, and treat it
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * as 'fallback needed' by calling
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * close_conn_mt_when_nouser()
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth k = -1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth loop = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth while (loop) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg_locked == B_FALSE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg_locked = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* Is s a preferred server ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (k == -1) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (j = 0; cmg->pservers[j] != NULL; j++) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (strcasecmp(cmg->pservers[j],
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth s) == 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth k = j;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* skip s if not a preferred server */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (k == -1) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* check each MT connection */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (cm = cmg->cm_head; cm; cm = cm->next) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Find an MT connection that is connected and
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * not marked, but leave WRITE or REFERRAL
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * connections alone, since fallback does not
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * make sense for them.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->state == NS_CONN_MT_CONNECTED &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->close_when_nouser == B_FALSE &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->conn != NULL && cm->opened_for !=
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_WRITE &&
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->referral == B_FALSE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth n = -1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * j < k ??? should we close
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * an active MT that is using s ?
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * ie could s went down and up
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * again, but cm is bound prior to
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the down ? Play safe here,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * and check j <= k.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (j = 0; j <= k; j++) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (strcasecmp(
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm->conn->serverAddr,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->pservers[j]) == 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth n = j;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * s is preferred, if its location
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * in the preferred server list is
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * ahead of that of the server
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * used by the cm (i.e., no match
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * found before s)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (n == -1) { /* s is preferred */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int fr = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth fr = close_conn_mt_when_nouser(
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_UNLOCK_AND_FREE(fr,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cm, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg_locked = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * break, not continue,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * because we need to
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * check the entire cm
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * list again. The call
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * above may change the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * cm list.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* if no (more) cm using s, check next server */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth loop = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } /* while loop */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg_locked == B_TRUE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* Shut down all MT connection managed by the connection management */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethshutdown_all_conn_mt(ns_conn_mgmt_t *cmg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t *ep;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *cm;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int free_cm = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t done = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ep = (ns_ldap_error_t *)calloc(1, sizeof (*ep));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (ep != NULL) { /* if NULL, not a problem */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* OK if returns NULL */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ep->message = strdup(NS_CONN_MSG_SHUTDOWN_RELOADED);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth while (cmg->cm_head != NULL && done == B_FALSE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (cm = cmg->cm_head; cm; cm = cm->next) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_lock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cm->next == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth done = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* shut down each conn_mt, ignore errors */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free_cm = close_conn_mt(cm, LDAP_OTHER, &ep, NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cm->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (free_cm == 1) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) free_conn_mt(cm, 0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * conn_mt may change, so start from
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * top of list again
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth break;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) mutex_unlock(&cmg->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) __ns_ldap_freeError(&ep);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* free all the resources used by the connection management */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_shutdown_conn_mgmt()
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = access_conn_mgmt(NS_CONN_MGMT_OP_SHUTDOWN);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg == NULL) /* already being SHUT done */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) shutdown_all_conn_mt(cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) release_conn_mgmt(cmg, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* then destroy the conn_mgmt */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) release_conn_mgmt(cmg, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
ca190d8debe6672d99069a376a987adee0765d6cmichen * Reinitialize the libsldap connection management after
ca190d8debe6672d99069a376a987adee0765d6cmichen * a new native LDAP configuration is received.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_reinit_conn_mgmt_new_config(ns_config_t *new_cfg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *ocmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = access_conn_mgmt(NS_CONN_MGMT_OP_REF);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg == NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg->config == new_cfg || cmg->state == NS_CONN_MGMT_DETACHED) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) release_conn_mgmt(cmg, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* reload the conn_mgmt and native LDAP config */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ocmg = access_conn_mgmt(NS_CONN_MGMT_OP_NEW_CONFIG);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (ocmg == cmg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth shutdown_all_conn_mt(ocmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* release the one obtained from access_conn_mgmt(RELOAD) */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) release_conn_mgmt(ocmg, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* release the one obtained when ocmg was created */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) release_conn_mgmt(ocmg, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* release the one obtained when this function is entered */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) release_conn_mgmt(cmg, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Prepare to retry ldap search operation if needed.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Return 1 if retry is needed, otherwise 0.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If first time in, return 1. If not, return 1 if:
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * - not a NS_CONN_USER_GETENT conn_user AND
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * - have not retried 3 times yet AND
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * - previous search failed AND
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * - the retry flag is set in the ns_conn_user_t or config was reloaded
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_setup_retry_search(ns_conn_user_t **conn_user,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_user_type_t type, int *try_cnt, int *rc,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t **errorp)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t retry;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_user_t *cu = *conn_user;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (*try_cnt > 0 && cu != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * if called from firstEntry(), keep conn_mt for
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the subsequent getnext requests
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu->type == NS_CONN_USER_GETENT && *rc == NS_LDAP_SUCCESS)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = cu->conn_mgmt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth retry = cu->retry;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu->conn_mt != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_conn_mt_return(cu);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg != NULL && cmg->cfg_reloaded == B_TRUE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth retry = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_conn_user_free(cu);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *conn_user = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (*rc == NS_LDAP_SUCCESS || retry != B_TRUE)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *try_cnt = *try_cnt + 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (*try_cnt > NS_LIST_TRY_MAX)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *conn_user = __s_api_conn_user_init(type, NULL, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (*conn_user == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (*try_cnt == 1) { /* first call before any retry */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *rc = NS_LDAP_MEMORY;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *errorp = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* for 1+ try, use previous rc and errorp */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* free ldap_error_t from previous search */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (*try_cnt > 1 && rc != NS_LDAP_SUCCESS && *errorp != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) __ns_ldap_freeError(errorp);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (1);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* prepare to get the next entry for an enumeration */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth__s_api_setup_getnext(ns_conn_user_t *cu, int *ns_err,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t **errorp)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * if using an MT connection, ensure the thread-specific data are set,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * but if the MT connection is no longer good, return the error saved.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu->conn_mt != NULL && (cmg = cu->conn_mgmt) != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cu->bad_mt_conn == B_TRUE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth __s_api_conn_mt_close(cu, 0, NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *ns_err = cu->ns_rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *errorp = cu->ns_error;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cu->ns_error = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (*ns_err);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth rc = conn_tsd_check(cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (rc != NS_LDAP_SUCCESS) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *errorp = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (rc);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NS_LDAP_SUCCESS);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* wait for an MT connection to become available */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethconn_wait(ns_conn_mt_t *conn_mt, ns_conn_user_t *conn_user)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_waiter_t mywait;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_waiter_t *head = &conn_mt->waiter;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) cond_init(&(mywait.waitcv), USYNC_THREAD, 0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth mywait.key = conn_user;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth mywait.signaled = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth mywait.next = head->next;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth mywait.prev = head;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (mywait.next)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth mywait.next->prev = &mywait;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth head->next = &mywait;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth atomic_inc_uint(&conn_mt->waiter_cnt);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth while (!mywait.signaled)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) cond_wait(&(mywait.waitcv), &conn_mt->lock);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (mywait.prev)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth mywait.prev->next = mywait.next;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (mywait.next)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth mywait.next->prev = mywait.prev;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (0);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* signal that an MT connection is now available */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic int
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethconn_signal(ns_conn_mt_t *conn_mt)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int c = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_waiter_t *head = &conn_mt->waiter;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_waiter_t *tmp = head->next;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth while (tmp) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) cond_signal(&(tmp->waitcv));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth tmp->signaled = 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth atomic_dec_uint(&conn_mt->waiter_cnt);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth c++;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth tmp = tmp->next;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (c);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * wait and process the server status and/or config change notification
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * from ldap_cachemgr
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethget_server_change(void *arg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth{
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth union {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_data_t s_d;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char s_b[DOORBUFFERSIZE];
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } space;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_data_t *sptr = &space.s_d;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int ndata;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int adata;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char *ptr;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int ds_cnt;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int door_rc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int which;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int retry = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t loop = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char *c, *oc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int dslen = strlen(DOORLINESEP);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char dsep = DOORLINESEP_CHR;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char chg_data[DOORBUFFERSIZE];
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char **servers = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t getchg_not_supported = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *ocmg = (ns_conn_mgmt_t *)arg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_t *cmg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_server_status_t *status = NULL;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_server_status_change_t chg = { 0 };
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_get_change_out_t *get_chg;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_get_chg_cookie_t cookie;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_get_chg_cookie_t new_cookie;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = access_conn_mgmt(NS_CONN_MGMT_OP_REF);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg != ocmg)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth thr_exit(NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* cmg is locked before called */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->procchg_tid = thr_self();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* make sure the thread specific data are set */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) conn_tsd_setup(cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cookie = cmg->cfg_cookie;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth while (loop) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (chg.servers != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(chg.servers);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (chg.changes != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(chg.changes);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (sptr != &space.s_d)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) munmap((char *)sptr, sizeof (space));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If the attached conn_mgmt has been deleted,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * then exit. The new conn_mgmt will starts it
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * own monitor thread later. If libsldap is being
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * unloaded or configuration reloaded, OR
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * ldap_cachemgr rejected the GETSTATUSCHANGE door
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * call, then exit as well.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg == NULL || cmg->state == NS_CONN_MGMT_DETACHED ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth getchg_not_supported == B_TRUE) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->procchg_started = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) release_conn_mgmt(cmg, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth conn_tsd_free();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth thr_exit(NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) memset(space.s_b, 0, DOORBUFFERSIZE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) memset(&chg, 0, sizeof (chg));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth adata = sizeof (ldap_call_t) + 1;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ndata = sizeof (space);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth space.s_d.ldap_call.ldap_callnumber = GETSTATUSCHANGE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth space.s_d.ldap_call.ldap_u.get_change.op =
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_STATUS_CHANGE_OP_START;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth space.s_d.ldap_call.ldap_u.get_change.cookie = cookie;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth sptr = &space.s_d;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth door_rc = __ns_ldap_trydoorcall_getfd();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->procchg_door_call = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (release_conn_mgmt(cmg, B_FALSE) == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth conn_tsd_free();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth thr_exit(NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (door_rc == NS_CACHE_SUCCESS)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth door_rc = __ns_ldap_trydoorcall_send(&sptr, &ndata,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth &adata);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Check and see if the conn_mgmt is still current.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If not, no need to continue.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = access_conn_mgmt(NS_CONN_MGMT_OP_REF);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg != NULL)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->procchg_door_call = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg != ocmg) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (cmg != NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg->procchg_started = B_FALSE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) release_conn_mgmt(cmg, B_FALSE);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth conn_tsd_free();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth thr_exit(NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (door_rc != NS_CACHE_SUCCESS) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (door_rc == NS_CACHE_NOSERVER) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (retry++ > 10)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth getchg_not_supported = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * ldap_cachemgr may be down, give
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * it time to restart
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) sleep(2);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else if (door_rc == NS_CACHE_NOTFOUND)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth getchg_not_supported = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth retry = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* copy info from door call return structure */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth get_chg = &sptr->ldap_ret.ldap_u.changes;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ptr = get_chg->data;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* configuration change ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (get_chg->type == NS_STATUS_CHANGE_TYPE_CONFIG) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg.config_changed = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = proc_server_change(&chg, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* server status changes ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (get_chg->type == NS_STATUS_CHANGE_TYPE_SERVER) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * first check cookies, if don't match, config
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * has changed
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth new_cookie = get_chg->cookie;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (new_cookie.mgr_pid != cookie.mgr_pid ||
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth new_cookie.seq_num != cookie.seq_num) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg.config_changed = B_TRUE;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = proc_server_change(&chg, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void) strlcpy(chg_data, ptr, sizeof (chg_data));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg.num_server = get_chg->server_count;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth servers = (char **)calloc(chg.num_server,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth sizeof (char *));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (servers == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_INFO, NS_CONN_MSG_MEMORY_ERROR);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth status = (ns_server_status_t *)calloc(chg.num_server,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth sizeof (int));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (status == NULL) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_INFO, NS_CONN_MSG_MEMORY_ERROR);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth free(servers);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ds_cnt = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth which = 0;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth oc = ptr;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth for (c = ptr; which != 2; c++) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* look for DOORLINESEP or end of string */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (*c != dsep && *c != '\0')
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (*c == dsep) { /* DOORLINESEP */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *c = '\0'; /* current value */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth c += dslen; /* skip to next value */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (which == 0) { /* get server info */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth servers[ds_cnt] = oc;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth oc = c;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth which = 1; /* get status next */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* which == 1, get up/down status */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (strcmp(NS_SERVER_CHANGE_UP, oc) == 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth status[ds_cnt] = NS_SERVER_UP;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth } else if (strcmp(NS_SERVER_CHANGE_DOWN,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth oc) == 0)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth status[ds_cnt] = NS_SERVER_DOWN;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_INFO,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MSG_BAD_CACHEMGR_DATA);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth oc = c;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ds_cnt++;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (*c == '\0')
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth which = 2; /* exit the loop */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth else
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth which = 0; /* get server info next */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg.servers = servers;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth chg.changes = status;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cmg = proc_server_change(&chg, cmg);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth continue;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth return (NULL);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/* start the thread handling the change notification from ldap_cachemgr */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstatic void
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstart_thread(ns_conn_mgmt_t *cmg) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int errnum;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * start a thread to get and process config and server status changes
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth if (thr_create(NULL, NULL, get_server_change,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth (void *)cmg, THR_DETACHED, NULL) != 0) {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth errnum = errno;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth syslog(LOG_WARNING, NS_CONN_MSG_NO_PROCCHG_THREAD,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth strerror(errnum));
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth }
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}