1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-25 23:21:33 +03:00

resolved: stick CNAME targets into main answer section in stub replies

This commit is contained in:
Lennart Poettering 2021-02-22 23:07:57 +01:00
parent d1f8fbea9f
commit 5bd7ebb332
2 changed files with 91 additions and 31 deletions

View File

@ -22,6 +22,10 @@ typedef enum DnsAnswerFlags {
DNS_ANSWER_SECTION_ANSWER = 1 << 5, /* When parsing: RR originates from answer section */
DNS_ANSWER_SECTION_AUTHORITY = 1 << 6, /* When parsing: RR originates from authority section */
DNS_ANSWER_SECTION_ADDITIONAL = 1 << 7, /* When parsing: RR originates from additional section */
DNS_ANSWER_MASK_SECTIONS = DNS_ANSWER_SECTION_ANSWER|
DNS_ANSWER_SECTION_AUTHORITY|
DNS_ANSWER_SECTION_ADDITIONAL,
} DnsAnswerFlags;
struct DnsAnswerItem {

View File

@ -139,12 +139,38 @@ static int stub_packet_compare_func(const DnsPacket *x, const DnsPacket *y) {
DEFINE_HASH_OPS(stub_packet_hash_ops, DnsPacket, stub_packet_hash_func, stub_packet_compare_func);
static int reply_add_with_rrsig(
DnsAnswer **reply,
DnsResourceRecord *rr,
int ifindex,
DnsAnswerFlags flags,
DnsResourceRecord *rrsig,
bool with_rrsig) {
int r;
assert(reply);
assert(rr);
r = dns_answer_add_extend(reply, rr, ifindex, flags, rrsig);
if (r < 0)
return r;
if (with_rrsig && rrsig) {
r = dns_answer_add_extend(reply, rrsig, ifindex, flags, NULL);
if (r < 0)
return r;
}
return 0;
}
static int dns_stub_collect_answer_by_question(
DnsAnswer **reply,
DnsAnswer *answer,
DnsQuestion *question,
bool with_rrsig) { /* Add RRSIG RR matching each RR */
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *redirected_key = NULL;
DnsAnswerItem *item;
int r;
@ -153,36 +179,71 @@ static int dns_stub_collect_answer_by_question(
/* Copies all RRs from 'answer' into 'reply', if they match 'question'. */
DNS_ANSWER_FOREACH_ITEM(item, answer) {
if (question) {
bool match = false;
r = dns_question_matches_rr(question, item->rr, NULL);
if (r < 0)
return r;
else if (r > 0)
match = true;
else {
r = dns_question_matches_cname_or_dname(question, item->rr, NULL);
if (r == 0) {
_cleanup_free_ char *target = NULL;
/* OK, so the RR doesn't directly match. Let's see if the RR is a matching
* CNAME or DNAME */
r = dns_resource_record_get_cname_target(
question->keys[0],
item->rr,
&target);
if (r == -EUNATCH)
continue; /* Not a CNAME/DNAME or doesn't match */
if (r < 0)
return r;
if (r > 0)
match = true;
}
if (!match)
continue;
dns_resource_key_unref(redirected_key);
/* There can only be one CNAME per name, hence no point in storing more than one here */
redirected_key = dns_resource_key_new(question->keys[0]->class, question->keys[0]->type, target);
if (!redirected_key)
return -ENOMEM;
}
}
r = dns_answer_add_extend(reply, item->rr, item->ifindex, item->flags, item->rrsig);
/* Mask the section info, we want the primary answers to always go without section info, so
* that it is added to the answer section when we synthesize a reply. */
r = reply_add_with_rrsig(
reply,
item->rr,
item->ifindex,
item->flags & ~DNS_ANSWER_MASK_SECTIONS,
item->rrsig,
with_rrsig);
if (r < 0)
return r;
}
if (with_rrsig && item->rrsig) {
r = dns_answer_add_extend(reply, item->rrsig, item->ifindex, item->flags, NULL);
if (r < 0)
return r;
}
if (!redirected_key)
return 0;
/* This is a CNAME/DNAME answer. In this case also append where the redirections point to to the main
* answer section */
DNS_ANSWER_FOREACH_ITEM(item, answer) {
r = dns_resource_key_match_rr(redirected_key, item->rr, NULL);
if (r < 0)
return r;
if (r == 0)
continue;
r = reply_add_with_rrsig(
reply,
item->rr,
item->ifindex,
item->flags & ~DNS_ANSWER_MASK_SECTIONS,
item->rrsig,
with_rrsig);
if (r < 0)
return r;
}
return 0;
@ -197,7 +258,6 @@ static int dns_stub_collect_answer_by_section(
bool with_dnssec) { /* Include DNSSEC RRs. RRSIG, NSEC, … */
DnsAnswerItem *item;
unsigned c = 0;
int r;
assert(reply);
@ -218,22 +278,18 @@ static int dns_stub_collect_answer_by_section(
if (((item->flags ^ section) & (DNS_ANSWER_SECTION_ANSWER|DNS_ANSWER_SECTION_AUTHORITY|DNS_ANSWER_SECTION_ADDITIONAL)) != 0)
continue;
r = dns_answer_add_extend(reply, item->rr, item->ifindex, item->flags, item->rrsig);
r = reply_add_with_rrsig(
reply,
item->rr,
item->ifindex,
item->flags,
item->rrsig,
with_dnssec);
if (r < 0)
return r;
c++;
if (with_dnssec && item->rrsig) {
r = dns_answer_add_extend(reply, item->rrsig, item->ifindex, item->flags, NULL);
if (r < 0)
return r;
c++;
}
}
return (int) c;
return 0;
}
static int dns_stub_assign_sections(