resolved-bus.c revision 2d4c5cbc0ed3ccb09dc086a040088b454c22c644
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen/***
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen This file is part of systemd.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Copyright 2014 Lennart Poettering
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen systemd is free software; you can redistribute it and/or modify it
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen under the terms of the GNU Lesser General Public License as published by
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen (at your option) any later version.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen systemd is distributed in the hope that it will be useful, but
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Lesser General Public License for more details.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen You should have received a copy of the GNU Lesser General Public License
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen***/
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "bus-errors.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "bus-util.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "resolved.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "resolved-dns-domain.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int reply_query_state(DnsQuery *q) {
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering _cleanup_free_ char *ip = NULL;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering const char *name;
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering int r;
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering if (q->request_hostname)
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering name = q->request_hostname;
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering else {
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering r = in_addr_to_string(q->request_family, &q->request_address, &ip);
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering if (r < 0)
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering return r;
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering name = ip;
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen switch (q->state) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen case DNS_QUERY_NO_SERVERS:
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen case DNS_QUERY_TIMEOUT:
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen case DNS_QUERY_ATTEMPTS_MAX:
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen case DNS_QUERY_RESOURCES:
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_RESOURCES, "Not enough resources");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen case DNS_QUERY_INVALID_REPLY:
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen case DNS_QUERY_FAILURE: {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", name);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen else {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen const char *rc, *n;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen char p[3]; /* the rcode is 4 bits long */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen rc = dns_rcode_to_string(q->answer_rcode);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!rc) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sprintf(p, "%i", q->answer_rcode);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen rc = p;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen n = strappenda(_BUS_ERROR_DNS, rc);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, rc);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return sd_bus_reply_method_error(q->request, &error);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen case DNS_QUERY_NULL:
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen case DNS_QUERY_PENDING:
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen case DNS_QUERY_SUCCESS:
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen default:
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert_not_reached("Impossible state");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(reply);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(rr);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_open_container(reply, 'r', "iayi");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (rr->key->type == DNS_TYPE_A) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_append(reply, "i", AF_INET);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen } else if (rr->key->type == DNS_TYPE_AAAA) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_append(reply, "i", AF_INET6);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen } else
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return -EAFNOSUPPORT;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_append(reply, "i", ifindex);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_close_container(reply);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void bus_method_resolve_hostname_complete(DnsQuery *q) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL, *canonical = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen unsigned added = 0, i;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int r, ifindex;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (q->state != DNS_QUERY_SUCCESS) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = reply_query_state(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_new_method_return(q->request, &reply);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_open_container(reply, 'a', "(iayi)");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen ifindex = q->answer_ifindex;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (q->answer) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen answer = dns_answer_ref(q->answer);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (i = 0; i < answer->n_rrs; i++) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_question_matches_rr(q->question, answer->rrs[i]);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r == 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* Hmm, if this is not an address record,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen maybe it's a cname? If so, remember this */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_question_matches_cname(q->question, answer->rrs[i]);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r > 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen cname = dns_resource_record_ref(answer->rrs[i]);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = append_address(reply, answer->rrs[i], ifindex);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!canonical)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen canonical = dns_resource_record_ref(answer->rrs[i]);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen added ++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (added <= 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!cname) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of requested type", q->request_hostname);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* This has a cname? Then update the query with the
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * new cname. */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_query_cname_redirect(q, cname->cname.name);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r == -ELOOP)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop on '%s'", q->request_hostname);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen else
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_reply_method_errno(q->request, -r, NULL);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* Before we restart the query, let's see if any of
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * the RRs we already got already answers our query */
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering for (i = 0; i < answer->n_rrs; i++) {
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering r = dns_question_matches_rr(q->question, answer->rrs[i]);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r == 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = append_address(reply, answer->rrs[i], ifindex);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!canonical)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen canonical = dns_resource_record_ref(answer->rrs[i]);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen added++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* If we didn't find anything, then let's restart the
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * query, this time with the cname */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (added <= 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_query_go(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r == -ESRCH) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_reply_method_errno(q->request, -r, NULL);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_close_container(reply);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* Return the precise spelling and uppercasing reported by the server */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(canonical);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_append(reply, "s", DNS_RESOURCE_KEY_NAME(canonical->key));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_send(q->manager->bus, reply, NULL);
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenfinish:
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to send hostname reply: %s", strerror(-r));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sd_bus_reply_method_errno(q->request, -r, NULL);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen dns_query_free(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int bus_method_resolve_hostname(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Manager *m = userdata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen const char *hostname;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int family;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen DnsQuery *q;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(bus);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(message);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(m);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_read(message, "si", &hostname, &family);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!hostname_is_valid(hostname))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen question = dns_question_new(family == AF_UNSPEC ? 2 : 1);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!question)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return -ENOMEM;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (family != AF_INET6) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, hostname);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!key)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return -ENOMEM;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_question_add(question, key);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (family != AF_INET) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, hostname);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!key)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return -ENOMEM;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_question_add(question, key);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_query_new(m, &q, question);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen q->request = sd_bus_message_ref(message);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen q->request_family = family;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen q->request_hostname = hostname;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen q->complete = bus_method_resolve_hostname_complete;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_query_go(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen dns_query_free(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r == -ESRCH)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return 1;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void bus_method_resolve_address_complete(DnsQuery *q) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen unsigned added = 0, i;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (q->state != DNS_QUERY_SUCCESS) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = reply_query_state(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_new_method_return(q->request, &reply);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_open_container(reply, 'a', "s");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (q->answer) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen answer = dns_answer_ref(q->answer);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (i = 0; i < answer->n_rrs; i++) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_question_matches_rr(q->question, answer->rrs[i]);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r == 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_append(reply, "s", answer->rrs[i]->ptr.name);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen added ++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
401cb61499f446c7c1579a160eeef435afd525fdTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (added <= 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_free_ char *ip = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen in_addr_to_string(q->request_family, &q->request_address, &ip);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", ip);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_close_container(reply);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_send(q->manager->bus, reply, NULL);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenfinish:
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to send address reply: %s", strerror(-r));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sd_bus_reply_method_errno(q->request, -r, NULL);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen dns_query_free(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int bus_method_resolve_address(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_free_ char *reverse = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Manager *m = userdata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int family, ifindex;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen const void *d;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen DnsQuery *q;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen size_t sz;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(bus);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(message);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(m);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_read(message, "i", &family);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!IN_SET(family, AF_INET, AF_INET6))
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_read_array(message, 'y', &d, &sz);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (sz != FAMILY_ADDRESS_SIZE(family))
4df4fd1127df4b70f78d952a37a51a8c69e3243fTom Gundersen return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
4df4fd1127df4b70f78d952a37a51a8c69e3243fTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_read(message, "i", &ifindex);
4df4fd1127df4b70f78d952a37a51a8c69e3243fTom Gundersen if (r < 0)
de9b34b6d4250056ae2c483cf22844880504bcccTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ifindex < 0)
de9b34b6d4250056ae2c483cf22844880504bcccTom Gundersen return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
de9b34b6d4250056ae2c483cf22844880504bcccTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_name_reverse(family, d, &reverse);
4df4fd1127df4b70f78d952a37a51a8c69e3243fTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
4df4fd1127df4b70f78d952a37a51a8c69e3243fTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen question = dns_question_new(1);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!question)
4df4fd1127df4b70f78d952a37a51a8c69e3243fTom Gundersen return -ENOMEM;
4df4fd1127df4b70f78d952a37a51a8c69e3243fTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse);
4df4fd1127df4b70f78d952a37a51a8c69e3243fTom Gundersen if (!key)
de9b34b6d4250056ae2c483cf22844880504bcccTom Gundersen return -ENOMEM;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
de9b34b6d4250056ae2c483cf22844880504bcccTom Gundersen reverse = NULL;
de9b34b6d4250056ae2c483cf22844880504bcccTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_question_add(question, key);
4df4fd1127df4b70f78d952a37a51a8c69e3243fTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
4df4fd1127df4b70f78d952a37a51a8c69e3243fTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_query_new(m, &q, question);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen q->request = sd_bus_message_ref(message);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen q->request_family = family;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen memcpy(&q->request_address, d, sz);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen q->complete = bus_method_resolve_address_complete;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_query_go(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen dns_query_free(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r == -ESRCH)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return 1;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic void bus_method_resolve_record_complete(DnsQuery *q) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen unsigned added = 0, i;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (q->state != DNS_QUERY_SUCCESS) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = reply_query_state(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_new_method_return(q->request, &reply);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_open_container(reply, 'a', "(qqay)");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (q->answer) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen answer = dns_answer_ref(q->answer);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen for (i = 0; i < answer->n_rrs; i++) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen size_t start;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_question_matches_rr(q->question, answer->rrs[i]);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r == 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen continue;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_packet_append_rr(p, answer->rrs[i], &start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
401cb61499f446c7c1579a160eeef435afd525fdTom Gundersen r = sd_bus_message_open_container(reply, 'r', "qqay");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_append(reply, "qq", answer->rrs[i]->key->class, answer->rrs[i]->key->type);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_append_array(reply, 'y', DNS_PACKET_DATA(p) + start, p->size - start);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_close_container(reply);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen added ++;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (added <= 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Name '%s' does not have any RR of the requested type", q->request_hostname);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_close_container(reply);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen goto finish;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_send(q->manager->bus, reply, NULL);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenfinish:
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to send record reply: %s", strerror(-r));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sd_bus_reply_method_errno(q->request, -r, NULL);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen dns_query_free(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int bus_method_resolve_record(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_free_ char *reverse = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Manager *m = userdata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen DnsQuery *q;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen uint16_t class, type;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen const char *name;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(bus);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(message);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(m);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_message_read(message, "sqq", &name, &class, &type);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen question = dns_question_new(1);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!question)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return -ENOMEM;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen key = dns_resource_key_new(class, type, name);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!key)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return -ENOMEM;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_question_add(question, key);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_query_new(m, &q, question);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen q->request = sd_bus_message_ref(message);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen q->request_hostname = name;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen q->complete = bus_method_resolve_record_complete;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = dns_query_go(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen dns_query_free(q);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r == -ESRCH)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return 1;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic const sd_bus_vtable resolve_vtable[] = {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen SD_BUS_VTABLE_START(0),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen SD_BUS_METHOD("ResolveHostname", "si", "a(iayi)s", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen SD_BUS_METHOD("ResolveAddress", "iayi", "as", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen SD_BUS_METHOD("ResolveRecord", "sqq", "a(qqay)", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen SD_BUS_VTABLE_END,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen};
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Manager *m = userdata;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(s);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(m);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen manager_connect_bus(m);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen}
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenint manager_connect_bus(Manager *m) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen assert(m);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (m->bus)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_default_system(&m->bus);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen /* We failed to connect? Yuck, we must be in early
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * boot. Let's try in 5s again. As soon as we have
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen * kdbus we can stop doing this... */
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_debug("Failed to connect to bus, trying again in 5s: %s", strerror(-r));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
ccc1002a1c510b7d4631833eaf60225f028f2280Tom Gundersen 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);
ccc1002a1c510b7d4631833eaf60225f028f2280Tom Gundersen if (r < 0) {
d854ba50a82f28b776c670d27156f0e9881fde8aMartin Pitt log_error("Failed to install bus reconnect time event: %s", strerror(-r));
ccc1002a1c510b7d4631833eaf60225f028f2280Tom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return 0;
aa20f49a1c5816e6e7e97f2e2ba209be47f3c0a3Tom Gundersen }
aa20f49a1c5816e6e7e97f2e2ba209be47f3c0a3Tom Gundersen
aa20f49a1c5816e6e7e97f2e2ba209be47f3c0a3Tom Gundersen r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to register object: %s", strerror(-r));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to register name: %s", strerror(-r));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return r;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
d854ba50a82f28b776c670d27156f0e9881fde8aMartin Pitt r = sd_bus_attach_event(m->bus, m->event, 0);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to attach bus to event loop: %s", strerror(-r));
ccc1002a1c510b7d4631833eaf60225f028f2280Tom Gundersen return r;
ccc1002a1c510b7d4631833eaf60225f028f2280Tom Gundersen }
ccc1002a1c510b7d4631833eaf60225f028f2280Tom Gundersen
ccc1002a1c510b7d4631833eaf60225f028f2280Tom Gundersen return 0;
d854ba50a82f28b776c670d27156f0e9881fde8aMartin Pitt}
d854ba50a82f28b776c670d27156f0e9881fde8aMartin Pitt