Allow ndots=0 in DnsNameResolver and search domains - fixes #5570

Motivation:

The ndots = 0 is a valid value for ndots, it means that when using a non dotted name, the resolution should first try using a search and if it fails then use subdomains. Currently it is not allowed. Docker compose uses this when wiring up containers as names have usually no dots inside.

Modification:

Modify DnsNameResolver to accept ndots = 0 and handle the case in the resolution procedure. In this case a direct search is done and then a fallback on the search path is performed.

Result:

The ndots = 0 case is implemented.
This commit is contained in:
Julien Viet 2016-07-23 09:47:43 +02:00 committed by Norman Maurer
parent f25f1f255d
commit 8d4cfd9002
4 changed files with 46 additions and 11 deletions

View File

@ -191,7 +191,7 @@ public class DnsNameResolver extends InetNameResolver {
this.hostsFileEntriesResolver = checkNotNull(hostsFileEntriesResolver, "hostsFileEntriesResolver");
this.resolveCache = resolveCache;
this.searchDomains = checkNotNull(searchDomains, "searchDomains").clone();
this.ndots = checkPositive(ndots, "ndots");
this.ndots = checkPositiveOrZero(ndots, "ndots");
Bootstrap b = new Bootstrap();
b.group(executor());

View File

@ -321,6 +321,7 @@ public final class DnsNameResolverBuilder {
/**
* Set the number of dots which must appear in a name before an initial absolute query is made.
* The default value is {@code 1}.
*
* @param ndots the ndots value
* @return {@code this}

View File

@ -123,14 +123,18 @@ abstract class DnsNameResolverContext<T> {
}
}
});
int dots = 0;
for (int idx = hostname.length() - 1; idx >= 0; idx--) {
if (hostname.charAt(idx) == '.' && ++dots >= parent.ndots()) {
internalResolve(promise);
return;
if (parent.ndots() == 0) {
internalResolve(promise);
} else {
int dots = 0;
for (int idx = hostname.length() - 1; idx >= 0; idx--) {
if (hostname.charAt(idx) == '.' && ++dots >= parent.ndots()) {
internalResolve(promise);
return;
}
}
promise.tryFailure(new UnknownHostException(hostname));
}
promise.tryFailure(new UnknownHostException(hostname));
}
}

View File

@ -48,6 +48,7 @@ public class SearchDomainTest {
private TestDnsServer dnsServer;
private EventLoopGroup group;
private DnsNameResolver resolver;
@Before
public void before() {
@ -60,6 +61,9 @@ public class SearchDomainTest {
dnsServer.stop();
dnsServer = null;
}
if (resolver != null) {
resolver.close();
}
group.shutdownGracefully();
}
@ -77,7 +81,7 @@ public class SearchDomainTest {
dnsServer = new TestDnsServer(store);
dnsServer.start();
DnsNameResolver resolver = newResolver().searchDomains(Collections.singletonList("foo.com")).build();
resolver = newResolver().searchDomains(Collections.singletonList("foo.com")).build();
String a = "host1.foo.com";
String resolved = assertResolve(resolver, a);
@ -124,7 +128,7 @@ public class SearchDomainTest {
dnsServer = new TestDnsServer(store);
dnsServer.start();
DnsNameResolver resolver = newResolver().searchDomains(Collections.singletonList("foo.com")).build();
resolver = newResolver().searchDomains(Collections.singletonList("foo.com")).build();
String a = "host1.foo.com";
List<String> resolved = assertResolveAll(resolver, a);
@ -169,7 +173,7 @@ public class SearchDomainTest {
dnsServer = new TestDnsServer(store);
dnsServer.start();
DnsNameResolver resolver = newResolver().searchDomains(Arrays.asList("foo.com", "bar.com")).build();
resolver = newResolver().searchDomains(Arrays.asList("foo.com", "bar.com")).build();
// "host1" resolves via the "foo.com" search path
String resolved = assertResolve(resolver, "host1");
@ -198,7 +202,7 @@ public class SearchDomainTest {
dnsServer = new TestDnsServer(store);
dnsServer.start();
DnsNameResolver resolver = newResolver().searchDomains(Collections.singleton("foo.com")).ndots(2).build();
resolver = newResolver().searchDomains(Collections.singleton("foo.com")).ndots(2).build();
String resolved = assertResolve(resolver, "host1.sub");
assertEquals(store.getAddress("host1.sub.foo.com"), resolved);
@ -208,6 +212,32 @@ public class SearchDomainTest {
assertEquals(store.getAddress("host2.sub.foo.com"), resolved);
}
@Test
public void testSearchDomainWithNdots0() throws Exception {
Set<String> domains = new HashSet<String>();
domains.add("host1");
domains.add("host1.foo.com");
domains.add("host2.foo.com");
TestDnsServer.MapRecordStoreA store = new TestDnsServer.MapRecordStoreA(domains);
dnsServer = new TestDnsServer(store);
dnsServer.start();
resolver = newResolver().searchDomains(Collections.singleton("foo.com")).ndots(0).build();
// "host1" resolves directly as ndots = 0
String resolved = assertResolve(resolver, "host1");
assertEquals(store.getAddress("host1"), resolved);
// "host1.foo.com" resolves to host1.foo
resolved = assertResolve(resolver, "host1.foo.com");
assertEquals(store.getAddress("host1.foo.com"), resolved);
// "host2" resolves to host2.foo.com with the foo.com search domain
resolved = assertResolve(resolver, "host2");
assertEquals(store.getAddress("host2.foo.com"), resolved);
}
private void assertNotResolve(DnsNameResolver resolver, String inetHost) throws InterruptedException {
Future<InetAddress> fut = resolver.resolve(inetHost);
assertTrue(fut.await(10, TimeUnit.SECONDS));