s3: Remove some unnecessary variables from libsmb/conn_cache.c
[ira/wip.git] / source3 / libsmb / conncache.c
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    Copyright (C) Volker Lendecke        2009
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16    
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21    
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26
27 #include "includes.h"
28
29 /**
30  * @file
31  * Negative connection cache implemented in terms of gencache API
32  *
33  * The negative connection cache stores names of servers which have
34  * been unresponsive so that we don't waste time repeatedly trying
35  * to contact them.  It used to use an in-memory linked list, but
36  * this limited its utility to a single process
37  */
38
39
40 /**
41  * Marshalls the domain and server name into the key for the gencache
42  * record
43  *
44  * @param[in] domain required
45  * @param[in] server may be a FQDN or an IP address
46  * @return the resulting string, which the caller is responsible for
47  *   SAFE_FREE()ing
48  * @retval NULL returned on error
49  */
50 static char *negative_conn_cache_keystr(const char *domain, const char *server)
51 {
52         char *keystr = NULL;
53
54         if (domain == NULL) {
55                 return NULL;
56         }
57         if (server == NULL)
58                 server = "";
59
60         keystr = talloc_asprintf(talloc_tos(), "NEG_CONN_CACHE/%s,%s",
61                                  domain, server);
62         if (keystr == NULL) {
63                 DEBUG(0, ("negative_conn_cache_keystr: malloc error\n"));
64         }
65
66         return keystr;
67 }
68
69 /**
70  * Marshalls the NT status into a printable value field for the gencache
71  * record
72  *
73  * @param[in] status
74  * @return the resulting string, which the caller is responsible for
75  *   SAFE_FREE()ing
76  * @retval NULL returned on error
77  */
78 static char *negative_conn_cache_valuestr(NTSTATUS status)
79 {
80         char *valuestr = NULL;
81
82         valuestr = talloc_asprintf(talloc_tos(), "%x", NT_STATUS_V(status));
83         if (valuestr == NULL) {
84                 DEBUG(0, ("negative_conn_cache_valuestr: malloc error\n"));
85         }
86
87         return valuestr;
88 }
89
90 /**
91  * Un-marshalls the NT status from a printable field for the gencache
92  * record
93  *
94  * @param[in] value  The value field from the record
95  * @return the decoded NT status
96  * @retval NT_STATUS_OK returned on error
97  */
98 static NTSTATUS negative_conn_cache_valuedecode(const char *value)
99 {
100         unsigned int v = NT_STATUS_V(NT_STATUS_INTERNAL_ERROR);;
101
102         if (value != NULL) {
103                 return NT_STATUS_INTERNAL_ERROR;
104         }
105         if (sscanf(value, "%x", &v) != 1) {
106                 DEBUG(0, ("negative_conn_cache_valuedecode: unable to parse "
107                           "value field '%s'\n", value));
108         }
109         return NT_STATUS(v);
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,
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)
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, 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)
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,
187     NTSTATUS result)
188 {
189         char *key = NULL;
190         char *value = NULL;
191
192         if (NT_STATUS_IS_OK(result)) {
193                 /* Nothing failed here */
194                 return;
195         }
196
197         key = negative_conn_cache_keystr(domain, server);
198         if (key == NULL) {
199                 DEBUG(0, ("add_failed_connection_entry: key creation error\n"));
200                 goto done;
201         }
202
203         value = negative_conn_cache_valuestr(result);
204         if (value == NULL) {
205                 DEBUG(0, ("add_failed_connection_entry: value creation error\n"));
206                 goto done;
207         }
208
209         if (gencache_set(key, value,
210                          time(NULL) + FAILED_CONNECTION_CACHE_TIMEOUT))
211                 DEBUG(9,("add_failed_connection_entry: added domain %s (%s) "
212                           "to failed conn cache\n", domain, server ));
213         else
214                 DEBUG(1,("add_failed_connection_entry: failed to add "
215                           "domain %s (%s) to failed conn cache\n",
216                           domain, server));
217         
218  done:
219         TALLOC_FREE(key);
220         TALLOC_FREE(value);
221         return;
222 }
223
224 /**
225  * Deletes all records from the negative connection cache in all domains
226  */
227 void flush_negative_conn_cache( void )
228 {
229         flush_negative_conn_cache_for_domain("*");
230 }
231
232
233 /**
234  * Deletes all records for a specified domain from the negative connection
235  * cache
236  *
237  * @param[in] domain String to match against domain portion of keys, or "*"
238  *  to match all domains
239  */
240 void flush_negative_conn_cache_for_domain(const char *domain)
241 {
242         char *key_pattern = NULL;
243
244         key_pattern = negative_conn_cache_keystr(domain,"*");
245         if (key_pattern == NULL) {
246                 DEBUG(0, ("flush_negative_conn_cache_for_domain: "
247                           "key creation error\n"));
248                 goto done;
249         }
250
251         gencache_iterate(delete_matches, NULL, key_pattern);
252         DEBUG(8, ("flush_negative_conn_cache_for_domain: flushed domain %s\n",
253                   domain));
254
255  done:
256         TALLOC_FREE(key_pattern);
257         return;
258 }