1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-09-01 14:17:37 +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_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_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_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; } DnsAnswerFlags;
struct DnsAnswerItem { 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); 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( static int dns_stub_collect_answer_by_question(
DnsAnswer **reply, DnsAnswer **reply,
DnsAnswer *answer, DnsAnswer *answer,
DnsQuestion *question, DnsQuestion *question,
bool with_rrsig) { /* Add RRSIG RR matching each RR */ bool with_rrsig) { /* Add RRSIG RR matching each RR */
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *redirected_key = NULL;
DnsAnswerItem *item; DnsAnswerItem *item;
int r; 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'. */ /* Copies all RRs from 'answer' into 'reply', if they match 'question'. */
DNS_ANSWER_FOREACH_ITEM(item, answer) { DNS_ANSWER_FOREACH_ITEM(item, answer) {
if (question) { if (question) {
bool match = false;
r = dns_question_matches_rr(question, item->rr, NULL); r = dns_question_matches_rr(question, item->rr, NULL);
if (r < 0) if (r < 0)
return r; return r;
else if (r > 0) if (r == 0) {
match = true; _cleanup_free_ char *target = NULL;
else {
r = dns_question_matches_cname_or_dname(question, item->rr, 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) if (r < 0)
return r; return r;
if (r > 0)
match = true;
}
if (!match) dns_resource_key_unref(redirected_key);
continue;
/* 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) if (r < 0)
return r; return r;
}
if (with_rrsig && item->rrsig) { if (!redirected_key)
r = dns_answer_add_extend(reply, item->rrsig, item->ifindex, item->flags, NULL); return 0;
if (r < 0)
return r; /* 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; return 0;
@ -197,7 +258,6 @@ static int dns_stub_collect_answer_by_section(
bool with_dnssec) { /* Include DNSSEC RRs. RRSIG, NSEC, … */ bool with_dnssec) { /* Include DNSSEC RRs. RRSIG, NSEC, … */
DnsAnswerItem *item; DnsAnswerItem *item;
unsigned c = 0;
int r; int r;
assert(reply); 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) if (((item->flags ^ section) & (DNS_ANSWER_SECTION_ANSWER|DNS_ANSWER_SECTION_AUTHORITY|DNS_ANSWER_SECTION_ADDITIONAL)) != 0)
continue; 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) if (r < 0)
return r; 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( static int dns_stub_assign_sections(