1
0
mirror of https://github.com/systemd/systemd synced 2025-09-30 17:24:46 +02:00

Compare commits

..

No commits in common. "f963f8953daeab03b892616ce0c65f7572932187" and "01131684ac66e82faae18e40e110089003d7c536" have entirely different histories.

30 changed files with 641 additions and 1721 deletions

View File

@ -1926,13 +1926,6 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>UseFQDN=</varname></term>
<listitem>
<para>Equivalent of <varname>UseHostname=</varname> in the [DHCPv4] section.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>RouteMetric=</varname></term> <term><varname>RouteMetric=</varname></term>
<listitem> <listitem>

View File

@ -75,7 +75,6 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_LINK, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_LINK, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY), SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY),
SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN), SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SOURCE, ESRCH),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DNSSD_SERVICE, ENOENT), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DNSSD_SERVICE, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_DNSSD_SERVICE_EXISTS, EEXIST), SD_BUS_ERROR_MAP(BUS_ERROR_DNSSD_SERVICE_EXISTS, EEXIST),

View File

@ -73,7 +73,6 @@
#define BUS_ERROR_NO_SUCH_LINK "org.freedesktop.resolve1.NoSuchLink" #define BUS_ERROR_NO_SUCH_LINK "org.freedesktop.resolve1.NoSuchLink"
#define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy" #define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy"
#define BUS_ERROR_NETWORK_DOWN "org.freedesktop.resolve1.NetworkDown" #define BUS_ERROR_NETWORK_DOWN "org.freedesktop.resolve1.NetworkDown"
#define BUS_ERROR_NO_SOURCE "org.freedesktop.resolve1.NoSource"
#define BUS_ERROR_NO_SUCH_DNSSD_SERVICE "org.freedesktop.resolve1.NoSuchDnssdService" #define BUS_ERROR_NO_SUCH_DNSSD_SERVICE "org.freedesktop.resolve1.NoSuchDnssdService"
#define BUS_ERROR_DNSSD_SERVICE_EXISTS "org.freedesktop.resolve1.DnssdServiceExists" #define BUS_ERROR_DNSSD_SERVICE_EXISTS "org.freedesktop.resolve1.DnssdServiceExists"
#define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError." #define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError."

View File

@ -11,7 +11,6 @@
#include "escape.h" #include "escape.h"
#include "hashmap.h" #include "hashmap.h"
#include "hostname-setup.h"
#include "hostname-util.h" #include "hostname-util.h"
#include "missing_network.h" #include "missing_network.h"
#include "networkd-address.h" #include "networkd-address.h"
@ -1074,25 +1073,6 @@ static int dhcp6_address_acquired(Link *link) {
return r; return r;
} }
if (link->network->dhcp6_use_fqdn) {
const char *dhcpname = NULL;
_cleanup_free_ char *hostname = NULL;
(void) sd_dhcp6_lease_get_fqdn(link->dhcp6_lease, &dhcpname);
if (dhcpname) {
r = shorten_overlong(dhcpname, &hostname);
if (r < 0)
log_link_warning_errno(link, r, "Unable to shorten overlong DHCP hostname '%s', ignoring: %m", dhcpname);
if (r == 1)
log_link_notice(link, "Overlong DHCP hostname received, shortened from '%s' to '%s'", dhcpname, hostname);
}
if (hostname) {
r = manager_set_hostname(link->manager, hostname);
if (r < 0)
log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
}
}
return 0; return 0;
} }

View File

@ -223,7 +223,6 @@ DHCPv4.RouteMTUBytes, config_parse_mtu,
DHCPv4.FallbackLeaseLifetimeSec, config_parse_dhcp_fallback_lease_lifetime, 0, 0 DHCPv4.FallbackLeaseLifetimeSec, config_parse_dhcp_fallback_lease_lifetime, 0, 0
DHCPv6.UseAddress, config_parse_bool, 0, offsetof(Network, dhcp6_use_address) DHCPv6.UseAddress, config_parse_bool, 0, offsetof(Network, dhcp6_use_address)
DHCPv6.UseDNS, config_parse_dhcp_use_dns, 0, 0 DHCPv6.UseDNS, config_parse_dhcp_use_dns, 0, 0
DHCPv6.UseFQDN, config_parse_bool, 0, offsetof(Network, dhcp6_use_fqdn)
DHCPv6.UseNTP, config_parse_dhcp_use_ntp, 0, 0 DHCPv6.UseNTP, config_parse_dhcp_use_ntp, 0, 0
DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit) DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit)
DHCPv6.MUDURL, config_parse_dhcp6_mud_url, 0, 0 DHCPv6.MUDURL, config_parse_dhcp6_mud_url, 0, 0

View File

@ -374,7 +374,6 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.dhcp6_use_address = true, .dhcp6_use_address = true,
.dhcp6_use_dns = true, .dhcp6_use_dns = true,
.dhcp6_use_fqdn = true,
.dhcp6_use_ntp = true, .dhcp6_use_ntp = true,
.dhcp6_rapid_commit = true, .dhcp6_rapid_commit = true,
.dhcp6_route_metric = DHCP_ROUTE_METRIC, .dhcp6_route_metric = DHCP_ROUTE_METRIC,

View File

@ -159,7 +159,6 @@ struct Network {
bool dhcp6_use_address; bool dhcp6_use_address;
bool dhcp6_use_dns; bool dhcp6_use_dns;
bool dhcp6_use_dns_set; bool dhcp6_use_dns_set;
bool dhcp6_use_fqdn;
bool dhcp6_use_ntp; bool dhcp6_use_ntp;
bool dhcp6_use_ntp_set; bool dhcp6_use_ntp_set;
bool dhcp6_rapid_commit; bool dhcp6_rapid_commit;

View File

@ -101,9 +101,6 @@ static int reply_query_state(DnsQuery *q) {
* thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */ * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
return sd_bus_reply_method_errorf(q->bus_request, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q)); return sd_bus_reply_method_errorf(q->bus_request, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
case DNS_TRANSACTION_NO_SOURCE:
return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NO_SOURCE, "All suitable resolution sources turned off");
case DNS_TRANSACTION_RCODE_FAILURE: { case DNS_TRANSACTION_RCODE_FAILURE: {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@ -277,8 +274,8 @@ static int validate_and_mangle_flags(
* *
* 1. Checks that the interface index is either 0 (meaning *all* interfaces) or positive * 1. Checks that the interface index is either 0 (meaning *all* interfaces) or positive
* *
* 2. Only the protocols flags and a bunch of NO_XYZ flags are set, at most. Plus additional flags * 2. Only the protocols flags and the NO_CNAME flag are set, at most. Plus additional flags specific
* specific to our method, passed in the "ok" parameter. * to our method, passed in the "ok" parameter.
* *
* 3. If zero protocol flags are specified it is automatically turned into *all* protocols. This way * 3. If zero protocol flags are specified it is automatically turned into *all* protocols. This way
* clients can simply pass 0 as flags and all will work as it should. They can also use this so * clients can simply pass 0 as flags and all will work as it should. They can also use this so
@ -286,15 +283,7 @@ static int validate_and_mangle_flags(
* to mean "all supported protocols". * to mean "all supported protocols".
*/ */
if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL| if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
SD_RESOLVED_NO_CNAME|
SD_RESOLVED_NO_VALIDATE|
SD_RESOLVED_NO_SYNTHESIZE|
SD_RESOLVED_NO_CACHE|
SD_RESOLVED_NO_ZONE|
SD_RESOLVED_NO_TRUST_ANCHOR|
SD_RESOLVED_NO_NETWORK|
ok))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter"); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */ if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
@ -417,7 +406,7 @@ static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata,
if (r < 0 && r != -EALREADY) if (r < 0 && r != -EALREADY)
return r; return r;
r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, NULL, ifindex, flags); r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, ifindex, flags);
if (r < 0) if (r < 0)
return r; return r;
@ -559,7 +548,7 @@ static int bus_method_resolve_address(sd_bus_message *message, void *userdata, s
if (r < 0) if (r < 0)
return r; return r;
r = dns_query_new(m, &q, question, question, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH); r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
if (r < 0) if (r < 0)
return r; return r;
@ -735,12 +724,14 @@ static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd
if (r < 0) if (r < 0)
return r; return r;
/* Setting SD_RESOLVED_CLAMP_TTL: let's request that the TTL is fixed up for locally cached entries, r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
* after all we return it in the wire format blob. */
r = dns_query_new(m, &q, question, question, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH|SD_RESOLVED_CLAMP_TTL);
if (r < 0) if (r < 0)
return r; return r;
/* Let's request that the TTL is fixed up for locally cached entries, after all we return it in the wire format
* blob */
q->clamp_ttl = true;
q->bus_request = sd_bus_message_ref(message); q->bus_request = sd_bus_message_ref(message);
q->complete = bus_method_resolve_record_complete; q->complete = bus_method_resolve_record_complete;
@ -1097,7 +1088,7 @@ static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifin
if (r < 0) if (r < 0)
return r; return r;
r = dns_query_new(q->manager, &aux, question, question, NULL, ifindex, q->flags|SD_RESOLVED_NO_SEARCH); r = dns_query_new(q->manager, &aux, question, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
if (r < 0) if (r < 0)
return r; return r;
@ -1267,7 +1258,7 @@ static int bus_method_resolve_service(sd_bus_message *message, void *userdata, s
if (r < 0) if (r < 0)
return r; return r;
r = dns_query_new(m, &q, question_utf8, question_idna, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH); r = dns_query_new(m, &q, question_utf8, question_idna, ifindex, flags|SD_RESOLVED_NO_SEARCH);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -27,31 +27,6 @@
/* Output: Result is authenticated */ /* Output: Result is authenticated */
#define SD_RESOLVED_AUTHENTICATED (UINT64_C(1) << 9) #define SD_RESOLVED_AUTHENTICATED (UINT64_C(1) << 9)
/* Input: Don't DNSSEC validate request */
#define SD_RESOLVED_NO_VALIDATE (UINT64_C(1) << 10)
/* Input: Don't answer request from locally synthesized records (which includes /etc/hosts) */
#define SD_RESOLVED_NO_SYNTHESIZE (UINT64_C(1) << 11)
/* Input: Don't answer request from cache */
#define SD_RESOLVED_NO_CACHE (UINT64_C(1) << 12)
/* Input: Don't answer request from locally registered public LLMNR/mDNS RRs */
#define SD_RESOLVED_NO_ZONE (UINT64_C(1) << 13)
/* Input: Don't answer request from locally registered public LLMNR/mDNS RRs */
#define SD_RESOLVED_NO_TRUST_ANCHOR (UINT64_C(1) << 14)
/* Input: Don't go to network for this request */
#define SD_RESOLVED_NO_NETWORK (UINT64_C(1) << 15)
/* Input: Require that request is answered from a "primary" answer, i.e. not from RRs acquired as
* side-effect of a previous transaction */
#define SD_RESOLVED_REQUIRE_PRIMARY (UINT64_C(1) << 16)
/* Input: If reply is answered from cache, the TTLs will be adjusted by age of cache entry */
#define SD_RESOLVED_CLAMP_TTL (UINT64_C(1) << 17)
#define SD_RESOLVED_LLMNR (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6) #define SD_RESOLVED_LLMNR (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
#define SD_RESOLVED_MDNS (SD_RESOLVED_MDNS_IPV4|SD_RESOLVED_MDNS_IPV6) #define SD_RESOLVED_MDNS (SD_RESOLVED_MDNS_IPV4|SD_RESOLVED_MDNS_IPV6)
#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS) #define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS)

View File

@ -55,21 +55,20 @@ DnsAnswer *dns_answer_new(size_t n) {
a->n_ref = 1; a->n_ref = 1;
a->n_allocated = n; a->n_allocated = n;
a->set_items = TAKE_PTR(s); a->set_items = TAKE_PTR(s);
return a; return a;
} }
static void dns_answer_flush(DnsAnswer *a) { static void dns_answer_flush(DnsAnswer *a) {
DnsAnswerItem *item; DnsResourceRecord *rr;
if (!a) if (!a)
return; return;
a->set_items = set_free(a->set_items); a->set_items = set_free(a->set_items);
DNS_ANSWER_FOREACH_ITEM(item, a) { DNS_ANSWER_FOREACH(rr, a)
dns_resource_record_unref(item->rr); dns_resource_record_unref(rr);
dns_resource_record_unref(item->rrsig);
}
a->n_rrs = 0; a->n_rrs = 0;
} }
@ -83,13 +82,7 @@ static DnsAnswer *dns_answer_free(DnsAnswer *a) {
DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsAnswer, dns_answer, dns_answer_free); DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsAnswer, dns_answer, dns_answer_free);
static int dns_answer_add_raw( static int dns_answer_add_raw(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
DnsAnswer *a,
DnsResourceRecord *rr,
int ifindex,
DnsAnswerFlags flags,
DnsResourceRecord *rrsig) {
int r; int r;
assert(rr); assert(rr);
@ -104,7 +97,6 @@ static int dns_answer_add_raw(
.rr = rr, .rr = rr,
.ifindex = ifindex, .ifindex = ifindex,
.flags = flags, .flags = flags,
.rrsig = dns_resource_record_ref(rrsig),
}; };
r = set_put(a->set_items, &a->items[a->n_rrs]); r = set_put(a->set_items, &a->items[a->n_rrs]);
@ -120,16 +112,12 @@ static int dns_answer_add_raw(
} }
static int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) { static int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) {
DnsAnswerItem *item; DnsResourceRecord *rr;
int r; DnsAnswerFlags flags;
int ifindex, r;
DNS_ANSWER_FOREACH_ITEM(item, source) { DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, source) {
r = dns_answer_add_raw( r = dns_answer_add_raw(a, rr, ifindex, flags);
a,
item->rr,
item->ifindex,
item->flags,
item->rrsig);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -137,13 +125,7 @@ static int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) {
return 0; return 0;
} }
int dns_answer_add( int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
DnsAnswer *a,
DnsResourceRecord *rr,
int ifindex,
DnsAnswerFlags flags,
DnsResourceRecord *rrsig) {
DnsAnswerItem tmp, *exist; DnsAnswerItem tmp, *exist;
assert(rr); assert(rr);
@ -170,28 +152,22 @@ int dns_answer_add(
if (rr->ttl > exist->rr->ttl) { if (rr->ttl > exist->rr->ttl) {
dns_resource_record_unref(exist->rr); dns_resource_record_unref(exist->rr);
exist->rr = dns_resource_record_ref(rr); exist->rr = dns_resource_record_ref(rr);
/* Update RRSIG and RR at the same time */
if (rrsig) {
dns_resource_record_ref(rrsig);
dns_resource_record_unref(exist->rrsig);
exist->rrsig = rrsig;
}
} }
exist->flags |= flags; exist->flags |= flags;
return 0; return 0;
} }
return dns_answer_add_raw(a, rr, ifindex, flags, rrsig); return dns_answer_add_raw(a, rr, ifindex, flags);
} }
static int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) { static int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) {
DnsAnswerItem *item; DnsResourceRecord *rr;
int r; DnsAnswerFlags flags;
int ifindex, r;
DNS_ANSWER_FOREACH_ITEM(item, b) { DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, b) {
r = dns_answer_add(a, item->rr, item->ifindex, item->flags, item->rrsig); r = dns_answer_add(a, rr, ifindex, flags);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -199,13 +175,7 @@ static int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) {
return 0; return 0;
} }
int dns_answer_add_extend( int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
DnsAnswer **a,
DnsResourceRecord *rr,
int ifindex,
DnsAnswerFlags flags,
DnsResourceRecord *rrsig) {
int r; int r;
assert(a); assert(a);
@ -215,7 +185,7 @@ int dns_answer_add_extend(
if (r < 0) if (r < 0)
return r; return r;
return dns_answer_add(*a, rr, ifindex, flags, rrsig); return dns_answer_add(*a, rr, ifindex, flags);
} }
int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex) { int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex) {
@ -241,7 +211,7 @@ int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex
soa->soa.expire = 1; soa->soa.expire = 1;
soa->soa.minimum = ttl; soa->soa.minimum = ttl;
return dns_answer_add(a, soa, ifindex, DNS_ANSWER_AUTHENTICATED, NULL); return dns_answer_add(a, soa, ifindex, DNS_ANSWER_AUTHENTICATED);
} }
int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) { int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) {
@ -279,9 +249,10 @@ int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags
int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) { int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) {
DnsResourceRecord *i; DnsResourceRecord *i;
DNS_ANSWER_FOREACH(i, a) DNS_ANSWER_FOREACH(i, a) {
if (IN_SET(i->key->type, DNS_TYPE_NSEC, DNS_TYPE_NSEC3)) if (IN_SET(i->key->type, DNS_TYPE_NSEC, DNS_TYPE_NSEC3))
return true; return true;
}
return false; return false;
} }
@ -313,22 +284,7 @@ int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone) {
return false; return false;
} }
int dns_answer_contains(DnsAnswer *answer, DnsResourceRecord *rr) { int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) {
DnsResourceRecord *i;
DNS_ANSWER_FOREACH(i, answer)
if (dns_resource_record_equal(i, rr))
return true;
return false;
}
int dns_answer_find_soa(
DnsAnswer *a,
const DnsResourceKey *key,
DnsResourceRecord **ret,
DnsAnswerFlags *ret_flags) {
DnsResourceRecord *rr, *soa = NULL; DnsResourceRecord *rr, *soa = NULL;
DnsAnswerFlags rr_flags, soa_flags = 0; DnsAnswerFlags rr_flags, soa_flags = 0;
int r; int r;
@ -337,7 +293,7 @@ int dns_answer_find_soa(
/* For a SOA record we can never find a matching SOA record */ /* For a SOA record we can never find a matching SOA record */
if (key->type == DNS_TYPE_SOA) if (key->type == DNS_TYPE_SOA)
goto not_found; return 0;
DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a) { DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a) {
r = dns_resource_key_match_soa(key, rr->key); r = dns_resource_key_match_soa(key, rr->key);
@ -359,30 +315,17 @@ int dns_answer_find_soa(
} }
if (!soa) if (!soa)
goto not_found; return 0;
if (ret) if (ret)
*ret = soa; *ret = soa;
if (ret_flags) if (flags)
*ret_flags = soa_flags; *flags = soa_flags;
return 1; return 1;
not_found:
if (ret)
*ret = NULL;
if (ret_flags)
*ret_flags = 0;
return 0;
} }
int dns_answer_find_cname_or_dname( int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) {
DnsAnswer *a,
const DnsResourceKey *key,
DnsResourceRecord **ret,
DnsAnswerFlags *ret_flags) {
DnsResourceRecord *rr; DnsResourceRecord *rr;
DnsAnswerFlags rr_flags; DnsAnswerFlags rr_flags;
int r; int r;
@ -400,17 +343,12 @@ int dns_answer_find_cname_or_dname(
if (r > 0) { if (r > 0) {
if (ret) if (ret)
*ret = rr; *ret = rr;
if (ret_flags) if (flags)
*ret_flags = rr_flags; *flags = rr_flags;
return 1; return 1;
} }
} }
if (ret)
*ret = NULL;
if (ret_flags)
*ret_flags = 0;
return 0; return 0;
} }
@ -502,20 +440,21 @@ int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {
if ((*a)->n_ref > 1) { if ((*a)->n_ref > 1) {
_cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL; _cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL;
DnsAnswerItem *item; DnsAnswerFlags flags;
int ifindex;
copy = dns_answer_new((*a)->n_rrs); copy = dns_answer_new((*a)->n_rrs);
if (!copy) if (!copy)
return -ENOMEM; return -ENOMEM;
DNS_ANSWER_FOREACH_ITEM(item, *a) { DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a) {
r = dns_resource_key_equal(item->rr->key, key); r = dns_resource_key_equal(rr->key, key);
if (r < 0) if (r < 0)
return r; return r;
if (r > 0) if (r > 0)
continue; continue;
r = dns_answer_add_raw(copy, item->rr, item->ifindex, item->flags, item->rrsig); r = dns_answer_add_raw(copy, rr, ifindex, flags);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -540,8 +479,6 @@ int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {
/* Kill this entry */ /* Kill this entry */
dns_resource_record_unref((*a)->items[i].rr); dns_resource_record_unref((*a)->items[i].rr);
dns_resource_record_unref((*a)->items[i].rrsig);
memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1)); memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1));
(*a)->n_rrs--; (*a)->n_rrs--;
continue; continue;
@ -588,20 +525,21 @@ int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rm) {
if ((*a)->n_ref > 1) { if ((*a)->n_ref > 1) {
_cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL; _cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL;
DnsAnswerItem *item; DnsAnswerFlags flags;
int ifindex;
copy = dns_answer_new((*a)->n_rrs); copy = dns_answer_new((*a)->n_rrs);
if (!copy) if (!copy)
return -ENOMEM; return -ENOMEM;
DNS_ANSWER_FOREACH_ITEM(item, *a) { DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a) {
r = dns_resource_record_equal(item->rr, rm); r = dns_resource_record_equal(rr, rm);
if (r < 0) if (r < 0)
return r; return r;
if (r > 0) if (r > 0)
continue; continue;
r = dns_answer_add_raw(copy, item->rr, item->ifindex, item->flags, item->rrsig); r = dns_answer_add_raw(copy, rr, ifindex, flags);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -626,7 +564,6 @@ int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rm) {
/* Kill this entry */ /* Kill this entry */
dns_resource_record_unref((*a)->items[i].rr); dns_resource_record_unref((*a)->items[i].rr);
dns_resource_record_unref((*a)->items[i].rrsig);
memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1)); memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1));
(*a)->n_rrs--; (*a)->n_rrs--;
continue; continue;
@ -639,24 +576,19 @@ int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rm) {
return 1; return 1;
} }
int dns_answer_copy_by_key( int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags) {
DnsAnswer **a, DnsResourceRecord *rr_source;
DnsAnswer *source, int ifindex_source, r;
const DnsResourceKey *key, DnsAnswerFlags flags_source;
DnsAnswerFlags or_flags,
DnsResourceRecord *rrsig) {
DnsAnswerItem *item;
int r;
assert(a); assert(a);
assert(key); assert(key);
/* Copy all RRs matching the specified key from source into *a */ /* Copy all RRs matching the specified key from source into *a */
DNS_ANSWER_FOREACH_ITEM(item, source) { DNS_ANSWER_FOREACH_FULL(rr_source, ifindex_source, flags_source, source) {
r = dns_resource_key_equal(item->rr->key, key); r = dns_resource_key_equal(rr_source->key, key);
if (r < 0) if (r < 0)
return r; return r;
if (r == 0) if (r == 0)
@ -667,7 +599,7 @@ int dns_answer_copy_by_key(
if (r < 0) if (r < 0)
return r; return r;
r = dns_answer_add(*a, item->rr, item->ifindex, item->flags|or_flags, item->rrsig); r = dns_answer_add(*a, rr_source, ifindex_source, flags_source|or_flags);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -675,19 +607,14 @@ int dns_answer_copy_by_key(
return 0; return 0;
} }
int dns_answer_move_by_key( int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags) {
DnsAnswer **to,
DnsAnswer **from,
const DnsResourceKey *key,
DnsAnswerFlags or_flags,
DnsResourceRecord *rrsig) {
int r; int r;
assert(to); assert(to);
assert(from); assert(from);
assert(key); assert(key);
r = dns_answer_copy_by_key(to, *from, key, or_flags, rrsig); r = dns_answer_copy_by_key(to, *from, key, or_flags);
if (r < 0) if (r < 0)
return r; return r;
@ -817,17 +744,19 @@ int dns_answer_reserve_or_clone(DnsAnswer **a, size_t n_free) {
* This function is not used in the code base, but is useful when debugging. Do not delete. * This function is not used in the code base, but is useful when debugging. Do not delete.
*/ */
void dns_answer_dump(DnsAnswer *answer, FILE *f) { void dns_answer_dump(DnsAnswer *answer, FILE *f) {
DnsAnswerItem *item; DnsResourceRecord *rr;
DnsAnswerFlags flags;
int ifindex;
if (!f) if (!f)
f = stdout; f = stdout;
DNS_ANSWER_FOREACH_ITEM(item, answer) { DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer) {
const char *t; const char *t;
fputc('\t', f); fputc('\t', f);
t = dns_resource_record_to_string(item->rr); t = dns_resource_record_to_string(rr);
if (!t) { if (!t) {
log_oom(); log_oom();
continue; continue;
@ -835,29 +764,21 @@ void dns_answer_dump(DnsAnswer *answer, FILE *f) {
fputs(t, f); fputs(t, f);
if (item->ifindex != 0 || item->rrsig || item->flags != 0) if (ifindex != 0 || flags != 0)
fputs("\t;", f); fputs("\t;", f);
if (item->ifindex != 0) if (ifindex != 0)
fprintf(f, " ifindex=%i", item->ifindex); fprintf(f, " ifindex=%i", ifindex);
if (item->rrsig) if (flags & DNS_ANSWER_AUTHENTICATED)
fputs(" rrsig", f);
if (item->flags & DNS_ANSWER_AUTHENTICATED)
fputs(" authenticated", f); fputs(" authenticated", f);
if (item->flags & DNS_ANSWER_CACHEABLE) if (flags & DNS_ANSWER_CACHEABLE)
fputs(" cacheable", f); fputs(" cacheable", f);
if (item->flags & DNS_ANSWER_SHARED_OWNER) if (flags & DNS_ANSWER_SHARED_OWNER)
fputs(" shared-owner", f); fputs(" shared-owner", f);
if (item->flags & DNS_ANSWER_CACHE_FLUSH) if (flags & DNS_ANSWER_CACHE_FLUSH)
fputs(" cache-flush", f); fputs(" cache-flush", f);
if (item->flags & DNS_ANSWER_GOODBYE) if (flags & DNS_ANSWER_GOODBYE)
fputs(" goodbye", f); fputs(" goodbye", f);
if (item->flags & DNS_ANSWER_SECTION_ANSWER)
fputs(" section-answer", f);
if (item->flags & DNS_ANSWER_SECTION_AUTHORITY)
fputs(" section-authority", f);
if (item->flags & DNS_ANSWER_SECTION_ADDITIONAL)
fputs(" section-additional", f);
fputc('\n', f); fputc('\n', f);
} }

View File

@ -8,8 +8,10 @@ typedef struct DnsAnswerItem DnsAnswerItem;
#include "resolved-dns-rr.h" #include "resolved-dns-rr.h"
#include "set.h" #include "set.h"
/* A simple array of resource records. We keep track of the originating ifindex for each RR where that makes /* A simple array of resource records. We keep track of the
* sense, so that we can qualify A and AAAA RRs referring to a local link with the right ifindex. * originating ifindex for each RR where that makes sense, so that we
* can qualify A and AAAA RRs referring to a local link with the
* right ifindex.
* *
* Note that we usually encode the empty DnsAnswer object as a simple NULL. */ * Note that we usually encode the empty DnsAnswer object as a simple NULL. */
@ -19,14 +21,10 @@ typedef enum DnsAnswerFlags {
DNS_ANSWER_SHARED_OWNER = 1 << 2, /* For mDNS: RRset may be owner by multiple peers */ DNS_ANSWER_SHARED_OWNER = 1 << 2, /* For mDNS: RRset may be owner by multiple peers */
DNS_ANSWER_CACHE_FLUSH = 1 << 3, /* For mDNS: sets cache-flush bit in the rrclass of response records */ DNS_ANSWER_CACHE_FLUSH = 1 << 3, /* For mDNS: sets cache-flush bit in the rrclass of response records */
DNS_ANSWER_GOODBYE = 1 << 4, /* For mDNS: item is subject to disappear */ DNS_ANSWER_GOODBYE = 1 << 4, /* For mDNS: item is subject to disappear */
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 */
} DnsAnswerFlags; } DnsAnswerFlags;
struct DnsAnswerItem { struct DnsAnswerItem {
DnsResourceRecord *rr; DnsResourceRecord *rr;
DnsResourceRecord *rrsig; /* Optionally, also store RRSIG RR that successfully validates this item */
int ifindex; int ifindex;
DnsAnswerFlags flags; DnsAnswerFlags flags;
}; };
@ -42,17 +40,16 @@ DnsAnswer *dns_answer_new(size_t n);
DnsAnswer *dns_answer_ref(DnsAnswer *a); DnsAnswer *dns_answer_ref(DnsAnswer *a);
DnsAnswer *dns_answer_unref(DnsAnswer *a); DnsAnswer *dns_answer_unref(DnsAnswer *a);
int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags, DnsResourceRecord *rrsig); int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags);
int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags, DnsResourceRecord *rrsig); int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags);
int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex); int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex);
int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *combined_flags); int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *combined_flags);
int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a); int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a);
int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone); int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone);
int dns_answer_contains(DnsAnswer *answer, DnsResourceRecord *rr);
int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *ret_flags); int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags);
int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *ret_flags); int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags);
int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret); int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret);
int dns_answer_extend(DnsAnswer **a, DnsAnswer *b); int dns_answer_extend(DnsAnswer **a, DnsAnswer *b);
@ -65,8 +62,8 @@ int dns_answer_reserve_or_clone(DnsAnswer **a, size_t n_free);
int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key); int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key);
int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rr); int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rr);
int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags, DnsResourceRecord *rrsig); int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags);
int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags, DnsResourceRecord *rrsig); int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags);
int dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname); int dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname);
@ -118,13 +115,17 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref);
#define DNS_ANSWER_FOREACH_FLAGS(kk, flags, a) _DNS_ANSWER_FOREACH_FLAGS(UNIQ, kk, flags, a) #define DNS_ANSWER_FOREACH_FLAGS(kk, flags, a) _DNS_ANSWER_FOREACH_FLAGS(UNIQ, kk, flags, a)
#define _DNS_ANSWER_FOREACH_ITEM(q, item, a) \ #define _DNS_ANSWER_FOREACH_FULL(q, kk, ifi, fl, a) \
for (size_t UNIQ_T(i, q) = ({ \ for (size_t UNIQ_T(i, q) = ({ \
(item) = dns_answer_isempty(a) ? NULL : (a)->items; \ (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
(ifi) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].ifindex : 0; \
(fl) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].flags : 0; \
0; \ 0; \
}); \ }); \
UNIQ_T(i, q) < dns_answer_size(a); \ (a) && (UNIQ_T(i, q) < (a)->n_rrs); \
UNIQ_T(i, q)++, \ UNIQ_T(i, q)++, \
(item) = ((UNIQ_T(i, q) < dns_answer_size(a)) ? (a)->items + UNIQ_T(i, q) : NULL)) (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \
(ifi) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].ifindex : 0), \
(fl) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].flags : 0))
#define DNS_ANSWER_FOREACH_ITEM(item, a) _DNS_ANSWER_FOREACH_ITEM(UNIQ, item, a) #define DNS_ANSWER_FOREACH_FULL(kk, ifindex, flags, a) _DNS_ANSWER_FOREACH_FULL(UNIQ, kk, ifindex, flags, a)

View File

@ -34,16 +34,13 @@ enum DnsCacheItemType {
struct DnsCacheItem { struct DnsCacheItem {
DnsCacheItemType type; DnsCacheItemType type;
DnsResourceKey *key; /* The key for this item, i.e. the lookup key */ DnsResourceKey *key;
DnsResourceRecord *rr; /* The RR for this item, i.e. the lookup value for positive queries */ DnsResourceRecord *rr;
DnsAnswer *answer; /* The full validated answer, if this is an RRset acquired via a "primary" lookup */
DnsPacket *full_packet; /* The full packet this information was acquired with */
int rcode; int rcode;
usec_t until; usec_t until;
bool authenticated:1; bool authenticated:1;
bool shared_owner:1; bool shared_owner:1;
DnssecResult dnssec_result;
int ifindex; int ifindex;
int owner_family; int owner_family;
@ -53,12 +50,6 @@ struct DnsCacheItem {
LIST_FIELDS(DnsCacheItem, by_key); LIST_FIELDS(DnsCacheItem, by_key);
}; };
/* Returns true if this is a cache item created as result of an explicit lookup, or created as "side-effect"
* of another request. "Primary" entries will carry the full answer data (with NSEC, ) that can aso prove
* wildcard expansion, non-existance and such, while entries that were created as "side-effect" just contain
* immediate RR data for the specified RR key, but nothing else. */
#define DNS_CACHE_ITEM_IS_PRIMARY(item) (!!(item)->answer)
static const char *dns_cache_item_type_to_string(DnsCacheItem *item) { static const char *dns_cache_item_type_to_string(DnsCacheItem *item) {
assert(item); assert(item);
@ -86,8 +77,6 @@ static void dns_cache_item_free(DnsCacheItem *i) {
dns_resource_record_unref(i->rr); dns_resource_record_unref(i->rr);
dns_resource_key_unref(i->key); dns_resource_key_unref(i->key);
dns_answer_unref(i->answer);
dns_packet_unref(i->full_packet);
free(i); free(i);
} }
@ -351,11 +340,8 @@ static void dns_cache_item_update_positive(
DnsCache *c, DnsCache *c,
DnsCacheItem *i, DnsCacheItem *i,
DnsResourceRecord *rr, DnsResourceRecord *rr,
DnsAnswer *answer,
DnsPacket *full_packet,
bool authenticated, bool authenticated,
bool shared_owner, bool shared_owner,
DnssecResult dnssec_result,
usec_t timestamp, usec_t timestamp,
int ifindex, int ifindex,
int owner_family, int owner_family,
@ -381,18 +367,9 @@ static void dns_cache_item_update_positive(
dns_resource_key_unref(i->key); dns_resource_key_unref(i->key);
i->key = dns_resource_key_ref(rr->key); i->key = dns_resource_key_ref(rr->key);
dns_answer_ref(answer); i->until = calculate_until(rr, (uint32_t) -1, timestamp, false);
dns_answer_unref(i->answer);
i->answer = answer;
dns_packet_ref(full_packet);
dns_packet_unref(i->full_packet);
i->full_packet = full_packet;
i->until = calculate_until(rr, UINT32_MAX, timestamp, false);
i->authenticated = authenticated; i->authenticated = authenticated;
i->shared_owner = shared_owner; i->shared_owner = shared_owner;
i->dnssec_result = dnssec_result;
i->ifindex = ifindex; i->ifindex = ifindex;
@ -405,11 +382,8 @@ static void dns_cache_item_update_positive(
static int dns_cache_put_positive( static int dns_cache_put_positive(
DnsCache *c, DnsCache *c,
DnsResourceRecord *rr, DnsResourceRecord *rr,
DnsAnswer *answer,
DnsPacket *full_packet,
bool authenticated, bool authenticated,
bool shared_owner, bool shared_owner,
DnssecResult dnssec_result,
usec_t timestamp, usec_t timestamp,
int ifindex, int ifindex,
int owner_family, int owner_family,
@ -446,11 +420,8 @@ static int dns_cache_put_positive(
c, c,
existing, existing,
rr, rr,
answer,
full_packet,
authenticated, authenticated,
shared_owner, shared_owner,
dnssec_result,
timestamp, timestamp,
ifindex, ifindex,
owner_family, owner_family,
@ -473,12 +444,9 @@ static int dns_cache_put_positive(
.type = DNS_CACHE_POSITIVE, .type = DNS_CACHE_POSITIVE,
.key = dns_resource_key_ref(rr->key), .key = dns_resource_key_ref(rr->key),
.rr = dns_resource_record_ref(rr), .rr = dns_resource_record_ref(rr),
.answer = dns_answer_ref(answer),
.full_packet = dns_packet_ref(full_packet),
.until = calculate_until(rr, (uint32_t) -1, timestamp, false), .until = calculate_until(rr, (uint32_t) -1, timestamp, false),
.authenticated = authenticated, .authenticated = authenticated,
.shared_owner = shared_owner, .shared_owner = shared_owner,
.dnssec_result = dnssec_result,
.ifindex = ifindex, .ifindex = ifindex,
.owner_family = owner_family, .owner_family = owner_family,
.owner_address = *owner_address, .owner_address = *owner_address,
@ -513,10 +481,7 @@ static int dns_cache_put_negative(
DnsCache *c, DnsCache *c,
DnsResourceKey *key, DnsResourceKey *key,
int rcode, int rcode,
DnsAnswer *answer,
DnsPacket *full_packet,
bool authenticated, bool authenticated,
DnssecResult dnssec_result,
uint32_t nsec_ttl, uint32_t nsec_ttl,
usec_t timestamp, usec_t timestamp,
DnsResourceRecord *soa, DnsResourceRecord *soa,
@ -567,13 +532,10 @@ static int dns_cache_put_negative(
rcode == DNS_RCODE_SUCCESS ? DNS_CACHE_NODATA : rcode == DNS_RCODE_SUCCESS ? DNS_CACHE_NODATA :
rcode == DNS_RCODE_NXDOMAIN ? DNS_CACHE_NXDOMAIN : DNS_CACHE_RCODE, rcode == DNS_RCODE_NXDOMAIN ? DNS_CACHE_NXDOMAIN : DNS_CACHE_RCODE,
.authenticated = authenticated, .authenticated = authenticated,
.dnssec_result = dnssec_result,
.owner_family = owner_family, .owner_family = owner_family,
.owner_address = *owner_address, .owner_address = *owner_address,
.prioq_idx = PRIOQ_IDX_NULL, .prioq_idx = PRIOQ_IDX_NULL,
.rcode = rcode, .rcode = rcode,
.answer = dns_answer_ref(answer),
.full_packet = dns_packet_ref(full_packet),
}; };
i->until = i->until =
@ -668,20 +630,17 @@ int dns_cache_put(
DnsResourceKey *key, DnsResourceKey *key,
int rcode, int rcode,
DnsAnswer *answer, DnsAnswer *answer,
DnsPacket *full_packet,
bool authenticated, bool authenticated,
DnssecResult dnssec_result,
uint32_t nsec_ttl, uint32_t nsec_ttl,
usec_t timestamp,
int owner_family, int owner_family,
const union in_addr_union *owner_address) { const union in_addr_union *owner_address) {
DnsResourceRecord *soa = NULL; DnsResourceRecord *soa = NULL, *rr;
bool weird_rcode = false; bool weird_rcode = false;
DnsAnswerItem *item;
DnsAnswerFlags flags; DnsAnswerFlags flags;
unsigned cache_keys; unsigned cache_keys;
usec_t timestamp; int r, ifindex;
int r;
assert(c); assert(c);
assert(owner_address); assert(owner_address);
@ -701,7 +660,6 @@ int dns_cache_put(
log_debug("Not caching negative entry without a SOA record: %s", log_debug("Not caching negative entry without a SOA record: %s",
dns_resource_key_to_string(key, key_str, sizeof key_str)); dns_resource_key_to_string(key, key_str, sizeof key_str));
} }
return 0; return 0;
} }
@ -721,53 +679,23 @@ int dns_cache_put(
/* Make some space for our new entries */ /* Make some space for our new entries */
dns_cache_make_space(c, cache_keys); dns_cache_make_space(c, cache_keys);
if (timestamp <= 0)
timestamp = now(clock_boottime_or_monotonic()); timestamp = now(clock_boottime_or_monotonic());
/* Second, add in positive entries for all contained RRs */ /* Second, add in positive entries for all contained RRs */
DNS_ANSWER_FOREACH_ITEM(item, answer) { DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer) {
int primary = false; if ((flags & DNS_ANSWER_CACHEABLE) == 0 ||
!rr_eligible(rr))
if (!FLAGS_SET(item->flags, DNS_ANSWER_CACHEABLE) ||
!rr_eligible(item->rr))
continue; continue;
if (key) {
/* We store the auxiliary RRs and packet data in the cache only if they were in
* direct response to the original query. If we cache an RR we also received, and
* that is just auxiliary information we can't use the data, hence don't. */
primary = dns_resource_key_match_rr(key, item->rr, NULL);
if (primary < 0)
return primary;
if (primary == 0) {
primary = dns_resource_key_match_cname_or_dname(key, item->rr->key, NULL);
if (primary < 0)
return primary;
}
}
if (!primary) {
DnsCacheItem *first;
/* Do not replace existing cache items for primary lookups with non-primary
* data. After all the primary lookup data is a lot more useful. */
first = hashmap_get(c->by_key, item->rr->key);
if (first && DNS_CACHE_ITEM_IS_PRIMARY(first))
return 0;
}
r = dns_cache_put_positive( r = dns_cache_put_positive(
c, c,
item->rr, rr,
primary ? answer : NULL, flags & DNS_ANSWER_AUTHENTICATED,
primary ? full_packet : NULL, flags & DNS_ANSWER_SHARED_OWNER,
item->flags & DNS_ANSWER_AUTHENTICATED,
item->flags & DNS_ANSWER_SHARED_OWNER,
dnssec_result,
timestamp, timestamp,
item->ifindex, ifindex,
owner_family, owner_family, owner_address);
owner_address);
if (r < 0) if (r < 0)
goto fail; goto fail;
} }
@ -817,10 +745,7 @@ int dns_cache_put(
c, c,
key, key,
rcode, rcode,
answer,
full_packet,
authenticated, authenticated,
dnssec_result,
nsec_ttl, nsec_ttl,
timestamp, timestamp,
soa, soa,
@ -837,11 +762,11 @@ fail:
if (key) if (key)
dns_cache_remove_by_key(c, key); dns_cache_remove_by_key(c, key);
DNS_ANSWER_FOREACH_ITEM(item, answer) { DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
if ((item->flags & DNS_ANSWER_CACHEABLE) == 0) if ((flags & DNS_ANSWER_CACHEABLE) == 0)
continue; continue;
dns_cache_remove_by_key(c, item->rr->key); dns_cache_remove_by_key(c, rr->key);
} }
return r; return r;
@ -902,59 +827,7 @@ static DnsCacheItem *dns_cache_get_by_key_follow_cname_dname_nsec(DnsCache *c, D
return NULL; return NULL;
} }
static int answer_add_clamp_ttl( int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, bool clamp_ttl, int *rcode, DnsAnswer **ret, bool *authenticated) {
DnsAnswer **answer,
DnsResourceRecord *rr,
int ifindex,
DnsAnswerFlags answer_flags,
DnsResourceRecord *rrsig,
uint64_t query_flags,
usec_t until,
usec_t current) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *patched = NULL, *patched_rrsig = NULL;
int r;
assert(answer);
assert(rr);
if (FLAGS_SET(query_flags, SD_RESOLVED_CLAMP_TTL)) {
patched = dns_resource_record_ref(rr);
r = dns_resource_record_clamp_ttl(&patched, LESS_BY(until, current) / USEC_PER_SEC);
if (r < 0)
return r;
rr = patched;
if (rrsig) {
patched_rrsig = dns_resource_record_ref(rrsig);
r = dns_resource_record_clamp_ttl(&patched_rrsig, LESS_BY(until, current) / USEC_PER_SEC);
if (r < 0)
return r;
rrsig = patched_rrsig;
}
}
r = dns_answer_add_extend(answer, rr, ifindex, answer_flags, rrsig);
if (r < 0)
return r;
return 0;
}
int dns_cache_lookup(
DnsCache *c,
DnsResourceKey *key,
uint64_t query_flags,
int *ret_rcode,
DnsAnswer **ret_answer,
DnsPacket **ret_full_packet,
bool *ret_authenticated,
DnssecResult *ret_dnssec_result) {
_cleanup_(dns_packet_unrefp) DnsPacket *full_packet = NULL;
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
char key_str[DNS_RESOURCE_KEY_STRING_MAX]; char key_str[DNS_RESOURCE_KEY_STRING_MAX];
unsigned n = 0; unsigned n = 0;
@ -964,19 +837,27 @@ int dns_cache_lookup(
bool have_authenticated = false, have_non_authenticated = false; bool have_authenticated = false, have_non_authenticated = false;
usec_t current; usec_t current;
int found_rcode = -1; int found_rcode = -1;
DnssecResult dnssec_result = -1;
int have_dnssec_result = -1;
assert(c); assert(c);
assert(key); assert(key);
assert(rcode);
assert(ret);
assert(authenticated);
if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) { if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
/* If we have ANY lookups we don't use the cache, so that the caller refreshes via the /* If we have ANY lookups we don't use the cache, so
* network. */ * that the caller refreshes via the network. */
log_debug("Ignoring cache for ANY lookup: %s", log_debug("Ignoring cache for ANY lookup: %s",
dns_resource_key_to_string(key, key_str, sizeof key_str)); dns_resource_key_to_string(key, key_str, sizeof key_str));
goto miss;
c->n_miss++;
*ret = NULL;
*rcode = DNS_RCODE_SUCCESS;
*authenticated = false;
return 0;
} }
first = dns_cache_get_by_key_follow_cname_dname_nsec(c, key); first = dns_cache_get_by_key_follow_cname_dname_nsec(c, key);
@ -985,80 +866,31 @@ int dns_cache_lookup(
log_debug("Cache miss for %s", log_debug("Cache miss for %s",
dns_resource_key_to_string(key, key_str, sizeof key_str)); dns_resource_key_to_string(key, key_str, sizeof key_str));
goto miss;
}
if (FLAGS_SET(query_flags, SD_RESOLVED_CLAMP_TTL)) c->n_miss++;
current = now(clock_boottime_or_monotonic());
*ret = NULL;
*rcode = DNS_RCODE_SUCCESS;
*authenticated = false;
return 0;
}
LIST_FOREACH(by_key, j, first) { LIST_FOREACH(by_key, j, first) {
/* If the caller doesn't allow us to answer questions from cache data learned from if (j->rr) {
* "side-effect", skip this entry. */
if (FLAGS_SET(query_flags, SD_RESOLVED_REQUIRE_PRIMARY) &&
!DNS_CACHE_ITEM_IS_PRIMARY(j)) {
log_debug("Primary answer was requested for cache lookup for %s, which we don't have.",
dns_resource_key_to_string(key, key_str, sizeof key_str));
goto miss;
}
if (j->type == DNS_CACHE_NXDOMAIN)
nxdomain = true;
else if (j->type == DNS_CACHE_RCODE)
found_rcode = j->rcode;
else if (j->rr) {
if (j->rr->key->type == DNS_TYPE_NSEC) if (j->rr->key->type == DNS_TYPE_NSEC)
nsec = j; nsec = j;
n++; n++;
} } else if (j->type == DNS_CACHE_NXDOMAIN)
nxdomain = true;
else if (j->type == DNS_CACHE_RCODE)
found_rcode = j->rcode;
if (j->authenticated) if (j->authenticated)
have_authenticated = true; have_authenticated = true;
else else
have_non_authenticated = true; have_non_authenticated = true;
if (j->dnssec_result < 0) {
have_dnssec_result = false; /* an entry without dnssec result? then invalidate things for good */
dnssec_result = _DNSSEC_RESULT_INVALID;
} else if (have_dnssec_result < 0) {
have_dnssec_result = true; /* So far no result seen, let's pick this one up */
dnssec_result = j->dnssec_result;
} else if (have_dnssec_result > 0 && j->dnssec_result != dnssec_result) {
have_dnssec_result = false; /* conflicting result seen? then invalidate for good */
dnssec_result = _DNSSEC_RESULT_INVALID;
}
/* Append the answer RRs to our answer. Ideally we have the answer object, which we
* preferably use. But if the cached entry was generated as "side-effect" of a reply,
* i.e. from validated auxiliary records rather than from the main reply, then we use the
* individual RRs only instead. */
if (j->answer) {
/* Minor optimization, if the full answer object of this and the previous RR is the
* same, don't bother adding it again. Typically we store a full RRset here, hence
* that should be the case. */
if (!j->by_key_prev || j->answer != j->by_key_prev->answer) {
DnsAnswerItem *item;
DNS_ANSWER_FOREACH_ITEM(item, j->answer) {
r = answer_add_clamp_ttl(&answer, item->rr, item->ifindex, item->flags, item->rrsig, query_flags, j->until, current);
if (r < 0)
return r;
}
}
} else if (j->rr) {
r = answer_add_clamp_ttl(&answer, j->rr, j->ifindex, j->authenticated ? DNS_ANSWER_AUTHENTICATED : 0, NULL, query_flags, j->until, current);
if (r < 0)
return r;
}
/* We'll return any packet we have for this. Typically all cache entries for the same key
* should come from the same packet anyway, hence it doesn't really matter which packet we
* return here, they should all resolve to the same anyway. */
if (!full_packet && j->full_packet)
full_packet = dns_packet_ref(j->full_packet);
} }
if (found_rcode >= 0) { if (found_rcode >= 0) {
@ -1066,41 +898,28 @@ int dns_cache_lookup(
dns_rcode_to_string(found_rcode), dns_rcode_to_string(found_rcode),
dns_resource_key_to_string(key, key_str, sizeof(key_str))); dns_resource_key_to_string(key, key_str, sizeof(key_str)));
if (ret_rcode) *ret = NULL;
*ret_rcode = found_rcode; *rcode = found_rcode;
if (ret_answer) *authenticated = false;
*ret_answer = TAKE_PTR(answer);
if (ret_full_packet)
*ret_full_packet = TAKE_PTR(full_packet);
if (ret_authenticated)
*ret_authenticated = false;
if (ret_dnssec_result)
*ret_dnssec_result = dnssec_result;
c->n_hit++; c->n_hit++;
return 1; return 1;
} }
if (nsec && !IN_SET(key->type, DNS_TYPE_NSEC, DNS_TYPE_DS)) { if (nsec && !IN_SET(key->type, DNS_TYPE_NSEC, DNS_TYPE_DS)) {
/* Note that we won't derive information for DS RRs from an NSEC, because we only cache NSEC /* Note that we won't derive information for DS RRs from an NSEC, because we only cache NSEC RRs from
* RRs from the lower-zone of a zone cut, but the DS RRs are on the upper zone. */ * the lower-zone of a zone cut, but the DS RRs are on the upper zone. */
log_debug("NSEC NODATA cache hit for %s", log_debug("NSEC NODATA cache hit for %s",
dns_resource_key_to_string(key, key_str, sizeof key_str)); dns_resource_key_to_string(key, key_str, sizeof key_str));
/* We only found an NSEC record that matches our name. If it says the type doesn't exist /* We only found an NSEC record that matches our name.
* report NODATA. Otherwise report a cache miss. */ * If it says the type doesn't exist report
* NODATA. Otherwise report a cache miss. */
if (ret_rcode) *ret = NULL;
*ret_rcode = DNS_RCODE_SUCCESS; *rcode = DNS_RCODE_SUCCESS;
if (ret_answer) *authenticated = nsec->authenticated;
*ret_answer = TAKE_PTR(answer);
if (ret_full_packet)
*ret_full_packet = TAKE_PTR(full_packet);
if (ret_authenticated)
*ret_authenticated = nsec->authenticated;
if (ret_dnssec_result)
*ret_dnssec_result = nsec->dnssec_result;
if (!bitmap_isset(nsec->rr->nsec.types, key->type) && if (!bitmap_isset(nsec->rr->nsec.types, key->type) &&
!bitmap_isset(nsec->rr->nsec.types, DNS_TYPE_CNAME) && !bitmap_isset(nsec->rr->nsec.types, DNS_TYPE_CNAME) &&
@ -1121,49 +940,46 @@ int dns_cache_lookup(
if (n <= 0) { if (n <= 0) {
c->n_hit++; c->n_hit++;
if (ret_rcode) *ret = NULL;
*ret_rcode = nxdomain ? DNS_RCODE_NXDOMAIN : DNS_RCODE_SUCCESS; *rcode = nxdomain ? DNS_RCODE_NXDOMAIN : DNS_RCODE_SUCCESS;
if (ret_answer) *authenticated = have_authenticated && !have_non_authenticated;
*ret_answer = TAKE_PTR(answer);
if (ret_full_packet)
*ret_full_packet = TAKE_PTR(full_packet);
if (ret_authenticated)
*ret_authenticated = have_authenticated && !have_non_authenticated;
if (ret_dnssec_result)
*ret_dnssec_result = dnssec_result;
return 1; return 1;
} }
answer = dns_answer_new(n);
if (!answer)
return -ENOMEM;
if (clamp_ttl)
current = now(clock_boottime_or_monotonic());
LIST_FOREACH(by_key, j, first) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
if (!j->rr)
continue;
if (clamp_ttl) {
rr = dns_resource_record_ref(j->rr);
r = dns_resource_record_clamp_ttl(&rr, LESS_BY(j->until, current) / USEC_PER_SEC);
if (r < 0)
return r;
}
r = dns_answer_add(answer, rr ?: j->rr, j->ifindex, j->authenticated ? DNS_ANSWER_AUTHENTICATED : 0);
if (r < 0)
return r;
}
c->n_hit++; c->n_hit++;
if (ret_rcode) *ret = answer;
*ret_rcode = DNS_RCODE_SUCCESS; *rcode = DNS_RCODE_SUCCESS;
if (ret_answer) *authenticated = have_authenticated && !have_non_authenticated;
*ret_answer = TAKE_PTR(answer); answer = NULL;
if (ret_full_packet)
*ret_full_packet = TAKE_PTR(full_packet);
if (ret_authenticated)
*ret_authenticated = have_authenticated && !have_non_authenticated;
if (ret_dnssec_result)
*ret_dnssec_result = dnssec_result;
return n; return n;
miss:
if (ret_rcode)
*ret_rcode = DNS_RCODE_SUCCESS;
if (ret_answer)
*ret_answer = NULL;
if (ret_full_packet)
*ret_full_packet = NULL;
if (ret_authenticated)
*ret_authenticated = false;
if (ret_dnssec_result)
*ret_dnssec_result = _DNSSEC_RESULT_INVALID;
c->n_miss++;
return 0;
} }
int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address) { int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address) {

View File

@ -5,7 +5,6 @@
#include "list.h" #include "list.h"
#include "prioq.h" #include "prioq.h"
#include "resolve-util.h" #include "resolve-util.h"
#include "resolved-dns-dnssec.h"
#include "time-util.h" #include "time-util.h"
typedef struct DnsCache { typedef struct DnsCache {
@ -23,28 +22,8 @@ typedef struct DnsCache {
void dns_cache_flush(DnsCache *c); void dns_cache_flush(DnsCache *c);
void dns_cache_prune(DnsCache *c); void dns_cache_prune(DnsCache *c);
int dns_cache_put( int dns_cache_put(DnsCache *c, DnsCacheMode cache_mode, DnsResourceKey *key, int rcode, DnsAnswer *answer, bool authenticated, uint32_t nsec_ttl, usec_t timestamp, int owner_family, const union in_addr_union *owner_address);
DnsCache *c, int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, bool clamp_ttl, int *rcode, DnsAnswer **answer, bool *authenticated);
DnsCacheMode cache_mode,
DnsResourceKey *key,
int rcode,
DnsAnswer *answer,
DnsPacket *full_packet,
bool authenticated,
DnssecResult dnssec_result,
uint32_t nsec_ttl,
int owner_family,
const union in_addr_union *owner_address);
int dns_cache_lookup(
DnsCache *c,
DnsResourceKey *key,
uint64_t query_flags,
int *ret_rcode,
DnsAnswer **ret_answer,
DnsPacket **ret_full_packet,
bool *ret_authenticated,
DnssecResult *ret_dnssec_result);
int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address); int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address);

View File

@ -160,38 +160,6 @@ int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t min_alloc
return 0; return 0;
} }
int dns_packet_dup(DnsPacket **ret, DnsPacket *p) {
DnsPacket *c;
int r;
assert(ret);
assert(p);
r = dns_packet_validate(p);
if (r < 0)
return r;
c = malloc(ALIGN(sizeof(DnsPacket)) + p->size);
if (!c)
return -ENOMEM;
*c = (DnsPacket) {
.n_ref = 1,
.protocol = p->protocol,
.size = p->size,
.rindex = DNS_PACKET_HEADER_SIZE,
.allocated = p->size,
.max_size = p->max_size,
.opt_start = (size_t) -1,
.opt_size = (size_t) -1,
};
memcpy(DNS_PACKET_DATA(c), DNS_PACKET_DATA(p), p->size);
*ret = c;
return 0;
}
DnsPacket *dns_packet_ref(DnsPacket *p) { DnsPacket *dns_packet_ref(DnsPacket *p) {
if (!p) if (!p)
@ -1215,7 +1183,7 @@ int dns_packet_append_question(DnsPacket *p, DnsQuestion *q) {
return 0; return 0;
} }
int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a, unsigned *completed) { int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a) {
DnsResourceRecord *rr; DnsResourceRecord *rr;
DnsAnswerFlags flags; DnsAnswerFlags flags;
int r; int r;
@ -1226,9 +1194,6 @@ int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a, unsigned *completed) {
r = dns_packet_append_rr(p, rr, flags, NULL, NULL); r = dns_packet_append_rr(p, rr, flags, NULL, NULL);
if (r < 0) if (r < 0)
return r; return r;
if (completed)
(*completed)++;
} }
return 0; return 0;
@ -1333,7 +1298,6 @@ int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
if (r < 0) if (r < 0)
return r; return r;
if (ret)
*ret = unaligned_read_be16(d); *ret = unaligned_read_be16(d);
return 0; return 0;
@ -1420,19 +1384,19 @@ int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, siz
int dns_packet_read_name( int dns_packet_read_name(
DnsPacket *p, DnsPacket *p,
char **ret, char **_ret,
bool allow_compression, bool allow_compression,
size_t *ret_start) { size_t *start) {
_cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder; _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
size_t after_rindex = 0, jump_barrier; size_t after_rindex = 0, jump_barrier;
_cleanup_free_ char *name = NULL; _cleanup_free_ char *ret = NULL;
size_t n = 0, allocated = 0; size_t n = 0, allocated = 0;
bool first = true; bool first = true;
int r; int r;
assert(p); assert(p);
assert(_ret);
INIT_REWINDER(rewinder, p); INIT_REWINDER(rewinder, p);
jump_barrier = p->rindex; jump_barrier = p->rindex;
@ -1457,15 +1421,15 @@ int dns_packet_read_name(
if (r < 0) if (r < 0)
return r; return r;
if (!GREEDY_REALLOC(name, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
return -ENOMEM; return -ENOMEM;
if (first) if (first)
first = false; first = false;
else else
name[n++] = '.'; ret[n++] = '.';
r = dns_label_escape(label, c, name + n, DNS_LABEL_ESCAPED_MAX); r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
if (r < 0) if (r < 0)
return r; return r;
@ -1493,19 +1457,18 @@ int dns_packet_read_name(
return -EBADMSG; return -EBADMSG;
} }
if (!GREEDY_REALLOC(name, allocated, n + 1)) if (!GREEDY_REALLOC(ret, allocated, n + 1))
return -ENOMEM; return -ENOMEM;
name[n] = 0; ret[n] = 0;
if (after_rindex != 0) if (after_rindex != 0)
p->rindex= after_rindex; p->rindex= after_rindex;
if (ret) *_ret = TAKE_PTR(ret);
*ret = TAKE_PTR(name);
if (ret_start)
*ret_start = rewinder.saved_rindex;
if (start)
*start = rewinder.saved_rindex;
CANCEL_REWINDER(rewinder); CANCEL_REWINDER(rewinder);
return 0; return 0;
@ -1607,19 +1570,16 @@ static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t siz
return 0; return 0;
} }
int dns_packet_read_key( int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start) {
DnsPacket *p,
DnsResourceKey **ret,
bool *ret_cache_flush,
size_t *ret_start) {
_cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder; _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
_cleanup_free_ char *name = NULL; _cleanup_free_ char *name = NULL;
bool cache_flush = false; bool cache_flush = false;
uint16_t class, type; uint16_t class, type;
DnsResourceKey *key;
int r; int r;
assert(p); assert(p);
assert(ret);
INIT_REWINDER(rewinder, p); INIT_REWINDER(rewinder, p);
r = dns_packet_read_name(p, &name, true, NULL); r = dns_packet_read_name(p, &name, true, NULL);
@ -1643,23 +1603,19 @@ int dns_packet_read_key(
} }
} }
if (ret) {
DnsResourceKey *key;
key = dns_resource_key_new_consume(class, type, name); key = dns_resource_key_new_consume(class, type, name);
if (!key) if (!key)
return -ENOMEM; return -ENOMEM;
TAKE_PTR(name); name = NULL;
*ret = key; *ret = key;
}
if (ret_cache_flush) if (ret_cache_flush)
*ret_cache_flush = cache_flush; *ret_cache_flush = cache_flush;
if (ret_start) if (start)
*ret_start = rewinder.saved_rindex; *start = rewinder.saved_rindex;
CANCEL_REWINDER(rewinder); CANCEL_REWINDER(rewinder);
return 0; return 0;
} }
@ -1669,12 +1625,7 @@ static bool loc_size_ok(uint8_t size) {
return m <= 9 && e <= 9 && (m > 0 || e == 0); return m <= 9 && e <= 9 && (m > 0 || e == 0);
} }
int dns_packet_read_rr( int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start) {
DnsPacket *p,
DnsResourceRecord **ret,
bool *ret_cache_flush,
size_t *ret_start) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
_cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder; _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
@ -1684,6 +1635,7 @@ int dns_packet_read_rr(
int r; int r;
assert(p); assert(p);
assert(ret);
INIT_REWINDER(rewinder, p); INIT_REWINDER(rewinder, p);
@ -2124,14 +2076,14 @@ int dns_packet_read_rr(
if (p->rindex != offset + rdlength) if (p->rindex != offset + rdlength)
return -EBADMSG; return -EBADMSG;
if (ret)
*ret = TAKE_PTR(rr); *ret = TAKE_PTR(rr);
if (ret_cache_flush) if (ret_cache_flush)
*ret_cache_flush = cache_flush; *ret_cache_flush = cache_flush;
if (ret_start) if (start)
*ret_start = rewinder.saved_rindex; *start = rewinder.saved_rindex;
CANCEL_REWINDER(rewinder); CANCEL_REWINDER(rewinder);
return 0; return 0;
} }
@ -2251,9 +2203,8 @@ static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
bool cache_flush = false; bool cache_flush = false;
size_t start;
r = dns_packet_read_rr(p, &rr, &cache_flush, &start); r = dns_packet_read_rr(p, &rr, &cache_flush, NULL);
if (r < 0) if (r < 0)
return r; return r;
@ -2321,26 +2272,15 @@ static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
} }
p->opt = dns_resource_record_ref(rr); p->opt = dns_resource_record_ref(rr);
p->opt_start = start;
assert(p->rindex >= start);
p->opt_size = p->rindex - start;
} else { } else {
DnsAnswerFlags flags = 0; /* According to RFC 4795, section 2.9. only the RRs from the Answer section
* shall be cached. Hence mark only those RRs as cacheable by default, but
* not the ones from the Additional or Authority sections. */
DnsAnswerFlags flags =
(i < DNS_PACKET_ANCOUNT(p) ? DNS_ANSWER_CACHEABLE : 0) |
(p->protocol == DNS_PROTOCOL_MDNS && !cache_flush ? DNS_ANSWER_SHARED_OWNER : 0);
if (p->protocol == DNS_PROTOCOL_MDNS && !cache_flush) r = dns_answer_add(answer, rr, p->ifindex, flags);
flags |= DNS_ANSWER_SHARED_OWNER;
/* According to RFC 4795, section 2.9. only the RRs from the Answer section shall be
* cached. Hence mark only those RRs as cacheable by default, but not the ones from
* the Additional or Authority sections. */
if (i < DNS_PACKET_ANCOUNT(p))
flags |= DNS_ANSWER_CACHEABLE|DNS_ANSWER_SECTION_ANSWER;
else if (i < DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p))
flags |= DNS_ANSWER_SECTION_AUTHORITY;
else
flags |= DNS_ANSWER_SECTION_ADDITIONAL;
r = dns_answer_add(answer, rr, p->ifindex, flags, NULL);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -2416,106 +2356,6 @@ int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) {
return dns_resource_key_equal(p->question->keys[0], key); return dns_resource_key_equal(p->question->keys[0], key);
} }
int dns_packet_patch_max_udp_size(DnsPacket *p, uint16_t max_udp_size) {
assert(p);
assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
if (p->opt_start == (size_t) -1) /* No OPT section, nothing to patch */
return 0;
assert(p->opt_size != (size_t) -1);
assert(p->opt_size >= 5);
unaligned_write_be16(DNS_PACKET_DATA(p) + p->opt_start + 3, max_udp_size);
return 1;
}
static int patch_rr(DnsPacket *p, usec_t age) {
_cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
size_t ttl_index;
uint32_t ttl;
uint16_t type, rdlength;
int r;
INIT_REWINDER(rewinder, p);
/* Patches the RR at the current rindex, substracts the specified time from the TTL */
r = dns_packet_read_name(p, NULL, true, NULL);
if (r < 0)
return r;
r = dns_packet_read_uint16(p, &type, NULL);
if (r < 0)
return r;
r = dns_packet_read_uint16(p, NULL, NULL);
if (r < 0)
return r;
r = dns_packet_read_uint32(p, &ttl, &ttl_index);
if (r < 0)
return r;
if (type != DNS_TYPE_OPT) { /* The TTL of the OPT field is not actually a TTL, skip it */
ttl = LESS_BY(ttl * USEC_PER_SEC, age) / USEC_PER_SEC;
unaligned_write_be32(DNS_PACKET_DATA(p) + ttl_index, ttl);
}
r = dns_packet_read_uint16(p, &rdlength, NULL);
if (r < 0)
return r;
r = dns_packet_read(p, rdlength, NULL, NULL);
if (r < 0)
return r;
CANCEL_REWINDER(rewinder);
return 0;
}
int dns_packet_patch_ttls(DnsPacket *p, usec_t timestamp) {
_cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = {};
unsigned i, n;
usec_t k;
int r;
assert(p);
assert(timestamp_is_set(timestamp));
/* Adjusts all TTLs in the packet by subtracting the time difference between now and the specified timestamp */
k = now(clock_boottime_or_monotonic());
assert(k >= timestamp);
k -= timestamp;
INIT_REWINDER(rewinder, p);
dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
n = DNS_PACKET_QDCOUNT(p);
for (i = 0; i < n; i++) {
r = dns_packet_read_key(p, NULL, NULL, NULL);
if (r < 0)
return r;
}
n = DNS_PACKET_RRCOUNT(p);
for (i = 0; i < n; i++) {
/* DNS servers suck, hence the RR count is in many servers off. If we reached the end
* prematurely, accept that, exit early */
if (p->rindex == p->size)
break;
r = patch_rr(p, k);
if (r < 0)
return r;
}
return 0;
}
static void dns_packet_hash_func(const DnsPacket *s, struct siphash *state) { static void dns_packet_hash_func(const DnsPacket *s, struct siphash *state) {
assert(s); assert(s);

View File

@ -176,8 +176,6 @@ static inline unsigned DNS_PACKET_RRCOUNT(DnsPacket *p) {
int dns_packet_new(DnsPacket **p, DnsProtocol protocol, size_t min_alloc_dsize, size_t max_size); int dns_packet_new(DnsPacket **p, DnsProtocol protocol, size_t min_alloc_dsize, size_t max_size);
int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t min_alloc_dsize, bool dnssec_checking_disabled); int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t min_alloc_dsize, bool dnssec_checking_disabled);
int dns_packet_dup(DnsPacket **ret, DnsPacket *p);
void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated); void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated);
DnsPacket *dns_packet_ref(DnsPacket *p); DnsPacket *dns_packet_ref(DnsPacket *p);
@ -203,10 +201,7 @@ int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *key, const DnsAnsw
int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, const DnsAnswerFlags flags, size_t *start, size_t *rdata_start); int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, const DnsAnswerFlags flags, size_t *start, size_t *rdata_start);
int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, bool include_rfc6975, int rcode, size_t *start); int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, bool include_rfc6975, int rcode, size_t *start);
int dns_packet_append_question(DnsPacket *p, DnsQuestion *q); int dns_packet_append_question(DnsPacket *p, DnsQuestion *q);
int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a, unsigned *completed); int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a);
int dns_packet_patch_max_udp_size(DnsPacket *p, uint16_t max_udp_size);
int dns_packet_patch_ttls(DnsPacket *p, usec_t timestamp);
void dns_packet_truncate(DnsPacket *p, size_t sz); void dns_packet_truncate(DnsPacket *p, size_t sz);
int dns_packet_truncate_opt(DnsPacket *p); int dns_packet_truncate_opt(DnsPacket *p);

View File

@ -97,35 +97,20 @@ static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
return 1; return 1;
} }
static int dns_query_candidate_add_transaction( static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResourceKey *key) {
DnsQueryCandidate *c,
DnsResourceKey *key,
DnsPacket *bypass) {
_cleanup_(dns_transaction_gcp) DnsTransaction *t = NULL; _cleanup_(dns_transaction_gcp) DnsTransaction *t = NULL;
int r; int r;
assert(c); assert(c);
assert(key);
if (key) { t = dns_scope_find_transaction(c->scope, key, true);
/* Regular lookup with a resource key */
assert(!bypass);
t = dns_scope_find_transaction(c->scope, key, c->query->flags);
if (!t) { if (!t) {
r = dns_transaction_new(&t, c->scope, key, NULL, c->query->flags); r = dns_transaction_new(&t, c->scope, key);
if (r < 0) if (r < 0)
return r; return r;
} else if (set_contains(c->transactions, t)) } else if (set_contains(c->transactions, t))
return 0; return 0;
} else {
/* "Bypass" lookup with a query packet */
assert(bypass);
r = dns_transaction_new(&t, c->scope, NULL, bypass, c->query->flags);
if (r < 0)
return r;
}
r = set_ensure_allocated(&t->notify_query_candidates_done, NULL); r = set_ensure_allocated(&t->notify_query_candidates_done, NULL);
if (r < 0) if (r < 0)
@ -141,6 +126,7 @@ static int dns_query_candidate_add_transaction(
return r; return r;
} }
t->clamp_ttl = c->query->clamp_ttl;
TAKE_PTR(t); TAKE_PTR(t);
return 1; return 1;
} }
@ -228,21 +214,6 @@ static int dns_query_candidate_setup_transactions(DnsQueryCandidate *c) {
dns_query_candidate_stop(c); dns_query_candidate_stop(c);
if (c->query->question_bypass) {
/* If this is a bypass query, then pass the original query packet along to the transaction */
assert(dns_question_size(c->query->question_bypass->question) == 1);
if (!dns_scope_good_key(c->scope, c->query->question_bypass->question->keys[0]))
return 0;
r = dns_query_candidate_add_transaction(c, NULL, c->query->question_bypass);
if (r < 0)
goto fail;
return 1;
}
question = dns_query_question_for_protocol(c->query, c->scope->protocol); question = dns_query_question_for_protocol(c->query, c->scope->protocol);
/* Create one transaction per question key */ /* Create one transaction per question key */
@ -262,7 +233,7 @@ static int dns_query_candidate_setup_transactions(DnsQueryCandidate *c) {
if (!dns_scope_good_key(c->scope, qkey)) if (!dns_scope_good_key(c->scope, qkey))
continue; continue;
r = dns_query_candidate_add_transaction(c, qkey, NULL); r = dns_query_candidate_add_transaction(c, qkey);
if (r < 0) if (r < 0)
goto fail; goto fail;
@ -350,7 +321,6 @@ static void dns_query_reset_answer(DnsQuery *q) {
q->answer_protocol = _DNS_PROTOCOL_INVALID; q->answer_protocol = _DNS_PROTOCOL_INVALID;
q->answer_family = AF_UNSPEC; q->answer_family = AF_UNSPEC;
q->answer_search_domain = dns_search_domain_unref(q->answer_search_domain); q->answer_search_domain = dns_search_domain_unref(q->answer_search_domain);
q->answer_full_packet = dns_packet_unref(q->answer_full_packet);
} }
DnsQuery *dns_query_free(DnsQuery *q) { DnsQuery *dns_query_free(DnsQuery *q) {
@ -370,7 +340,6 @@ DnsQuery *dns_query_free(DnsQuery *q) {
dns_question_unref(q->question_idna); dns_question_unref(q->question_idna);
dns_question_unref(q->question_utf8); dns_question_unref(q->question_utf8);
dns_packet_unref(q->question_bypass);
dns_query_reset_answer(q); dns_query_reset_answer(q);
@ -382,15 +351,13 @@ DnsQuery *dns_query_free(DnsQuery *q) {
varlink_unref(q->varlink_request); varlink_unref(q->varlink_request);
} }
dns_packet_unref(q->request_packet); dns_packet_unref(q->request_dns_packet);
dns_answer_unref(q->reply_answer); dns_packet_unref(q->reply_dns_packet);
dns_answer_unref(q->reply_authoritative);
dns_answer_unref(q->reply_additional);
if (q->request_stream) { if (q->request_dns_stream) {
/* Detach the stream from our query, in case something else keeps a reference to it. */ /* Detach the stream from our query, in case something else keeps a reference to it. */
(void) set_remove(q->request_stream->queries, q); (void) set_remove(q->request_dns_stream->queries, q);
q->request_stream = dns_stream_unref(q->request_stream); q->request_dns_stream = dns_stream_unref(q->request_dns_stream);
} }
free(q->request_address_string); free(q->request_address_string);
@ -408,25 +375,17 @@ int dns_query_new(
DnsQuery **ret, DnsQuery **ret,
DnsQuestion *question_utf8, DnsQuestion *question_utf8,
DnsQuestion *question_idna, DnsQuestion *question_idna,
DnsPacket *question_bypass,
int ifindex, int ifindex,
uint64_t flags) { uint64_t flags) {
_cleanup_(dns_query_freep) DnsQuery *q = NULL; _cleanup_(dns_query_freep) DnsQuery *q = NULL;
char key_str[DNS_RESOURCE_KEY_STRING_MAX];
DnsResourceKey *key; DnsResourceKey *key;
bool good = false;
int r; int r;
char key_str[DNS_RESOURCE_KEY_STRING_MAX];
assert(m); assert(m);
if (question_bypass) {
/* It's either a "bypass" query, or a regular one, but can't be both. */
if (question_utf8 || question_idna)
return -EINVAL;
} else {
bool good = false;
if (dns_question_size(question_utf8) > 0) { if (dns_question_size(question_utf8) > 0) {
r = dns_question_is_valid_for_query(question_utf8); r = dns_question_is_valid_for_query(question_utf8);
if (r < 0) if (r < 0)
@ -457,7 +416,6 @@ int dns_query_new(
if (!good) /* don't allow empty queries */ if (!good) /* don't allow empty queries */
return -EINVAL; return -EINVAL;
}
if (m->n_dns_queries >= QUERIES_MAX) if (m->n_dns_queries >= QUERIES_MAX)
return -EBUSY; return -EBUSY;
@ -469,7 +427,6 @@ int dns_query_new(
*q = (DnsQuery) { *q = (DnsQuery) {
.question_utf8 = dns_question_ref(question_utf8), .question_utf8 = dns_question_ref(question_utf8),
.question_idna = dns_question_ref(question_idna), .question_idna = dns_question_ref(question_idna),
.question_bypass = dns_packet_ref(question_bypass),
.ifindex = ifindex, .ifindex = ifindex,
.flags = flags, .flags = flags,
.answer_dnssec_result = _DNSSEC_RESULT_INVALID, .answer_dnssec_result = _DNSSEC_RESULT_INVALID,
@ -477,11 +434,6 @@ int dns_query_new(
.answer_family = AF_UNSPEC, .answer_family = AF_UNSPEC,
}; };
if (question_bypass) {
DNS_QUESTION_FOREACH(key, question_bypass->question)
log_debug("Looking up bypass packet for %s.",
dns_resource_key_to_string(key, key_str, sizeof key_str));
} else {
/* First dump UTF8 question */ /* First dump UTF8 question */
DNS_QUESTION_FOREACH(key, question_utf8) DNS_QUESTION_FOREACH(key, question_utf8)
log_debug("Looking up RR for %s.", log_debug("Looking up RR for %s.",
@ -498,7 +450,6 @@ int dns_query_new(
log_debug("Looking up IDNA RR for %s.", log_debug("Looking up IDNA RR for %s.",
dns_resource_key_to_string(key, key_str, sizeof key_str)); dns_resource_key_to_string(key, key_str, sizeof key_str));
} }
}
LIST_PREPEND(queries, m->dns_queries, q); LIST_PREPEND(queries, m->dns_queries, q);
m->n_dns_queries++; m->n_dns_queries++;
@ -506,8 +457,8 @@ int dns_query_new(
if (ret) if (ret)
*ret = q; *ret = q;
q = NULL;
TAKE_PTR(q);
return 0; return 0;
} }
@ -608,12 +559,9 @@ static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
DNS_TRANSACTION_NOT_FOUND)) DNS_TRANSACTION_NOT_FOUND))
return 0; return 0;
if (FLAGS_SET(q->flags, SD_RESOLVED_NO_SYNTHESIZE))
return 0;
r = dns_synthesize_answer( r = dns_synthesize_answer(
q->manager, q->manager,
q->question_bypass ? q->question_bypass->question : q->question_utf8, q->question_utf8,
q->ifindex, q->ifindex,
&answer); &answer);
if (r == -ENXIO) { if (r == -ENXIO) {
@ -653,12 +601,9 @@ static int dns_query_try_etc_hosts(DnsQuery *q) {
/* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is /* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is
* done. The data from /etc/hosts hence takes precedence over the network. */ * done. The data from /etc/hosts hence takes precedence over the network. */
if (FLAGS_SET(q->flags, SD_RESOLVED_NO_SYNTHESIZE))
return 0;
r = manager_etc_hosts_lookup( r = manager_etc_hosts_lookup(
q->manager, q->manager,
q->question_bypass ? q->question_bypass->question : q->question_utf8, q->question_utf8,
&answer); &answer);
if (r <= 0) if (r <= 0)
return r; return r;
@ -812,7 +757,6 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
q->answer_dnssec_result = _DNSSEC_RESULT_INVALID; q->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
q->answer_authenticated = false; q->answer_authenticated = false;
q->answer_errno = c->error_code; q->answer_errno = c->error_code;
q->answer_full_packet = dns_packet_unref(q->answer_full_packet);
} }
SET_FOREACH(t, c->transactions) { SET_FOREACH(t, c->transactions) {
@ -820,24 +764,14 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
switch (t->state) { switch (t->state) {
case DNS_TRANSACTION_SUCCESS: { case DNS_TRANSACTION_SUCCESS: {
/* We found a successful reply, merge it into the answer */ /* We found a successfully reply, merge it into the answer */
if (state == DNS_TRANSACTION_SUCCESS) {
r = dns_answer_extend(&q->answer, t->answer); r = dns_answer_extend(&q->answer, t->answer);
if (r < 0) if (r < 0)
goto fail; goto fail;
} else {
/* Override non-successful previous answers */
dns_answer_unref(q->answer);
q->answer = dns_answer_ref(t->answer);
}
q->answer_rcode = t->answer_rcode; q->answer_rcode = t->answer_rcode;
q->answer_errno = 0; q->answer_errno = 0;
dns_packet_unref(q->answer_full_packet);
q->answer_full_packet = dns_packet_ref(t->received);
if (t->answer_authenticated) { if (t->answer_authenticated) {
has_authenticated = true; has_authenticated = true;
dnssec_result_authenticated = t->answer_dnssec_result; dnssec_result_authenticated = t->answer_dnssec_result;
@ -866,14 +800,11 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
if (q->answer_authenticated && !t->answer_authenticated) if (q->answer_authenticated && !t->answer_authenticated)
continue; continue;
dns_answer_unref(q->answer); q->answer = dns_answer_unref(q->answer);
q->answer = dns_answer_ref(t->answer);
q->answer_rcode = t->answer_rcode; q->answer_rcode = t->answer_rcode;
q->answer_dnssec_result = t->answer_dnssec_result; q->answer_dnssec_result = t->answer_dnssec_result;
q->answer_authenticated = t->answer_authenticated; q->answer_authenticated = t->answer_authenticated;
q->answer_errno = t->answer_errno; q->answer_errno = t->answer_errno;
dns_packet_unref(q->answer_full_packet);
q->answer_full_packet = dns_packet_ref(t->received);
state = t->state; state = t->state;
break; break;
@ -1067,9 +998,6 @@ int dns_query_process_cname(DnsQuery *q) {
DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol) { DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol) {
assert(q); assert(q);
if (q->question_bypass)
return q->question_bypass->question;
switch (protocol) { switch (protocol) {
case DNS_PROTOCOL_DNS: case DNS_PROTOCOL_DNS:
@ -1090,9 +1018,6 @@ const char *dns_query_string(DnsQuery *q) {
/* Returns a somewhat useful human-readable lookup key string for this query */ /* Returns a somewhat useful human-readable lookup key string for this query */
if (q->question_bypass)
return dns_question_first_name(q->question_bypass->question);
if (q->request_address_string) if (q->request_address_string)
return q->request_address_string; return q->request_address_string;

View File

@ -49,13 +49,12 @@ struct DnsQuery {
DnsQuestion *question_idna; DnsQuestion *question_idna;
DnsQuestion *question_utf8; DnsQuestion *question_utf8;
/* If this is not a question by ourselves, but a "bypass" request, we propagate the original packet
* here, and use that instead. */
DnsPacket *question_bypass;
uint64_t flags; uint64_t flags;
int ifindex; int ifindex;
/* If true, the RR TTLs of the answer will be clamped by their current left validity in the cache */
bool clamp_ttl;
DnsTransactionState state; DnsTransactionState state;
unsigned n_cname_redirects; unsigned n_cname_redirects;
@ -72,7 +71,6 @@ struct DnsQuery {
DnsSearchDomain *answer_search_domain; DnsSearchDomain *answer_search_domain;
int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */ int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */
bool previous_redirect_unauthenticated; bool previous_redirect_unauthenticated;
DnsPacket *answer_full_packet;
/* Bus + Varlink client information */ /* Bus + Varlink client information */
sd_bus_message *bus_request; sd_bus_message *bus_request;
@ -84,11 +82,9 @@ struct DnsQuery {
char *request_address_string; char *request_address_string;
/* DNS stub information */ /* DNS stub information */
DnsPacket *request_packet; DnsPacket *request_dns_packet;
DnsStream *request_stream; DnsStream *request_dns_stream;
DnsAnswer *reply_answer; DnsPacket *reply_dns_packet;
DnsAnswer *reply_authoritative;
DnsAnswer *reply_additional;
DnsStubListenerExtra *stub_listener_extra; DnsStubListenerExtra *stub_listener_extra;
/* Completion callback */ /* Completion callback */
@ -113,7 +109,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryCandidate*, dns_query_candidate_unref);
void dns_query_candidate_notify(DnsQueryCandidate *c); void dns_query_candidate_notify(DnsQueryCandidate *c);
int dns_query_new(Manager *m, DnsQuery **q, DnsQuestion *question_utf8, DnsQuestion *question_idna, DnsPacket *question_bypass, int family, uint64_t flags); int dns_query_new(Manager *m, DnsQuery **q, DnsQuestion *question_utf8, DnsQuestion *question_idna, int family, uint64_t flags);
DnsQuery *dns_query_free(DnsQuery *q); DnsQuery *dns_query_free(DnsQuery *q);
int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for); int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for);

View File

@ -646,10 +646,11 @@ bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key) {
assert(s); assert(s);
assert(key); assert(key);
/* Check if it makes sense to resolve the specified key on this scope. Note that this call assumes a /* Check if it makes sense to resolve the specified key on
* fully qualified name, i.e. the search suffixes already appended. */ * this scope. Note that this call assumes as fully qualified
* name, i.e. the search suffixes already appended. */
if (!IN_SET(key->class, DNS_CLASS_IN, DNS_CLASS_ANY)) if (key->class != DNS_CLASS_IN)
return false; return false;
if (s->protocol == DNS_PROTOCOL_DNS) { if (s->protocol == DNS_PROTOCOL_DNS) {
@ -671,7 +672,8 @@ bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key) {
return !dns_name_is_root(name); return !dns_name_is_root(name);
} }
/* On mDNS and LLMNR, send A and AAAA queries only on the respective scopes */ /* On mDNS and LLMNR, send A and AAAA queries only on the
* respective scopes */
key_family = dns_type_to_af(key->type); key_family = dns_type_to_af(key->type);
if (key_family < 0) if (key_family < 0)
@ -763,7 +765,6 @@ int dns_scope_make_reply_packet(
DnsPacket **ret) { DnsPacket **ret) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
unsigned n_answer = 0, n_soa = 0;
int r; int r;
assert(s); assert(s);
@ -795,15 +796,15 @@ int dns_scope_make_reply_packet(
return r; return r;
DNS_PACKET_HEADER(p)->qdcount = htobe16(dns_question_size(q)); DNS_PACKET_HEADER(p)->qdcount = htobe16(dns_question_size(q));
r = dns_packet_append_answer(p, answer, &n_answer); r = dns_packet_append_answer(p, answer);
if (r < 0) if (r < 0)
return r; return r;
DNS_PACKET_HEADER(p)->ancount = htobe16(n_answer); DNS_PACKET_HEADER(p)->ancount = htobe16(dns_answer_size(answer));
r = dns_packet_append_answer(p, soa, &n_soa); r = dns_packet_append_answer(p, soa);
if (r < 0) if (r < 0)
return r; return r;
DNS_PACKET_HEADER(p)->arcount = htobe16(n_soa); DNS_PACKET_HEADER(p)->arcount = htobe16(dns_answer_size(soa));
*ret = TAKE_PTR(p); *ret = TAKE_PTR(p);
@ -925,50 +926,26 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
} }
} }
DnsTransaction *dns_scope_find_transaction( DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok) {
DnsScope *scope, DnsTransaction *t;
DnsResourceKey *key,
uint64_t query_flags) {
DnsTransaction *first, *t;
assert(scope); assert(scope);
assert(key); assert(key);
/* Iterate through the list of transactions with a matching key */ /* Try to find an ongoing transaction that is a equal to the
first = hashmap_get(scope->transactions_by_key, key); * specified question */
LIST_FOREACH(transactions_by_key, t, first) { t = hashmap_get(scope->transactions_by_key, key);
if (!t)
return NULL;
/* These four flags must match exactly: we cannot use a validated response for a /* Refuse reusing transactions that completed based on cached
* non-validating client, and we cannot use a non-validated response for a validating * data instead of a real packet, if that's requested. */
* client. Similar, if the sources don't match things aren't usable either. */ if (!cache_ok &&
if (((query_flags ^ t->query_flags) & IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_RCODE_FAILURE) &&
(SD_RESOLVED_NO_VALIDATE| t->answer_source != DNS_TRANSACTION_NETWORK)
SD_RESOLVED_NO_ZONE| return NULL;
SD_RESOLVED_NO_TRUST_ANCHOR|
SD_RESOLVED_NO_NETWORK)) != 0)
continue;
/* We can reuse a primary query if a regular one is requested, but not vice versa */
if ((query_flags & SD_RESOLVED_REQUIRE_PRIMARY) &&
!(t->query_flags & SD_RESOLVED_REQUIRE_PRIMARY))
continue;
/* Don't reuse a transaction that allowed caching when we got told not to use it */
if ((query_flags & SD_RESOLVED_NO_CACHE) &&
!(t->query_flags & SD_RESOLVED_NO_CACHE))
continue;
/* If we are are asked to clamp ttls an the existing transaction doesn't do it, we can't
* reuse */
if ((query_flags & SD_RESOLVED_CLAMP_TTL) &&
!(t->query_flags & SD_RESOLVED_CLAMP_TTL))
continue;
return t; return t;
}
return NULL;
} }
static int dns_scope_make_conflict_packet( static int dns_scope_make_conflict_packet(
@ -1312,7 +1289,7 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) {
else else
flags = goodbye ? (DNS_ANSWER_GOODBYE|DNS_ANSWER_CACHE_FLUSH) : DNS_ANSWER_CACHE_FLUSH; flags = goodbye ? (DNS_ANSWER_GOODBYE|DNS_ANSWER_CACHE_FLUSH) : DNS_ANSWER_CACHE_FLUSH;
r = dns_answer_add(answer, i->rr, 0, flags, NULL); r = dns_answer_add(answer, i->rr, 0 , flags);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to add RR to announce: %m"); return log_debug_errno(r, "Failed to add RR to announce: %m");
} }
@ -1330,7 +1307,7 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) {
if (r < 0) if (r < 0)
log_warning_errno(r, "Failed to add DNS-SD PTR record to MDNS zone: %m"); log_warning_errno(r, "Failed to add DNS-SD PTR record to MDNS zone: %m");
r = dns_answer_add(answer, rr, 0, 0, NULL); r = dns_answer_add(answer, rr, 0 , 0);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to add RR to announce: %m"); return log_debug_errno(r, "Failed to add RR to announce: %m");
} }

View File

@ -53,12 +53,14 @@ struct DnsScope {
LIST_HEAD(DnsQueryCandidate, query_candidates); LIST_HEAD(DnsQueryCandidate, query_candidates);
/* Note that we keep track of ongoing transactions in two ways: once in a hashmap, indexed by the rr /* Note that we keep track of ongoing transactions in two
* key, and once in a linked list. We use the hashmap to quickly find transactions we can reuse for a * ways: once in a hashmap, indexed by the rr key, and once in
* key. But note that there might be multiple transactions for the same key (because the associated * a linked list. We use the hashmap to quickly find
* query flags might differ in incompatible ways: e.g. we may not reuse a non-validating transaction * transactions we can reuse for a key. But note that there
* as validating. Hence we maintain a per-key list of transactions, which we iterate through to find * might be multiple transactions for the same key (because
* one we can reuse with matching flags. */ * the zone probing can't reuse a transaction answered from
* the zone or the cache), and the hashmap only tracks the
* most recent entry. */
Hashmap *transactions_by_key; Hashmap *transactions_by_key;
LIST_HEAD(DnsTransaction, transactions); LIST_HEAD(DnsTransaction, transactions);
@ -88,7 +90,7 @@ int dns_scope_mdns_membership(DnsScope *s, bool b);
int dns_scope_make_reply_packet(DnsScope *s, uint16_t id, int rcode, DnsQuestion *q, DnsAnswer *answer, DnsAnswer *soa, bool tentative, DnsPacket **ret); int dns_scope_make_reply_packet(DnsScope *s, uint16_t id, int rcode, DnsQuestion *q, DnsAnswer *answer, DnsAnswer *soa, bool tentative, DnsPacket **ret);
void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p); void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p);
DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, uint64_t query_flags); DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok);
int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr); int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr);
void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p); void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p);

View File

@ -85,259 +85,69 @@ DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p) {
return mfree(p); return mfree(p);
} }
static int dns_stub_collect_answer_by_question(
DnsAnswer **reply,
DnsAnswer *answer,
DnsQuestion *question,
bool with_rrsig) { /* Add RRSIG RR matching each RR */
DnsAnswerItem *item;
int r;
assert(reply);
/* 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)
return r;
if (r > 0)
match = true;
}
if (!match)
continue;
}
r = dns_answer_add_extend(reply, item->rr, item->ifindex, item->flags, item->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;
}
}
return 0;
}
static int dns_stub_collect_answer_by_section(
DnsAnswer **reply,
DnsAnswer *answer,
DnsAnswerFlags section,
DnsAnswer *exclude1,
DnsAnswer *exclude2,
bool with_dnssec) { /* Include DNSSEC RRs. RRSIG, NSEC, … */
DnsAnswerItem *item;
unsigned c = 0;
int r;
assert(reply);
/* Copies all RRs from 'answer' into 'reply', if they originate from the specified section. Also,
* avoid any RRs listed in 'exclude'. */
DNS_ANSWER_FOREACH_ITEM(item, answer) {
if (dns_answer_contains(exclude1, item->rr) ||
dns_answer_contains(exclude2, item->rr))
continue;
if (!with_dnssec &&
dns_type_is_dnssec(item->rr->key->type))
continue;
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);
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;
}
static int dns_stub_assign_sections(
DnsQuery *q,
DnsQuestion *question,
bool edns0_do) {
int r;
assert(q);
assert(question);
/* Let's assign the 'answer' and 'answer_auxiliary' RRs we collected to their respective sections in
* the reply datagram. We try to reproduce a section assignment similar to what the upstream DNS
* server responded to us. We use the DNS_ANSWER_SECTION_xyz flags to match things up, which is where
* the original upstream's packet section assignment is stored in the DnsAnswer object. Not all RRs
* in the 'answer' and 'answer_auxiliary' objects come with section information though (for example,
* because they were synthesized locally, and not from a DNS packet). To deal with that we extend the
* assignment logic a bit: anything from the 'answer' object that directly matches the original
* question is always put in the ANSWER section, regardless if it carries section info, or what that
* section info says. Then, anything from the 'answer' and 'answer_auxiliary' objects that is from
* the ANSWER or AUTHORITY sections, and wasn't already added to the ANSWER section is placed in the
* AUTHORITY section. Everything else from either object is added to the ADDITIONAL section. */
/* Include all RRs that directly answer the question in the answer section */
r = dns_stub_collect_answer_by_question(
&q->reply_answer,
q->answer,
question,
edns0_do);
if (r < 0)
return r;
/* Include all RRs that originate from the answer or authority sections, and aren't listed in the
* answer section, in the authority section */
r = dns_stub_collect_answer_by_section(
&q->reply_authoritative,
q->answer,
DNS_ANSWER_SECTION_ANSWER,
q->reply_answer, NULL,
edns0_do);
if (r < 0)
return r;
/* Include all RRs that originate from the answer or authority sections, and aren't listed in the
* answer section, in the authority section */
r = dns_stub_collect_answer_by_section(
&q->reply_authoritative,
q->answer,
DNS_ANSWER_SECTION_AUTHORITY,
q->reply_answer, NULL,
edns0_do);
if (r < 0)
return r;
/* Include all RRs that originate from the additional sections in the additional section (except if
* already listed in the other two sections). Also add all RRs with no section marking. */
r = dns_stub_collect_answer_by_section(
&q->reply_additional,
q->answer,
DNS_ANSWER_SECTION_ADDITIONAL,
q->reply_answer, q->reply_authoritative,
edns0_do);
if (r < 0)
return r;
r = dns_stub_collect_answer_by_section(
&q->reply_additional,
q->answer,
0,
q->reply_answer, q->reply_authoritative,
edns0_do);
if (r < 0)
return r;
return 0;
}
static int dns_stub_make_reply_packet( static int dns_stub_make_reply_packet(
DnsPacket **ret, DnsPacket **p,
size_t max_size, size_t max_size,
DnsQuestion *q, DnsQuestion *q,
DnsAnswer *answer,
bool *ret_truncated) { bool *ret_truncated) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; bool truncated = false;
bool tc = false; DnsResourceRecord *rr;
int r; unsigned c = 0;
assert(ret);
r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0, max_size);
if (r < 0)
return r;
r = dns_packet_append_question(p, q);
if (r == -EMSGSIZE)
tc = true;
else if (r < 0)
return r;
if (ret_truncated)
*ret_truncated = tc;
else if (tc)
return -EMSGSIZE;
DNS_PACKET_HEADER(p)->qdcount = htobe16(dns_question_size(q));
*ret = TAKE_PTR(p);
return 0;
}
static int dns_stub_add_reply_packet_body(
DnsPacket *p,
DnsAnswer *answer,
DnsAnswer *authoritative,
DnsAnswer *additional,
bool edns0_do, /* Client expects DNSSEC RRs? */
bool *truncated) {
unsigned n_answer = 0, n_authoritative = 0, n_additional = 0;
bool tc = false;
int r; int r;
assert(p); assert(p);
/* Add the three sections to the packet. If the answer section doesn't fit we'll signal that as /* Note that we don't bother with any additional RRs, as this is stub is for local lookups only, and hence
* truncation. If the authoritative section doesn't fit and we are in DNSSEC mode, also signal * roundtrips aren't expensive. */
* truncation. In all other cases where things don't fit don't signal truncation, as for those cases
* the dropped RRs should not be essential. */
r = dns_packet_append_answer(p, answer, &n_answer); if (!*p) {
if (r == -EMSGSIZE) r = dns_packet_new(p, DNS_PROTOCOL_DNS, 0, max_size);
tc = true; if (r < 0)
else if (r < 0)
return r; return r;
else {
r = dns_packet_append_answer(p, authoritative, &n_authoritative); r = dns_packet_append_question(*p, q);
if (r < 0)
return r;
DNS_PACKET_HEADER(*p)->qdcount = htobe16(dns_question_size(q));
}
DNS_ANSWER_FOREACH(rr, answer) {
r = dns_question_matches_rr(q, rr, NULL);
if (r < 0)
return r;
if (r > 0)
goto add;
r = dns_question_matches_cname_or_dname(q, rr, NULL);
if (r < 0)
return r;
if (r > 0)
goto add;
continue;
add:
r = dns_packet_append_rr(*p, rr, 0, NULL, NULL);
if (r == -EMSGSIZE) { if (r == -EMSGSIZE) {
if (edns0_do) truncated = true;
tc = true; break;
} else if (r < 0)
return r;
else {
r = dns_packet_append_answer(p, additional, &n_additional);
if (r < 0 && r != -EMSGSIZE)
return r;
} }
if (r < 0)
return r;
c++;
} }
if (tc) { if (ret_truncated)
if (!truncated) *ret_truncated = truncated;
else if (truncated)
return -EMSGSIZE; return -EMSGSIZE;
*truncated = true; DNS_PACKET_HEADER(*p)->ancount = htobe16(be16toh(DNS_PACKET_HEADER(*p)->ancount) + c);
}
DNS_PACKET_HEADER(p)->ancount = htobe16(n_answer);
DNS_PACKET_HEADER(p)->nscount = htobe16(n_authoritative);
DNS_PACKET_HEADER(p)->arcount = htobe16(n_additional);
return 0; return 0;
} }
@ -349,7 +159,6 @@ static int dns_stub_finish_reply_packet(
bool add_opt, /* add an OPT RR to this packet? */ bool add_opt, /* add an OPT RR to this packet? */
bool edns0_do, /* set the EDNS0 DNSSEC OK bit? */ bool edns0_do, /* set the EDNS0 DNSSEC OK bit? */
bool ad, /* set the DNSSEC authenticated data bit? */ bool ad, /* set the DNSSEC authenticated data bit? */
bool cd, /* set the DNSSEC checking disabled bit? */
uint16_t max_udp_size) { /* The maximum UDP datagram size to advertise to clients */ uint16_t max_udp_size) { /* The maximum UDP datagram size to advertise to clients */
int r; int r;
@ -362,21 +171,19 @@ static int dns_stub_finish_reply_packet(
tc = true; tc = true;
else if (r < 0) else if (r < 0)
return r; return r;
} else { } else {
/* If the client can't to EDNS0, don't do DO either */ /* If the client can't to EDNS0, don't do DO either */
edns0_do = false; edns0_do = false;
/* If we don't do EDNS, clamp the rcode to 4 bit */ /* If the client didn't do EDNS, clamp the rcode to 4 bit */
if (rcode > 0xF) if (rcode > 0xF)
rcode = DNS_RCODE_SERVFAIL; rcode = DNS_RCODE_SERVFAIL;
} }
/* Don't set the AD or CD bit unless DO is on, too */ /* Don't set the AD bit unless DO is on, too */
if (!edns0_do) { if (!edns0_do)
ad = false; ad = false;
cd = false;
}
DNS_PACKET_HEADER(p)->id = id; DNS_PACKET_HEADER(p)->id = id;
@ -388,7 +195,7 @@ static int dns_stub_finish_reply_packet(
1 /* rd */, 1 /* rd */,
1 /* ra */, 1 /* ra */,
ad /* ad */, ad /* ad */,
cd /* cd */, 0 /* cd */,
rcode)); rcode));
return 0; return 0;
@ -424,66 +231,6 @@ static int dns_stub_send(
return 0; return 0;
} }
static int dns_stub_send_reply(
DnsQuery *q,
int rcode) {
_cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
bool truncated, edns0_do;
int r;
assert(q);
/* Reply with DNSSEC DO set? Only if client supports it; and we did any DNSSEC verification
* ourselves, or consider the data fully authenticated because we generated it locally, or
* the client set cd */
edns0_do =
DNS_PACKET_DO(q->request_packet) &&
(q->answer_dnssec_result >= 0 || /* we did proper DNSSEC validation … */
dns_query_fully_authenticated(q) || /* … or we considered it authentic otherwise … */
DNS_PACKET_CD(q->request_packet)); /* … or client set CD */
r = dns_stub_assign_sections(
q,
q->request_packet->question,
edns0_do);
if (r < 0)
return log_debug_errno(r, "Failed to assign sections: %m");
r = dns_stub_make_reply_packet(
&reply,
DNS_PACKET_PAYLOAD_SIZE_MAX(q->request_packet),
q->request_packet->question,
&truncated);
if (r < 0)
return log_debug_errno(r, "Failed to build reply packet: %m");
r = dns_stub_add_reply_packet_body(
reply,
q->reply_answer,
q->reply_authoritative,
q->reply_additional,
edns0_do,
&truncated);
if (r < 0)
return log_debug_errno(r, "Failed to append reply packet body: %m");
r = dns_stub_finish_reply_packet(
reply,
DNS_PACKET_ID(q->request_packet),
rcode,
truncated,
!!q->request_packet->opt,
edns0_do,
dns_query_fully_authenticated(q),
DNS_PACKET_CD(q->request_packet),
q->stub_listener_extra ? ADVERTISE_EXTRA_DATAGRAM_SIZE_MAX : ADVERTISE_DATAGRAM_SIZE_MAX);
if (r < 0)
return log_debug_errno(r, "Failed to build failure packet: %m");
return dns_stub_send(q->manager, q->stub_listener_extra, q->request_stream, q->request_packet, reply);
}
static int dns_stub_send_failure( static int dns_stub_send_failure(
Manager *m, Manager *m,
DnsStubListenerExtra *l, DnsStubListenerExtra *l,
@ -493,17 +240,12 @@ static int dns_stub_send_failure(
bool authenticated) { bool authenticated) {
_cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL; _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
bool truncated;
int r; int r;
assert(m); assert(m);
assert(p); assert(p);
r = dns_stub_make_reply_packet( r = dns_stub_make_reply_packet(&reply, DNS_PACKET_PAYLOAD_SIZE_MAX(p), p->question, NULL, NULL);
&reply,
DNS_PACKET_PAYLOAD_SIZE_MAX(p),
p->question,
&truncated);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to make failure packet: %m"); return log_debug_errno(r, "Failed to make failure packet: %m");
@ -511,11 +253,10 @@ static int dns_stub_send_failure(
reply, reply,
DNS_PACKET_ID(p), DNS_PACKET_ID(p),
rcode, rcode,
truncated, /* truncated = */ false,
!!p->opt, !!p->opt,
DNS_PACKET_DO(p), DNS_PACKET_DO(p),
authenticated, authenticated,
DNS_PACKET_CD(p),
l ? ADVERTISE_EXTRA_DATAGRAM_SIZE_MAX : ADVERTISE_DATAGRAM_SIZE_MAX); l ? ADVERTISE_EXTRA_DATAGRAM_SIZE_MAX : ADVERTISE_DATAGRAM_SIZE_MAX);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to build failure packet: %m"); return log_debug_errno(r, "Failed to build failure packet: %m");
@ -523,87 +264,27 @@ static int dns_stub_send_failure(
return dns_stub_send(m, l, s, p, reply); return dns_stub_send(m, l, s, p, reply);
} }
static int dns_stub_patch_bypass_reply_packet(
DnsPacket **ret, /* Where to place the patched packet */
DnsPacket *original, /* The packet to patch */
DnsPacket *request) { /* The packet the patched packet shall look like a reply to */
_cleanup_(dns_packet_unrefp) DnsPacket *c = NULL;
int r;
assert(ret);
assert(original);
assert(request);
r = dns_packet_dup(&c, original);
if (r < 0)
return r;
/* Extract the packet, so that we know where the OPT field is */
r = dns_packet_extract(c);
if (r < 0)
return r;
/* Copy over the original client request ID, so that we can make the upstream query look like our own reply. */
DNS_PACKET_HEADER(c)->id = DNS_PACKET_HEADER(request)->id;
/* Patch in our own maximum datagram size, if EDNS0 was on */
r = dns_packet_patch_max_udp_size(c, ADVERTISE_DATAGRAM_SIZE_MAX);
if (r < 0)
return r;
/* Lower all TTLs by the time passed since we received the datagram. */
if (timestamp_is_set(original->timestamp)) {
r = dns_packet_patch_ttls(c, original->timestamp);
if (r < 0)
return r;
}
/* Our upstream connection might have supported larger DNS requests than our downstream one, hence
* set the TC bit if our reply is larger than what the client supports, and truncate. */
if (c->size > DNS_PACKET_PAYLOAD_SIZE_MAX(request)) {
log_debug("Artificially truncating stub response, as advertised size of client is smaller than upstream one.");
dns_packet_truncate(c, DNS_PACKET_PAYLOAD_SIZE_MAX(request));
DNS_PACKET_HEADER(c)->flags = htobe16(be16toh(DNS_PACKET_HEADER(c)->flags) | DNS_PACKET_FLAG_TC);
}
*ret = TAKE_PTR(c);
return 0;
}
static void dns_stub_query_complete(DnsQuery *q) { static void dns_stub_query_complete(DnsQuery *q) {
int r; int r;
assert(q); assert(q);
assert(q->request_packet); assert(q->request_dns_packet);
if (q->question_bypass) {
/* This is a bypass reply. If so, let's propagate the upstream packet, if we have it and it
* is regular DNS. (We can't do this if the upstream packet is LLMNR or mDNS, since the
* packets are not 100% compatible.) */
if (q->answer_full_packet &&
q->answer_full_packet->protocol == DNS_PROTOCOL_DNS) {
_cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
r = dns_stub_patch_bypass_reply_packet(&reply, q->answer_full_packet, q->request_packet);
if (r < 0)
log_debug_errno(r, "Failed to patch bypass reply packet: %m");
else
(void) dns_stub_send(q->manager, q->stub_listener_extra, q->request_stream, q->request_packet, reply);
dns_query_free(q);
return;
}
}
switch (q->state) { switch (q->state) {
case DNS_TRANSACTION_SUCCESS: case DNS_TRANSACTION_SUCCESS: {
/* Follow CNAMEs, and accumulate answers. Except if DNSSEC is requested, then let the client do that. */ bool truncated;
if (!DNS_PACKET_DO(q->request_packet)) {
r = dns_stub_make_reply_packet(&q->reply_dns_packet, DNS_PACKET_PAYLOAD_SIZE_MAX(q->request_dns_packet), q->question_idna, q->answer, &truncated);
if (r < 0) {
log_debug_errno(r, "Failed to build reply packet: %m");
break;
}
if (!truncated) {
r = dns_query_process_cname(q); r = dns_query_process_cname(q);
if (r == -ELOOP) { /* CNAME loop */ if (r == -ELOOP) {
(void) dns_stub_send_reply(q, DNS_RCODE_SERVFAIL); (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false);
break; break;
} }
if (r < 0) { if (r < 0) {
@ -614,15 +295,30 @@ static void dns_stub_query_complete(DnsQuery *q) {
return; return;
} }
(void) dns_stub_send_reply(q, q->answer_rcode); r = dns_stub_finish_reply_packet(
q->reply_dns_packet,
DNS_PACKET_ID(q->request_dns_packet),
q->answer_rcode,
truncated,
!!q->request_dns_packet->opt,
DNS_PACKET_DO(q->request_dns_packet),
dns_query_fully_authenticated(q),
q->stub_listener_extra ? ADVERTISE_EXTRA_DATAGRAM_SIZE_MAX : ADVERTISE_DATAGRAM_SIZE_MAX);
if (r < 0) {
log_debug_errno(r, "Failed to finish reply packet: %m");
break; break;
}
(void) dns_stub_send(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, q->reply_dns_packet);
break;
}
case DNS_TRANSACTION_RCODE_FAILURE: case DNS_TRANSACTION_RCODE_FAILURE:
(void) dns_stub_send_reply(q, q->answer_rcode); (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, q->answer_rcode, dns_query_fully_authenticated(q));
break; break;
case DNS_TRANSACTION_NOT_FOUND: case DNS_TRANSACTION_NOT_FOUND:
(void) dns_stub_send_reply(q, DNS_RCODE_NXDOMAIN); (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_NXDOMAIN, dns_query_fully_authenticated(q));
break; break;
case DNS_TRANSACTION_TIMEOUT: case DNS_TRANSACTION_TIMEOUT:
@ -638,8 +334,7 @@ static void dns_stub_query_complete(DnsQuery *q) {
case DNS_TRANSACTION_NO_TRUST_ANCHOR: case DNS_TRANSACTION_NO_TRUST_ANCHOR:
case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED: case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED:
case DNS_TRANSACTION_NETWORK_DOWN: case DNS_TRANSACTION_NETWORK_DOWN:
case DNS_TRANSACTION_NO_SOURCE: (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false);
(void) dns_stub_send_reply(q, DNS_RCODE_SERVFAIL);
break; break;
case DNS_TRANSACTION_NULL: case DNS_TRANSACTION_NULL:
@ -703,13 +398,13 @@ static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStrea
if (dns_type_is_obsolete(p->question->keys[0]->type)) { if (dns_type_is_obsolete(p->question->keys[0]->type)) {
log_debug("Got message with obsolete key type, refusing."); log_debug("Got message with obsolete key type, refusing.");
dns_stub_send_failure(m, l, s, p, DNS_RCODE_REFUSED, false); dns_stub_send_failure(m, l, s, p, DNS_RCODE_NOTIMP, false);
return; return;
} }
if (dns_type_is_zone_transer(p->question->keys[0]->type)) { if (dns_type_is_zone_transer(p->question->keys[0]->type)) {
log_debug("Got request for zone transfer, refusing."); log_debug("Got request for zone transfer, refusing.");
dns_stub_send_failure(m, l, s, p, DNS_RCODE_REFUSED, false); dns_stub_send_failure(m, l, s, p, DNS_RCODE_NOTIMP, false);
return; return;
} }
@ -721,29 +416,23 @@ static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStrea
} }
if (DNS_PACKET_DO(p) && DNS_PACKET_CD(p)) { if (DNS_PACKET_DO(p) && DNS_PACKET_CD(p)) {
log_debug("Got request with DNSSEC checking disabled, enabling bypass logic."); log_debug("Got request with DNSSEC CD bit set, refusing.");
dns_stub_send_failure(m, l, s, p, DNS_RCODE_NOTIMP, false);
return;
}
r = dns_query_new(m, &q, NULL, NULL, p, 0, r = dns_query_new(m, &q, p->question, p->question, 0, SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_SEARCH);
SD_RESOLVED_PROTOCOLS_ALL|
SD_RESOLVED_NO_CNAME|
SD_RESOLVED_NO_SEARCH|
SD_RESOLVED_NO_VALIDATE|
SD_RESOLVED_REQUIRE_PRIMARY|
SD_RESOLVED_CLAMP_TTL);
} else
r = dns_query_new(m, &q, p->question, p->question, NULL, 0,
SD_RESOLVED_PROTOCOLS_ALL|
SD_RESOLVED_NO_SEARCH|
(DNS_PACKET_DO(p) ? SD_RESOLVED_NO_CNAME|SD_RESOLVED_REQUIRE_PRIMARY : 0)|
SD_RESOLVED_CLAMP_TTL);
if (r < 0) { if (r < 0) {
log_error_errno(r, "Failed to generate query object: %m"); log_error_errno(r, "Failed to generate query object: %m");
dns_stub_send_failure(m, l, s, p, DNS_RCODE_SERVFAIL, false); dns_stub_send_failure(m, l, s, p, DNS_RCODE_SERVFAIL, false);
return; return;
} }
q->request_packet = dns_packet_ref(p); /* Request that the TTL is corrected by the cached time for this lookup, so that we return vaguely useful TTLs */
q->request_stream = dns_stream_ref(s); /* make sure the stream stays around until we can send a reply through it */ q->clamp_ttl = true;
q->request_dns_packet = dns_packet_ref(p);
q->request_dns_stream = dns_stream_ref(s); /* make sure the stream stays around until we can send a reply through it */
q->stub_listener_extra = l; q->stub_listener_extra = l;
q->complete = dns_stub_query_complete; q->complete = dns_stub_query_complete;

View File

@ -76,7 +76,7 @@ static int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, int if
rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK); rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED, NULL); r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -90,7 +90,7 @@ static int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, int if
rr->aaaa.in6_addr = in6addr_loopback; rr->aaaa.in6_addr = in6addr_loopback;
r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED, NULL); r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -109,7 +109,7 @@ static int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to,
if (!rr->ptr.name) if (!rr->ptr.name)
return -ENOMEM; return -ENOMEM;
return dns_answer_add(*answer, rr, ifindex, flags, NULL); return dns_answer_add(*answer, rr, ifindex, flags);
} }
static int synthesize_localhost_ptr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) { static int synthesize_localhost_ptr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
@ -155,7 +155,7 @@ static int answer_add_addresses_rr(
if (r < 0) if (r < 0)
return r; return r;
r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED, NULL); r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -197,7 +197,7 @@ static int answer_add_addresses_ptr(
if (r < 0) if (r < 0)
return r; return r;
r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED, NULL); r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
if (r < 0) if (r < 0)
return r; return r;

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,6 @@
#include "in-addr-util.h" #include "in-addr-util.h"
typedef struct DnsTransaction DnsTransaction; typedef struct DnsTransaction DnsTransaction;
typedef struct DnsTransactionFinder DnsTransactionFinder;
typedef enum DnsTransactionState DnsTransactionState; typedef enum DnsTransactionState DnsTransactionState;
typedef enum DnsTransactionSource DnsTransactionSource; typedef enum DnsTransactionSource DnsTransactionSource;
@ -32,7 +31,6 @@ enum DnsTransactionState {
DNS_TRANSACTION_RR_TYPE_UNSUPPORTED, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED,
DNS_TRANSACTION_NETWORK_DOWN, DNS_TRANSACTION_NETWORK_DOWN,
DNS_TRANSACTION_NOT_FOUND, /* like NXDOMAIN, but when LLMNR/TCP connections fail */ DNS_TRANSACTION_NOT_FOUND, /* like NXDOMAIN, but when LLMNR/TCP connections fail */
DNS_TRANSACTION_NO_SOURCE, /* All suitable DnsTransactionSource turned off */
_DNS_TRANSACTION_STATE_MAX, _DNS_TRANSACTION_STATE_MAX,
_DNS_TRANSACTION_STATE_INVALID = -EINVAL, _DNS_TRANSACTION_STATE_INVALID = -EINVAL,
}; };
@ -51,10 +49,7 @@ enum DnsTransactionSource {
struct DnsTransaction { struct DnsTransaction {
DnsScope *scope; DnsScope *scope;
DnsResourceKey *key; /* For regular lookups the RR key to look for */ DnsResourceKey *key;
DnsPacket *bypass; /* For bypass lookups the full original request packet */
uint64_t query_flags;
DnsTransactionState state; DnsTransactionState state;
@ -65,6 +60,8 @@ struct DnsTransaction {
bool initial_jitter_scheduled:1; bool initial_jitter_scheduled:1;
bool initial_jitter_elapsed:1; bool initial_jitter_elapsed:1;
bool clamp_ttl:1;
bool probing:1; bool probing:1;
DnsPacket *sent, *received; DnsPacket *sent, *received;
@ -136,10 +133,9 @@ struct DnsTransaction {
LIST_FIELDS(DnsTransaction, transactions_by_scope); LIST_FIELDS(DnsTransaction, transactions_by_scope);
LIST_FIELDS(DnsTransaction, transactions_by_stream); LIST_FIELDS(DnsTransaction, transactions_by_stream);
LIST_FIELDS(DnsTransaction, transactions_by_key);
}; };
int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key, DnsPacket *bypass, uint64_t flags); int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key);
DnsTransaction* dns_transaction_free(DnsTransaction *t); DnsTransaction* dns_transaction_free(DnsTransaction *t);
bool dns_transaction_gc(DnsTransaction *t); bool dns_transaction_gc(DnsTransaction *t);
@ -154,23 +150,6 @@ void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source);
int dns_transaction_validate_dnssec(DnsTransaction *t); int dns_transaction_validate_dnssec(DnsTransaction *t);
int dns_transaction_request_dnssec_keys(DnsTransaction *t); int dns_transaction_request_dnssec_keys(DnsTransaction *t);
static inline DnsResourceKey *dns_transaction_key(DnsTransaction *t) {
assert(t);
/* Return the lookup key of this transaction. Either takes the lookup key from the bypass packet if
* we are a bypass transaction. Or take the configured key for regular transactions. */
if (t->key)
return t->key;
assert(t->bypass);
if (dns_question_isempty(t->bypass->question))
return NULL;
return t->bypass->question->keys[0];
}
const char* dns_transaction_state_to_string(DnsTransactionState p) _const_; const char* dns_transaction_state_to_string(DnsTransactionState p) _const_;
DnsTransactionState dns_transaction_state_from_string(const char *s) _pure_; DnsTransactionState dns_transaction_state_from_string(const char *s) _pure_;

View File

@ -60,7 +60,7 @@ static int add_root_ksk(
if (!rr->ds.digest) if (!rr->ds.digest)
return -ENOMEM; return -ENOMEM;
r = dns_answer_add(answer, rr, 0, DNS_ANSWER_AUTHENTICATED, NULL); r = dns_answer_add(answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
if (r < 0) if (r < 0)
return r; return r;
@ -354,7 +354,7 @@ static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, u
old_answer = hashmap_get(d->positive_by_key, rr->key); old_answer = hashmap_get(d->positive_by_key, rr->key);
answer = dns_answer_ref(old_answer); answer = dns_answer_ref(old_answer);
r = dns_answer_add_extend(&answer, rr, 0, DNS_ANSWER_AUTHENTICATED, NULL); r = dns_answer_add_extend(&answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to add trust anchor RR: %m"); return log_error_errno(r, "Failed to add trust anchor RR: %m");

View File

@ -170,10 +170,7 @@ static int dns_zone_item_probe_start(DnsZoneItem *i) {
if (i->probe_transaction) if (i->probe_transaction)
return 0; return 0;
t = dns_scope_find_transaction( t = dns_scope_find_transaction(i->scope, &DNS_RESOURCE_KEY_CONST(i->rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(i->rr->key)), false);
i->scope,
&DNS_RESOURCE_KEY_CONST(i->rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(i->rr->key)),
SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
if (!t) { if (!t) {
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
@ -181,7 +178,7 @@ static int dns_zone_item_probe_start(DnsZoneItem *i) {
if (!key) if (!key)
return -ENOMEM; return -ENOMEM;
r = dns_transaction_new(&t, i->scope, key, NULL, SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE); r = dns_transaction_new(&t, i->scope, key);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -299,7 +296,7 @@ static int dns_zone_add_authenticated_answer(DnsAnswer *a, DnsZoneItem *i, int i
else else
flags = DNS_ANSWER_AUTHENTICATED; flags = DNS_ANSWER_AUTHENTICATED;
return dns_answer_add(a, i->rr, ifindex, flags, NULL); return dns_answer_add(a, i->rr, ifindex, flags);
} }
int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, int ifindex, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) { int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, int ifindex, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {

View File

@ -406,7 +406,7 @@ int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer) {
if (!rr->ptr.name) if (!rr->ptr.name)
return -ENOMEM; return -ENOMEM;
r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED, NULL); r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -458,7 +458,7 @@ int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer) {
if (r < 0) if (r < 0)
return r; return r;
r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED, NULL); r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
if (r < 0) if (r < 0)
return r; return r;
} }

View File

@ -301,25 +301,25 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
rr->ttl = 1; rr->ttl = 1;
} }
t = dns_scope_find_transaction(scope, rr->key, SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE); t = dns_scope_find_transaction(scope, rr->key, false);
if (t) if (t)
dns_transaction_process_reply(t, p); dns_transaction_process_reply(t, p);
/* Also look for the various types of ANY transactions */ /* Also look for the various types of ANY transactions */
t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE); t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), false);
if (t) if (t)
dns_transaction_process_reply(t, p); dns_transaction_process_reply(t, p);
t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, rr->key->type, dns_resource_key_name(rr->key)), SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE); t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, rr->key->type, dns_resource_key_name(rr->key)), false);
if (t) if (t)
dns_transaction_process_reply(t, p); dns_transaction_process_reply(t, p);
t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE); t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), false);
if (t) if (t)
dns_transaction_process_reply(t, p); dns_transaction_process_reply(t, p);
} }
dns_cache_put(&scope->cache, scope->manager->enable_cache, NULL, DNS_PACKET_RCODE(p), p->answer, NULL, false, _DNSSEC_RESULT_INVALID, (uint32_t) -1, p->family, &p->sender); dns_cache_put(&scope->cache, scope->manager->enable_cache, NULL, DNS_PACKET_RCODE(p), p->answer, false, (uint32_t) -1, 0, p->family, &p->sender);
} else if (dns_packet_validate_query(p) > 0) { } else if (dns_packet_validate_query(p) > 0) {
log_debug("Got mDNS query packet for id %u", DNS_PACKET_ID(p)); log_debug("Got mDNS query packet for id %u", DNS_PACKET_ID(p));

View File

@ -57,9 +57,6 @@ static int reply_query_state(DnsQuery *q) {
case DNS_TRANSACTION_NETWORK_DOWN: case DNS_TRANSACTION_NETWORK_DOWN:
return varlink_error(q->varlink_request, "io.systemd.Resolve.NetworkDown", NULL); return varlink_error(q->varlink_request, "io.systemd.Resolve.NetworkDown", NULL);
case DNS_TRANSACTION_NO_SOURCE:
return varlink_error(q->varlink_request, "io.systemd.Resolve.NoSource", NULL);
case DNS_TRANSACTION_NOT_FOUND: case DNS_TRANSACTION_NOT_FOUND:
/* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we
* thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */ * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
@ -106,7 +103,7 @@ static bool validate_and_mangle_flags(
/* This checks that the specified client-provided flags parameter actually makes sense, and mangles /* This checks that the specified client-provided flags parameter actually makes sense, and mangles
* it slightly. Specifically: * it slightly. Specifically:
* *
* 1. We check that only the protocol flags and a bunch of NO_XYZ flags are on at most, plus the * 1. We check that only the protocol flags and the NO_CNAME flag are on at most, plus the
* method-specific flags specified in 'ok'. * method-specific flags specified in 'ok'.
* *
* 2. If no protocols are enabled we automatically convert that to "all protocols are enabled". * 2. If no protocols are enabled we automatically convert that to "all protocols are enabled".
@ -117,15 +114,7 @@ static bool validate_and_mangle_flags(
* "everything". * "everything".
*/ */
if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL| if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
SD_RESOLVED_NO_CNAME|
SD_RESOLVED_NO_VALIDATE|
SD_RESOLVED_NO_SYNTHESIZE|
SD_RESOLVED_NO_CACHE|
SD_RESOLVED_NO_ZONE|
SD_RESOLVED_NO_TRUST_ANCHOR|
SD_RESOLVED_NO_NETWORK|
ok))
return false; return false;
if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */ if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
@ -323,7 +312,7 @@ static int vl_method_resolve_hostname(Varlink *link, JsonVariant *parameters, Va
if (r < 0 && r != -EALREADY) if (r < 0 && r != -EALREADY)
return r; return r;
r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, NULL, p.ifindex, p.flags); r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, p.ifindex, p.flags);
if (r < 0) if (r < 0)
return r; return r;
@ -492,7 +481,7 @@ static int vl_method_resolve_address(Varlink *link, JsonVariant *parameters, Var
if (r < 0) if (r < 0)
return r; return r;
r = dns_query_new(m, &q, question, question, NULL, p.ifindex, p.flags|SD_RESOLVED_NO_SEARCH); r = dns_query_new(m, &q, question, question, p.ifindex, p.flags|SD_RESOLVED_NO_SEARCH);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -170,7 +170,7 @@ static void test_dnssec_verify_rfc8080_ed25519_example1(void) {
answer = dns_answer_new(1); answer = dns_answer_new(1);
assert_se(answer); assert_se(answer);
assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0); assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
assert_se(dnssec_verify_rrset(answer, mx->key, rrsig, dnskey, assert_se(dnssec_verify_rrset(answer, mx->key, rrsig, dnskey,
rrsig->rrsig.inception * USEC_PER_SEC, &result) >= 0); rrsig->rrsig.inception * USEC_PER_SEC, &result) >= 0);
@ -262,7 +262,7 @@ static void test_dnssec_verify_rfc8080_ed25519_example2(void) {
answer = dns_answer_new(1); answer = dns_answer_new(1);
assert_se(answer); assert_se(answer);
assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0); assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
assert_se(dnssec_verify_rrset(answer, mx->key, rrsig, dnskey, assert_se(dnssec_verify_rrset(answer, mx->key, rrsig, dnskey,
rrsig->rrsig.inception * USEC_PER_SEC, &result) >= 0); rrsig->rrsig.inception * USEC_PER_SEC, &result) >= 0);
@ -344,7 +344,7 @@ static void test_dnssec_verify_rrset(void) {
answer = dns_answer_new(1); answer = dns_answer_new(1);
assert_se(answer); assert_se(answer);
assert_se(dns_answer_add(answer, a, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0); assert_se(dns_answer_add(answer, a, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
/* Validate the RR as it if was 2015-12-2 today */ /* Validate the RR as it if was 2015-12-2 today */
assert_se(dnssec_verify_rrset(answer, a->key, rrsig, dnskey, 1449092754*USEC_PER_SEC, &result) >= 0); assert_se(dnssec_verify_rrset(answer, a->key, rrsig, dnskey, 1449092754*USEC_PER_SEC, &result) >= 0);
@ -436,7 +436,7 @@ static void test_dnssec_verify_rrset2(void) {
answer = dns_answer_new(1); answer = dns_answer_new(1);
assert_se(answer); assert_se(answer);
assert_se(dns_answer_add(answer, nsec, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0); assert_se(dns_answer_add(answer, nsec, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
/* Validate the RR as it if was 2015-12-11 today */ /* Validate the RR as it if was 2015-12-11 today */
assert_se(dnssec_verify_rrset(answer, nsec->key, rrsig, dnskey, 1449849318*USEC_PER_SEC, &result) >= 0); assert_se(dnssec_verify_rrset(answer, nsec->key, rrsig, dnskey, 1449849318*USEC_PER_SEC, &result) >= 0);
@ -563,10 +563,10 @@ static void test_dnssec_verify_rrset3(void) {
answer = dns_answer_new(4); answer = dns_answer_new(4);
assert_se(answer); assert_se(answer);
assert_se(dns_answer_add(answer, mx1, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0); assert_se(dns_answer_add(answer, mx1, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
assert_se(dns_answer_add(answer, mx2, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0); assert_se(dns_answer_add(answer, mx2, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
assert_se(dns_answer_add(answer, mx3, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0); assert_se(dns_answer_add(answer, mx3, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
assert_se(dns_answer_add(answer, mx4, 0, DNS_ANSWER_AUTHENTICATED, NULL) >= 0); assert_se(dns_answer_add(answer, mx4, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
/* Validate the RR as it if was 2020-02-24 today */ /* Validate the RR as it if was 2020-02-24 today */
assert_se(dnssec_verify_rrset(answer, mx1->key, rrsig, dnskey, 1582534685*USEC_PER_SEC, &result) >= 0); assert_se(dnssec_verify_rrset(answer, mx1->key, rrsig, dnskey, 1582534685*USEC_PER_SEC, &result) >= 0);

View File

@ -127,7 +127,6 @@ FallbackLeaseLifetimeSec=
UseAddress= UseAddress=
UseNTP= UseNTP=
UseDNS= UseDNS=
UseFQDN=
RapidCommit= RapidCommit=
ForceDHCPv6PDOtherInformation= ForceDHCPv6PDOtherInformation=
PrefixDelegationHint= PrefixDelegationHint=