cb5caa98562cf06753163f558cbcfe30b8f4673adjl/*
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * CDDL HEADER START
cb5caa98562cf06753163f558cbcfe30b8f4673adjl *
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * The contents of this file are subject to the terms of the
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * Common Development and Distribution License (the "License").
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * You may not use this file except in compliance with the License.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl *
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * or http://www.opensolaris.org/os/licensing.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * See the License for the specific language governing permissions
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * and limitations under the License.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl *
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * When distributing Covered Code, include this CDDL HEADER in each
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * If applicable, add the following below this CDDL HEADER, with the
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * fields enclosed by brackets "[]" replaced with your own identifying
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * information: Portions Copyright [yyyy] [name of copyright owner]
cb5caa98562cf06753163f558cbcfe30b8f4673adjl *
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * CDDL HEADER END
cb5caa98562cf06753163f558cbcfe30b8f4673adjl */
cb5caa98562cf06753163f558cbcfe30b8f4673adjl/*
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * Use is subject to license terms.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl */
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl#pragma ident "%Z%%M% %I% %E% SMI"
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl#include <stdlib.h>
cb5caa98562cf06753163f558cbcfe30b8f4673adjl#include <stdio.h>
cb5caa98562cf06753163f558cbcfe30b8f4673adjl#include "nscd_db.h"
cb5caa98562cf06753163f558cbcfe30b8f4673adjl#include "nscd_log.h"
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjlstatic rwlock_t addrDB_rwlock = DEFAULTRWLOCK;
cb5caa98562cf06753163f558cbcfe30b8f4673adjlstatic nscd_db_t *addrDB = NULL;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl/*
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * internal structure representing a nscd internal address
cb5caa98562cf06753163f558cbcfe30b8f4673adjl */
cb5caa98562cf06753163f558cbcfe30b8f4673adjltypedef struct nscd_int_addr {
cb5caa98562cf06753163f558cbcfe30b8f4673adjl int to_delete; /* no longer valid */
cb5caa98562cf06753163f558cbcfe30b8f4673adjl int type;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl void *ptr;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl nscd_seq_num_t seq_num;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl rwlock_t rwlock; /* used to serialize get and destroy */
cb5caa98562cf06753163f558cbcfe30b8f4673adjl} nscd_int_addr_t;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl/*
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * FUNCTION: _nscd_create_int_addrDB
cb5caa98562cf06753163f558cbcfe30b8f4673adjl *
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * Create the internal address database to keep track of the
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * memory allocated by _nscd_alloc.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl */
cb5caa98562cf06753163f558cbcfe30b8f4673adjlvoid *
cb5caa98562cf06753163f558cbcfe30b8f4673adjl_nscd_create_int_addrDB()
cb5caa98562cf06753163f558cbcfe30b8f4673adjl{
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl nscd_db_t *ret;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl char *me = "_nscd_create_int_addrDB";
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl _NSCD_LOG(NSCD_LOG_INT_ADDR | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (me, "initializing the internal address database\n");
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_wrlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl if (addrDB != NULL) {
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_unlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl return (addrDB);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl }
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl ret = _nscd_alloc_db(NSCD_DB_SIZE_LARGE);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl if (ret != NULL)
cb5caa98562cf06753163f558cbcfe30b8f4673adjl addrDB = ret;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_unlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl return (ret);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl}
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl/*
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * FUNCTION: _nscd_add_int_addr
cb5caa98562cf06753163f558cbcfe30b8f4673adjl *
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * Add an address of 'type' to the internal address database.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl */
cb5caa98562cf06753163f558cbcfe30b8f4673adjlnscd_rc_t
cb5caa98562cf06753163f558cbcfe30b8f4673adjl_nscd_add_int_addr(
cb5caa98562cf06753163f558cbcfe30b8f4673adjl void *ptr,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl int type,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl nscd_seq_num_t seq_num)
cb5caa98562cf06753163f558cbcfe30b8f4673adjl{
cb5caa98562cf06753163f558cbcfe30b8f4673adjl int size;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl char buf[2 * sizeof (ptr) + 1];
cb5caa98562cf06753163f558cbcfe30b8f4673adjl nscd_db_entry_t *db_entry;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl nscd_int_addr_t *int_addr;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl if (ptr == NULL)
cb5caa98562cf06753163f558cbcfe30b8f4673adjl return (NSCD_INVALID_ARGUMENT);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) snprintf(buf, sizeof (buf), "%p", ptr);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl size = sizeof (*int_addr);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl db_entry = _nscd_alloc_db_entry(NSCD_DATA_ADDR,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (const char *)buf, size, 1, 1);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl if (db_entry == NULL)
cb5caa98562cf06753163f558cbcfe30b8f4673adjl return (NSCD_NO_MEMORY);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl int_addr = (nscd_int_addr_t *)*(db_entry->data_array);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl int_addr->ptr = ptr;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl int_addr->type = type;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl int_addr->seq_num = seq_num;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rwlock_init(&int_addr->rwlock, USYNC_THREAD, NULL);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_wrlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) _nscd_add_db_entry(addrDB, buf, db_entry,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl NSCD_ADD_DB_ENTRY_FIRST);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_unlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl return (NSCD_SUCCESS);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl}
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl/*
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * FUNCTION: _nscd_is_int_addr
cb5caa98562cf06753163f558cbcfe30b8f4673adjl *
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * Check to see if an address can be found in the internal
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * address database, if so, obtain a reader lock on the
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * associated rw_lock. The caller needs to unlock it when
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * done using the data.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl */
cb5caa98562cf06753163f558cbcfe30b8f4673adjlrwlock_t *
cb5caa98562cf06753163f558cbcfe30b8f4673adjl_nscd_is_int_addr(
cb5caa98562cf06753163f558cbcfe30b8f4673adjl void *ptr,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl nscd_seq_num_t seq_num)
cb5caa98562cf06753163f558cbcfe30b8f4673adjl{
cb5caa98562cf06753163f558cbcfe30b8f4673adjl char *me = "_nscd_is_int_addr";
cb5caa98562cf06753163f558cbcfe30b8f4673adjl char ptrstr[1 + 2 * sizeof (ptr)];
cb5caa98562cf06753163f558cbcfe30b8f4673adjl rwlock_t *addr_rwlock;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl const nscd_db_entry_t *db_entry;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl if (ptr == NULL)
cb5caa98562cf06753163f558cbcfe30b8f4673adjl return (NULL);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) snprintf(ptrstr, sizeof (ptrstr), "%p", ptr);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_rdlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl db_entry = _nscd_get_db_entry(addrDB, NSCD_DATA_ADDR,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (const char *)ptrstr, NSCD_GET_FIRST_DB_ENTRY, 0);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl if (db_entry != NULL) {
cb5caa98562cf06753163f558cbcfe30b8f4673adjl nscd_int_addr_t *int_addr;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl int_addr = (nscd_int_addr_t *)*(db_entry->data_array);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl addr_rwlock = &int_addr->rwlock;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_rdlock(addr_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl /*
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * If the data is marked as to be deleted
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * or the sequence number does not match,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * return NULL.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl */
cb5caa98562cf06753163f558cbcfe30b8f4673adjl if (int_addr->to_delete == 1 ||
cb5caa98562cf06753163f558cbcfe30b8f4673adjl int_addr->seq_num != seq_num) {
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_unlock(addr_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl addr_rwlock = NULL;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl }
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl _NSCD_LOG(NSCD_LOG_INT_ADDR, NSCD_LOG_LEVEL_DEBUG)
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (me, "found %p, seq# = %lld\n", ptr, int_addr->seq_num);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl } else
cb5caa98562cf06753163f558cbcfe30b8f4673adjl addr_rwlock = NULL;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_unlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl return (addr_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl}
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl/*
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * FUNCTION: _nscd_del_int_addr
cb5caa98562cf06753163f558cbcfe30b8f4673adjl *
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * Delete an address from the internal address database.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl */
cb5caa98562cf06753163f558cbcfe30b8f4673adjlvoid
cb5caa98562cf06753163f558cbcfe30b8f4673adjl_nscd_del_int_addr(
cb5caa98562cf06753163f558cbcfe30b8f4673adjl void *ptr,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl nscd_seq_num_t seq_num)
cb5caa98562cf06753163f558cbcfe30b8f4673adjl{
cb5caa98562cf06753163f558cbcfe30b8f4673adjl char *me = "_nscd_del_int_addr";
cb5caa98562cf06753163f558cbcfe30b8f4673adjl char ptrstr[1 + 2 * sizeof (ptr)];
cb5caa98562cf06753163f558cbcfe30b8f4673adjl rwlock_t *addr_rwlock;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl nscd_int_addr_t *int_addr;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl const nscd_db_entry_t *db_entry;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl if (ptr == NULL)
cb5caa98562cf06753163f558cbcfe30b8f4673adjl return;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl _NSCD_LOG(NSCD_LOG_INT_ADDR, NSCD_LOG_LEVEL_DEBUG)
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (me, "deleting int addr %p (%d)\n", ptr, seq_num);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) snprintf(ptrstr, sizeof (ptrstr), "%p", ptr);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_rdlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl /*
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * first find the db entry and make sure that
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * no one is currently locking it. i.e.,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * no one is waiting to use the same address.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * If it is locked, rw_wrlock() will not return
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * until it is unlocked.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl */
cb5caa98562cf06753163f558cbcfe30b8f4673adjl db_entry = _nscd_get_db_entry(addrDB,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl NSCD_DATA_ADDR,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (const char *)ptrstr,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl NSCD_GET_FIRST_DB_ENTRY, 0);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl if (db_entry != NULL) {
cb5caa98562cf06753163f558cbcfe30b8f4673adjl int_addr = (nscd_int_addr_t *)*(db_entry->data_array);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl addr_rwlock = &int_addr->rwlock;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_wrlock(addr_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl } else {
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_unlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl return;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl }
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_unlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl /*
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * delete the db entry if the sequence numbers match
cb5caa98562cf06753163f558cbcfe30b8f4673adjl */
cb5caa98562cf06753163f558cbcfe30b8f4673adjl if (int_addr->seq_num == seq_num) {
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_wrlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) _nscd_delete_db_entry(addrDB,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl NSCD_DATA_ADDR,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (const char *)ptrstr,
cb5caa98562cf06753163f558cbcfe30b8f4673adjl NSCD_DEL_FIRST_DB_ENTRY, 0);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_unlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl }
cb5caa98562cf06753163f558cbcfe30b8f4673adjl}
cb5caa98562cf06753163f558cbcfe30b8f4673adjl
cb5caa98562cf06753163f558cbcfe30b8f4673adjl/*
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * FUNCTION: _nscd_destroy_int_addrDB
cb5caa98562cf06753163f558cbcfe30b8f4673adjl *
cb5caa98562cf06753163f558cbcfe30b8f4673adjl * Destroy the internal address database.
cb5caa98562cf06753163f558cbcfe30b8f4673adjl */
cb5caa98562cf06753163f558cbcfe30b8f4673adjlvoid
cb5caa98562cf06753163f558cbcfe30b8f4673adjl_nscd_destroy_int_addrDB()
cb5caa98562cf06753163f558cbcfe30b8f4673adjl{
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_wrlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl _nscd_free_db(addrDB);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl addrDB = NULL;
cb5caa98562cf06753163f558cbcfe30b8f4673adjl (void) rw_unlock(&addrDB_rwlock);
cb5caa98562cf06753163f558cbcfe30b8f4673adjl}