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*c9a5bc8fSMilan Jurik * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23cb5caa98Sdjl * Use is subject to license terms. 24cb5caa98Sdjl */ 25cb5caa98Sdjl 26cb5caa98Sdjl #ifndef _NSCD_H 27cb5caa98Sdjl #define _NSCD_H 28cb5caa98Sdjl 29cb5caa98Sdjl /* 30cb5caa98Sdjl * This is a private header file. Applications should not directly include 31cb5caa98Sdjl * this file. 32cb5caa98Sdjl */ 33cb5caa98Sdjl 34cb5caa98Sdjl #ifdef __cplusplus 35cb5caa98Sdjl extern "C" { 36cb5caa98Sdjl #endif 37cb5caa98Sdjl 38cb5caa98Sdjl #include <sys/avl.h> 39cb5caa98Sdjl #include <thread.h> 40cb5caa98Sdjl #include <synch.h> 41cb5caa98Sdjl #include <nss_dbdefs.h> 42cb5caa98Sdjl #include "getxby_door.h" 43cb5caa98Sdjl #include "nscd_common.h" 44cb5caa98Sdjl #include "nscd_config.h" 45cb5caa98Sdjl 46cb5caa98Sdjl /* 47cb5caa98Sdjl * OR'D in by server to call self for updates 48cb5caa98Sdjl */ 49cb5caa98Sdjl #define UPDATEBIT (1<<30) 50cb5caa98Sdjl #define MASKUPDATEBIT(a) ((~UPDATEBIT)&(a)) 51cb5caa98Sdjl 52cb5caa98Sdjl /* 53cb5caa98Sdjl * debug levels 54cb5caa98Sdjl */ 55cb5caa98Sdjl #define DBG_OFF 0 56cb5caa98Sdjl #define DBG_CANT_FIND 2 57cb5caa98Sdjl #define DBG_NETLOOKUPS 4 58cb5caa98Sdjl #define DBG_ALL 6 59cb5caa98Sdjl 60cb5caa98Sdjl /* 61cb5caa98Sdjl * Max size name we allow to be passed to avoid 62cb5caa98Sdjl * buffer overflow problems 63cb5caa98Sdjl */ 64cb5caa98Sdjl #define NSCDMAXNAMELEN 255 65cb5caa98Sdjl 66cb5caa98Sdjl /* 67cb5caa98Sdjl * cached entry status 68cb5caa98Sdjl */ 69cb5caa98Sdjl #define ST_UPDATE_PENDING 0x1 70cb5caa98Sdjl #define ST_LOOKUP_PENDING 0x2 71cb5caa98Sdjl #define ST_PENDING (ST_LOOKUP_PENDING | ST_UPDATE_PENDING) 72cb5caa98Sdjl #define ST_NEW_ENTRY 0x4 73cb5caa98Sdjl #define ST_DISCARD 0x8 74cb5caa98Sdjl 75cb5caa98Sdjl /* 76cb5caa98Sdjl * Cache eviction start and stop levels 77cb5caa98Sdjl */ 78cb5caa98Sdjl #define _NSC_EVICTION_START_LEVEL 90 79cb5caa98Sdjl #define _NSC_EVICTION_SAFE_LEVEL 80 80cb5caa98Sdjl 81cb5caa98Sdjl /* 82cb5caa98Sdjl * other internal constants 83cb5caa98Sdjl */ 84*c9a5bc8fSMilan Jurik #define _NSC_MAX_DB 3 85cb5caa98Sdjl #define _NSC_PUBLIC_ACCESS -1 86cb5caa98Sdjl #define _NSC_FILE_CHECK_TIME 0 /* check always for backwards compat */ 87cb5caa98Sdjl 88cb5caa98Sdjl /* 89cb5caa98Sdjl * Macros used for logging purposes 90cb5caa98Sdjl */ 91cb5caa98Sdjl #define yes_no(flag) (flag == nscd_true)?"yes":"no" 92cb5caa98Sdjl #define check_null(str) (str)?str:"<null>" 93cb5caa98Sdjl 94cb5caa98Sdjl /* 95cb5caa98Sdjl * Macros used by compare routines 96cb5caa98Sdjl */ 97cb5caa98Sdjl #define _NSC_INT_KEY_CMP(n1, n2) \ 98cb5caa98Sdjl (n1 > n2)?1:((n1 == n2)?0:-1) 99cb5caa98Sdjl 100cb5caa98Sdjl #define _NSC_GET_HITRATE(sp) \ 101cb5caa98Sdjl sp->hitrate = sp->pos_misses + sp->neg_misses + \ 102cb5caa98Sdjl sp->pos_hits + sp->neg_hits; \ 103cb5caa98Sdjl if (sp->hitrate > 0.0) \ 104cb5caa98Sdjl sp->hitrate = (100.0 * \ 105cb5caa98Sdjl ((double)sp->pos_hits + \ 106cb5caa98Sdjl (double)sp->neg_hits)) / sp->hitrate; 107cb5caa98Sdjl 108cb5caa98Sdjl /* 109cb5caa98Sdjl * nsc_lookup action 110cb5caa98Sdjl */ 111cb5caa98Sdjl typedef enum { 112cb5caa98Sdjl _NSC_NSLOOKUP = 0, 113cb5caa98Sdjl _NSC_WAIT, 114cb5caa98Sdjl _NSC_USECACHED 115cb5caa98Sdjl } nsc_action_t; 116cb5caa98Sdjl 117cb5caa98Sdjl /* 118cb5caa98Sdjl * What each entry in the nameserver cache looks like. 119cb5caa98Sdjl */ 120cb5caa98Sdjl 121cb5caa98Sdjl typedef struct nsc_entry_stat { 122cb5caa98Sdjl uint_t hits; /* number of hits */ 123cb5caa98Sdjl uint8_t status; /* activity status */ 124cb5caa98Sdjl time_t timestamp; /* expiry time */ 125cb5caa98Sdjl int refcount; /* reference count */ 126cb5caa98Sdjl } nsc_entry_stat_t; 127cb5caa98Sdjl 128cb5caa98Sdjl typedef struct nsc_entry { 129cb5caa98Sdjl avl_node_t avl_link; /* libavl requirement */ 130cb5caa98Sdjl struct nsc_entry *qnext; /* next on pqueue */ 131cb5caa98Sdjl struct nsc_entry *qprev; /* prev on pqueue */ 132cb5caa98Sdjl nsc_entry_stat_t stats; /* entry's statistics */ 133cb5caa98Sdjl nss_XbyY_key_t key; /* entry's key */ 134cb5caa98Sdjl void *buffer; /* data buffer */ 135cb5caa98Sdjl size_t bufsize; /* data buffer length */ 136cb5caa98Sdjl } nsc_entry_t; 137cb5caa98Sdjl 138cb5caa98Sdjl typedef struct nsc_keephot { 139cb5caa98Sdjl void *ptr; 140cb5caa98Sdjl uint_t num; 141cb5caa98Sdjl } nsc_keephot_t; 142cb5caa98Sdjl 143cb5caa98Sdjl /* 1443ea037ccSmichen * Structure to handle waiting for pending name service requests 1453ea037ccSmichen */ 1463ea037ccSmichen typedef struct waiter { 1473ea037ccSmichen cond_t w_waitcv; 1483ea037ccSmichen uint8_t w_signaled; 1493ea037ccSmichen nsc_entry_t *w_key; 1503ea037ccSmichen struct waiter *w_next, *w_prev; 1513ea037ccSmichen } waiter_t; 1523ea037ccSmichen 1533ea037ccSmichen /* 154cb5caa98Sdjl * Macros used by hash table 155cb5caa98Sdjl * 156cb5caa98Sdjl * _NSC_HTSIZE_PRIMES are prime numbers that are used as hash table 157cb5caa98Sdjl * sizes when hash table type is nsc_ht_prime. For hash tables of 158cb5caa98Sdjl * type nsc_ht_power2, the size is automatically calculated. 159cb5caa98Sdjl * Number of primes listed below is _NSC_HTSIZE_NUM_SLOTS + 1. 160cb5caa98Sdjl * Each number (except the first) is a prime closest to a 161cb5caa98Sdjl * power of 2 in increasing order. Ex: 509 is the closest prime to 162cb5caa98Sdjl * 512 (2**9), 1021 is closest to 1024 (2**10), and so on. 163cb5caa98Sdjl * The first prime is chosen as 211 for historical reasons. 164cb5caa98Sdjl */ 165cb5caa98Sdjl #define _NSC_INIT_HTSIZE_PRIME 211 166cb5caa98Sdjl #define _NSC_INIT_HTSIZE_POWER2 256 167cb5caa98Sdjl #define _NSC_INIT_HTSIZE_SLOT_VALUE 2896 168cb5caa98Sdjl #define _NSC_HTSIZE_NUM_SLOTS 10 169cb5caa98Sdjl #define _NSC_HTSIZE_PRIMES 211, 509, 1021, 2053, 4099, 8191, \ 170cb5caa98Sdjl 16381, 32771, 65537, 131071, 262147 171cb5caa98Sdjl 172cb5caa98Sdjl #define _NSC_DB_CES_KEY(ptr) \ 173cb5caa98Sdjl ((ptr)->db_type == nsc_key_ces) 174cb5caa98Sdjl #define _NSC_DB_CIS_KEY(ptr) \ 175cb5caa98Sdjl ((ptr)->db_type == nsc_key_cis) 176cb5caa98Sdjl #define _NSC_DB_STR_KEY(ptr) \ 177cb5caa98Sdjl _NSC_DB_CES_KEY(ptr) || _NSC_DB_CIS_KEY(ptr) 178cb5caa98Sdjl #define _NSC_DB_INT_KEY(ptr) \ 179cb5caa98Sdjl ((ptr)->db_type == nsc_key_int) 180cb5caa98Sdjl 181cb5caa98Sdjl /* 182cb5caa98Sdjl * cache backend param group (global) 183cb5caa98Sdjl */ 184cb5caa98Sdjl #define NSCD_CFG_GROUP_INFO_GLOBAL_CACHE {1, 0x0001} 185cb5caa98Sdjl typedef struct nscd_cfg_global_cache { 186cb5caa98Sdjl nscd_cfg_group_info_t gi; /* config requirement */ 187cb5caa98Sdjl nscd_bool_t enable; 188cb5caa98Sdjl } nscd_cfg_global_cache_t; 189cb5caa98Sdjl 190cb5caa98Sdjl #define NSCD_CFG_GLOBAL_CACHE_DEFAULTS \ 191cb5caa98Sdjl { NSCD_CFG_GROUP_INFO_GLOBAL_CACHE, nscd_true } 192cb5caa98Sdjl 193cb5caa98Sdjl /* 194cb5caa98Sdjl * cache backend param group (per database) 195cb5caa98Sdjl */ 196cb5caa98Sdjl #define NSCD_CFG_GROUP_INFO_CACHE {12, 0x0fff} 197cb5caa98Sdjl typedef struct nscd_cfg_cache { 198cb5caa98Sdjl nscd_cfg_group_info_t gi; /* config requirement */ 199cb5caa98Sdjl nscd_bool_t enable; /* if false return NOSERVER */ 200cb5caa98Sdjl nscd_bool_t per_user; /* if true per user access */ 201cb5caa98Sdjl nscd_bool_t avoid_ns; /* if true avoid name service */ 202cb5caa98Sdjl nscd_bool_t check_files; /* if true check file */ 203cb5caa98Sdjl int check_interval; /* check interval */ 204cb5caa98Sdjl int pos_ttl; /* time to live for +ve entries */ 205cb5caa98Sdjl int neg_ttl; /* time to live for -ve entries */ 206cb5caa98Sdjl int keephot; /* keep hot count */ 207cb5caa98Sdjl int hint_size; /* size to return for a GETHINTS */ 208cb5caa98Sdjl ulong_t maxentries; /* maximum entries allowed */ 209cb5caa98Sdjl int suggestedsize; /* obsolete */ 210cb5caa98Sdjl nscd_bool_t old_data_ok; /* obsolete */ 211cb5caa98Sdjl } nscd_cfg_cache_t; 212cb5caa98Sdjl 213cb5caa98Sdjl #define NSCD_CFG_CACHE_DEFAULTS \ 214cb5caa98Sdjl { \ 215cb5caa98Sdjl NSCD_CFG_GROUP_INFO_CACHE, \ 216cb5caa98Sdjl nscd_true, nscd_false, nscd_false, nscd_true, \ 217cb5caa98Sdjl _NSC_FILE_CHECK_TIME, 600, 10, 0, 1 << 11, 0, \ 218cb5caa98Sdjl 0, nscd_false \ 219cb5caa98Sdjl } 220cb5caa98Sdjl 221cb5caa98Sdjl /* 222cb5caa98Sdjl * cache backend stat group (per database) 223cb5caa98Sdjl */ 224cb5caa98Sdjl #define NSCD_CFG_STAT_GROUP_INFO_CACHE {9, 0x01ff} 225cb5caa98Sdjl typedef struct nscd_cfg_stat_cache { 226cb5caa98Sdjl nscd_cfg_group_info_t gi; /* config requirement */ 227cb5caa98Sdjl ulong_t pos_hits; /* hits on +ve entries */ 228cb5caa98Sdjl ulong_t neg_hits; /* hits on -ve entries */ 229cb5caa98Sdjl ulong_t pos_misses; /* misses on +ve entries */ 230cb5caa98Sdjl ulong_t neg_misses; /* misses on -ve entries */ 231cb5caa98Sdjl ulong_t entries; /* count of cache entries */ 232cb5caa98Sdjl ulong_t drop_count; /* cache queries dropped */ 233cb5caa98Sdjl ulong_t wait_count; /* cache queries queued */ 234cb5caa98Sdjl ulong_t invalidate_count; /* count for cache invalidation */ 235cb5caa98Sdjl double hitrate; /* computed from other fields */ 236cb5caa98Sdjl } nscd_cfg_stat_cache_t; 237cb5caa98Sdjl 238cb5caa98Sdjl typedef struct nsc_db { 239cb5caa98Sdjl /* 240cb5caa98Sdjl * Data 241cb5caa98Sdjl */ 242cb5caa98Sdjl avl_tree_t tree; 243cb5caa98Sdjl nsc_entry_t **htable; 244cb5caa98Sdjl nsc_entry_t *qhead; 245cb5caa98Sdjl nsc_entry_t *qtail; 246cb5caa98Sdjl nsc_entry_t *reap_node; 247cb5caa98Sdjl int callnumber; 248cb5caa98Sdjl int dbop; 249cb5caa98Sdjl char *name; 250cb5caa98Sdjl mutex_t db_mutex; 2513ea037ccSmichen waiter_t db_wait; /* lookup wait CV */ 252cb5caa98Sdjl int htsize; 253cb5caa98Sdjl enum hash_type { 254cb5caa98Sdjl nsc_ht_default = 0, 255cb5caa98Sdjl nsc_ht_prime = 1, 256cb5caa98Sdjl nsc_ht_power2 = 2 257cb5caa98Sdjl } hash_type; 258cb5caa98Sdjl enum db_type { 259cb5caa98Sdjl nsc_key_ces = 0, 260cb5caa98Sdjl nsc_key_cis = 1, 261cb5caa98Sdjl nsc_key_int = 2, 262cb5caa98Sdjl nsc_key_other = 3 263cb5caa98Sdjl } db_type; 264cb5caa98Sdjl /* 265cb5caa98Sdjl * Methods 266cb5caa98Sdjl */ 267cb5caa98Sdjl uint_t (*gethash)(nss_XbyY_key_t *, int); 268cb5caa98Sdjl int (*compar)(const void *, const void *); 269cb5caa98Sdjl void (*getlogstr)(char *, char *, size_t, nss_XbyY_args_t *); 270cb5caa98Sdjl /* 271cb5caa98Sdjl * Config 272cb5caa98Sdjl */ 273cb5caa98Sdjl nscd_cfg_cache_t cfg; 274cb5caa98Sdjl time_t cfg_mtime; 275cb5caa98Sdjl } nsc_db_t; 276cb5caa98Sdjl 277cb5caa98Sdjl 278cb5caa98Sdjl typedef struct nsc_ctx { 279cb5caa98Sdjl char *dbname; /* cache name */ 280cb5caa98Sdjl nscd_cfg_stat_cache_t stats; /* statistics */ 281cb5caa98Sdjl nscd_cfg_cache_t cfg; /* configs */ 282cb5caa98Sdjl time_t cfg_mtime; /* config last modified time */ 283cb5caa98Sdjl rwlock_t cfg_rwlp; /* config rwlock */ 284cb5caa98Sdjl mutex_t stats_mutex; /* stats mutex */ 285cb5caa98Sdjl mutex_t file_mutex; /* file mutex */ 286cb5caa98Sdjl time_t file_mtime; /* file last modified time */ 287cb5caa98Sdjl time_t file_chktime; /* file last checked time */ 288cb5caa98Sdjl off_t file_size; /* file size at last check */ 289cb5caa98Sdjl ino_t file_ino; /* file inode at last check */ 290cb5caa98Sdjl const char *file_name; /* filename for check_files */ 291*c9a5bc8fSMilan Jurik int db_count; /* number of caches, max _NSC_MAX_DB */ 292cb5caa98Sdjl nsc_db_t *nsc_db[_NSC_MAX_DB]; /* caches */ 293cb5caa98Sdjl sema_t throttle_sema; /* throttle lookups */ 294cb5caa98Sdjl sema_t revalidate_sema; /* revalidation threads */ 295cb5caa98Sdjl nscd_bool_t revalidate_on; /* reval. thread started */ 296cb5caa98Sdjl nscd_bool_t reaper_on; /* reaper thread started */ 297cb5caa98Sdjl } nsc_ctx_t; 298cb5caa98Sdjl 299cb5caa98Sdjl typedef struct nsc_lookup_args { 300cb5caa98Sdjl nsc_ctx_t *ctx; 301cb5caa98Sdjl nsc_db_t *nscdb; 302cb5caa98Sdjl void *buffer; 303cb5caa98Sdjl size_t bufsize; 304cb5caa98Sdjl } nsc_lookup_args_t; 305cb5caa98Sdjl 306cb5caa98Sdjl #define CACHE_CTX_COUNT 20 307cb5caa98Sdjl 308cb5caa98Sdjl /* Context initialization */ 309cb5caa98Sdjl extern void passwd_init_ctx(nsc_ctx_t *); 310cb5caa98Sdjl extern void group_init_ctx(nsc_ctx_t *); 311cb5caa98Sdjl extern void host_init_ctx(nsc_ctx_t *); 312cb5caa98Sdjl extern void ipnode_init_ctx(nsc_ctx_t *); 313cb5caa98Sdjl extern void exec_init_ctx(nsc_ctx_t *); 314cb5caa98Sdjl extern void prof_init_ctx(nsc_ctx_t *); 315cb5caa98Sdjl extern void user_init_ctx(nsc_ctx_t *); 316cb5caa98Sdjl extern void ether_init_ctx(nsc_ctx_t *); 317cb5caa98Sdjl extern void rpc_init_ctx(nsc_ctx_t *); 318cb5caa98Sdjl extern void proto_init_ctx(nsc_ctx_t *); 319cb5caa98Sdjl extern void net_init_ctx(nsc_ctx_t *); 320cb5caa98Sdjl extern void bootp_init_ctx(nsc_ctx_t *); 321cb5caa98Sdjl extern void auuser_init_ctx(nsc_ctx_t *); 322cb5caa98Sdjl extern void auth_init_ctx(nsc_ctx_t *); 323cb5caa98Sdjl extern void serv_init_ctx(nsc_ctx_t *); 324cb5caa98Sdjl extern void netmask_init_ctx(nsc_ctx_t *); 325cb5caa98Sdjl extern void printer_init_ctx(nsc_ctx_t *); 326cb5caa98Sdjl extern void project_init_ctx(nsc_ctx_t *); 327cb5caa98Sdjl extern void tnrhtp_init_ctx(nsc_ctx_t *); 328cb5caa98Sdjl extern void tnrhdb_init_ctx(nsc_ctx_t *); 329cb5caa98Sdjl 330cb5caa98Sdjl /* Functions used to throttle threads */ 3313ea037ccSmichen extern int nscd_wait(nsc_ctx_t *, nsc_db_t *, nsc_entry_t *); 3323ea037ccSmichen extern int nscd_signal(nsc_ctx_t *, nsc_db_t *, nsc_entry_t *); 333cb5caa98Sdjl 334cb5caa98Sdjl /* Cache creation and initialization */ 335cb5caa98Sdjl extern nscd_rc_t init_cache(); 336cb5caa98Sdjl extern nsc_db_t *make_cache(enum db_type, int, char *, 337cb5caa98Sdjl int (*compar) (const void *, const void *), 338cb5caa98Sdjl void (*getlogstr)(char *, char *, size_t, nss_XbyY_args_t *), 339cb5caa98Sdjl uint_t (*gethash)(nss_XbyY_key_t *, int), 340cb5caa98Sdjl enum hash_type, int); 341cb5caa98Sdjl 342cb5caa98Sdjl /* Cache backend lookup */ 343cb5caa98Sdjl extern void nsc_lookup(nsc_lookup_args_t *, int); 344cb5caa98Sdjl 345cb5caa98Sdjl /* Cache backend info */ 346cb5caa98Sdjl extern void nsc_info(nsc_ctx_t *, char *, nscd_cfg_cache_t cfg[], 347cb5caa98Sdjl nscd_cfg_stat_cache_t stats[]); 348cb5caa98Sdjl #ifdef NSCD_DEBUG 349cb5caa98Sdjl extern int nsc_dump(char *, int); 350cb5caa98Sdjl #endif /* NSCD_DEBUG */ 351cb5caa98Sdjl 352cb5caa98Sdjl /* Cache invalidate */ 353cb5caa98Sdjl extern void nsc_invalidate(nsc_ctx_t *, char *, nsc_ctx_t **); 354cb5caa98Sdjl 355cb5caa98Sdjl /* Keep hot functions */ 356cb5caa98Sdjl extern nsc_keephot_t *maken(int); 357cb5caa98Sdjl extern void *insertn(nsc_keephot_t *, uint_t, void *); 358cb5caa98Sdjl 359cb5caa98Sdjl /* hash related routines */ 360cb5caa98Sdjl extern uint_t cis_gethash(const char *, int); 361cb5caa98Sdjl extern uint_t ces_gethash(const char *, int); 362cb5caa98Sdjl extern uint_t db_gethash(const void *, int, int); 363cb5caa98Sdjl 364cb5caa98Sdjl extern void leave(int n); 365cb5caa98Sdjl extern int get_cache_idx(char *); 366cb5caa98Sdjl 367cb5caa98Sdjl #ifdef __cplusplus 368cb5caa98Sdjl } 369cb5caa98Sdjl #endif 370cb5caa98Sdjl 371cb5caa98Sdjl #endif /* _NSCD_H */ 372