diff options
author | Simon Kelley <simon@thekelleys.org.uk> | 2014-02-10 21:02:01 +0000 |
---|---|---|
committer | Simon Kelley <simon@thekelleys.org.uk> | 2014-02-10 21:02:01 +0000 |
commit | 83349b8aa4f8667f611918b9189446b0e93fc2bb (patch) | |
tree | cc1b22f105b7eca82424513d1390bd36cdc9c07e | |
parent | 7fa836e1055112845b5fc6be654381d55b41086d (diff) | |
download | dnsmasq-83349b8aa4f8667f611918b9189446b0e93fc2bb.tar.gz |
Further tidying of AD and DO bit handling.
-rw-r--r-- | src/dnsmasq.h | 4 | ||||
-rw-r--r-- | src/forward.c | 58 | ||||
-rw-r--r-- | src/rfc1035.c | 19 |
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; } |