From cd9868ec7872447f31efd5f175c7f3e90ac92657 Mon Sep 17 00:00:00 2001
From: Philip Hazel <ph10@hermes.cam.ac.uk>
Date: Wed, 14 Mar 2007 11:22:23 +0000
Subject: [PATCH 1/1] Fix manualroute bug for localhost following multihomed
 host.

---
 doc/doc-txt/ChangeLog                |  9 ++++++++-
 src/src/routers/rf_lookup_hostlist.c | 15 ++++++++++-----
 test/dnszones-src/db.test.ex         |  7 ++++++-
 test/scripts/0000-Basic/0430         |  2 ++
 test/stdout/0430                     |  4 ++++
 5 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 2ed229741..9140b63c7 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.494 2007/03/13 16:37:57 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.495 2007/03/14 11:22:23 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -168,6 +168,13 @@ PH/38 The host_find_failed option in the manualroute router can now be set
       found. If all hosts are ignored, the behaviour is controlled by the new
       host_all_ignored option.
 
+PH/39 In a list of hosts for manualroute, if one item (either because of multi-
+      homing or because of multiple MX records with /mx) generated more than
+      one IP address, and the following item turned out to be the local host,
+      all the secondary addresses of the first item were incorrectly removed
+      from the list, along with the local host and any following hosts (which
+      is what is supposed to happen).
+
 
 Exim version 4.66
 -----------------
diff --git a/src/src/routers/rf_lookup_hostlist.c b/src/src/routers/rf_lookup_hostlist.c
index a5beb49f4..68ff8c5b0 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.9 2007/03/13 15:32:48 ph10 Exp $ */
+/* $Cambridge: exim/src/src/routers/rf_lookup_hostlist.c,v 1.10 2007/03/14 11:22:23 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -64,13 +64,13 @@ list of MX hosts. If the first host is the local host, act according to the
 "self" option in the configuration. */
 
 prev = NULL;
-for (h = addr->host_list; h != NULL; prev = h, h = next_h)
+for (h = addr->host_list; h != NULL; h = next_h)
   {
   uschar *canonical_name;
   int rc, len, port;
 
   next_h = h->next;
-  if (h->address != NULL) continue;
+  if (h->address != NULL) { prev = h; continue; }
 
   DEBUG(D_route|D_host_lookup)
     debug_printf("finding IP address for %s\n", h->name);
@@ -160,8 +160,7 @@ for (h = addr->host_list; h != NULL; prev = h, h = next_h)
     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 */
+      continue;   /* With the next host, leave prev unchanged */
       }
 
     if (hff_code == hff_pass) return PASS;
@@ -213,6 +212,12 @@ for (h = addr->host_list; h != NULL; prev = h, h = next_h)
       }
     self_send = TRUE;
     }
+
+  /* Ensure that prev is the host before next_h; this will not be h if a lookup
+  found multiple addresses or multiple MX records. */
+
+  prev = h;
+  while (prev->next != next_h) prev = prev->next;
   }
 
 return OK;
diff --git a/test/dnszones-src/db.test.ex b/test/dnszones-src/db.test.ex
index b269d5856..d6122d4e3 100644
--- a/test/dnszones-src/db.test.ex
+++ b/test/dnszones-src/db.test.ex
@@ -1,4 +1,4 @@
-; $Cambridge: exim/test/dnszones-src/db.test.ex,v 1.5 2006/10/03 15:11:22 ph10 Exp $
+; $Cambridge: exim/test/dnszones-src/db.test.ex,v 1.6 2007/03/14 11:22:23 ph10 Exp $
 
 ; This is a testing zone file for use when testing DNS handling in Exim. This
 ; is a fake zone of no real use - hence no SOA record. The zone name is
@@ -312,6 +312,11 @@ mxt14        MX  4  ten-5-6.test.ex.
              MX  5  ten-5.test.ex.
              MX  6  ten-6.test.ex.
 
+; Non-local hosts with different precedence
+
+mxt15        MX 10  ten-1.test.ex.
+             MX 20  ten-2.test.ex.
+
 ; Large number of IP addresses at one MX value, and then some
 ; at another, to check that hosts_max_try tries the MX different
 ; values if it can.
diff --git a/test/scripts/0000-Basic/0430 b/test/scripts/0000-Basic/0430
index 2d338965d..e7a89d4a9 100644
--- a/test/scripts/0000-Basic/0430
+++ b/test/scripts/0000-Basic/0430
@@ -28,3 +28,5 @@ exim -DLIST=mxt11.test.ex/MX:ten-6.test.ex -bt x@random.manual.route
 ****
 exim -DLIST=mxt11a.test.ex/MX:ten-6.test.ex -bt x@random.manual.route
 ****
+exim -DLIST=mxt15.test.ex/MX:localhost.test.ex -bt x@manual.route
+****
diff --git a/test/stdout/0430 b/test/stdout/0430
index 0d6c72294..8281df8ef 100644
--- a/test/stdout/0430
+++ b/test/stdout/0430
@@ -55,3 +55,7 @@ x@random.manual.route
   router = r2, transport = t1
   host ten-6.test.ex [V4NET.0.0.6] 
   host ten-1.test.ex [V4NET.0.0.1] MX=6
+x@manual.route
+  router = r1, transport = t1
+  host ten-1.test.ex [V4NET.0.0.1] MX=10
+  host ten-2.test.ex [V4NET.0.0.2] MX=20
-- 
2.30.2