mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
resolved: add support for explicitly forgetting everything we learnt about DNS server feature levels
This adds "systemd-resolve --reset-server-features" for explicitly forgetting what we learnt. This might be useful for debugging purposes, and to force systemd-resolved to restart its learning logic for all DNS servers.
This commit is contained in:
parent
59c0fd0e17
commit
d55b0463b2
6
NEWS
6
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
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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) {
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user