1/*
2   Unix SMB/CIFS implementation.
3
4   NetBIOS name cache module on top of gencache mechanism.
5
6   Copyright (C) Tim Potter         2002
7   Copyright (C) Rafal Szczesniak   2002
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24#include "includes.h"
25
26#define NBTKEY_FMT  "NBT/%s#%02X"
27
28
29/**
30 * Initialise namecache system. Function calls gencache
31 * initialisation function to perform necessary actions
32 *
33 * @return true upon successful initialisation of the cache or
34 *         false on failure
35 **/
36
37BOOL namecache_enable(void)
38{
39	/*
40	 * Check if name caching disabled by setting the name cache
41	 * timeout to zero.
42	 */
43
44	if (lp_name_cache_timeout() == 0) {
45		DEBUG(5, ("namecache_enable: disabling netbios name cache\n"));
46		return False;
47	}
48
49	/* Init namecache by calling gencache initialisation */
50
51	if (!gencache_init()) {
52		DEBUG(2, ("namecache_enable: Couldn't initialise namecache on top of gencache.\n"));
53		return False;
54	}
55
56	/* I leave it for now, though I don't think we really need this (mimir, 27.09.2002) */
57	DEBUG(5, ("namecache_enable: enabling netbios namecache, timeout %d "
58		  "seconds\n", lp_name_cache_timeout()));
59
60	return True;
61}
62
63
64/**
65 * Shutdown namecache. Routine calls gencache close function
66 * to safely close gencache file.
67 *
68 * @return true upon successful shutdown of the cache or
69 *         false on failure
70 **/
71
72BOOL namecache_shutdown(void)
73{
74	if (!gencache_shutdown()) {
75		DEBUG(2, ("namecache_shutdown: Couldn't close namecache on top of gencache.\n"));
76		return False;
77	}
78
79	DEBUG(5, ("namecache_shutdown: netbios namecache closed successfully.\n"));
80	return True;
81}
82
83
84/**
85 * Generates a key for netbios name lookups on basis of
86 * netbios name and type.
87 * The caller must free returned key string when finished.
88 *
89 * @param name netbios name string (case insensitive)
90 * @param name_type netbios type of the name being looked up
91 *
92 * @return string consisted of uppercased name and appended
93 *         type number
94 */
95
96static char* namecache_key(const char *name, int name_type)
97{
98	char *keystr;
99	asprintf(&keystr, NBTKEY_FMT, strupper_static(name), name_type);
100
101	return keystr;
102}
103
104
105/**
106 * Store a name(s) in the name cache
107 *
108 * @param name netbios names array
109 * @param name_type integer netbios name type
110 * @param num_names number of names being stored
111 * @param ip_list array of in_addr structures containing
112 *        ip addresses being stored
113 **/
114
115BOOL namecache_store(const char *name, int name_type,
116                     int num_names, struct ip_service *ip_list)
117{
118	time_t expiry;
119	char *key, *value_string;
120	int i;
121	BOOL ret;
122
123	/*
124	 * we use gecache call to avoid annoying debug messages about
125	 * initialised namecache again and again...
126	 */
127	if (!gencache_init()) return False;
128
129	if ( DEBUGLEVEL >= 5 ) {
130		DEBUG(5, ("namecache_store: storing %d address%s for %s#%02x: ",
131			num_names, num_names == 1 ? "": "es", name, name_type));
132
133		for (i = 0; i < num_names; i++)
134			DEBUGADD(5, ("%s:%d%s", inet_ntoa(ip_list[i].ip),
135				ip_list[i].port, (i == (num_names - 1) ? "" : ",")));
136
137		DEBUGADD(5, ("\n"));
138	}
139
140	key = namecache_key(name, name_type);
141	expiry = time(NULL) + lp_name_cache_timeout();
142
143	/*
144	 * Generate string representation of ip addresses list
145	 * First, store the number of ip addresses and then
146	 * place each single ip
147	 */
148	if (!ipstr_list_make(&value_string, ip_list, num_names)) {
149		SAFE_FREE(key);
150		SAFE_FREE(value_string);
151		return False;
152	}
153
154	/* set the entry */
155	ret = gencache_set(key, value_string, expiry);
156	SAFE_FREE(key);
157	SAFE_FREE(value_string);
158	return ret;
159}
160
161
162/**
163 * Look up a name in the cache.
164 *
165 * @param name netbios name to look up for
166 * @param name_type netbios name type of @param name
167 * @param ip_list mallocated list of IP addresses if found in the cache,
168 *        NULL otherwise
169 * @param num_names number of entries found
170 *
171 * @return true upon successful fetch or
172 *         false if name isn't found in the cache or has expired
173 **/
174
175BOOL namecache_fetch(const char *name, int name_type, struct ip_service **ip_list,
176                     int *num_names)
177{
178	char *key, *value;
179	time_t timeout;
180
181	*num_names = 0;
182
183	/* exit now if null pointers were passed as they're required further */
184	if (!ip_list || !num_names) return False;
185
186	if (!gencache_init())
187		return False;
188
189	/*
190	 * Use gencache interface - lookup the key
191	 */
192	key = namecache_key(name, name_type);
193
194	if (!gencache_get(key, &value, &timeout)) {
195		DEBUG(5, ("no entry for %s#%02X found.\n", name, name_type));
196		gencache_del(key);
197		SAFE_FREE(key);
198		SAFE_FREE(value);
199		return False;
200	} else {
201		DEBUG(5, ("name %s#%02X found.\n", name, name_type));
202	}
203
204	/*
205	 * Split up the stored value into the list of IP adresses
206	 */
207	*num_names = ipstr_list_parse(value, ip_list);
208
209	SAFE_FREE(key);
210	SAFE_FREE(value);
211
212	return *num_names > 0;		/* true only if some ip has been fetched */
213}
214
215
216/**
217 * Delete single namecache entry. Look at the
218 * gencache_iterate definition.
219 *
220 **/
221
222static void flush_netbios_name(const char* key, const char *value, time_t timeout, void* dptr)
223{
224	gencache_del(key);
225	DEBUG(5, ("Deleting entry %s\n", key));
226}
227
228
229/**
230 * Flush all names from the name cache.
231 * It's done by gencache_iterate()
232 *
233 * @return True upon successful deletion or
234 *         False in case of an error
235 **/
236
237void namecache_flush(void)
238{
239	if (!gencache_init())
240		return;
241
242	/*
243	 * iterate through each NBT cache's entry and flush it
244	 * by flush_netbios_name function
245	 */
246	gencache_iterate(flush_netbios_name, NULL, "NBT/*");
247	DEBUG(5, ("Namecache flushed\n"));
248}
249
250/* Construct a name status record key. */
251
252static char *namecache_status_record_key(const char *name, int name_type1,
253				int name_type2, struct in_addr keyip)
254{
255	char *keystr;
256
257	asprintf(&keystr, "NBT/%s#%02X.%02X.%s",
258			strupper_static(name), name_type1, name_type2, inet_ntoa(keyip));
259	return keystr;
260}
261
262/* Store a name status record. */
263
264BOOL namecache_status_store(const char *keyname, int keyname_type,
265		int name_type, struct in_addr keyip,
266		const char *srvname)
267{
268	char *key;
269	time_t expiry;
270	BOOL ret;
271
272	if (!gencache_init())
273		return False;
274
275	key = namecache_status_record_key(keyname, keyname_type, name_type, keyip);
276	if (!key)
277		return False;
278
279	expiry = time(NULL) + lp_name_cache_timeout();
280	ret = gencache_set(key, srvname, expiry);
281
282	if (ret)
283		DEBUG(5, ("namecache_status_store: entry %s -> %s\n", key, srvname ));
284	else
285		DEBUG(5, ("namecache_status_store: entry %s store failed.\n", key ));
286
287	SAFE_FREE(key);
288	return ret;
289}
290
291/* Fetch a name status record. */
292
293BOOL namecache_status_fetch(const char *keyname, int keyname_type,
294			int name_type, struct in_addr keyip, char *srvname_out)
295{
296	char *key = NULL;
297	char *value = NULL;
298	time_t timeout;
299
300	if (!gencache_init())
301		return False;
302
303	key = namecache_status_record_key(keyname, keyname_type, name_type, keyip);
304	if (!key)
305		return False;
306
307	if (!gencache_get(key, &value, &timeout)) {
308		DEBUG(5, ("namecache_status_fetch: no entry for %s found.\n", key));
309		gencache_del(key);
310		SAFE_FREE(key);
311		SAFE_FREE(value);
312		return False;
313	} else {
314		DEBUG(5, ("namecache_status_fetch: key %s -> %s\n", key, value ));
315	}
316
317	strlcpy(srvname_out, value, 16);
318	SAFE_FREE(key);
319	SAFE_FREE(value);
320	return True;
321}
322