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:
@ -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 {
|
||||||
|
@ -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(
|
||||||
|
Reference in New Issue
Block a user