summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--man/systemd-resolve.xml13
-rw-r--r--man/systemd-resolved.service.xml30
-rw-r--r--src/resolve/resolve-tool.c77
-rw-r--r--src/resolve/resolved-bus.c12
-rw-r--r--src/resolve/resolved-manager.c13
-rw-r--r--src/resolve/resolved-manager.h1
-rw-r--r--src/resolve/resolved.c2
8 files changed, 126 insertions, 28 deletions
diff --git a/NEWS b/NEWS
index ac6f23c37d..bc1a77bf12 100644
--- a/NEWS
+++ b/NEWS
@@ -209,6 +209,12 @@ CHANGES WITH 235:
too. Note that while the other databases are world-readable
(i.e. 0644), btmp is not and remains more restrictive.
+ * The systemd-resolve tool gained a new --reset-server-features
+ switch. When invoked like this systemd-resolved will forget
+ everything it learnt about the features supported by the configured
+ upstream DNS servers, and restarts the feature probing logic on the
+ next resolver look-up for them at the highest feature level again.
+
Contributions from: Abdó Roig-Maranges, Alan Jenkins, Alexander
Kuleshov, Andreas Rammhold, Andrew Jeddeloh, Andrew Soutar, Ansgar
Burchardt, b1tninja, bengal, Benjamin Berg, Benjamin Robin, Charles
diff --git a/man/systemd-resolve.xml b/man/systemd-resolve.xml
index 47c90f2e48..53f843ff93 100644
--- a/man/systemd-resolve.xml
+++ b/man/systemd-resolve.xml
@@ -299,7 +299,18 @@
<varlistentry>
<term><option>--flush-caches</option></term>
- <listitem><para>Flushes all DNS resource record caches the service maintains locally.</para></listitem>
+ <listitem><para>Flushes all DNS resource record caches the service maintains locally. This is mostly equivalent
+ to sending the <constant>SIGUSR2</constant> to the <command>systemd-resolved</command>
+ service.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--reset-server-features</option></term>
+
+ <listitem><para>Flushes all feature level information the resolver learnt about specific servers, and ensures
+ that the server feature probing logic is started from the beginning with the next look-up request. This is
+ mostly equivalent to sending the <constant>SIGRTMIN+1</constant> to the <command>systemd-resolved</command>
+ service.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd-resolved.service.xml b/man/systemd-resolved.service.xml
index fd717e4963..1ad9500d78 100644
--- a/man/systemd-resolved.service.xml
+++ b/man/systemd-resolved.service.xml
@@ -202,19 +202,37 @@
<varlistentry>
<term><constant>SIGUSR1</constant></term>
- <listitem><para>Upon reception of the SIGUSR1 process signal <command>systemd-resolved</command> will dump the
- contents of all DNS resource record caches it maintains into the system logs.</para></listitem>
+ <listitem><para>Upon reception of the <constant>SIGUSR1</constant> process signal
+ <command>systemd-resolved</command> will dump the contents of all DNS resource record caches it maintains into
+ the system logs.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>SIGUSR2</constant></term>
- <listitem><para>Upon reception of the SIGUSR2 process signal <command>systemd-resolved</command> will flush all
- caches it maintains. Note that it should normally not be necessary to request this explicitly – except for
- debugging purposes – as <command>systemd-resolved</command> flushes the caches automatically anyway any time
- the host's network configuration changes.</para></listitem>
+ <listitem><para>Upon reception of the <constant>SIGUSR2</constant> process signal
+ <command>systemd-resolved</command> will flush all caches it maintains. Note that it should normally not be
+ necessary to request this explicitly – except for debugging purposes – as <command>systemd-resolved</command>
+ flushes the caches automatically anyway any time the host's network configuration changes. Sending this signal
+ to <command>systemd-resolved</command> is equivalent to the <command>systemd-resolve --flush-caches</command>
+ command, however the latter is recommended since it operates in a synchronous way.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+1</constant></term>
+
+ <listitem><para>Upon reception of the <constant>SIGRTMIN+1</constant> process signal
+ <command>systemd-resolved</command> will forget everything it learnt about the configured DNS
+ servers. Specifically any information about server feature support is flushed out, and the server feature
+ probing logic is restarted on the next request, starting with the most fully featured level. Note that it
+ should normally not be necessary to request this explicitly – except for debugging purposes – as
+ <command>systemd-resolved</command> automatically forgets learnt information any time the DNS server
+ configuration changes. Sending this signal to <command>systemd-resolved</command> is equivalent to the
+ <command>systemd-resolve --reset-server-features</command> command, however the latter is recommended since it
+ operates in a synchronous way.</para></listitem>
</varlistentry>
</variablelist>
+
</refsect1>
<refsect1>
diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c
index 195555c3c0..708378573f 100644
--- a/src/resolve/resolve-tool.c
+++ b/src/resolve/resolve-tool.c
@@ -72,6 +72,7 @@ static enum {
MODE_STATISTICS,
MODE_RESET_STATISTICS,
MODE_FLUSH_CACHES,
+ MODE_RESET_SERVER_FEATURES,
MODE_STATUS,
} arg_mode = MODE_RESOLVE_HOST;
@@ -1055,6 +1056,24 @@ static int flush_caches(sd_bus *bus) {
return 0;
}
+static int reset_server_features(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",
+ "ResetServerFeatures",
+ &error,
+ NULL,
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to reset server features: %s", bus_error_message(&error, r));
+
+ return 0;
+}
+
static int map_link_dns_servers(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
char ***l = userdata;
int r;
@@ -1588,6 +1607,8 @@ static void help(void) {
" --reset-statistics Reset resolver statistics\n"
" --status Show link and server status\n"
" --flush-caches Flush all local DNS caches\n"
+ " --reset-server-features\n"
+ " Forget learnt DNS server feature levels\n"
, program_invocation_short_name);
}
@@ -1607,30 +1628,32 @@ static int parse_argv(int argc, char *argv[]) {
ARG_RESET_STATISTICS,
ARG_STATUS,
ARG_FLUSH_CACHES,
+ ARG_RESET_SERVER_FEATURES,
ARG_NO_PAGER,
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "type", required_argument, NULL, 't' },
- { "class", required_argument, NULL, 'c' },
- { "legend", required_argument, NULL, ARG_LEGEND },
- { "interface", required_argument, NULL, 'i' },
- { "protocol", required_argument, NULL, 'p' },
- { "cname", required_argument, NULL, ARG_CNAME },
- { "service", no_argument, NULL, ARG_SERVICE },
- { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS },
- { "service-txt", required_argument, NULL, ARG_SERVICE_TXT },
- { "openpgp", no_argument, NULL, ARG_OPENPGP },
- { "tlsa", optional_argument, NULL, ARG_TLSA },
- { "raw", optional_argument, NULL, ARG_RAW },
- { "search", required_argument, NULL, ARG_SEARCH },
- { "statistics", no_argument, NULL, ARG_STATISTICS, },
- { "reset-statistics", no_argument, NULL, ARG_RESET_STATISTICS },
- { "status", no_argument, NULL, ARG_STATUS },
- { "flush-caches", no_argument, NULL, ARG_FLUSH_CACHES },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "type", required_argument, NULL, 't' },
+ { "class", required_argument, NULL, 'c' },
+ { "legend", required_argument, NULL, ARG_LEGEND },
+ { "interface", required_argument, NULL, 'i' },
+ { "protocol", required_argument, NULL, 'p' },
+ { "cname", required_argument, NULL, ARG_CNAME },
+ { "service", no_argument, NULL, ARG_SERVICE },
+ { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS },
+ { "service-txt", required_argument, NULL, ARG_SERVICE_TXT },
+ { "openpgp", no_argument, NULL, ARG_OPENPGP },
+ { "tlsa", optional_argument, NULL, ARG_TLSA },
+ { "raw", optional_argument, NULL, ARG_RAW },
+ { "search", required_argument, NULL, ARG_SEARCH },
+ { "statistics", no_argument, NULL, ARG_STATISTICS, },
+ { "reset-statistics", no_argument, NULL, ARG_RESET_STATISTICS },
+ { "status", no_argument, NULL, ARG_STATUS },
+ { "flush-caches", no_argument, NULL, ARG_FLUSH_CACHES },
+ { "reset-server-features", no_argument, NULL, ARG_RESET_SERVER_FEATURES },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
{}
};
@@ -1814,6 +1837,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_mode = MODE_FLUSH_CACHES;
break;
+ case ARG_RESET_SERVER_FEATURES:
+ arg_mode = MODE_RESET_SERVER_FEATURES;
+ break;
+
case ARG_STATUS:
arg_mode = MODE_STATUS;
break;
@@ -1999,6 +2026,16 @@ int main(int argc, char **argv) {
r = flush_caches(bus);
break;
+ case MODE_RESET_SERVER_FEATURES:
+ if (argc > optind) {
+ log_error("Too many arguments.");
+ r = -EINVAL;
+ goto finish;
+ }
+
+ r = reset_server_features(bus);
+ break;
+
case MODE_STATUS:
if (argc > optind) {
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
index bf822d3aaa..c6f14eb416 100644
--- a/src/resolve/resolved-bus.c
+++ b/src/resolve/resolved-bus.c
@@ -1569,6 +1569,17 @@ static int bus_method_flush_caches(sd_bus_message *message, void *userdata, sd_b
return sd_bus_reply_method_return(message, NULL);
}
+static int bus_method_reset_server_features(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+
+ assert(message);
+ assert(m);
+
+ manager_reset_server_features(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),
@@ -1587,6 +1598,7 @@ static const sd_bus_vtable resolve_vtable[] = {
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("ResetServerFeatures", NULL, NULL, bus_method_reset_server_features, 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 3765d74cee..50d32d37e9 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -552,6 +552,17 @@ static int manager_sigusr2(sd_event_source *s, const struct signalfd_siginfo *si
return 0;
}
+static int manager_sigrtmin1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
+ Manager *m = userdata;
+
+ assert(s);
+ assert(si);
+ assert(m);
+
+ manager_reset_server_features(m);
+ return 0;
+}
+
int manager_new(Manager **ret) {
_cleanup_(manager_freep) Manager *m = NULL;
int r;
@@ -616,6 +627,7 @@ int manager_new(Manager **ret) {
(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);
+ (void) sd_event_add_signal(m->event, &m->sigrtmin1_event_source, SIGRTMIN+1, manager_sigrtmin1, m);
manager_cleanup_saved_user(m);
@@ -679,6 +691,7 @@ Manager *manager_free(Manager *m) {
sd_event_source_unref(m->sigusr1_event_source);
sd_event_source_unref(m->sigusr2_event_source);
+ sd_event_source_unref(m->sigrtmin1_event_source);
sd_event_unref(m->event);
diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h
index bb45ecc1d6..32a0e5fe0f 100644
--- a/src/resolve/resolved-manager.h
+++ b/src/resolve/resolved-manager.h
@@ -126,6 +126,7 @@ struct Manager {
sd_event_source *sigusr1_event_source;
sd_event_source *sigusr2_event_source;
+ sd_event_source *sigrtmin1_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 8fd81956b8..2eb7bfd030 100644
--- a/src/resolve/resolved.c
+++ b/src/resolve/resolved.c
@@ -80,7 +80,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, SIGUSR2, -1) >= 0);
+ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, SIGUSR2, SIGRTMIN+1, -1) >= 0);
r = manager_new(&m);
if (r < 0) {