summaryrefslogtreecommitdiff
path: root/src/resolve/resolved-dns-query.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-01-20 22:06:26 +0100
committerLennart Poettering <lennart@poettering.net>2016-01-25 15:59:40 +0100
commit839a4a20d8b4f6ebf3a342fd05c821358be5a313 (patch)
tree98a242768ad282c69c7c07327f533792508b93da /src/resolve/resolved-dns-query.c
parentd07b43a18e2234e8abebc1cd4d93bfd78ab62001 (diff)
resolved: split out RR synthesis logic into its own C file
Also, while we are at it, set the "authenticated" bit for everything we synthesize
Diffstat (limited to 'src/resolve/resolved-dns-query.c')
-rw-r--r--src/resolve/resolved-dns-query.c386
1 files changed, 18 insertions, 368 deletions
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c
index 47f1924702..2f9dd1c47b 100644
--- a/src/resolve/resolved-dns-query.c
+++ b/src/resolve/resolved-dns-query.c
@@ -24,6 +24,7 @@
#include "hostname-util.h"
#include "local-addresses.h"
#include "resolved-dns-query.h"
+#include "resolved-dns-synthesize.h"
#include "string-util.h"
/* How long to wait for the query in total */
@@ -547,328 +548,15 @@ fail:
return r;
}
-static int SYNTHESIZE_IFINDEX(int ifindex) {
-
- /* When the caller asked for resolving on a specific
- * interface, we synthesize the answer for that
- * interface. However, if nothing specific was claimed and we
- * only return localhost RRs, we synthesize the answer for
- * localhost. */
-
- if (ifindex > 0)
- return ifindex;
-
- return LOOPBACK_IFINDEX;
-}
-
-static int SYNTHESIZE_FAMILY(uint64_t flags) {
-
- /* Picks an address family depending on set flags. This is
- * purely for synthesized answers, where the family we return
- * for the reply should match what was requested in the
- * question, even though we are synthesizing the answer
- * here. */
-
- if (!(flags & SD_RESOLVED_DNS)) {
- if (flags & SD_RESOLVED_LLMNR_IPV4)
- return AF_INET;
- if (flags & SD_RESOLVED_LLMNR_IPV6)
- return AF_INET6;
- }
-
- return AF_UNSPEC;
-}
-
-static DnsProtocol SYNTHESIZE_PROTOCOL(uint64_t flags) {
-
- /* Similar as SYNTHESIZE_FAMILY() but does this for the
- * protocol. If resolving via DNS was requested, we claim it
- * was DNS. Similar, if nothing specific was
- * requested. However, if only resolving via LLMNR was
- * requested we return that. */
-
- if (flags & SD_RESOLVED_DNS)
- return DNS_PROTOCOL_DNS;
- if (flags & SD_RESOLVED_LLMNR)
- return DNS_PROTOCOL_LLMNR;
-
- return DNS_PROTOCOL_DNS;
-}
-
-static int synthesize_localhost_rr(DnsQuery *q, const DnsResourceKey *key, DnsAnswer **answer) {
- int r;
-
- assert(q);
- assert(key);
- assert(answer);
-
- r = dns_answer_reserve(answer, 2);
- if (r < 0)
- return r;
-
- if (IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY)) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
-
- rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
- if (!rr)
- return -ENOMEM;
-
- rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
-
- r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex), DNS_ANSWER_AUTHENTICATED);
- if (r < 0)
- return r;
- }
-
- if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
-
- rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
- if (!rr)
- return -ENOMEM;
-
- rr->aaaa.in6_addr = in6addr_loopback;
-
- r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex), DNS_ANSWER_AUTHENTICATED);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to, int ifindex, DnsAnswerFlags flags) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
-
- rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from);
- if (!rr)
- return -ENOMEM;
-
- rr->ptr.name = strdup(to);
- if (!rr->ptr.name)
- return -ENOMEM;
-
- return dns_answer_add(*answer, rr, ifindex, flags);
-}
-
-static int synthesize_localhost_ptr(DnsQuery *q, const DnsResourceKey *key, DnsAnswer **answer) {
- int r;
-
- assert(q);
- assert(key);
- assert(answer);
-
- if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) {
- r = dns_answer_reserve(answer, 1);
- if (r < 0)
- return r;
-
- r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", SYNTHESIZE_IFINDEX(q->ifindex), DNS_ANSWER_AUTHENTICATED);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int answer_add_addresses_rr(
- DnsAnswer **answer,
- const char *name,
- struct local_address *addresses,
- unsigned n_addresses) {
-
- unsigned j;
- int r;
-
- assert(answer);
- assert(name);
-
- r = dns_answer_reserve(answer, n_addresses);
- if (r < 0)
- return r;
-
- for (j = 0; j < n_addresses; j++) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
-
- r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name);
- if (r < 0)
- return r;
-
- r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int answer_add_addresses_ptr(
- DnsAnswer **answer,
- const char *name,
- struct local_address *addresses,
- unsigned n_addresses,
- int af, const union in_addr_union *match) {
-
- unsigned j;
- int r;
-
- assert(answer);
- assert(name);
-
- for (j = 0; j < n_addresses; j++) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
-
- if (af != AF_UNSPEC) {
-
- if (addresses[j].family != af)
- continue;
-
- if (match && !in_addr_equal(af, match, &addresses[j].address))
- continue;
- }
-
- r = dns_answer_reserve(answer, 1);
- if (r < 0)
- return r;
-
- r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name);
- if (r < 0)
- return r;
-
- r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int synthesize_system_hostname_rr(DnsQuery *q, const DnsResourceKey *key, DnsAnswer **answer) {
- _cleanup_free_ struct local_address *addresses = NULL;
- int n = 0, af;
-
- assert(q);
- assert(key);
- assert(answer);
-
- af = dns_type_to_af(key->type);
- if (af >= 0) {
- n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
- if (n < 0)
- return n;
-
- if (n == 0) {
- struct local_address buffer[2];
-
- /* If we have no local addresses then use ::1
- * and 127.0.0.2 as local ones. */
-
- if (af == AF_INET || af == AF_UNSPEC)
- buffer[n++] = (struct local_address) {
- .family = AF_INET,
- .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
- .address.in.s_addr = htobe32(0x7F000002),
- };
-
- if (af == AF_INET6 || af == AF_UNSPEC)
- buffer[n++] = (struct local_address) {
- .family = AF_INET6,
- .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
- .address.in6 = in6addr_loopback,
- };
-
- return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
- }
- }
-
- return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
-}
-
-static int synthesize_system_hostname_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
- _cleanup_free_ struct local_address *addresses = NULL;
- int n, r;
-
- assert(q);
- assert(address);
- assert(answer);
-
- if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
-
- /* Always map the IPv4 address 127.0.0.2 to the local
- * hostname, in addition to "localhost": */
-
- r = dns_answer_reserve(answer, 3);
- if (r < 0)
- return r;
-
- r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->llmnr_hostname, SYNTHESIZE_IFINDEX(q->ifindex), DNS_ANSWER_AUTHENTICATED);
- if (r < 0)
- return r;
-
- r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->mdns_hostname, SYNTHESIZE_IFINDEX(q->ifindex), DNS_ANSWER_AUTHENTICATED);
- if (r < 0)
- return r;
-
- r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", SYNTHESIZE_IFINDEX(q->ifindex), DNS_ANSWER_AUTHENTICATED);
- if (r < 0)
- return r;
-
- return 0;
- }
-
- n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
- if (n < 0)
- return n;
-
- r = answer_add_addresses_ptr(answer, q->manager->llmnr_hostname, addresses, n, af, address);
- if (r < 0)
- return r;
-
- return answer_add_addresses_ptr(answer, q->manager->mdns_hostname, addresses, n, af, address);
-}
-
-static int synthesize_gateway_rr(DnsQuery *q, const DnsResourceKey *key, DnsAnswer **answer) {
- _cleanup_free_ struct local_address *addresses = NULL;
- int n = 0, af;
-
- assert(q);
- assert(key);
- assert(answer);
-
- af = dns_type_to_af(key->type);
- if (af >= 0) {
- n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
- if (n < 0)
- return n;
- }
-
- return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
-}
-
-static int synthesize_gateway_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
- _cleanup_free_ struct local_address *addresses = NULL;
- int n;
-
- assert(q);
- assert(address);
- assert(answer);
-
- n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
- if (n < 0)
- return n;
-
- return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
-}
-
static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- DnsResourceKey *key;
- int r;
+ DnsProtocol protocol;
+ int family, r;
assert(q);
assert(state);
- /* Tries to synthesize localhost RR replies where appropriate */
+ /* Tries to synthesize localhost RR replies (and others) where appropriate */
if (!IN_SET(*state,
DNS_TRANSACTION_RCODE_FAILURE,
@@ -878,64 +566,26 @@ static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
DNS_TRANSACTION_NETWORK_DOWN))
return 0;
- DNS_QUESTION_FOREACH(key, q->question_utf8) {
- union in_addr_union address;
- const char *name;
- int af;
-
- if (key->class != DNS_CLASS_IN &&
- key->class != DNS_CLASS_ANY)
- continue;
-
- name = DNS_RESOURCE_KEY_NAME(key);
+ r = dns_synthesize_answer(
+ q->manager,
+ q->question_utf8,
+ q->ifindex,
+ q->flags,
+ &answer,
+ &protocol,
+ &family);
- if (is_localhost(name)) {
-
- r = synthesize_localhost_rr(q, key, &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
-
- } else if (manager_is_own_hostname(q->manager, name)) {
-
- r = synthesize_system_hostname_rr(q, key, &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize system hostname RRs: %m");
-
- } else if (is_gateway_hostname(name)) {
-
- r = synthesize_gateway_rr(q, key, &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
-
- } else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
- dns_name_equal(name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) {
-
- r = synthesize_localhost_ptr(q, key, &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
-
- } else if (dns_name_address(name, &af, &address) > 0) {
-
- r = synthesize_system_hostname_ptr(q, af, &address, &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m");
-
- r = synthesize_gateway_ptr(q, af, &address, &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m");
- }
- }
+ if (r <= 0)
+ return r;
- if (!answer)
- return 0;
+ dns_query_reset_answer(q);
- dns_answer_unref(q->answer);
q->answer = answer;
answer = NULL;
-
q->answer_rcode = DNS_RCODE_SUCCESS;
- q->answer_protocol = SYNTHESIZE_PROTOCOL(q->flags);
- q->answer_family = SYNTHESIZE_FAMILY(q->flags);
+ q->answer_protocol = protocol;
+ q->answer_family = family;
+ q->answer_authenticated = true;
*state = DNS_TRANSACTION_SUCCESS;