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 /* 22cb5caa98Sdjl * Copyright 2006 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; 51*e37190e5Smichen 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, 102*e37190e5Smichen nscd_cookie_num_t cookie_num) 103cb5caa98Sdjl { 104cb5caa98Sdjl int size; 105*e37190e5Smichen char buf[2 * sizeof (cookie_num) + 1]; 106cb5caa98Sdjl nscd_db_entry_t *db_entry; 107cb5caa98Sdjl nscd_getent_ctx_t *gnctx; 108cb5caa98Sdjl 109cb5caa98Sdjl if (ptr == NULL) 110cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 111cb5caa98Sdjl 112*e37190e5Smichen (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; 123*e37190e5Smichen 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( 141*e37190e5Smichen nscd_cookie_num_t cookie_num) 142cb5caa98Sdjl { 143*e37190e5Smichen char ptrstr[1 + 2 * sizeof (cookie_num)]; 144cb5caa98Sdjl const nscd_db_entry_t *db_entry; 145cb5caa98Sdjl nscd_getent_context_t *ret = NULL; 146cb5caa98Sdjl 147*e37190e5Smichen (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 /* 160cb5caa98Sdjl * If the ctx is not to be deleted and 161cb5caa98Sdjl * the cookie numbers match, return the ctx. 162cb5caa98Sdjl * Otherwise return NULL. 163cb5caa98Sdjl */ 164*e37190e5Smichen if (gnctx->to_delete == 0 && gnctx->cookie_num == cookie_num) 165cb5caa98Sdjl ret = gnctx->ptr; 166cb5caa98Sdjl } 167cb5caa98Sdjl 168cb5caa98Sdjl (void) rw_unlock(&getent_ctxDB_rwlock); 169cb5caa98Sdjl 170cb5caa98Sdjl return (ret); 171cb5caa98Sdjl } 172cb5caa98Sdjl 173cb5caa98Sdjl /* 174cb5caa98Sdjl * FUNCTION: _nscd_del_getent_ctx 175cb5caa98Sdjl * 176cb5caa98Sdjl * Delete a getent context from the internal getent context database. 177cb5caa98Sdjl */ 178cb5caa98Sdjl static void 179cb5caa98Sdjl _nscd_del_getent_ctx( 180cb5caa98Sdjl nscd_getent_context_t *ptr, 181*e37190e5Smichen nscd_cookie_num_t cookie_num) 182cb5caa98Sdjl { 183*e37190e5Smichen char ptrstr[1 + 2 * sizeof (cookie_num)]; 184cb5caa98Sdjl nscd_getent_ctx_t *gnctx; 185cb5caa98Sdjl const nscd_db_entry_t *db_entry; 186cb5caa98Sdjl 187cb5caa98Sdjl if (ptr == NULL) 188cb5caa98Sdjl return; 189cb5caa98Sdjl 190*e37190e5Smichen (void) snprintf(ptrstr, sizeof (ptrstr), "%lld", cookie_num); 191cb5caa98Sdjl 192cb5caa98Sdjl (void) rw_rdlock(&getent_ctxDB_rwlock); 193cb5caa98Sdjl /* 194cb5caa98Sdjl * first find the db entry and make sure the 195cb5caa98Sdjl * sequence number matched, then delete it from 196cb5caa98Sdjl * the database. 197cb5caa98Sdjl */ 198cb5caa98Sdjl db_entry = _nscd_get_db_entry(getent_ctxDB, 199cb5caa98Sdjl NSCD_DATA_CTX_ADDR, 200cb5caa98Sdjl (const char *)ptrstr, 201cb5caa98Sdjl NSCD_GET_FIRST_DB_ENTRY, 0); 202cb5caa98Sdjl if (db_entry != NULL) { 203cb5caa98Sdjl gnctx = (nscd_getent_ctx_t *)*(db_entry->data_array); 204*e37190e5Smichen if (gnctx->ptr == ptr && gnctx->cookie_num == cookie_num) { 205cb5caa98Sdjl 206cb5caa98Sdjl (void) rw_unlock(&getent_ctxDB_rwlock); 207cb5caa98Sdjl (void) rw_wrlock(&getent_ctxDB_rwlock); 208cb5caa98Sdjl 209cb5caa98Sdjl (void) _nscd_delete_db_entry(getent_ctxDB, 210cb5caa98Sdjl NSCD_DATA_CTX_ADDR, 211cb5caa98Sdjl (const char *)ptrstr, 212cb5caa98Sdjl NSCD_DEL_FIRST_DB_ENTRY, 0); 213cb5caa98Sdjl } 214cb5caa98Sdjl } 215cb5caa98Sdjl (void) rw_unlock(&getent_ctxDB_rwlock); 216cb5caa98Sdjl } 217cb5caa98Sdjl 218cb5caa98Sdjl static void 219cb5caa98Sdjl _nscd_free_getent_ctx( 220cb5caa98Sdjl nscd_getent_context_t *gnctx) 221cb5caa98Sdjl { 222cb5caa98Sdjl 223cb5caa98Sdjl char *me = "_nscd_free_getent_ctx"; 224cb5caa98Sdjl 225cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 226cb5caa98Sdjl (me, "getent context %p\n", gnctx); 227cb5caa98Sdjl 228cb5caa98Sdjl _nscd_put_nsw_state(gnctx->nsw_state); 229*e37190e5Smichen _nscd_del_getent_ctx(gnctx, gnctx->cookie_num); 230cb5caa98Sdjl free(gnctx); 231cb5caa98Sdjl } 232cb5caa98Sdjl 233cb5caa98Sdjl 234cb5caa98Sdjl static void 235cb5caa98Sdjl _nscd_free_getent_ctx_base( 236cb5caa98Sdjl nscd_acc_data_t *data) 237cb5caa98Sdjl { 238cb5caa98Sdjl nscd_getent_ctx_base_t *base = (nscd_getent_ctx_base_t *)data; 239cb5caa98Sdjl nscd_getent_context_t *c, *tc; 240cb5caa98Sdjl char *me = "_nscd_free_getent_ctx_base"; 241cb5caa98Sdjl 242cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 243cb5caa98Sdjl (me, "getent context base %p\n", base); 244cb5caa98Sdjl 245cb5caa98Sdjl if (base == NULL) 246cb5caa98Sdjl return; 247cb5caa98Sdjl 248cb5caa98Sdjl c = base->first; 249cb5caa98Sdjl while (c != NULL) { 250cb5caa98Sdjl tc = c->next; 251cb5caa98Sdjl _nscd_free_getent_ctx(c); 252cb5caa98Sdjl c = tc; 253cb5caa98Sdjl } 254cb5caa98Sdjl } 255cb5caa98Sdjl 256cb5caa98Sdjl void 257cb5caa98Sdjl _nscd_free_all_getent_ctx_base() 258cb5caa98Sdjl { 259cb5caa98Sdjl nscd_getent_ctx_base_t *base; 260cb5caa98Sdjl int i; 261cb5caa98Sdjl char *me = "_nscd_free_all_getent_ctx_base"; 262cb5caa98Sdjl 263cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 264cb5caa98Sdjl (me, "entering ..\n"); 265cb5caa98Sdjl 266cb5caa98Sdjl (void) rw_wrlock(&nscd_getent_ctx_base_lock); 267cb5caa98Sdjl 268cb5caa98Sdjl for (i = 0; i < NSCD_NUM_DB; i++) { 269cb5caa98Sdjl 270cb5caa98Sdjl base = nscd_getent_ctx_base[i]; 271cb5caa98Sdjl if (base == NULL) 272cb5caa98Sdjl continue; 273cb5caa98Sdjl 274cb5caa98Sdjl nscd_getent_ctx_base[i] = (nscd_getent_ctx_base_t *) 275cb5caa98Sdjl _nscd_set((nscd_acc_data_t *)base, NULL); 276cb5caa98Sdjl } 277cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 278cb5caa98Sdjl } 279cb5caa98Sdjl 280cb5caa98Sdjl static nscd_getent_context_t * 281cb5caa98Sdjl _nscd_create_getent_ctx( 282cb5caa98Sdjl nscd_nsw_params_t *params) 283cb5caa98Sdjl { 284cb5caa98Sdjl nscd_getent_context_t *gnctx; 285cb5caa98Sdjl nss_db_root_t db_root; 286cb5caa98Sdjl char *me = "_nscd_create_getent_ctx"; 287cb5caa98Sdjl 288cb5caa98Sdjl gnctx = calloc(1, sizeof (nscd_getent_context_t)); 289cb5caa98Sdjl if (gnctx == NULL) 290cb5caa98Sdjl return (NULL); 291cb5caa98Sdjl else { 292cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 293cb5caa98Sdjl (me, "getent context allocated %p\n", gnctx); 294cb5caa98Sdjl } 295cb5caa98Sdjl 296cb5caa98Sdjl gnctx->dbi = params->dbi; 297*e37190e5Smichen gnctx->cookie_num = _nscd_get_cookie_num(); 2989f590749Smichen gnctx->pid = -1; 299cb5caa98Sdjl 300cb5caa98Sdjl if (_nscd_get_nsw_state(&db_root, params) != NSCD_SUCCESS) { 301cb5caa98Sdjl free(gnctx); 302cb5caa98Sdjl return (NULL); 303cb5caa98Sdjl } 304cb5caa98Sdjl gnctx->nsw_state = (nscd_nsw_state_t *)db_root.s; 305cb5caa98Sdjl /* this is a nsw_state used for getent processing */ 306cb5caa98Sdjl gnctx->nsw_state->getent = 1; 307cb5caa98Sdjl 308cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 309cb5caa98Sdjl (me, "got nsw_state %p\n", gnctx->nsw_state); 310cb5caa98Sdjl 311cb5caa98Sdjl return (gnctx); 312cb5caa98Sdjl } 313cb5caa98Sdjl 314cb5caa98Sdjl 315cb5caa98Sdjl nscd_rc_t 316cb5caa98Sdjl _nscd_get_getent_ctx( 317cb5caa98Sdjl nss_getent_t *contextpp, 318cb5caa98Sdjl nscd_nsw_params_t *params) 319cb5caa98Sdjl { 320cb5caa98Sdjl 321cb5caa98Sdjl nscd_getent_context_t *c; 322cb5caa98Sdjl nscd_getent_ctx_base_t *base, *tmp; 323cb5caa98Sdjl nscd_rc_t rc; 324cb5caa98Sdjl char *me = "_nscd_get_getent_ctx"; 325cb5caa98Sdjl 326cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 327cb5caa98Sdjl (me, "entering ...\n"); 328cb5caa98Sdjl 329cb5caa98Sdjl (void) rw_rdlock(&nscd_getent_ctx_base_lock); 330cb5caa98Sdjl base = nscd_getent_ctx_base[params->dbi]; 331cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 332cb5caa98Sdjl assert(base != NULL); 333cb5caa98Sdjl 334cb5caa98Sdjl /* 335cb5caa98Sdjl * If the context list is not empty, return the first one 336cb5caa98Sdjl * on the list. Otherwise, create and return a new one if 337cb5caa98Sdjl * limit is not reached. if reacehed, wait for the 'one is 338cb5caa98Sdjl * available' signal. 339cb5caa98Sdjl */ 340cb5caa98Sdjl tmp = (nscd_getent_ctx_base_t *)_nscd_mutex_lock( 341cb5caa98Sdjl (nscd_acc_data_t *)base); 342cb5caa98Sdjl assert(base == tmp); 343cb5caa98Sdjl if (base->first == NULL) { 344cb5caa98Sdjl if (base->num_getent_ctx == base->max_getent_ctx) { 345cb5caa98Sdjl base->num_waiter++; 346cb5caa98Sdjl while (base->first == NULL) { 347cb5caa98Sdjl 348cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, 349cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 350cb5caa98Sdjl (me, "waiting for signal\n"); 351cb5caa98Sdjl 352cb5caa98Sdjl _nscd_cond_wait((nscd_acc_data_t *)base, NULL); 353cb5caa98Sdjl 354cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, 355cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 356cb5caa98Sdjl (me, "woke up\n"); 357cb5caa98Sdjl } 358cb5caa98Sdjl base->num_waiter--; 359cb5caa98Sdjl } else { 360cb5caa98Sdjl base->first = _nscd_create_getent_ctx(params); 361cb5caa98Sdjl if (base->first != NULL) { 362cb5caa98Sdjl base->first->base = base; 363cb5caa98Sdjl base->num_getent_ctx++; 364cb5caa98Sdjl } else { 365cb5caa98Sdjl /* not able to create an getent ctx */ 366cb5caa98Sdjl 367cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, 368cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 369cb5caa98Sdjl (me, "create getent ctx failed\n"); 370cb5caa98Sdjl 371cb5caa98Sdjl _nscd_mutex_unlock((nscd_acc_data_t *)base); 372cb5caa98Sdjl return (NSCD_CREATE_GETENT_CTX_FAILED); 373cb5caa98Sdjl } 374cb5caa98Sdjl 375cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 376cb5caa98Sdjl (me, "got a new getent ctx %p\n", base->first); 377cb5caa98Sdjl } 378cb5caa98Sdjl } 379cb5caa98Sdjl 380cb5caa98Sdjl assert(base->first != NULL); 381cb5caa98Sdjl 382cb5caa98Sdjl c = base->first; 383cb5caa98Sdjl base->first = c->next; 384cb5caa98Sdjl c->next = NULL; 385cb5caa98Sdjl c->seq_num = 1; 386cb5caa98Sdjl 387cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 388cb5caa98Sdjl (me, "got a getent ctx %p\n", c); 389cb5caa98Sdjl 390cb5caa98Sdjl _nscd_mutex_unlock((nscd_acc_data_t *)base); 391cb5caa98Sdjl 392cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 393*e37190e5Smichen (me, "adding new ctx %p, cookie # = %lld\n", c, c->cookie_num); 394cb5caa98Sdjl 395*e37190e5Smichen if ((rc = _nscd_add_getent_ctx(c, c->cookie_num)) != NSCD_SUCCESS) { 396cb5caa98Sdjl _nscd_put_getent_ctx(c); 397cb5caa98Sdjl return (rc); 398cb5caa98Sdjl } 399cb5caa98Sdjl contextpp->ctx = (struct nss_getent_context *)c; 400cb5caa98Sdjl 401cb5caa98Sdjl /* start monitor and reclaim orphan getent context */ 402cb5caa98Sdjl if (getent_monitor_started == 0) { 403cb5caa98Sdjl (void) mutex_lock(&getent_monitor_mutex); 404cb5caa98Sdjl if (getent_monitor_started == 0) { 405cb5caa98Sdjl getent_monitor_started = 1; 406cb5caa98Sdjl (void) _nscd_init_getent_ctx_monitor(); 407cb5caa98Sdjl } 408cb5caa98Sdjl (void) mutex_unlock(&getent_monitor_mutex); 409cb5caa98Sdjl } 410cb5caa98Sdjl 411cb5caa98Sdjl return (NSCD_SUCCESS); 412cb5caa98Sdjl } 413cb5caa98Sdjl 414cb5caa98Sdjl void 415cb5caa98Sdjl _nscd_put_getent_ctx( 416cb5caa98Sdjl nscd_getent_context_t *gnctx) 417cb5caa98Sdjl { 418cb5caa98Sdjl 419cb5caa98Sdjl nscd_getent_ctx_base_t *base; 420cb5caa98Sdjl char *me = "_nscd_put_getent_ctx"; 421cb5caa98Sdjl 422cb5caa98Sdjl base = gnctx->base; 423cb5caa98Sdjl gnctx->seq_num = 0; 424cb5caa98Sdjl 425cb5caa98Sdjl /* if context base is gone, so should this context */ 426cb5caa98Sdjl if ((_nscd_mutex_lock((nscd_acc_data_t *)base)) == NULL) { 427cb5caa98Sdjl _nscd_free_getent_ctx(gnctx); 428cb5caa98Sdjl return; 429cb5caa98Sdjl } 430cb5caa98Sdjl 431cb5caa98Sdjl if (base->first != NULL) { 432cb5caa98Sdjl gnctx->next = base->first; 433cb5caa98Sdjl base->first = gnctx; 434cb5caa98Sdjl } else 435cb5caa98Sdjl base->first = gnctx; 436cb5caa98Sdjl 437cb5caa98Sdjl /* put back the db state */ 438cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 439cb5caa98Sdjl (me, "putting back nsw state %p\n", gnctx->nsw_state); 440cb5caa98Sdjl 441cb5caa98Sdjl /* this nsw_state is no longer used for getent processing */ 442cb5caa98Sdjl if (gnctx->nsw_state != NULL) 443cb5caa98Sdjl gnctx->nsw_state->getent = 0; 444cb5caa98Sdjl _nscd_put_nsw_state(gnctx->nsw_state); 445cb5caa98Sdjl gnctx->nsw_state = NULL; 446cb5caa98Sdjl 447*e37190e5Smichen _nscd_del_getent_ctx(gnctx, gnctx->cookie_num); 448cb5caa98Sdjl 449cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 450*e37190e5Smichen (me, "ctx (%p, cookie # = %lld) removed from getent ctx DB\n", 451*e37190e5Smichen gnctx, gnctx->cookie_num); 452cb5caa98Sdjl 453cb5caa98Sdjl if (base->num_waiter > 0) { 454cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 455cb5caa98Sdjl (me, "signaling (waiter = %d)\n", base->num_waiter); 456cb5caa98Sdjl 457cb5caa98Sdjl _nscd_cond_signal((nscd_acc_data_t *)base); 458cb5caa98Sdjl } 459cb5caa98Sdjl 460cb5caa98Sdjl _nscd_mutex_unlock((nscd_acc_data_t *)base); 461cb5caa98Sdjl } 462cb5caa98Sdjl 463cb5caa98Sdjl nscd_rc_t 464cb5caa98Sdjl _nscd_init_getent_ctx_base( 465cb5caa98Sdjl int dbi, 466cb5caa98Sdjl int lock) 467cb5caa98Sdjl { 468cb5caa98Sdjl nscd_getent_ctx_base_t *base = NULL; 469cb5caa98Sdjl char *me = "_nscd_init_getent_ctx_base"; 470cb5caa98Sdjl 471cb5caa98Sdjl if (lock) 472cb5caa98Sdjl (void) rw_rdlock(&nscd_getent_ctx_base_lock); 473cb5caa98Sdjl 474cb5caa98Sdjl base = (nscd_getent_ctx_base_t *)_nscd_alloc( 475cb5caa98Sdjl NSCD_DATA_GETENT_CTX_BASE, 476cb5caa98Sdjl sizeof (nscd_getent_ctx_base_t), 477cb5caa98Sdjl _nscd_free_getent_ctx_base, 478cb5caa98Sdjl NSCD_ALLOC_MUTEX | NSCD_ALLOC_COND); 479cb5caa98Sdjl 480cb5caa98Sdjl if (base == NULL) { 481cb5caa98Sdjl if (lock) 482cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 483cb5caa98Sdjl return (NSCD_NO_MEMORY); 484cb5caa98Sdjl } 485cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 486cb5caa98Sdjl (me, "base %p allocated\n", base); 487cb5caa98Sdjl 488cb5caa98Sdjl /* 489cb5caa98Sdjl * initialize and activate the new getent_ctx base 490cb5caa98Sdjl */ 491cb5caa98Sdjl base->dbi = dbi; 492cb5caa98Sdjl base->max_getent_ctx = NSCD_SW_CFG(dbi).max_getent_ctx_per_db; 493cb5caa98Sdjl nscd_getent_ctx_base[dbi] = 494cb5caa98Sdjl (nscd_getent_ctx_base_t *)_nscd_set( 495cb5caa98Sdjl (nscd_acc_data_t *)nscd_getent_ctx_base[dbi], 496cb5caa98Sdjl (nscd_acc_data_t *)base); 497cb5caa98Sdjl 498cb5caa98Sdjl if (lock) 499cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 500cb5caa98Sdjl 501cb5caa98Sdjl return (NSCD_SUCCESS); 502cb5caa98Sdjl } 503cb5caa98Sdjl 504cb5caa98Sdjl nscd_rc_t 505cb5caa98Sdjl _nscd_init_all_getent_ctx_base() 506cb5caa98Sdjl { 507cb5caa98Sdjl int i; 508cb5caa98Sdjl nscd_rc_t rc; 509cb5caa98Sdjl char *me = "_nscd_init_all_getent_ctx_base"; 510cb5caa98Sdjl 511cb5caa98Sdjl (void) rw_wrlock(&nscd_getent_ctx_base_lock); 512cb5caa98Sdjl 513cb5caa98Sdjl for (i = 0; i < NSCD_NUM_DB; i++) { 514cb5caa98Sdjl 515cb5caa98Sdjl rc = _nscd_init_getent_ctx_base(i, 0); 516cb5caa98Sdjl 517cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 518cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 519cb5caa98Sdjl return (rc); 520cb5caa98Sdjl } 521cb5caa98Sdjl } 522cb5caa98Sdjl 523cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 524cb5caa98Sdjl (me, "all getent context base initialized\n"); 525cb5caa98Sdjl 526cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 527cb5caa98Sdjl 528cb5caa98Sdjl return (NSCD_SUCCESS); 529cb5caa98Sdjl } 530cb5caa98Sdjl nscd_rc_t 531cb5caa98Sdjl _nscd_alloc_getent_ctx_base() 532cb5caa98Sdjl { 533cb5caa98Sdjl 534cb5caa98Sdjl (void) rw_wrlock(&nscd_getent_ctx_base_lock); 535cb5caa98Sdjl 536cb5caa98Sdjl nscd_getent_ctx_base = calloc(NSCD_NUM_DB, 537cb5caa98Sdjl sizeof (nscd_getent_ctx_base_t *)); 538cb5caa98Sdjl if (nscd_getent_ctx_base == NULL) { 539cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 540cb5caa98Sdjl return (NSCD_NO_MEMORY); 541cb5caa98Sdjl } 542cb5caa98Sdjl 543cb5caa98Sdjl (void) rw_unlock(&nscd_getent_ctx_base_lock); 544cb5caa98Sdjl 545cb5caa98Sdjl return (NSCD_SUCCESS); 546cb5caa98Sdjl } 547cb5caa98Sdjl 548cb5caa98Sdjl static int 549cb5caa98Sdjl process_exited(pid_t pid) 550cb5caa98Sdjl { 551cb5caa98Sdjl char pname[PATH_MAX]; 552cb5caa98Sdjl int fd; 553cb5caa98Sdjl 554cb5caa98Sdjl (void) snprintf(pname, sizeof (pname), "/proc/%d/psinfo", pid); 555cb5caa98Sdjl if ((fd = open(pname, O_RDONLY)) == -1) 556cb5caa98Sdjl return (1); 557cb5caa98Sdjl else { 558cb5caa98Sdjl (void) close(fd); 559cb5caa98Sdjl return (0); 560cb5caa98Sdjl } 561cb5caa98Sdjl } 562cb5caa98Sdjl 563cb5caa98Sdjl /* 564cb5caa98Sdjl * FUNCTION: reclaim_getent_ctx 565cb5caa98Sdjl */ 566cb5caa98Sdjl /*ARGSUSED*/ 567cb5caa98Sdjl static void * 568cb5caa98Sdjl reclaim_getent_ctx(void *arg) 569cb5caa98Sdjl { 570cb5caa98Sdjl void *cookie = NULL; 571cb5caa98Sdjl nscd_db_entry_t *ep; 572cb5caa98Sdjl nscd_getent_ctx_t *ctx; 573cb5caa98Sdjl nscd_getent_context_t *gctx, *c; 574cb5caa98Sdjl nscd_getent_context_t *first = NULL, *last = NULL; 575cb5caa98Sdjl char *me = "reclaim_getent_ctx"; 576cb5caa98Sdjl 577cb5caa98Sdjl /*CONSTCOND*/ 578cb5caa98Sdjl while (1) { 579cb5caa98Sdjl 5809f590749Smichen (void) sleep(60); 5819f590749Smichen 582cb5caa98Sdjl (void) rw_rdlock(&getent_ctxDB_rwlock); 583cb5caa98Sdjl 584cb5caa98Sdjl for (ep = _nscd_walk_db(getent_ctxDB, &cookie); ep != NULL; 585cb5caa98Sdjl ep = _nscd_walk_db(getent_ctxDB, &cookie)) { 586cb5caa98Sdjl 587cb5caa98Sdjl ctx = (nscd_getent_ctx_t *)*(ep->data_array); 588cb5caa98Sdjl 589cb5caa98Sdjl gctx = ctx->ptr; 590cb5caa98Sdjl 591cb5caa98Sdjl /* 592cb5caa98Sdjl * if the client process, which did the setent, 593cb5caa98Sdjl * exited, add the context to the orphan list 594cb5caa98Sdjl */ 595cb5caa98Sdjl if (gctx->pid != -1 && process_exited(gctx->pid)) { 596cb5caa98Sdjl 597cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, 598cb5caa98Sdjl NSCD_LOG_LEVEL_DEBUG) 599cb5caa98Sdjl (me, "process %d exited, " 600cb5caa98Sdjl "getent context = %p, " 601*e37190e5Smichen "db index = %d, cookie # = %lld, " 602cb5caa98Sdjl "sequence # = %lld\n", 603cb5caa98Sdjl gctx->pid, gctx, gctx->dbi, 604*e37190e5Smichen gctx->cookie_num, gctx->seq_num); 605cb5caa98Sdjl 606cb5caa98Sdjl if (first != NULL) { 607cb5caa98Sdjl last->next = gctx; 608cb5caa98Sdjl last = gctx; 609cb5caa98Sdjl } else { 610cb5caa98Sdjl first = gctx; 611cb5caa98Sdjl last = gctx; 612cb5caa98Sdjl } 613cb5caa98Sdjl } 614cb5caa98Sdjl } 615cb5caa98Sdjl 616cb5caa98Sdjl (void) rw_unlock(&getent_ctxDB_rwlock); 617cb5caa98Sdjl 618cb5caa98Sdjl 619cb5caa98Sdjl /* 620cb5caa98Sdjl * return all the orphan getent contexts to the pool 621cb5caa98Sdjl */ 622cb5caa98Sdjl for (gctx = first; gctx; ) { 623cb5caa98Sdjl c = gctx->next; 624cb5caa98Sdjl gctx->next = NULL; 625cb5caa98Sdjl _nscd_put_getent_ctx(gctx); 626cb5caa98Sdjl gctx = c; 627cb5caa98Sdjl } 628cb5caa98Sdjl first = last = NULL; 629cb5caa98Sdjl } 630cb5caa98Sdjl /*NOTREACHED*/ 631cb5caa98Sdjl /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/ 632cb5caa98Sdjl } 633cb5caa98Sdjl 634cb5caa98Sdjl static nscd_rc_t 635cb5caa98Sdjl _nscd_init_getent_ctx_monitor() { 636cb5caa98Sdjl 637cb5caa98Sdjl int errnum; 638cb5caa98Sdjl char *me = "_nscd_init_getent_ctx_monitor"; 639cb5caa98Sdjl 640cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) 641cb5caa98Sdjl (me, "initializing the getent context monitor\n"); 642cb5caa98Sdjl 643cb5caa98Sdjl /* 644cb5caa98Sdjl * the forker nscd does not process getent requests 645cb5caa98Sdjl * so no need to monitor orphan getent contexts 646cb5caa98Sdjl */ 647cb5caa98Sdjl if (_whoami == NSCD_FORKER) 648cb5caa98Sdjl return (NSCD_SUCCESS); 649cb5caa98Sdjl 650cb5caa98Sdjl /* 651cb5caa98Sdjl * start a thread to reclaim unused getent contexts 652cb5caa98Sdjl */ 653cb5caa98Sdjl if (thr_create(NULL, NULL, reclaim_getent_ctx, 654cb5caa98Sdjl NULL, THR_DETACHED, NULL) != 0) { 655cb5caa98Sdjl errnum = errno; 656cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_ERROR) 657cb5caa98Sdjl (me, "thr_create: %s\n", strerror(errnum)); 658cb5caa98Sdjl return (NSCD_THREAD_CREATE_ERROR); 659cb5caa98Sdjl } 660cb5caa98Sdjl 661cb5caa98Sdjl return (NSCD_SUCCESS); 662cb5caa98Sdjl } 663