101 lines
3 KiB
Diff
101 lines
3 KiB
Diff
|
From 1f60a18ea1c64beb8b6cffa0650a2bfad95ac352 Mon Sep 17 00:00:00 2001
|
||
|
From: Simon Kelley <simon@thekelleys.org.uk>
|
||
|
Date: Fri, 11 May 2018 16:44:16 +0100
|
||
|
Subject: [PATCH 07/10] Retry SERVFAIL DNSSEC queries to a different server, if
|
||
|
possible.
|
||
|
|
||
|
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||
|
---
|
||
|
src/forward.c | 53 ++++++++++++++++++++++++++++++++++++++++++-----------
|
||
|
1 file changed, 42 insertions(+), 11 deletions(-)
|
||
|
|
||
|
--- a/src/forward.c
|
||
|
+++ b/src/forward.c
|
||
|
@@ -825,9 +825,12 @@ void reply_query(int fd, int family, tim
|
||
|
size_t plen;
|
||
|
int is_sign;
|
||
|
|
||
|
+#ifdef HAVE_DNSSEC
|
||
|
/* For DNSSEC originated queries, just retry the query to the same server. */
|
||
|
if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
|
||
|
{
|
||
|
+ struct server *start;
|
||
|
+
|
||
|
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
|
||
|
plen = forward->stash_len;
|
||
|
|
||
|
@@ -839,26 +842,54 @@ void reply_query(int fd, int family, tim
|
||
|
else
|
||
|
log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
|
||
|
#endif
|
||
|
-
|
||
|
- if (forward->sentto->sfd)
|
||
|
- fd = forward->sentto->sfd->fd;
|
||
|
+
|
||
|
+ start = forward->sentto;
|
||
|
+
|
||
|
+ /* for non-domain specific servers, see if we can find another to try. */
|
||
|
+ if ((forward->sentto->flags & SERV_TYPE) == 0)
|
||
|
+ while (1)
|
||
|
+ {
|
||
|
+ if (!(start = start->next))
|
||
|
+ start = daemon->servers;
|
||
|
+ if (start == forward->sentto)
|
||
|
+ break;
|
||
|
+
|
||
|
+ if ((start->flags & SERV_TYPE) == 0 &&
|
||
|
+ (start->flags & SERV_DO_DNSSEC))
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+
|
||
|
+ if (start->sfd)
|
||
|
+ fd = start->sfd->fd;
|
||
|
else
|
||
|
{
|
||
|
#ifdef HAVE_IPV6
|
||
|
- if (forward->sentto->addr.sa.sa_family == AF_INET6)
|
||
|
- fd = forward->rfd6->fd;
|
||
|
+ if (start->addr.sa.sa_family == AF_INET6)
|
||
|
+ {
|
||
|
+ /* may have changed family */
|
||
|
+ if (!forward->rfd6)
|
||
|
+ forward->rfd6 = allocate_rfd(AF_INET6);
|
||
|
+ fd = forward->rfd6->fd;
|
||
|
+ }
|
||
|
else
|
||
|
#endif
|
||
|
- fd = forward->rfd4->fd;
|
||
|
+ {
|
||
|
+ /* may have changed family */
|
||
|
+ if (!forward->rfd4)
|
||
|
+ forward->rfd4 = allocate_rfd(AF_INET);
|
||
|
+ fd = forward->rfd4->fd;
|
||
|
+ }
|
||
|
}
|
||
|
-
|
||
|
+
|
||
|
while (retry_send(sendto(fd, (char *)header, plen, 0,
|
||
|
- &forward->sentto->addr.sa,
|
||
|
- sa_len(&forward->sentto->addr))));
|
||
|
+ &start->addr.sa,
|
||
|
+ sa_len(&start->addr))));
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
-
|
||
|
+#endif
|
||
|
+
|
||
|
/* In strict order mode, there must be a server later in the chain
|
||
|
left to send to, otherwise without the forwardall mechanism,
|
||
|
code further on will cycle around the list forwever if they
|
||
|
@@ -1024,7 +1055,7 @@ void reply_query(int fd, int family, tim
|
||
|
while (1)
|
||
|
{
|
||
|
if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
|
||
|
- (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
|
||
|
+ ((type & SERV_TYPE) != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
|
||
|
!(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
|
||
|
{
|
||
|
new_server = start;
|