/* The actual values here matter, since we sort on them to get records in the order
- IPv6 addr, IPv4 addr, all zero return, resolvconf servers, upstream server, no-data return */
-#define SERV_LITERAL_ADDRESS 1 /* addr is the answer, or NoDATA is the answer, depending on the next four flags */
-#define SERV_USE_RESOLV 2 /* forward this domain in the normal way */
+ IPv6 addr, IPv4 addr, all zero return, no-data return, resolvconf servers, upstream server */
+#define SERV_USE_RESOLV 1 /* forward this domain in the normal way */
+#define SERV_LITERAL_ADDRESS 2 /* addr is the answer, or NoDATA is the answer, depending on the next four flags */
#define SERV_ALL_ZEROS 4 /* return all zeros for A and AAAA */
#define SERV_4ADDR 8 /* addr is IPv4 */
#define SERV_6ADDR 16 /* addr is IPv6 */
static int order_qsort(const void *a, const void *b);
static int order_servers(struct server *s, struct server *s2);
-/* If the server is USE_RESOLV or LITERAL_ADDRES, it lives on the local_domains chain. */
+/* If the server is USE_RESOLV or LITERAL_ADDRESS, it lives on the local_domains chain. */
#define SERV_IS_LOCAL (SERV_USE_RESOLV | SERV_LITERAL_ADDRESS)
void build_server_array(void)
return 1;
}
-/* Return first server in group of equivalent servers; this is the "master" record. */
int server_samegroup(struct server *a, struct server *b)
{
return order_servers(a, b) == 0;
}
else
{
- /* Now the servers are on order between low and high, in the order
- IPv6 addr, IPv4 addr, return zero for both, resolvconf servers, send upstream, no-data return.
+ /* Now the matching server records are all between low and high.
+ order_qsort() ensures that they are in the order
+ IPv6 addr, IPv4 addr, return zero for both, no-data return,
+ "use resolvconf" servers, domain-specific upstream servers.
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 (!(flags & F_SERVER) && i != nlow && (flags & F_IPV6))
{
nlow = i;
- /* Short to resolv.conf servers */
- for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_USE_RESOLV); i++);
+ /* now look for a NXDOMAIN answer --local=/domain/ */
+ for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_LITERAL_ADDRESS); i++);
- if (i != nlow)
+ if (!(flags & (F_DOMAINSRV | F_SERVER)) && i != nlow)
nhigh = i;
else
{
- /* now look for a server */
- for (i = nlow; i < nhigh && !(daemon->serverarray[i]->flags & SERV_LITERAL_ADDRESS); i++);
+ nlow = i;
+
+ /* return "use resolv.conf servers" if they exist */
+ for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_USE_RESOLV); i++);
if (i != nlow)
+ nhigh = i;
+ else
{
/* If we want a server for a particular domain, and this one isn't, return nothing. */
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_DOMAINSRV | F_SERVER))
- nhigh = i;
+ nlow = i;
}
}
}
rc = order_servers(s1, s2);
/* Sort all literal NODATA and local IPV4 or IPV6 responses together,
- in a very specific order. We flip the SERV_LITERAL_ADDRESS bit
- so the order is IPv6 literal, IPv4 literal, all-zero literal,
- unqualified servers, upstream server, NXDOMAIN literal. */
+ in a very specific order IPv6 literal, IPv4 literal, all-zero literal,
+ NXDOMAIN literal. We also include SERV_USE_RESOLV in this, so that
+ use-standard servers sort before ordinary servers. (SERV_USR_RESOLV set
+ implies that none of SERV_LITERAL_ADDRESS,SERV_4ADDR,SERV_6ADDR,SERV_ALL_ZEROS
+ are set) */
if (rc == 0)
- rc = ((s2->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_USE_RESOLV | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS) -
- ((s1->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_USE_RESOLV | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS);
+ rc = ((s2->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS | SERV_USE_RESOLV))) -
+ ((s1->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS | SERV_USE_RESOLV)));
/* Finally, order by appearance in /etc/resolv.conf etc, for --strict-order */
if (rc == 0)