From c456d9bb38922c3e5ff511b934a1b7a282935f75 Mon Sep 17 00:00:00 2001 From: Philip Hazel Date: Tue, 13 Mar 2007 15:32:47 +0000 Subject: [PATCH] Add host_find_failed=ignore and host_all_ignored to manualroute. --- doc/doc-txt/ChangeLog | 7 ++- doc/doc-txt/NewStuff | 9 +++- doc/doc-txt/OptionLists.txt | 3 +- src/src/macros.h | 5 +- src/src/routers/manualroute.c | 79 +++++++++++++++++++++++----- src/src/routers/manualroute.h | 4 +- src/src/routers/rf_lookup_hostlist.c | 9 +++- test/confs/0557 | 49 +++++++++++++++++ test/scripts/0000-Basic/0557 | 28 ++++++++++ test/stderr/0557 | 2 + test/stdout/0536 | 8 +-- test/stdout/0557 | 16 ++++++ 12 files changed, 195 insertions(+), 24 deletions(-) create mode 100644 test/confs/0557 create mode 100644 test/scripts/0000-Basic/0557 create mode 100644 test/stderr/0557 create mode 100644 test/stdout/0557 diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 7f6590ec6..9695d2d61 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.492 2007/03/13 11:26:49 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.493 2007/03/13 15:32:47 ph10 Exp $ Change log file for Exim from version 4.21 ------------------------------------------- @@ -163,6 +163,11 @@ PH/37 If a message is not accepted after it has had an id assigned (e.g. lack of a "<=" line in the log, and they are now listed as "not accepted". +PH/38 The host_find_failed option in the manualroute router can now be set + to "ignore", to completely ignore a host whose IP address cannot be + found. If all hosts are ignored, the behaviour is controlled by the new + host_all_ignored option. + Exim version 4.66 ----------------- diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 37368ac4d..bd43aecf8 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/NewStuff,v 1.144 2007/03/13 11:06:48 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/NewStuff,v 1.145 2007/03/13 15:32:47 ph10 Exp $ New Features in Exim -------------------- @@ -394,6 +394,13 @@ Version 4.67 19. The exigrep utility now has a -v option, which inverts the matching condition. +20. The host_find_failed option in the manualroute router can now be set to + "ignore". This causes it to completely ignore a host whose IP address + cannot be found. If all the hosts in the list are ignored, the behaviour is + controlled by the new host_all_ignored option, which takes the same values + as host_find_failed, except that it cannot be set to "ignore". Its default + is "defer". + Version 4.66 ------------ diff --git a/doc/doc-txt/OptionLists.txt b/doc/doc-txt/OptionLists.txt index 4d7e3bdad..fe080c567 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.30 2007/02/06 14:49:13 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/OptionLists.txt,v 1.31 2007/03/13 15:32:47 ph10 Exp $ LISTS OF EXIM OPTIONS --------------------- @@ -258,6 +258,7 @@ helo_verify_hosts host list unset main hide_child_in_errmsg false redirect 4.00 hold_domains domain list unset main 1.70 home_directory string* unset transports 4.00 replaces individual options +host_all_ignored string "defer" manualroute 4.67 host_find_failed string "freeze" manualroute 4.00 host_lookup host list unset main 3.00 host_lookup_order string list "bydns:byaddr" main 4.30 diff --git a/src/src/macros.h b/src/src/macros.h index 00e040b5f..f6aca465c 100644 --- a/src/src/macros.h +++ b/src/src/macros.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/macros.h,v 1.32 2007/02/06 11:11:40 ph10 Exp $ */ +/* $Cambridge: exim/src/src/macros.h,v 1.33 2007/03/13 15:32:48 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -754,13 +754,14 @@ enum { #define topt_no_body 0x040 /* Omit body */ #define topt_escape_headers 0x080 /* Apply escape check to headers */ -/* Codes for the host_find_failed option. */ +/* Codes for the host_find_failed and host_all_ignored options. */ #define hff_freeze 0 #define hff_defer 1 #define hff_pass 2 #define hff_decline 3 #define hff_fail 4 +#define hff_ignore 5 /* Router information flags */ diff --git a/src/src/routers/manualroute.c b/src/src/routers/manualroute.c index a6bbcd499..ab304a95f 100644 --- a/src/src/routers/manualroute.c +++ b/src/src/routers/manualroute.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/routers/manualroute.c,v 1.5 2007/01/08 10:50:20 ph10 Exp $ */ +/* $Cambridge: exim/src/src/routers/manualroute.c,v 1.6 2007/03/13 15:32:48 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -16,6 +16,8 @@ /* Options specific to the manualroute router. */ optionlist manualroute_router_options[] = { + { "host_all_ignored", opt_stringptr, + (void *)(offsetof(manualroute_router_options_block, host_all_ignored)) }, { "host_find_failed", opt_stringptr, (void *)(offsetof(manualroute_router_options_block, host_find_failed)) }, { "hosts_randomize", opt_bool, @@ -37,14 +39,30 @@ int manualroute_router_options_count = /* Default private options block for the manualroute router. */ manualroute_router_options_block manualroute_router_option_defaults = { - hff_freeze, /* host_find_failed code */ + -1, /* host_all_ignored code (unset) */ + -1, /* host_find_failed code (unset) */ FALSE, /* hosts_randomize */ + US"defer", /* host_all_ignored */ US"freeze", /* host_find_failed */ NULL, /* route_data */ NULL /* route_list */ }; +/* Names and values for host_find_failed and host_all_ignored. */ + +static uschar *hff_names[] = { + US"ignore", /* MUST be first - not valid for host_all_ignored */ + US"decline", + US"defer", + US"fail", + US"freeze", + US"pass" }; + +static int hff_codes[] = { hff_ignore, hff_decline, hff_defer, hff_fail, + hff_freeze, hff_pass }; + +static int hff_count= sizeof(hff_codes)/sizeof(int); @@ -60,23 +78,34 @@ manualroute_router_init(router_instance *rblock) { manualroute_router_options_block *ob = (manualroute_router_options_block *)(rblock->options_block); +int i; /* Host_find_failed must be a recognized word */ -if (Ustrcmp(ob->host_find_failed, "freeze") == 0) - ob->hff_code = hff_freeze; -else if (Ustrcmp(ob->host_find_failed, "decline") == 0) - ob->hff_code = hff_decline; -else if (Ustrcmp(ob->host_find_failed, "defer") == 0) - ob->hff_code = hff_defer; -else if (Ustrcmp(ob->host_find_failed, "pass") == 0) - ob->hff_code = hff_pass; -else if (Ustrcmp(ob->host_find_failed, "fail") == 0) - ob->hff_code = hff_fail; -else +for (i = 0; i < hff_count; i++) + { + if (Ustrcmp(ob->host_find_failed, hff_names[i]) == 0) + { + ob->hff_code = hff_codes[i]; + break; + } + } +if (ob->hff_code < 0) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n " "unrecognized setting for host_find_failed option", rblock->name); +for (i = 1; i < hff_count; i++) /* NB starts at 1 to skip "ignore" */ + { + if (Ustrcmp(ob->host_all_ignored, hff_names[i]) == 0) + { + ob->hai_code = hff_codes[i]; + break; + } + } +if (ob->hai_code < 0) + log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n " + "unrecognized setting for host_all_ignored option", rblock->name); + /* One of route_list or route_data must be specified */ if ((ob->route_list == NULL && ob->route_data == NULL) || @@ -401,6 +430,30 @@ rc = rf_lookup_hostlist(rblock, addr, rblock->ignore_target_hosts, lookup_type, ob->hff_code, addr_new); if (rc != OK) return rc; +/* If host_find_failed is set to "ignore", it is possible for all the hosts to +be ignored, in which case we will end up with an empty host list. What happens +is controlled by host_all_ignored. */ + +if (addr->host_list == NULL) + { + int i; + DEBUG(D_route) debug_printf("host_find_failed ignored every host\n"); + if (ob->hai_code == hff_decline) return DECLINE; + if (ob->hai_code == hff_pass) return PASS; + + for (i = 0; i < hff_count; i++) + if (ob->hai_code == hff_codes[i]) break; + + addr->message = string_sprintf("lookup failed for all hosts in %s router: " + "host_find_failed=ignore host_all_ignored=%s", rblock->name, hff_names[i]); + + if (ob->hai_code == hff_defer) return DEFER; + if (ob->hai_code == hff_fail) return FAIL; + + addr->special_action = SPECIAL_FREEZE; + return DEFER; + } + /* Finally, since we have done all the routing here, there must be a transport defined for these hosts. It will be a remote one, as a local transport is dealt with above. However, we don't need one if verifying only. */ diff --git a/src/src/routers/manualroute.h b/src/src/routers/manualroute.h index 6249d3f6c..38413999b 100644 --- a/src/src/routers/manualroute.h +++ b/src/src/routers/manualroute.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/routers/manualroute.h,v 1.5 2007/01/08 10:50:20 ph10 Exp $ */ +/* $Cambridge: exim/src/src/routers/manualroute.h,v 1.6 2007/03/13 15:32:48 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -12,8 +12,10 @@ /* Structure for the private options. */ typedef struct { + int hai_code; int hff_code; BOOL hosts_randomize; + uschar *host_all_ignored; uschar *host_find_failed; uschar *route_data; uschar *route_list; diff --git a/src/src/routers/rf_lookup_hostlist.c b/src/src/routers/rf_lookup_hostlist.c index 74b59173c..a5beb49f4 100644 --- a/src/src/routers/rf_lookup_hostlist.c +++ b/src/src/routers/rf_lookup_hostlist.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/routers/rf_lookup_hostlist.c,v 1.8 2007/01/08 10:50:20 ph10 Exp $ */ +/* $Cambridge: exim/src/src/routers/rf_lookup_hostlist.c,v 1.9 2007/03/13 15:32:48 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -157,6 +157,13 @@ for (h = addr->host_list; h != NULL; prev = h, h = next_h) if (rc == HOST_FIND_FAILED) { + if (hff_code == hff_ignore) + { + if (prev == NULL) addr->host_list = next_h; else prev->next = next_h; + h = prev; /* Because the loop sets prev to h */ + continue; /* With the next host */ + } + if (hff_code == hff_pass) return PASS; if (hff_code == hff_decline) return DECLINE; diff --git a/test/confs/0557 b/test/confs/0557 new file mode 100644 index 000000000..3b134db34 --- /dev/null +++ b/test/confs/0557 @@ -0,0 +1,49 @@ +# Exim test configuration 0557 + +X= +Y= +HOSTS= +HAI= + +exim_path = EXIM_PATH +host_lookup_order = bydns +primary_hostname = myhost.test.ex +rfc1413_query_timeout = 0s +spool_directory = DIR/spool +log_file_path = DIR/spool/log/%slog +gecos_pattern = "" +gecos_name = CALLER_NAME + +# ----- Main settings ----- + + +# ----- Routers ----- + +begin routers + +r1: + driver = manualroute + route_list = * HOSTS +X host_find_failed = ignore +Y host_all_ignored = HAI + no_more + self = send + transport = t1 + +r2: + driver = accept + transport = t2 + + +# ----- Transports ----- + +begin transports + +t1: + driver = smtp + +t2: + driver = appendfile + file = /dev/null + +# End diff --git a/test/scripts/0000-Basic/0557 b/test/scripts/0000-Basic/0557 new file mode 100644 index 000000000..8e05b4719 --- /dev/null +++ b/test/scripts/0000-Basic/0557 @@ -0,0 +1,28 @@ +# host_find_failed=ignore +1 +exim -DX=# -DY=# -bt userx@test.ex +**** +1 +exim -DY=# -DHOSTS=a.non.exist -bt userx@test.ex +**** +1 +exim -DY=# -DHOSTS=a.non.exist:b.non.exist -bt userx@test.ex +**** +exim -DY=# -DHOSTS=a.non.exist:127.0.0.1 -bt userx@test.ex +**** +exim -DY=# -DHOSTS=127.0.0.1:b.non.exist:127.0.0.2 -bt userx@test.ex +**** +1 +exim -DHOSTS=a.non.exist -DHAI=defer -bt userx@test.ex +**** +2 +exim -DHOSTS=a.non.exist -DHAI=decline -bt userx@test.ex +**** +2 +exim -DHOSTS=a.non.exist -DHAI=fail -bt userx@test.ex +**** +exim -DHOSTS=a.non.exist -DHAI=pass -bt userx@test.ex +**** +1 +exim -DHOSTS=a.non.exist -DHAI=freeze -bt userx@test.ex +**** diff --git a/test/stderr/0557 b/test/stderr/0557 new file mode 100644 index 000000000..8e5906ca8 --- /dev/null +++ b/test/stderr/0557 @@ -0,0 +1,2 @@ +LOG: MAIN + error in r1 router: no host(s) specified for domain * diff --git a/test/stdout/0536 b/test/stdout/0536 index cc4ce1e60..1ec52de1e 100644 --- a/test/stdout/0536 +++ b/test/stdout/0536 @@ -22,10 +22,10 @@ 590 Main code 590 5.4.3 Main and extended code 550 Wrong code -451 Temporary local problem - please try later -490 Temporary local problem - please try later -490 4.4.3 Temporary local problem - please try later -451 Temporary local problem - please try later +451 No code +490 Main code +490 4.4.3 Main and extended code +451 Wrong code 221 myhost.test.ex closing connection 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 250-myhost.test.ex Hello CALLER at test.ex diff --git a/test/stdout/0557 b/test/stdout/0557 new file mode 100644 index 000000000..5077c0d0a --- /dev/null +++ b/test/stdout/0557 @@ -0,0 +1,16 @@ +userx@test.ex cannot be resolved at this time: error in r1 router: no host(s) specified for domain * +userx@test.ex cannot be resolved at this time: lookup failed for all hosts in r1 router: host_find_failed=ignore host_all_ignored=defer +userx@test.ex cannot be resolved at this time: lookup failed for all hosts in r1 router: host_find_failed=ignore host_all_ignored=defer +userx@test.ex + router = r1, transport = t1 + host 127.0.0.1 [127.0.0.1] +userx@test.ex + router = r1, transport = t1 + host 127.0.0.1 [127.0.0.1] + host 127.0.0.2 [127.0.0.2] +userx@test.ex cannot be resolved at this time: lookup failed for all hosts in r1 router: host_find_failed=ignore host_all_ignored=defer +userx@test.ex is undeliverable: Unrouteable address +userx@test.ex is undeliverable: lookup failed for all hosts in r1 router: host_find_failed=ignore host_all_ignored=fail +userx@test.ex + router = r2, transport = t2 +userx@test.ex cannot be resolved at this time: lookup failed for all hosts in r1 router: host_find_failed=ignore host_all_ignored=freeze -- 2.25.1