Remove all user-facing references to the internal `legacyDNSMode` variable
name. Error messages now reuse the deprecated.Note.MessageWithLink() method
to provide consistent deprecation text with migration URLs. Other internal
jargon ("consume response state", "response_*") is replaced with
user-friendly descriptions.
Add two migration guide entries under 1.14.0: one for strategy → rule items,
one for address filter fields → evaluate with match_response.
Exchange and Lookup held rulesAccess.RLock across all DNS network I/O,
blocking rebuildRules from swapping in new rules until every in-flight
query finished. Replace the RWMutex with an atomic pointer to a
refcounted rulesSnapshot so queries only hold a snapshot reference
during execution, allowing concurrent rule rebuilds.
Legacy DNS address-filter mode still accepts destination-side IP
predicates with a deprecation warning, but the recent evaluate/
match_response refactor started evaluating those predicates during
pre-response Match(). That broke rules whose transport selection must
be deferred until MatchAddressLimit() can inspect the upstream reply.
Restore the old defer behavior by reintroducing an internal
IgnoreDestinationIPCIDRMatch flag on InboundContext and using it only
for legacy pre-response DNS matching. Default and logical DNS rules now
carry the legacy mode bit, set the ignore flag on metadata copies while
performing pre-response Match(), and explicitly clear it again for
match_response and MatchAddressLimit() so response-phase matching still
checks the returned addresses.
Add regression coverage for direct legacy destination-IP rules,
rule_set-backed CIDR rules, logical wrappers, and the legacy Lookup
router path, including fallback after a rejected response. This keeps
legacy configs working without changing new-mode evaluate semantics.
Tests: go test ./route/rule ./dns
Tests: make