resolved-bus.c revision 801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47dd
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering This file is part of systemd.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Copyright 2014 Lennart 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 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 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 Poetteringstatic int reply_query_state(DnsQuery *q) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = in_addr_to_string(q->request_family, &q->request_address, &ip);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering name = dns_question_first_name(q->question);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
7085053a437456ab87d726f3697002dd811fdf7aDaniel Wallace return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
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 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
1b12a7b5896f94bdf33b3a6661ebabd761ea6adcHarald Hoyer return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_RESOURCES, "Not enough resources");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
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 const char *rc, *n;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char p[3]; /* the rcode is 4 bits long */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering rc = dns_rcode_to_string(q->answer_rcode);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, rc);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_reply_method_error(q->request, &error);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_open_container(reply, 'r', "iiay");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(reply, "i", ifindex);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(reply, "i", AF_INET);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else if (rr->key->type == DNS_TYPE_AAAA) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(reply, "i", AF_INET6);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_close_container(reply);
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 if (q->state != DNS_TRANSACTION_SUCCESS) {
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 if (r > 0) /* This was a cname, and the query was restarted. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_new_method_return(q->request, &reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_open_container(reply, 'a', "(iiay)");
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 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 r = sd_bus_message_close_container(reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Return the precise spelling and uppercasing and CNAME target reported by the server */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_send(q->manager->bus, reply, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error_errno(r, "Failed to send hostname reply: %m");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_bus_reply_method_errno(q->request, r, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int check_ifindex_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
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 if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
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 assert_cc(sizeof(int) == sizeof(int32_t));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
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 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_new_address(&question, family, hostname);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_query_new(m, &q, question, ifindex, flags);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering q->request = sd_bus_message_ref(message);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering q->complete = bus_method_resolve_hostname_complete;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic void bus_method_resolve_address_complete(DnsQuery *q) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->state != DNS_TRANSACTION_SUCCESS) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* We don't process CNAME for PTR lookups. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_new_method_return(q->request, &reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_open_container(reply, 'a', "(is)");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_matches_rr(q->question, rr, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(reply, "(is)", ifindex, rr->ptr.name);
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 r = sd_bus_message_close_container(reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_send(q->manager->bus, reply, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error_errno(r, "Failed to send address reply: %m");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_bus_reply_method_errno(q->request, r, NULL);
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 const void *d;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert_cc(sizeof(int) == sizeof(int32_t));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_read(message, "ii", &ifindex, &family);
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 r = sd_bus_message_read_array(message, 'y', &d, &sz);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = sd_bus_message_read(message, "t", &flags);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = check_ifindex_flags(ifindex, &flags, 0, error);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = dns_question_new_reverse(&question, family, d);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna q->complete = bus_method_resolve_address_complete;
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 r = sd_bus_message_open_container(m, 'r', "iqqay");
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append_array(m, 'y', DNS_PACKET_DATA(p) + start, p->size - start);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_message_close_container(m);
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 if (q->state != DNS_TRANSACTION_SUCCESS) {
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 if (r > 0) /* Following a CNAME */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_new_method_return(q->request, &reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_open_container(reply, 'a', "(iqqay)");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_matches_rr(q->question, rr, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = bus_message_append_rr(reply, rr, ifindex);
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 r = sd_bus_message_close_container(reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_send(q->manager->bus, reply, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error_errno(r, "Failed to send record reply: %m");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_bus_reply_method_errno(q->request, r, NULL);
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 assert_cc(sizeof(int) == sizeof(int32_t));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = check_ifindex_flags(ifindex, &flags, 0, error);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering key = dns_resource_key_new(class, type, name);
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering q->request = sd_bus_message_ref(message);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering q->complete = bus_method_resolve_record_complete;
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 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 if (aux->state != DNS_TRANSACTION_SUCCESS)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = dns_name_equal(dns_question_first_name(aux->question), rr->srv.name);
c62e11ce3966c55d23520b9f0785c7e839cf7f37Lennart Poettering r = dns_question_matches_rr(aux->question, zz, NULL);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s");
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering rr->srv.priority, rr->srv.weight, rr->srv.port, rr->srv.name);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "(iiay)");
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (aux->state != DNS_TRANSACTION_SUCCESS)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = dns_name_equal(dns_question_first_name(aux->question), rr->srv.name);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = dns_question_matches_rr(aux->question, zz, NULL);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_close_container(reply);
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 r = sd_bus_message_close_container(reply);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poetteringstatic int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_append_array(reply, 'y', i->data, i->length);
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 unsigned added = false;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* If an auxiliary query is still pending, let's wait */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* We can only return one error, hence pick the last error we encountered */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (bad->state == DNS_TRANSACTION_SUCCESS) {
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 r = sd_bus_message_new_method_return(q->request, &reply);
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen r = sd_bus_message_open_container(reply, 'a', "(qqqsa(iiay)s)");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_matches_rr(q->question, rr, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == 0) /* not an SRV record */
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 r = sd_bus_message_close_container(reply);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "ay");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_matches_rr(q->question, rr, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_message_close_container(reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_service_split(DNS_RESOURCE_KEY_NAME(canonical->key), &name, &type, &domain);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_bus_send(q->manager->bus, reply, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error_errno(r, "Failed to send service reply: %m");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_bus_reply_method_errno(q->request, r, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic void resolve_service_hostname_complete(DnsQuery *q) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (q->state != DNS_TRANSACTION_SUCCESS) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering resolve_service_all_complete(q->auxiliary_for);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r > 0) /* This was a cname, and the query was restarted. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering resolve_service_all_complete(q->auxiliary_for);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* OK, we found an SRV record for the service. Let's resolve
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * the hostname included in it */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_question_new_address(&question, q->request_family, rr->srv.name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_query_new(q->manager, &aux, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering aux->complete = resolve_service_hostname_complete;
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 /* Note that auxiliary queries do not track the original bus
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * client, only the primary request does that. */
unsigned found = 0;
assert(q);
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;
goto finish;
if (q->answer) {
int ifindex;
goto finish;
q->block_all_complete ++;
q->block_all_complete --;
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;
dns_query_free(q);
static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
DnsQuery *q;
assert(m);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
if (type) {
joined = n;
goto fail;
r = dns_query_go(q);
goto fail;
fail:
dns_query_free(q);
assert(s);
static int bus_property_get_dns_servers(
const char *path,
const char *interface,
const char *property,
void *userdata,
DnsServer *s;
Iterator i;
Link *l;
assert(m);
static int bus_property_get_search_domains(
const char *path,
const char *interface,
const char *property,
void *userdata,
DnsSearchDomain *d;
Iterator i;
Link *l;
assert(m);
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),
assert(s);
assert(m);
static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
assert(m);
assert(m);
if (m->bus)
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);
r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
"path='/org/freedesktop/login1'",