source: branches/samba-3.3.x/source/libsmb/conncache.c@ 578

Last change on this file since 578 was 206, checked in by Herwig Bauernfeind, 16 years ago

Import Samba 3.3 branch at 3.0.0 level (psmedley's port)

File size: 6.7 KB
Line 
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 */
42static 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 */
54static char *negative_conn_cache_keystr(const char *domain, const char *server)
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 */
81static char *negative_conn_cache_valuestr(NTSTATUS status)
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 */
101static NTSTATUS negative_conn_cache_valuedecode(const char *value)
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 */
121static 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 */
136NTSTATUS 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, (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 */
162void 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 */
186void add_failed_connection_entry(const char *domain, const char *server,
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 */
225void flush_negative_conn_cache( void )
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 */
238void flush_negative_conn_cache_for_domain(const char *domain)
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}
Note: See TracBrowser for help on using the repository browser.