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