]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: add support for explicitly forgetting everything we learnt about DNS server...
authorLennart Poettering <lennart@poettering.net>
Fri, 29 Sep 2017 19:19:54 +0000 (21:19 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 5 Oct 2017 14:56:50 +0000 (16:56 +0200)
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.

NEWS
man/systemd-resolve.xml
man/systemd-resolved.service.xml
src/resolve/resolve-tool.c
src/resolve/resolved-bus.c
src/resolve/resolved-manager.c
src/resolve/resolved-manager.h
src/resolve/resolved.c

diff --git a/NEWS b/NEWS
index ac6f23c37dff3018cd913dbad328c0d80538dc17..bc1a77bf1227f68240bdbf218fec501c7562f9b0 100644 (file)
--- 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
index 47c90f2e482ae7a21a21ab73958996268b1415f0..53f843ff93869bf7c974b095e8506a09151c15db 100644 (file)
       <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>
index fd717e4963e7a62e4f3d623b9bda1c04ec59cc20..1ad9500d78bd28561aa3c0da4ff44351a2bf3273 100644 (file)
       <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>
index 195555c3c0a4684696472e9051576a5279e1e6b8..708378573fcdbd9b442f5ac68b990ef33058b195 100644 (file)
@@ -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) {
index bf822d3aaa58734f5cdf4b7910f2bbe448a6fb4b..c6f14eb416ce7721b94e1bfbe10eede19fa719ac 100644 (file)
@@ -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),
index 3765d74cee3f67b179341896d25daaf274689da1..50d32d37e9a010e9ac163169ed4df06abff783c7 100644 (file)
@@ -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);
 
index bb45ecc1d60979c5921e1952722a5fde75f8acb4..32a0e5fe0f80f8a1482418767de5c4b486a15a3f 100644 (file)
@@ -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];
index 8fd81956b8316a643091ee6bd95d0056e3b24794..2eb7bfd03079cc20ba1cd5a727c3730c88bce891 100644 (file)
@@ -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) {