summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2014-02-10 21:02:01 +0000
committerSimon Kelley <simon@thekelleys.org.uk>2014-02-10 21:02:01 +0000
commit83349b8aa4f8667f611918b9189446b0e93fc2bb (patch)
treecc1b22f105b7eca82424513d1390bd36cdc9c07e
parent7fa836e1055112845b5fc6be654381d55b41086d (diff)
downloaddnsmasq-83349b8aa4f8667f611918b9189446b0e93fc2bb.tar.gz
Further tidying of AD and DO bit handling.
-rw-r--r--src/dnsmasq.h4
-rw-r--r--src/forward.c58
-rw-r--r--src/rfc1035.c19
3 files changed, 44 insertions, 37 deletions
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 204c104..1f42818 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -539,6 +539,7 @@ struct hostsfile {
#define FREC_HAS_SUBNET 4
#define FREC_DNSKEY_QUERY 8
#define FREC_DS_QUERY 16
+#define FREC_AD_QUESTION 32
#ifdef HAVE_DNSSEC
#define HASH_SIZE 20 /* SHA-1 digest size */
@@ -1041,7 +1042,8 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff,
time_t now, char **ipsets, int is_sign, int checkrebind,
int no_cache, int secure, int *doctored);
size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
- struct in_addr local_addr, struct in_addr local_netmask, time_t now);
+ struct in_addr local_addr, struct in_addr local_netmask,
+ time_t now, int *ad_reqd);
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
struct bogus_addr *addr, time_t now);
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
diff --git a/src/forward.c b/src/forward.c
index 5163e87..27f619b 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -234,7 +234,8 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp,
static int forward_query(int udpfd, union mysockaddr *udpaddr,
struct all_addr *dst_addr, unsigned int dst_iface,
- struct dns_header *header, size_t plen, time_t now, struct frec *forward)
+ struct dns_header *header, size_t plen, time_t now,
+ struct frec *forward, int ad_reqd)
{
char *domain = NULL;
int type = 0, norebind = 0;
@@ -331,6 +332,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
forward->flags |= FREC_NOREBIND;
if (header->hb4 & HB4_CD)
forward->flags |= FREC_CHECKING_DISABLED;
+ if (ad_reqd)
+ forward->flags |= FREC_AD_QUESTION;
#ifdef HAVE_DNSSEC
forward->work_counter = DNSSEC_WORK;
#endif
@@ -503,13 +506,15 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
}
static size_t process_reply(struct dns_header *header, time_t now, struct server *server, size_t n, int check_rebind,
- int no_cache, int cache_secure, int check_subnet, union mysockaddr *query_source)
+ int no_cache, int cache_secure, int ad_reqd, int check_subnet, union mysockaddr *query_source)
{
unsigned char *pheader, *sizep;
char **sets = 0;
int munged = 0, is_sign;
size_t plen;
+ (void)ad_reqd;
+
#ifdef HAVE_IPSET
/* Similar algorithm to search_servers. */
struct ipsets *ipset_pos;
@@ -535,15 +540,13 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)))
{
- if (!is_sign)
- {
- unsigned short udpsz;
- unsigned char *psave = sizep;
-
- GETSHORT(udpsz, sizep);
- if (udpsz > daemon->edns_pktsz)
- PUTSHORT(daemon->edns_pktsz, psave);
- }
+ unsigned short udpsz;
+ unsigned char *psave = sizep;
+
+ GETSHORT(udpsz, sizep);
+
+ if (!is_sign && udpsz > daemon->edns_pktsz)
+ PUTSHORT(daemon->edns_pktsz, psave);
if (check_subnet && !check_source(header, plen, pheader, query_source))
{
@@ -551,7 +554,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
return 0;
}
}
-
+
/* RFC 4035 sect 4.6 para 3 */
if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
header->hb4 &= ~HB4_AD;
@@ -619,7 +622,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
if (option_bool(OPT_DNSSEC_VALID))
header->hb4 &= ~HB4_AD;
- if (!(header->hb4 & HB4_CD) && cache_secure)
+ if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
header->hb4 |= HB4_AD;
#endif
@@ -705,7 +708,7 @@ void reply_query(int fd, int family, time_t now)
if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
{
header->hb3 &= ~(HB3_QR | HB3_TC);
- forward_query(-1, NULL, NULL, 0, header, nn, now, forward);
+ forward_query(-1, NULL, NULL, 0, header, nn, now, forward, 0);
return;
}
}
@@ -914,17 +917,17 @@ void reply_query(int fd, int family, time_t now)
cache_secure = 1;
else if (status == STAT_BOGUS)
no_cache_dnssec = 1;
-
- /* restore CD bit to the value in the query */
- if (forward->flags & FREC_CHECKING_DISABLED)
- header->hb4 |= HB4_CD;
- else
- header->hb4 &= ~HB4_CD;
}
-#endif
+#endif
+
+ /* restore CD bit to the value in the query */
+ if (forward->flags & FREC_CHECKING_DISABLED)
+ header->hb4 |= HB4_CD;
+ else
+ header->hb4 &= ~HB4_CD;
if ((nn = process_reply(header, now, server, (size_t)n, check_rebind, no_cache_dnssec, cache_secure,
- forward->flags & FREC_HAS_SUBNET, &forward->source)))
+ forward->flags & FREC_AD_QUESTION, forward->flags & FREC_HAS_SUBNET, &forward->source)))
{
header->id = htons(forward->orig_id);
header->hb4 |= HB4_RA; /* recursion if available */
@@ -1166,8 +1169,9 @@ void receive_query(struct listener *listen, time_t now)
else
#endif
{
+ int ad_reqd;
m = answer_request(header, ((char *) header) + daemon->packet_buff_sz, (size_t)n,
- dst_addr_4, netmask, now);
+ dst_addr_4, netmask, now, &ad_reqd);
if (m >= 1)
{
@@ -1176,7 +1180,7 @@ void receive_query(struct listener *listen, time_t now)
daemon->local_answer++;
}
else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
- header, (size_t)n, now, NULL))
+ header, (size_t)n, now, NULL, ad_reqd))
daemon->queries_forwarded++;
else
daemon->local_answer++;
@@ -1268,7 +1272,7 @@ unsigned char *tcp_request(int confd, time_t now,
#ifdef HAVE_AUTH
int local_auth = 0;
#endif
- int checking_disabled, check_subnet, no_cache_dnssec = 0, cache_secure = 0;
+ int checking_disabled, ad_question, check_subnet, no_cache_dnssec = 0, cache_secure = 0;
size_t m;
unsigned short qtype;
unsigned int gotname;
@@ -1346,7 +1350,7 @@ unsigned char *tcp_request(int confd, time_t now,
{
/* m > 0 if answered from cache */
m = answer_request(header, ((char *) header) + 65536, (size_t)size,
- dst_addr_4, netmask, now);
+ dst_addr_4, netmask, now, &ad_question);
/* Do this by steam now we're not in the select() loop */
check_log_writer(NULL);
@@ -1526,7 +1530,7 @@ unsigned char *tcp_request(int confd, time_t now,
m = process_reply(header, now, last_server, (unsigned int)m,
option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec,
- cache_secure, check_subnet, &peer_addr);
+ cache_secure, ad_question, check_subnet, &peer_addr);
break;
}
diff --git a/src/rfc1035.c b/src/rfc1035.c
index e0bf47e..c58b9ff 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1452,7 +1452,8 @@ static unsigned long crec_ttl(struct crec *crecp, time_t now)
/* return zero if we can't answer from cache, or packet size if we can */
size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
- struct in_addr local_addr, struct in_addr local_netmask, time_t now)
+ struct in_addr local_addr, struct in_addr local_netmask,
+ time_t now, int *ad_reqd)
{
char *name = daemon->namebuff;
unsigned char *p, *ansp, *pheader;
@@ -1471,7 +1472,10 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
/* Don't return AD set if checking disabled. */
if (header->hb4 & HB4_CD)
sec_data = 0;
-
+
+ /* RFC 6840 5.7 */
+ *ad_reqd = header->hb4 & HB4_AD;
+
/* If there is an RFC2671 pseudoheader then it will be overwritten by
partial replies, so we have to do a dry run to see if we can answer
the query. We check to see if the do bit is set, if so we always
@@ -1490,6 +1494,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
GETSHORT(flags, pheader);
sec_reqd = flags & 0x8000; /* do bit */
+ *ad_reqd = 1;
/* If our client is advertising a larger UDP packet size
than we allow, trim it so that we don't get an overlarge
@@ -2257,19 +2262,15 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
header->nscount = htons(0);
header->arcount = htons(addncount);
- /* RFC 6840 5.7 */
- if (header->hb4 & HB4_AD)
- sec_reqd = 1;
-
- header->hb4 &= ~HB4_AD;
-
len = ansp - (unsigned char *)header;
if (have_pseudoheader)
len = add_pseudoheader(header, len, (unsigned char *)limit, 0, NULL, 0, sec_reqd);
- if (sec_reqd && sec_data)
+ if (*ad_reqd && sec_data)
header->hb4 |= HB4_AD;
+ else
+ header->hb4 &= ~HB4_AD;
return len;
}