summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/doc-txt/ChangeLog5
-rw-r--r--src/OS/os.h-NetBSD4
-rw-r--r--src/src/dns.c30
-rw-r--r--src/src/exim.h11
-rw-r--r--src/src/exim_lock.c4
-rw-r--r--src/src/os.c44
6 files changed, 87 insertions, 11 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 80e8edf97..ed226b756 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -81,6 +81,11 @@ PP/17 OpenSSL: new expansion var $tls_sni, which if used in tls_certificate
PP/18 Bugzilla 1122 - check localhost_number expansion for failure, avoid
NULL dereference. Report and patch from Alun Jones.
+PP/19 DNS resolver init changes for NetBSD compatibility. (Risk of breakage
+ on less well tested platforms). Obviates NetBSD pkgsrc patch-ac.
+ Not seeing resolver debug output on NetBSD, but suspect this is a
+ resolver implementation change.
+
Exim version 4.77
-----------------
diff --git a/src/OS/os.h-NetBSD b/src/OS/os.h-NetBSD
index 0f3a3d8fc..19a8ac0c7 100644
--- a/src/OS/os.h-NetBSD
+++ b/src/OS/os.h-NetBSD
@@ -12,6 +12,10 @@ typedef struct flock flock_t;
#define os_strsignal strsignal
#define OS_STRSIGNAL
+#define os_get_dns_resolver_res __res_get_state
+#define os_put_dns_resolver_res(RP) __res_put_state(RP)
+#define OS_GET_DNS_RESOLVER_RES
+
#include <sys/param.h>
#if __NetBSD_Version__ >= 299000900
diff --git a/src/src/dns.c b/src/src/dns.c
index f5e8ab738..c903d0ba9 100644
--- a/src/src/dns.c
+++ b/src/src/dns.c
@@ -166,26 +166,30 @@ Returns: nothing
void
dns_init(BOOL qualify_single, BOOL search_parents)
{
-if ((_res.options & RES_INIT) == 0)
+res_state resp = os_get_dns_resolver_res();
+
+if ((resp->options & RES_INIT) == 0)
{
- DEBUG(D_resolver) _res.options |= RES_DEBUG; /* For Cygwin */
+ DEBUG(D_resolver) resp->options |= RES_DEBUG; /* For Cygwin */
+ os_put_dns_resolver_res(resp);
res_init();
- DEBUG(D_resolver) _res.options |= RES_DEBUG;
+ DEBUG(D_resolver) resp->options |= RES_DEBUG;
+ os_put_dns_resolver_res(resp);
}
-_res.options &= ~(RES_DNSRCH | RES_DEFNAMES);
-_res.options |= (qualify_single? RES_DEFNAMES : 0) |
+resp->options &= ~(RES_DNSRCH | RES_DEFNAMES);
+resp->options |= (qualify_single? RES_DEFNAMES : 0) |
(search_parents? RES_DNSRCH : 0);
-if (dns_retrans > 0) _res.retrans = dns_retrans;
-if (dns_retry > 0) _res.retry = dns_retry;
+if (dns_retrans > 0) resp->retrans = dns_retrans;
+if (dns_retry > 0) resp->retry = dns_retry;
#ifdef RES_USE_EDNS0
if (dns_use_edns0 >= 0)
{
if (dns_use_edns0)
- _res.options |= RES_USE_EDNS0;
+ resp->options |= RES_USE_EDNS0;
else
- _res.options &= ~RES_USE_EDNS0;
+ resp->options &= ~RES_USE_EDNS0;
DEBUG(D_resolver)
debug_printf("Coerced resolver EDNS0 support %s.\n",
dns_use_edns0 ? "on" : "off");
@@ -196,6 +200,8 @@ if (dns_use_edns0 >= 0)
debug_printf("Unable to %sset EDNS0 without resolver support.\n",
dns_use_edns0 ? "" : "un");
#endif
+
+os_put_dns_resolver_res(resp);
}
@@ -440,9 +446,10 @@ Returns: the return code
static int
dns_return(uschar *name, int type, int rc)
{
+res_state resp = os_get_dns_resolver_res();
tree_node *node = store_get_perm(sizeof(tree_node) + 290);
sprintf(CS node->name, "%.255s-%s-%lx", name, dns_text_type(type),
- _res.options);
+ resp->options);
node->data.val = rc;
(void)tree_insertnode(&tree_dns_fails, node);
return rc;
@@ -482,6 +489,7 @@ dns_basic_lookup(dns_answer *dnsa, uschar *name, int type)
int rc = -1;
uschar *save;
#endif
+res_state resp = os_get_dns_resolver_res();
tree_node *previous;
uschar node_name[290];
@@ -492,7 +500,7 @@ have many addresses in the same domain. We rely on the resolver and name server
caching for successful lookups. */
sprintf(CS node_name, "%.255s-%s-%lx", name, dns_text_type(type),
- _res.options);
+ resp->options);
previous = tree_search(tree_dns_fails, node_name);
if (previous != NULL)
{
diff --git a/src/src/exim.h b/src/src/exim.h
index 626d33dae..e6e72facc 100644
--- a/src/src/exim.h
+++ b/src/src/exim.h
@@ -353,6 +353,17 @@ to undefine it if resolv.h defines it. */
#undef __P
#endif
+/* If not defined by os.h, we do nothing special to push DNS resolver state
+back to be available by the classic resolver routines. Also, provide
+prototype for our get routine, unless defined away. */
+
+#ifndef os_put_dns_resolver_res
+# define os_put_dns_resolver_res(R) do {/**/} while(0)
+#endif
+#ifndef os_get_dns_resolver_res
+res_state os_get_dns_resolver_res(void);
+#endif
+
/* These three are to support the IP option logging code. Linux is
different to everyone else and there are also other systems which don't
have netinet/ip_var.h, so there's a general macro to control its inclusion. */
diff --git a/src/src/exim_lock.c b/src/src/exim_lock.c
index 027a55831..0a9dfde2d 100644
--- a/src/src/exim_lock.c
+++ b/src/src/exim_lock.c
@@ -70,6 +70,10 @@ the other stuff in os.c, so force the other macros to omit it. */
#define FIND_RUNNING_INTERFACES
#endif
+#ifndef OS_GET_DNS_RESOLVER_RES
+ #define OS_GET_DNS_RESOLVER_RES
+#endif
+
#include "../src/os.c"
diff --git a/src/src/os.c b/src/src/os.c
index 07514b5cf..a70bc6115 100644
--- a/src/src/os.c
+++ b/src/src/os.c
@@ -795,6 +795,50 @@ return yield;
+/* ----------------------------------------------------------------------- */
+
+/***********************************************************
+* DNS Resolver Base Finder *
+***********************************************************/
+
+/* We need to be able to set options for the system resolver(5), historically
+made available as _res. At least one OS (NetBSD) now no longer provides this
+directly, instead making you call a function per thread to get a handle.
+Other OSs handle thread-safe resolver differently, in ways which fail if the
+programmer creates their own structs. */
+
+#ifndef OS_GET_DNS_RESOLVER_RES
+
+#include <resolv.h>
+
+/* confirmed that res_state is typedef'd as a struct* on BSD and Linux, will
+find out how unportable it is on other OSes, but most resolver implementations
+should be descended from ISC's bind.
+
+Linux and BSD do:
+ define _res (*__res_state())
+identically. We just can't rely on __foo functions. It's surprising that use
+of _res has been as portable as it has, for so long.
+
+So, since _res works everywhere, and everything can decode the struct, I'm
+going to gamble that res_state is a typedef everywhere and use that as the
+return type.
+*/
+
+res_state
+os_get_dns_resolver_res(void)
+{
+ return &_res;
+}
+
+#endif /* OS_GET_DNS_RESOLVER_RES */
+
+
+/* ----------------------------------------------------------------------- */
+
+
+
+
/*************************************************
**************************************************