2 Unix SMB/CIFS implementation.
4 NetBIOS name cache module on top of gencache mechanism.
6 Copyright (C) Tim Potter 2002
7 Copyright (C) Rafal Szczesniak 2002
8 Copyright (C) Jeremy Allison 2007
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.
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.
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/>.
25 #include "lib/gencache.h"
26 #include "libsmb/namequery.h"
28 #define IPSTR_LIST_SEP ","
29 #define IPSTR_LIST_CHAR ','
32 * Allocate and initialise an ipstr list using samba_sockaddr ip adresses
33 * passed as arguments.
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
41 static char *ipstr_list_make_sa(TALLOC_CTX
*ctx
,
42 const struct samba_sockaddr
*sa_list
,
45 char *ipstr_list
= NULL
;
48 /* arguments checking */
49 if (sa_list
== NULL
) {
53 /* process ip addresses given as arguments */
54 for (i
= 0; i
< ip_count
; i
++) {
55 char addr_buf
[INET6_ADDRSTRLEN
];
58 print_sockaddr(addr_buf
,
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
,
69 /* IPv6 - port no longer used, store 0 */
70 new_str
= talloc_asprintf(ctx
,
75 if (new_str
== NULL
) {
76 TALLOC_FREE(ipstr_list
);
80 if (ipstr_list
== NULL
) {
81 /* First ip address. */
85 * Append the separator "," and then the new
86 * ip address to the existing list.
88 * The efficiency here is horrible, but
89 * ip_count should be small enough we can
92 char *tmp
= talloc_asprintf(ctx
,
99 TALLOC_FREE(ipstr_list
);
102 TALLOC_FREE(new_str
);
103 TALLOC_FREE(ipstr_list
);
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, ...
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
122 static int ipstr_list_parse(TALLOC_CTX
*ctx
,
123 const char *ipstr_list
,
124 struct samba_sockaddr
**sa_list_out
)
126 TALLOC_CTX
*frame
= talloc_stackframe();
127 struct samba_sockaddr
*sa_list
= NULL
;
128 char *token_str
= NULL
;
134 array_size
= count_chars(ipstr_list
, IPSTR_LIST_CHAR
) + 1;
135 sa_list
= talloc_zero_array(frame
,
136 struct samba_sockaddr
,
138 if (sa_list
== NULL
) {
144 for (i
=0; next_token_talloc(frame
, &ipstr_list
, &token_str
,
145 IPSTR_LIST_SEP
); i
++ ) {
148 char *p
= strrchr(token_str
, ':');
149 struct sockaddr_storage ss
;
151 /* Ensure we don't overrun. */
152 if (count
>= array_size
) {
158 /* We now ignore the port. */
161 /* convert single token to ip address */
162 if (token_str
[0] == '[') {
165 p
= strchr(token_str
, ']');
171 ok
= interpret_string_addr(&ss
, s
, AI_NUMERICHOST
);
175 ok
= sockaddr_storage_to_samba_sockaddr(&sa_list
[count
],
183 *sa_list_out
= talloc_move(ctx
, &sa_list
);
189 #define NBTKEY_FMT "NBT/%s#%02X"
192 * Generates a key for netbios name lookups on basis of
193 * netbios name and type.
194 * The caller must free returned key string when finished.
196 * @param name netbios name string (case insensitive)
197 * @param name_type netbios type of the name being looked up
199 * @return string consisted of uppercased name and appended
203 static char *namecache_key(TALLOC_CTX
*ctx
,
207 return talloc_asprintf_strupper_m(ctx
,
214 * Store a name(s) in the name cache - samba_sockaddr version.
216 * @param name netbios names array
217 * @param name_type integer netbios name type
218 * @param num_names number of names being stored
219 * @param ip_list array of in_addr structures containing
220 * ip addresses being stored
223 bool namecache_store(const char *name
,
226 struct samba_sockaddr
*sa_list
)
230 char *value_string
= NULL
;
233 TALLOC_CTX
*frame
= talloc_stackframe();
235 if (name_type
> 255) {
236 /* Don't store non-real name types. */
240 if ( DEBUGLEVEL
>= 5 ) {
243 DBG_INFO("storing %zu address%s for %s#%02x: ",
244 num_names
, num_names
== 1 ? "": "es", name
, name_type
);
246 for (i
= 0; i
< num_names
; i
++) {
247 addr
= print_canonical_sockaddr(frame
,
252 DEBUGADD(5, ("%s%s", addr
,
253 (i
== (num_names
- 1) ? "" : ",")));
259 key
= namecache_key(frame
, name
, name_type
);
264 expiry
= time(NULL
) + lp_name_cache_timeout();
267 * Generate string representation of ip addresses list
269 value_string
= ipstr_list_make_sa(frame
, sa_list
, num_names
);
270 if (value_string
== NULL
) {
275 ret
= gencache_set(key
, value_string
, expiry
);
280 TALLOC_FREE(value_string
);
286 * Look up a name in the cache.
288 * @param name netbios name to look up for
289 * @param name_type netbios name type of @param name
290 * @param ip_list talloced list of IP addresses if found in the cache,
292 * @param num_names number of entries found
294 * @return true upon successful fetch or
295 * false if name isn't found in the cache or has expired
298 bool namecache_fetch(TALLOC_CTX
*ctx
,
301 struct samba_sockaddr
**sa_list
,
307 if (name_type
> 255) {
308 return false; /* Don't fetch non-real name types. */
314 * Use gencache interface - lookup the key
316 key
= namecache_key(talloc_tos(), name
, name_type
);
321 if (!gencache_get(key
, talloc_tos(), &value
, &timeout
)) {
322 DBG_INFO("no entry for %s#%02X found.\n", name
, name_type
);
327 DBG_INFO("name %s#%02X found.\n", name
, name_type
);
330 * Split up the stored value into the list of IP adresses
332 *num_names
= ipstr_list_parse(ctx
, value
, sa_list
);
337 return *num_names
> 0; /* true only if some ip has been fetched */
341 * Remove a namecache entry. Needed for site support.
345 bool namecache_delete(const char *name
, int name_type
)
350 if (name_type
> 255) {
351 return false; /* Don't fetch non-real name types. */
354 key
= namecache_key(talloc_tos(), name
, name_type
);
358 ret
= gencache_del(key
);
364 * Delete single namecache entry. Look at the
365 * gencache_iterate definition.
369 static void flush_netbios_name(const char *key
,
375 DBG_INFO("Deleting entry %s\n", key
);
379 * Flush all names from the name cache.
380 * It's done by gencache_iterate()
382 * @return true upon successful deletion or
383 * false in case of an error
386 void namecache_flush(void)
389 * iterate through each NBT cache's entry and flush it
390 * by flush_netbios_name function
392 gencache_iterate(flush_netbios_name
, NULL
, "NBT/*");
393 DBG_INFO("Namecache flushed\n");
396 /* Construct a name status record key. */
398 static char *namecache_status_record_key(TALLOC_CTX
*ctx
,
402 const struct sockaddr_storage
*keyip
)
404 char addr
[INET6_ADDRSTRLEN
];
406 print_sockaddr(addr
, sizeof(addr
), keyip
);
407 return talloc_asprintf_strupper_m(ctx
,
408 "NBT/%s#%02X.%02X.%s",
415 /* Store a name status record. */
417 bool namecache_status_store(const char *keyname
, int keyname_type
,
418 int name_type
, const struct sockaddr_storage
*keyip
,
425 key
= namecache_status_record_key(talloc_tos(),
433 expiry
= time(NULL
) + lp_name_cache_timeout();
434 ret
= gencache_set(key
, srvname
, expiry
);
437 DBG_INFO("entry %s -> %s\n", key
, srvname
);
439 DBG_INFO("entry %s store failed.\n", key
);
446 /* Fetch a name status record. */
448 bool namecache_status_fetch(const char *keyname
,
451 const struct sockaddr_storage
*keyip
,
458 key
= namecache_status_record_key(talloc_tos(),
466 if (!gencache_get(key
, talloc_tos(), &value
, &timeout
)) {
467 DBG_INFO("no entry for %s found.\n", key
);
471 DBG_INFO("key %s -> %s\n", key
, value
);
474 strlcpy(srvname_out
, value
, 16);