diff --git a/src/libs/xpl/dns.c b/src/libs/xpl/dns.c index 93f7f99..fd093a6 100644 --- a/src/libs/xpl/dns.c +++ b/src/libs/xpl/dns.c @@ -416,24 +416,35 @@ XplDns_Result * _XplDns_Query(const char *domain, XplDns_RecordType type) { XplDns_Result *result; + struct __res_state resolver; unsigned char answer_buffer[4096]; int answer_len = -1; + int resolver_error = 0; result = MemMalloc(sizeof(XplDns_Result)); result->list = NULL; result->status = XPLDNS_FAIL; result->dnssec_authenticated = 0; - // FIXME: is this re-entrant _everywhere_ ? /* DNS mail records are Internet-class data. ns_c_any is class 255, * not an instruction to accept any result, and authoritative servers - * are not required to answer MX/A/TXT questions sent with that class. */ - answer_len = res_query(domain, ns_c_in, type, answer_buffer, 4096); + * are not required to answer MX/A/TXT questions sent with that class. + * Use a per-call resolver state because SMTP queue workers run in + * parallel. glibc strips the AD bit unless RES_TRUSTAD is explicitly + * enabled, while RES_USE_DNSSEC requests the DNSSEC records needed by + * a validating resolver. */ + memset(&resolver, 0, sizeof(resolver)); + if (res_ninit(&resolver) != 0) return result; + resolver.options |= RES_USE_DNSSEC | RES_TRUSTAD; + answer_len = res_nquery(&resolver, domain, ns_c_in, type, + answer_buffer, sizeof(answer_buffer)); + resolver_error = resolver.res_h_errno; + res_nclose(&resolver); if (answer_len < 0) { // didn't get a sensible answer - if (h_errno) { - result->status = (XplDns_ResultCode) h_errno; + if (resolver_error) { + result->status = (XplDns_ResultCode) resolver_error; return result; } else { return result;