diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/OS/os.h-NetBSD | 4 | ||||
-rw-r--r-- | src/src/dns.c | 30 | ||||
-rw-r--r-- | src/src/exim.h | 11 | ||||
-rw-r--r-- | src/src/exim_lock.c | 4 | ||||
-rw-r--r-- | src/src/os.c | 44 |
5 files changed, 82 insertions, 11 deletions
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 */ + + +/* ----------------------------------------------------------------------- */ + + + + /************************************************* ************************************************** |