UDP retries for DNSSEC
diff --git a/src/forward.c b/src/forward.c
index 21a3a19..c1f1975 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -252,6 +252,46 @@
forward = NULL;
else if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, crc)))
{
+#ifdef HAVE_DNSSEC
+ /* If we've already got an answer to this query, but we're awaiting keys for vaildation,
+ there's no point retrying the query, retry the key query instead...... */
+ if (forward->blocking_query)
+ {
+ int fd;
+
+ while (forward->blocking_query)
+ forward = forward->blocking_query;
+
+ blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
+ plen = forward->stash_len;
+
+ if (forward->sentto->addr.sa.sa_family)
+ log_query(F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
+#ifdef HAVE_IPV6
+ else
+ log_query(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 (sendto(fd, (char *)header, plen, 0,
+ &forward->sentto->addr.sa,
+ sa_len(&forward->sentto->addr)) == -1 && retry_send());
+
+ return 1;
+ }
+#endif
+
/* retry on existing query, send to all available servers */
domain = forward->sentto->domain;
forward->sentto->failed_queries++;
@@ -704,7 +744,7 @@
int status;
/* We've had a reply already, which we're validating. Ignore this duplicate */
- if (forward->stash)
+ if (forward->blocking_query)
return;
if (header->hb3 & HB3_TC)
@@ -737,7 +777,6 @@
struct frec *next = new->next;
*new = *forward; /* copy everything, then overwrite */
new->next = next;
- new->stash = NULL;
new->blocking_query = NULL;
new->rfd4 = NULL;
#ifdef HAVE_IPV6
@@ -745,7 +784,14 @@
#endif
new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
- if ((forward->stash = blockdata_alloc((char *)header, n)))
+ /* Free any saved query */
+ if (forward->stash)
+ blockdata_free(forward->stash);
+
+ /* Now save reply pending receipt of key data */
+ if (!(forward->stash = blockdata_alloc((char *)header, n)))
+ free_frec(new); /* malloc failure, unwind */
+ else
{
int fd;
@@ -760,7 +806,7 @@
nn = dnssec_generate_query(header, ((char *) header) + daemon->packet_buff_sz,
daemon->keyname, forward->class, T_DNSKEY, &server->addr);
}
- else if (status == STAT_NEED_DS)
+ else
{
new->flags |= FREC_DS_QUERY;
nn = dnssec_generate_query(header,((char *) header) + daemon->packet_buff_sz,
@@ -769,6 +815,9 @@
new->crc = questions_crc(header, nn, daemon->namebuff);
new->new_id = get_id(new->crc);
header->id = htons(new->new_id);
+ /* Save query for retransmission */
+ new->stash = blockdata_alloc((char *)header, nn);
+ new->stash_len = nn;
/* Don't resend this. */
daemon->srv_save = NULL;