root/source3/libsmb/conncache.c

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

DEFINITIONS

This source file includes following definitions.
  1. negative_conn_cache_keystr
  2. negative_conn_cache_valuestr
  3. negative_conn_cache_valuedecode
  4. delete_matches
  5. check_negative_conn_cache
  6. delete_negative_conn_cache
  7. add_failed_connection_entry
  8. flush_negative_conn_cache
  9. flush_negative_conn_cache_for_domain

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    Winbind daemon connection manager
   5 
   6    Copyright (C) Tim Potter             2001
   7    Copyright (C) Andrew Bartlett        2002
   8    Copyright (C) Gerald (Jerry) Carter  2003
   9    Copyright (C) Marc VanHeyningen      2008
  10    
  11    This program is free software; you can redistribute it and/or modify
  12    it under the terms of the GNU General Public License as published by
  13    the Free Software Foundation; either version 3 of the License, or
  14    (at your option) any later version.
  15    
  16    This program is distributed in the hope that it will be useful,
  17    but WITHOUT ANY WARRANTY; without even the implied warranty of
  18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19    GNU General Public License for more details.
  20    
  21    You should have received a copy of the GNU General Public License
  22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  23 */
  24 
  25 
  26 #include "includes.h"
  27 
  28 /**
  29  * @file
  30  * Negative connection cache implemented in terms of gencache API
  31  *
  32  * The negative connection cache stores names of servers which have
  33  * been unresponsive so that we don't waste time repeatedly trying
  34  * to contact them.  It used to use an in-memory linked list, but
  35  * this limited its utility to a single process
  36  */
  37 
  38 
  39 /**
  40  * prefix used for all entries put into the general cache
  41  */
  42 static const char NEGATIVE_CONN_CACHE_PREFIX[] = "NEG_CONN_CACHE";
  43 
  44 /**
  45  * Marshalls the domain and server name into the key for the gencache
  46  * record
  47  *
  48  * @param[in] domain required
  49  * @param[in] server may be a FQDN or an IP address
  50  * @return the resulting string, which the caller is responsible for
  51  *   SAFE_FREE()ing
  52  * @retval NULL returned on error
  53  */
  54 static char *negative_conn_cache_keystr(const char *domain, const char *server)
     /* [<][>][^][v][top][bottom][index][help] */
  55 {
  56         const char NEGATIVE_CONN_CACHE_KEY_FMT[] = "%s/%s,%s";
  57         char *keystr = NULL;
  58 
  59         SMB_ASSERT(domain != NULL);
  60         if (server == NULL)
  61                 server = "";
  62 
  63         keystr = talloc_asprintf(talloc_tos(),NEGATIVE_CONN_CACHE_KEY_FMT,
  64                                  NEGATIVE_CONN_CACHE_PREFIX, domain, server);
  65         if (keystr == NULL) {
  66                 DEBUG(0, ("negative_conn_cache_keystr: malloc error\n"));
  67         }
  68 
  69         return keystr;
  70 }
  71 
  72 /**
  73  * Marshalls the NT status into a printable value field for the gencache
  74  * record
  75  *
  76  * @param[in] status
  77  * @return the resulting string, which the caller is responsible for
  78  *   SAFE_FREE()ing
  79  * @retval NULL returned on error
  80  */
  81 static char *negative_conn_cache_valuestr(NTSTATUS status)
     /* [<][>][^][v][top][bottom][index][help] */
  82 {
  83         char *valuestr = NULL;
  84 
  85         valuestr = talloc_asprintf(talloc_tos(), "%x", NT_STATUS_V(status));
  86         if (valuestr == NULL) {
  87                 DEBUG(0, ("negative_conn_cache_valuestr: malloc error\n"));
  88         }
  89 
  90         return valuestr;
  91 }
  92 
  93 /**
  94  * Un-marshalls the NT status from a printable field for the gencache
  95  * record
  96  *
  97  * @param[in] value  The value field from the record
  98  * @return the decoded NT status
  99  * @retval NT_STATUS_OK returned on error
 100  */
 101 static NTSTATUS negative_conn_cache_valuedecode(const char *value)
     /* [<][>][^][v][top][bottom][index][help] */
 102 {
 103         NTSTATUS result = NT_STATUS_OK;
 104 
 105         SMB_ASSERT(value != NULL);
 106         if (sscanf(value, "%x", &(NT_STATUS_V(result))) != 1)
 107                 DEBUG(0, ("negative_conn_cache_valuestr: unable to parse "
 108                           "value field '%s'\n", value));
 109         return result;
 110 }
 111 
 112 /**
 113  * Function passed to gencache_iterate to remove any matching items
 114  * from the list
 115  *
 116  * @param[in] key Key to the record found and to be deleted
 117  * @param[in] value Value to the record (ignored)
 118  * @param[in] timeout Timeout remaining for the record (ignored)
 119  * @param[in] dptr Handle for passing additional data (ignored)
 120  */
 121 static void delete_matches(const char *key, const char *value,
     /* [<][>][^][v][top][bottom][index][help] */
 122     time_t timeout, void *dptr)
 123 {
 124         gencache_del(key);
 125 }
 126 
 127 
 128 /**
 129  * Checks for a given domain/server record in the negative cache
 130  *
 131  * @param[in] domain
 132  * @param[in] server may be either a FQDN or an IP address
 133  * @return The cached failure status
 134  * @retval NT_STATUS_OK returned if no record is found or an error occurs
 135  */
 136 NTSTATUS check_negative_conn_cache( const char *domain, const char *server)
     /* [<][>][^][v][top][bottom][index][help] */
 137 {
 138         NTSTATUS result = NT_STATUS_OK;
 139         char *key = NULL;
 140         char *value = NULL;
 141 
 142         key = negative_conn_cache_keystr(domain, server);
 143         if (key == NULL)
 144                 goto done;
 145 
 146         if (gencache_get(key, &value, (time_t *) NULL))
 147                 result = negative_conn_cache_valuedecode(value);
 148  done:
 149         DEBUG(9,("check_negative_conn_cache returning result %d for domain %s "
 150                   "server %s\n", NT_STATUS_V(result), domain, server));
 151         TALLOC_FREE(key);
 152         SAFE_FREE(value);
 153         return result;
 154 }
 155 
 156 /**
 157  * Delete any negative cache entry for the given domain/server
 158  *
 159  * @param[in] domain
 160  * @param[in] server may be either a FQDN or an IP address
 161  */
 162 void delete_negative_conn_cache(const char *domain, const char *server)
     /* [<][>][^][v][top][bottom][index][help] */
 163 {
 164         char *key = NULL;
 165 
 166         key = negative_conn_cache_keystr(domain, server);
 167         if (key == NULL)
 168                 goto done;
 169 
 170         gencache_del(key);
 171         DEBUG(9,("delete_negative_conn_cache removing domain %s server %s\n",
 172                   domain, server));
 173  done:
 174         TALLOC_FREE(key);
 175         return;
 176 }
 177 
 178 
 179 /**
 180  * Add an entry to the failed connection cache
 181  *
 182  * @param[in] domain
 183  * @param[in] server may be a FQDN or an IP addr in printable form
 184  * @param[in] result error to cache; must not be NT_STATUS_OK
 185  */
 186 void add_failed_connection_entry(const char *domain, const char *server,
     /* [<][>][^][v][top][bottom][index][help] */
 187     NTSTATUS result)
 188 {
 189         char *key = NULL;
 190         char *value = NULL;
 191 
 192         SMB_ASSERT(!NT_STATUS_IS_OK(result));
 193 
 194         key = negative_conn_cache_keystr(domain, server);
 195         if (key == NULL) {
 196                 DEBUG(0, ("add_failed_connection_entry: key creation error\n"));
 197                 goto done;
 198         }
 199 
 200         value = negative_conn_cache_valuestr(result);
 201         if (value == NULL) {
 202                 DEBUG(0, ("add_failed_connection_entry: value creation error\n"));
 203                 goto done;
 204         }
 205 
 206         if (gencache_set(key, value,
 207                          time((time_t *) NULL)
 208                          + FAILED_CONNECTION_CACHE_TIMEOUT))
 209                 DEBUG(9,("add_failed_connection_entry: added domain %s (%s) "
 210                           "to failed conn cache\n", domain, server ));
 211         else
 212                 DEBUG(1,("add_failed_connection_entry: failed to add "
 213                           "domain %s (%s) to failed conn cache\n",
 214                           domain, server));
 215         
 216  done:
 217         TALLOC_FREE(key);
 218         TALLOC_FREE(value);
 219         return;
 220 }
 221 
 222 /**
 223  * Deletes all records from the negative connection cache in all domains
 224  */
 225 void flush_negative_conn_cache( void )
     /* [<][>][^][v][top][bottom][index][help] */
 226 {
 227         flush_negative_conn_cache_for_domain("*");
 228 }
 229 
 230 
 231 /**
 232  * Deletes all records for a specified domain from the negative connection
 233  * cache
 234  *
 235  * @param[in] domain String to match against domain portion of keys, or "*"
 236  *  to match all domains
 237  */
 238 void flush_negative_conn_cache_for_domain(const char *domain)
     /* [<][>][^][v][top][bottom][index][help] */
 239 {
 240         char *key_pattern = NULL;
 241 
 242         key_pattern = negative_conn_cache_keystr(domain,"*");
 243         if (key_pattern == NULL) {
 244                 DEBUG(0, ("flush_negative_conn_cache_for_domain: "
 245                           "key creation error\n"));
 246                 goto done;
 247         }
 248 
 249         gencache_iterate(delete_matches, (void *) NULL, key_pattern);
 250         DEBUG(8, ("flush_negative_conn_cache_for_domain: flushed domain %s\n",
 251                   domain));
 252         
 253  done:
 254         TALLOC_FREE(key_pattern);
 255         return;
 256 }

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