s3:tests: let modprinter.pl use $TMPDIR
[Samba.git] / source3 / libsmb / conncache.c
blob7310b508a3b3f9b5b72733dc5db0281e05d92a18
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
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
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.
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.
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/>.
27 #include "includes.h"
28 #include "lib/gencache.h"
30 /**
31 * @file
32 * Negative connection cache implemented in terms of gencache API
34 * The negative connection cache stores names of servers which have
35 * been unresponsive so that we don't waste time repeatedly trying
36 * to contact them. It used to use an in-memory linked list, but
37 * this limited its utility to a single process
41 /**
42 * Marshalls the domain and server name into the key for the gencache
43 * record
45 * @param[in] domain required
46 * @param[in] server may be a FQDN or an IP address
47 * @return the resulting string, which the caller is responsible for
48 * SAFE_FREE()ing
49 * @retval NULL returned on error
51 static char *negative_conn_cache_keystr(const char *domain, const char *server)
53 char *keystr = NULL;
55 if (domain == NULL) {
56 return NULL;
58 if (server == NULL)
59 server = "";
61 keystr = talloc_asprintf(talloc_tos(), "NEG_CONN_CACHE/%s,%s",
62 domain, server);
63 if (keystr == NULL) {
64 DEBUG(0, ("negative_conn_cache_keystr: malloc error\n"));
67 return keystr;
70 /**
71 * Marshalls the NT status into a printable value field for the gencache
72 * record
74 * @param[in] status
75 * @return the resulting string, which the caller is responsible for
76 * SAFE_FREE()ing
77 * @retval NULL returned on error
79 static char *negative_conn_cache_valuestr(NTSTATUS status)
81 char *valuestr = NULL;
83 valuestr = talloc_asprintf(talloc_tos(), "%x", NT_STATUS_V(status));
84 if (valuestr == NULL) {
85 DEBUG(0, ("negative_conn_cache_valuestr: malloc error\n"));
88 return valuestr;
91 /**
92 * Un-marshalls the NT status from a printable field for the gencache
93 * record
95 * @param[in] value The value field from the record
96 * @return the decoded NT status
97 * @retval NT_STATUS_OK returned on error
99 static NTSTATUS negative_conn_cache_valuedecode(const char *value)
101 unsigned int v = NT_STATUS_V(NT_STATUS_INTERNAL_ERROR);
103 if (value == NULL) {
104 return NT_STATUS_INTERNAL_ERROR;
106 if (sscanf(value, "%x", &v) != 1) {
107 DEBUG(0, ("negative_conn_cache_valuedecode: unable to parse "
108 "value field '%s'\n", value));
110 return NT_STATUS(v);
114 * Function passed to gencache_iterate to remove any matching items
115 * from the list
117 * @param[in] key Key to the record found and to be deleted
118 * @param[in] value Value to the record (ignored)
119 * @param[in] timeout Timeout remaining for the record (ignored)
120 * @param[in] dptr Handle for passing additional data (ignored)
122 static void delete_matches(const char *key, const char *value,
123 time_t timeout, void *dptr)
125 gencache_del(key);
130 * Checks for a given domain/server record in the negative cache
132 * @param[in] domain
133 * @param[in] server may be either a FQDN or an IP address
134 * @return The cached failure status
135 * @retval NT_STATUS_OK returned if no record is found or an error occurs
137 NTSTATUS check_negative_conn_cache( const char *domain, const char *server)
139 NTSTATUS result = NT_STATUS_OK;
140 char *key = NULL;
141 char *value = NULL;
143 key = negative_conn_cache_keystr(domain, server);
144 if (key == NULL)
145 goto done;
147 if (gencache_get(key, talloc_tos(), &value, NULL))
148 result = negative_conn_cache_valuedecode(value);
149 done:
150 DEBUG(9,("check_negative_conn_cache returning result %d for domain %s "
151 "server %s\n", NT_STATUS_V(result), domain, server));
152 TALLOC_FREE(key);
153 TALLOC_FREE(value);
154 return result;
158 * Add an entry to the failed connection cache
160 * @param[in] domain
161 * @param[in] server may be a FQDN or an IP addr in printable form
162 * @param[in] result error to cache; must not be NT_STATUS_OK
164 void add_failed_connection_entry(const char *domain, const char *server,
165 NTSTATUS result)
167 char *key = NULL;
168 char *value = NULL;
170 if (NT_STATUS_IS_OK(result)) {
171 /* Nothing failed here */
172 return;
175 key = negative_conn_cache_keystr(domain, server);
176 if (key == NULL) {
177 DEBUG(0, ("add_failed_connection_entry: key creation error\n"));
178 goto done;
181 value = negative_conn_cache_valuestr(result);
182 if (value == NULL) {
183 DEBUG(0, ("add_failed_connection_entry: value creation error\n"));
184 goto done;
187 if (gencache_set(key, value,
188 time(NULL) + FAILED_CONNECTION_CACHE_TIMEOUT))
189 DEBUG(9,("add_failed_connection_entry: added domain %s (%s) "
190 "to failed conn cache\n", domain, server ));
191 else
192 DEBUG(1,("add_failed_connection_entry: failed to add "
193 "domain %s (%s) to failed conn cache\n",
194 domain, server));
196 done:
197 TALLOC_FREE(key);
198 TALLOC_FREE(value);
199 return;
203 * Deletes all records for a specified domain from the negative connection
204 * cache
206 * @param[in] domain String to match against domain portion of keys, or "*"
207 * to match all domains
209 void flush_negative_conn_cache_for_domain(const char *domain)
211 char *key_pattern = NULL;
213 key_pattern = negative_conn_cache_keystr(domain,"*");
214 if (key_pattern == NULL) {
215 DEBUG(0, ("flush_negative_conn_cache_for_domain: "
216 "key creation error\n"));
217 goto done;
220 gencache_iterate(delete_matches, NULL, key_pattern);
221 DEBUG(8, ("flush_negative_conn_cache_for_domain: flushed domain %s\n",
222 domain));
224 done:
225 TALLOC_FREE(key_pattern);
226 return;