~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/libsmb/namecache.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
37
 
BOOL 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
 
 
72
 
BOOL 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
 
 
96
 
static 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
 
 
115
 
BOOL 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
 
 
175
 
BOOL 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
 
 
222
 
static 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
 
 
237
 
void 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
 
 
252
 
static 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
 
 
264
 
BOOL 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
 
 
293
 
BOOL 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
 
}