resolved-bus.c revision 801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47dd
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/***
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering This file is part of systemd.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Copyright 2014 Lennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is free software; you can redistribute it and/or modify it
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering under the terms of the GNU Lesser General Public License as published by
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (at your option) any later version.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is distributed in the hope that it will be useful, but
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Lesser General Public License for more details.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering You should have received a copy of the GNU Lesser General Public License
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering***/
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
a9cdc94f7ff40f22a3cf9472f612a80730a1b010Dave Reisner#include "alloc-util.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "bus-common-errors.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "bus-util.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "dns-domain.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "resolved-bus.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "resolved-def.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int reply_query_state(DnsQuery *q) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_free_ char *ip = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *name;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->request_address_valid) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = in_addr_to_string(q->request_family, &q->request_address, &ip);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering name = ip;
0affed79d2e30013f07cb94e6f07e3fcb81c02faLennart Poettering } else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering name = dns_question_first_name(q->question);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering switch (q->state) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering case DNS_TRANSACTION_NO_SERVERS:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering case DNS_TRANSACTION_TIMEOUT:
7085053a437456ab87d726f3697002dd811fdf7aDaniel Wallace return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
7085053a437456ab87d726f3697002dd811fdf7aDaniel Wallace
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering case DNS_TRANSACTION_INVALID_REPLY:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering case DNS_TRANSACTION_RESOURCES:
1b12a7b5896f94bdf33b3a6661ebabd761ea6adcHarald Hoyer return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_RESOURCES, "Not enough resources");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering case DNS_TRANSACTION_ABORTED:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering case DNS_TRANSACTION_FAILURE: {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *rc, *n;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char p[3]; /* the rcode is 4 bits long */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering rc = dns_rcode_to_string(q->answer_rcode);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!rc) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sprintf(p, "%i", q->answer_rcode);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering rc = p;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering n = strjoina(_BUS_ERROR_DNS, rc);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, rc);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_reply_method_error(q->request, &error);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering case DNS_TRANSACTION_NULL:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering case DNS_TRANSACTION_PENDING:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering case DNS_TRANSACTION_SUCCESS:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering default:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert_not_reached("Impossible state");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(rr);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_open_container(reply, 'r', "iiay");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(reply, "i", ifindex);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (rr->key->type == DNS_TYPE_A) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(reply, "i", AF_INET);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else if (rr->key->type == DNS_TYPE_AAAA) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(reply, "i", AF_INET6);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EAFNOSUPPORT;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_close_container(reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic void bus_method_resolve_hostname_complete(DnsQuery *q) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned added = 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->state != DNS_TRANSACTION_SUCCESS) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = reply_query_state(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_query_process_cname(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == -ELOOP) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r > 0) /* This was a cname, and the query was restarted. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_new_method_return(q->request, &reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_open_container(reply, 'a', "(iiay)");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->answer) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DnsResourceRecord *rr;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int ifindex;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_matches_rr(q->question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering continue;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = append_address(reply, rr, ifindex);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!canonical)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering canonical = dns_resource_record_ref(rr);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering added ++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (added <= 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_question_first_name(q->question));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_close_container(reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Return the precise spelling and uppercasing and CNAME target reported by the server */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(canonical);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering reply, "st",
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DNS_RESOURCE_KEY_NAME(canonical->key),
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_send(q->manager->bus, reply, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringfinish:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error_errno(r, "Failed to send hostname reply: %m");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_bus_reply_method_errno(q->request, r, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering dns_query_free(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int check_ifindex_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(flags);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (ifindex < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *flags |= SD_RESOLVED_PROTOCOLS_ALL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Manager *m = userdata;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *hostname;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int family, ifindex;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering uint64_t flags;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DnsQuery *q;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(message);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(m);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert_cc(sizeof(int) == sizeof(int32_t));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_name_is_valid(hostname);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_new_address(&question, family, hostname);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_query_new(m, &q, question, ifindex, flags);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering q->request = sd_bus_message_ref(message);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna q->request_family = family;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering q->complete = bus_method_resolve_hostname_complete;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_query_bus_track(q, message);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto fail;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_query_go(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto fail;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringfail:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering dns_query_free(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic void bus_method_resolve_address_complete(DnsQuery *q) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DnsResourceRecord *rr;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned added = 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int ifindex, r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->state != DNS_TRANSACTION_SUCCESS) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = reply_query_state(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* We don't process CNAME for PTR lookups. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_new_method_return(q->request, &reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_open_container(reply, 'a', "(is)");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->answer) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_matches_rr(q->question, rr, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna goto finish;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (r == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering continue;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(reply, "(is)", ifindex, rr->ptr.name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering added ++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (added <= 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_free_ char *ip = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering in_addr_to_string(q->request_family, &q->request_address, &ip);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", strna(ip));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_close_container(reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_send(q->manager->bus, reply, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringfinish:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error_errno(r, "Failed to send address reply: %m");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_bus_reply_method_errno(q->request, r, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering dns_query_free(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2f7a4867babd3fd382e5495f21724358f30fa67dMichal Sekletar
2f7a4867babd3fd382e5495f21724358f30fa67dMichal Sekletarstatic int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Manager *m = userdata;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int family, ifindex;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering uint64_t flags;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const void *d;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DnsQuery *q;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering size_t sz;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
0affed79d2e30013f07cb94e6f07e3fcb81c02faLennart Poettering assert(message);
0affed79d2e30013f07cb94e6f07e3fcb81c02faLennart Poettering assert(m);
0affed79d2e30013f07cb94e6f07e3fcb81c02faLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert_cc(sizeof(int) == sizeof(int32_t));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_read(message, "ii", &ifindex, &family);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek if (!IN_SET(family, AF_INET, AF_INET6))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_read_array(message, 'y', &d, &sz);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (sz != FAMILY_ADDRESS_SIZE(family))
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = sd_bus_message_read(message, "t", &flags);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (r < 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return r;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = check_ifindex_flags(ifindex, &flags, 0, error);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (r < 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return r;
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = dns_question_new_reverse(&question, family, d);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (r < 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return r;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (r < 0)
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek return r;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna q->request = sd_bus_message_ref(message);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna q->request_family = family;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna memcpy(&q->request_address, d, sz);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna q->complete = bus_method_resolve_address_complete;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = dns_query_bus_track(q, message);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (r < 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna goto fail;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = dns_query_go(q);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (r < 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna goto fail;
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek return 1;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmekfail:
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek dns_query_free(q);
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek return r;
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek}
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagnastatic int bus_message_append_rr(sd_bus_message *m, DnsResourceRecord *rr, int ifindex) {
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna size_t start;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna int r;
8333c77edf8fd1654cd96f3f6ee0f078dd64b58bZbigniew Jędrzejewski-Szmek
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna assert(m);
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek assert(rr);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = sd_bus_message_open_container(m, 'r', "iqqay");
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek if (r < 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return r;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = sd_bus_message_append(m, "iqq",
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek ifindex,
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna rr->key->class,
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna rr->key->type);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (r < 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return r;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (r < 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return r;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek p->refuse_compression = true;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = dns_packet_append_rr(p, rr, &start);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (r < 0)
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek return r;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append_array(m, 'y', DNS_PACKET_DATA(p) + start, p->size - start);
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek if (r < 0)
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_message_close_container(m);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic void bus_method_resolve_record_complete(DnsQuery *q) {
7c2d80944afb4196f2eff614e8da1450dffcbeaaThomas Hindoe Paaboel Andersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned added = 0;
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->state != DNS_TRANSACTION_SUCCESS) {
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen r = reply_query_state(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_query_process_cname(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == -ELOOP) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r > 0) /* Following a CNAME */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_new_method_return(q->request, &reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_open_container(reply, 'a', "(iqqay)");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->answer) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DnsResourceRecord *rr;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int ifindex;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_matches_rr(q->question, rr, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering continue;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = bus_message_append_rr(reply, rr, ifindex);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering added ++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (added <= 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Name '%s' does not have any RR of the requested type", dns_question_first_name(q->question));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_close_container(reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_send(q->manager->bus, reply, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringfinish:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error_errno(r, "Failed to send record reply: %m");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_bus_reply_method_errno(q->request, r, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek dns_query_free(q);
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Manager *m = userdata;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering uint16_t class, type;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *name;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r, ifindex;
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer uint64_t flags;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DnsQuery *q;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(message);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(m);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert_cc(sizeof(int) == sizeof(int32_t));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_name_is_valid(name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = check_ifindex_flags(ifindex, &flags, 0, error);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering question = dns_question_new(1);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!question)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering key = dns_resource_key_new(class, type, name);
7c2d80944afb4196f2eff614e8da1450dffcbeaaThomas Hindoe Paaboel Andersen if (!key)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_add(question, key);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering q->request = sd_bus_message_ref(message);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering q->complete = bus_method_resolve_record_complete;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_query_bus_track(q, message);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto fail;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_query_go(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto fail;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 1;
6b2b6f30e38d67b032d6bdc6b47ae05e143e96c5Michal Schmidt
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringfail:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering dns_query_free(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DnsQuery *aux;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(rr);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(rr->key);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (rr->key->type != DNS_TYPE_SRV)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* First, let's see if we could find an appropriate A or AAAA
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * record for the SRV record */
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering DnsResourceRecord *zz;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (aux->state != DNS_TRANSACTION_SUCCESS)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering continue;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (aux->auxiliary_result != 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering continue;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = dns_name_equal(dns_question_first_name(aux->question), rr->srv.name);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r == 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering continue;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering DNS_ANSWER_FOREACH(zz, aux->answer) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
c62e11ce3966c55d23520b9f0785c7e839cf7f37Lennart Poettering r = dns_question_matches_rr(aux->question, zz, NULL);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r == 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering continue;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering canonical = dns_resource_record_ref(zz);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering break;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (canonical)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering break;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (!canonical)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return 0;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s");
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_append(
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering reply,
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering "qqqs",
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering rr->srv.priority, rr->srv.weight, rr->srv.port, rr->srv.name);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "(iiay)");
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering DnsResourceRecord *zz;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering int ifindex;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (aux->state != DNS_TRANSACTION_SUCCESS)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering continue;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (aux->auxiliary_result != 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering continue;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = dns_name_equal(dns_question_first_name(aux->question), rr->srv.name);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r == 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering continue;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = dns_question_matches_rr(aux->question, zz, NULL);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r == 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering continue;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = append_address(reply, zz, ifindex);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_close_container(reply);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* Note that above we appended the hostname as encoded in the
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * SRV, and here the canonical hostname this maps to. */
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_append(reply, "s", canonical ? DNS_RESOURCE_KEY_NAME(canonical->key) : rr->srv.name);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_close_container(reply);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return 1;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering}
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poetteringstatic int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering DnsTxtItem *i;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(rr);
82c1d8f4eb74ddd9be2c9b9b56d9dc564c599effLennart Poettering assert(rr->key);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (rr->key->type != DNS_TYPE_TXT)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return 0;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
2927b326ccf67236e148444679f582ea1437ef5aJan Janssen LIST_FOREACH(items, i, rr->txt.items) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (i->length <= 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering continue;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_append_array(reply, 'y', i->data, i->length);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return 1;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering}
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poetteringstatic void resolve_service_all_complete(DnsQuery *q) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DnsQuery *aux;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned added = false;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->block_all_complete > 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DnsQuery *bad = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering bool have_success = false;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering switch (aux->state) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering case DNS_TRANSACTION_PENDING:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* If an auxiliary query is still pending, let's wait */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering case DNS_TRANSACTION_SUCCESS:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (aux->auxiliary_result == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering have_success = true;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering bad = aux;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering break;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering default:
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen bad = aux;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering break;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!have_success) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* We can only return one error, hence pick the last error we encountered */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(bad);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (bad->state == DNS_TRANSACTION_SUCCESS) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(bad->auxiliary_result != 0);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (bad->auxiliary_result == -ELOOP) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(bad->question));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = bad->auxiliary_result;
7085053a437456ab87d726f3697002dd811fdf7aDaniel Wallace goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = reply_query_state(bad);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_new_method_return(q->request, &reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen r = sd_bus_message_open_container(reply, 'a', "(qqqsa(iiay)s)");
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen if (r < 0)
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->answer) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DnsResourceRecord *rr;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DNS_ANSWER_FOREACH(rr, q->answer) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_matches_rr(q->question, rr, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering continue;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = append_srv(q, reply, rr);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == 0) /* not an SRV record */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering continue;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!canonical)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering canonical = dns_resource_record_ref(rr);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering added++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (added <= 0) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_question_first_name(q->question));
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering goto finish;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_close_container(reply);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering goto finish;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "ay");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->answer) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DnsResourceRecord *rr;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DNS_ANSWER_FOREACH(rr, q->answer) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_matches_rr(q->question, rr, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering continue;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = append_txt(reply, rr);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_close_container(reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(canonical);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_service_split(DNS_RESOURCE_KEY_NAME(canonical->key), &name, &type, &domain);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering reply,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "ssst",
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering name, type, domain,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_send(q->manager->bus, reply, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringfinish:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error_errno(r, "Failed to send service reply: %m");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_bus_reply_method_errno(q->request, r, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering dns_query_free(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic void resolve_service_hostname_complete(DnsQuery *q) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(q->auxiliary_for);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->state != DNS_TRANSACTION_SUCCESS) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering resolve_service_all_complete(q->auxiliary_for);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_query_process_cname(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r > 0) /* This was a cname, and the query was restarted. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering q->auxiliary_result = r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering resolve_service_all_complete(q->auxiliary_for);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DnsQuery *aux;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(rr);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(rr->key);
a9cdc94f7ff40f22a3cf9472f612a80730a1b010Dave Reisner assert(rr->key->type == DNS_TYPE_SRV);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* OK, we found an SRV record for the service. Let's resolve
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * the hostname included in it */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_new_address(&question, q->request_family, rr->srv.name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_query_new(q->manager, &aux, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering aux->request_family = q->request_family;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering aux->complete = resolve_service_hostname_complete;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_query_make_auxiliary(aux, q);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == -EAGAIN) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Too many auxiliary lookups? If so, don't complain,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * let's just not add this one, we already have more
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * than enough */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering dns_query_free(aux);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto fail;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Note that auxiliary queries do not track the original bus
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * client, only the primary request does that. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_query_go(aux);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto fail;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringfail:
dns_query_free(aux);
return r;
}
static void bus_method_resolve_service_complete(DnsQuery *q) {
unsigned found = 0;
int r;
assert(q);
if (q->state != DNS_TRANSACTION_SUCCESS) {
r = reply_query_state(q);
goto finish;
}
r = dns_query_process_cname(q);
if (r == -ELOOP) {
r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
goto finish;
}
if (r < 0)
goto finish;
if (r > 0) /* This was a cname, and the query was restarted. */
return;
if (q->answer) {
DnsResourceRecord *rr;
int ifindex;
DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
r = dns_question_matches_rr(q->question, rr, NULL);
if (r < 0)
goto finish;
if (r == 0)
continue;
if (rr->key->type != DNS_TYPE_SRV)
continue;
if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
q->block_all_complete ++;
r = resolve_service_hostname(q, rr, ifindex);
q->block_all_complete --;
if (r < 0)
goto finish;
}
found++;
}
}
if (found <= 0) {
r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_question_first_name(q->question));
goto finish;
}
/* Maybe we are already finished? check now... */
resolve_service_all_complete(q);
return;
finish:
if (r < 0) {
log_error_errno(r, "Failed to send service reply: %m");
sd_bus_reply_method_errno(q->request, r, NULL);
}
dns_query_free(q);
}
static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
const char *name, *type, *domain, *joined;
_cleanup_free_ char *n = NULL;
Manager *m = userdata;
int family, ifindex;
uint64_t flags;
DnsQuery *q;
int r;
assert(message);
assert(m);
assert_cc(sizeof(int) == sizeof(int32_t));
r = sd_bus_message_read(message, "isssit", &ifindex, &name, &type, &domain, &family, &flags);
if (r < 0)
return r;
if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
if (isempty(name))
name = NULL;
else {
if (!dns_service_name_is_valid(name))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service name '%s'", name);
}
if (isempty(type))
type = NULL;
else {
r = dns_srv_type_verify(type);
if (r < 0)
return r;
if (r == 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SRV service type '%s'", type);
}
r = dns_name_is_valid(domain);
if (r < 0)
return r;
if (r == 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid domain '%s'", domain);
if (name && !type)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
if (r < 0)
return r;
if (type) {
/* If the type is specified, we generate the full domain name to look up ourselves */
r = dns_service_join(name, type, domain, &n);
if (r < 0)
return r;
joined = n;
} else
/* If no type is specified, we assume the domain
* contains the full domain name to lookup already */
joined = domain;
r = dns_question_new_service(&question, joined, !(flags & SD_RESOLVED_NO_TXT));
if (r < 0)
return r;
r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
if (r < 0)
return r;
q->request = sd_bus_message_ref(message);
q->request_family = family;
q->complete = bus_method_resolve_service_complete;
r = dns_query_bus_track(q, message);
if (r < 0)
goto fail;
r = dns_query_go(q);
if (r < 0)
goto fail;
return 1;
fail:
dns_query_free(q);
return r;
}
static int append_dns_server(sd_bus_message *reply, DnsServer *s) {
int r;
assert(reply);
assert(s);
r = sd_bus_message_open_container(reply, 'r', "iiay");
if (r < 0)
return r;
r = sd_bus_message_append(reply, "ii", s->link ? s->link->ifindex : 0, s->family);
if (r < 0)
return r;
r = sd_bus_message_append_array(reply, 'y', &s->address, FAMILY_ADDRESS_SIZE(s->family));
if (r < 0)
return r;
return sd_bus_message_close_container(reply);
}
static int bus_property_get_dns_servers(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
Manager *m = userdata;
unsigned c = 0;
DnsServer *s;
Iterator i;
Link *l;
int r;
assert(reply);
assert(m);
r = sd_bus_message_open_container(reply, 'a', "(iiay)");
if (r < 0)
return r;
LIST_FOREACH(servers, s, m->dns_servers) {
r = append_dns_server(reply, s);
if (r < 0)
return r;
c++;
}
HASHMAP_FOREACH(l, m->links, i) {
LIST_FOREACH(servers, s, l->dns_servers) {
r = append_dns_server(reply, s);
if (r < 0)
return r;
c++;
}
}
if (c == 0) {
LIST_FOREACH(servers, s, m->fallback_dns_servers) {
r = append_dns_server(reply, s);
if (r < 0)
return r;
}
}
return sd_bus_message_close_container(reply);
}
static int bus_property_get_search_domains(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
Manager *m = userdata;
DnsSearchDomain *d;
Iterator i;
Link *l;
int r;
assert(reply);
assert(m);
r = sd_bus_message_open_container(reply, 'a', "(is)");
if (r < 0)
return r;
LIST_FOREACH(domains, d, m->search_domains) {
r = sd_bus_message_append(reply, "(is)", 0, d->name);
if (r < 0)
return r;
}
HASHMAP_FOREACH(l, m->links, i) {
LIST_FOREACH(domains, d, l->search_domains) {
r = sd_bus_message_append(reply, "is", l->ifindex, d->name);
if (r < 0)
return r;
}
}
return sd_bus_message_close_container(reply);
}
static const sd_bus_vtable resolve_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0),
SD_BUS_PROPERTY("DNSServers", "a(iiay)", bus_property_get_dns_servers, 0, 0),
SD_BUS_PROPERTY("SearchDomains", "a(is)", bus_property_get_search_domains, 0, 0),
SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END,
};
static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
Manager *m = userdata;
assert(s);
assert(m);
m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
manager_connect_bus(m);
return 0;
}
static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
Manager *m = userdata;
int b, r;
assert(message);
assert(m);
r = sd_bus_message_read(message, "b", &b);
if (r < 0) {
log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
return 0;
}
if (b)
return 0;
log_debug("Coming back from suspend, verifying all RRs...");
manager_verify_all(m);
return 0;
}
int manager_connect_bus(Manager *m) {
int r;
assert(m);
if (m->bus)
return 0;
r = sd_bus_default_system(&m->bus);
if (r < 0) {
/* We failed to connect? Yuck, we must be in early
* boot. Let's try in 5s again. As soon as we have
* kdbus we can stop doing this... */
log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m);
if (r < 0)
return log_error_errno(r, "Failed to install bus reconnect time event: %m");
return 0;
}
r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
if (r < 0)
return log_error_errno(r, "Failed to register object: %m");
r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
if (r < 0)
return log_error_errno(r, "Failed to register name: %m");
r = sd_bus_attach_event(m->bus, m->event, 0);
if (r < 0)
return log_error_errno(r, "Failed to attach bus to event loop: %m");
r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
"type='signal',"
"sender='org.freedesktop.login1',"
"interface='org.freedesktop.login1.Manager',"
"member='PrepareForSleep',"
"path='/org/freedesktop/login1'",
match_prepare_for_sleep,
m);
if (r < 0)
log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
return 0;
}