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