From bc81447ea556586b09226ce2d3fe375a7adc2c16 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 10 Jun 2016 20:23:49 +0200 Subject: resolved: flush all caches if SIGUSR2 is received --- src/resolve/resolved-manager.c | 17 +++++++++++++++++ src/resolve/resolved-manager.h | 1 + src/resolve/resolved.c | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 8dc7891143..6cf75f9183 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -466,6 +466,21 @@ static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si return 0; } +static int manager_sigusr2(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + Manager *m = userdata; + DnsScope *scope; + + assert(s); + assert(si); + assert(m); + + LIST_FOREACH(scopes, scope, m->dns_scopes) + dns_cache_flush(&scope->cache); + + log_info("Flushed all caches."); + return 0; +} + int manager_new(Manager **ret) { _cleanup_(manager_freep) Manager *m = NULL; int r; @@ -526,6 +541,7 @@ int manager_new(Manager **ret) { return r; (void) sd_event_add_signal(m->event, &m->sigusr1_event_source, SIGUSR1, manager_sigusr1, m); + (void) sd_event_add_signal(m->event, &m->sigusr2_event_source, SIGUSR2, manager_sigusr2, m); *ret = m; m = NULL; @@ -584,6 +600,7 @@ Manager *manager_free(Manager *m) { sd_bus_unref(m->bus); sd_event_source_unref(m->sigusr1_event_source); + sd_event_source_unref(m->sigusr2_event_source); sd_event_unref(m->event); diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index e82a824f29..97f75ace79 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -120,6 +120,7 @@ struct Manager { sd_bus_slot *prepare_for_sleep_slot; sd_event_source *sigusr1_event_source; + sd_event_source *sigusr2_event_source; unsigned n_transactions_total; unsigned n_dnssec_verdict[_DNSSEC_VERDICT_MAX]; diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c index 6cef401870..3a47b82d8a 100644 --- a/src/resolve/resolved.c +++ b/src/resolve/resolved.c @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, -1) >= 0); + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, SIGUSR2, -1) >= 0); r = manager_new(&m); if (r < 0) { -- cgit v1.2.3-54-g00ecf From ba35662fbdde7b90aed6b34c641b4ff0ea740c68 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 10 Jun 2016 20:40:30 +0200 Subject: resolved: also add a way to flush all caches via the bus And expose it in "resolve-tool --flush-caches". --- man/systemd-resolve.xml | 6 ++++++ src/resolve/resolve-tool.c | 36 ++++++++++++++++++++++++++++++++++++ src/resolve/resolved-bus.c | 12 ++++++++++++ src/resolve/resolved-manager.c | 15 +++++++++++---- src/resolve/resolved-manager.h | 2 ++ 5 files changed, 67 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/man/systemd-resolve.xml b/man/systemd-resolve.xml index 4b66f836a2..b917ac20a2 100644 --- a/man/systemd-resolve.xml +++ b/man/systemd-resolve.xml @@ -288,6 +288,12 @@ Resets the statistics counters shown in to zero. + + + + Flushes all DNS resource record caches the service maintains locally. + + diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c index 7e145c64c4..bc6dcf04a4 100644 --- a/src/resolve/resolve-tool.c +++ b/src/resolve/resolve-tool.c @@ -66,6 +66,7 @@ static enum { MODE_RESOLVE_TLSA, MODE_STATISTICS, MODE_RESET_STATISTICS, + MODE_FLUSH_CACHES, } arg_mode = MODE_RESOLVE_HOST; static ServiceFamily service_family_from_string(const char *s) { @@ -1037,6 +1038,24 @@ static int reset_statistics(sd_bus *bus) { return 0; } +static int flush_caches(sd_bus *bus) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + r = sd_bus_call_method(bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "FlushCaches", + &error, + NULL, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to flush caches: %s", bus_error_message(&error, r)); + + return 0; +} + static void help_protocol_types(void) { if (arg_legend) puts("Known protocol types:"); @@ -1097,6 +1116,7 @@ static void help(void) { " --legend=BOOL Print headers and additional info (default: yes)\n" " --statistics Show resolver statistics\n" " --reset-statistics Reset resolver statistics\n" + " --flush-caches Flush all local DNS caches\n" , program_invocation_short_name); } @@ -1114,6 +1134,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_SEARCH, ARG_STATISTICS, ARG_RESET_STATISTICS, + ARG_FLUSH_CACHES, }; static const struct option options[] = { @@ -1134,6 +1155,7 @@ static int parse_argv(int argc, char *argv[]) { { "search", required_argument, NULL, ARG_SEARCH }, { "statistics", no_argument, NULL, ARG_STATISTICS, }, { "reset-statistics", no_argument, NULL, ARG_RESET_STATISTICS }, + { "flush-caches", no_argument, NULL, ARG_FLUSH_CACHES }, {} }; @@ -1307,6 +1329,10 @@ static int parse_argv(int argc, char *argv[]) { arg_mode = MODE_RESET_STATISTICS; break; + case ARG_FLUSH_CACHES: + arg_mode = MODE_FLUSH_CACHES; + break; + case '?': return -EINVAL; @@ -1473,6 +1499,16 @@ int main(int argc, char **argv) { r = reset_statistics(bus); break; + + case MODE_FLUSH_CACHES: + if (argc > optind) { + log_error("Too many arguments."); + r = -EINVAL; + goto finish; + } + + r = flush_caches(bus); + break; } finish: diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index 6d4e5746f7..a72a03cfad 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -1535,6 +1535,17 @@ static int bus_method_get_link(sd_bus_message *message, void *userdata, sd_bus_e return sd_bus_reply_method_return(message, "o", p); } +static int bus_method_flush_caches(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + assert(message); + assert(m); + + manager_flush_caches(m); + + return sd_bus_reply_method_return(message, NULL); +} + static const sd_bus_vtable resolve_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0), @@ -1550,6 +1561,7 @@ static const sd_bus_vtable resolve_vtable[] = { 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_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, 0), + SD_BUS_METHOD("FlushCaches", NULL, NULL, bus_method_flush_caches, 0), SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, 0), SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_domains, 0), diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 6cf75f9183..a46f13b92f 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -468,16 +468,14 @@ static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si static int manager_sigusr2(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { Manager *m = userdata; - DnsScope *scope; assert(s); assert(si); assert(m); - LIST_FOREACH(scopes, scope, m->dns_scopes) - dns_cache_flush(&scope->cache); - + manager_flush_caches(m); log_info("Flushed all caches."); + return 0; } @@ -1251,3 +1249,12 @@ bool manager_routable(Manager *m, int family) { return false; } + +void manager_flush_caches(Manager *m) { + DnsScope *scope; + + assert(m); + + LIST_FOREACH(scopes, scope, m->dns_scopes) + dns_cache_flush(&scope->cache); +} diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index 97f75ace79..ef71202ef9 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -170,3 +170,5 @@ bool manager_dnssec_supported(Manager *m); void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResourceKey *key); bool manager_routable(Manager *m, int family); + +void manager_flush_caches(Manager *m); -- cgit v1.2.3-54-g00ecf From 04b764bf76a74943ca652691cfd5b511ed8fe96c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 10 Jun 2016 20:54:10 +0200 Subject: resolved: move verification that link is unmanaged into the proper bus calls Previously, we checked only for the various SetLinkXYZ() calls on the Manager object exposed on the bus if the specified interface is managed/unmanaged by networkd (as we don't permit overriding DNS configuration via bus calls if networkd owns the device), but the equivalent SetXYZ() calls on the Link object did not have such a check. Fix that by moving the appropriate check into the latter, as the former just calls that anyway. --- src/resolve/resolved-bus.c | 22 +--------------------- src/resolve/resolved-link-bus.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index a72a03cfad..6d86cbf123 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -1442,26 +1442,6 @@ static int get_any_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error return 0; } -static int get_unmanaged_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) { - Link *l; - int r; - - assert(m); - assert(ret); - - r = get_any_link(m, ifindex, &l, error); - if (r < 0) - return r; - - if (l->flags & IFF_LOOPBACK) - return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is loopback device.", l->name); - if (l->is_managed) - return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is managed.", l->name); - - *ret = l; - return 0; -} - static int call_link_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) { int ifindex, r; Link *l; @@ -1475,7 +1455,7 @@ static int call_link_method(Manager *m, sd_bus_message *message, sd_bus_message_ if (r < 0) return r; - r = get_unmanaged_link(m, ifindex, &l, error); + r = get_any_link(m, ifindex, &l, error); if (r < 0) return r; diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c index 6aff427192..bfb87d78e7 100644 --- a/src/resolve/resolved-link-bus.c +++ b/src/resolve/resolved-link-bus.c @@ -18,6 +18,7 @@ ***/ #include "alloc-util.h" +#include "bus-common-errors.h" #include "bus-util.h" #include "parse-util.h" #include "resolve-util.h" @@ -158,6 +159,17 @@ static int property_get_dnssec_supported( return sd_bus_message_append(reply, "b", link_dnssec_supported(l)); } +static int verify_unmanaged_link(Link *l, sd_bus_error *error) { + assert(l); + + if (l->flags & IFF_LOOPBACK) + return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is loopback device.", l->name); + if (l->is_managed) + return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is managed.", l->name); + + 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; size_t allocated = 0, n = 0; @@ -168,6 +180,10 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_ assert(message); assert(l); + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + r = sd_bus_message_enter_container(message, 'a', "(iay)"); if (r < 0) return r; @@ -249,6 +265,10 @@ int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_ assert(message); assert(l); + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + r = sd_bus_message_enter_container(message, 'a', "(sb)"); if (r < 0) return r; @@ -328,6 +348,10 @@ int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_er assert(message); assert(l); + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + r = sd_bus_message_read(message, "s", &llmnr); if (r < 0) return r; @@ -356,6 +380,10 @@ int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_err assert(message); assert(l); + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + r = sd_bus_message_read(message, "s", &mdns); if (r < 0) return r; @@ -384,6 +412,10 @@ int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_e assert(message); assert(l); + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + r = sd_bus_message_read(message, "s", &dnssec); if (r < 0) return r; @@ -411,6 +443,10 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v assert(message); assert(l); + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + r = sd_bus_message_read_strv(message, &ntas); if (r < 0) return r; @@ -442,10 +478,15 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error *error) { Link *l = userdata; + int r; assert(message); assert(l); + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + link_flush_settings(l); link_allocate_scopes(l); link_add_rrs(l, false); -- cgit v1.2.3-54-g00ecf