From 95ce1ba87bc5fb0a439d91336dc7456d7c61db0b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 3 Jul 2020 20:31:15 +0900 Subject: [PATCH] resolve: add DBus method to set DNS server with port number and SNI --- src/resolve/resolved-bus.c | 9 +++ src/resolve/resolved-link-bus.c | 110 ++++++++++++++++++++++---------- src/resolve/resolved-link-bus.h | 1 + 3 files changed, 88 insertions(+), 32 deletions(-) diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index 45687c8fcab..2de86b0f4c7 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -1532,6 +1532,10 @@ static int bus_method_set_link_dns_servers(sd_bus_message *message, void *userda return call_link_method(userdata, message, bus_link_method_set_dns_servers, error); } +static int bus_method_set_link_dns_servers_ex(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_dns_servers_ex, error); +} + static int bus_method_set_link_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) { return call_link_method(userdata, message, bus_link_method_set_domains, error); } @@ -1895,6 +1899,11 @@ static const sd_bus_vtable resolve_vtable[] = { SD_BUS_NO_RESULT, bus_method_set_link_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_ARGS("SetLinkDNSEx", + SD_BUS_ARGS("i", ifindex, "a(iayqs)", addresses), + SD_BUS_NO_RESULT, + bus_method_set_link_dns_servers_ex, + SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD_WITH_ARGS("SetLinkDomains", SD_BUS_ARGS("i", ifindex, "a(sb)", domains), SD_BUS_NO_RESULT, diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c index 1694b1aa5a7..53fe180b81a 100644 --- a/src/resolve/resolved-link-bus.c +++ b/src/resolve/resolved-link-bus.c @@ -13,6 +13,7 @@ #include "resolved-bus.h" #include "resolved-link-bus.h" #include "resolved-resolv-conf.h" +#include "socket-netlink.h" #include "stdio-util.h" #include "strv.h" #include "user-util.h" @@ -204,11 +205,10 @@ static int verify_unmanaged_link(Link *l, sd_bus_error *error) { return 0; } -int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_free_ struct in_addr_data *dns = NULL; +static int bus_link_method_set_dns_servers_internal(sd_bus_message *message, void *userdata, sd_bus_error *error, bool extended) { + struct in_addr_full **dns = NULL; size_t allocated = 0, n = 0; Link *l = userdata; - unsigned i; int r; assert(message); @@ -218,76 +218,106 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_ if (r < 0) return r; - r = sd_bus_message_enter_container(message, 'a', "(iay)"); + r = sd_bus_message_enter_container(message, 'a', extended ? "(iayqs)" : "(iay)"); if (r < 0) return r; for (;;) { + const char *server_name = NULL; + union in_addr_union a; + uint16_t port = 0; + const void *d; int family; size_t sz; - const void *d; assert_cc(sizeof(int) == sizeof(int32_t)); - r = sd_bus_message_enter_container(message, 'r', "iay"); + r = sd_bus_message_enter_container(message, 'r', extended ? "iayqs" : "iay"); if (r < 0) - return r; + goto finalize; if (r == 0) break; r = sd_bus_message_read(message, "i", &family); if (r < 0) - return r; + goto finalize; - if (!IN_SET(family, AF_INET, AF_INET6)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); + if (!IN_SET(family, AF_INET, AF_INET6)) { + r = sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); + goto finalize; + } r = sd_bus_message_read_array(message, 'y', &d, &sz); if (r < 0) - return r; - if (sz != FAMILY_ADDRESS_SIZE(family)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size"); + goto finalize; + if (sz != FAMILY_ADDRESS_SIZE(family)) { + r = sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size"); + goto finalize; + } + + if (!dns_server_address_valid(family, d)) { + r = sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address"); + goto finalize; + } + + if (extended) { + r = sd_bus_message_read(message, "q", &port); + if (r < 0) + goto finalize; - if (!dns_server_address_valid(family, d)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address"); + if (IN_SET(port, 53, 853)) + port = 0; + + r = sd_bus_message_read(message, "s", &server_name); + if (r < 0) + goto finalize; + } r = sd_bus_message_exit_container(message); if (r < 0) - return r; + goto finalize; - if (!GREEDY_REALLOC(dns, allocated, n+1)) - return -ENOMEM; + if (!GREEDY_REALLOC(dns, allocated, n+1)) { + r = -ENOMEM; + goto finalize; + } - dns[n].family = family; - memcpy(&dns[n].address, d, sz); + memcpy(&a, d, sz); + r = in_addr_full_new(family, &a, port, 0, server_name, dns + n); + if (r < 0) + goto finalize; n++; } r = sd_bus_message_exit_container(message); if (r < 0) - return r; + goto finalize; r = bus_verify_polkit_async(message, CAP_NET_ADMIN, "org.freedesktop.resolve1.set-dns-servers", NULL, true, UID_INVALID, &l->manager->polkit_registry, error); if (r < 0) - return r; - if (r == 0) - return 1; /* Polkit will call us back */ + goto finalize; + if (r == 0) { + r = 1; /* Polkit will call us back */ + goto finalize; + } dns_server_mark_all(l->dns_servers); - for (i = 0; i < n; i++) { + for (size_t i = 0; i < n; i++) { DnsServer *s; - s = dns_server_find(l->dns_servers, dns[i].family, &dns[i].address, 0, 0, NULL); + s = dns_server_find(l->dns_servers, dns[i]->family, &dns[i]->address, dns[i]->port, 0, dns[i]->server_name); if (s) dns_server_move_back_and_unmark(s); else { - r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address, 0, 0, NULL); - if (r < 0) - goto clear; + r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i]->family, &dns[i]->address, dns[i]->port, 0, dns[i]->server_name); + if (r < 0) { + dns_server_unlink_all(l->dns_servers); + goto finalize; + } } } @@ -299,13 +329,24 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_ (void) manager_write_resolv_conf(l->manager); (void) manager_send_changed(l->manager, "DNS"); - return sd_bus_reply_method_return(message, NULL); + r = sd_bus_reply_method_return(message, NULL); + +finalize: + for (size_t i = 0; i < n; i++) + in_addr_full_free(dns[i]); + free(dns); -clear: - dns_server_unlink_all(l->dns_servers); return r; } +int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_link_method_set_dns_servers_internal(message, userdata, error, false); +} + +int bus_link_method_set_dns_servers_ex(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_link_method_set_dns_servers_internal(message, userdata, error, true); +} + int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) { Link *l = userdata; int r; @@ -777,6 +818,11 @@ static const sd_bus_vtable link_vtable[] = { SD_BUS_NO_RESULT, bus_link_method_set_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_ARGS("SetDNSEx", + SD_BUS_ARGS("a(iayqs)", addresses), + SD_BUS_NO_RESULT, + bus_link_method_set_dns_servers_ex, + SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD_WITH_ARGS("SetDomains", SD_BUS_ARGS("a(sb)", domains), SD_BUS_NO_RESULT, diff --git a/src/resolve/resolved-link-bus.h b/src/resolve/resolved-link-bus.h index c2499600243..fc85ff855c1 100644 --- a/src/resolve/resolved-link-bus.h +++ b/src/resolve/resolved-link-bus.h @@ -11,6 +11,7 @@ extern const BusObjectImplementation link_object; char *link_bus_path(const Link *link); int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_dns_servers_ex(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_link_method_set_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error); -- 2.39.2