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 577f77f7ab..882b9d7e48 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 @@ -930,7 +930,8 @@ abstract class DnsResolveContext { // If cause != null we know this was caused by a timeout / cancel / transport exception. In this case we // won't try to resolve the CNAME as we only should do this if we could not get the expected records // because they do not exist and the DNS server did probably signal it. - if (cause == null && !triedCNAME) { + if (cause == null && !triedCNAME && + (question.type() == DnsRecordType.A || question.type() == DnsRecordType.AAAA)) { // As the last resort, try to query CNAME, just in case the name server has it. triedCNAME = true; 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 343c0f71e4..9b123d766b 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 @@ -112,6 +112,7 @@ import java.util.concurrent.atomic.AtomicReference; import static io.netty.handler.codec.dns.DnsRecordType.A; import static io.netty.handler.codec.dns.DnsRecordType.AAAA; import static io.netty.handler.codec.dns.DnsRecordType.CNAME; +import static io.netty.handler.codec.dns.DnsRecordType.NAPTR; import static io.netty.handler.codec.dns.DnsRecordType.SRV; import static io.netty.resolver.dns.DnsNameResolver.DEFAULT_RESOLVE_ADDRESS_TYPES; import static io.netty.resolver.dns.DnsServerAddresses.sequential; @@ -3286,6 +3287,65 @@ public class DnsNameResolverTest { } } + @Test + public void testCNAMEOnlyTriedOnAddressLookups() throws Exception { + + final AtomicInteger cnameQueries = new AtomicInteger(); + + TestDnsServer dnsServer2 = new TestDnsServer(new RecordStore() { + @Override + public Set getRecords(QuestionRecord questionRecord) { + if (questionRecord.getRecordType() == RecordType.CNAME) { + cnameQueries.incrementAndGet(); + } + + return Collections.emptySet(); + } + }); + + dnsServer2.start(); + + DnsNameResolver resolver = null; + try { + resolver = newNonCachedResolver(ResolvedAddressTypes.IPV4_PREFERRED) + .maxQueriesPerResolve(4) + .searchDomains(Collections.emptyList()) + .nameServerProvider(new SingletonDnsServerAddressStreamProvider(dnsServer2.localAddress())) + .build(); + + // We expect these resolves to fail with UnknownHostException, + // and then check that no unexpected CNAME queries were performed. + assertThat(resolver.resolveAll(new DefaultDnsQuestion("lookup-srv.netty.io", SRV)).await().cause(), + instanceOf(UnknownHostException.class)); + assertEquals(0, cnameQueries.get()); + + assertThat(resolver.resolveAll(new DefaultDnsQuestion("lookup-naptr.netty.io", NAPTR)).await().cause(), + instanceOf(UnknownHostException.class)); + assertEquals(0, cnameQueries.get()); + + assertThat(resolver.resolveAll(new DefaultDnsQuestion("lookup-cname.netty.io", CNAME)).await().cause(), + instanceOf(UnknownHostException.class)); + assertEquals(1, cnameQueries.getAndSet(0)); + + assertThat(resolver.resolveAll(new DefaultDnsQuestion("lookup-a.netty.io", A)).await().cause(), + instanceOf(UnknownHostException.class)); + assertEquals(1, cnameQueries.getAndSet(0)); + + assertThat(resolver.resolveAll(new DefaultDnsQuestion("lookup-aaaa.netty.io", AAAA)).await().cause(), + instanceOf(UnknownHostException.class)); + assertEquals(1, cnameQueries.getAndSet(0)); + + assertThat(resolver.resolveAll("lookup-address.netty.io").await().cause(), + instanceOf(UnknownHostException.class)); + assertEquals(1, cnameQueries.getAndSet(0)); + } finally { + dnsServer2.stop(); + if (resolver != null) { + resolver.close(); + } + } + } + private static void assertNotEmptyAndRelease(Future> recordsFuture) throws Exception { List records = recordsFuture.get(); assertFalse(records.isEmpty());