Add host_find_failed=ignore and host_all_ignored to manualroute.
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Tue, 13 Mar 2007 15:32:47 +0000 (15:32 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Tue, 13 Mar 2007 15:32:47 +0000 (15:32 +0000)
12 files changed:
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
doc/doc-txt/OptionLists.txt
src/src/macros.h
src/src/routers/manualroute.c
src/src/routers/manualroute.h
src/src/routers/rf_lookup_hostlist.c
test/confs/0557 [new file with mode: 0644]
test/scripts/0000-Basic/0557 [new file with mode: 0644]
test/stderr/0557 [new file with mode: 0644]
test/stdout/0536
test/stdout/0557 [new file with mode: 0644]

index 7f6590ec6e24f1f14d5f292eb8e1ca767bdc53d4..9695d2d61d2a8f14d199f79dddf51991c80d473a 100644 (file)
@@ -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
 -----------------
index 37368ac4d69bf1f4c63a2f3a38332a5734da65ff..bd43aecf884019b908a0925e69226a57451d3edb 100644 (file)
@@ -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
 ------------
index 4d7e3bdada318561538b01c28141ed829ef3bb08..fe080c567b075cd8531a316cbc05a326ddf252ec 100644 (file)
@@ -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
index 00e040b5f8857516a9b1219ac7a9dad2b14d13e8..f6aca465ca4d16e1e7cbff0c85657bdd8ab8416c 100644 (file)
@@ -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 */
 
index a6bbcd4998af352339507cce3e64904ba9a03d99..ab304a95f1d67420c0b5350fd85f6ac9aee78586 100644 (file)
@@ -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. */
index 6249d3f6c6e97c2c19edc00ec37e59c743af00e7..38413999b60622c1ee898280dcb648d4d89a1bd1 100644 (file)
@@ -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    *
 /* 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;
index 74b59173c55253db98461a0dc34301ae2cddb961..a5beb49f4f7c2cafed52a4d05b6799c5f635039e 100644 (file)
@@ -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 (file)
index 0000000..3b134db
--- /dev/null
@@ -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 (file)
index 0000000..8e05b47
--- /dev/null
@@ -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 (file)
index 0000000..8e5906c
--- /dev/null
@@ -0,0 +1,2 @@
+LOG: MAIN
+  error in r1 router: no host(s) specified for domain *
index cc4ce1e601d35b3a8ff18bc7bfbb8177a1f1e33d..1ec52de1e5cd756cfa9c8f7412d01bb901cb6b5c 100644 (file)
 590 Main code\r
 590 5.4.3 Main and extended code\r
 550 Wrong code\r
-451 Temporary local problem - please try later\r
-490 Temporary local problem - please try later\r
-490 4.4.3 Temporary local problem - please try later\r
-451 Temporary local problem - please try later\r
+451 No code\r
+490 Main code\r
+490 4.4.3 Main and extended code\r
+451 Wrong code\r
 221 myhost.test.ex closing connection\r
 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
 250-myhost.test.ex Hello CALLER at test.ex\r
diff --git a/test/stdout/0557 b/test/stdout/0557
new file mode 100644 (file)
index 0000000..5077c0d
--- /dev/null
@@ -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