From df5eb060f729a18582d659f868f764edc9a7277e Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Fri, 18 Jan 2019 21:06:44 +0100 Subject: [PATCH] Only handle NXDOMAIN as failure when nameserver is authoritive or no other nameservers are left. (#8731) Motivation: When using multiple nameservers and a nameserver respond with NXDOMAIN we should only fail the query if the nameserver in question is authoritive or no nameservers are left to try. Modifications: - Try next nameserver if NXDOMAIN was returned but the nameserver is not authoritive - Adjust testcase to respect correct behaviour. Result: Fixes https://github.com/netty/netty/issues/8261 --- .../netty/resolver/dns/DnsResolveContext.java | 23 +++++++++++++++++++ .../resolver/dns/DnsNameResolverTest.java | 10 ++------ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsResolveContext.java b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsResolveContext.java index 847bfb5b9f..f625be975c 100644 --- a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsResolveContext.java +++ b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsResolveContext.java @@ -497,6 +497,29 @@ abstract class DnsResolveContext { queryLifecycleObserver.queryNoAnswer(code), true, promise, null); } else { queryLifecycleObserver.queryFailed(NXDOMAIN_QUERY_FAILED_EXCEPTION); + + // Try with the next server if is not authoritative for the domain. + // + // From https://tools.ietf.org/html/rfc1035 : + // + // RCODE Response code - this 4 bit field is set as part of + // responses. The values have the following + // interpretation: + // + // .... + // .... + // + // 3 Name Error - Meaningful only for + // responses from an authoritative name + // server, this code signifies that the + // domain name referenced in the query does + // not exist. + // .... + // .... + if (!res.isAuthoritativeAnswer()) { + query(nameServerAddrStream, nameServerAddrStreamIndex + 1, question, + newDnsQueryLifecycleObserver(question), true, promise, null); + } } } finally { ReferenceCountUtil.safeRelease(envelope); diff --git a/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java b/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java index 1326a7975e..d03ee87077 100644 --- a/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java +++ b/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java @@ -1143,7 +1143,7 @@ public class DnsNameResolverTest { new TestRecursiveCacheDnsQueryLifecycleObserverFactory(); DnsNameResolverBuilder builder = new DnsNameResolverBuilder(group.next()) - .resolvedAddressTypes(ResolvedAddressTypes.IPV6_PREFERRED) + .resolvedAddressTypes(ResolvedAddressTypes.IPV4_ONLY) .dnsQueryLifecycleObserverFactory(lifecycleObserverFactory) .channelType(NioDatagramChannel.class) .optResourceEnabled(false) @@ -1156,18 +1156,12 @@ public class DnsNameResolverTest { TestDnsQueryLifecycleObserver observer = lifecycleObserverFactory.observers.poll(); assertNotNull(observer); - assertEquals(2, lifecycleObserverFactory.observers.size()); + assertEquals(1, lifecycleObserverFactory.observers.size()); assertEquals(2, observer.events.size()); QueryWrittenEvent writtenEvent = (QueryWrittenEvent) observer.events.poll(); assertEquals(dnsServer1.localAddress(), writtenEvent.dnsServerAddress); QueryFailedEvent failedEvent = (QueryFailedEvent) observer.events.poll(); - observer = lifecycleObserverFactory.observers.poll(); - assertEquals(2, observer.events.size()); - writtenEvent = (QueryWrittenEvent) observer.events.poll(); - assertEquals(dnsServer1.localAddress(), writtenEvent.dnsServerAddress); - failedEvent = (QueryFailedEvent) observer.events.poll(); - observer = lifecycleObserverFactory.observers.poll(); assertEquals(2, observer.events.size()); writtenEvent = (QueryWrittenEvent) observer.events.poll();