From: Philip Hazel Date: Tue, 4 Jan 2005 16:36:27 +0000 (+0000) Subject: Added the hosts_max_try_hardlimit option. (The removed file is left over X-Git-Tag: exim-4_50~48 X-Git-Url: https://vcs.fsf.org/?p=exim.git;a=commitdiff_plain;h=533244aff041c5fd9d193947f533a4c0150a9c9e;hp=60dc5e56c3e1a53aa42c0b74a4af3f7a3ad9118c Added the hosts_max_try_hardlimit option. (The removed file is left over from a previous update; I screwed up the CVS-ing.) --- diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index bf214bce7..891a3e04e 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.63 2005/01/04 13:31:41 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.64 2005/01/04 16:36:27 ph10 Exp $ Change log file for Exim from version 4.21 ------------------------------------------- @@ -290,6 +290,8 @@ Exim version 4.50 SMTP connection. (Fix 4.40/11 dealt with the non-cache case, but overlooked the caching.) +66. Added hosts_max_try_hardlimit to the smtp transport, default 50. + Exim version 4.43 ----------------- diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 30cb58ab5..5d6e915d3 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/NewStuff,v 1.24 2004/12/29 10:16:52 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/NewStuff,v 1.25 2005/01/04 16:36:27 ph10 Exp $ New Features in Exim -------------------- @@ -247,6 +247,14 @@ Version 4.50 (2) The default for smtp_banner uses $smtp_active_hostname instead of $primary_hostname. +22. The hosts_max_try_hardlimit option (default 50) is added to the smtp + transport. Exim will never try more than this number of IP addresses; if it + hits this limit and they are all timed out, the message is bounced, even + though not all IP addresses may have been tried. Compare hosts_max_try, + which is a "soft" limit, because Exim will exceed it when hosts time out. + The new limit is a protection against lunatic DNS configurations with + hundreds of IP addresses. + Version 4.43 ------------ diff --git a/doc/doc-txt/OptionLists.txt b/doc/doc-txt/OptionLists.txt index ae04feb59..ebdae0f51 100644 --- a/doc/doc-txt/OptionLists.txt +++ b/doc/doc-txt/OptionLists.txt @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/OptionLists.txt,v 1.4 2004/11/10 10:29:56 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/OptionLists.txt,v 1.5 2005/01/04 16:36:27 ph10 Exp $ LISTS OF EXIM OPTIONS --------------------- @@ -247,6 +247,7 @@ hosts_avoid_esmtp host list unset smtp hosts_avoid_tls host list unset smtp 3.20 hosts_connection_nolog host list unset main 4.43 hosts_max_try integer 5 smtp 3.20 +hosts_max_try_hardlimit integer 50 smtp 4.50 hosts_nopass_tls host list unset smtp 4.00 hosts_override boolean false smtp 2.11 hosts_randomize boolean false manualroute 4.00 diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 424f9afa9..738fd1cc2 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/transports/smtp.c,v 1.3 2005/01/04 10:00:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/transports/smtp.c,v 1.4 2005/01/04 16:36:28 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -57,6 +57,8 @@ optionlist smtp_transport_options[] = { #endif { "hosts_max_try", opt_int, (void *)offsetof(smtp_transport_options_block, hosts_max_try) }, + { "hosts_max_try_hardlimit", opt_int, + (void *)offsetof(smtp_transport_options_block, hosts_max_try_hardlimit) }, #ifdef SUPPORT_TLS { "hosts_nopass_tls", opt_stringptr, (void *)offsetof(smtp_transport_options_block, hosts_nopass_tls) }, @@ -138,6 +140,7 @@ smtp_transport_options_block smtp_transport_option_defaults = { 10*60, /* final timeout */ 1024, /* size_addition */ 5, /* hosts_max_try */ + 50, /* hosts_max_try_hardlimit */ FALSE, /* allow_localhost */ FALSE, /* gethostbyname */ TRUE, /* dns_qualify_single */ @@ -1926,6 +1929,7 @@ int hosts_looked_up = 0; int hosts_retry = 0; int hosts_serial = 0; int hosts_total = 0; +int total_hosts_tried = 0; address_item *addr; BOOL expired = TRUE; BOOL continuing = continue_hostname != NULL; @@ -2091,7 +2095,9 @@ if (Ustrcmp(pistring, ":25") == 0) pistring = US""; . If there are any addresses whose status is still DEFER, carry on to the next host/IPaddress, unless we have tried the number of hosts given - by hosts_max_try; otherwise return. + by hosts_max_try or hosts_max_try_hardlimit; otherwise return. Note that + there is some fancy logic for hosts_max_try that means its limit can be + overstepped in some circumstances. If we get to the end of the list, all hosts have deferred at least one address, or not reached their retry times. If delay_after_cutoff is unset, it requests a @@ -2108,7 +2114,9 @@ for (cutoff_retry = 0; expired && int unexpired_hosts_tried = 0; for (host = hostlist; - host != NULL && unexpired_hosts_tried < ob->hosts_max_try; + host != NULL && + unexpired_hosts_tried < ob->hosts_max_try && + total_hosts_tried < ob->hosts_max_try_hardlimit; host = nexthost) { int rc; @@ -2413,13 +2421,16 @@ for (cutoff_retry = 0; expired && /* This is for real. If the host is expired, we don't count it for hosts_max_retry. This ensures that all hosts must expire before an address - is timed out. Otherwise, if we are about to hit the hosts_max_retry limit, - check to see if there is a subsequent hosts with a different MX value. If - so, make that the next host, and don't count this one. This is a heuristic - to make sure that different MXs do get tried. With a normal kind of retry - rule, they would get tried anyway when the earlier hosts were delayed, but - if the domain has a "retry every time" type of rule - as is often used for - the the very large ISPs, that won't happen. */ + is timed out, unless hosts_max_try_hardlimit (which protects against + lunatic DNS configurations) is reached. + + If the host is not expired and we are about to hit the hosts_max_retry + limit, check to see if there is a subsequent hosts with a different MX + value. If so, make that the next host, and don't count this one. This is a + heuristic to make sure that different MXs do get tried. With a normal kind + of retry rule, they would get tried anyway when the earlier hosts were + delayed, but if the domain has a "retry every time" type of rule - as is + often used for the the very large ISPs, that won't happen. */ else { @@ -2441,6 +2452,7 @@ for (cutoff_retry = 0; expired && /* Attempt the delivery. */ + total_hosts_tried++; rc = smtp_deliver(addrlist, host, host_af, port, interface, tblock, expanded_hosts != NULL, &message_defer, FALSE); @@ -2606,7 +2618,7 @@ for (cutoff_retry = 0; expired && maximum retry time for this host. This means we may try try all hosts, ignoring the limit, when messages have been around for some time. This is important because if we don't try all hosts, the address will never time - out. */ + out. NOTE: this does not apply to hosts_max_try_hardlimit. */ if ((rc == DEFER || some_deferred) && nexthost != NULL) { @@ -2671,15 +2683,26 @@ found, we end up here, but can detect these cases and handle them specially. */ for (addr = addrlist; addr != NULL; addr = addr->next) { /* If host is not NULL, it means that we stopped processing the host list - because of hosts_max_try. This means we need to behave as if some hosts were - skipped because their retry time had not come. Specifically, this prevents - the address from timing out. */ + because of hosts_max_try or hosts_max_try_hardlimit. In the former case, this + means we need to behave as if some hosts were skipped because their retry + time had not come. Specifically, this prevents the address from timing out. + However, if we have hit hosts_max_try_hardlimit, we want to behave as if all + hosts were tried. */ if (host != NULL) { - DEBUG(D_transport) - debug_printf("hosts_max_try limit caused some hosts to be skipped\n"); - setflag(addr, af_retry_skipped); + if (total_hosts_tried >= ob->hosts_max_try_hardlimit) + { + DEBUG(D_transport) + debug_printf("hosts_max_try_hardlimit reached: behave as if all " + "hosts were tried\n"); + } + else + { + DEBUG(D_transport) + debug_printf("hosts_max_try limit caused some hosts to be skipped\n"); + setflag(addr, af_retry_skipped); + } } if (queue_smtp) /* no deliveries attempted */ diff --git a/src/src/transports/smtp.h b/src/src/transports/smtp.h index 756da659c..99af73228 100644 --- a/src/src/transports/smtp.h +++ b/src/src/transports/smtp.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/transports/smtp.h,v 1.2 2005/01/04 10:00:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/transports/smtp.h,v 1.3 2005/01/04 16:36:28 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -32,6 +32,7 @@ typedef struct { int final_timeout; int size_addition; int hosts_max_try; + int hosts_max_try_hardlimit; BOOL allow_localhost; BOOL gethostbyname; BOOL dns_qualify_single;