X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/4fab92fbc2b63bac2d89c1dae69fa1845cb640b7..da40b1ec6b91ccd3faa4def9e5cff05ec51ca573:/src/src/retry.c diff --git a/src/src/retry.c b/src/src/retry.c index 364591bd0..d068f547d 100644 --- a/src/src/retry.c +++ b/src/src/retry.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2015 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions concerned with retrying unsuccessful deliveries. */ @@ -33,29 +33,28 @@ retry_ultimate_address_timeout(uschar *retry_key, const uschar *domain, dbdata_retry *retry_record, time_t now) { BOOL address_timeout; +retry_config * retry; DEBUG(D_retry) { debug_printf("retry time not reached: checking ultimate address timeout\n"); - debug_printf(" now=%d first_failed=%d next_try=%d expired=%d\n", - (int)now, (int)retry_record->first_failed, - (int)retry_record->next_try, retry_record->expired); + debug_printf(" now=" TIME_T_FMT " first_failed=" TIME_T_FMT + " next_try=" TIME_T_FMT " expired=%c\n", + now, retry_record->first_failed, + retry_record->next_try, retry_record->expired ? 'T' : 'F'); } -retry_config *retry = - retry_find_config(retry_key+2, domain, +retry = retry_find_config(retry_key+2, domain, retry_record->basic_errno, retry_record->more_errno); -if (retry != NULL && retry->rules != NULL) +if (retry && retry->rules) { retry_rule *last_rule; - for (last_rule = retry->rules; - last_rule->next != NULL; - last_rule = last_rule->next); + for (last_rule = retry->rules; last_rule->next; last_rule = last_rule->next) ; DEBUG(D_retry) - debug_printf(" received_time=%d diff=%d timeout=%d\n", - received_time, (int)(now - received_time), last_rule->timeout); - address_timeout = (now - received_time > last_rule->timeout); + debug_printf(" received_time=" TIME_T_FMT " diff=%d timeout=%d\n", + received_time.tv_sec, (int)(now - received_time.tv_sec), last_rule->timeout); + address_timeout = (now - received_time.tv_sec > last_rule->timeout); } else { @@ -159,8 +158,7 @@ deliveries (so as to do it all in one go). The tree records addresses that have become unusable during this delivery process (i.e. those that will get put into the retry database when it is updated). */ -node = tree_search(tree_unusable, host_key); -if (node != NULL) +if ((node = tree_search(tree_unusable, host_key))) { DEBUG(D_transport|D_retry) debug_printf("found in tree of unusables\n"); host->status = (node->data.val > 255)? @@ -172,7 +170,7 @@ if (node != NULL) /* Open the retry database, giving up if there isn't one. Otherwise, search for the retry records, and then close the database again. */ -if ((dbm_file = dbfn_open(US"retry", O_RDONLY, &dbblock, FALSE)) == NULL) +if (!(dbm_file = dbfn_open(US"retry", O_RDONLY, &dbblock, FALSE, TRUE))) { DEBUG(D_deliver|D_retry|D_hints_lookup) debug_printf("no retry data available\n"); @@ -184,7 +182,7 @@ dbfn_close(dbm_file); /* Ignore the data if it is too old - too long since it was written */ -if (host_retry_record == NULL) +if (!host_retry_record) { DEBUG(D_transport|D_retry) debug_printf("no host retry record\n"); } @@ -194,7 +192,7 @@ else if (now - host_retry_record->time_stamp > retry_data_expire) DEBUG(D_transport|D_retry) debug_printf("host retry record too old\n"); } -if (message_retry_record == NULL) +if (!message_retry_record) { DEBUG(D_transport|D_retry) debug_printf("no message retry record\n"); } @@ -211,14 +209,14 @@ address. Allow the delivery if it has. Otherwise set the appropriate unusable flag and return FALSE. Otherwise arrange to return TRUE if this is an expired host. */ -if (host_retry_record != NULL) +if (host_retry_record) { *retry_host_key = host_key; /* We have not reached the next try time. Check for the ultimate address timeout if the host has not expired. */ - if (now < host_retry_record->next_try && !deliver_force) + if (now < host_retry_record->next_try && !f.deliver_force) { if (!host_retry_record->expired && retry_ultimate_address_timeout(host_key, domain, @@ -243,10 +241,10 @@ if (host_retry_record != NULL) for reaching its retry time (or forcing). If not, mark the host unusable, unless the ultimate address timeout has been reached. */ -if (message_retry_record != NULL) +if (message_retry_record) { *retry_message_key = message_key; - if (now < message_retry_record->next_try && !deliver_force) + if (now < message_retry_record->next_try && !f.deliver_force) { if (!retry_ultimate_address_timeout(host_key, domain, message_retry_record, now)) @@ -293,8 +291,9 @@ Returns: nothing void retry_add_item(address_item *addr, uschar *key, int flags) { -retry_item *rti = store_get(sizeof(retry_item)); +retry_item *rti = store_get(sizeof(retry_item), FALSE); host_item * host = addr->host_used; + rti->next = addr->retries; addr->retries = rti; rti->key = key; @@ -378,7 +377,7 @@ if (alternate) alternate = string_sprintf("*@%s", alternate); /* Scan the configured retry items. */ -for (yield = retries; yield != NULL; yield = yield->next) +for (yield = retries; yield; yield = yield->next) { const uschar *plist = yield->pattern; const uschar *slist = yield->senders; @@ -472,19 +471,19 @@ for (yield = retries; yield != NULL; yield = yield->next) /* If the "senders" condition is set, check it. Note that sender_address may be null during -brt checking, in which case we do not use this rule. */ - if (slist != NULL && (sender_address == NULL || - match_address_list(sender_address, TRUE, TRUE, &slist, NULL, -1, 0, - NULL) != OK)) + if ( slist + && ( !sender_address + || match_address_list_basic(sender_address, &slist, 0) != OK + ) ) continue; /* Check for a match between the address list item at the start of this retry rule and either the main or alternate keys. */ - if (match_address_list(key, TRUE, TRUE, &plist, NULL, -1, UCHAR_MAX+1, - NULL) == OK || - (alternate != NULL && - match_address_list(alternate, TRUE, TRUE, &plist, NULL, -1, - UCHAR_MAX+1, NULL) == OK)) + if ( match_address_list_basic(key, &plist, UCHAR_MAX+1) == OK + || ( alternate + && match_address_list_basic(alternate, &plist, UCHAR_MAX+1) == OK + ) ) break; } @@ -524,7 +523,6 @@ retry_update(address_item **addr_defer, address_item **addr_failed, open_db dbblock; open_db *dbm_file = NULL; time_t now = time(NULL); -int i; DEBUG(D_retry) debug_printf("Processing retry items\n"); @@ -532,7 +530,7 @@ DEBUG(D_retry) debug_printf("Processing retry items\n"); Deferred addresses must be handled after failed ones, because some may be moved to the failed chain if they have timed out. */ -for (i = 0; i < 3; i++) +for (int i = 0; i < 3; i++) { address_item *endaddr, *addr; address_item *last_first = NULL; @@ -556,7 +554,6 @@ for (i = 0; i < 3; i++) while ((endaddr = *paddr)) { BOOL timed_out = FALSE; - retry_item *rti; for (addr = endaddr; addr; addr = addr->parent) { @@ -568,7 +565,7 @@ for (i = 0; i < 3; i++) /* Loop for each retry item. */ - for (rti = addr->retries; rti; rti = rti->next) + for (retry_item * rti = addr->retries; rti; rti = rti->next) { uschar *message; int message_length, message_space, failing_interval, next_try; @@ -583,7 +580,7 @@ for (i = 0; i < 3; i++) reached their retry next try time. */ if (!dbm_file) - dbm_file = dbfn_open(US"retry", O_RDWR, &dbblock, TRUE); + dbm_file = dbfn_open(US"retry", O_RDWR, &dbblock, TRUE, TRUE); if (!dbm_file) { @@ -639,7 +636,6 @@ for (i = 0; i < 3; i++) } DEBUG(D_retry) - { if (rti->flags & rf_host) debug_printf("retry for %s (%s) = %s %d %d\n", rti->key, addr->domain, retry->pattern, retry->basic_errno, @@ -647,7 +643,6 @@ for (i = 0; i < 3; i++) else debug_printf("retry for %s = %s %d %d\n", rti->key, retry->pattern, retry->basic_errno, retry->more_errno); - } /* Set up the message for the database retry record. Because DBM records have a maximum data length, we enforce a limit. There isn't @@ -671,7 +666,8 @@ for (i = 0; i < 3; i++) if (!retry_record) { - retry_record = store_get(sizeof(dbdata_retry) + message_length); + retry_record = store_get(sizeof(dbdata_retry) + message_length, + is_tainted(message)); message_space = message_length; retry_record->first_failed = now; retry_record->last_try = now; @@ -756,7 +752,7 @@ for (i = 0; i < 3; i++) this is a small bit of code, and it does no harm to leave it in place, just in case. */ - if ( received_time <= retry_record->first_failed + if ( received_time.tv_sec <= retry_record->first_failed && addr == endaddr && !retry_record->expired && rule) @@ -764,7 +760,7 @@ for (i = 0; i < 3; i++) retry_rule *last_rule; for (last_rule = rule; last_rule->next; last_rule = last_rule->next) ; - if (now - received_time > last_rule->timeout) + if (now - received_time.tv_sec > last_rule->timeout) { DEBUG(D_retry) debug_printf("on queue longer than maximum retry\n"); timedout_count++; @@ -815,7 +811,7 @@ for (i = 0; i < 3; i++) if (message_length > message_space) { - dbdata_retry *newr = store_get(sizeof(dbdata_retry) + message_length); + dbdata_retry *newr = store_get(sizeof(dbdata_retry) + message_length, FALSE); memcpy(newr, retry_record, sizeof(dbdata_retry)); retry_record = newr; } @@ -861,10 +857,8 @@ for (i = 0; i < 3; i++) timed_out = TRUE; } else - { DEBUG(D_retry) debug_printf("timed out but some hosts were skipped\n"); - } } /* Loop for an address and its parents */ /* If this is a deferred address, and retry processing was requested by @@ -892,16 +886,17 @@ for (i = 0; i < 3; i++) for (;; addr = addr->next) { setflag(addr, af_retry_timedout); - addr->message = (addr->message == NULL)? US"retry timeout exceeded" : - string_sprintf("%s: retry timeout exceeded", addr->message); - addr->user_message = (addr->user_message == NULL)? - US"retry timeout exceeded" : - string_sprintf("%s: retry timeout exceeded", addr->user_message); + addr->message = addr->message + ? string_sprintf("%s: retry timeout exceeded", addr->message) + : US"retry timeout exceeded"; + addr->user_message = addr->user_message + ? string_sprintf("%s: retry timeout exceeded", addr->user_message) + : US"retry timeout exceeded"; log_write(0, LOG_MAIN, "** %s%s%s%s: retry timeout exceeded", addr->address, - (addr->parent == NULL)? US"" : US" <", - (addr->parent == NULL)? US"" : addr->parent->address, - (addr->parent == NULL)? US"" : US">"); + addr->parent ? US" <" : US"", + addr->parent ? addr->parent->address : US"", + addr->parent ? US">" : US""); if (addr == endaddr) break; }