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