The TTL computation and assignment loops treat OPT record's Hdr.Ttl
as a regular TTL, but per RFC 6891 it encodes EDNS0 metadata
(ExtRCode|Version|Flags). This corrupts cached responses causing
systemd-resolved to reject them with EDNS version 255.
Also fix pointer aliasing: storeCache() stored raw *dns.Msg pointer
so subsequent mutations by Exchange() corrupted cached data.
- Skip OPT records in all TTL loops (Exchange + loadResponse)
- Use message.Copy() in storeCache() to isolate cache from mutations
The cache deduplication in Client.Exchange uses a channel-based lock
per DNS question. Waiting goroutines blocked on <-cond without context
awareness, causing them to accumulate indefinitely when the owning
goroutine's transport call stalls. Add select on ctx.Done() so waiters
respect context cancellation and timeouts.
We mistakenly believed that `libresolv`'s `search` function worked correctly in NetworkExtension, but it seems only `getaddrinfo` does.
This commit changes the behavior of the `local` DNS server in NetworkExtension to prefer DHCP, falling back to `getaddrinfo` if DHCP servers are unavailable.
It's worth noting that `prefer_go` does not disable DHCP since it respects Dial Fields, but `getaddrinfo` does the opposite. The new behavior only applies to NetworkExtension, not to all scenarios (primarily command-line binaries) as it did previously.
In addition, this commit also improves the DHCP DNS server to use the same robust query logic as `local`.
Previously, the buffer was not reset within the response loop. If a packet
handle failed or completed, the buffer retained its state. Specifically,
if `ReadPacketFrom` returned `io.ErrShortBuffer`, the error was ignored
via `continue`, but the buffer remained full. This caused the next
read attempt to immediately fail with the same error, creating a tight
busy-wait loop that consumed 100% CPU.
Validates `buffer.Reset()` is called at the start of each iteration to
ensure a clean state for 'ReadPacketFrom'.
The cache lookup was performed before rule matching, using the caller's
strategy (usually AsIS/0) instead of the resolved strategy. This caused
cache misses when ipv4_only was configured globally but the cache lookup
expected both A and AAAA records.
Remove LookupCache and ExchangeCache from Router, as the cache checks
inside client.Lookup and client.Exchange already handle caching correctly
after rule matching with the proper strategy and transport.