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