summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2017-05-09 01:34:02 +0100
committerSimon Kelley <simon@thekelleys.org.uk>2017-05-09 01:34:02 +0100
commit09f3b2cd9c7b5b5e0e96ba41f666e69808862620 (patch)
treed1a163a2df1a5b01475cfb39e0b274cc62aecbc9
parent22827870fa249246a828bc9d6645b84956aa9dd9 (diff)
downloaddnsmasq-2.77rc1.tar.gz
Fix case of DS queries to domains marked as not doing DNSSEC.v2.77rc1
This was causing confusion: DNSSEC queries would be sent to servers for domains that don't do DNSSEC, but because of that status the answers would be treated as answers to ordinary queries, sometimes resulting in a crash.
-rw-r--r--src/forward.c120
1 files changed, 60 insertions, 60 deletions
diff --git a/src/forward.c b/src/forward.c
index 14cdfaa..a077620 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -120,8 +120,10 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigne
unsigned int flags = 0;
for (serv = daemon->servers; serv; serv=serv->next)
+ if (qtype == F_DNSSECOK && !(serv->flags & SERV_DO_DNSSEC))
+ continue;
/* domain matches take priority over NODOTS matches */
- if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
+ else if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
{
unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
*type = SERV_FOR_NODOTS;
@@ -877,10 +879,10 @@ void reply_query(int fd, int family, time_t now)
return;
/* Truncated answer can't be validated.
- If this is an answer to a DNSSEC-generated query, we still
- need to get the client to retry over TCP, so return
- an answer with the TC bit set, even if the actual answer fits.
- */
+ If this is an answer to a DNSSEC-generated query, we still
+ need to get the client to retry over TCP, so return
+ an answer with the TC bit set, even if the actual answer fits.
+ */
if (header->hb3 & HB3_TC)
status = STAT_TRUNCATED;
@@ -933,37 +935,35 @@ void reply_query(int fd, int family, time_t now)
/* Find server to forward to. This will normally be the
same as for the original query, but may be another if
servers for domains are involved. */
- if (search_servers(now, NULL, F_QUERY, daemon->keyname, &type, &domain, NULL) == 0)
+ if (search_servers(now, NULL, F_DNSSECOK, daemon->keyname, &type, &domain, NULL) == 0)
{
struct server *start = server, *new_server = NULL;
- type &= ~SERV_DO_DNSSEC;
-
- while (1)
- {
- if (type == (start->flags & SERV_TYPE) &&
- (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
- !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
- {
- new_server = start;
- if (server == start)
- {
- new_server = NULL;
- break;
- }
- }
-
- if (!(start = start->next))
- start = daemon->servers;
- if (start == server)
- break;
- }
-
- if (new_server)
- server = new_server;
+
+ while (1)
+ {
+ if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
+ (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
+ !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
+ {
+ new_server = start;
+ if (server == start)
+ {
+ new_server = NULL;
+ break;
+ }
+ }
+
+ if (!(start = start->next))
+ start = daemon->servers;
+ if (start == server)
+ break;
+ }
+
+ if (new_server)
+ server = new_server;
}
-
+
new->sentto = server;
-
new->rfd4 = NULL;
#ifdef HAVE_IPV6
new->rfd6 = NULL;
@@ -1506,14 +1506,12 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
/* Find server to forward to. This will normally be the
same as for the original query, but may be another if
servers for domains are involved. */
- if (search_servers(now, NULL, F_QUERY, keyname, &type, &domain, NULL) != 0)
+ if (search_servers(now, NULL, F_DNSSECOK, keyname, &type, &domain, NULL) != 0)
{
new_status = STAT_ABANDONED;
break;
}
- type &= ~SERV_DO_DNSSEC;
-
while (1)
{
if (!firstsendto)
@@ -1530,34 +1528,34 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
}
}
- if (type != (server->flags & SERV_TYPE) ||
+ if (type != (server->flags & (SERV_TYPE | SERV_DO_DNSSEC)) ||
(type == SERV_HAS_DOMAIN && !hostname_isequal(domain, server->domain)) ||
(server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
continue;
-
- retry:
- /* may need to make new connection. */
- if (server->tcpfd == -1)
- {
- if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
- continue; /* No good, next server */
-
+
+ retry:
+ /* may need to make new connection. */
+ if (server->tcpfd == -1)
+ {
+ if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
+ continue; /* No good, next server */
+
#ifdef HAVE_CONNTRACK
- /* Copy connection mark of incoming query to outgoing connection. */
- if (have_mark)
- setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
+ /* Copy connection mark of incoming query to outgoing connection. */
+ if (have_mark)
+ setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
#endif
-
- if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 1) ||
- connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
- {
- close(server->tcpfd);
- server->tcpfd = -1;
- continue; /* No good, next server */
- }
-
- server->flags &= ~SERV_GOT_TCP;
- }
+
+ if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 1) ||
+ connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
+ {
+ close(server->tcpfd);
+ server->tcpfd = -1;
+ continue; /* No good, next server */
+ }
+
+ server->flags &= ~SERV_GOT_TCP;
+ }
if (!read_write(server->tcpfd, packet, m + sizeof(u16), 0) ||
!read_write(server->tcpfd, &c1, 1, 1) ||
@@ -2080,6 +2078,8 @@ static void free_frec(struct frec *f)
#endif
}
+
+
/* if wait==NULL return a free or older than TIMEOUT record.
else return *wait zero if one available, or *wait is delay to
when the oldest in-use record will expire. Impose an absolute
@@ -2126,7 +2126,7 @@ struct frec *get_new_frec(time_t now, int *wait, int force)
/* can't find empty one, use oldest if there is one
and it's older than timeout */
- if (oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
+ if (!force && oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
{
/* keep stuff for twice timeout if we can by allocating a new
record instead */
@@ -2166,7 +2166,7 @@ struct frec *get_new_frec(time_t now, int *wait, int force)
return f; /* OK if malloc fails and this is NULL */
}
-
+
/* crc is all-ones if not known. */
static struct frec *lookup_frec(unsigned short id, void *hash)
{