root/source3/libsmb/namecache.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. namecache_enable
  2. namecache_key
  3. namecache_store
  4. namecache_fetch
  5. namecache_delete
  6. flush_netbios_name
  7. namecache_flush
  8. namecache_status_record_key
  9. namecache_status_store
  10. namecache_status_fetch

   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 
  26 #define NBTKEY_FMT  "NBT/%s#%02X"
  27 
  28 /**
  29  * Initialise namecache system. Function calls gencache
  30  * initialisation function to perform necessary actions
  31  *
  32  * @return true upon successful initialisation of the cache or
  33  *         false on failure
  34  **/
  35 
  36 bool namecache_enable(void)
     /* [<][>][^][v][top][bottom][index][help] */
  37 {
  38         /*
  39          * Check if name caching disabled by setting the name cache
  40          * timeout to zero.
  41          */
  42 
  43         if (lp_name_cache_timeout() == 0) {
  44                 DEBUG(5, ("namecache_enable: disabling netbios name cache\n"));
  45                 return False;
  46         }
  47 
  48         /* Init namecache by calling gencache initialisation */
  49 
  50         if (!gencache_init()) {
  51                 DEBUG(2, ("namecache_enable: "
  52                         "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
  57          * need this (mimir, 27.09.2002) */
  58         DEBUG(5, ("namecache_enable: enabling netbios namecache, timeout %d "
  59                   "seconds\n", lp_name_cache_timeout()));
  60 
  61         return True;
  62 }
  63 
  64 /**
  65  * Generates a key for netbios name lookups on basis of
  66  * netbios name and type.
  67  * The caller must free returned key string when finished.
  68  *
  69  * @param name netbios name string (case insensitive)
  70  * @param name_type netbios type of the name being looked up
  71  *
  72  * @return string consisted of uppercased name and appended
  73  *         type number
  74  */
  75 
  76 static char* namecache_key(const char *name,
     /* [<][>][^][v][top][bottom][index][help] */
  77                                 int name_type)
  78 {
  79         char *keystr;
  80         asprintf_strupper_m(&keystr, NBTKEY_FMT, name, name_type);
  81 
  82         return keystr;
  83 }
  84 
  85 /**
  86  * Store a name(s) in the name cache
  87  *
  88  * @param name netbios names array
  89  * @param name_type integer netbios name type
  90  * @param num_names number of names being stored
  91  * @param ip_list array of in_addr structures containing
  92  *        ip addresses being stored
  93  **/
  94 
  95 bool namecache_store(const char *name,
     /* [<][>][^][v][top][bottom][index][help] */
  96                         int name_type,
  97                         int num_names,
  98                         struct ip_service *ip_list)
  99 {
 100         time_t expiry;
 101         char *key, *value_string;
 102         int i;
 103         bool ret;
 104 
 105         /*
 106          * we use gecache call to avoid annoying debug messages about
 107          * initialised namecache again and again...
 108          */
 109         if (!gencache_init()) {
 110                 return False;
 111         }
 112 
 113         if (name_type > 255) {
 114                 return False; /* Don't store non-real name types. */
 115         }
 116 
 117         if ( DEBUGLEVEL >= 5 ) {
 118                 TALLOC_CTX *ctx = talloc_stackframe();
 119                 char *addr = NULL;
 120 
 121                 DEBUG(5, ("namecache_store: storing %d address%s for %s#%02x: ",
 122                         num_names, num_names == 1 ? "": "es", name, name_type));
 123 
 124                 for (i = 0; i < num_names; i++) {
 125                         addr = print_canonical_sockaddr(ctx,
 126                                                         &ip_list[i].ss);
 127                         if (!addr) {
 128                                 continue;
 129                         }
 130                         DEBUGADD(5, ("%s%s", addr,
 131                                 (i == (num_names - 1) ? "" : ",")));
 132 
 133                 }
 134                 DEBUGADD(5, ("\n"));
 135                 TALLOC_FREE(ctx);
 136         }
 137 
 138         key = namecache_key(name, name_type);
 139         if (!key) {
 140                 return False;
 141         }
 142 
 143         expiry = time(NULL) + lp_name_cache_timeout();
 144 
 145         /*
 146          * Generate string representation of ip addresses list
 147          * First, store the number of ip addresses and then
 148          * place each single ip
 149          */
 150         if (!ipstr_list_make(&value_string, ip_list, num_names)) {
 151                 SAFE_FREE(key);
 152                 SAFE_FREE(value_string);
 153                 return false;
 154         }
 155 
 156         /* set the entry */
 157         ret = gencache_set(key, value_string, expiry);
 158         SAFE_FREE(key);
 159         SAFE_FREE(value_string);
 160         return ret;
 161 }
 162 
 163 /**
 164  * Look up a name in the cache.
 165  *
 166  * @param name netbios name to look up for
 167  * @param name_type netbios name type of @param name
 168  * @param ip_list mallocated list of IP addresses if found in the cache,
 169  *        NULL otherwise
 170  * @param num_names number of entries found
 171  *
 172  * @return true upon successful fetch or
 173  *         false if name isn't found in the cache or has expired
 174  **/
 175 
 176 bool namecache_fetch(const char *name,
     /* [<][>][^][v][top][bottom][index][help] */
 177                         int name_type,
 178                         struct ip_service **ip_list,
 179                         int *num_names)
 180 {
 181         char *key, *value;
 182         time_t timeout;
 183 
 184         /* exit now if null pointers were passed as they're required further */
 185         if (!ip_list || !num_names) {
 186                 return False;
 187         }
 188 
 189         if (!gencache_init()) {
 190                 return False;
 191         }
 192 
 193         if (name_type > 255) {
 194                 return False; /* Don't fetch non-real name types. */
 195         }
 196 
 197         *num_names = 0;
 198 
 199         /*
 200          * Use gencache interface - lookup the key
 201          */
 202         key = namecache_key(name, name_type);
 203         if (!key) {
 204                 return False;
 205         }
 206 
 207         if (!gencache_get(key, &value, &timeout)) {
 208                 DEBUG(5, ("no entry for %s#%02X found.\n", name, name_type));
 209                 SAFE_FREE(key);
 210                 return False;
 211         } else {
 212                 DEBUG(5, ("name %s#%02X found.\n", name, name_type));
 213         }
 214 
 215         /*
 216          * Split up the stored value into the list of IP adresses
 217          */
 218         *num_names = ipstr_list_parse(value, ip_list);
 219 
 220         SAFE_FREE(key);
 221         SAFE_FREE(value);
 222 
 223         return *num_names > 0; /* true only if some ip has been fetched */
 224 }
 225 
 226 /**
 227  * Remove a namecache entry. Needed for site support.
 228  *
 229  **/
 230 
 231 bool namecache_delete(const char *name, int name_type)
     /* [<][>][^][v][top][bottom][index][help] */
 232 {
 233         bool ret;
 234         char *key;
 235 
 236         if (!gencache_init())
 237                 return False;
 238 
 239         if (name_type > 255) {
 240                 return False; /* Don't fetch non-real name types. */
 241         }
 242 
 243         key = namecache_key(name, name_type);
 244         if (!key) {
 245                 return False;
 246         }
 247         ret = gencache_del(key);
 248         SAFE_FREE(key);
 249         return ret;
 250 }
 251 
 252 /**
 253  * Delete single namecache entry. Look at the
 254  * gencache_iterate definition.
 255  *
 256  **/
 257 
 258 static void flush_netbios_name(const char *key,
     /* [<][>][^][v][top][bottom][index][help] */
 259                         const char *value,
 260                         time_t timeout,
 261                         void *dptr)
 262 {
 263         gencache_del(key);
 264         DEBUG(5, ("Deleting entry %s\n", key));
 265 }
 266 
 267 /**
 268  * Flush all names from the name cache.
 269  * It's done by gencache_iterate()
 270  *
 271  * @return true upon successful deletion or
 272  *         false in case of an error
 273  **/
 274 
 275 void namecache_flush(void)
     /* [<][>][^][v][top][bottom][index][help] */
 276 {
 277         if (!gencache_init()) {
 278                 return;
 279         }
 280 
 281         /*
 282          * iterate through each NBT cache's entry and flush it
 283          * by flush_netbios_name function
 284          */
 285         gencache_iterate(flush_netbios_name, NULL, "NBT/*");
 286         DEBUG(5, ("Namecache flushed\n"));
 287 }
 288 
 289 /* Construct a name status record key. */
 290 
 291 static char *namecache_status_record_key(const char *name,
     /* [<][>][^][v][top][bottom][index][help] */
 292                                 int name_type1,
 293                                 int name_type2,
 294                                 const struct sockaddr_storage *keyip)
 295 {
 296         char addr[INET6_ADDRSTRLEN];
 297         char *keystr;
 298 
 299         print_sockaddr(addr, sizeof(addr), keyip);
 300         asprintf_strupper_m(&keystr, "NBT/%s#%02X.%02X.%s", name,
 301                             name_type1, name_type2, addr);
 302         return keystr;
 303 }
 304 
 305 /* Store a name status record. */
 306 
 307 bool namecache_status_store(const char *keyname, int keyname_type,
     /* [<][>][^][v][top][bottom][index][help] */
 308                 int name_type, const struct sockaddr_storage *keyip,
 309                 const char *srvname)
 310 {
 311         char *key;
 312         time_t expiry;
 313         bool ret;
 314 
 315         if (!gencache_init()) {
 316                 return False;
 317         }
 318 
 319         key = namecache_status_record_key(keyname, keyname_type,
 320                         name_type, keyip);
 321         if (!key)
 322                 return False;
 323 
 324         expiry = time(NULL) + lp_name_cache_timeout();
 325         ret = gencache_set(key, srvname, expiry);
 326 
 327         if (ret) {
 328                 DEBUG(5, ("namecache_status_store: entry %s -> %s\n",
 329                                         key, srvname ));
 330         } else {
 331                 DEBUG(5, ("namecache_status_store: entry %s store failed.\n",
 332                                         key ));
 333         }
 334 
 335         SAFE_FREE(key);
 336         return ret;
 337 }
 338 
 339 /* Fetch a name status record. */
 340 
 341 bool namecache_status_fetch(const char *keyname,
     /* [<][>][^][v][top][bottom][index][help] */
 342                                 int keyname_type,
 343                                 int name_type,
 344                                 const struct sockaddr_storage *keyip,
 345                                 char *srvname_out)
 346 {
 347         char *key = NULL;
 348         char *value = NULL;
 349         time_t timeout;
 350 
 351         if (!gencache_init())
 352                 return False;
 353 
 354         key = namecache_status_record_key(keyname, keyname_type,
 355                         name_type, keyip);
 356         if (!key)
 357                 return False;
 358 
 359         if (!gencache_get(key, &value, &timeout)) {
 360                 DEBUG(5, ("namecache_status_fetch: no entry for %s found.\n",
 361                                         key));
 362                 SAFE_FREE(key);
 363                 return False;
 364         } else {
 365                 DEBUG(5, ("namecache_status_fetch: key %s -> %s\n",
 366                                         key, value ));
 367         }
 368 
 369         strlcpy(srvname_out, value, 16);
 370         SAFE_FREE(key);
 371         SAFE_FREE(value);
 372         return True;
 373 }

/* [<][>][^][v][top][bottom][index][help] */