Arrange to call dns_init() for host_find_byname() as well as for
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Mon, 9 Oct 2006 14:36:25 +0000 (14:36 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Mon, 9 Oct 2006 14:36:25 +0000 (14:36 +0000)
host_find_bydns().

doc/doc-txt/ChangeLog
src/src/expand.c
src/src/functions.h
src/src/host.c
src/src/route.c
src/src/routers/iplookup.c
src/src/routers/rf_lookup_hostlist.c
src/src/smtp_in.c
src/src/transports/appendfile.c
src/src/transports/smtp.c
src/src/verify.c

index e7d4a3f55ac94b7d3bad4c4f9f5331cf664b9b7d..599c7877a57a31ff1454af0e75633687e7246010 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.403 2006/10/03 15:11:22 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.404 2006/10/09 14:36:25 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -95,6 +95,20 @@ PH/15 Applied Michael Deutschmann's patch to allow DNS black list processing to
       look up a TXT record in a specific list after matching in a combined
       list.
 
+PH/16 It seems that the options setting for the resolver (RES_DEFNAMES and
+      RES_DNSRCH) can affect the behaviour of gethostbyname() and friends when
+      they consult the DNS. I had assumed they would set it the way they
+      wanted; and indeed my experiments on Linux seem to show that in some
+      cases they do (I could influence IPv6 lookups but not IPv4 lookups).
+      To be on the safe side, however, I have now made the interface to
+      host_find_byname() similar to host_find_bydns(), with an argument
+      containing the DNS resolver options. The host_find_byname() function now
+      sets these options at its start, just as host_find_bydns() does. The smtp
+      transport options dns_qualify_single and dns_search_parents are passed to
+      host_find_byname() when gethostbyname=TRUE in this transport. Other uses
+      of host_find_byname() use the default settings of RES_DEFNAMES
+      (qualify_single) but not RES_DNSRCH (search_parents).
+
 
 Exim version 4.63
 -----------------
index fc4d63aad3bb26e9cf245f3a84d26cd6dc59b59d..23e46200d980c925be9ff8c852337542caaeda5c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/expand.c,v 1.63 2006/10/03 08:54:50 ph10 Exp $ */
+/* $Cambridge: exim/src/src/expand.c,v 1.64 2006/10/09 14:36:25 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -3748,7 +3748,8 @@ while (*s != 0)
           else
             {
             shost.name = server_name;
-            if (host_find_byname(&shost, NULL, NULL, FALSE) != HOST_FOUND)
+            if (host_find_byname(&shost, NULL, HOST_FIND_QUALIFY_SINGLE, NULL,
+                FALSE) != HOST_FOUND)
               {
               expand_string_message =
                 string_sprintf("no IP address found for host %s", shost.name);
index 85b48ee37d14a2434088b236e3c1eecb8c006d40..302f8b6d16f5ba38ec21f32bd99ecde702455698 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/functions.h,v 1.27 2006/09/19 11:28:45 ph10 Exp $ */
+/* $Cambridge: exim/src/src/functions.h,v 1.28 2006/10/09 14:36:25 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -116,7 +116,7 @@ extern void    host_build_hostlist(host_item **, uschar *, BOOL);
 extern ip_address_item *host_build_ifacelist(uschar *, uschar *);
 extern void    host_build_log_info(void);
 extern void    host_build_sender_fullhost(void);
-extern BOOL    host_find_byname(host_item *, uschar *, uschar **, BOOL);
+extern BOOL    host_find_byname(host_item *, uschar *, int, uschar **, BOOL);
 extern int     host_find_bydns(host_item *, uschar *, int, uschar *, uschar *,
                  uschar *,uschar **, BOOL *);
 extern ip_address_item *host_find_interfaces(void);
index fdaab31e5919220aee7ed81a0978f542ddf3fc99..039f58fb219576862ae7f7602d06c8bb4bdc70c5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/host.c,v 1.25 2006/09/05 14:05:43 ph10 Exp $ */
+/* $Cambridge: exim/src/src/host.c,v 1.26 2006/10/09 14:36:25 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1763,11 +1763,11 @@ for (hname = sender_host_name; hname != NULL; hname = *aliases++)
   h.mx = MX_NONE;
   h.address = NULL;
 
-  /* When called with the 5th argument FALSE, host_find_byname() won't return
+  /* When called with the last argument FALSE, host_find_byname() won't return
   HOST_FOUND_LOCAL. If the incoming address is an IPv4 address expressed in
   IPv6 format, we must compare the IPv4 part to any IPv4 addresses. */
 
-  if ((rc = host_find_byname(&h, NULL, NULL, FALSE)) == HOST_FOUND)
+  if ((rc = host_find_byname(&h, NULL, 0, NULL, FALSE)) == HOST_FOUND)
     {
     host_item *hh;
     HDEBUG(D_host_lookup) debug_printf("checking addresses for %s\n", hname);
@@ -1848,9 +1848,12 @@ return FAIL;
 *************************************************/
 
 /* The input is a host_item structure with the name filled in and the address
-field set to NULL. We use gethostbyname(). Of course, gethostbyname() may use
-the DNS, but it doesn't do MX processing. If more than one address is given,
-chain on additional host items, with other relevant fields copied.
+field set to NULL. We use gethostbyname() or getipnodebyname() or
+gethostbyname2(), as appropriate. Of course, these functions may use the DNS,
+but they do not do MX processing. It appears, however, that in some systems the
+current setting of resolver options is used when one of these functions calls
+the resolver. For this reason, we call dns_init() at the start, with arguments
+influenced by bits in "flags", just as we do for host_find_bydns().
 
 The second argument provides a host list (usually an IP list) of hosts to
 ignore. This makes it possible to ignore IPv6 link-local addresses or loopback
@@ -1867,6 +1870,8 @@ Arguments:
                            multiple IP addresses cause other host items to be
                              chained on.
   ignore_target_hosts    a list of hosts to ignore
+  flags                  HOST_FIND_QUALIFY_SINGLE   ) passed to
+                         HOST_FIND_SEARCH_PARENTS   )   dns_init()
   fully_qualified_name   if not NULL, set to point to host name for
                          compatibility with host_find_bydns
   local_host_check       TRUE if a check for the local host is wanted
@@ -1878,7 +1883,7 @@ Returns:                 HOST_FIND_FAILED  Failed to find the host or domain
 */
 
 int
-host_find_byname(host_item *host, uschar *ignore_target_hosts,
+host_find_byname(host_item *host, uschar *ignore_target_hosts, int flags,
   uschar **fully_qualified_name, BOOL local_host_check)
 {
 int i, yield, times;
@@ -1899,6 +1904,12 @@ if (running_in_test_harness)
   if (Ustrcmp(endname - 14, "test.again.dns") == 0) goto RETURN_AGAIN;
   }
 
+/* Make sure DNS options are set as required. This appears to be necessary in
+some circumstances when the get..byname() function actually calls the DNS. */
+
+dns_init((flags & HOST_FIND_QUALIFY_SINGLE) != 0,
+         (flags & HOST_FIND_SEARCH_PARENTS) != 0);
+
 /* In an IPv6 world, unless IPv6 has been disabled, we need to scan for both
 kinds of address, so go round the loop twice. Note that we have ensured that
 AF_INET6 is defined even in an IPv4 world, which makes for slightly tidier
@@ -1906,14 +1917,17 @@ code. However, if dns_ipv4_lookup matches the domain, we also just do IPv4
 lookups here (except when testing standalone). */
 
 #if HAVE_IPV6
-  #ifndef STAND_ALONE
-  if (disable_ipv6 || (dns_ipv4_lookup != NULL &&
+  #ifdef STAND_ALONE
+  if (disable_ipv6)
+  #else
+  if (disable_ipv6 ||
+    (dns_ipv4_lookup != NULL &&
         match_isinlist(host->name, &dns_ipv4_lookup, 0, NULL, NULL, MCL_DOMAIN,
           TRUE, NULL) == OK))
+  #endif
+
     { af = AF_INET; times = 1; }
   else
-  #endif  /* STAND_ALONE */
-
     { af = AF_INET6; times = 2; }
 
 /* No IPv6 support */
@@ -1939,6 +1953,10 @@ for (i = 1; i <= times;
   int error_num = 0;
   struct hostent *hostdata;
 
+  #ifdef STAND_ALONE
+  printf("Looking up: %s\n", host->name);
+  #endif
+
   #if HAVE_IPV6
   if (running_in_test_harness)
     hostdata = host_fake_gethostbyname(host->name, af, &error_num);
@@ -2976,6 +2994,7 @@ BOOL search_parents = FALSE;
 uschar **argv = USS cargv;
 uschar buffer[256];
 
+disable_ipv6 = FALSE;
 primary_hostname = US"";
 store_pool = POOL_MAIN;
 debug_selector = D_host_lookup|D_interface;
@@ -3023,6 +3042,7 @@ while (Ufgets(buffer, 256, stdin) != NULL)
   else if (Ustrcmp(buffer, "no_search_parents") == 0) search_parents = FALSE;
   else if (Ustrcmp(buffer, "test_harness") == 0)
     running_in_test_harness = !running_in_test_harness;
+  else if (Ustrcmp(buffer, "ipv6") == 0) disable_ipv6 = !disable_ipv6;
   else if (Ustrcmp(buffer, "res_debug") == 0)
     {
     _res.options ^= RES_DEBUG;
@@ -3053,7 +3073,7 @@ while (Ufgets(buffer, 256, stdin) != NULL)
     if (search_parents) flags |= HOST_FIND_SEARCH_PARENTS;
 
     rc = byname?
-      host_find_byname(&h, NULL, &fully_qualified_name, TRUE)
+      host_find_byname(&h, NULL, flags, &fully_qualified_name, TRUE)
       :
       host_find_bydns(&h, NULL, flags, US"smtp", NULL, NULL,
         &fully_qualified_name, NULL);
index cc0d63cb0281c4b10d1320401eac92e960adfd62..f80256e3e82f4128b06e973bcea1aafd3592ca1e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/route.c,v 1.10 2006/07/17 09:21:00 ph10 Exp $ */
+/* $Cambridge: exim/src/src/route.c,v 1.11 2006/10/09 14:36:25 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1884,7 +1884,7 @@ if (r->translate_ip_address != NULL)
     h->mx = MX_NONE;
 
     store_pool = POOL_PERM;
-    rc = host_find_byname(h, NULL, NULL, TRUE);
+    rc = host_find_byname(h, NULL, HOST_FIND_QUALIFY_SINGLE, NULL, TRUE);
     store_pool = old_pool;
 
     if (rc == HOST_FIND_FAILED || rc == HOST_FIND_AGAIN)
index 9dafd6fa536979afd02a90da23ec496b02638cc6..069c0dda1a333aa873d62e2968099cadc6602514 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/routers/iplookup.c,v 1.7 2006/04/04 09:09:45 ph10 Exp $ */
+/* $Cambridge: exim/src/src/routers/iplookup.c,v 1.8 2006/10/09 14:36:25 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -206,7 +206,7 @@ while ((hostname = string_nextinlist(&listptr, &sep, host_buffer,
     host->address = host->name;
   else
     {
-    int rc = host_find_byname(host, NULL, NULL, TRUE);
+    int rc = host_find_byname(host, NULL, HOST_FIND_QUALIFY_SINGLE, NULL, TRUE);
     if (rc == HOST_FIND_FAILED || rc == HOST_FIND_AGAIN) continue;
     }
 
index cea4c3d6f5929b43bac762358a47b097bca10d2f..9876225478d879217b13988c888ef68e331d1a56 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/routers/rf_lookup_hostlist.c,v 1.6 2006/02/07 11:19:02 ph10 Exp $ */
+/* $Cambridge: exim/src/src/routers/rf_lookup_hostlist.c,v 1.7 2006/10/09 14:36:25 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -106,7 +106,8 @@ for (h = addr->host_list; h != NULL; prev = h, h = next_h)
   else if (lookup_type == lk_byname || string_is_ip_address(h->name, NULL) != 0)
     {
     DEBUG(D_route|D_host_lookup) debug_printf("calling host_find_byname\n");
-    rc = host_find_byname(h, ignore_target_hosts, &canonical_name, TRUE);
+    rc = host_find_byname(h, ignore_target_hosts, HOST_FIND_QUALIFY_SINGLE,
+      &canonical_name, TRUE);
     }
 
   /* Otherwise, do a DNS lookup. If that yields "host not found", and the
@@ -129,7 +130,8 @@ for (h = addr->host_list; h != NULL; prev = h, h = next_h)
         {
         DEBUG(D_route|D_host_lookup)
           debug_printf("DNS lookup failed: trying getipnodebyname\n");
-        rc = host_find_byname(h, ignore_target_hosts, &canonical_name, TRUE);
+        rc = host_find_byname(h, ignore_target_hosts, HOST_FIND_QUALIFY_SINGLE,
+          &canonical_name, TRUE);
         }
       }
     }
index 36c4c3021d921a7f8540ab3ded2f898d45d8bada..a87b65221bf1b355035a34ec4eec18624089f48e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/smtp_in.c,v 1.44 2006/09/25 10:14:20 ph10 Exp $ */
+/* $Cambridge: exim/src/src/smtp_in.c,v 1.45 2006/10/09 14:36:25 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -2119,7 +2119,7 @@ else
     h.next = NULL;
     HDEBUG(D_receive) debug_printf("getting IP address for %s\n",
       sender_helo_name);
-    rc = host_find_byname(&h, NULL, NULL, TRUE);
+    rc = host_find_byname(&h, NULL, 0, NULL, TRUE);
     if (rc == HOST_FOUND || rc == HOST_FOUND_LOCAL)
       {
       host_item *hh = &h;
index 76acded26db3d801f285e6efd5922d4fa4016a89..1925888c8253c3050838fa5b897cbb8239ae12c1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.18 2006/04/27 08:53:24 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.19 2006/10/09 14:36:25 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -599,10 +599,10 @@ host.next = NULL;
 until one succeeds. However, it appears that at least on some systems, comsat
 doesn't listen on the ::1 address. So for the moment, just force the address to
 be 127.0.0.1. At some future stage, when IPv6 really is superseding IPv4, this
-can be changed. */
+can be changed. (But actually, comsat is probably dying out anyway.) */
 
 /******
-if (host_find_byname(&host, NULL, NULL, FALSE) == HOST_FIND_FAILED)
+if (host_find_byname(&host, NULL, 0, NULL, FALSE) == HOST_FIND_FAILED)
   {
   DEBUG(D_transport) debug_printf("\"localhost\" unknown\n");
   return;
index 3d7c64e40fa16c0c1944dddd3a47b4e41466f001..55f13d6a39903965f05199500e681a54852817c7 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/transports/smtp.c,v 1.26 2006/09/25 11:25:37 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/smtp.c,v 1.27 2006/10/09 14:36:25 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -2311,7 +2311,7 @@ for (cutoff_retry = 0; expired &&
 
     if (host->address == NULL)
       {
-      int new_port;
+      int new_port, flags;
       host_item *hh;
       uschar *canonical_name;
 
@@ -2336,16 +2336,15 @@ for (cutoff_retry = 0; expired &&
       /* Find by name if so configured, or if it's an IP address. We don't
       just copy the IP address, because we need the test-for-local to happen. */
 
+      flags = HOST_FIND_BY_A;
+      if (ob->dns_qualify_single) flags |= HOST_FIND_QUALIFY_SINGLE;
+      if (ob->dns_search_parents) flags |= HOST_FIND_SEARCH_PARENTS;
+
       if (ob->gethostbyname || string_is_ip_address(host->name, NULL) != 0)
-        rc = host_find_byname(host, NULL, &canonical_name, TRUE);
+        rc = host_find_byname(host, NULL, flags, &canonical_name, TRUE);
       else
-        {
-        int flags = HOST_FIND_BY_A;
-        if (ob->dns_qualify_single) flags |= HOST_FIND_QUALIFY_SINGLE;
-        if (ob->dns_search_parents) flags |= HOST_FIND_SEARCH_PARENTS;
         rc = host_find_bydns(host, NULL, flags, NULL, NULL, NULL,
           &canonical_name, NULL);
-        }
 
       /* Update the host (and any additional blocks, resulting from
       multihoming) with a host-specific port, if any. */
index 4d0fe69d2f2a526bc03485ac37e663ee2ebd3f7c..4f0da9bbdf65c1792ba72ad5e829560d63e601db 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/verify.c,v 1.41 2006/10/03 15:11:22 ph10 Exp $ */
+/* $Cambridge: exim/src/src/verify.c,v 1.42 2006/10/09 14:36:25 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1009,17 +1009,11 @@ information about the top level address, not anything that it generated. */
 while (addr_new != NULL)
   {
   int rc;
-  uschar *show_address;
   address_item *addr = addr_new;
 
   addr_new = addr->next;
   addr->next = NULL;
 
-  /* When full_info is set, child addresses are displayed in top-level
-  messages. Otherwise, we show only the top level address. */
-
-  show_address = full_info? addr->address : address;
-
   DEBUG(D_verify)
     {
     debug_printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
@@ -1141,6 +1135,7 @@ while (addr_new != NULL)
             }
           else
             {
+            int flags;
             uschar *canonical_name;
             host_item *host, *nexthost;
             host_build_hostlist(&host_list, s, tf.hosts_randomize);
@@ -1151,20 +1146,19 @@ while (addr_new != NULL)
             additional host items being inserted into the chain. Hence we must
             save the next host first. */
 
+            flags = HOST_FIND_BY_A;
+            if (tf.qualify_single) flags |= HOST_FIND_QUALIFY_SINGLE;
+            if (tf.search_parents) flags |= HOST_FIND_SEARCH_PARENTS;
+
             for (host = host_list; host != NULL; host = nexthost)
               {
               nexthost = host->next;
               if (tf.gethostbyname ||
                   string_is_ip_address(host->name, NULL) != 0)
-                (void)host_find_byname(host, NULL, &canonical_name, TRUE);
+                (void)host_find_byname(host, NULL, flags, &canonical_name, TRUE);
               else
-                {
-                int flags = HOST_FIND_BY_A;
-                if (tf.qualify_single) flags |= HOST_FIND_QUALIFY_SINGLE;
-                if (tf.search_parents) flags |= HOST_FIND_SEARCH_PARENTS;
                 (void)host_find_bydns(host, NULL, flags, NULL, NULL, NULL,
                   &canonical_name, NULL);
-                }
               }
             }
           }
@@ -1215,7 +1209,7 @@ while (addr_new != NULL)
       {
       address_item *p = addr->parent;
 
-      fprintf(f, "%s%s %s", ko_prefix, show_address,
+      fprintf(f, "%s%s %s", ko_prefix, full_info? addr->address : address,
         address_test_mode? "is undeliverable" : "failed to verify");
       if (!expn && admin_user)
         {
@@ -1248,7 +1242,7 @@ while (addr_new != NULL)
       {
       address_item *p = addr->parent;
       fprintf(f, "%s%s cannot be resolved at this time", ko_prefix,
-        show_address);
+        full_info? addr->address : address);
       if (!expn && admin_user)
         {
         if (addr->basic_errno > 0)
@@ -1321,7 +1315,7 @@ while (addr_new != NULL)
          (addr_new != NULL &&            /* At least one new address AND */
           success_on_redirect)))         /* success_on_redirect is set */
       {
-      if (f != NULL) fprintf(f, "%s %s\n", show_address,
+      if (f != NULL) fprintf(f, "%s %s\n", address,
         address_test_mode? "is deliverable" : "verified");
 
       /* If we have carried on to verify a child address, we want the value
@@ -2223,7 +2217,7 @@ if (*t == 0)
   h.address = NULL;
   h.mx = MX_NONE;
 
-  rc = host_find_byname(&h, NULL, NULL, FALSE);
+  rc = host_find_byname(&h, NULL, HOST_FIND_QUALIFY_SINGLE, NULL, FALSE);
   if (rc == HOST_FOUND || rc == HOST_FOUND_LOCAL)
     {
     host_item *hh;