From 322050c2d9e83d10f046da71aa2cd9cc5a355b0b Mon Sep 17 00:00:00 2001 From: Philip Hazel Date: Mon, 9 Oct 2006 14:36:25 +0000 Subject: [PATCH] Arrange to call dns_init() for host_find_byname() as well as for host_find_bydns(). --- doc/doc-txt/ChangeLog | 16 +++++++++- src/src/expand.c | 5 ++-- src/src/functions.h | 4 +-- src/src/host.c | 44 ++++++++++++++++++++-------- src/src/route.c | 4 +-- src/src/routers/iplookup.c | 4 +-- src/src/routers/rf_lookup_hostlist.c | 8 +++-- src/src/smtp_in.c | 4 +-- src/src/transports/appendfile.c | 6 ++-- src/src/transports/smtp.c | 15 +++++----- src/src/verify.c | 28 +++++++----------- 11 files changed, 84 insertions(+), 54 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index e7d4a3f55..599c7877a 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -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 ----------------- diff --git a/src/src/expand.c b/src/src/expand.c index fc4d63aad..23e46200d 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -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); diff --git a/src/src/functions.h b/src/src/functions.h index 85b48ee37..302f8b6d1 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -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); diff --git a/src/src/host.c b/src/src/host.c index fdaab31e5..039f58fb2 100644 --- a/src/src/host.c +++ b/src/src/host.c @@ -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); diff --git a/src/src/route.c b/src/src/route.c index cc0d63cb0..f80256e3e 100644 --- a/src/src/route.c +++ b/src/src/route.c @@ -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) diff --git a/src/src/routers/iplookup.c b/src/src/routers/iplookup.c index 9dafd6fa5..069c0dda1 100644 --- a/src/src/routers/iplookup.c +++ b/src/src/routers/iplookup.c @@ -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; } diff --git a/src/src/routers/rf_lookup_hostlist.c b/src/src/routers/rf_lookup_hostlist.c index cea4c3d6f..987622547 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.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); } } } diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 36c4c3021..a87b65221 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -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; diff --git a/src/src/transports/appendfile.c b/src/src/transports/appendfile.c index 76acded26..1925888c8 100644 --- a/src/src/transports/appendfile.c +++ b/src/src/transports/appendfile.c @@ -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; diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 3d7c64e40..55f13d6a3 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.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. */ diff --git a/src/src/verify.c b/src/src/verify.c index 4d0fe69d2..4f0da9bbd 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -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; -- 2.25.1