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