return (unsigned int)(random_seed >> 16) % limit;
}
+/*************************************************
+* Wrappers for logging lookup times *
+*************************************************/
+
+/* When the 'slow_lookup_log' variable is enabled, these wrappers will
+write to the log file all (potential) dns lookups that take more than
+slow_lookup_log milliseconds
+*/
+
+static void
+log_long_lookup(const uschar * type, const uschar * data, unsigned long msec)
+{
+log_write(0, LOG_MAIN, "Long %s lookup for '%s': %lu msec",
+ type, data, msec);
+}
+
+
+/* returns the current system epoch time in milliseconds. */
+static unsigned long
+get_time_in_ms()
+{
+struct timeval tmp_time;
+unsigned long seconds, microseconds;
+
+gettimeofday(&tmp_time, NULL);
+seconds = (unsigned long) tmp_time.tv_sec;
+microseconds = (unsigned long) tmp_time.tv_usec;
+return seconds*1000 + microseconds/1000;
+}
+
+
+static int
+dns_lookup_timerwrap(dns_answer *dnsa, const uschar *name, int type,
+ const uschar **fully_qualified_name)
+{
+int retval;
+unsigned long time_msec;
+
+if (!slow_lookup_log)
+ return dns_lookup(dnsa, name, type, fully_qualified_name);
+
+time_msec = get_time_in_ms();
+retval = dns_lookup(dnsa, name, type, fully_qualified_name);
+if ((time_msec = get_time_in_ms() - time_msec) > slow_lookup_log)
+ log_long_lookup(US"name", name, time_msec);
+return retval;
+}
/*************************************************
*/
static struct hostent *
-host_fake_gethostbyname(uschar *name, int af, int *error_num)
+host_fake_gethostbyname(const uschar *name, int af, int *error_num)
{
#if HAVE_IPV6
int alen = (af == AF_INET)? sizeof(struct in_addr):sizeof(struct in6_addr);
#endif
int ipa;
-uschar *lname = name;
+const uschar *lname = name;
uschar *adds;
uschar **alist;
struct hostent *yield;
else
{
int type = (af == AF_INET)? T_A:T_AAAA;
- int rc = dns_lookup(&dnsa, lname, type, NULL);
+ int rc = dns_lookup_timerwrap(&dnsa, lname, type, NULL);
int count = 0;
+ lookup_dnssec_authenticated = NULL;
+
switch(rc)
{
case DNS_SUCCEED: break;
*/
void
-host_build_hostlist(host_item **anchor, uschar *list, BOOL randomize)
+host_build_hostlist(host_item **anchor, const uschar *list, BOOL randomize)
{
int sep = 0;
int fake_mx = MX_NONE; /* This value is actually -1 */
uschar *name;
-uschar buffer[1024];
if (list == NULL) return;
if (randomize) fake_mx--; /* Start at -2 for randomizing */
*anchor = NULL;
-while ((name = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
+while ((name = string_nextinlist(&list, &sep, NULL, 0)) != NULL)
{
host_item *h;
}
h = store_get(sizeof(host_item));
- h->name = string_copy(name);
+ h->name = name;
h->address = NULL;
h->port = PORT_NONE;
h->mx = fake_mx;
int
host_item_get_port(host_item *h)
{
-uschar *p;
+const uschar *p;
int port, x;
int len = Ustrlen(h->name);
*/
ip_address_item *
-host_build_ifacelist(uschar *list, uschar *name)
+host_build_ifacelist(const uschar *list, uschar *name)
{
int sep = 0;
uschar *s;
if (local_interface_data == NULL)
{
void *reset_item = store_get(0);
- ip_address_item *dlist = host_build_ifacelist(local_interfaces,
+ ip_address_item *dlist = host_build_ifacelist(CUS local_interfaces,
US"local_interfaces");
- ip_address_item *xlist = host_build_ifacelist(extra_local_interfaces,
+ ip_address_item *xlist = host_build_ifacelist(CUS extra_local_interfaces,
US"extra_local_interfaces");
ip_address_item *ipa;
*/
int
-host_aton(uschar *address, int *bin)
+host_aton(const uschar *address, int *bin)
{
int x[4];
int v4offset = 0;
if (Ustrchr(address, ':') != NULL)
{
- uschar *p = address;
- uschar *component[8];
+ const uschar *p = address;
+ const uschar *component[8];
BOOL ipv4_ends = FALSE;
int ci = 0;
int nulloffset = 0;
{
int sep = 0;
uschar buffer[32];
-uschar *list = tls_on_connect_ports;
+const uschar *list = tls_in.on_connect_ports;
uschar *s;
+uschar *end;
-if (tls_on_connect) return TRUE;
+if (tls_in.on_connect) return TRUE;
-while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
- {
- uschar *end;
- int lport = Ustrtol(s, &end, 10);
- if (*end != 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "tls_on_connect_ports "
- "contains \"%s\", which is not a port number: exim abandoned", s);
- if (lport == port) return TRUE;
- }
+while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer))))
+ if (Ustrtol(s, &end, 10) == port)
+ return TRUE;
return FALSE;
}
*/
BOOL
-host_is_in_net(uschar *host, uschar *net, int maskoffset)
+host_is_in_net(const uschar *host, const uschar *net, int maskoffset)
{
int i;
int address[4];
if (hosts_treat_as_local != NULL)
{
int rc;
- uschar *save = deliver_domain;
+ const uschar *save = deliver_domain;
deliver_domain = h->name; /* set $domain */
- rc = match_isinlist(string_copylc(h->name), &hosts_treat_as_local, 0,
+ rc = match_isinlist(string_copylc(h->name), CUSS &hosts_treat_as_local, 0,
&domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL);
deliver_domain = save;
if (rc == OK) goto FOUND_LOCAL;
uschar *s, *t;
struct hostent *hosts;
struct in_addr addr;
+unsigned long time_msec;
+
+if (slow_lookup_log) time_msec = get_time_in_ms();
/* Lookup on IPv6 system */
hosts = gethostbyaddr(CS(&addr), sizeof(addr), AF_INET);
#endif
+if ( slow_lookup_log
+ && (time_msec = get_time_in_ms() - time_msec) > slow_lookup_log
+ )
+ log_long_lookup(US"name", sender_host_address, time_msec);
+
/* Failed to look up the host. */
if (hosts == NULL)
uschar **aliases;
uschar buffer[256];
uschar *ordername;
-uschar *list = host_lookup_order;
+const uschar *list = host_lookup_order;
dns_record *rr;
dns_answer dnsa;
dns_scan dnss;
-host_lookup_deferred = host_lookup_failed = FALSE;
+sender_host_dnssec = host_lookup_deferred = host_lookup_failed = FALSE;
HDEBUG(D_host_lookup)
debug_printf("looking up host name for %s\n", sender_host_address);
{
if (strcmpic(ordername, US"bydns") == 0)
{
- dns_init(FALSE, FALSE);
+ dns_init(FALSE, FALSE, FALSE); /* dnssec ctrl by dns_dnssec_ok glbl */
dns_build_reverse(sender_host_address, buffer);
- rc = dns_lookup(&dnsa, buffer, T_PTR, NULL);
+ rc = dns_lookup_timerwrap(&dnsa, buffer, T_PTR, NULL);
/* The first record we come across is used for the name; others are
considered to be aliases. We have to scan twice, in order to find out the
int count = 0;
int old_pool = store_pool;
+ /* Ideally we'd check DNSSEC both forward and reverse, but we use the
+ gethost* routines for forward, so can't do that unless/until we rewrite. */
+ sender_host_dnssec = dns_is_secure(&dnsa);
+ DEBUG(D_dns)
+ debug_printf("Reverse DNS security status: %s\n",
+ sender_host_dnssec ? "DNSSEC verified (AD)" : "unverified");
+
store_pool = POOL_PERM; /* Save names in permanent storage */
for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
HDEBUG(D_host_lookup)
{
uschar **aliases = sender_host_aliases;
- debug_printf("IP address lookup yielded %s\n", sender_host_name);
- while (*aliases != NULL) debug_printf(" alias %s\n", *aliases++);
+ debug_printf("IP address lookup yielded \"%s\"\n", sender_host_name);
+ while (*aliases != NULL) debug_printf(" alias \"%s\"\n", *aliases++);
}
/* We need to verify that a forward lookup on the name we found does indeed
*/
int
-host_find_byname(host_item *host, uschar *ignore_target_hosts, int flags,
- uschar **fully_qualified_name, BOOL local_host_check)
+host_find_byname(host_item *host, const uschar *ignore_target_hosts, int flags,
+ const uschar **fully_qualified_name, BOOL local_host_check)
{
int i, yield, times;
uschar **addrlist;
if (running_in_test_harness)
{
- uschar *endname = host->name + Ustrlen(host->name);
+ const uschar *endname = host->name + Ustrlen(host->name);
if (Ustrcmp(endname - 14, "test.again.dns") == 0) goto RETURN_AGAIN;
}
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);
+ (flags & HOST_FIND_SEARCH_PARENTS) != 0,
+ FALSE); /*XXX dnssec? */
/* 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
#else
if (disable_ipv6 ||
(dns_ipv4_lookup != NULL &&
- match_isinlist(host->name, &dns_ipv4_lookup, 0, NULL, NULL, MCL_DOMAIN,
- TRUE, NULL) == OK))
+ match_isinlist(host->name, CUSS &dns_ipv4_lookup, 0, NULL, NULL,
+ MCL_DOMAIN, TRUE, NULL) == OK))
#endif
{ af = AF_INET; times = 1; }
BOOL ipv4_addr;
int error_num = 0;
struct hostent *hostdata;
+ unsigned long time_msec;
#ifdef STAND_ALONE
printf("Looking up: %s\n", host->name);
#endif
+ if (slow_lookup_log) time_msec = get_time_in_ms();
+
#if HAVE_IPV6
if (running_in_test_harness)
hostdata = host_fake_gethostbyname(host->name, af, &error_num);
}
#endif /* HAVE_IPV6 */
+ if ( slow_lookup_log
+ && (time_msec = get_time_in_ms() - time_msec) > slow_lookup_log
+ )
+ log_long_lookup(US"name", host->name, time_msec);
+
if (hostdata == NULL)
{
uschar *error;
switch (error_num)
{
case HOST_NOT_FOUND: error = US"HOST_NOT_FOUND"; break;
- case TRY_AGAIN: error = US"TRY_AGAIN"; break;
- case NO_RECOVERY: error = US"NO_RECOVERY"; break;
- case NO_DATA: error = US"NO_DATA"; break;
+ case TRY_AGAIN: error = US"TRY_AGAIN"; break;
+ case NO_RECOVERY: error = US"NO_RECOVERY"; break;
+ case NO_DATA: error = US"NO_DATA"; break;
#if NO_DATA != NO_ADDRESS
- case NO_ADDRESS: error = US"NO_ADDRESS"; break;
+ case NO_ADDRESS: error = US"NO_ADDRESS"; break;
#endif
default: error = US"?"; break;
}
host->port = PORT_NONE;
host->status = hstatus_unknown;
host->why = hwhy_unknown;
+ host->dnssec = DS_UNK;
last = host;
}
next->port = PORT_NONE;
next->status = hstatus_unknown;
next->why = hwhy_unknown;
+ next->dnssec = DS_UNK;
next->last_try = 0;
next->next = last->next;
last->next = next;
HDEBUG(D_host_lookup)
{
- host_item *h;
+ const host_item *h;
if (fully_qualified_name != NULL)
debug_printf("fully qualified name = %s\n", *fully_qualified_name);
debug_printf("%s looked up these IP addresses:\n",
{
#ifndef STAND_ALONE
int rc;
- uschar *save = deliver_domain;
+ const uschar *save = deliver_domain;
deliver_domain = host->name; /* set $domain */
- rc = match_isinlist(host->name, &dns_again_means_nonexist, 0, NULL, NULL,
+ rc = match_isinlist(host->name, CUSS &dns_again_means_nonexist, 0, NULL, NULL,
MCL_DOMAIN, TRUE, NULL);
deliver_domain = save;
if (rc == OK)
fully_qualified_name if not NULL, return fully qualified name here if
the contents are different (i.e. it must be preset
to something)
+ dnnssec_require if TRUE check the DNS result AD bit
Returns: HOST_FIND_FAILED couldn't find A record
HOST_FIND_AGAIN try again later
static int
set_address_from_dns(host_item *host, host_item **lastptr,
- uschar *ignore_target_hosts, BOOL allow_ip, uschar **fully_qualified_name)
+ const uschar *ignore_target_hosts, BOOL allow_ip,
+ const uschar **fully_qualified_name,
+ BOOL dnssec_request, BOOL dnssec_require)
{
dns_record *rr;
host_item *thishostlast = NULL; /* Indicates not yet filled in anything */
#if HAVE_IPV6
#ifndef STAND_ALONE
if (disable_ipv6 || (dns_ipv4_lookup != NULL &&
- match_isinlist(host->name, &dns_ipv4_lookup, 0, NULL, NULL, MCL_DOMAIN,
- TRUE, NULL) == OK))
+ match_isinlist(host->name, CUSS &dns_ipv4_lookup, 0, NULL, NULL,
+ MCL_DOMAIN, TRUE, NULL) == OK))
i = 0; /* look up A records only */
else
#endif /* STAND_ALONE */
- #ifdef SUPPORT_A6
- i = 2; /* look up A6 and AAAA and A records */
- #else
i = 1; /* look up AAAA and A records */
- #endif /* SUPPORT_A6 */
/* The IPv4 world */
dns_answer dnsa;
dns_scan dnss;
- int rc = dns_lookup(&dnsa, host->name, type, fully_qualified_name);
+ int rc = dns_lookup_timerwrap(&dnsa, host->name, type, fully_qualified_name);
+ lookup_dnssec_authenticated = !dnssec_request ? NULL
+ : dns_is_secure(&dnsa) ? US"yes" : US"no";
/* We want to return HOST_FIND_AGAIN if one of the A, A6, or AAAA lookups
fails or times out, but not if another one succeeds. (In the early
continue;
}
+ if (dnssec_request)
+ {
+ if (dns_is_secure(&dnsa))
+ {
+ DEBUG(D_host_lookup) debug_printf("%s A DNSSEC\n", host->name);
+ if (host->dnssec == DS_UNK) /* set in host_find_bydns() */
+ host->dnssec = DS_YES;
+ }
+ else
+ {
+ if (dnssec_require)
+ {
+ log_write(L_host_lookup_failed, LOG_MAIN,
+ "dnssec fail on %s for %.256s",
+ i>1 ? "A6" : i>0 ? "AAAA" : "A", host->name);
+ continue;
+ }
+ if (host->dnssec == DS_YES) /* set in host_find_bydns() */
+ {
+ DEBUG(D_host_lookup) debug_printf("%s A cancel DNSSEC\n", host->name);
+ host->dnssec = DS_NO;
+ lookup_dnssec_authenticated = US"no";
+ }
+ }
+ }
+
/* Lookup succeeded: fill in the given host item with the first non-ignored
address found; create additional items for any others. A single A6 record
- may generate more than one address. */
+ may generate more than one address. The lookup had a chance to update the
+ fqdn; we do not want any later times round the loop to do so. */
+
+ fully_qualified_name = NULL;
for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
rr != NULL;
srv_service when SRV used, the service name
srv_fail_domains DNS errors for these domains => assume nonexist
mx_fail_domains DNS errors for these domains => assume nonexist
+ dnssec_request_domains => make dnssec request
+ dnssec_require_domains => ditto and nonexist failures
fully_qualified_name if not NULL, return fully-qualified name
removed set TRUE if local host was removed from the list
*/
int
-host_find_bydns(host_item *host, uschar *ignore_target_hosts, int whichrrs,
+host_find_bydns(host_item *host, const uschar *ignore_target_hosts, int whichrrs,
uschar *srv_service, uschar *srv_fail_domains, uschar *mx_fail_domains,
- uschar **fully_qualified_name, BOOL *removed)
+ uschar *dnssec_request_domains, uschar *dnssec_require_domains,
+ const uschar **fully_qualified_name, BOOL *removed)
{
host_item *h, *last;
dns_record *rr;
int yield;
dns_answer dnsa;
dns_scan dnss;
+BOOL dnssec_require = match_isinlist(host->name, CUSS &dnssec_require_domains,
+ 0, NULL, NULL, MCL_DOMAIN, TRUE, NULL) == OK;
+BOOL dnssec_request = dnssec_require
+ || match_isinlist(host->name, CUSS &dnssec_request_domains,
+ 0, NULL, NULL, MCL_DOMAIN, TRUE, NULL) == OK;
+dnssec_status_t dnssec;
/* Set the default fully qualified name to the incoming name, initialize the
resolver if necessary, set up the relevant options, and initialize the flag
if (fully_qualified_name != NULL) *fully_qualified_name = host->name;
dns_init((whichrrs & HOST_FIND_QUALIFY_SINGLE) != 0,
- (whichrrs & HOST_FIND_SEARCH_PARENTS) != 0);
+ (whichrrs & HOST_FIND_SEARCH_PARENTS) != 0,
+ dnssec_request
+ );
host_find_failed_syntax = FALSE;
/* First, if requested, look for SRV records. The service name is given; we
the input name, pass back the new original domain, without the prepended
magic. */
- rc = dns_lookup(&dnsa, buffer, ind_type, &temp_fully_qualified_name);
+ dnssec = DS_UNK;
+ lookup_dnssec_authenticated = NULL;
+ rc = dns_lookup_timerwrap(&dnsa, buffer, ind_type, CUSS &temp_fully_qualified_name);
+
+ if (dnssec_request)
+ {
+ if (dns_is_secure(&dnsa))
+ { dnssec = DS_YES; lookup_dnssec_authenticated = US"yes"; }
+ else
+ { dnssec = DS_NO; lookup_dnssec_authenticated = US"no"; }
+ }
+
if (temp_fully_qualified_name != buffer && fully_qualified_name != NULL)
*fully_qualified_name = temp_fully_qualified_name + prefix_length;
/* On DNS failures, we give the "try again" error unless the domain is
listed as one for which we continue. */
+ if (rc == DNS_SUCCEED && dnssec_require && !dns_is_secure(&dnsa))
+ {
+ log_write(L_host_lookup_failed, LOG_MAIN,
+ "dnssec fail on SRV for %.256s", host->name);
+ rc = DNS_FAIL;
+ }
if (rc == DNS_FAIL || rc == DNS_AGAIN)
{
#ifndef STAND_ALONE
- if (match_isinlist(host->name, &srv_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
- TRUE, NULL) != OK)
+ if (match_isinlist(host->name, CUSS &srv_fail_domains, 0, NULL, NULL,
+ MCL_DOMAIN, TRUE, NULL) != OK)
#endif
- return HOST_FIND_AGAIN;
+ { yield = HOST_FIND_AGAIN; goto out; }
DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
"(domain in srv_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
}
if (rc != DNS_SUCCEED && (whichrrs & HOST_FIND_BY_MX) != 0)
{
ind_type = T_MX;
- rc = dns_lookup(&dnsa, host->name, ind_type, fully_qualified_name);
- if (rc == DNS_NOMATCH) return HOST_FIND_FAILED;
- if (rc == DNS_FAIL || rc == DNS_AGAIN)
+ dnssec = DS_UNK;
+ lookup_dnssec_authenticated = NULL;
+ rc = dns_lookup_timerwrap(&dnsa, host->name, ind_type, fully_qualified_name);
+
+ if (dnssec_request)
{
- #ifndef STAND_ALONE
- if (match_isinlist(host->name, &mx_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
- TRUE, NULL) != OK)
- #endif
- return HOST_FIND_AGAIN;
- DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
- "(domain in mx_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
+ if (dns_is_secure(&dnsa))
+ {
+ DEBUG(D_host_lookup) debug_printf("%s MX DNSSEC\n", host->name);
+ dnssec = DS_YES; lookup_dnssec_authenticated = US"yes";
+ }
+ else
+ {
+ dnssec = DS_NO; lookup_dnssec_authenticated = US"no";
+ }
+ }
+
+ switch (rc)
+ {
+ case DNS_NOMATCH:
+ yield = HOST_FIND_FAILED; goto out;
+
+ case DNS_SUCCEED:
+ if (!dnssec_require || dns_is_secure(&dnsa))
+ break;
+ log_write(L_host_lookup_failed, LOG_MAIN,
+ "dnssec fail on MX for %.256s", host->name);
+ rc = DNS_FAIL;
+ /*FALLTHROUGH*/
+
+ case DNS_FAIL:
+ case DNS_AGAIN:
+ #ifndef STAND_ALONE
+ if (match_isinlist(host->name, CUSS &mx_fail_domains, 0, NULL, NULL,
+ MCL_DOMAIN, TRUE, NULL) != OK)
+ #endif
+ { yield = HOST_FIND_AGAIN; goto out; }
+ DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
+ "(domain in mx_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
+ break;
}
}
if ((whichrrs & HOST_FIND_BY_A) == 0)
{
DEBUG(D_host_lookup) debug_printf("Address records are not being sought\n");
- return HOST_FIND_FAILED;
+ yield = HOST_FIND_FAILED;
+ goto out;
}
last = host; /* End of local chainlet */
host->mx = MX_NONE;
host->port = PORT_NONE;
+ host->dnssec = DS_UNK;
+ lookup_dnssec_authenticated = NULL;
rc = set_address_from_dns(host, &last, ignore_target_hosts, FALSE,
- fully_qualified_name);
+ fully_qualified_name, dnssec_request, dnssec_require);
/* If one or more address records have been found, check that none of them
are local. Since we know the host items all have their IP addresses
}
}
- return rc;
+ yield = rc;
+ goto out;
}
/* We have found one or more MX or SRV records. Sort them according to
the same precedence to sort randomly. */
if (ind_type == T_MX)
- {
weight = random_number(500);
- }
/* SRV records are specified with a port and a weight. The weight is used
in a special algorithm. However, to start with, we just use it to order the
host->sort_key = precedence * 1000 + weight;
host->status = hstatus_unknown;
host->why = hwhy_unknown;
+ host->dnssec = dnssec;
last = host;
}
next->sort_key = sort_key;
next->status = hstatus_unknown;
next->why = hwhy_unknown;
+ next->dnssec = dnssec;
next->last_try = 0;
/* Handle the case when we have to insert before the first item. */
if (host == last && host->name[0] == 0)
{
DEBUG(D_host_lookup) debug_printf("the single SRV record is \".\"\n");
- return HOST_FIND_FAILED;
+ yield = HOST_FIND_FAILED;
+ goto out;
}
DEBUG(D_host_lookup)
if they happen to match something local. */
yield = HOST_FIND_FAILED; /* Default yield */
-dns_init(FALSE, FALSE); /* Disable qualify_single and search_parents */
+dns_init(FALSE, FALSE, /* Disable qualify_single and search_parents */
+ dnssec_request || dnssec_require);
for (h = host; h != last->next; h = h->next)
{
if (h->address != NULL) continue; /* Inserted by a multihomed host */
- rc = set_address_from_dns(h, &last, ignore_target_hosts, allow_mx_to_ip, NULL);
+ rc = set_address_from_dns(h, &last, ignore_target_hosts, allow_mx_to_ip,
+ NULL, dnssec_request, dnssec_require);
if (rc != HOST_FOUND)
{
h->status = hstatus_unusable;
yield);
for (h = host; h != last->next; h = h->next)
{
- debug_printf(" %s %s MX=%d ", h->name,
- (h->address == NULL)? US"<null>" : h->address, h->mx);
+ debug_printf(" %s %s MX=%d %s", h->name,
+ !h->address ? US"<null>" : h->address, h->mx,
+ h->dnssec == DS_YES ? US"DNSSEC " : US"");
if (h->port != PORT_NONE) debug_printf("port=%d ", h->port);
if (h->status >= hstatus_unusable) debug_printf("*");
debug_printf("\n");
}
}
+out:
+
+dns_init(FALSE, FALSE, FALSE); /* clear the dnssec bit for getaddrbyname */
return yield;
}
-
-
-
/*************************************************
**************************************************
* Stand-alone test program *
BOOL byname = FALSE;
BOOL qualify_single = TRUE;
BOOL search_parents = FALSE;
+BOOL request_dnssec = FALSE;
+BOOL require_dnssec = FALSE;
uschar **argv = USS cargv;
uschar buffer[256];
/* So that debug level changes can be done first */
-dns_init(qualify_single, search_parents);
+dns_init(qualify_single, search_parents, FALSE);
printf("Testing host lookup\n");
printf("> ");
whichrrs = HOST_FIND_BY_SRV | HOST_FIND_BY_MX;
else if (Ustrcmp(buffer, "srv+mx+a") == 0)
whichrrs = HOST_FIND_BY_SRV | HOST_FIND_BY_MX | HOST_FIND_BY_A;
- else if (Ustrcmp(buffer, "qualify_single") == 0) qualify_single = TRUE;
+ else if (Ustrcmp(buffer, "qualify_single") == 0) qualify_single = TRUE;
else if (Ustrcmp(buffer, "no_qualify_single") == 0) qualify_single = FALSE;
- else if (Ustrcmp(buffer, "search_parents") == 0) search_parents = TRUE;
+ else if (Ustrcmp(buffer, "search_parents") == 0) search_parents = TRUE;
else if (Ustrcmp(buffer, "no_search_parents") == 0) search_parents = FALSE;
+ else if (Ustrcmp(buffer, "request_dnssec") == 0) request_dnssec = TRUE;
+ else if (Ustrcmp(buffer, "no_request_dnssec") == 0) request_dnssec = FALSE;
+ else if (Ustrcmp(buffer, "require_dnssec") == 0) require_dnssec = TRUE;
+ else if (Ustrcmp(buffer, "no_reqiret_dnssec") == 0) require_dnssec = 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;
if (qualify_single) flags |= HOST_FIND_QUALIFY_SINGLE;
if (search_parents) flags |= HOST_FIND_SEARCH_PARENTS;
- rc = byname?
- host_find_byname(&h, NULL, flags, &fully_qualified_name, TRUE)
- :
- host_find_bydns(&h, NULL, flags, US"smtp", NULL, NULL,
- &fully_qualified_name, NULL);
+ rc = byname
+ ? host_find_byname(&h, NULL, flags, &fully_qualified_name, TRUE)
+ : host_find_bydns(&h, NULL, flags, US"smtp", NULL, NULL,
+ request_dnssec ? &h.name : NULL,
+ require_dnssec ? &h.name : NULL,
+ &fully_qualified_name, NULL);
if (rc == HOST_FIND_FAILED) printf("Failed\n");
else if (rc == HOST_FIND_AGAIN) printf("Again\n");
}
#endif /* STAND_ALONE */
+/* vi: aw ai sw=2
+*/
/* End of host.c */