1cb5caa98Sdjl /* 2cb5caa98Sdjl * CDDL HEADER START 3cb5caa98Sdjl * 4cb5caa98Sdjl * The contents of this file are subject to the terms of the 5cb5caa98Sdjl * Common Development and Distribution License (the "License"). 6cb5caa98Sdjl * You may not use this file except in compliance with the License. 7cb5caa98Sdjl * 8cb5caa98Sdjl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9cb5caa98Sdjl * or http://www.opensolaris.org/os/licensing. 10cb5caa98Sdjl * See the License for the specific language governing permissions 11cb5caa98Sdjl * and limitations under the License. 12cb5caa98Sdjl * 13cb5caa98Sdjl * When distributing Covered Code, include this CDDL HEADER in each 14cb5caa98Sdjl * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15cb5caa98Sdjl * If applicable, add the following below this CDDL HEADER, with the 16cb5caa98Sdjl * fields enclosed by brackets "[]" replaced with your own identifying 17cb5caa98Sdjl * information: Portions Copyright [yyyy] [name of copyright owner] 18cb5caa98Sdjl * 19cb5caa98Sdjl * CDDL HEADER END 20cb5caa98Sdjl */ 21cb5caa98Sdjl /* 22*29836b19Smichen * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23cb5caa98Sdjl * Use is subject to license terms. 24cb5caa98Sdjl */ 25cb5caa98Sdjl 26cb5caa98Sdjl #pragma ident "%Z%%M% %I% %E% SMI" 27cb5caa98Sdjl 28cb5caa98Sdjl #include <stdlib.h> 29cb5caa98Sdjl #include <assert.h> 30cb5caa98Sdjl #include <string.h> 31cb5caa98Sdjl #include <errno.h> 32cb5caa98Sdjl #include <fcntl.h> 33cb5caa98Sdjl #include "nscd_db.h" 34cb5caa98Sdjl #include "nscd_log.h" 35cb5caa98Sdjl #include "nscd_switch.h" 36cb5caa98Sdjl #include "nscd_door.h" 37cb5caa98Sdjl 38cb5caa98Sdjl extern int _whoami; 39cb5caa98Sdjl static mutex_t getent_monitor_mutex = DEFAULTMUTEX; 40cb5caa98Sdjl static int getent_monitor_started = 0; 41cb5caa98Sdjl 42cb5caa98Sdjl static rwlock_t getent_ctxDB_rwlock = DEFAULTRWLOCK; 43cb5caa98Sdjl static nscd_db_t *getent_ctxDB = NULL; 44cb5caa98Sdjl 45cb5caa98Sdjl /* 46cb5caa98Sdjl * internal structure representing a nscd getent context 47cb5caa98Sdjl */ 48cb5caa98Sdjl typedef struct nscd_getent_ctx { 49cb5caa98Sdjl int to_delete; /* this ctx no longer valid */ 50cb5caa98Sdjl nscd_getent_context_t *ptr; 51e37190e5Smichen nscd_cookie_num_t cookie_num; 52cb5caa98Sdjl } nscd_getent_ctx_t; 53cb5caa98Sdjl 54cb5caa98Sdjl /* 55cb5caa98Sdjl * nscd_getent_context_t list for each nss database. Protected 56cb5caa98Sdjl * by the readers/writer lock nscd_getent_ctx_lock. 57cb5caa98Sdjl */ 58cb5caa98Sdjl nscd_getent_ctx_base_t **nscd_getent_ctx_base; 59cb5caa98Sdjl static rwlock_t nscd_getent_ctx_base_lock = DEFAULTRWLOCK; 60cb5caa98Sdjl 61cb5caa98Sdjl extern nscd_db_entry_t *_nscd_walk_db(nscd_db_t *db, void **cookie); 62cb5caa98Sdjl 63cb5caa98Sdjl static nscd_rc_t _nscd_init_getent_ctx_monitor(); 64cb5caa98Sdjl 65cb5caa98Sdjl /* 66cb5caa98Sdjl * FUNCTION: _nscd_create_getent_ctxDB 67cb5caa98Sdjl * 68cb5caa98Sdjl * Create the internal getent context database to keep track of the 69cb5caa98Sdjl * getent contexts currently being used. 70cb5caa98Sdjl */ 71cb5caa98Sdjl nscd_db_t * 72cb5caa98Sdjl _nscd_create_getent_ctxDB() 73cb5caa98Sdjl { 74cb5caa98Sdjl 75cb5caa98Sdjl nscd_db_t *ret; 76cb5caa98Sdjl 77cb5caa98Sdjl (void) rw_wrlock(&getent_ctxDB_rwlock); 78cb5caa98Sdjl 79cb5caa98Sdjl if (getent_ctxDB != NULL) { 80cb5caa98Sdjl (void) rw_unlock(&getent_ctxDB_rwlock); 81cb5caa98Sdjl return (getent_ctxDB); 82cb5caa98Sdjl } 83cb5caa98Sdjl 84cb5caa98Sdjl ret = _nscd_alloc_db(NSCD_DB_SIZE_LARGE); 85cb5caa98Sdjl 86cb5caa98Sdjl if (ret != NULL) 87cb5caa98Sdjl getent_ctxDB = ret; 88cb5caa98Sdjl 89cb5caa98Sdjl (void) rw_unlock(&getent_ctxDB_rwlock); 90cb5caa98Sdjl 91cb5caa98Sdjl return (ret); 92cb5caa98Sdjl } 93cb5caa98Sdjl 94cb5caa98Sdjl /* 95cb5caa98Sdjl * FUNCTION: _nscd_add_getent_ctx 96cb5caa98Sdjl * 97cb5caa98Sdjl * Add a getent context to the internal context database. 98cb5caa98Sdjl */ 99cb5caa98Sdjl static nscd_rc_t 100cb5caa98Sdjl _nscd_add_getent_ctx( 101cb5caa98Sdjl nscd_getent_context_t *ptr, 102e37190e5Smichen nscd_cookie_num_t cookie_num) 103cb5caa98Sdjl { 104cb5caa98Sdjl int size; 105*29836b19Smichen char buf[32]; 106cb5caa98Sdjl nscd_db_entry_t *db_entry; 107cb5caa98Sdjl nscd_getent_ctx_t *gnctx; 108cb5caa98Sdjl 109cb5caa98Sdjl if (ptr == NULL) 110cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 111cb5caa98Sdjl 112e37190e5Smichen (void) snprintf(buf, sizeof (buf), "%lld", cookie_num); 113cb5caa98Sdjl 114cb5caa98Sdjl size = sizeof (*gnctx); 115cb5caa98Sdjl 116cb5caa98Sdjl db_entry = _nscd_alloc_db_entry(NSCD_DATA_CTX_ADDR, 117cb5caa98Sdjl (const char *)buf, size, 1, 1); 118cb5caa98Sdjl if (db_entry == NULL) 119cb5caa98Sdjl return (NSCD_NO_MEMORY); 120cb5caa98Sdjl 121cb5caa98Sdjl gnctx = (nscd_getent_ctx_t *)*(db_entry->data_array); 122cb5caa98Sdjl gnctx->ptr = ptr; 123e37190e5Smichen gnctx->cookie_num = cookie_num; 124cb5caa98Sdjl 125cb5caa98Sdjl (void) rw_wrlock(&getent_ctxDB_rwlock); 126cb5caa98Sdjl (void) _nscd_add_db_entry(getent_ctxDB, buf, db_entry, 127cb5caa98Sdjl NSCD_ADD_DB_ENTRY_FIRST); 128cb5caa98Sdjl (void) rw_unlock(&getent_ctxDB_rwlock); 129cb5caa98Sdjl 130cb5caa98Sdjl return (NSCD_SUCCESS); 131cb5caa98Sdjl } 132cb5caa98Sdjl 133cb5caa98Sdjl /* 134cb5caa98Sdjl * FUNCTION: _nscd_is_getent_ctx 135cb5caa98Sdjl * 136cb5caa98Sdjl * Check to see if a getent context can be found in the internal 137cb5caa98Sdjl * getent context database. 138cb5caa98Sdjl */ 139cb5caa98Sdjl nscd_getent_context_t * 140cb5caa98Sdjl _nscd_is_getent_ctx( 141e37190e5Smichen nscd_cookie_num_t cookie_num) 142cb5caa98Sdjl { 143*29836b19Smichen char ptrstr[32]; 144cb5caa98Sdjl const nscd_db_entry_t *db_entry; 145cb5caa98Sdjl nscd_getent_context_t *ret = NULL; 146cb5caa98Sdjl 147e37190e5Smichen (void) snprintf(ptrstr, sizeof (ptrstr), "%lld", cookie_num); 148cb5caa98Sdjl 149cb5caa98Sdjl (void) rw_rdlock(&getent_ctxDB_rwlock); 150cb5caa98Sdjl 151cb5caa98Sdjl db_entry = _nscd_get_db_entry(getent_ctxDB, NSCD_DATA_CTX_ADDR, 152cb5caa98Sdjl (const char *)ptrstr, NSCD_GET_FIRST_DB_ENTRY, 0); 153cb5caa98Sdjl 154cb5caa98Sdjl if (db_entry != NULL) { 155cb5caa98Sdjl nscd_getent_ctx_t *gnctx; 156cb5caa98Sdjl 157cb5caa98Sdjl gnctx = (nscd_getent_ctx_t *)*(db_entry->data_array); 158cb5caa98Sdjl 159cb5caa98Sdjl /* 160*29836b19Smichen * If the ctx is not to be deleted and the cookie number 161*29836b19Smichen * match, return the ctx if not aborted and not in use, 162cb5caa98Sdjl * Otherwise return NULL. 163cb5caa98Sdjl */ 164*29836b19Smichen if (gnctx->to_delete == 0 && gnctx->cookie_num == cookie_num) { 165cb5caa98Sdjl ret = gnctx->ptr; 166*29836b19Smichen (void) mutex_lock(&gnctx->ptr->getent_mutex); 167*29836b19Smichen if (ret->aborted == 1 || ret->in_use == 1) 168*29836b19Smichen ret = NULL; 169*29836b19Smichen else 170*29836b19Smichen ret->in_use = 1; 171*29836b19Smichen (void) mutex_unlock(&gnctx->ptr->getent_mutex); 172*29836b19Smichen } 173cb5caa98Sdjl } 174cb5caa98Sdjl 175cb5caa98Sdjl (void) rw_unlock(&getent_ctxDB_rwlock); 176cb5caa98Sdjl 177cb5caa98Sdjl return (ret); 178cb5caa98Sdjl } 179cb5caa98Sdjl 180cb5caa98Sdjl /* 181*29836b19Smichen * FUNCTION: _nscd_free_ctx_if_aborted 182*29836b19Smichen * 183*29836b19Smichen * Check to see if the getent session associated with a getent context had 184*29836b19Smichen * been aborted. If so, return the getent context back to the pool. 185*29836b19Smichen */ 186*29836b19Smichen void 187*29836b19Smichen _nscd_free_ctx_if_aborted( 188*29836b19Smichen nscd_getent_context_t *ctx) 189*29836b19Smichen { 190*29836b19Smichen int aborted; 191*29836b19Smichen char *me = "_nscd_free_ctx_if_aborted"; 192*29836b19Smichen 193*29836b19Smichen if (ctx->in_use != 1) 194*29836b19Smichen return; 195*29836b19Smichen 196*29836b19Smichen (void) mutex_lock(&ctx->getent_mutex); 197*29836b19Smichen aborted = ctx->aborted; 198*29836b19Smichen (void) mutex_unlock(&ctx->getent_mutex); 199*29836b19Smichen 200*29836b19Smichen if (aborted == 1) { 201*29836b19Smichen _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 202*29836b19Smichen (me, "getent session aborted, return the getent context\n"); 203*29836b19Smichen _nscd_put_getent_ctx(ctx); 204*29836b19Smichen } 205*29836b19Smichen ctx->in_use = 0; 206*29836b19Smichen } 207*29836b19Smichen 208*29836b19Smichen /* 209cb5caa98Sdjl * FUNCTION: _nscd_del_getent_ctx 210cb5caa98Sdjl * 211cb5caa98Sdjl * Delete a getent context from the internal getent context database. 212cb5caa98Sdjl */ 213cb5caa98Sdjl static void 214cb5caa98Sdjl _nscd_del_getent_ctx( 215cb5caa98Sdjl nscd_getent_context_t *ptr, 216e37190e5Smichen nscd_cookie_num_t cookie_num) 217cb5caa98Sdjl { 218*29836b19Smichen char ptrstr[32]; 219cb5caa98Sdjl nscd_getent_ctx_t *gnctx; 220cb5caa98Sdjl const nscd_db_entry_t *db_entry; 221cb5caa98Sdjl 222cb5caa98Sdjl if (ptr == NULL) 223cb5caa98Sdjl return; 224cb5caa98Sdjl 225e37190e5Smichen (void) snprintf(ptrstr, sizeof (ptrstr), "%lld", cookie_num); 226cb5caa98Sdjl 227cb5caa98Sdjl (void) rw_rdlock(&getent_ctxDB_rwlock); 228cb5caa98Sdjl /* 229cb5caa98Sdjl * first find the db entry and make sure the 230cb5caa98Sdjl * sequence number matched, then delete it from 231cb5caa98Sdjl * the database. 232cb5caa98Sdjl */ 233cb5caa98Sdjl db_entry = _nscd_get_db_entry(getent_ctxDB, 234cb5caa98Sdjl NSCD_DATA_CTX_ADDR, 235cb5caa98Sdjl (const char *)ptrstr, 236cb5caa98Sdjl NSCD_GET_FIRST_DB_ENTRY, 0); 237cb5caa98Sdjl if (db_entry != NULL) { 238cb5caa98Sdjl gnctx = (nscd_getent_ctx_t *)*(db_entry->data_array); 239e37190e5Smichen if (gnctx->ptr == ptr && gnctx->cookie_num == cookie_num) { 240cb5caa98Sdjl 241cb5caa98Sdjl (void) rw_unlock(&getent_ctxDB_rwlock); 242cb5caa98Sdjl (void) rw_wrlock(&getent_ctxDB_rwlock); 243cb5caa98Sdjl 244cb5caa98Sdjl (void) _nscd_delete_db_entry(getent_ctxDB, 245cb5caa98Sdjl NSCD_DATA_CTX_ADDR, 246cb5caa98Sdjl (const char *)ptrstr, 247cb5caa98Sdjl NSCD_DEL_FIRST_DB_ENTRY, 0); 248cb5caa98Sdjl } 249cb5caa98Sdjl } 250cb5caa98Sdjl (void) rw_unlock(&getent_ctxDB_rwlock); 251cb5caa98Sdjl } 252cb5caa98Sdjl 253cb5caa98Sdjl static void 254cb5caa98Sdjl _nscd_free_getent_ctx( 255cb5caa98Sdjl nscd_getent_context_t *gnctx) 256cb5caa98Sdjl { 257cb5caa98Sdjl 258cb5caa98Sdjl char *me = "_nscd_free_getent_ctx"; 259cb5caa98Sdjl 260cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 261cb5caa98Sdjl (me, "getent context %p\n", gnctx); 262cb5caa98Sdjl 263cb5caa98Sdjl _nscd_put_nsw_state(gnctx->nsw_state); 264e37190e5Smichen _nscd_del_getent_ctx(gnctx, gnctx->cookie_num); 265cb5caa98Sdjl free(gnctx); 266cb5caa98Sdjl } 267cb5caa98Sdjl 268cb5caa98Sdjl 269cb5caa98Sdjl static void 270cb5caa98Sdjl _nscd_free_getent_ctx_base( 271cb5caa98Sdjl nscd_acc_data_t *data) 272cb5caa98Sdjl { 273cb5caa98Sdjl nscd_getent_ctx_base_t *base = (nscd_getent_ctx_base_t *)data; 274cb5caa98Sdjl nscd_getent_context_t *c, *tc; 275cb5caa98Sdjl char *me = "_nscd_free_getent_ctx_base"; 276cb5caa98Sdjl 277cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 278cb5caa98Sdjl (me, "getent context base %p\n", base); 279cb5caa98Sdjl 280cb5caa98Sdjl if (base == NULL) 281cb5caa98Sdjl return; 282cb5caa98Sdjl 283cb5caa98Sdjl c = base->first; 284cb5caa98Sdjl while (c != NULL) { 285cb5caa98Sdjl tc = c->next; 286cb5caa98Sdjl _nscd_free_getent_ctx(c); 287cb5caa98Sdjl c = tc; 288cb5caa98Sdjl } 289cb5caa98Sdjl } 290cb5caa98Sdjl 291cb5caa98Sdjl void 292cb5caa98Sdjl _nscd_free_all_getent_ctx_base() 293cb5caa98Sdjl { 294cb5caa98Sdjl nscd_getent_ctx_base_t *base; 295cb5caa98Sdjl int i; 296cb5caa98Sdjl char *me = "_nscd_free_all_getent_ctx_base"; 297cb5caa98Sdjl 298cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 299cb5caa98Sdjl (me, "entering ..\n"); 300cb5caa98Sdjl 301cb5caa98Sdjl (void) rw_wrlock(&nscd_getent_ctx_base_lock); 302cb5caa98Sdjl 303cb5caa98Sdjl for (i = 0; i < NSCD_NUM_DB; i++) { 304cb5caa98Sdjl 305cb5caa98Sdjl base = nscd_getent_ctx_base[i]; 306cb5caa98Sdjl if (base == NULL) 307cb5caa98Sdjl continue; 308cb5caa98Sdjl 309cb5caa98Sdjl nscd_getent_ctx_base[i] = (nscd_getent_ctx_base_t *) 310cb5caa98Sdjl _nscd_set((nscd_acc_data_t *)base, NULL); 311cb5caa98Sdjl } 312cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 313cb5caa98Sdjl } 314cb5caa98Sdjl 315cb5caa98Sdjl static nscd_getent_context_t * 316cb5caa98Sdjl _nscd_create_getent_ctx( 317cb5caa98Sdjl nscd_nsw_params_t *params) 318cb5caa98Sdjl { 319cb5caa98Sdjl nscd_getent_context_t *gnctx; 320cb5caa98Sdjl nss_db_root_t db_root; 321cb5caa98Sdjl char *me = "_nscd_create_getent_ctx"; 322cb5caa98Sdjl 323cb5caa98Sdjl gnctx = calloc(1, sizeof (nscd_getent_context_t)); 324cb5caa98Sdjl if (gnctx == NULL) 325cb5caa98Sdjl return (NULL); 326cb5caa98Sdjl else { 327cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 328cb5caa98Sdjl (me, "getent context allocated %p\n", gnctx); 329cb5caa98Sdjl } 330cb5caa98Sdjl 331cb5caa98Sdjl gnctx->dbi = params->dbi; 332e37190e5Smichen gnctx->cookie_num = _nscd_get_cookie_num(); 3339f590749Smichen gnctx->pid = -1; 334*29836b19Smichen (void) mutex_init(&gnctx->getent_mutex, USYNC_THREAD, NULL); 335cb5caa98Sdjl 336cb5caa98Sdjl if (_nscd_get_nsw_state(&db_root, params) != NSCD_SUCCESS) { 337cb5caa98Sdjl free(gnctx); 338cb5caa98Sdjl return (NULL); 339cb5caa98Sdjl } 340cb5caa98Sdjl gnctx->nsw_state = (nscd_nsw_state_t *)db_root.s; 341cb5caa98Sdjl /* this is a nsw_state used for getent processing */ 342cb5caa98Sdjl gnctx->nsw_state->getent = 1; 343cb5caa98Sdjl 344cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 345cb5caa98Sdjl (me, "got nsw_state %p\n", gnctx->nsw_state); 346cb5caa98Sdjl 347cb5caa98Sdjl return (gnctx); 348cb5caa98Sdjl } 349cb5caa98Sdjl 350cb5caa98Sdjl 351cb5caa98Sdjl nscd_rc_t 352cb5caa98Sdjl _nscd_get_getent_ctx( 353cb5caa98Sdjl nss_getent_t *contextpp, 354cb5caa98Sdjl nscd_nsw_params_t *params) 355cb5caa98Sdjl { 356cb5caa98Sdjl 357cb5caa98Sdjl nscd_getent_context_t *c; 358cb5caa98Sdjl nscd_getent_ctx_base_t *base, *tmp; 359cb5caa98Sdjl nscd_rc_t rc; 360cb5caa98Sdjl char *me = "_nscd_get_getent_ctx"; 361cb5caa98Sdjl 362cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 363cb5caa98Sdjl (me, "entering ...\n"); 364cb5caa98Sdjl 365cb5caa98Sdjl (void) rw_rdlock(&nscd_getent_ctx_base_lock); 366cb5caa98Sdjl base = nscd_getent_ctx_base[params->dbi]; 367cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 368cb5caa98Sdjl assert(base != NULL); 369cb5caa98Sdjl 370cb5caa98Sdjl /* 371cb5caa98Sdjl * If the context list is not empty, return the first one 372cb5caa98Sdjl * on the list. Otherwise, create and return a new one if 373cb5caa98Sdjl * limit is not reached. if reacehed, wait for the 'one is 374cb5caa98Sdjl * available' signal. 375cb5caa98Sdjl */ 376cb5caa98Sdjl tmp = (nscd_getent_ctx_base_t *)_nscd_mutex_lock( 377cb5caa98Sdjl (nscd_acc_data_t *)base); 378cb5caa98Sdjl assert(base == tmp); 379cb5caa98Sdjl if (base->first == NULL) { 380cb5caa98Sdjl if (base->num_getent_ctx == base->max_getent_ctx) { 381cb5caa98Sdjl base->num_waiter++; 382cb5caa98Sdjl while (base->first == NULL) { 383cb5caa98Sdjl 384cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, 385cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 386cb5caa98Sdjl (me, "waiting for signal\n"); 387cb5caa98Sdjl 388cb5caa98Sdjl _nscd_cond_wait((nscd_acc_data_t *)base, NULL); 389cb5caa98Sdjl 390cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, 391cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 392cb5caa98Sdjl (me, "woke up\n"); 393cb5caa98Sdjl } 394cb5caa98Sdjl base->num_waiter--; 395cb5caa98Sdjl } else { 396cb5caa98Sdjl base->first = _nscd_create_getent_ctx(params); 397cb5caa98Sdjl if (base->first != NULL) { 398cb5caa98Sdjl base->first->base = base; 399cb5caa98Sdjl base->num_getent_ctx++; 400cb5caa98Sdjl } else { 401cb5caa98Sdjl /* not able to create an getent ctx */ 402cb5caa98Sdjl 403cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, 404cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 405cb5caa98Sdjl (me, "create getent ctx failed\n"); 406cb5caa98Sdjl 407cb5caa98Sdjl _nscd_mutex_unlock((nscd_acc_data_t *)base); 408cb5caa98Sdjl return (NSCD_CREATE_GETENT_CTX_FAILED); 409cb5caa98Sdjl } 410cb5caa98Sdjl 411cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 412cb5caa98Sdjl (me, "got a new getent ctx %p\n", base->first); 413cb5caa98Sdjl } 414cb5caa98Sdjl } 415cb5caa98Sdjl 416cb5caa98Sdjl assert(base->first != NULL); 417cb5caa98Sdjl 418cb5caa98Sdjl c = base->first; 419cb5caa98Sdjl base->first = c->next; 420cb5caa98Sdjl c->next = NULL; 421cb5caa98Sdjl c->seq_num = 1; 422*29836b19Smichen c->in_use = 1; 423cb5caa98Sdjl 424cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 425cb5caa98Sdjl (me, "got a getent ctx %p\n", c); 426cb5caa98Sdjl 427cb5caa98Sdjl _nscd_mutex_unlock((nscd_acc_data_t *)base); 428cb5caa98Sdjl 429cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 430e37190e5Smichen (me, "adding new ctx %p, cookie # = %lld\n", c, c->cookie_num); 431cb5caa98Sdjl 432e37190e5Smichen if ((rc = _nscd_add_getent_ctx(c, c->cookie_num)) != NSCD_SUCCESS) { 433cb5caa98Sdjl _nscd_put_getent_ctx(c); 434cb5caa98Sdjl return (rc); 435cb5caa98Sdjl } 436cb5caa98Sdjl contextpp->ctx = (struct nss_getent_context *)c; 437cb5caa98Sdjl 438cb5caa98Sdjl /* start monitor and reclaim orphan getent context */ 439cb5caa98Sdjl if (getent_monitor_started == 0) { 440cb5caa98Sdjl (void) mutex_lock(&getent_monitor_mutex); 441cb5caa98Sdjl if (getent_monitor_started == 0) { 442cb5caa98Sdjl getent_monitor_started = 1; 443cb5caa98Sdjl (void) _nscd_init_getent_ctx_monitor(); 444cb5caa98Sdjl } 445cb5caa98Sdjl (void) mutex_unlock(&getent_monitor_mutex); 446cb5caa98Sdjl } 447cb5caa98Sdjl 448cb5caa98Sdjl return (NSCD_SUCCESS); 449cb5caa98Sdjl } 450cb5caa98Sdjl 451cb5caa98Sdjl void 452cb5caa98Sdjl _nscd_put_getent_ctx( 453cb5caa98Sdjl nscd_getent_context_t *gnctx) 454cb5caa98Sdjl { 455cb5caa98Sdjl 456cb5caa98Sdjl nscd_getent_ctx_base_t *base; 457cb5caa98Sdjl char *me = "_nscd_put_getent_ctx"; 458cb5caa98Sdjl 459cb5caa98Sdjl base = gnctx->base; 460cb5caa98Sdjl gnctx->seq_num = 0; 461cb5caa98Sdjl 462cb5caa98Sdjl /* if context base is gone, so should this context */ 463cb5caa98Sdjl if ((_nscd_mutex_lock((nscd_acc_data_t *)base)) == NULL) { 464cb5caa98Sdjl _nscd_free_getent_ctx(gnctx); 465cb5caa98Sdjl return; 466cb5caa98Sdjl } 467cb5caa98Sdjl 468cb5caa98Sdjl if (base->first != NULL) { 469cb5caa98Sdjl gnctx->next = base->first; 470cb5caa98Sdjl base->first = gnctx; 471cb5caa98Sdjl } else 472cb5caa98Sdjl base->first = gnctx; 473cb5caa98Sdjl 474cb5caa98Sdjl /* put back the db state */ 475cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 476cb5caa98Sdjl (me, "putting back nsw state %p\n", gnctx->nsw_state); 477cb5caa98Sdjl 478cb5caa98Sdjl /* this nsw_state is no longer used for getent processing */ 479cb5caa98Sdjl if (gnctx->nsw_state != NULL) 480cb5caa98Sdjl gnctx->nsw_state->getent = 0; 481cb5caa98Sdjl _nscd_put_nsw_state(gnctx->nsw_state); 482cb5caa98Sdjl gnctx->nsw_state = NULL; 483cb5caa98Sdjl 484*29836b19Smichen gnctx->aborted = 0; 485*29836b19Smichen gnctx->in_use = 0; 486e37190e5Smichen _nscd_del_getent_ctx(gnctx, gnctx->cookie_num); 487cb5caa98Sdjl 488cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 489e37190e5Smichen (me, "ctx (%p, cookie # = %lld) removed from getent ctx DB\n", 490e37190e5Smichen gnctx, gnctx->cookie_num); 491cb5caa98Sdjl 492cb5caa98Sdjl if (base->num_waiter > 0) { 493cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 494cb5caa98Sdjl (me, "signaling (waiter = %d)\n", base->num_waiter); 495cb5caa98Sdjl 496cb5caa98Sdjl _nscd_cond_signal((nscd_acc_data_t *)base); 497cb5caa98Sdjl } 498cb5caa98Sdjl 499cb5caa98Sdjl _nscd_mutex_unlock((nscd_acc_data_t *)base); 500cb5caa98Sdjl } 501cb5caa98Sdjl 502cb5caa98Sdjl nscd_rc_t 503cb5caa98Sdjl _nscd_init_getent_ctx_base( 504cb5caa98Sdjl int dbi, 505cb5caa98Sdjl int lock) 506cb5caa98Sdjl { 507cb5caa98Sdjl nscd_getent_ctx_base_t *base = NULL; 508cb5caa98Sdjl char *me = "_nscd_init_getent_ctx_base"; 509cb5caa98Sdjl 510cb5caa98Sdjl if (lock) 511cb5caa98Sdjl (void) rw_rdlock(&nscd_getent_ctx_base_lock); 512cb5caa98Sdjl 513cb5caa98Sdjl base = (nscd_getent_ctx_base_t *)_nscd_alloc( 514cb5caa98Sdjl NSCD_DATA_GETENT_CTX_BASE, 515cb5caa98Sdjl sizeof (nscd_getent_ctx_base_t), 516cb5caa98Sdjl _nscd_free_getent_ctx_base, 517cb5caa98Sdjl NSCD_ALLOC_MUTEX | NSCD_ALLOC_COND); 518cb5caa98Sdjl 519cb5caa98Sdjl if (base == NULL) { 520cb5caa98Sdjl if (lock) 521cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 522cb5caa98Sdjl return (NSCD_NO_MEMORY); 523cb5caa98Sdjl } 524cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 525cb5caa98Sdjl (me, "base %p allocated\n", base); 526cb5caa98Sdjl 527cb5caa98Sdjl /* 528cb5caa98Sdjl * initialize and activate the new getent_ctx base 529cb5caa98Sdjl */ 530cb5caa98Sdjl base->dbi = dbi; 531cb5caa98Sdjl base->max_getent_ctx = NSCD_SW_CFG(dbi).max_getent_ctx_per_db; 532cb5caa98Sdjl nscd_getent_ctx_base[dbi] = 533cb5caa98Sdjl (nscd_getent_ctx_base_t *)_nscd_set( 534cb5caa98Sdjl (nscd_acc_data_t *)nscd_getent_ctx_base[dbi], 535cb5caa98Sdjl (nscd_acc_data_t *)base); 536cb5caa98Sdjl 537cb5caa98Sdjl if (lock) 538cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 539cb5caa98Sdjl 540cb5caa98Sdjl return (NSCD_SUCCESS); 541cb5caa98Sdjl } 542cb5caa98Sdjl 543cb5caa98Sdjl nscd_rc_t 544cb5caa98Sdjl _nscd_init_all_getent_ctx_base() 545cb5caa98Sdjl { 546cb5caa98Sdjl int i; 547cb5caa98Sdjl nscd_rc_t rc; 548cb5caa98Sdjl char *me = "_nscd_init_all_getent_ctx_base"; 549cb5caa98Sdjl 550cb5caa98Sdjl (void) rw_wrlock(&nscd_getent_ctx_base_lock); 551cb5caa98Sdjl 552cb5caa98Sdjl for (i = 0; i < NSCD_NUM_DB; i++) { 553cb5caa98Sdjl 554cb5caa98Sdjl rc = _nscd_init_getent_ctx_base(i, 0); 555cb5caa98Sdjl 556cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 557cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 558cb5caa98Sdjl return (rc); 559cb5caa98Sdjl } 560cb5caa98Sdjl } 561cb5caa98Sdjl 562cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 563cb5caa98Sdjl (me, "all getent context base initialized\n"); 564cb5caa98Sdjl 565cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 566cb5caa98Sdjl 567cb5caa98Sdjl return (NSCD_SUCCESS); 568cb5caa98Sdjl } 569cb5caa98Sdjl nscd_rc_t 570cb5caa98Sdjl _nscd_alloc_getent_ctx_base() 571cb5caa98Sdjl { 572cb5caa98Sdjl 573cb5caa98Sdjl (void) rw_wrlock(&nscd_getent_ctx_base_lock); 574cb5caa98Sdjl 575cb5caa98Sdjl nscd_getent_ctx_base = calloc(NSCD_NUM_DB, 576cb5caa98Sdjl sizeof (nscd_getent_ctx_base_t *)); 577cb5caa98Sdjl if (nscd_getent_ctx_base == NULL) { 578cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 579cb5caa98Sdjl return (NSCD_NO_MEMORY); 580cb5caa98Sdjl } 581cb5caa98Sdjl 582cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 583cb5caa98Sdjl 584cb5caa98Sdjl return (NSCD_SUCCESS); 585cb5caa98Sdjl } 586cb5caa98Sdjl 587cb5caa98Sdjl static int 588cb5caa98Sdjl process_exited(pid_t pid) 589cb5caa98Sdjl { 590cb5caa98Sdjl char pname[PATH_MAX]; 591cb5caa98Sdjl int fd; 592cb5caa98Sdjl 593cb5caa98Sdjl (void) snprintf(pname, sizeof (pname), "/proc/%d/psinfo", pid); 594cb5caa98Sdjl if ((fd = open(pname, O_RDONLY)) == -1) 595cb5caa98Sdjl return (1); 596cb5caa98Sdjl else { 597cb5caa98Sdjl (void) close(fd); 598cb5caa98Sdjl return (0); 599cb5caa98Sdjl } 600cb5caa98Sdjl } 601cb5caa98Sdjl 602cb5caa98Sdjl /* 603cb5caa98Sdjl * FUNCTION: reclaim_getent_ctx 604cb5caa98Sdjl */ 605cb5caa98Sdjl /*ARGSUSED*/ 606cb5caa98Sdjl static void * 607cb5caa98Sdjl reclaim_getent_ctx(void *arg) 608cb5caa98Sdjl { 609cb5caa98Sdjl void *cookie = NULL; 610cb5caa98Sdjl nscd_db_entry_t *ep; 611cb5caa98Sdjl nscd_getent_ctx_t *ctx; 612cb5caa98Sdjl nscd_getent_context_t *gctx, *c; 613cb5caa98Sdjl nscd_getent_context_t *first = NULL, *last = NULL; 614cb5caa98Sdjl char *me = "reclaim_getent_ctx"; 615cb5caa98Sdjl 616cb5caa98Sdjl /*CONSTCOND*/ 617cb5caa98Sdjl while (1) { 618cb5caa98Sdjl 6199f590749Smichen (void) sleep(60); 6209f590749Smichen 621cb5caa98Sdjl (void) rw_rdlock(&getent_ctxDB_rwlock); 622cb5caa98Sdjl 623cb5caa98Sdjl for (ep = _nscd_walk_db(getent_ctxDB, &cookie); ep != NULL; 624cb5caa98Sdjl ep = _nscd_walk_db(getent_ctxDB, &cookie)) { 625cb5caa98Sdjl 626cb5caa98Sdjl ctx = (nscd_getent_ctx_t *)*(ep->data_array); 627cb5caa98Sdjl 628cb5caa98Sdjl gctx = ctx->ptr; 629cb5caa98Sdjl 630cb5caa98Sdjl /* 631cb5caa98Sdjl * if the client process, which did the setent, 632cb5caa98Sdjl * exited, add the context to the orphan list 633cb5caa98Sdjl */ 634cb5caa98Sdjl if (gctx->pid != -1 && process_exited(gctx->pid)) { 635cb5caa98Sdjl 636cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, 637cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 638cb5caa98Sdjl (me, "process %d exited, " 639cb5caa98Sdjl "getent context = %p, " 640e37190e5Smichen "db index = %d, cookie # = %lld, " 641cb5caa98Sdjl "sequence # = %lld\n", 642cb5caa98Sdjl gctx->pid, gctx, gctx->dbi, 643e37190e5Smichen gctx->cookie_num, gctx->seq_num); 644cb5caa98Sdjl 645cb5caa98Sdjl if (first != NULL) { 646cb5caa98Sdjl last->next = gctx; 647cb5caa98Sdjl last = gctx; 648cb5caa98Sdjl } else { 649cb5caa98Sdjl first = gctx; 650cb5caa98Sdjl last = gctx; 651cb5caa98Sdjl } 652cb5caa98Sdjl } 653cb5caa98Sdjl } 654cb5caa98Sdjl 655cb5caa98Sdjl (void) rw_unlock(&getent_ctxDB_rwlock); 656cb5caa98Sdjl 657cb5caa98Sdjl 658cb5caa98Sdjl /* 659*29836b19Smichen * return all the orphan getent contexts to the pool if not 660*29836b19Smichen * in use 661cb5caa98Sdjl */ 662cb5caa98Sdjl for (gctx = first; gctx; ) { 663*29836b19Smichen int in_use; 664cb5caa98Sdjl c = gctx->next; 665*29836b19Smichen gctx->aborted = 1; 666*29836b19Smichen (void) mutex_lock(&gctx->getent_mutex); 667*29836b19Smichen in_use = gctx->in_use; 668*29836b19Smichen (void) mutex_unlock(&gctx->getent_mutex); 669*29836b19Smichen if (in_use != 1) { 670cb5caa98Sdjl gctx->next = NULL; 671cb5caa98Sdjl _nscd_put_getent_ctx(gctx); 672*29836b19Smichen } 673cb5caa98Sdjl gctx = c; 674cb5caa98Sdjl } 675cb5caa98Sdjl first = last = NULL; 676cb5caa98Sdjl } 677cb5caa98Sdjl /*NOTREACHED*/ 678cb5caa98Sdjl /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/ 679cb5caa98Sdjl } 680cb5caa98Sdjl 681cb5caa98Sdjl static nscd_rc_t 682cb5caa98Sdjl _nscd_init_getent_ctx_monitor() { 683cb5caa98Sdjl 684cb5caa98Sdjl int errnum; 685cb5caa98Sdjl char *me = "_nscd_init_getent_ctx_monitor"; 686cb5caa98Sdjl 687cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 688cb5caa98Sdjl (me, "initializing the getent context monitor\n"); 689cb5caa98Sdjl 690cb5caa98Sdjl /* 691cb5caa98Sdjl * the forker nscd does not process getent requests 692cb5caa98Sdjl * so no need to monitor orphan getent contexts 693cb5caa98Sdjl */ 694cb5caa98Sdjl if (_whoami == NSCD_FORKER) 695cb5caa98Sdjl return (NSCD_SUCCESS); 696cb5caa98Sdjl 697cb5caa98Sdjl /* 698cb5caa98Sdjl * start a thread to reclaim unused getent contexts 699cb5caa98Sdjl */ 700cb5caa98Sdjl if (thr_create(NULL, NULL, reclaim_getent_ctx, 701cb5caa98Sdjl NULL, THR_DETACHED, NULL) != 0) { 702cb5caa98Sdjl errnum = errno; 703cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_ERROR) 704cb5caa98Sdjl (me, "thr_create: %s\n", strerror(errnum)); 705cb5caa98Sdjl return (NSCD_THREAD_CREATE_ERROR); 706cb5caa98Sdjl } 707cb5caa98Sdjl 708cb5caa98Sdjl return (NSCD_SUCCESS); 709cb5caa98Sdjl } 710