diff options
author | Simon Kelley <simon@thekelleys.org.uk> | 2014-02-04 22:03:06 +0000 |
---|---|---|
committer | Simon Kelley <simon@thekelleys.org.uk> | 2014-02-04 22:03:06 +0000 |
commit | 12fae49fff5c42675ab4f130edea9e3a6ca73ba6 (patch) | |
tree | 8df9d993381c587dae00ea5f8d4386e4a4fc5606 | |
parent | fd372273bde910735f6117461f070fe8b250158b (diff) | |
download | dnsmasq-12fae49fff5c42675ab4f130edea9e3a6ca73ba6.tar.gz |
Make RR work when returning A/AAAA records and an RRSIG.
-rw-r--r-- | src/cache.c | 9 | ||||
-rw-r--r-- | src/dnsmasq.h | 5 | ||||
-rw-r--r-- | src/rfc1035.c | 43 |
3 files changed, 31 insertions, 26 deletions
diff --git a/src/cache.c b/src/cache.c index ba53837..19a5d61 100644 --- a/src/cache.c +++ b/src/cache.c @@ -592,10 +592,13 @@ void cache_end_insert(void) new_chain = NULL; } -struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned short prot) +struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned int prot) { struct crec *ans; + int no_rr = prot & F_NO_RR; + prot &= ~F_NO_RR; + if (crecp) /* iterating */ ans = crecp->next; else @@ -643,7 +646,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi } else { - if (!insert) + if (!insert && !no_rr) { insert = up; ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL); @@ -683,7 +686,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi } struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr, - time_t now, unsigned short prot) + time_t now, unsigned int prot) { struct crec *ans; #ifdef HAVE_IPV6 diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 5317ea3..58a4fe2 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -423,6 +423,7 @@ struct crec { #define F_DNSSEC (1u<<22) #define F_KEYTAG (1u<<23) #define F_SECSTAT (1u<<24) +#define F_NO_RR (1u<<25) /* struct sockaddr is not large enough to hold any address, @@ -993,9 +994,9 @@ char *record_source(int index); void querystr(char *desc, char *str, unsigned short type); struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr, time_t now, - unsigned short prot); + unsigned int prot); struct crec *cache_find_by_name(struct crec *crecp, - char *name, time_t now, unsigned short prot); + char *name, time_t now, unsigned int prot); void cache_end_insert(void); void cache_start_insert(void); struct crec *cache_insert(char *name, struct all_addr *addr, diff --git a/src/rfc1035.c b/src/rfc1035.c index a50b7d9..26cda15 100644 --- a/src/rfc1035.c +++ b/src/rfc1035.c @@ -1242,7 +1242,7 @@ int check_for_local_domain(char *name, time_t now) struct ptr_record *ptr; struct naptr *naptr; - if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME)) && + if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_NO_RR)) && (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))) return 1; @@ -1742,24 +1742,25 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, else if (crecp->flags & F_DNSSECOK) { int gotsig = 0; - - crecp = NULL; - while ((crecp = cache_find_by_name(crecp, name, now, F_DS | F_DNSKEY))) + struct crec *rr_crec = NULL; + + while ((rr_crec = cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY))) { - if (crecp->addr.sig.type_covered == T_PTR && crecp->uid == C_IN) + if (rr_crec->addr.sig.type_covered == T_PTR && rr_crec->uid == C_IN) { - char *sigdata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL); + char *sigdata = blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec->addr.sig.keylen, NULL); gotsig = 1; if (!dryrun && add_resource_record(header, limit, &trunc, nameoffset, &ansp, - crecp->ttd - now, &nameoffset, + rr_crec->ttd - now, &nameoffset, T_RRSIG, C_IN, "t", crecp->addr.sig.keylen, sigdata)) anscount++; } } - /* Need to re-run original cache search */ - crecp = gotsig ? cache_find_by_addr(NULL, &addr, now, is_arpa) : NULL; + + if (!gotsig) + crecp = NULL; } #endif } @@ -1923,7 +1924,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, } cname_restart: - if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME))) + if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME | (dryrun ? F_NO_RR : 0)))) { int localise = 0; @@ -1954,7 +1955,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, else if (crecp->flags & F_DNSSECOK) { /* We're returning validated data, need to return the RRSIG too. */ - + struct crec *rr_crec = NULL; int sigtype = type; /* The signature may have expired even though the data is still in cache, forward instead of answering from cache if so. */ @@ -1963,23 +1964,23 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, if (crecp->flags & F_CNAME) sigtype = T_CNAME; - crecp = NULL; - while ((crecp = cache_find_by_name(crecp, name, now, F_DS | F_DNSKEY))) + while ((rr_crec = cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY))) { - if (crecp->addr.sig.type_covered == sigtype && crecp->uid == C_IN) + if (rr_crec->addr.sig.type_covered == sigtype && rr_crec->uid == C_IN) { - char *sigdata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL); + char *sigdata = blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec->addr.sig.keylen, NULL); gotsig = 1; if (!dryrun && add_resource_record(header, limit, &trunc, nameoffset, &ansp, - crecp->ttd - now, &nameoffset, - T_RRSIG, C_IN, "t", crecp->addr.sig.keylen, sigdata)) + rr_crec->ttd - now, &nameoffset, + T_RRSIG, C_IN, "t", rr_crec->addr.sig.keylen, sigdata)) anscount++; } } - /* Need to re-run original cache search */ - crecp = gotsig ? cache_find_by_name(NULL, name, now, flag | F_CNAME) : NULL; + + if (!gotsig) + crecp = NULL; } #endif } @@ -2072,7 +2073,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, if (qtype == T_CNAME || qtype == T_ANY) { if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)) && - (qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))) + (qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG | (dryrun ? F_NO_RR : 0))))) { if (!(crecp->flags & F_DNSSECOK)) sec_data = 0; @@ -2111,7 +2112,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, } if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) && - cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP)) + cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP | F_NO_RR)) { ans = 1; if (!dryrun) |