From a0088e83640d7d1544127dd668660462e9f78e52 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Thu, 10 May 2018 21:43:14 +0100 Subject: [PATCH 06/17] Handle query retry on REFUSED or SERVFAIL for DNSSEC-generated queries. Signed-off-by: Kevin Darbyshire-Bryant --- src/forward.c | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) --- a/src/forward.c +++ b/src/forward.c @@ -298,9 +298,9 @@ static int forward_query(int udpfd, unio fd = forward->rfd4->fd; } - while (retry_send( sendto(fd, (char *)header, plen, 0, - &forward->sentto->addr.sa, - sa_len(&forward->sentto->addr)))); + while (retry_send(sendto(fd, (char *)header, plen, 0, + &forward->sentto->addr.sa, + sa_len(&forward->sentto->addr)))); return 1; } @@ -804,8 +804,7 @@ void reply_query(int fd, int family, tim dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY, (void *)header, n, &serveraddr, NULL); #endif - - + /* log_query gets called indirectly all over the place, so pass these in global variables - sorry. */ daemon->log_display_id = forward->log_id; @@ -826,6 +825,40 @@ void reply_query(int fd, int family, tim size_t plen; int is_sign; + /* For DNSSEC originated queries, just retry the query to the same server. */ + if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) + { + blockdata_retrieve(forward->stash, forward->stash_len, (void *)header); + plen = forward->stash_len; + + forward->forwardall = 2; /* only retry once */ + + if (forward->sentto->addr.sa.sa_family == AF_INET) + log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec"); +#ifdef HAVE_IPV6 + 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; + else + { +#ifdef HAVE_IPV6 + if (forward->sentto->addr.sa.sa_family == AF_INET6) + fd = forward->rfd6->fd; + else +#endif + fd = forward->rfd4->fd; + } + + while (retry_send(sendto(fd, (char *)header, plen, 0, + &forward->sentto->addr.sa, + sa_len(&forward->sentto->addr)))); + + return; + } + /* 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 @@ -1017,7 +1050,8 @@ void reply_query(int fd, int family, tim #ifdef HAVE_IPV6 new->rfd6 = NULL; #endif - new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY); + new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA); + new->forwardall = 0; new->dependent = forward; /* to find query awaiting new one. */ forward->blocking_query = new; /* for garbage cleaning */