Use python.h from libreplace
[samba.git] / source3 / libsmb / namecache.c
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 #include "libsmb/namequery.h"
27
28 #define IPSTR_LIST_SEP  ","
29 #define IPSTR_LIST_CHAR ','
30
31 /**
32  * Allocate and initialise an ipstr list using samba_sockaddr ip addresses
33  * passed as arguments.
34  *
35  * @param ctx TALLOC_CTX to use
36  * @param ip_list array of ip addresses to place in the list
37  * @param ip_count number of addresses stored in ip_list
38  * @return pointer to allocated ip string
39  **/
40
41 static char *ipstr_list_make_sa(TALLOC_CTX *ctx,
42                         const struct samba_sockaddr *sa_list,
43                         size_t ip_count)
44 {
45         char *ipstr_list = NULL;
46         size_t i;
47
48         /* arguments checking */
49         if (sa_list == NULL) {
50                 return NULL;
51         }
52
53         /* process ip addresses given as arguments */
54         for (i = 0; i < ip_count; i++) {
55                 char addr_buf[INET6_ADDRSTRLEN];
56                 char *new_str = NULL;
57
58                 print_sockaddr(addr_buf,
59                                 sizeof(addr_buf),
60                                 &sa_list[i].u.ss);
61
62                 if (sa_list[i].u.ss.ss_family == AF_INET) {
63                         /* IPv4 - port no longer used, store 0 */
64                         new_str = talloc_asprintf(ctx,
65                                                 "%s:%d",
66                                                 addr_buf,
67                                                 0);
68                 } else {
69                         /* IPv6 - port no longer used, store 0 */
70                         new_str = talloc_asprintf(ctx,
71                                                 "[%s]:%d",
72                                                 addr_buf,
73                                                 0);
74                 }
75                 if (new_str == NULL) {
76                         TALLOC_FREE(ipstr_list);
77                         return NULL;
78                 }
79
80                 if (ipstr_list == NULL) {
81                         /* First ip address. */
82                         ipstr_list = new_str;
83                 } else {
84                         /*
85                          * Append the separator "," and then the new
86                          * ip address to the existing list.
87                          *
88                          * The efficiency here is horrible, but
89                          * ip_count should be small enough we can
90                          * live with it.
91                          */
92                         char *tmp = talloc_asprintf(ctx,
93                                                 "%s%s%s",
94                                                 ipstr_list,
95                                                 IPSTR_LIST_SEP,
96                                                 new_str);
97                         if (tmp == NULL) {
98                                 TALLOC_FREE(new_str);
99                                 TALLOC_FREE(ipstr_list);
100                                 return NULL;
101                         }
102                         TALLOC_FREE(new_str);
103                         TALLOC_FREE(ipstr_list);
104                         ipstr_list = tmp;
105                 }
106         }
107
108         return ipstr_list;
109 }
110
111 /**
112  * Parse given ip string list into array of ip addresses
113  * (as ip_service structures)
114  *    e.g. [IPv6]:port,192.168.1.100:389,192.168.1.78, ...
115  *
116  * @param ipstr ip string list to be parsed
117  * @param ip_list pointer to array of ip addresses which is
118  *        talloced by this function and must be freed by caller
119  * @return number of successfully parsed addresses
120  **/
121
122 static int ipstr_list_parse(TALLOC_CTX *ctx,
123                         const char *ipstr_list,
124                         struct samba_sockaddr **sa_list_out)
125 {
126         TALLOC_CTX *frame = talloc_stackframe();
127         struct samba_sockaddr *sa_list = NULL;
128         char *token_str = NULL;
129         size_t count;
130         size_t array_size;
131
132         *sa_list_out = NULL;
133
134         array_size = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
135         sa_list = talloc_zero_array(frame,
136                                 struct samba_sockaddr,
137                                 array_size);
138         if (sa_list == NULL) {
139                 TALLOC_FREE(frame);
140                 return 0;
141         }
142
143         count = 0;
144         while (next_token_talloc(frame,
145                                  &ipstr_list,
146                                  &token_str,
147                                  IPSTR_LIST_SEP)) {
148                 bool ok;
149                 char *s = token_str;
150                 char *p = strrchr(token_str, ':');
151                 struct sockaddr_storage ss;
152
153                 /* Ensure we don't overrun. */
154                 if (count >= array_size) {
155                         break;
156                 }
157
158                 if (p) {
159                         *p = 0;
160                         /* We now ignore the port. */
161                 }
162
163                 /* convert single token to ip address */
164                 if (token_str[0] == '[') {
165                         /* IPv6 address. */
166                         s++;
167                         p = strchr(token_str, ']');
168                         if (!p) {
169                                 continue;
170                         }
171                         *p = '\0';
172                 }
173                 ok = interpret_string_addr(&ss, s, AI_NUMERICHOST);
174                 if (!ok) {
175                         continue;
176                 }
177                 ok = sockaddr_storage_to_samba_sockaddr(&sa_list[count],
178                                                         &ss);
179                 if (!ok) {
180                         continue;
181                 }
182                 count++;
183         }
184         if (count > 0) {
185                 *sa_list_out = talloc_move(ctx, &sa_list);
186         }
187         TALLOC_FREE(frame);
188         return count;
189 }
190
191 #define NBTKEY_FMT  "NBT/%s#%02X"
192
193 /**
194  * Generates a key for netbios name lookups on basis of
195  * netbios name and type.
196  * The caller must free returned key string when finished.
197  *
198  * @param name netbios name string (case insensitive)
199  * @param name_type netbios type of the name being looked up
200  *
201  * @return string consisted of uppercased name and appended
202  *         type number
203  */
204
205 static char *namecache_key(TALLOC_CTX *ctx,
206                            const char *name,
207                            int name_type)
208 {
209         return talloc_asprintf_strupper_m(ctx,
210                                           NBTKEY_FMT,
211                                           name,
212                                           name_type);
213 }
214
215 /**
216  * Store a name(s) in the name cache - samba_sockaddr version.
217  *
218  * @param name netbios names array
219  * @param name_type integer netbios name type
220  * @param num_names number of names being stored
221  * @param ip_list array of in_addr structures containing
222  *        ip addresses being stored
223  **/
224
225 bool namecache_store(const char *name,
226                         int name_type,
227                         size_t num_names,
228                         struct samba_sockaddr *sa_list)
229 {
230         time_t expiry;
231         char *key = NULL;
232         char *value_string = NULL;
233         size_t i;
234         bool ret = false;
235         TALLOC_CTX *frame = talloc_stackframe();
236
237         if (name_type > 255) {
238                 /* Don't store non-real name types. */
239                 goto out;
240         }
241
242         if ( DEBUGLEVEL >= 5 ) {
243                 char *addr = NULL;
244
245                 DBG_INFO("storing %zu address%s for %s#%02x: ",
246                         num_names, num_names == 1 ? "": "es", name, name_type);
247
248                 for (i = 0; i < num_names; i++) {
249                         addr = print_canonical_sockaddr(frame,
250                                         &sa_list[i].u.ss);
251                         if (!addr) {
252                                 continue;
253                         }
254                         DEBUGADD(5, ("%s%s", addr,
255                                 (i == (num_names - 1) ? "" : ",")));
256
257                 }
258                 DEBUGADD(5, ("\n"));
259         }
260
261         key = namecache_key(frame, name, name_type);
262         if (!key) {
263                 goto out;
264         }
265
266         expiry = time(NULL) + lp_name_cache_timeout();
267
268         /*
269          * Generate string representation of ip addresses list
270          */
271         value_string = ipstr_list_make_sa(frame, sa_list, num_names);
272         if (value_string == NULL) {
273                 goto out;
274         }
275
276         /* set the entry */
277         ret = gencache_set(key, value_string, expiry);
278
279   out:
280
281         TALLOC_FREE(key);
282         TALLOC_FREE(value_string);
283         TALLOC_FREE(frame);
284         return ret;
285 }
286
287 /**
288  * Look up a name in the cache.
289  *
290  * @param name netbios name to look up for
291  * @param name_type netbios name type of @param name
292  * @param ip_list talloced list of IP addresses if found in the cache,
293  *        NULL otherwise
294  * @param num_names number of entries found
295  *
296  * @return true upon successful fetch or
297  *         false if name isn't found in the cache or has expired
298  **/
299
300 bool namecache_fetch(TALLOC_CTX *ctx,
301                 const char *name,
302                 int name_type,
303                 struct samba_sockaddr **sa_list,
304                 size_t *num_names)
305 {
306         char *key, *value;
307         time_t timeout;
308
309         if (name_type > 255) {
310                 return false; /* Don't fetch non-real name types. */
311         }
312
313         *num_names = 0;
314
315         /*
316          * Use gencache interface - lookup the key
317          */
318         key = namecache_key(talloc_tos(), name, name_type);
319         if (!key) {
320                 return false;
321         }
322
323         if (!gencache_get(key, talloc_tos(), &value, &timeout)) {
324                 DBG_INFO("no entry for %s#%02X found.\n", name, name_type);
325                 TALLOC_FREE(key);
326                 return false;
327         }
328
329         DBG_INFO("name %s#%02X found.\n", name, name_type);
330
331         /*
332          * Split up the stored value into the list of IP addresses
333          */
334         *num_names = ipstr_list_parse(ctx, value, sa_list);
335
336         TALLOC_FREE(key);
337         TALLOC_FREE(value);
338
339         return *num_names > 0; /* true only if some ip has been fetched */
340 }
341
342 /**
343  * Remove a namecache entry. Needed for site support.
344  *
345  **/
346
347 bool namecache_delete(const char *name, int name_type)
348 {
349         bool ret;
350         char *key;
351
352         if (name_type > 255) {
353                 return false; /* Don't fetch non-real name types. */
354         }
355
356         key = namecache_key(talloc_tos(), name, name_type);
357         if (!key) {
358                 return false;
359         }
360         ret = gencache_del(key);
361         TALLOC_FREE(key);
362         return ret;
363 }
364
365 /**
366  * Delete single namecache entry. Look at the
367  * gencache_iterate definition.
368  *
369  **/
370
371 static void flush_netbios_name(const char *key,
372                         const char *value,
373                         time_t timeout,
374                         void *dptr)
375 {
376         gencache_del(key);
377         DBG_INFO("Deleting entry %s\n", key);
378 }
379
380 /**
381  * Flush all names from the name cache.
382  * It's done by gencache_iterate()
383  *
384  * @return true upon successful deletion or
385  *         false in case of an error
386  **/
387
388 void namecache_flush(void)
389 {
390         /*
391          * iterate through each NBT cache's entry and flush it
392          * by flush_netbios_name function
393          */
394         gencache_iterate(flush_netbios_name, NULL, "NBT/*");
395         DBG_INFO("Namecache flushed\n");
396 }
397
398 /* Construct a name status record key. */
399
400 static char *namecache_status_record_key(TALLOC_CTX *ctx,
401                                 const char *name,
402                                 int name_type1,
403                                 int name_type2,
404                                 const struct sockaddr_storage *keyip)
405 {
406         char addr[INET6_ADDRSTRLEN];
407
408         print_sockaddr(addr, sizeof(addr), keyip);
409         return talloc_asprintf_strupper_m(ctx,
410                                           "NBT/%s#%02X.%02X.%s",
411                                           name,
412                                           name_type1,
413                                           name_type2,
414                                           addr);
415 }
416
417 /* Store a name status record. */
418
419 bool namecache_status_store(const char *keyname, int keyname_type,
420                 int name_type, const struct sockaddr_storage *keyip,
421                 const char *srvname)
422 {
423         char *key;
424         time_t expiry;
425         bool ret;
426
427         key = namecache_status_record_key(talloc_tos(),
428                                           keyname,
429                                           keyname_type,
430                                           name_type,
431                                           keyip);
432         if (!key)
433                 return false;
434
435         expiry = time(NULL) + lp_name_cache_timeout();
436         ret = gencache_set(key, srvname, expiry);
437
438         if (ret) {
439                 DBG_INFO("entry %s -> %s\n", key, srvname);
440         } else {
441                 DBG_INFO("entry %s store failed.\n", key);
442         }
443
444         TALLOC_FREE(key);
445         return ret;
446 }
447
448 /* Fetch a name status record. */
449
450 bool namecache_status_fetch(const char *keyname,
451                                 int keyname_type,
452                                 int name_type,
453                                 const struct sockaddr_storage *keyip,
454                                 char *srvname_out)
455 {
456         char *key = NULL;
457         char *value = NULL;
458         time_t timeout;
459
460         key = namecache_status_record_key(talloc_tos(),
461                                           keyname,
462                                           keyname_type,
463                                           name_type,
464                                           keyip);
465         if (!key)
466                 return false;
467
468         if (!gencache_get(key, talloc_tos(), &value, &timeout)) {
469                 DBG_INFO("no entry for %s found.\n", key);
470                 TALLOC_FREE(key);
471                 return false;
472         } else {
473                 DBG_INFO("key %s -> %s\n", key, value);
474         }
475
476         strlcpy(srvname_out, value, 16);
477         TALLOC_FREE(key);
478         TALLOC_FREE(value);
479         return true;
480 }