/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _NSCD_H #define _NSCD_H /* * This is a private header file. Applications should not directly include * this file. */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include "getxby_door.h" #include "nscd_common.h" #include "nscd_config.h" /* * OR'D in by server to call self for updates */ #define UPDATEBIT (1<<30) #define MASKUPDATEBIT(a) ((~UPDATEBIT)&(a)) /* * debug levels */ #define DBG_OFF 0 #define DBG_CANT_FIND 2 #define DBG_NETLOOKUPS 4 #define DBG_ALL 6 /* * Max size name we allow to be passed to avoid * buffer overflow problems */ #define NSCDMAXNAMELEN 255 /* * cached entry status */ #define ST_UPDATE_PENDING 0x1 #define ST_LOOKUP_PENDING 0x2 #define ST_PENDING (ST_LOOKUP_PENDING | ST_UPDATE_PENDING) #define ST_NEW_ENTRY 0x4 #define ST_DISCARD 0x8 /* * Cache eviction start and stop levels */ #define _NSC_EVICTION_START_LEVEL 90 #define _NSC_EVICTION_SAFE_LEVEL 80 /* * other internal constants */ #define _NSC_MAX_DB 3 #define _NSC_PUBLIC_ACCESS -1 #define _NSC_FILE_CHECK_TIME 0 /* check always for backwards compat */ /* * Macros used for logging purposes */ #define yes_no(flag) (flag == nscd_true)?"yes":"no" #define check_null(str) (str)?str:"" /* * Macros used by compare routines */ #define _NSC_INT_KEY_CMP(n1, n2) \ (n1 > n2)?1:((n1 == n2)?0:-1) #define _NSC_GET_HITRATE(sp) \ sp->hitrate = sp->pos_misses + sp->neg_misses + \ sp->pos_hits + sp->neg_hits; \ if (sp->hitrate > 0.0) \ sp->hitrate = (100.0 * \ ((double)sp->pos_hits + \ (double)sp->neg_hits)) / sp->hitrate; /* * nsc_lookup action */ typedef enum { _NSC_NSLOOKUP = 0, _NSC_WAIT, _NSC_USECACHED } nsc_action_t; /* * What each entry in the nameserver cache looks like. */ typedef struct nsc_entry_stat { uint_t hits; /* number of hits */ uint8_t status; /* activity status */ time_t timestamp; /* expiry time */ int refcount; /* reference count */ } nsc_entry_stat_t; typedef struct nsc_entry { avl_node_t avl_link; /* libavl requirement */ struct nsc_entry *qnext; /* next on pqueue */ struct nsc_entry *qprev; /* prev on pqueue */ nsc_entry_stat_t stats; /* entry's statistics */ nss_XbyY_key_t key; /* entry's key */ void *buffer; /* data buffer */ size_t bufsize; /* data buffer length */ } nsc_entry_t; typedef struct nsc_keephot { void *ptr; uint_t num; } nsc_keephot_t; /* * Structure to handle waiting for pending name service requests */ typedef struct waiter { cond_t w_waitcv; uint8_t w_signaled; nsc_entry_t *w_key; struct waiter *w_next, *w_prev; } waiter_t; /* * Macros used by hash table * * _NSC_HTSIZE_PRIMES are prime numbers that are used as hash table * sizes when hash table type is nsc_ht_prime. For hash tables of * type nsc_ht_power2, the size is automatically calculated. * Number of primes listed below is _NSC_HTSIZE_NUM_SLOTS + 1. * Each number (except the first) is a prime closest to a * power of 2 in increasing order. Ex: 509 is the closest prime to * 512 (2**9), 1021 is closest to 1024 (2**10), and so on. * The first prime is chosen as 211 for historical reasons. */ #define _NSC_INIT_HTSIZE_PRIME 211 #define _NSC_INIT_HTSIZE_POWER2 256 #define _NSC_INIT_HTSIZE_SLOT_VALUE 2896 #define _NSC_HTSIZE_NUM_SLOTS 10 #define _NSC_HTSIZE_PRIMES 211, 509, 1021, 2053, 4099, 8191, \ 16381, 32771, 65537, 131071, 262147 #define _NSC_DB_CES_KEY(ptr) \ ((ptr)->db_type == nsc_key_ces) #define _NSC_DB_CIS_KEY(ptr) \ ((ptr)->db_type == nsc_key_cis) #define _NSC_DB_STR_KEY(ptr) \ _NSC_DB_CES_KEY(ptr) || _NSC_DB_CIS_KEY(ptr) #define _NSC_DB_INT_KEY(ptr) \ ((ptr)->db_type == nsc_key_int) /* * cache backend param group (global) */ #define NSCD_CFG_GROUP_INFO_GLOBAL_CACHE {1, 0x0001} typedef struct nscd_cfg_global_cache { nscd_cfg_group_info_t gi; /* config requirement */ nscd_bool_t enable; } nscd_cfg_global_cache_t; #define NSCD_CFG_GLOBAL_CACHE_DEFAULTS \ { NSCD_CFG_GROUP_INFO_GLOBAL_CACHE, nscd_true } /* * cache backend param group (per database) */ #define NSCD_CFG_GROUP_INFO_CACHE {12, 0x0fff} typedef struct nscd_cfg_cache { nscd_cfg_group_info_t gi; /* config requirement */ nscd_bool_t enable; /* if false return NOSERVER */ nscd_bool_t per_user; /* if true per user access */ nscd_bool_t avoid_ns; /* if true avoid name service */ nscd_bool_t check_files; /* if true check file */ int check_interval; /* check interval */ int pos_ttl; /* time to live for +ve entries */ int neg_ttl; /* time to live for -ve entries */ int keephot; /* keep hot count */ int hint_size; /* size to return for a GETHINTS */ ulong_t maxentries; /* maximum entries allowed */ int suggestedsize; /* obsolete */ nscd_bool_t old_data_ok; /* obsolete */ } nscd_cfg_cache_t; #define NSCD_CFG_CACHE_DEFAULTS \ { \ NSCD_CFG_GROUP_INFO_CACHE, \ nscd_true, nscd_false, nscd_false, nscd_true, \ _NSC_FILE_CHECK_TIME, 600, 10, 0, 1 << 11, 0, \ 0, nscd_false \ } /* * cache backend stat group (per database) */ #define NSCD_CFG_STAT_GROUP_INFO_CACHE {9, 0x01ff} typedef struct nscd_cfg_stat_cache { nscd_cfg_group_info_t gi; /* config requirement */ ulong_t pos_hits; /* hits on +ve entries */ ulong_t neg_hits; /* hits on -ve entries */ ulong_t pos_misses; /* misses on +ve entries */ ulong_t neg_misses; /* misses on -ve entries */ ulong_t entries; /* count of cache entries */ ulong_t drop_count; /* cache queries dropped */ ulong_t wait_count; /* cache queries queued */ ulong_t invalidate_count; /* count for cache invalidation */ double hitrate; /* computed from other fields */ } nscd_cfg_stat_cache_t; typedef struct nsc_db { /* * Data */ avl_tree_t tree; nsc_entry_t **htable; nsc_entry_t *qhead; nsc_entry_t *qtail; nsc_entry_t *reap_node; int callnumber; int dbop; char *name; mutex_t db_mutex; waiter_t db_wait; /* lookup wait CV */ int htsize; enum hash_type { nsc_ht_default = 0, nsc_ht_prime = 1, nsc_ht_power2 = 2 } hash_type; enum db_type { nsc_key_ces = 0, nsc_key_cis = 1, nsc_key_int = 2, nsc_key_other = 3 } db_type; /* * Methods */ uint_t (*gethash)(nss_XbyY_key_t *, int); int (*compar)(const void *, const void *); void (*getlogstr)(char *, char *, size_t, nss_XbyY_args_t *); /* * Config */ nscd_cfg_cache_t cfg; time_t cfg_mtime; } nsc_db_t; typedef struct nsc_ctx { char *dbname; /* cache name */ nscd_cfg_stat_cache_t stats; /* statistics */ nscd_cfg_cache_t cfg; /* configs */ time_t cfg_mtime; /* config last modified time */ rwlock_t cfg_rwlp; /* config rwlock */ mutex_t stats_mutex; /* stats mutex */ mutex_t file_mutex; /* file mutex */ time_t file_mtime; /* file last modified time */ time_t file_chktime; /* file last checked time */ off_t file_size; /* file size at last check */ ino_t file_ino; /* file inode at last check */ const char *file_name; /* filename for check_files */ int db_count; /* number of caches, max _NSC_MAX_DB */ nsc_db_t *nsc_db[_NSC_MAX_DB]; /* caches */ sema_t throttle_sema; /* throttle lookups */ sema_t revalidate_sema; /* revalidation threads */ nscd_bool_t revalidate_on; /* reval. thread started */ nscd_bool_t reaper_on; /* reaper thread started */ } nsc_ctx_t; typedef struct nsc_lookup_args { nsc_ctx_t *ctx; nsc_db_t *nscdb; void *buffer; size_t bufsize; } nsc_lookup_args_t; #define CACHE_CTX_COUNT 20 /* Context initialization */ extern void passwd_init_ctx(nsc_ctx_t *); extern void group_init_ctx(nsc_ctx_t *); extern void host_init_ctx(nsc_ctx_t *); extern void ipnode_init_ctx(nsc_ctx_t *); extern void exec_init_ctx(nsc_ctx_t *); extern void prof_init_ctx(nsc_ctx_t *); extern void user_init_ctx(nsc_ctx_t *); extern void ether_init_ctx(nsc_ctx_t *); extern void rpc_init_ctx(nsc_ctx_t *); extern void proto_init_ctx(nsc_ctx_t *); extern void net_init_ctx(nsc_ctx_t *); extern void bootp_init_ctx(nsc_ctx_t *); extern void auuser_init_ctx(nsc_ctx_t *); extern void auth_init_ctx(nsc_ctx_t *); extern void serv_init_ctx(nsc_ctx_t *); extern void netmask_init_ctx(nsc_ctx_t *); extern void printer_init_ctx(nsc_ctx_t *); extern void project_init_ctx(nsc_ctx_t *); extern void tnrhtp_init_ctx(nsc_ctx_t *); extern void tnrhdb_init_ctx(nsc_ctx_t *); /* Functions used to throttle threads */ extern int nscd_wait(nsc_ctx_t *, nsc_db_t *, nsc_entry_t *); extern int nscd_signal(nsc_ctx_t *, nsc_db_t *, nsc_entry_t *); /* Cache creation and initialization */ extern nscd_rc_t init_cache(); extern nsc_db_t *make_cache(enum db_type, int, char *, int (*compar) (const void *, const void *), void (*getlogstr)(char *, char *, size_t, nss_XbyY_args_t *), uint_t (*gethash)(nss_XbyY_key_t *, int), enum hash_type, int); /* Cache backend lookup */ extern void nsc_lookup(nsc_lookup_args_t *, int); /* Cache backend info */ extern void nsc_info(nsc_ctx_t *, char *, nscd_cfg_cache_t cfg[], nscd_cfg_stat_cache_t stats[]); #ifdef NSCD_DEBUG extern int nsc_dump(char *, int); #endif /* NSCD_DEBUG */ /* Cache invalidate */ extern void nsc_invalidate(nsc_ctx_t *, char *, nsc_ctx_t **); /* Keep hot functions */ extern nsc_keephot_t *maken(int); extern void *insertn(nsc_keephot_t *, uint_t, void *); /* hash related routines */ extern uint_t cis_gethash(const char *, int); extern uint_t ces_gethash(const char *, int); extern uint_t db_gethash(const void *, int, int); extern void leave(int n); extern int get_cache_idx(char *); #ifdef __cplusplus } #endif #endif /* _NSCD_H */