Commit e0c0ad3b authored by Simon Kelley's avatar Simon Kelley

UDP retries for DNSSEC

parent 4619d946
...@@ -868,7 +868,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char ...@@ -868,7 +868,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
{ {
unsigned char *psave, *p = (unsigned char *)(header+1); unsigned char *psave, *p = (unsigned char *)(header+1);
struct crec *crecp; struct crec *crecp;
int qtype, qclass, val, j, gotone; int qtype, qclass, val, j;
struct blockdata *key; struct blockdata *key;
if (ntohs(header->qdcount) != 1 || if (ntohs(header->qdcount) != 1 ||
...@@ -895,7 +895,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char ...@@ -895,7 +895,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
cache_start_insert(); cache_start_insert();
for (gotone = 0, j = ntohs(header->ancount); j != 0; j--) for (j = ntohs(header->ancount); j != 0; j--)
{ {
int ttl, rdlen, rc, algo, digest, keytag; int ttl, rdlen, rc, algo, digest, keytag;
......
...@@ -252,6 +252,46 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, ...@@ -252,6 +252,46 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
forward = NULL; forward = NULL;
else if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, crc))) 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 */ /* retry on existing query, send to all available servers */
domain = forward->sentto->domain; domain = forward->sentto->domain;
forward->sentto->failed_queries++; forward->sentto->failed_queries++;
...@@ -704,7 +744,7 @@ void reply_query(int fd, int family, time_t now) ...@@ -704,7 +744,7 @@ void reply_query(int fd, int family, time_t now)
int status; int status;
/* We've had a reply already, which we're validating. Ignore this duplicate */ /* We've had a reply already, which we're validating. Ignore this duplicate */
if (forward->stash) if (forward->blocking_query)
return; return;
if (header->hb3 & HB3_TC) if (header->hb3 & HB3_TC)
...@@ -737,7 +777,6 @@ void reply_query(int fd, int family, time_t now) ...@@ -737,7 +777,6 @@ void reply_query(int fd, int family, time_t now)
struct frec *next = new->next; struct frec *next = new->next;
*new = *forward; /* copy everything, then overwrite */ *new = *forward; /* copy everything, then overwrite */
new->next = next; new->next = next;
new->stash = NULL;
new->blocking_query = NULL; new->blocking_query = NULL;
new->rfd4 = NULL; new->rfd4 = NULL;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
...@@ -745,7 +784,14 @@ void reply_query(int fd, int family, time_t now) ...@@ -745,7 +784,14 @@ void reply_query(int fd, int family, time_t now)
#endif #endif
new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY); 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; int fd;
...@@ -760,7 +806,7 @@ void reply_query(int fd, int family, time_t now) ...@@ -760,7 +806,7 @@ void reply_query(int fd, int family, time_t now)
nn = dnssec_generate_query(header, ((char *) header) + daemon->packet_buff_sz, nn = dnssec_generate_query(header, ((char *) header) + daemon->packet_buff_sz,
daemon->keyname, forward->class, T_DNSKEY, &server->addr); daemon->keyname, forward->class, T_DNSKEY, &server->addr);
} }
else if (status == STAT_NEED_DS) else
{ {
new->flags |= FREC_DS_QUERY; new->flags |= FREC_DS_QUERY;
nn = dnssec_generate_query(header,((char *) header) + daemon->packet_buff_sz, nn = dnssec_generate_query(header,((char *) header) + daemon->packet_buff_sz,
...@@ -769,6 +815,9 @@ void reply_query(int fd, int family, time_t now) ...@@ -769,6 +815,9 @@ void reply_query(int fd, int family, time_t now)
new->crc = questions_crc(header, nn, daemon->namebuff); new->crc = questions_crc(header, nn, daemon->namebuff);
new->new_id = get_id(new->crc); new->new_id = get_id(new->crc);
header->id = htons(new->new_id); 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. */ /* Don't resend this. */
daemon->srv_save = NULL; daemon->srv_save = NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment