839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering This file is part of systemd.
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering Copyright 2014 Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering systemd is free software; you can redistribute it and/or modify it
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering under the terms of the GNU Lesser General Public License as published by
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering (at your option) any later version.
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering systemd is distributed in the hope that it will be useful, but
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering Lesser General Public License for more details.
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering You should have received a copy of the GNU Lesser General Public License
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* When the caller asked for resolving on a specific
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * interface, we synthesize the answer for that
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * interface. However, if nothing specific was claimed and we
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * only return localhost RRs, we synthesize the answer for
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * localhost. */
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringint dns_synthesize_family(uint64_t flags) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* Picks an address family depending on set flags. This is
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * purely for synthesized answers, where the family we return
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * for the reply should match what was requested in the
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * question, even though we are synthesizing the answer
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (flags & (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_MDNS_IPV4))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (flags & (SD_RESOLVED_LLMNR_IPV6|SD_RESOLVED_MDNS_IPV6))
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart PoetteringDnsProtocol dns_synthesize_protocol(uint64_t flags) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering /* Similar as dns_synthesize_family() but does this for the
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * protocol. If resolving via DNS was requested, we claim it
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * was DNS. Similar, if nothing specific was
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * requested. However, if only resolving via LLMNR was
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * requested we return that. */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY)) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to, int ifindex, DnsAnswerFlags flags) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return dns_answer_add(*answer, rr, ifindex, flags);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int synthesize_localhost_ptr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_answer_reserve(answer, n_addresses);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering for (j = 0; j < n_addresses; j++) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering int af, const union in_addr_union *match) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering for (j = 0; j < n_addresses; j++) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (match && !in_addr_equal(af, match, &addresses[j].address))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int synthesize_system_hostname_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering n = local_addresses(m->rtnl, ifindex, af, &addresses);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* If we have no local addresses then use ::1
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * and 127.0.0.2 as local ones. */
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering .ifindex = dns_synthesize_ifindex(ifindex),
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering .address.in.s_addr = htobe32(0x7F000002),
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering .ifindex = dns_synthesize_ifindex(ifindex),
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int synthesize_system_hostname_ptr(Manager *m, int af, const union in_addr_union *address, int ifindex, DnsAnswer **answer) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* Always map the IPv4 address 127.0.0.2 to the local
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * hostname, in addition to "localhost": */
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->llmnr_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->mdns_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering n = local_addresses(m->rtnl, ifindex, af, &addresses);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = answer_add_addresses_ptr(answer, m->llmnr_hostname, addresses, n, af, address);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return answer_add_addresses_ptr(answer, m->mdns_hostname, addresses, n, af, address);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int synthesize_gateway_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering n = local_gateways(m->rtnl, ifindex, af, &addresses);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int synthesize_gateway_ptr(Manager *m, int af, const union in_addr_union *address, int ifindex, DnsAnswer **answer) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering n = local_gateways(m->rtnl, ifindex, af, &addresses);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = synthesize_localhost_rr(m, key, ifindex, &answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering } else if (manager_is_own_hostname(m, name)) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = synthesize_system_hostname_rr(m, key, ifindex, &answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return log_error_errno(r, "Failed to synthesize system hostname RRs: %m");
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = synthesize_gateway_rr(m, key, ifindex, &answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering } else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering 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) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = synthesize_localhost_ptr(m, key, ifindex, &answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering } else if (dns_name_address(name, &af, &address) > 0) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = synthesize_system_hostname_ptr(m, af, &address, ifindex, &answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m");
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = synthesize_gateway_ptr(m, af, &address, ifindex, &answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m");