From 719f79a8fdb7cc72a061b2492ea98f7486b6f90e Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Tue, 6 Jul 2021 21:02:35 +0100 Subject: [PATCH] Subtle change to priority of --server types. Make --server=/example.com/1.2.3.4 take priority over --server=/example.com/ (AKA --address=/example.com/ or --local=/example.com/) This corrects a regression in the domain-match rewrite, and appears to be the more useful order. It got swapped because I didn't consider that both could usefully co-exist. --- src/domain-match.c | 47 +++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/domain-match.c b/src/domain-match.c index f2377b0..f8e4796 100644 --- a/src/domain-match.c +++ b/src/domain-match.c @@ -243,11 +243,6 @@ int lookup_domain(char *domain, int flags, int *lowout, int *highout) (nlow == nhigh || daemon->serverarray[nlow]->domain_len == 0)) filter_servers(daemon->serverarraysz-1, flags, &nlow, &nhigh); - /* F_DOMAINSRV returns only domain-specific servers, so if we got to a - general server, return empty set. */ - if (nlow != nhigh && (flags & F_DOMAINSRV) && daemon->serverarray[nlow]->domain_len == 0) - nlow = nhigh; - if (lowout) *lowout = nlow; @@ -282,11 +277,6 @@ int filter_servers(int seed, int flags, int *lowout, int *highout) nhigh++; - /* Now the servers are on order between low and high, in the order - return zero for both, IPv6 addr, IPv4 addr, no-data return, send upstream. - - See which of those match our query in that priority order and narrow (low, high) */ - #define SERV_LOCAL_ADDRESS (SERV_6ADDR | SERV_4ADDR | SERV_ALL_ZEROS) if (flags & F_CONFIG) @@ -302,6 +292,11 @@ int filter_servers(int seed, int flags, int *lowout, int *highout) } else { + /* Now the servers are on order between low and high, in the order + IPv6 addr, IPv4 addr, return zero for both, send upstream, no-data return. + + See which of those match our query in that priority order and narrow (low, high) */ + for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_6ADDR); i++); if (i != nlow && (flags & F_IPV6)) @@ -326,18 +321,26 @@ int filter_servers(int seed, int flags, int *lowout, int *highout) { nlow = i; - for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_LITERAL_ADDRESS); i++); - - /* --local=/domain/, only return if we don't need a server. */ - if (i != nlow && !(flags & (F_DNSSECOK | F_DOMAINSRV | F_SERVER))) - nhigh = i; - else + /* now look for a server */ + for (i = nlow; i < nhigh && !(daemon->serverarray[i]->flags & SERV_LITERAL_ADDRESS); i++); + + if (i != nlow) { - nlow = i; /* If we want a server that can do DNSSEC, and this one can't, - return nothing. */ + return nothing, similarly if were looking only for a server + for a particular domain. */ if ((flags & F_DNSSECOK) && !(daemon->serverarray[nlow]->flags & SERV_DO_DNSSEC)) nlow = nhigh; + else if ((flags & F_DOMAINSRV) && daemon->serverarray[nlow]->domain_len == 0) + nlow = nhigh; + else + nhigh = i; + } + else + { + /* --local=/domain/, only return if we don't need a server. */ + if (flags & (F_DNSSECOK | F_DOMAINSRV | F_SERVER)) + nhigh = i; } } } @@ -515,10 +518,12 @@ static int order_qsort(const void *a, const void *b) rc = order_servers(s1, s2); /* Sort all literal NODATA and local IPV4 or IPV6 responses together, - in a very specific order. */ + in a very specific order. We flip the SERV_LITERAL_ADDRESS bit + so the order is IPv6 literal, IPv4 literal, all-zero literal, + upstream server, NXDOMAIN literal. */ if (rc == 0) - rc = (s2->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS)) - - (s1->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS)); + rc = ((s2->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS) - + ((s1->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS); /* Finally, order by appearance in /etc/resolv.conf etc, for --strict-order */ if (rc == 0)