diff options
author | Michael Brown <mcb30@ipxe.org> | 2022-02-23 22:52:08 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2022-02-23 23:17:05 +0000 |
commit | 2acdc92994e7aca397b0d24b112e4973e82e0f91 (patch) | |
tree | 7edfaaa9f2b8cf705b948e5ca4404d7242727f3c | |
parent | bc5c612f756b11c08e5e1eaeee3c1fd91252534d (diff) | |
download | ipxe-2acdc92994e7aca397b0d24b112e4973e82e0f91.zip ipxe-2acdc92994e7aca397b0d24b112e4973e82e0f91.tar.gz ipxe-2acdc92994e7aca397b0d24b112e4973e82e0f91.tar.bz2 |
[dns] Always start DNS queries using the first configured DNS serverdns_primary
We currently define the active DNS server as a global variable. All
queries will start by attempting to contact the active DNS server, and
the active DNS server will be changed only if we fail to get a
response. This effectively treats the DNS server list as expressing a
weak preference ordering: we will try servers in order, but once we
have found a working server we will stick with that server for as long
as it continues to respond to queries.
Some sites are misconfigured to hand out DNS servers that do not have
a consistent worldview. For example: the site may hand out two DNS
server addresses, the first being an internal DNS server (which is
able to resolve names in private DNS domains) and the second being a
public DNS server such as 8.8.8.8 (which will correctly return
NXDOMAIN for any private DNS domains). This type of configuration is
fundamentally broken and should never be used, since any DNS resolver
performing a query for a name within a private DNS domain may obtain a
spurious NXDOMAIN response for a valid private DNS name.
Work around these broken configurations by treating the DNS server
list as expressing a strong preference ordering, and always starting
DNS queries from the first server in the list (rather than maintaining
a global concept of the active server). This will have the debatable
benefit of converting permanent spurious NXDOMAIN errors into
transient spurious NXDOMAIN errors, which can at least be worked
around at a higher level (e.g. by retrying a download in a loop within
an iPXE script).
The cost of always starting DNS queries from the first server in the
list is a slight delay introduced when the first server is genuinely
unavailable. This should be negligible in practice since DNS queries
are relatively infrequent and the failover expiry time is short.
Treating the DNS server list as a preference ordering is permitted by
the language of RFC 2132, which defines DHCP option 6 as a list in
which "[DNS] servers SHOULD be listed in order of preference". No
specification defines a precise algorithm for how this preference
order should be applied in practice: this new approach seems as good
as any.
Requested-by: Andreas Hammarskjöld <junior@2PintSoftware.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/net/udp/dns.c | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/src/net/udp/dns.c b/src/net/udp/dns.c index e557917..f46eeb5 100644 --- a/src/net/udp/dns.c +++ b/src/net/udp/dns.c @@ -87,9 +87,6 @@ static struct dns_server dns6; /** Total number of DNS servers */ static unsigned int dns_count; -/** Current DNS server index */ -static unsigned int dns_index; - /** The DNS search list */ static struct dns_name dns_search; @@ -489,6 +486,8 @@ struct dns_request { size_t offset; /** Search list */ struct dns_name search; + /** Server index */ + unsigned int index; /** Recursion counter */ unsigned int recursion; }; @@ -606,7 +605,7 @@ static int dns_send_packet ( struct dns_request *dns ) { DBGC ( dns, "DNS %p lost DNS servers mid query\n", dns ); return -EINVAL; } - index = ( dns_index % dns_count ); + index = ( dns->index % dns_count ); if ( index < dns6.count ) { nameserver.sin6.sin6_family = AF_INET6; memcpy ( &nameserver.sin6.sin6_addr, &dns6.in6[index], @@ -651,7 +650,7 @@ static void dns_timer_expired ( struct retry_timer *timer, int fail ) { /* Move to next DNS server if this is a retransmission */ if ( dns->buf.query.id ) - dns_index++; + dns->index++; /* Send DNS query */ dns_send_packet ( dns ); |