-
Notifications
You must be signed in to change notification settings - Fork 260
Description
Summary:
This issue reports a performance inefficiency in the org.xbill.DNS.Lookup class, specifically related to how it handles DNS lookups for names with a number of labels greater than or equal to the configured ndots value. This can lead to unnecessary double lookups, causing delays, especially when the DNS resolver has timeouts.
Problem Description:
- A change (commit hash) introduced logic to lookup a name as absolute after search path exhaustion.
- However, when the provided name already has more labels than the configured
ndotsvalue and is not an absolute name (i.e., it doesn't end with a dot), this logic results in the code attempting to resolve the name twice:- An initial absolute lookup is performed because the name is already considered "absolute enough" based on
ndots. - After exhausting the search path, a second absolute lookup is attempted again.
- An initial absolute lookup is performed because the name is already considered "absolute enough" based on
- This double lookup causes unnecessary network overhead and delays, particularly if the DNS server is slow or unresponsive. It can also exacerbate timeout issues.
Example Scenario:
Consider the following configuration:
- DNS search path:
internal.lan ndots:2
And an application trying to resolve the name my-service.internal.
- The name
my-service.internalhas 2 labels, and becausendotsis also2, it triggers an initial absolute lookup formy-service.internal.. - After the initial lookup, the code will iterate over the search path.
- After the search path is exhausted, the code attempts to resolve the name
my-service.internal.again, causing a double lookup.
Impact:
- Performance degradation, especially in environments with slow DNS resolvers.
- Increased probability of timeouts.
Proposed Solution:
The fix is to avoid the second absolute lookup if an initial absolute lookup was already performed. We can achieve this by tracking whether the initial lookup was performed and conditionally skipping the final lookup after the search path is exhausted.
Code Snippet (Illustrative - Java):
Here's a code snippet demonstrating the issue and the proposed fix. The code is based on the Lookup.java class.
// Original code (problematic)
if (searchPath == null) {
resolve(name, Name.root);
} else {
if (name.labels() > ndots) { // <-- Initial absolute lookup
resolve(name, Name.root);
}
if (done) {
return;
}
for (String element : searchPath) {
if (element == null || element.isEmpty()){
continue;
}
Name suffix = Name.fromString(element, Name.root);
Name full = Name.relative(name, suffix);
resolve(full, suffix);
if (done) {
break;
}
}
resolve(name, Name.root); // <-- Double lookup, always performed
}/ /Proposed fix
if (searchPath == null) {
resolve(name, Name.root);
} else {
boolean sendInitialAbsoluteQuery = name.labels() > ndots; // <-- Track if the initial absolute lookup was done
if (sendInitialAbsoluteQuery) {
resolve(name, Name.root); // <-- Initial absolute lookup
}
if (done) {
return;
}
for (String element : searchPath) {
if (element == null || element.isEmpty()){
continue;
}
Name suffix = Name.fromString(element, Name.root);
Name full = Name.relative(name, suffix);
resolve(full, suffix);
if (done) {
break;
}
}
if (!sendInitialAbsoluteQuery) { // <-- Skip the final absolute lookup if initial was performed
resolve(name, Name.root);
}
}