]>
Commit | Line | Data |
---|---|---|
cb4fdfcc | 1 | commit da1aecfce80fba32b9abb328cf78088d95b7700a |
4022a9ec | 2 | Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de> |
cb4fdfcc | 3 | Date: Wed Aug 19 15:22:41 2015 +0200 |
4022a9ec | 4 | |
cb4fdfcc AM |
5 | Fix post-transport-crash. |
6 | ||
7 | The crash probably was introduced in a39bd74d3e94 and | |
8 | needs 'split_spool_directory=yes' to expose. | |
4022a9ec | 9 | |
cb4fdfcc | 10 | Thanks to Wolfgang Breyha, who found the same fix. |
4022a9ec | 11 | |
cb4fdfcc | 12 | (cherry picked from commit 6b51df8340eacc95e3def9a4376506610e91996c) |
4022a9ec | 13 | |
cb4fdfcc AM |
14 | diff --git a/src/src/transport.c b/src/src/transport.c |
15 | index fa6f869..a6ad3ed 100644 | |
16 | --- a/src/src/transport.c | |
17 | +++ b/src/src/transport.c | |
18 | @@ -1752,7 +1752,7 @@ while (1) | |
19 | { | |
20 | if (split_spool_directory) | |
21 | sprintf(CS spool_file, "%s%c/%s-D", | |
22 | - spool_dir, new_message_id[5], msgq[i].message_id); | |
23 | + spool_dir, msgq[i].message_id[5], msgq[i].message_id); | |
24 | else | |
25 | sprintf(CS spool_file, "%s%s-D", spool_dir, msgq[i].message_id); | |
4022a9ec AM |
26 | |
27 | ||
cb4fdfcc AM |
28 | commit d7168d8b112d3ba642a25ed04de36fb76d4a847d |
29 | Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de> | |
30 | Date: Thu Aug 20 13:58:06 2015 +0200 | |
4022a9ec | 31 | |
cb4fdfcc AM |
32 | Fix post-transport-crash: safeguard for missing spool BUG 1671 |
33 | ||
34 | Based on a proposal from Wolfgang Breyha. | |
35 | ||
36 | (cherry picked from commit dadff1d47e54962b0fdf98e8ce5cef42b6cb7fb5) | |
4022a9ec | 37 | |
cb4fdfcc AM |
38 | diff --git a/src/src/deliver.c b/src/src/deliver.c |
39 | index 78f8f4b..4154ff7 100644 | |
40 | --- a/src/src/deliver.c | |
41 | +++ b/src/src/deliver.c | |
42 | @@ -9,6 +9,7 @@ | |
4022a9ec | 43 | |
4022a9ec | 44 | |
cb4fdfcc AM |
45 | #include "exim.h" |
46 | +#include <assert.h> | |
4022a9ec | 47 | |
4022a9ec | 48 | |
cb4fdfcc AM |
49 | /* Data block for keeping track of subprocesses for parallel remote |
50 | @@ -7904,17 +7905,36 @@ if (!regex_IGNOREQUOTA) regex_IGNOREQUOTA = | |
51 | uschar * | |
52 | deliver_get_sender_address (uschar * id) | |
53 | { | |
54 | +int rc; | |
55 | +uschar * new_sender_address, | |
56 | + * save_sender_address; | |
4022a9ec | 57 | + |
cb4fdfcc AM |
58 | if (!spool_open_datafile(id)) |
59 | return NULL; | |
60 | ||
61 | +/* Save and restore the global sender_address. I'm not sure if we should | |
62 | +not save/restore all the other global variables too, because | |
63 | +spool_read_header() may change all of them. But OTOH, when this | |
64 | +deliver_get_sender_address() gets called, the current message is done | |
65 | +already and nobody needs the globals anymore. (HS12, 2015-08-21) */ | |
4022a9ec | 66 | + |
cb4fdfcc AM |
67 | sprintf(CS spoolname, "%s-H", id); |
68 | -if (spool_read_header(spoolname, TRUE, TRUE) != spool_read_OK) | |
69 | +save_sender_address = sender_address; | |
4022a9ec | 70 | + |
cb4fdfcc | 71 | +rc = spool_read_header(spoolname, TRUE, TRUE); |
4022a9ec | 72 | + |
cb4fdfcc AM |
73 | +new_sender_address = sender_address; |
74 | +sender_address = save_sender_address; | |
4022a9ec | 75 | + |
cb4fdfcc AM |
76 | +if (rc != spool_read_OK) |
77 | return NULL; | |
4022a9ec | 78 | |
cb4fdfcc | 79 | +assert(new_sender_address); |
4022a9ec | 80 | + |
cb4fdfcc AM |
81 | (void)close(deliver_datafile); |
82 | deliver_datafile = -1; | |
4022a9ec | 83 | |
cb4fdfcc AM |
84 | -return sender_address; |
85 | +return new_sender_address; | |
86 | } | |
87 | ||
88 | /* vi: aw ai sw=2 | |
89 | diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c | |
90 | index a952413..5ac5533 100644 | |
91 | --- a/src/src/transports/smtp.c | |
92 | +++ b/src/src/transports/smtp.c | |
93 | @@ -1274,14 +1274,19 @@ we will veto this new message. */ | |
4022a9ec | 94 | static BOOL |
cb4fdfcc | 95 | smtp_are_same_identities(uschar * message_id, smtp_compare_t * s_compare) |
4022a9ec | 96 | { |
cb4fdfcc AM |
97 | -uschar * save_sender_address = sender_address; |
98 | -uschar * current_local_identity = | |
4022a9ec | 99 | + |
cb4fdfcc AM |
100 | +uschar * message_local_identity, |
101 | + * current_local_identity, | |
102 | + * new_sender_address; | |
4022a9ec | 103 | + |
cb4fdfcc AM |
104 | +current_local_identity = |
105 | smtp_local_identity(s_compare->current_sender_address, s_compare->tblock); | |
106 | -uschar * new_sender_address = deliver_get_sender_address(message_id); | |
107 | -uschar * message_local_identity = | |
108 | - smtp_local_identity(new_sender_address, s_compare->tblock); | |
4022a9ec | 109 | |
cb4fdfcc AM |
110 | -sender_address = save_sender_address; |
111 | +if (!(new_sender_address = deliver_get_sender_address(message_id))) | |
112 | + return 0; | |
113 | + | |
114 | +message_local_identity = | |
115 | + smtp_local_identity(new_sender_address, s_compare->tblock); | |
4022a9ec | 116 | |
cb4fdfcc | 117 | return Ustrcmp(current_local_identity, message_local_identity) == 0; |
4022a9ec | 118 | } |
4022a9ec | 119 | |
cb4fdfcc | 120 | commit 9e1acebc3fbb288da804ab9031c7c448dffd841a |
4022a9ec AM |
121 | Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de> |
122 | Date: Tue Aug 11 17:36:29 2015 +0200 | |
123 | ||
124 | Fix ESMTP MAIL command option processing | |
125 | ||
126 | If the address containes spaces, the option processing | |
127 | was confused. | |
cb4fdfcc AM |
128 | |
129 | (cherry picked from commit 2ef7ed082481b2dccd3c2e0eae849b24bf0b172a) | |
4022a9ec AM |
130 | |
131 | diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c | |
cb4fdfcc | 132 | index cf0a5d6..980d54b 100644 |
4022a9ec AM |
133 | --- a/src/src/smtp_in.c |
134 | +++ b/src/src/smtp_in.c | |
135 | @@ -9,6 +9,7 @@ | |
136 | ||
137 | ||
138 | #include "exim.h" | |
139 | +#include <assert.h> | |
140 | ||
141 | ||
142 | /* Initialize for TCP wrappers if so configured. It appears that the macro | |
143 | @@ -232,6 +233,7 @@ static uschar *protocols[] = { | |
144 | ||
145 | /* Sanity check and validate optional args to MAIL FROM: envelope */ | |
146 | enum { | |
147 | + ENV_MAIL_OPT_NULL, | |
148 | ENV_MAIL_OPT_SIZE, ENV_MAIL_OPT_BODY, ENV_MAIL_OPT_AUTH, | |
149 | #ifndef DISABLE_PRDR | |
150 | ENV_MAIL_OPT_PRDR, | |
151 | @@ -240,7 +242,6 @@ enum { | |
152 | #ifdef EXPERIMENTAL_INTERNATIONAL | |
153 | ENV_MAIL_OPT_UTF8, | |
154 | #endif | |
155 | - ENV_MAIL_OPT_NULL | |
156 | }; | |
157 | typedef struct { | |
158 | uschar * name; /* option requested during MAIL cmd */ | |
159 | @@ -260,7 +261,8 @@ static env_mail_type_t env_mail_type_list[] = { | |
160 | #ifdef EXPERIMENTAL_INTERNATIONAL | |
161 | { US"SMTPUTF8",ENV_MAIL_OPT_UTF8, FALSE }, /* rfc6531 */ | |
162 | #endif | |
163 | - { US"NULL", ENV_MAIL_OPT_NULL, FALSE } | |
164 | + /* keep this the last entry */ | |
165 | + { US"NULL", ENV_MAIL_OPT_NULL, FALSE }, | |
166 | }; | |
167 | ||
168 | /* When reading SMTP from a remote host, we have to use our own versions of the | |
169 | @@ -3887,7 +3889,7 @@ while (done <= 0) | |
170 | if (!extract_option(&name, &value)) break; | |
171 | ||
172 | for (mail_args = env_mail_type_list; | |
173 | - (char *)mail_args < (char *)env_mail_type_list + sizeof(env_mail_type_list); | |
174 | + mail_args->value != ENV_MAIL_OPT_NULL; | |
175 | mail_args++ | |
176 | ) | |
177 | if (strcmpic(name, mail_args->name) == 0) | |
178 | @@ -4066,15 +4068,17 @@ while (done <= 0) | |
179 | } | |
180 | break; | |
181 | #endif | |
182 | - /* Unknown option. Stick back the terminator characters and break | |
183 | + /* No valid option. Stick back the terminator characters and break | |
184 | the loop. Do the name-terminator second as extract_option sets | |
185 | - value==name when it found no equal-sign. | |
186 | - An error for a malformed address will occur. */ | |
187 | - default: | |
188 | + value==name when it found no equal-sign. | |
189 | + An error for a malformed address will occur. */ | |
190 | + case ENV_MAIL_OPT_NULL: | |
191 | value[-1] = '='; | |
192 | name[-1] = ' '; | |
193 | arg_error = TRUE; | |
194 | break; | |
195 | + | |
196 | + default: assert(0); | |
197 | } | |
198 | /* Break out of for loop if switch() had bad argument or | |
199 | when start of the email address is reached */ | |
200 | ||
cb4fdfcc | 201 | commit 22c82c48aa5d23c49d38e3581810ea54587df61b |
4022a9ec | 202 | Author: Jeremy Harris <jgh146exb@wizmail.org> |
cb4fdfcc | 203 | Date: Tue Aug 25 10:36:27 2015 +0100 |
4022a9ec | 204 | |
cb4fdfcc AM |
205 | Close logs after daemon-process exceptional write. Bug 728 |
206 | ||
207 | (cherry picked from commit c8899c20aa08c9ae6a4c291aad23ba90512bebe4) | |
4022a9ec | 208 | |
cb4fdfcc AM |
209 | diff --git a/src/src/daemon.c b/src/src/daemon.c |
210 | index 894a96f..a7a49f0 100644 | |
211 | --- a/src/src/daemon.c | |
212 | +++ b/src/src/daemon.c | |
213 | @@ -735,6 +735,7 @@ else (void)close(dup_accept_socket); | |
214 | /* Release any store used in this process, including the store used for holding | |
215 | the incoming host address and an expanded active_hostname. */ | |
4022a9ec | 216 | |
cb4fdfcc AM |
217 | +log_close_all(); |
218 | store_reset(reset_point); | |
219 | sender_host_address = NULL; | |
220 | } | |
221 | ||
222 | commit 4d3b8805796ffa39889060d9f216bfaf7391c542 | |
223 | Author: Jeremy Harris <jgh146exb@wizmail.org> | |
224 | Date: Thu Sep 17 13:35:16 2015 +0100 | |
225 | ||
226 | DNS: time-limit cached returns, using TTL. Bug 1395 | |
227 | ||
228 | This can matter for fast-changing data such as DNSBLs. | |
229 | ||
230 | (cherry picked from commit 14b3c5bc64a16df07583fe4b5ef2e0129d063893) | |
231 | ||
232 | DNS: avoid overflow in cache TTL for negative entries. Bug 1395 | |
233 | ||
234 | (cherry picked from commit e162fc9757d4b8cb41aca74214e968622d6c3dee) | |
235 | ||
236 | diff --git a/src/src/dns.c b/src/src/dns.c | |
237 | index 64958d9..abed126 100644 | |
238 | --- a/src/src/dns.c | |
239 | +++ b/src/src/dns.c | |
240 | @@ -390,7 +390,8 @@ from the following bytes. */ | |
241 | ||
242 | dnss->aptr += namelen; | |
243 | GETSHORT(dnss->srr.type, dnss->aptr); /* Record type */ | |
244 | -dnss->aptr += 6; /* Don't want class or TTL */ | |
245 | +dnss->aptr += 2; /* Don't want class */ | |
246 | +GETLONG(dnss->srr.ttl, dnss->aptr); /* TTL */ | |
247 | GETSHORT(dnss->srr.size, dnss->aptr); /* Size of data portion */ | |
248 | dnss->srr.data = dnss->aptr; /* The record's data follows */ | |
249 | dnss->aptr += dnss->srr.size; /* Advance to next RR */ | |
250 | diff --git a/src/src/lookupapi.h b/src/src/lookupapi.h | |
251 | index cdd1c85..03de8f6 100644 | |
252 | --- a/src/src/lookupapi.h | |
253 | +++ b/src/src/lookupapi.h | |
254 | @@ -34,7 +34,7 @@ typedef struct lookup_info { | |
255 | int, /* length of key or query */ | |
256 | uschar **, /* for returning answer */ | |
257 | uschar **, /* for error message */ | |
258 | - BOOL *); /* to request cache cleanup */ | |
259 | + uint *); /* cache TTL, sconds */ | |
260 | void (*close)( /* close function */ | |
261 | void *); /* handle */ | |
262 | void (*tidy)(void); /* tidy function */ | |
263 | @@ -46,9 +46,10 @@ typedef struct lookup_info { | |
264 | } lookup_info; | |
265 | ||
266 | /* This magic number is used by the following lookup_module_info structure | |
267 | - for checking API compatibility. It's equivalent to the string"LMM2" */ | |
268 | -#define LOOKUP_MODULE_INFO_MAGIC 0x4c4d4d32 | |
269 | + for checking API compatibility. It used to be equivalent to the string"LMM3" */ | |
270 | +#define LOOKUP_MODULE_INFO_MAGIC 0x4c4d4933 | |
271 | /* Version 2 adds: version_report */ | |
272 | +/* Version 3 change: non/cache becomes TTL in seconds */ | |
273 | ||
274 | typedef struct lookup_module_info { | |
275 | uint magic; | |
276 | diff --git a/src/src/lookups/README b/src/src/lookups/README | |
277 | index 98905dc..31fea64 100644 | |
278 | --- a/src/src/lookups/README | |
279 | +++ b/src/src/lookups/README | |
280 | @@ -122,12 +122,15 @@ DEFER. The arguments are: | |
281 | uschar **errmsg where to put an error message on failure; | |
282 | this is initially set to "", and should be left | |
283 | as that for a standard "entry not found" error | |
284 | - BOOL *do_cache the lookup should set this to FALSE when it changes data. | |
285 | - This is TRUE by default. When set to FALSE the cache tree | |
286 | + uint *do_cache the lookup should set this to 0 when it changes data. | |
287 | + This is MAXINT by default. When set to 0 the cache tree | |
288 | of the current search handle will be cleaned and the | |
289 | current result will NOT be cached. Currently the mysql | |
290 | and pgsql lookups use this when UPDATE/INSERT queries are | |
291 | executed. | |
292 | + If set to a nonzero number of seconds, the cached value | |
293 | + becomes unusable after this time. Currently the dnsdb | |
294 | + lookup uses this to support the TTL value. | |
295 | ||
296 | Even though the key is zero-terminated, the length is passed because in the | |
297 | common case it has been computed already and is often needed. | |
298 | diff --git a/src/src/lookups/cdb.c b/src/src/lookups/cdb.c | |
299 | index ea017de..ba925dc 100644 | |
300 | --- a/src/src/lookups/cdb.c | |
301 | +++ b/src/src/lookups/cdb.c | |
302 | @@ -279,7 +279,7 @@ cdb_find(void *handle, | |
303 | int key_len, | |
304 | uschar **result, | |
305 | uschar **errmsg, | |
306 | - BOOL *do_cache) | |
307 | + uint *do_cache) | |
308 | { | |
309 | struct cdb_state * cdbp = handle; | |
310 | uint32 item_key_len, | |
311 | diff --git a/src/src/lookups/dbmdb.c b/src/src/lookups/dbmdb.c | |
312 | index 03248e4..b8c42d5 100644 | |
313 | --- a/src/src/lookups/dbmdb.c | |
314 | +++ b/src/src/lookups/dbmdb.c | |
315 | @@ -87,7 +87,7 @@ the keylength in order to include the terminating zero. */ | |
316 | ||
317 | static int | |
318 | dbmdb_find(void *handle, uschar *filename, const uschar *keystring, int length, | |
319 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
320 | + uschar **result, uschar **errmsg, uint *do_cache) | |
321 | { | |
322 | EXIM_DB *d = (EXIM_DB *)handle; | |
323 | EXIM_DATUM key, data; | |
324 | @@ -120,7 +120,7 @@ return FAIL; | |
4022a9ec | 325 | |
cb4fdfcc AM |
326 | int |
327 | static dbmnz_find(void *handle, uschar *filename, const uschar *keystring, int length, | |
328 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
329 | + uschar **result, uschar **errmsg, uint *do_cache) | |
4022a9ec | 330 | { |
cb4fdfcc AM |
331 | return dbmdb_find(handle, filename, keystring, length-1, result, errmsg, |
332 | do_cache); | |
333 | @@ -140,7 +140,7 @@ return dbmdb_find(handle, filename, keystring, length-1, result, errmsg, | |
334 | ||
335 | static int | |
336 | dbmjz_find(void *handle, uschar *filename, const uschar *keystring, int length, | |
337 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
338 | + uschar **result, uschar **errmsg, uint *do_cache) | |
339 | { | |
340 | uschar *key_item, *key_buffer, *key_p; | |
341 | const uschar *key_elems = keystring; | |
342 | diff --git a/src/src/lookups/dnsdb.c b/src/src/lookups/dnsdb.c | |
343 | index e3de279..70e6c8c 100644 | |
344 | --- a/src/src/lookups/dnsdb.c | |
345 | +++ b/src/src/lookups/dnsdb.c | |
346 | @@ -131,7 +131,7 @@ separator, as always, is colon. */ | |
347 | ||
348 | static int | |
349 | dnsdb_find(void *handle, uschar *filename, const uschar *keystring, int length, | |
350 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
351 | + uschar **result, uschar **errmsg, uint *do_cache) | |
352 | { | |
353 | int rc; | |
354 | int size = 256; | |
355 | @@ -388,6 +388,9 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) | |
356 | { | |
357 | if (rr->type != searchtype) continue; | |
4022a9ec | 358 | |
cb4fdfcc AM |
359 | + if (*do_cache > rr->ttl) |
360 | + *do_cache = rr->ttl; | |
361 | + | |
362 | if (type == T_A || type == T_AAAA || type == T_ADDRESSES) | |
363 | { | |
364 | dns_address *da; | |
365 | diff --git a/src/src/lookups/dsearch.c b/src/src/lookups/dsearch.c | |
366 | index f8c592a..9f7dd8d 100644 | |
367 | --- a/src/src/lookups/dsearch.c | |
368 | +++ b/src/src/lookups/dsearch.c | |
369 | @@ -67,7 +67,7 @@ for us. */ | |
4022a9ec | 370 | |
cb4fdfcc AM |
371 | int |
372 | static dsearch_find(void *handle, uschar *dirname, const uschar *keystring, int length, | |
373 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
374 | + uschar **result, uschar **errmsg, uint *do_cache) | |
375 | { | |
376 | struct stat statbuf; | |
377 | int save_errno; | |
378 | diff --git a/src/src/lookups/ibase.c b/src/src/lookups/ibase.c | |
379 | index 23e1dea..7fd53d0 100644 | |
380 | --- a/src/src/lookups/ibase.c | |
381 | +++ b/src/src/lookups/ibase.c | |
382 | @@ -451,7 +451,7 @@ deferred with a retryable error. */ | |
383 | ||
384 | static int | |
385 | ibase_find(void *handle, uschar * filename, uschar * query, int length, | |
386 | - uschar ** result, uschar ** errmsg, BOOL *do_cache) | |
387 | + uschar ** result, uschar ** errmsg, uint *do_cache) | |
388 | { | |
389 | int sep = 0; | |
390 | uschar *server; | |
391 | diff --git a/src/src/lookups/ldap.c b/src/src/lookups/ldap.c | |
392 | index a56eff3..b870df1 100644 | |
393 | --- a/src/src/lookups/ldap.c | |
394 | +++ b/src/src/lookups/ldap.c | |
395 | @@ -1339,7 +1339,7 @@ The handle and filename arguments are not used. */ | |
396 | ||
397 | static int | |
398 | eldap_find(void *handle, uschar *filename, const uschar *ldap_url, int length, | |
399 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
400 | + uschar **result, uschar **errmsg, uint *do_cache) | |
401 | { | |
402 | /* Keep picky compilers happy */ | |
403 | do_cache = do_cache; | |
404 | @@ -1348,7 +1348,7 @@ return(control_ldap_search(ldap_url, SEARCH_LDAP_SINGLE, result, errmsg)); | |
405 | ||
406 | static int | |
407 | eldapm_find(void *handle, uschar *filename, const uschar *ldap_url, int length, | |
408 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
409 | + uschar **result, uschar **errmsg, uint *do_cache) | |
410 | { | |
411 | /* Keep picky compilers happy */ | |
412 | do_cache = do_cache; | |
413 | @@ -1357,7 +1357,7 @@ return(control_ldap_search(ldap_url, SEARCH_LDAP_MULTIPLE, result, errmsg)); | |
414 | ||
415 | static int | |
416 | eldapdn_find(void *handle, uschar *filename, const uschar *ldap_url, int length, | |
417 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
418 | + uschar **result, uschar **errmsg, uint *do_cache) | |
419 | { | |
420 | /* Keep picky compilers happy */ | |
421 | do_cache = do_cache; | |
422 | @@ -1366,7 +1366,7 @@ return(control_ldap_search(ldap_url, SEARCH_LDAP_DN, result, errmsg)); | |
4022a9ec | 423 | |
cb4fdfcc AM |
424 | int |
425 | eldapauth_find(void *handle, uschar *filename, const uschar *ldap_url, int length, | |
426 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
427 | + uschar **result, uschar **errmsg, uint *do_cache) | |
428 | { | |
429 | /* Keep picky compilers happy */ | |
430 | do_cache = do_cache; | |
431 | diff --git a/src/src/lookups/lf_functions.h b/src/src/lookups/lf_functions.h | |
432 | index 73e9303..d2487d3 100644 | |
433 | --- a/src/src/lookups/lf_functions.h | |
434 | +++ b/src/src/lookups/lf_functions.h | |
435 | @@ -12,7 +12,7 @@ extern int lf_check_file(int, uschar *, int, int, uid_t *, gid_t *, | |
436 | extern uschar *lf_quote(uschar *, uschar *, int, uschar *, int *, int *); | |
437 | extern int lf_sqlperform(const uschar *, const uschar *, const uschar *, | |
438 | const uschar *, uschar **, | |
439 | - uschar **, BOOL *, int(*)(const uschar *, uschar *, uschar **, | |
440 | - uschar **, BOOL *, BOOL *)); | |
441 | + uschar **, uint *, int(*)(const uschar *, uschar *, uschar **, | |
442 | + uschar **, BOOL *, uint *)); | |
443 | ||
444 | /* End of lf_functions.h */ | |
445 | diff --git a/src/src/lookups/lf_sqlperform.c b/src/src/lookups/lf_sqlperform.c | |
446 | index 2d7f326..6d4f7a7 100644 | |
447 | --- a/src/src/lookups/lf_sqlperform.c | |
448 | +++ b/src/src/lookups/lf_sqlperform.c | |
449 | @@ -27,7 +27,7 @@ Arguments: | |
450 | query the query | |
451 | result where to pass back the result | |
452 | errmsg where to pass back an error message | |
453 | - do_cache to be set FALSE if data is changed | |
454 | + do_cache to be set zero if data is changed | |
455 | func the lookup function to call | |
456 | ||
457 | Returns: the return from the lookup function, or DEFER | |
458 | @@ -36,8 +36,8 @@ Returns: the return from the lookup function, or DEFER | |
459 | int | |
460 | lf_sqlperform(const uschar *name, const uschar *optionname, | |
461 | const uschar *optserverlist, const uschar *query, | |
462 | - uschar **result, uschar **errmsg, BOOL *do_cache, | |
463 | - int(*fn)(const uschar *, uschar *, uschar **, uschar **, BOOL *, BOOL *)) | |
464 | + uschar **result, uschar **errmsg, uint *do_cache, | |
465 | + int(*fn)(const uschar *, uschar *, uschar **, uschar **, BOOL *, uint *)) | |
466 | { | |
467 | int sep, rc; | |
468 | uschar *server; | |
469 | diff --git a/src/src/lookups/lsearch.c b/src/src/lookups/lsearch.c | |
470 | index 3883d4b..eb70a45 100644 | |
471 | --- a/src/src/lookups/lsearch.c | |
472 | +++ b/src/src/lookups/lsearch.c | |
473 | @@ -323,7 +323,7 @@ return FAIL; | |
474 | ||
475 | static int | |
476 | lsearch_find(void *handle, uschar *filename, const uschar *keystring, int length, | |
477 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
478 | + uschar **result, uschar **errmsg, uint *do_cache) | |
479 | { | |
480 | do_cache = do_cache; /* Keep picky compilers happy */ | |
481 | return internal_lsearch_find(handle, filename, keystring, length, result, | |
482 | @@ -340,7 +340,7 @@ return internal_lsearch_find(handle, filename, keystring, length, result, | |
483 | ||
484 | static int | |
485 | wildlsearch_find(void *handle, uschar *filename, const uschar *keystring, int length, | |
486 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
487 | + uschar **result, uschar **errmsg, uint *do_cache) | |
488 | { | |
489 | do_cache = do_cache; /* Keep picky compilers happy */ | |
490 | return internal_lsearch_find(handle, filename, keystring, length, result, | |
491 | @@ -357,7 +357,7 @@ return internal_lsearch_find(handle, filename, keystring, length, result, | |
492 | ||
493 | static int | |
494 | nwildlsearch_find(void *handle, uschar *filename, const uschar *keystring, int length, | |
495 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
496 | + uschar **result, uschar **errmsg, uint *do_cache) | |
497 | { | |
498 | do_cache = do_cache; /* Keep picky compilers happy */ | |
499 | return internal_lsearch_find(handle, filename, keystring, length, result, | |
500 | @@ -375,7 +375,7 @@ return internal_lsearch_find(handle, filename, keystring, length, result, | |
501 | ||
502 | static int | |
503 | iplsearch_find(void *handle, uschar *filename, const uschar *keystring, int length, | |
504 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
505 | + uschar **result, uschar **errmsg, uint *do_cache) | |
506 | { | |
507 | do_cache = do_cache; /* Keep picky compilers happy */ | |
508 | if ((length == 1 && keystring[0] == '*') || | |
509 | diff --git a/src/src/lookups/mysql.c b/src/src/lookups/mysql.c | |
510 | index 8dff86a..1ce8831 100644 | |
511 | --- a/src/src/lookups/mysql.c | |
512 | +++ b/src/src/lookups/mysql.c | |
513 | @@ -74,7 +74,7 @@ Arguments: | |
514 | resultptr where to store the result | |
515 | errmsg where to point an error message | |
516 | defer_break TRUE if no more servers are to be tried after DEFER | |
517 | - do_cache set false if data is changed | |
518 | + do_cache set zero if data is changed | |
519 | ||
520 | The server string is of the form "host/dbname/user/password". The host can be | |
521 | host:port. This string is in a nextinlist temporary buffer, so can be | |
522 | @@ -85,7 +85,7 @@ Returns: OK, FAIL, or DEFER | |
523 | ||
524 | static int | |
525 | perform_mysql_search(const uschar *query, uschar *server, uschar **resultptr, | |
526 | - uschar **errmsg, BOOL *defer_break, BOOL *do_cache) | |
527 | + uschar **errmsg, BOOL *defer_break, uint *do_cache) | |
528 | { | |
529 | MYSQL *mysql_handle = NULL; /* Keep compilers happy */ | |
530 | MYSQL_RES *mysql_result = NULL; | |
531 | @@ -225,7 +225,7 @@ can be detected by calling mysql_field_count(). If its result is zero, no data | |
532 | was expected (this is all explained clearly in the MySQL manual). In this case, | |
533 | we return the number of rows affected by the command. In this event, we do NOT | |
534 | want to cache the result; also the whole cache for the handle must be cleaned | |
535 | -up. Setting do_cache FALSE requests this. */ | |
536 | +up. Setting do_cache zero requests this. */ | |
537 | ||
538 | if ((mysql_result = mysql_use_result(mysql_handle)) == NULL) | |
539 | { | |
540 | @@ -233,7 +233,7 @@ if ((mysql_result = mysql_use_result(mysql_handle)) == NULL) | |
541 | { | |
542 | DEBUG(D_lookup) debug_printf("MYSQL: query was not one that returns data\n"); | |
543 | result = string_sprintf("%d", mysql_affected_rows(mysql_handle)); | |
544 | - *do_cache = FALSE; | |
545 | + *do_cache = 0; | |
546 | goto MYSQL_EXIT; | |
4022a9ec | 547 | } |
cb4fdfcc AM |
548 | *errmsg = string_sprintf("MYSQL: lookup result failed: %s\n", |
549 | @@ -341,7 +341,7 @@ shared with other SQL lookups. */ | |
4022a9ec | 550 | |
cb4fdfcc AM |
551 | static int |
552 | mysql_find(void *handle, uschar *filename, const uschar *query, int length, | |
553 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
554 | + uschar **result, uschar **errmsg, uint *do_cache) | |
555 | { | |
556 | return lf_sqlperform(US"MySQL", US"mysql_servers", mysql_servers, query, | |
557 | result, errmsg, do_cache, perform_mysql_search); | |
558 | diff --git a/src/src/lookups/nis.c b/src/src/lookups/nis.c | |
559 | index 7b012b1..1faa884 100644 | |
560 | --- a/src/src/lookups/nis.c | |
561 | +++ b/src/src/lookups/nis.c | |
562 | @@ -42,7 +42,7 @@ code. */ | |
563 | ||
564 | static int | |
565 | nis_find(void *handle, uschar *filename, uschar *keystring, int length, | |
566 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
567 | + uschar **result, uschar **errmsg, uint *do_cache) | |
568 | { | |
569 | int rc; | |
570 | uschar *nis_data; | |
571 | @@ -68,7 +68,7 @@ return (rc == YPERR_KEY || rc == YPERR_MAP)? FAIL : DEFER; | |
4022a9ec | 572 | |
cb4fdfcc AM |
573 | static int |
574 | nis0_find(void *handle, uschar *filename, uschar *keystring, int length, | |
575 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
576 | + uschar **result, uschar **errmsg, uint *do_cache) | |
4022a9ec | 577 | { |
4022a9ec | 578 | int rc; |
cb4fdfcc AM |
579 | uschar *nis_data; |
580 | diff --git a/src/src/lookups/nisplus.c b/src/src/lookups/nisplus.c | |
581 | index 8895cee..a4a7a2d 100644 | |
582 | --- a/src/src/lookups/nisplus.c | |
583 | +++ b/src/src/lookups/nisplus.c | |
584 | @@ -43,7 +43,7 @@ equals sign. */ | |
585 | ||
586 | static int | |
587 | nisplus_find(void *handle, uschar *filename, uschar *query, int length, | |
588 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
589 | + uschar **result, uschar **errmsg, uint *do_cache) | |
590 | { | |
591 | int i; | |
592 | int ssize = 0; | |
593 | diff --git a/src/src/lookups/oracle.c b/src/src/lookups/oracle.c | |
594 | index 1f2520a..adb17b4 100644 | |
595 | --- a/src/src/lookups/oracle.c | |
596 | +++ b/src/src/lookups/oracle.c | |
597 | @@ -517,7 +517,7 @@ deferred with a retryable error. */ | |
598 | ||
599 | static int | |
600 | oracle_find(void *handle, uschar *filename, uschar *query, int length, | |
601 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
602 | + uschar **result, uschar **errmsg, uint *do_cache) | |
603 | { | |
604 | int sep = 0; | |
605 | uschar *server; | |
606 | diff --git a/src/src/lookups/passwd.c b/src/src/lookups/passwd.c | |
607 | index e726f3e..315677f 100644 | |
608 | --- a/src/src/lookups/passwd.c | |
609 | +++ b/src/src/lookups/passwd.c | |
610 | @@ -34,7 +34,7 @@ return (void *)(-1); /* Just return something non-null */ | |
611 | ||
612 | static int | |
613 | passwd_find(void *handle, uschar *filename, const uschar *keystring, int length, | |
614 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
615 | + uschar **result, uschar **errmsg, uint *do_cache) | |
616 | { | |
617 | struct passwd *pw; | |
618 | ||
619 | diff --git a/src/src/lookups/pgsql.c b/src/src/lookups/pgsql.c | |
620 | index c86ac23..4be3d98 100644 | |
621 | --- a/src/src/lookups/pgsql.c | |
622 | +++ b/src/src/lookups/pgsql.c | |
623 | @@ -119,7 +119,7 @@ Returns: OK, FAIL, or DEFER | |
624 | ||
625 | static int | |
626 | perform_pgsql_search(const uschar *query, uschar *server, uschar **resultptr, | |
627 | - uschar **errmsg, BOOL *defer_break, BOOL *do_cache) | |
628 | + uschar **errmsg, BOOL *defer_break, uint *do_cache) | |
629 | { | |
630 | PGconn *pg_conn = NULL; | |
631 | PGresult *pg_result = NULL; | |
632 | @@ -290,10 +290,10 @@ else | |
633 | /* The command was successful but did not return any data since it was | |
634 | * not SELECT but either an INSERT, UPDATE or DELETE statement. Tell the | |
635 | * high level code to not cache this query, and clean the current cache for | |
636 | - * this handle by setting *do_cache FALSE. */ | |
637 | + * this handle by setting *do_cache zero. */ | |
638 | result = string_copy(US PQcmdTuples(pg_result)); | |
639 | offset = Ustrlen(result); | |
640 | - *do_cache = FALSE; | |
641 | + *do_cache = 0; | |
642 | DEBUG(D_lookup) debug_printf("PGSQL: command does not return any data " | |
643 | "but was successful. Rows affected: %s\n", result); | |
644 | ||
645 | @@ -399,7 +399,7 @@ shared with other SQL lookups. */ | |
646 | ||
647 | static int | |
648 | pgsql_find(void *handle, uschar *filename, const uschar *query, int length, | |
649 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
650 | + uschar **result, uschar **errmsg, uint *do_cache) | |
651 | { | |
652 | return lf_sqlperform(US"PostgreSQL", US"pgsql_servers", pgsql_servers, query, | |
653 | result, errmsg, do_cache, perform_pgsql_search); | |
654 | diff --git a/src/src/lookups/redis.c b/src/src/lookups/redis.c | |
655 | index ac4d0ec..18cd3a0 100644 | |
656 | --- a/src/src/lookups/redis.c | |
657 | +++ b/src/src/lookups/redis.c | |
658 | @@ -65,7 +65,7 @@ redis_tidy(void) | |
659 | */ | |
660 | static int | |
661 | perform_redis_search(uschar *command, uschar *server, uschar **resultptr, | |
662 | - uschar **errmsg, BOOL *defer_break, BOOL *do_cache) | |
663 | + uschar **errmsg, BOOL *defer_break, uint *do_cache) | |
664 | { | |
665 | redisContext *redis_handle = NULL; /* Keep compilers happy */ | |
666 | redisReply *redis_reply = NULL; | |
667 | @@ -197,7 +197,7 @@ perform_redis_search(uschar *command, uschar *server, uschar **resultptr, | |
668 | case REDIS_REPLY_ERROR: | |
669 | *errmsg = string_sprintf("REDIS: lookup result failed: %s\n", redis_reply->str); | |
670 | *defer_break = FALSE; | |
671 | - *do_cache = FALSE; | |
672 | + *do_cache = 0; | |
673 | goto REDIS_EXIT; | |
674 | /* NOTREACHED */ | |
675 | ||
676 | @@ -205,7 +205,7 @@ perform_redis_search(uschar *command, uschar *server, uschar **resultptr, | |
677 | case REDIS_REPLY_NIL: | |
678 | DEBUG(D_lookup) debug_printf("REDIS: query was not one that returned any data\n"); | |
679 | result = string_sprintf(""); | |
680 | - *do_cache = FALSE; | |
681 | + *do_cache = 0; | |
682 | goto REDIS_EXIT; | |
683 | /* NOTREACHED */ | |
684 | ||
685 | @@ -304,7 +304,7 @@ perform_redis_search(uschar *command, uschar *server, uschar **resultptr, | |
686 | ||
687 | static int | |
688 | redis_find(void *handle __attribute__((unused)), uschar *filename __attribute__((unused)), | |
689 | - uschar *command, int length, uschar **result, uschar **errmsg, BOOL *do_cache) | |
690 | + uschar *command, int length, uschar **result, uschar **errmsg, uint *do_cache) | |
691 | { | |
692 | return lf_sqlperform(US"Redis", US"redis_servers", redis_servers, command, | |
693 | result, errmsg, do_cache, perform_redis_search); | |
694 | diff --git a/src/src/lookups/spf.c b/src/src/lookups/spf.c | |
695 | index 23ad2ad..2671fc9 100644 | |
696 | --- a/src/src/lookups/spf.c | |
697 | +++ b/src/src/lookups/spf.c | |
698 | @@ -31,7 +31,9 @@ static void dummy(int x) { dummy2(x-1); } | |
699 | #include <spf2/spf_dns_resolv.h> | |
700 | #include <spf2/spf_dns_cache.h> | |
701 | ||
702 | -static void *spf_open(uschar *filename, uschar **errmsg) { | |
703 | +static void * | |
704 | +spf_open(uschar *filename, uschar **errmsg) | |
705 | +{ | |
706 | SPF_server_t *spf_server = NULL; | |
707 | spf_server = SPF_server_new(SPF_DNS_CACHE, 0); | |
708 | if (spf_server == NULL) { | |
709 | @@ -41,13 +43,17 @@ static void *spf_open(uschar *filename, uschar **errmsg) { | |
710 | return (void *) spf_server; | |
711 | } | |
712 | ||
713 | -static void spf_close(void *handle) { | |
714 | +static void | |
715 | +spf_close(void *handle) | |
716 | +{ | |
717 | SPF_server_t *spf_server = handle; | |
718 | if (spf_server) SPF_server_free(spf_server); | |
719 | } | |
720 | ||
721 | -static int spf_find(void *handle, uschar *filename, uschar *keystring, int key_len, | |
722 | - uschar **result, uschar **errmsg, BOOL *do_cache) { | |
723 | +static int | |
724 | +spf_find(void *handle, uschar *filename, uschar *keystring, int key_len, | |
725 | + uschar **result, uschar **errmsg, uint *do_cache) | |
726 | +{ | |
727 | SPF_server_t *spf_server = handle; | |
728 | SPF_request_t *spf_request = NULL; | |
729 | SPF_response_t *spf_response = NULL; | |
730 | diff --git a/src/src/lookups/sqlite.c b/src/src/lookups/sqlite.c | |
731 | index bb92c8c..e2330f9 100644 | |
732 | --- a/src/src/lookups/sqlite.c | |
733 | +++ b/src/src/lookups/sqlite.c | |
734 | @@ -81,7 +81,7 @@ return 0; | |
735 | ||
736 | static int | |
737 | sqlite_find(void *handle, uschar *filename, const uschar *query, int length, | |
738 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
739 | + uschar **result, uschar **errmsg, uint *do_cache) | |
740 | { | |
741 | int ret; | |
742 | struct strbuf res = { NULL, 0, 0 }; | |
743 | @@ -93,7 +93,7 @@ if (ret != SQLITE_OK) | |
744 | return FAIL; | |
745 | } | |
4022a9ec | 746 | |
cb4fdfcc AM |
747 | -if (res.string == NULL) *do_cache = FALSE; |
748 | +if (res.string == NULL) *do_cache = 0; | |
749 | ||
750 | *result = res.string; | |
751 | return OK; | |
752 | diff --git a/src/src/lookups/testdb.c b/src/src/lookups/testdb.c | |
753 | index c82fa7f..401f7c8 100644 | |
754 | --- a/src/src/lookups/testdb.c | |
755 | +++ b/src/src/lookups/testdb.c | |
756 | @@ -38,7 +38,7 @@ return (void *)(1); /* Just return something non-null */ | |
757 | ||
758 | static int | |
759 | testdb_find(void *handle, uschar *filename, const uschar *query, int length, | |
760 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
761 | + uschar **result, uschar **errmsg, uint *do_cache) | |
762 | { | |
763 | handle = handle; /* Keep picky compilers happy */ | |
764 | filename = filename; | |
765 | @@ -57,7 +57,7 @@ if (Ustrcmp(query, "defer") == 0) | |
766 | return DEFER; | |
767 | } | |
4022a9ec | 768 | |
cb4fdfcc AM |
769 | -if (Ustrcmp(query, "nocache") == 0) *do_cache = FALSE; |
770 | +if (Ustrcmp(query, "nocache") == 0) *do_cache = 0; | |
771 | ||
772 | *result = string_copy(query); | |
773 | return OK; | |
774 | diff --git a/src/src/lookups/whoson.c b/src/src/lookups/whoson.c | |
775 | index 4166089..9ac5a3a 100644 | |
776 | --- a/src/src/lookups/whoson.c | |
777 | +++ b/src/src/lookups/whoson.c | |
778 | @@ -36,7 +36,7 @@ return (void *)(1); /* Just return something non-null */ | |
779 | ||
780 | static int | |
781 | whoson_find(void *handle, uschar *filename, uschar *query, int length, | |
782 | - uschar **result, uschar **errmsg, BOOL *do_cache) | |
783 | + uschar **result, uschar **errmsg, uint *do_cache) | |
784 | { | |
785 | uschar buffer[80]; | |
786 | handle = handle; /* Keep picky compilers happy */ | |
787 | diff --git a/src/src/search.c b/src/src/search.c | |
788 | index a055291..cd522da 100644 | |
789 | --- a/src/src/search.c | |
790 | +++ b/src/src/search.c | |
791 | @@ -466,6 +466,7 @@ internal_search_find(void *handle, uschar *filename, uschar *keystring) | |
792 | { | |
793 | tree_node *t = (tree_node *)handle; | |
794 | search_cache *c = (search_cache *)(t->data.ptr); | |
795 | +expiring_data *e; | |
796 | uschar *data = NULL; | |
797 | int search_type = t->name[0] - '0'; | |
798 | int old_pool = store_pool; | |
799 | @@ -491,18 +492,27 @@ store_pool = POOL_SEARCH; | |
800 | /* Look up the data for the key, unless it is already in the cache for this | |
801 | file. No need to check c->item_cache for NULL, tree_search will do so. */ | |
802 | ||
803 | -if ((t = tree_search(c->item_cache, keystring)) == NULL) | |
804 | +if ( (t = tree_search(c->item_cache, keystring)) | |
805 | + && (!(e = t->data.ptr)->expiry || e->expiry > time(NULL)) | |
806 | + ) | |
807 | + { /* Data was in the cache already; set the pointer from the tree node */ | |
808 | + data = e->ptr; | |
809 | + DEBUG(D_lookup) debug_printf("cached data used for lookup of %s%s%s\n", | |
810 | + keystring, | |
811 | + filename ? US"\n in " : US"", filename ? filename : US""); | |
812 | + } | |
813 | +else | |
4022a9ec | 814 | { |
cb4fdfcc AM |
815 | - BOOL do_cache = TRUE; |
816 | + uint do_cache = UINT_MAX; | |
817 | int keylength = Ustrlen(keystring); | |
4022a9ec | 818 | |
cb4fdfcc | 819 | DEBUG(D_lookup) |
4022a9ec | 820 | { |
cb4fdfcc AM |
821 | - if (filename != NULL) |
822 | - debug_printf("file lookup required for %s\n in %s\n", | |
823 | - keystring, filename); | |
824 | - else | |
825 | - debug_printf("database lookup required for %s\n", keystring); | |
826 | + if (t) debug_printf("cached data found but past valid time; "); | |
827 | + debug_printf("%s lookup required for %s%s%s\n", | |
828 | + filename ? US"file" : US"database", | |
829 | + keystring, | |
830 | + filename ? US"\n in " : US"", filename ? filename : US""); | |
4022a9ec AM |
831 | } |
832 | ||
cb4fdfcc AM |
833 | /* Call the code for the different kinds of search. DEFER is handled |
834 | @@ -511,9 +521,7 @@ if ((t = tree_search(c->item_cache, keystring)) == NULL) | |
4022a9ec | 835 | |
cb4fdfcc AM |
836 | if (lookup_list[search_type]->find(c->handle, filename, keystring, keylength, |
837 | &data, &search_error_message, &do_cache) == DEFER) | |
838 | - { | |
839 | search_find_defer = TRUE; | |
840 | - } | |
4022a9ec | 841 | |
cb4fdfcc AM |
842 | /* A record that has been found is now in data, which is either NULL |
843 | or points to a bit of dynamic store. Cache the result of the lookup if | |
844 | @@ -524,10 +532,22 @@ if ((t = tree_search(c->item_cache, keystring)) == NULL) | |
845 | else if (do_cache) | |
846 | { | |
847 | int len = keylength + 1; | |
848 | - t = store_get(sizeof(tree_node) + len); | |
849 | - memcpy(t->name, keystring, len); | |
850 | - t->data.ptr = data; | |
851 | - tree_insertnode(&c->item_cache, t); | |
852 | + | |
853 | + if (t) /* Previous, out-of-date cache entry. Update with the */ | |
854 | + { /* new result and forget the old one */ | |
855 | + e->expiry = do_cache == UINT_MAX ? 0 : time(NULL)+do_cache; | |
856 | + e->ptr = data; | |
857 | + } | |
858 | + else | |
4022a9ec | 859 | + { |
cb4fdfcc AM |
860 | + t = store_get(sizeof(tree_node) + len + sizeof(expiring_data)); |
861 | + e = (expiring_data *)((char *)t + sizeof(tree_node) + len); | |
862 | + e->expiry = do_cache == UINT_MAX ? 0 : time(NULL)+do_cache; | |
863 | + e->ptr = data; | |
864 | + memcpy(t->name, keystring, len); | |
865 | + t->data.ptr = e; | |
866 | + tree_insertnode(&c->item_cache, t); | |
4022a9ec | 867 | + } |
cb4fdfcc | 868 | } |
4022a9ec | 869 | |
cb4fdfcc AM |
870 | /* If caching was disabled, empty the cache tree. We just set the cache |
871 | @@ -540,34 +560,19 @@ if ((t = tree_search(c->item_cache, keystring)) == NULL) | |
872 | } | |
873 | } | |
4022a9ec | 874 | |
cb4fdfcc | 875 | -/* Data was in the cache already; set the pointer from the tree node */ |
4022a9ec | 876 | - |
cb4fdfcc AM |
877 | -else |
878 | - { | |
879 | - data = US t->data.ptr; | |
880 | - DEBUG(D_lookup) debug_printf("cached data used for lookup of %s%s%s\n", | |
881 | - keystring, | |
882 | - (filename == NULL)? US"" : US"\n in ", | |
883 | - (filename == NULL)? US"" : filename); | |
884 | - } | |
4022a9ec | 885 | - |
cb4fdfcc | 886 | -/* Debug: output the answer */ |
4022a9ec | 887 | - |
cb4fdfcc AM |
888 | DEBUG(D_lookup) |
889 | { | |
890 | - if (data == NULL) | |
891 | - { | |
892 | - if (search_find_defer) debug_printf("lookup deferred: %s\n", | |
893 | - search_error_message); | |
894 | - else debug_printf("lookup failed\n"); | |
4022a9ec | 895 | - } |
cb4fdfcc AM |
896 | - else debug_printf("lookup yielded: %s\n", data); |
897 | + if (data) | |
898 | + debug_printf("lookup yielded: %s\n", data); | |
899 | + else if (search_find_defer) | |
900 | + debug_printf("lookup deferred: %s\n", search_error_message); | |
901 | + else debug_printf("lookup failed\n"); | |
902 | } | |
4022a9ec | 903 | |
cb4fdfcc | 904 | /* Return it in new dynamic store in the regular pool */ |
4022a9ec | 905 | |
cb4fdfcc AM |
906 | store_pool = old_pool; |
907 | -return (data == NULL)? NULL : string_copy(data); | |
908 | +return data ? string_copy(data) : NULL; | |
4022a9ec AM |
909 | } |
910 | ||
4022a9ec | 911 | |
4022a9ec | 912 | diff --git a/src/src/structs.h b/src/src/structs.h |
cb4fdfcc | 913 | index 6f143d6..d9da38b 100644 |
4022a9ec AM |
914 | --- a/src/src/structs.h |
915 | +++ b/src/src/structs.h | |
cb4fdfcc AM |
916 | @@ -657,6 +657,16 @@ typedef struct tree_node { |
917 | uschar name[1]; /* node name - variable length */ | |
918 | } tree_node; | |
919 | ||
920 | +/* Structure for holding time-limited data such as DNS returns. | |
921 | +We use this rather than extending tree_node to avoid wasting | |
922 | +space for most tree use (variables...) at the cost of complexity | |
923 | +for the lookups cache */ | |
924 | + | |
925 | +typedef struct expiring_data { | |
926 | + time_t expiry; /* if nonzero, data invalid after this time */ | |
927 | + void *ptr; /* pointer to data */ | |
928 | +} expiring_data; | |
929 | + | |
930 | /* Structure for holding the handle and the cached last lookup for searches. | |
931 | This block is pointed to by the tree entry for the file. The file can get | |
932 | closed if too many are opened at once. There is a LRU chain for deciding which | |
933 | @@ -676,6 +686,7 @@ uncompressed, but the data pointer is into the raw data. */ | |
934 | typedef struct { | |
935 | uschar name[DNS_MAXNAME]; /* domain name */ | |
936 | int type; /* record type */ | |
937 | + unsigned short ttl; /* time-to-live, seconds */ | |
938 | int size; /* size of data */ | |
939 | uschar *data; /* pointer to data */ | |
940 | } dns_record; | |
941 | diff --git a/src/src/verify.c b/src/src/verify.c | |
942 | index e00e7b9..d392fda 100644 | |
943 | --- a/src/src/verify.c | |
944 | +++ b/src/src/verify.c | |
945 | @@ -21,6 +21,7 @@ uschar ctbuffer[8192]; | |
946 | /* Structure for caching DNSBL lookups */ | |
4022a9ec | 947 | |
cb4fdfcc AM |
948 | typedef struct dnsbl_cache_block { |
949 | + time_t expiry; | |
950 | dns_address *rhs; | |
951 | uschar *text; | |
952 | int rc; | |
953 | @@ -3584,21 +3585,37 @@ if (!string_format(query, sizeof(query), "%s.%s", prepend, domain)) | |
4022a9ec | 954 | |
cb4fdfcc | 955 | /* Look for this query in the cache. */ |
4022a9ec | 956 | |
cb4fdfcc AM |
957 | -t = tree_search(dnsbl_cache, query); |
958 | +if ( (t = tree_search(dnsbl_cache, query)) | |
959 | + && (cb = t->data.ptr)->expiry > time(NULL) | |
960 | + ) | |
4022a9ec | 961 | + |
cb4fdfcc | 962 | +/* Previous lookup was cached */ |
4022a9ec | 963 | + |
cb4fdfcc AM |
964 | + { |
965 | + HDEBUG(D_dnsbl) debug_printf("using result of previous DNS lookup\n"); | |
966 | + } | |
4022a9ec | 967 | |
cb4fdfcc AM |
968 | /* If not cached from a previous lookup, we must do a DNS lookup, and |
969 | cache the result in permanent memory. */ | |
4022a9ec | 970 | |
cb4fdfcc AM |
971 | -if (t == NULL) |
972 | +else | |
4022a9ec | 973 | { |
cb4fdfcc | 974 | + uint ttl = 3600; |
4022a9ec | 975 | + |
cb4fdfcc | 976 | store_pool = POOL_PERM; |
4022a9ec | 977 | |
cb4fdfcc AM |
978 | - /* Set up a tree entry to cache the lookup */ |
979 | + if (t) | |
4022a9ec | 980 | + { |
cb4fdfcc | 981 | + HDEBUG(D_dnsbl) debug_printf("cached data found but past valid time; "); |
4022a9ec AM |
982 | + } |
983 | ||
cb4fdfcc AM |
984 | - t = store_get(sizeof(tree_node) + Ustrlen(query)); |
985 | - Ustrcpy(t->name, query); | |
986 | - t->data.ptr = cb = store_get(sizeof(dnsbl_cache_block)); | |
987 | - (void)tree_insertnode(&dnsbl_cache, t); | |
988 | + else | |
989 | + { /* Set up a tree entry to cache the lookup */ | |
990 | + t = store_get(sizeof(tree_node) + Ustrlen(query)); | |
991 | + Ustrcpy(t->name, query); | |
992 | + t->data.ptr = cb = store_get(sizeof(dnsbl_cache_block)); | |
993 | + (void)tree_insertnode(&dnsbl_cache, t); | |
4022a9ec AM |
994 | + } |
995 | ||
cb4fdfcc | 996 | /* Do the DNS loopup . */ |
4022a9ec | 997 | |
cb4fdfcc | 998 | @@ -3616,7 +3633,10 @@ if (t == NULL) |
4022a9ec | 999 | |
cb4fdfcc AM |
1000 | Quite apart from one A6 RR generating multiple addresses, there are DNS |
1001 | lists that return more than one A record, so we must handle multiple | |
1002 | - addresses generated in that way as well. */ | |
1003 | + addresses generated in that way as well. | |
1004 | + | |
1005 | + Mark the cache entry with the "now" plus the minimum of the address TTLs, | |
1006 | + or some suitably far-future time if none were found. */ | |
4022a9ec | 1007 | |
cb4fdfcc AM |
1008 | if (cb->rc == DNS_SUCCEED) |
1009 | { | |
1010 | @@ -3634,6 +3654,7 @@ if (t == NULL) | |
1011 | *addrp = da; | |
1012 | while (da->next != NULL) da = da->next; | |
1013 | addrp = &(da->next); | |
1014 | + if (ttl > rr->ttl) ttl = rr->ttl; | |
1015 | } | |
1016 | } | |
4022a9ec | 1017 | } |
cb4fdfcc AM |
1018 | @@ -3645,17 +3666,10 @@ if (t == NULL) |
1019 | if (cb->rhs == NULL) cb->rc = DNS_NODATA; | |
4022a9ec | 1020 | } |
4022a9ec | 1021 | |
cb4fdfcc AM |
1022 | + cb->expiry = time(NULL)+ttl; |
1023 | store_pool = old_pool; | |
1024 | } | |
4022a9ec | 1025 | |
cb4fdfcc AM |
1026 | -/* Previous lookup was cached */ |
1027 | - | |
1028 | -else | |
1029 | - { | |
1030 | - HDEBUG(D_dnsbl) debug_printf("using result of previous DNS lookup\n"); | |
1031 | - cb = t->data.ptr; | |
1032 | - } | |
1033 | - | |
1034 | /* We now have the result of the DNS lookup, either newly done, or cached | |
1035 | from a previous call. If the lookup succeeded, check against the address | |
1036 | list if there is one. This may be a positive equality list (introduced by | |
1037 | ||
1038 | commit c4dcf906ceb3a45c6b30f76476d73ca836b262cd | |
1039 | Author: Jeremy Harris <jgh146exb@wizmail.org> | |
1040 | Date: Sat Sep 19 13:59:22 2015 +0100 | |
1041 | ||
1042 | Retry: always use interface, if set, for retry DB key. Bug 1678 | |
1043 | ||
1044 | Even constant values must be used, as multiple transports with | |
1045 | different values may be in play and should be kept distinct. | |
1046 | ||
1047 | (cherry picked from commit 6f6dedccb47f231a0712d882da20feffbac8d0bc) | |
1048 | ||
1049 | diff --git a/src/src/functions.h b/src/src/functions.h | |
1050 | index 0257904..94e3f5f 100644 | |
1051 | --- a/src/src/functions.h | |
1052 | +++ b/src/src/functions.h | |
1053 | @@ -374,7 +374,7 @@ extern int smtp_sock_connect(host_item *, int, int, uschar *, | |
1054 | extern int smtp_feof(void); | |
1055 | extern int smtp_ferror(void); | |
1056 | extern uschar *smtp_get_connection_info(void); | |
1057 | -extern BOOL smtp_get_interface(uschar *, int, address_item *, BOOL *, | |
1058 | +extern BOOL smtp_get_interface(uschar *, int, address_item *, | |
1059 | uschar **, uschar *); | |
1060 | extern BOOL smtp_get_port(uschar *, address_item *, int *, uschar *); | |
1061 | extern int smtp_getc(void); | |
1062 | diff --git a/src/src/smtp_out.c b/src/src/smtp_out.c | |
1063 | index c704a0b..2fdf38b 100644 | |
1064 | --- a/src/src/smtp_out.c | |
1065 | +++ b/src/src/smtp_out.c | |
1066 | @@ -26,7 +26,6 @@ Arguments: | |
1067 | which case the function does nothing | |
1068 | host_af AF_INET or AF_INET6 for the outgoing IP address | |
1069 | addr the mail address being handled (for setting errors) | |
1070 | - changed if not NULL, set TRUE if expansion actually changed istring | |
1071 | interface point this to the interface | |
1072 | msg to add to any error message | |
1073 | ||
1074 | @@ -36,7 +35,7 @@ Returns: TRUE on success, FALSE on failure, with error message | |
1075 | ||
1076 | BOOL | |
1077 | smtp_get_interface(uschar *istring, int host_af, address_item *addr, | |
1078 | - BOOL *changed, uschar **interface, uschar *msg) | |
1079 | + uschar **interface, uschar *msg) | |
1080 | { | |
1081 | const uschar * expint; | |
1082 | uschar *iface; | |
1083 | @@ -54,8 +53,6 @@ if (expint == NULL) | |
1084 | return FALSE; | |
1085 | } | |
4022a9ec | 1086 | |
cb4fdfcc AM |
1087 | -if (changed != NULL) *changed = expint != istring; |
1088 | - | |
1089 | while (isspace(*expint)) expint++; | |
1090 | if (*expint == 0) return TRUE; | |
4022a9ec | 1091 | |
cb4fdfcc AM |
1092 | diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c |
1093 | index 5ac5533..ba7fb5e 100644 | |
1094 | --- a/src/src/transports/smtp.c | |
1095 | +++ b/src/src/transports/smtp.c | |
1096 | @@ -3174,7 +3174,6 @@ for (cutoff_retry = 0; expired && | |
1097 | BOOL serialized = FALSE; | |
1098 | BOOL host_is_expired = FALSE; | |
1099 | BOOL message_defer = FALSE; | |
1100 | - BOOL ifchanges = FALSE; | |
1101 | BOOL some_deferred = FALSE; | |
1102 | address_item *first_addr = NULL; | |
1103 | uschar *interface = NULL; | |
1104 | @@ -3350,15 +3349,18 @@ for (cutoff_retry = 0; expired && | |
1105 | if (Ustrcmp(pistring, ":25") == 0) pistring = US""; | |
1106 | ||
1107 | /* Select IPv4 or IPv6, and choose an outgoing interface. If the interface | |
1108 | - string changes upon expansion, we must add it to the key that is used for | |
1109 | - retries, because connections to the same host from a different interface | |
1110 | - should be treated separately. */ | |
1111 | + string is set, even if constant (as different transports can have different | |
1112 | + constant settings), we must add it to the key that is used for retries, | |
1113 | + because connections to the same host from a different interface should be | |
1114 | + treated separately. */ | |
1115 | ||
1116 | host_af = (Ustrchr(host->address, ':') == NULL)? AF_INET : AF_INET6; | |
1117 | - if (!smtp_get_interface(ob->interface, host_af, addrlist, &ifchanges, | |
1118 | - &interface, tid)) | |
1119 | - return FALSE; | |
1120 | - if (ifchanges) pistring = string_sprintf("%s/%s", pistring, interface); | |
1121 | + if ((rs = ob->interface) && *rs) | |
1122 | + { | |
1123 | + if (!smtp_get_interface(rs, host_af, addrlist, &interface, tid)) | |
1124 | + return FALSE; | |
1125 | + pistring = string_sprintf("%s/%s", pistring, interface); | |
1126 | + } | |
4022a9ec | 1127 | |
cb4fdfcc AM |
1128 | /* The first time round the outer loop, check the status of the host by |
1129 | inspecting the retry data. The second time round, we are interested only | |
1130 | diff --git a/src/src/verify.c b/src/src/verify.c | |
1131 | index d392fda..6411c7e 100644 | |
1132 | --- a/src/src/verify.c | |
1133 | +++ b/src/src/verify.c | |
1134 | @@ -444,7 +444,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. | |
1135 | ||
1136 | host_af = (Ustrchr(host->address, ':') == NULL)? AF_INET:AF_INET6; | |
1137 | ||
1138 | - if (!smtp_get_interface(tf->interface, host_af, addr, NULL, &interface, | |
1139 | + if (!smtp_get_interface(tf->interface, host_af, addr, &interface, | |
1140 | US"callout") || | |
1141 | !smtp_get_port(tf->port, addr, &port, US"callout")) | |
1142 | log_write(0, LOG_MAIN|LOG_PANIC, "<%s>: %s", addr->address, | |
1143 | @@ -579,7 +579,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. | |
1144 | deliver_domain = addr->domain; | |
1145 | transport_name = addr->transport->name; | |
1146 | ||
1147 | - if ( !smtp_get_interface(tf->interface, host_af, addr, NULL, &interface, | |
1148 | + if ( !smtp_get_interface(tf->interface, host_af, addr, &interface, | |
1149 | US"callout") | |
1150 | || !smtp_get_port(tf->port, addr, &port, US"callout") | |
1151 | ) |