Commit 83349b8a authored by Simon Kelley's avatar Simon Kelley

Further tidying of AD and DO bit handling.

parent 7fa836e1
...@@ -539,6 +539,7 @@ struct hostsfile { ...@@ -539,6 +539,7 @@ struct hostsfile {
#define FREC_HAS_SUBNET 4 #define FREC_HAS_SUBNET 4
#define FREC_DNSKEY_QUERY 8 #define FREC_DNSKEY_QUERY 8
#define FREC_DS_QUERY 16 #define FREC_DS_QUERY 16
#define FREC_AD_QUESTION 32
#ifdef HAVE_DNSSEC #ifdef HAVE_DNSSEC
#define HASH_SIZE 20 /* SHA-1 digest size */ #define HASH_SIZE 20 /* SHA-1 digest size */
...@@ -1041,7 +1042,8 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff, ...@@ -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, time_t now, char **ipsets, int is_sign, int checkrebind,
int no_cache, int secure, int *doctored); int no_cache, int secure, int *doctored);
size_t answer_request(struct dns_header *header, char *limit, size_t qlen, 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, int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
struct bogus_addr *addr, time_t now); struct bogus_addr *addr, time_t now);
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
......
...@@ -234,7 +234,8 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp, ...@@ -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, static int forward_query(int udpfd, union mysockaddr *udpaddr,
struct all_addr *dst_addr, unsigned int dst_iface, 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; char *domain = NULL;
int type = 0, norebind = 0; int type = 0, norebind = 0;
...@@ -331,6 +332,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, ...@@ -331,6 +332,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
forward->flags |= FREC_NOREBIND; forward->flags |= FREC_NOREBIND;
if (header->hb4 & HB4_CD) if (header->hb4 & HB4_CD)
forward->flags |= FREC_CHECKING_DISABLED; forward->flags |= FREC_CHECKING_DISABLED;
if (ad_reqd)
forward->flags |= FREC_AD_QUESTION;
#ifdef HAVE_DNSSEC #ifdef HAVE_DNSSEC
forward->work_counter = DNSSEC_WORK; forward->work_counter = DNSSEC_WORK;
#endif #endif
...@@ -503,13 +506,15 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, ...@@ -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, 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; unsigned char *pheader, *sizep;
char **sets = 0; char **sets = 0;
int munged = 0, is_sign; int munged = 0, is_sign;
size_t plen; size_t plen;
(void)ad_reqd;
#ifdef HAVE_IPSET #ifdef HAVE_IPSET
/* Similar algorithm to search_servers. */ /* Similar algorithm to search_servers. */
struct ipsets *ipset_pos; struct ipsets *ipset_pos;
...@@ -534,16 +539,14 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server ...@@ -534,16 +539,14 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
requests for the client. We can't do this for signed packets. */ requests for the client. We can't do this for signed packets. */
if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign))) if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)))
{
if (!is_sign)
{ {
unsigned short udpsz; unsigned short udpsz;
unsigned char *psave = sizep; unsigned char *psave = sizep;
GETSHORT(udpsz, sizep); GETSHORT(udpsz, sizep);
if (udpsz > daemon->edns_pktsz)
if (!is_sign && udpsz > daemon->edns_pktsz)
PUTSHORT(daemon->edns_pktsz, psave); PUTSHORT(daemon->edns_pktsz, psave);
}
if (check_subnet && !check_source(header, plen, pheader, query_source)) if (check_subnet && !check_source(header, plen, pheader, query_source))
{ {
...@@ -619,7 +622,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server ...@@ -619,7 +622,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
if (option_bool(OPT_DNSSEC_VALID)) if (option_bool(OPT_DNSSEC_VALID))
header->hb4 &= ~HB4_AD; header->hb4 &= ~HB4_AD;
if (!(header->hb4 & HB4_CD) && cache_secure) if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
header->hb4 |= HB4_AD; header->hb4 |= HB4_AD;
#endif #endif
...@@ -705,7 +708,7 @@ void reply_query(int fd, int family, time_t now) ...@@ -705,7 +708,7 @@ void reply_query(int fd, int family, time_t now)
if ((nn = resize_packet(header, (size_t)n, pheader, plen))) if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
{ {
header->hb3 &= ~(HB3_QR | HB3_TC); 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; return;
} }
} }
...@@ -914,17 +917,17 @@ void reply_query(int fd, int family, time_t now) ...@@ -914,17 +917,17 @@ void reply_query(int fd, int family, time_t now)
cache_secure = 1; cache_secure = 1;
else if (status == STAT_BOGUS) else if (status == STAT_BOGUS)
no_cache_dnssec = 1; no_cache_dnssec = 1;
}
#endif
/* restore CD bit to the value in the query */ /* restore CD bit to the value in the query */
if (forward->flags & FREC_CHECKING_DISABLED) if (forward->flags & FREC_CHECKING_DISABLED)
header->hb4 |= HB4_CD; header->hb4 |= HB4_CD;
else else
header->hb4 &= ~HB4_CD; header->hb4 &= ~HB4_CD;
}
#endif
if ((nn = process_reply(header, now, server, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, 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->id = htons(forward->orig_id);
header->hb4 |= HB4_RA; /* recursion if available */ header->hb4 |= HB4_RA; /* recursion if available */
...@@ -1166,8 +1169,9 @@ void receive_query(struct listener *listen, time_t now) ...@@ -1166,8 +1169,9 @@ void receive_query(struct listener *listen, time_t now)
else else
#endif #endif
{ {
int ad_reqd;
m = answer_request(header, ((char *) header) + daemon->packet_buff_sz, (size_t)n, 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) if (m >= 1)
{ {
...@@ -1176,7 +1180,7 @@ void receive_query(struct listener *listen, time_t now) ...@@ -1176,7 +1180,7 @@ void receive_query(struct listener *listen, time_t now)
daemon->local_answer++; daemon->local_answer++;
} }
else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index, 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++; daemon->queries_forwarded++;
else else
daemon->local_answer++; daemon->local_answer++;
...@@ -1268,7 +1272,7 @@ unsigned char *tcp_request(int confd, time_t now, ...@@ -1268,7 +1272,7 @@ unsigned char *tcp_request(int confd, time_t now,
#ifdef HAVE_AUTH #ifdef HAVE_AUTH
int local_auth = 0; int local_auth = 0;
#endif #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; size_t m;
unsigned short qtype; unsigned short qtype;
unsigned int gotname; unsigned int gotname;
...@@ -1346,7 +1350,7 @@ unsigned char *tcp_request(int confd, time_t now, ...@@ -1346,7 +1350,7 @@ unsigned char *tcp_request(int confd, time_t now,
{ {
/* m > 0 if answered from cache */ /* m > 0 if answered from cache */
m = answer_request(header, ((char *) header) + 65536, (size_t)size, 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 */ /* Do this by steam now we're not in the select() loop */
check_log_writer(NULL); check_log_writer(NULL);
...@@ -1526,7 +1530,7 @@ unsigned char *tcp_request(int confd, time_t now, ...@@ -1526,7 +1530,7 @@ unsigned char *tcp_request(int confd, time_t now,
m = process_reply(header, now, last_server, (unsigned int)m, m = process_reply(header, now, last_server, (unsigned int)m,
option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec,
cache_secure, check_subnet, &peer_addr); cache_secure, ad_question, check_subnet, &peer_addr);
break; break;
} }
......
...@@ -1452,7 +1452,8 @@ static unsigned long crec_ttl(struct crec *crecp, time_t now) ...@@ -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 */ /* 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, 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; char *name = daemon->namebuff;
unsigned char *p, *ansp, *pheader; unsigned char *p, *ansp, *pheader;
...@@ -1472,6 +1473,9 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ...@@ -1472,6 +1473,9 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if (header->hb4 & HB4_CD) if (header->hb4 & HB4_CD)
sec_data = 0; 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 /* 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 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 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, ...@@ -1490,6 +1494,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
GETSHORT(flags, pheader); GETSHORT(flags, pheader);
sec_reqd = flags & 0x8000; /* do bit */ sec_reqd = flags & 0x8000; /* do bit */
*ad_reqd = 1;
/* If our client is advertising a larger UDP packet size /* If our client is advertising a larger UDP packet size
than we allow, trim it so that we don't get an overlarge 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, ...@@ -2257,19 +2262,15 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
header->nscount = htons(0); header->nscount = htons(0);
header->arcount = htons(addncount); 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; len = ansp - (unsigned char *)header;
if (have_pseudoheader) if (have_pseudoheader)
len = add_pseudoheader(header, len, (unsigned char *)limit, 0, NULL, 0, sec_reqd); 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; header->hb4 |= HB4_AD;
else
header->hb4 &= ~HB4_AD;
return len; return len;
} }
......
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