839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering/***
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering This file is part of systemd.
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering Copyright 2014 Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart 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
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
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***/
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#include "alloc-util.h"
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#include "hostname-util.h"
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#include "local-addresses.h"
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering#include "resolved-dns-synthesize.h"
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringint dns_synthesize_ifindex(int ifindex) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
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. */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (ifindex > 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return ifindex;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return LOOPBACK_IFINDEX;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering}
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringint dns_synthesize_family(uint64_t flags) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
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 * here. */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (!(flags & SD_RESOLVED_DNS)) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (flags & (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_MDNS_IPV4))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return AF_INET;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (flags & (SD_RESOLVED_LLMNR_IPV6|SD_RESOLVED_MDNS_IPV6))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return AF_INET6;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering }
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return AF_UNSPEC;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering}
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart PoetteringDnsProtocol dns_synthesize_protocol(uint64_t flags) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
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 Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (flags & SD_RESOLVED_DNS)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return DNS_PROTOCOL_DNS;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (flags & SD_RESOLVED_LLMNR)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return DNS_PROTOCOL_LLMNR;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (flags & SD_RESOLVED_MDNS)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return DNS_PROTOCOL_MDNS;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return DNS_PROTOCOL_DNS;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering}
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering int r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(m);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(key);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_answer_reserve(answer, 2);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
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
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (!rr)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return -ENOMEM;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering }
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
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
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (!rr)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return -ENOMEM;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering rr->aaaa.in6_addr = in6addr_loopback;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering }
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return 0;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering}
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
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
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (!rr)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return -ENOMEM;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering rr->ptr.name = strdup(to);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (!rr->ptr.name)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return -ENOMEM;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return dns_answer_add(*answer, rr, ifindex, flags);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering}
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int synthesize_localhost_ptr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering int r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(m);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(key);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_answer_reserve(answer, 1);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering }
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return 0;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering}
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int answer_add_addresses_rr(
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering DnsAnswer **answer,
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering const char *name,
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering struct local_address *addresses,
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering unsigned n_addresses) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering unsigned j;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering int r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(name);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_answer_reserve(answer, n_addresses);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering for (j = 0; j < n_addresses; j++) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering }
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return 0;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering}
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringstatic int answer_add_addresses_ptr(
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering DnsAnswer **answer,
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering const char *name,
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering struct local_address *addresses,
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering unsigned n_addresses,
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering int af, const union in_addr_union *match) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering unsigned j;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering int r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(name);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering for (j = 0; j < n_addresses; j++) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (af != AF_UNSPEC) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (addresses[j].family != af)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering continue;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (match && !in_addr_equal(af, match, &addresses[j].address))
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering continue;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering }
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_answer_reserve(answer, 1);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering }
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return 0;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering}
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
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 int n = 0, af;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(m);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(key);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering af = dns_type_to_af(key->type);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (af >= 0) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering n = local_addresses(m->rtnl, ifindex, af, &addresses);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (n < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return n;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (n == 0) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering struct local_address buffer[2];
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* If we have no local addresses then use ::1
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * and 127.0.0.2 as local ones. */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (af == AF_INET || af == AF_UNSPEC)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering buffer[n++] = (struct local_address) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering .family = AF_INET,
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering .ifindex = dns_synthesize_ifindex(ifindex),
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering .address.in.s_addr = htobe32(0x7F000002),
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering };
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (af == AF_INET6 || af == AF_UNSPEC)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering buffer[n++] = (struct local_address) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering .family = AF_INET6,
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering .ifindex = dns_synthesize_ifindex(ifindex),
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering .address.in6 = in6addr_loopback,
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering };
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering }
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering }
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering}
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
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 int n, r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(m);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(address);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering /* Always map the IPv4 address 127.0.0.2 to the local
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering * hostname, in addition to "localhost": */
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = dns_answer_reserve(answer, 3);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->llmnr_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->mdns_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return 0;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering }
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering n = local_addresses(m->rtnl, ifindex, af, &addresses);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (n < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return n;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = answer_add_addresses_ptr(answer, m->llmnr_hostname, addresses, n, af, address);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return answer_add_addresses_ptr(answer, m->mdns_hostname, addresses, n, af, address);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering}
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
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 int n = 0, af;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(m);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(key);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering af = dns_type_to_af(key->type);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (af >= 0) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering n = local_gateways(m->rtnl, ifindex, af, &addresses);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (n < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return n;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering }
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering}
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
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 int n;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(m);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(address);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering n = local_gateways(m->rtnl, ifindex, af, &addresses);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (n < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return n;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering}
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poetteringint dns_synthesize_answer(
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering Manager *m,
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering DnsQuestion *q,
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering int ifindex,
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering DnsAnswer **ret) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering DnsResourceKey *key;
528e685ebd3657f2531f8666c9e4bba6fbd38acdLennart Poettering bool found = false;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering int r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(m);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering assert(q);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering DNS_QUESTION_FOREACH(key, q) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering union in_addr_union address;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering const char *name;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering int af;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (key->class != DNS_CLASS_IN &&
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering key->class != DNS_CLASS_ANY)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering continue;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering name = DNS_RESOURCE_KEY_NAME(key);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (is_localhost(name)) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = synthesize_localhost_rr(m, key, ifindex, &answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering } else if (manager_is_own_hostname(m, name)) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = synthesize_system_hostname_rr(m, key, ifindex, &answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return log_error_errno(r, "Failed to synthesize system hostname RRs: %m");
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering } else if (is_gateway_hostname(name)) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = synthesize_gateway_rr(m, key, ifindex, &answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
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
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = synthesize_localhost_ptr(m, key, ifindex, &answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering } else if (dns_name_address(name, &af, &address) > 0) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = synthesize_system_hostname_ptr(m, af, &address, ifindex, &answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m");
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering r = synthesize_gateway_ptr(m, af, &address, ifindex, &answer);
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (r < 0)
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m");
528e685ebd3657f2531f8666c9e4bba6fbd38acdLennart Poettering } else
528e685ebd3657f2531f8666c9e4bba6fbd38acdLennart Poettering continue;
528e685ebd3657f2531f8666c9e4bba6fbd38acdLennart Poettering
528e685ebd3657f2531f8666c9e4bba6fbd38acdLennart Poettering found = true;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering }
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
528e685ebd3657f2531f8666c9e4bba6fbd38acdLennart Poettering r = found;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering if (ret) {
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering *ret = answer;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering answer = NULL;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering }
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering return r;
839a4a20d8b4f6ebf3a342fd05c821358be5a313Lennart Poettering}