From 59c0fd0e17e485d551daa9cd26fa0cfc726085b0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 29 Sep 2017 21:18:29 +0200 Subject: [PATCH 1/3] resolved: automatically forget all learnt DNS server information when the network configuration changes When the network configuration changes we should relearn everything there is to know about the configured DNS servers, because we might talk to the same addresses, but there might be different servers behind them. --- src/resolve/resolved-dns-server.c | 35 +++++++++++++++++++++++++----- src/resolve/resolved-dns-server.h | 3 +++ src/resolve/resolved-link.c | 21 ++++++++++++++++-- src/resolve/resolved-link.h | 2 ++ src/resolve/resolved-manager.c | 13 +++++++++++ src/resolve/resolved-manager.h | 1 + src/resolve/resolved-resolv-conf.c | 6 +++++ 7 files changed, 74 insertions(+), 7 deletions(-) diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index b3d37525f4..f0822d1f72 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -70,15 +70,12 @@ int dns_server_new( s->n_ref = 1; s->manager = m; - s->verified_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID; - s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST; - s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC; - s->received_udp_packet_max = DNS_PACKET_UNICAST_SIZE_MAX; s->type = type; s->family = family; s->address = *in_addr; s->ifindex = ifindex; - s->resend_timeout = DNS_TIMEOUT_MIN_USEC; + + dns_server_reset_features(s); switch (type) { @@ -828,6 +825,34 @@ void dns_server_flush_cache(DnsServer *s) { dns_cache_flush(&scope->cache); } +void dns_server_reset_features(DnsServer *s) { + assert(s); + + s->max_rtt = 0; + s->resend_timeout = DNS_TIMEOUT_MIN_USEC; + + s->verified_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID; + s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST; + + s->received_udp_packet_max = DNS_PACKET_UNICAST_SIZE_MAX; + + s->packet_bad_opt = false; + s->packet_rrsig_missing = false; + + s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC; + + s->warned_downgrade = false; + + dns_server_reset_counters(s); +} + +void dns_server_reset_features_all(DnsServer *s) { + DnsServer *i; + + LIST_FOREACH(servers, i, s) + dns_server_reset_features(i); +} + static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = { [DNS_SERVER_SYSTEM] = "system", [DNS_SERVER_FALLBACK] = "fallback", diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h index bc95d53c6a..a5a82f7b76 100644 --- a/src/resolve/resolved-dns-server.h +++ b/src/resolve/resolved-dns-server.h @@ -151,3 +151,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServer*, dns_server_unref); extern const struct hash_ops dns_server_hash_ops; void dns_server_flush_cache(DnsServer *s); + +void dns_server_reset_features(DnsServer *s); +void dns_server_reset_features_all(DnsServer *s); diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index 21fd8465e6..3d26831b06 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -111,13 +111,30 @@ Link *link_free(Link *l) { } void link_allocate_scopes(Link *l) { + bool unicast_relevant; int r; assert(l); - if (link_relevant(l, AF_UNSPEC, false) && - l->dns_servers) { + /* If a link that used to be relevant is no longer, or a link that did not use to be relevant now becomes + * relevant, let's reinit the learnt global DNS server information, since we might talk to different servers + * now, even if they have the same addresses as before. */ + + unicast_relevant = link_relevant(l, AF_UNSPEC, false); + if (unicast_relevant != l->unicast_relevant) { + l->unicast_relevant = unicast_relevant; + + dns_server_reset_features_all(l->manager->fallback_dns_servers); + dns_server_reset_features_all(l->manager->dns_servers); + } + + /* And now, allocate all scopes that makes sense now if we didn't have them yet, and drop those which we don't + * need anymore */ + + if (unicast_relevant && l->dns_servers) { if (!l->unicast_scope) { + dns_server_reset_features_all(l->dns_servers); + r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC); if (r < 0) log_warning_errno(r, "Failed to allocate DNS scope: %m"); diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h index 55a56b7906..c20b8b6d29 100644 --- a/src/resolve/resolved-link.h +++ b/src/resolve/resolved-link.h @@ -88,6 +88,8 @@ struct Link { bool loaded; char *state_file; + + bool unicast_relevant; }; int link_new(Manager *m, Link **ret, int ifindex); diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 58fe572d3b..3765d74cee 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -1396,6 +1396,19 @@ void manager_flush_caches(Manager *m) { log_info("Flushed all caches."); } +void manager_reset_server_features(Manager *m) { + Iterator i; + Link *l; + + dns_server_reset_features_all(m->dns_servers); + dns_server_reset_features_all(m->fallback_dns_servers); + + HASHMAP_FOREACH(l, m->links, i) + dns_server_reset_features_all(l->dns_servers); + + log_info("Resetting learnt feature levels on all servers."); +} + void manager_cleanup_saved_user(Manager *m) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index 97c52b7729..bb45ecc1d6 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -184,5 +184,6 @@ void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResource bool manager_routable(Manager *m, int family); void manager_flush_caches(Manager *m); +void manager_reset_server_features(Manager *m); void manager_cleanup_saved_user(Manager *m); diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c index 2af77b3407..e3d6a33409 100644 --- a/src/resolve/resolved-resolv-conf.c +++ b/src/resolve/resolved-resolv-conf.c @@ -26,6 +26,7 @@ #include "fileio.h" #include "ordered-set.h" #include "resolved-conf.h" +#include "resolved-dns-server.h" #include "resolved-resolv-conf.h" #include "string-util.h" #include "strv.h" @@ -136,6 +137,11 @@ int manager_read_resolv_conf(Manager *m) { if (m->unicast_scope) dns_cache_flush(&m->unicast_scope->cache); + /* If /etc/resolv.conf changed, make sure to forget everything we learned about the DNS servers. After all we + * might now talk to a very different DNS server that just happens to have the same IP address as an old one + * (think 192.168.1.1). */ + dns_server_reset_features_all(m->dns_servers); + return 0; clear: From d55b0463b2537874feca70e3c4c419b4f8831444 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 29 Sep 2017 21:19:54 +0200 Subject: [PATCH 2/3] 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. --- NEWS | 6 +++ man/systemd-resolve.xml | 13 +++++- man/systemd-resolved.service.xml | 30 ++++++++++--- src/resolve/resolve-tool.c | 77 +++++++++++++++++++++++--------- src/resolve/resolved-bus.c | 12 +++++ src/resolve/resolved-manager.c | 13 ++++++ src/resolve/resolved-manager.h | 1 + src/resolve/resolved.c | 2 +- 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 @@ - Flushes all DNS resource record caches the service maintains locally. + Flushes all DNS resource record caches the service maintains locally. This is mostly equivalent + to sending the SIGUSR2 to the systemd-resolved + service. + + + + + + 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 SIGRTMIN+1 to the systemd-resolved + service. 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 @@ SIGUSR1 - Upon reception of the SIGUSR1 process signal systemd-resolved will dump the - contents of all DNS resource record caches it maintains into the system logs. + Upon reception of the SIGUSR1 process signal + systemd-resolved will dump the contents of all DNS resource record caches it maintains into + the system logs. SIGUSR2 - Upon reception of the SIGUSR2 process signal systemd-resolved will flush all - caches it maintains. Note that it should normally not be necessary to request this explicitly – except for - debugging purposes – as systemd-resolved flushes the caches automatically anyway any time - the host's network configuration changes. + Upon reception of the SIGUSR2 process signal + systemd-resolved will flush all caches it maintains. Note that it should normally not be + necessary to request this explicitly – except for debugging purposes – as systemd-resolved + flushes the caches automatically anyway any time the host's network configuration changes. Sending this signal + to systemd-resolved is equivalent to the systemd-resolve --flush-caches + command, however the latter is recommended since it operates in a synchronous way. + + + + SIGRTMIN+1 + + Upon reception of the SIGRTMIN+1 process signal + systemd-resolved 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 + systemd-resolved automatically forgets learnt information any time the DNS server + configuration changes. Sending this signal to systemd-resolved is equivalent to the + systemd-resolve --reset-server-features command, however the latter is recommended since it + operates in a synchronous way. + 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) { From cf84484a56bb03043569445f2df7afd4d7aa3fb0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 5 Oct 2017 16:53:32 +0200 Subject: [PATCH 3/3] resolved: include DNS server feature level info in SIGUSR1 status dump let's make the status dump more useful for tracking down server issues. --- NEWS | 7 ++++- man/systemd-resolved.service.xml | 5 +-- src/resolve/resolved-dns-server.c | 51 +++++++++++++++++++++++++++++++ src/resolve/resolved-dns-server.h | 2 ++ src/resolve/resolved-manager.c | 11 +++++++ 5 files changed, 73 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index bc1a77bf12..fdd0b88077 100644 --- a/NEWS +++ b/NEWS @@ -213,7 +213,12 @@ CHANGES WITH 235: 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. + next resolver look-up for them at the highest feature level + again. + + * The status dump systemd-resolved sends to the logs upon receiving + SIGUSR1 now also includes information about all DNS servers it is + configured to use, and the features levels it probed for them. Contributions from: Abdó Roig-Maranges, Alan Jenkins, Alexander Kuleshov, Andreas Rammhold, Andrew Jeddeloh, Andrew Soutar, Ansgar diff --git a/man/systemd-resolved.service.xml b/man/systemd-resolved.service.xml index 1ad9500d78..d07d1968b4 100644 --- a/man/systemd-resolved.service.xml +++ b/man/systemd-resolved.service.xml @@ -203,8 +203,9 @@ SIGUSR1 Upon reception of the SIGUSR1 process signal - systemd-resolved will dump the contents of all DNS resource record caches it maintains into - the system logs. + systemd-resolved will dump the contents of all DNS resource record caches it maintains, as + well as all feature level information it learnt about configured DNS servers into the system + logs. diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index f0822d1f72..1b61dea626 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -853,6 +853,57 @@ void dns_server_reset_features_all(DnsServer *s) { dns_server_reset_features(i); } +void dns_server_dump(DnsServer *s, FILE *f) { + assert(s); + + if (!f) + f = stdout; + + fputs("[Server ", f); + fputs(dns_server_string(s), f); + fputs(" type=", f); + fputs(dns_server_type_to_string(s->type), f); + + if (s->type == DNS_SERVER_LINK) { + assert(s->link); + + fputs(" interface=", f); + fputs(s->link->name, f); + } + + fputs("]\n", f); + + fputs("\tVerified feature level: ", f); + fputs(strna(dns_server_feature_level_to_string(s->verified_feature_level)), f); + fputc('\n', f); + + fputs("\tPossible feature level: ", f); + fputs(strna(dns_server_feature_level_to_string(s->possible_feature_level)), f); + fputc('\n', f); + + fputs("\tDNSSEC Mode: ", f); + fputs(strna(dnssec_mode_to_string(dns_server_get_dnssec_mode(s))), f); + fputc('\n', f); + + fputs("\tCan do DNSSEC: ", f); + fputs(yes_no(dns_server_dnssec_supported(s)), f); + fputc('\n', f); + + fprintf(f, + "\tMaximum UDP packet size received: %zu\n" + "\tFailed UDP attempts: %u\n" + "\tFailed TCP attempts: %u\n" + "\tSeen truncated packet: %s\n" + "\tSeen OPT RR getting lost: %s\n" + "\tSeen RRSIG RR missing: %s\n", + s->received_udp_packet_max, + s->n_failed_udp, + s->n_failed_tcp, + yes_no(s->packet_truncated), + yes_no(s->packet_bad_opt), + yes_no(s->packet_rrsig_missing)); +} + static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = { [DNS_SERVER_SYSTEM] = "system", [DNS_SERVER_FALLBACK] = "fallback", diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h index a5a82f7b76..00edd47d9a 100644 --- a/src/resolve/resolved-dns-server.h +++ b/src/resolve/resolved-dns-server.h @@ -154,3 +154,5 @@ void dns_server_flush_cache(DnsServer *s); void dns_server_reset_features(DnsServer *s); void dns_server_reset_features_all(DnsServer *s); + +void dns_server_dump(DnsServer *s, FILE *f); diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 50d32d37e9..23c6731954 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -519,8 +519,11 @@ static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si _cleanup_free_ char *buffer = NULL; _cleanup_fclose_ FILE *f = NULL; Manager *m = userdata; + DnsServer *server; size_t size = 0; DnsScope *scope; + Iterator i; + Link *l; assert(s); assert(si); @@ -533,6 +536,14 @@ static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si LIST_FOREACH(scopes, scope, m->dns_scopes) dns_scope_dump(scope, f); + LIST_FOREACH(servers, server, m->dns_servers) + dns_server_dump(server, f); + LIST_FOREACH(servers, server, m->fallback_dns_servers) + dns_server_dump(server, f); + HASHMAP_FOREACH(l, m->links, i) + LIST_FOREACH(servers, server, l->dns_servers) + dns_server_dump(server, f); + if (fflush_and_check(f) < 0) return log_oom();