Remove two-decade old hack.
answer_request() builds answers in the same packet buffer as the request. This means that any EDNS0 header from the original request is overwritten. If the answer is in cache, that's fine: dnsmasq adds its own EDNS0 header, but if the cache lookup fails partially and the request needs to be sent upstream, it's a problem. This was fixed a long, long time ago by running the cache lookup twice if the request included an EDNS0 header. The first time, nothing would be written to the answer packet, nad if the cache lookup failed, the untouched question packet was still available to forward upstream. If cache lookup succeeded, the whole thing was done again, this time writing the data into the reply packet. In a world where EDNS0 was rare and so was memory, this was a reasonable solution. Today EDNS0 is ubiquitous so basically every query is being looked up twice in the cache. There's also the problem that any code change which makes successive cache lookups for a query possibly return different answers adds a subtle hidden bug, because this hack depends on absence of that behaviour. This commit removes the lookup-twice hack entirely. answer_request() can now return zero and overwrite the question packet. The code which was previously added to support stale caching by saving a copy of the query in the block-storage system is extended to always be active. This handles the case where answer_request() returns no answer OR a stale answer and a copy of the original query is needed to forward upstream.
This commit is contained in:
parent
c03882667d
commit
829f9aa732
|
@ -1878,11 +1878,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||
int stale, filtered;
|
||||
int ad_reqd = do_bit;
|
||||
int fd = listen->fd;
|
||||
struct blockdata *saved_question = NULL;
|
||||
|
||||
/* In case answer is stale */
|
||||
if (daemon->cache_max_expiry != 0)
|
||||
saved_question = blockdata_alloc((char *) header, (size_t)n);
|
||||
struct blockdata *saved_question = blockdata_alloc((char *) header, (size_t)n);
|
||||
|
||||
/* RFC 6840 5.7 */
|
||||
if (header->hb4 & HB4_AD)
|
||||
|
@ -1954,11 +1950,10 @@ void receive_query(struct listener *listen, time_t now)
|
|||
daemon->metrics[METRIC_DNS_STALE_ANSWERED]++;
|
||||
}
|
||||
|
||||
if (stale && saved_question)
|
||||
if (stale)
|
||||
{
|
||||
/* We answered with stale cache data, so forward the query anyway to
|
||||
refresh that. Restore saved query. */
|
||||
blockdata_retrieve(saved_question, (size_t)n, header);
|
||||
refresh that. */
|
||||
m = 0;
|
||||
|
||||
/* We've already answered the client, so don't send it the answer
|
||||
|
@ -1966,15 +1961,20 @@ void receive_query(struct listener *listen, time_t now)
|
|||
fd = -1;
|
||||
}
|
||||
|
||||
blockdata_free(saved_question);
|
||||
|
||||
if (m == 0)
|
||||
if (saved_question)
|
||||
{
|
||||
if (forward_query(fd, &source_addr, &dst_addr, if_index,
|
||||
header, (size_t)n, ((char *) header) + udp_size, now, NULL, ad_reqd, do_bit, 0))
|
||||
daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++;
|
||||
else
|
||||
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
|
||||
if (m == 0)
|
||||
{
|
||||
blockdata_retrieve(saved_question, (size_t)n, header);
|
||||
|
||||
if (forward_query(fd, &source_addr, &dst_addr, if_index,
|
||||
header, (size_t)n, ((char *) header) + udp_size, now, NULL, ad_reqd, do_bit, 0))
|
||||
daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++;
|
||||
else
|
||||
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
|
||||
}
|
||||
|
||||
blockdata_free(saved_question);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2277,25 +2277,15 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
{
|
||||
int ede = EDE_UNSET;
|
||||
|
||||
if (do_stale)
|
||||
{
|
||||
/* We answered the last query with stale data. Now try and get fresh data.
|
||||
Restore saved query */
|
||||
if (!saved_question)
|
||||
break;
|
||||
|
||||
blockdata_retrieve(saved_question, (size_t)saved_size, header);
|
||||
size = saved_size;
|
||||
}
|
||||
else
|
||||
if (!do_stale)
|
||||
{
|
||||
if (query_count == TCP_MAX_QUERIES)
|
||||
return packet;
|
||||
|
||||
break;
|
||||
|
||||
if (!read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
|
||||
!(size = c1 << 8 | c2) ||
|
||||
!read_write(confd, payload, size, 1))
|
||||
return packet;
|
||||
break;
|
||||
}
|
||||
|
||||
if (size < (int)sizeof(struct dns_header))
|
||||
|
@ -2437,14 +2427,11 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
m = 0;
|
||||
else
|
||||
{
|
||||
if (daemon->cache_max_expiry != 0)
|
||||
{
|
||||
if (saved_question)
|
||||
blockdata_free(saved_question);
|
||||
|
||||
saved_question = blockdata_alloc((char *) header, (size_t)size);
|
||||
saved_size = size;
|
||||
}
|
||||
if (saved_question)
|
||||
blockdata_free(saved_question);
|
||||
|
||||
saved_question = blockdata_alloc((char *) header, (size_t)size);
|
||||
saved_size = size;
|
||||
|
||||
/* m > 0 if answered from cache */
|
||||
m = answer_request(header, ((char *) header) + 65536, (size_t)size,
|
||||
|
@ -2453,11 +2440,14 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
/* Do this by steam now we're not in the select() loop */
|
||||
check_log_writer(1);
|
||||
|
||||
if (m == 0)
|
||||
if (m == 0 && saved_question)
|
||||
{
|
||||
struct server *master;
|
||||
int start;
|
||||
|
||||
blockdata_retrieve(saved_question, (size_t)saved_size, header);
|
||||
size = saved_size;
|
||||
|
||||
if (lookup_domain(daemon->namebuff, gotname, &first, &last))
|
||||
flags = is_local_answer(now, first, daemon->namebuff);
|
||||
else
|
||||
|
@ -2622,7 +2612,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
break;
|
||||
|
||||
/* If we answered with stale data, this process will now try and get fresh data into
|
||||
the cache then and cannot therefore accept new queries. Close the incoming
|
||||
the cache and cannot therefore accept new queries. Close the incoming
|
||||
connection to signal that to the client. Then set do_stale and loop round
|
||||
once more to try and get fresh data, after which we exit. */
|
||||
if (stale)
|
||||
|
|
|
@ -1491,7 +1491,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
int nameoffset;
|
||||
unsigned short flag;
|
||||
int q, ans, anscount = 0, addncount = 0;
|
||||
int dryrun = 0;
|
||||
struct crec *crecp;
|
||||
int nxdomain = 0, notimp = 0, auth = 1, trunc = 0, sec_data = 1;
|
||||
struct mx_srv_record *rec;
|
||||
|
@ -1515,16 +1514,9 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
if (header->hb4 & HB4_CD)
|
||||
sec_data = 0;
|
||||
|
||||
/* If there is an additional data section then it will be overwritten by
|
||||
partial replies, so we have to do a dry run to see if we can answer
|
||||
the query. */
|
||||
if (ntohs(header->arcount) != 0)
|
||||
dryrun = 1;
|
||||
|
||||
for (rec = daemon->mxnames; rec; rec = rec->next)
|
||||
rec->offset = 0;
|
||||
|
||||
rerun:
|
||||
/* determine end of question section (we put answers there) */
|
||||
if (!(ansp = skip_questions(header, qlen)))
|
||||
return 0; /* bad packet */
|
||||
|
@ -1566,8 +1558,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
{
|
||||
if (qtype == T_CNAME)
|
||||
{
|
||||
if (!dryrun)
|
||||
log_query(stale_flag | crecp->flags, name, NULL, record_source(crecp->uid), 0);
|
||||
log_query(stale_flag | crecp->flags, name, NULL, record_source(crecp->uid), 0);
|
||||
auth = 0;
|
||||
nxdomain = 1;
|
||||
ans = 1;
|
||||
|
@ -1587,15 +1578,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
if (!(crecp->flags & F_DNSSECOK))
|
||||
sec_data = 0;
|
||||
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(stale_flag | crecp->flags, name, NULL, record_source(crecp->uid), 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), &nameoffset,
|
||||
T_CNAME, C_IN, "d", cname_target))
|
||||
anscount++;
|
||||
}
|
||||
|
||||
log_query(stale_flag | crecp->flags, name, NULL, record_source(crecp->uid), 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), &nameoffset,
|
||||
T_CNAME, C_IN, "d", cname_target))
|
||||
anscount++;
|
||||
}
|
||||
else
|
||||
return 0; /* give up if any cached CNAME in chain can't be used for DNSSEC reasons. */
|
||||
|
@ -1613,28 +1600,26 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
{
|
||||
if (t->class == qclass && hostname_isequal(name, t->name))
|
||||
{
|
||||
unsigned long ttl = daemon->local_ttl;
|
||||
int ok = 1;
|
||||
|
||||
ans = 1, sec_data = 0;
|
||||
if (!dryrun)
|
||||
{
|
||||
unsigned long ttl = daemon->local_ttl;
|
||||
int ok = 1;
|
||||
#ifndef NO_ID
|
||||
/* Dynamically generate stat record */
|
||||
if (t->stat != 0)
|
||||
{
|
||||
ttl = 0;
|
||||
if (!cache_make_stat(t))
|
||||
ok = 0;
|
||||
}
|
||||
/* Dynamically generate stat record */
|
||||
if (t->stat != 0)
|
||||
{
|
||||
ttl = 0;
|
||||
if (!cache_make_stat(t))
|
||||
ok = 0;
|
||||
}
|
||||
#endif
|
||||
if (ok)
|
||||
{
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
ttl, NULL,
|
||||
T_TXT, t->class, "t", t->len, t->txt))
|
||||
anscount++;
|
||||
}
|
||||
if (ok)
|
||||
{
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
ttl, NULL,
|
||||
T_TXT, t->class, "t", t->len, t->txt))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1648,11 +1633,10 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
if (!ans)
|
||||
{
|
||||
notimp = 1, auth = 0;
|
||||
if (!dryrun)
|
||||
{
|
||||
addr.log.rcode = NOTIMP;
|
||||
log_query(F_CONFIG | F_RCODE, name, &addr, NULL, 0);
|
||||
}
|
||||
|
||||
addr.log.rcode = NOTIMP;
|
||||
log_query(F_CONFIG | F_RCODE, name, &addr, NULL, 0);
|
||||
|
||||
ans = 1, sec_data = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1667,16 +1651,13 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
{
|
||||
ans = 1;
|
||||
sec_data = 0;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, NULL, t->class);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL,
|
||||
t->class, C_IN, "t", t->len, t->txt))
|
||||
anscount++;
|
||||
}
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, NULL, t->class);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL,
|
||||
t->class, C_IN, "t", t->len, t->txt))
|
||||
anscount++;
|
||||
}
|
||||
|
||||
|
||||
if (qtype == T_PTR || qtype == T_ANY)
|
||||
{
|
||||
/* see if it's w.z.y.z.in-addr.arpa format */
|
||||
|
@ -1723,30 +1704,24 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
{
|
||||
sec_data = 0;
|
||||
ans = 1;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(is_arpa | F_REVERSE | F_CONFIG, intr->name, &addr, NULL, 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL,
|
||||
T_PTR, C_IN, "d", intr->name))
|
||||
anscount++;
|
||||
}
|
||||
log_query(is_arpa | F_REVERSE | F_CONFIG, intr->name, &addr, NULL, 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL,
|
||||
T_PTR, C_IN, "d", intr->name))
|
||||
anscount++;
|
||||
}
|
||||
else if (ptr)
|
||||
{
|
||||
ans = 1;
|
||||
sec_data = 0;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<PTR>", 0);
|
||||
for (ptr = daemon->ptr; ptr; ptr = ptr->next)
|
||||
if (hostname_isequal(name, ptr->name) &&
|
||||
add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL,
|
||||
T_PTR, C_IN, "d", ptr->ptr))
|
||||
anscount++;
|
||||
|
||||
}
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<PTR>", 0);
|
||||
for (ptr = daemon->ptr; ptr; ptr = ptr->next)
|
||||
if (hostname_isequal(name, ptr->name) &&
|
||||
add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL,
|
||||
T_PTR, C_IN, "d", ptr->ptr))
|
||||
anscount++;
|
||||
|
||||
}
|
||||
else if (is_arpa && (crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
|
||||
{
|
||||
|
@ -1782,23 +1757,20 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
auth = 0;
|
||||
if (crecp->flags & F_NXDOMAIN)
|
||||
nxdomain = 1;
|
||||
if (!dryrun)
|
||||
log_query(stale_flag | (crecp->flags & ~F_FORWARD), name, &addr, NULL, 0);
|
||||
log_query(stale_flag | (crecp->flags & ~F_FORWARD), name, &addr, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
|
||||
auth = 0;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(stale_flag | (crecp->flags & ~F_FORWARD), cache_get_name(crecp), &addr,
|
||||
record_source(crecp->uid), 0);
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), NULL,
|
||||
T_PTR, C_IN, "d", cache_get_name(crecp)))
|
||||
anscount++;
|
||||
}
|
||||
|
||||
log_query(stale_flag | (crecp->flags & ~F_FORWARD), cache_get_name(crecp), &addr,
|
||||
record_source(crecp->uid), 0);
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), NULL,
|
||||
T_PTR, C_IN, "d", cache_get_name(crecp)))
|
||||
anscount++;
|
||||
}
|
||||
} while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa)));
|
||||
}
|
||||
|
@ -1807,15 +1779,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
{
|
||||
ans = 1;
|
||||
sec_data = 0;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(F_CONFIG | F_REVERSE | is_arpa, name, &addr, NULL, 0);
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL,
|
||||
T_PTR, C_IN, "d", name))
|
||||
anscount++;
|
||||
}
|
||||
log_query(F_CONFIG | F_REVERSE | is_arpa, name, &addr, NULL, 0);
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL,
|
||||
T_PTR, C_IN, "d", name))
|
||||
anscount++;
|
||||
}
|
||||
else if (option_bool(OPT_BOGUSPRIV) &&
|
||||
((is_arpa == F_IPV6 && private_net6(&addr.addr6, 1)) || (is_arpa == F_IPV4 && private_net(addr.addr4, 1))) &&
|
||||
|
@ -1825,9 +1794,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
ans = 1;
|
||||
sec_data = 0;
|
||||
nxdomain = 1;
|
||||
if (!dryrun)
|
||||
log_query(F_CONFIG | F_REVERSE | is_arpa | F_NEG | F_NXDOMAIN,
|
||||
name, &addr, NULL, 0);
|
||||
log_query(F_CONFIG | F_REVERSE | is_arpa | F_NEG | F_NXDOMAIN,
|
||||
name, &addr, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1879,25 +1847,22 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
|
||||
ans = 1;
|
||||
sec_data = 0;
|
||||
if (!dryrun)
|
||||
{
|
||||
gotit = 1;
|
||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL, 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL, type, C_IN,
|
||||
type == T_A ? "4" : "6", &addrlist->addr))
|
||||
anscount++;
|
||||
}
|
||||
gotit = 1;
|
||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL, 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL, type, C_IN,
|
||||
type == T_A ? "4" : "6", &addrlist->addr))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dryrun && !gotit)
|
||||
if (!gotit)
|
||||
log_query(F_FORWARD | F_CONFIG | flag | F_NEG, name, NULL, NULL, 0);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((crecp = cache_find_by_name(NULL, name, now, flag | F_NXDOMAIN | (dryrun ? F_NO_RR : 0))))
|
||||
if ((crecp = cache_find_by_name(NULL, name, now, flag | F_NXDOMAIN)))
|
||||
{
|
||||
int localise = 0;
|
||||
|
||||
|
@ -1950,8 +1915,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
ans = 1;
|
||||
sec_data = 0;
|
||||
|
||||
if (!dryrun)
|
||||
log_query(F_NEG | F_CONFIG | flag, name, NULL, NULL, 0);
|
||||
log_query(F_NEG | F_CONFIG | flag, name, NULL, NULL, 0);
|
||||
|
||||
if (filtered)
|
||||
*filtered = 1;
|
||||
|
@ -1962,10 +1926,10 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
auth = 0;
|
||||
if (crecp->flags & F_NXDOMAIN)
|
||||
nxdomain = 1;
|
||||
if (!dryrun)
|
||||
// Pi-hole modification: Added record_source(crecp->uid) such that the subroutines know
|
||||
// where the reply came from (e.g. gravity.list)
|
||||
log_query(stale_flag | crecp->flags, name, NULL, record_source(crecp->uid), 0);
|
||||
|
||||
log_query(stale_flag | crecp->flags, name, NULL, record_source(crecp->uid), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1977,65 +1941,57 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
continue;
|
||||
|
||||
ans = 1;
|
||||
if (!dryrun)
|
||||
log_query(stale_flag | (crecp->flags & ~F_REVERSE), name, &crecp->addr,
|
||||
record_source(crecp->uid), 0);
|
||||
// ****************************** Pi-hole modification ******************************
|
||||
const char *src = crecp != NULL ? crecp->flags & F_BIGNAME ? crecp->name.bname->name : crecp->name.sname : NULL;
|
||||
if(FTL_CNAME(name, src, daemon->log_display_id))
|
||||
{
|
||||
log_query(stale_flag | (crecp->flags & ~F_REVERSE), name, &crecp->addr,
|
||||
record_source(crecp->uid), 0);
|
||||
// ****************************** Pi-hole modification ******************************
|
||||
const char *src = crecp != NULL ? crecp->flags & F_BIGNAME ? crecp->name.bname->name : crecp->name.sname : NULL;
|
||||
if(FTL_CNAME(name, src, daemon->log_display_id))
|
||||
{
|
||||
// Served from cache. This can happen if a domain hidden in the CNAME path
|
||||
// is only blocked for some but not all clients. In this case, the entire
|
||||
// CNAME path may already be in the cache.
|
||||
// This query is to be blocked as we found a blocked domain while walking the CNAME path.
|
||||
// Log to pihole.log: "cached domainabc.com is blocked during CNAME inspection"
|
||||
log_query(F_UPSTREAM, name, NULL, "blocked during CNAME inspection", 0);
|
||||
break;
|
||||
}
|
||||
// **********************************************************************************
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), NULL, type, C_IN,
|
||||
type == T_A ? "4" : "6", &crecp->addr))
|
||||
anscount++;
|
||||
// Served from cache. This can happen if a domain hidden in the CNAME path
|
||||
// is only blocked for some but not all clients. In this case, the entire
|
||||
// CNAME path may already be in the cache.
|
||||
// This query is to be blocked as we found a blocked domain while walking the CNAME path.
|
||||
// Log to pihole.log: "cached domainabc.com is blocked during CNAME inspection"
|
||||
log_query(F_UPSTREAM, name, NULL, "blocked during CNAME inspection", 0);
|
||||
break;
|
||||
}
|
||||
// **********************************************************************************
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), NULL, type, C_IN,
|
||||
type == T_A ? "4" : "6", &crecp->addr))
|
||||
anscount++;
|
||||
}
|
||||
} while ((crecp = cache_find_by_name(crecp, name, now, flag)));
|
||||
}
|
||||
else if (is_name_synthetic(flag, name, &addr))
|
||||
{
|
||||
ans = 1, sec_data = 0;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL, 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL, type, C_IN, type == T_A ? "4" : "6", &addr))
|
||||
anscount++;
|
||||
}
|
||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL, 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL, type, C_IN, type == T_A ? "4" : "6", &addr))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (qtype == T_MX || qtype == T_ANY)
|
||||
{
|
||||
int found = 0;
|
||||
for (rec = daemon->mxnames; rec; rec = rec->next)
|
||||
if (!rec->issrv && hostname_isequal(name, rec->name))
|
||||
{
|
||||
int offset;
|
||||
|
||||
ans = found = 1;
|
||||
sec_data = 0;
|
||||
|
||||
if (!dryrun)
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||
&offset, T_MX, C_IN, "sd", rec->weight, rec->target))
|
||||
{
|
||||
int offset;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||
&offset, T_MX, C_IN, "sd", rec->weight, rec->target))
|
||||
{
|
||||
anscount++;
|
||||
if (rec->target)
|
||||
rec->offset = offset;
|
||||
}
|
||||
anscount++;
|
||||
if (rec->target)
|
||||
rec->offset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2044,14 +2000,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
{
|
||||
ans = 1;
|
||||
sec_data = 0;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL,
|
||||
T_MX, C_IN, "sd", 1,
|
||||
option_bool(OPT_SELFMX) ? name : daemon->mxtarget))
|
||||
anscount++;
|
||||
}
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL,
|
||||
T_MX, C_IN, "sd", 1,
|
||||
option_bool(OPT_SELFMX) ? name : daemon->mxtarget))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2062,20 +2015,18 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
for (rec = daemon->mxnames; rec; rec = rec->next)
|
||||
if (rec->issrv && hostname_isequal(name, rec->name))
|
||||
{
|
||||
int offset;
|
||||
|
||||
ans = 1;
|
||||
sec_data = 0;
|
||||
if (!dryrun)
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||
&offset, T_SRV, C_IN, "sssd",
|
||||
rec->priority, rec->weight, rec->srvport, rec->target))
|
||||
{
|
||||
int offset;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||
&offset, T_SRV, C_IN, "sssd",
|
||||
rec->priority, rec->weight, rec->srvport, rec->target))
|
||||
{
|
||||
anscount++;
|
||||
if (rec->target)
|
||||
rec->offset = offset;
|
||||
}
|
||||
anscount++;
|
||||
if (rec->target)
|
||||
rec->offset = offset;
|
||||
}
|
||||
|
||||
/* unlink first SRV record found */
|
||||
|
@ -2089,7 +2040,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
}
|
||||
else
|
||||
up = &rec->next;
|
||||
|
||||
|
||||
/* put first SRV record back at the end. */
|
||||
if (move)
|
||||
{
|
||||
|
@ -2106,14 +2057,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
{
|
||||
ans = 1;
|
||||
sec_data = 0;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||
NULL, T_NAPTR, C_IN, "sszzzd",
|
||||
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
|
||||
anscount++;
|
||||
}
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||
NULL, T_NAPTR, C_IN, "sszzzd",
|
||||
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2124,13 +2072,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
{
|
||||
ans = 1;
|
||||
sec_data = 0;
|
||||
if (!dryrun)
|
||||
log_query(F_CONFIG | F_NEG, name, &addr, NULL, 0);
|
||||
log_query(F_CONFIG | F_NEG, name, &addr, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
if (!ans)
|
||||
{
|
||||
if ((crecp = cache_find_by_name(NULL, name, now, F_RR | F_NXDOMAIN | (dryrun ? F_NO_RR : 0))) &&
|
||||
if ((crecp = cache_find_by_name(NULL, name, now, F_RR | F_NXDOMAIN)) &&
|
||||
rd_bit && (!do_bit || cache_validated(crecp)))
|
||||
do
|
||||
{
|
||||
|
@ -2144,7 +2091,10 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
|
||||
if ((flags & F_NXDOMAIN) || rrtype == qtype)
|
||||
{
|
||||
if (crec_isstale(crecp, now))
|
||||
char *rrdata = NULL;
|
||||
unsigned short rrlen = 0;
|
||||
|
||||
if (crec_isstale(crecp, now))
|
||||
{
|
||||
if (stale)
|
||||
*stale = 1;
|
||||
|
@ -2163,36 +2113,30 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
auth = 0;
|
||||
ans = 1;
|
||||
|
||||
if (!dryrun)
|
||||
if (!(flags & F_NEG))
|
||||
{
|
||||
char *rrdata = NULL;
|
||||
unsigned short rrlen = 0;
|
||||
|
||||
if (!(flags & F_NEG))
|
||||
if (flags & F_KEYTAG)
|
||||
{
|
||||
if (flags & F_KEYTAG)
|
||||
{
|
||||
rrlen = crecp->addr.rrblock.datalen;
|
||||
rrdata = blockdata_retrieve(crecp->addr.rrblock.rrdata, crecp->addr.rrblock.datalen, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
rrlen = crecp->addr.rrdata.datalen;
|
||||
rrdata = crecp->addr.rrdata.data;
|
||||
}
|
||||
rrlen = crecp->addr.rrblock.datalen;
|
||||
rrdata = blockdata_retrieve(crecp->addr.rrblock.rrdata, crecp->addr.rrblock.datalen, NULL);
|
||||
}
|
||||
|
||||
if (!(flags & F_NEG) && add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), NULL, qtype, C_IN, "t",
|
||||
rrlen, rrdata))
|
||||
anscount++;
|
||||
|
||||
/* log after cache insertion as log_txt mangles rrdata */
|
||||
if (qtype == T_TXT && !(crecp->flags & F_NEG))
|
||||
log_txt(name, (unsigned char *)rrdata, rrlen, crecp->flags & F_DNSSECOK);
|
||||
else
|
||||
log_query(flags, name, &crecp->addr, NULL, 0);
|
||||
{
|
||||
rrlen = crecp->addr.rrdata.datalen;
|
||||
rrdata = crecp->addr.rrdata.data;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & F_NEG) && add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
crec_ttl(crecp, now), NULL, qtype, C_IN, "t",
|
||||
rrlen, rrdata))
|
||||
anscount++;
|
||||
|
||||
/* log after cache insertion as log_txt mangles rrdata */
|
||||
if (qtype == T_TXT && !(crecp->flags & F_NEG))
|
||||
log_txt(name, (unsigned char *)rrdata, rrlen, crecp->flags & F_DNSSECOK);
|
||||
else
|
||||
log_query(flags, name, &crecp->addr, NULL, 0);
|
||||
}
|
||||
} while ((crecp = cache_find_by_name(crecp, name, now, F_RR)));
|
||||
}
|
||||
|
@ -2201,8 +2145,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
{
|
||||
ans = 1;
|
||||
sec_data = 0;
|
||||
if (!dryrun)
|
||||
log_query(F_CONFIG | F_NEG, name, NULL, NULL, 0);
|
||||
log_query(F_CONFIG | F_NEG, name, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2220,8 +2163,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
ans = 1;
|
||||
sec_data = auth = 0;
|
||||
|
||||
if (!dryrun)
|
||||
log_query(F_NEG | F_CONFIG | flag, name, NULL, NULL, 0);
|
||||
log_query(F_NEG | F_CONFIG | flag, name, NULL, NULL, 0);
|
||||
|
||||
if (filtered)
|
||||
*filtered = 1;
|
||||
|
@ -2233,12 +2175,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||
return 0; /* failed to answer a question */
|
||||
}
|
||||
|
||||
if (dryrun)
|
||||
{
|
||||
dryrun = 0;
|
||||
goto rerun;
|
||||
}
|
||||
|
||||
/* create an additional data section, for stuff in SRV and MX record replies. */
|
||||
for (rec = daemon->mxnames; rec; rec = rec->next)
|
||||
if (rec->offset != 0)
|
||||
|
|
Loading…
Reference in New Issue