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:
parent
f25f1f255d
commit
8d4cfd9002
@ -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());
|
||||
|
@ -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}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user