From 4d506d6bb757af3b99e0876234c465e6898c5ea4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Aug 2015 09:41:45 +0200 Subject: [PATCH] resolved: dump cache and zone contents to syslog on SIGUSR1 --- src/resolve/resolved-dns-cache.c | 51 ++++++++++++++++++++++++++++++++ src/resolve/resolved-dns-cache.h | 3 ++ src/resolve/resolved-dns-scope.c | 32 ++++++++++++++++++++ src/resolve/resolved-dns-scope.h | 2 ++ src/resolve/resolved-dns-zone.c | 37 +++++++++++++++++++++++ src/resolve/resolved-dns-zone.h | 3 ++ src/resolve/resolved-manager.c | 29 ++++++++++++++++++ src/resolve/resolved-manager.h | 2 ++ src/resolve/resolved.c | 2 +- 9 files changed, 160 insertions(+), 1 deletion(-) diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index 7ee098397cb..ef6b69c768e 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -620,3 +620,54 @@ int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_ /* There's a conflict */ return 1; } + +void dns_cache_dump(DnsCache *cache, FILE *f) { + Iterator iterator; + DnsCacheItem *i; + int r; + + if (!cache) + return; + + if (!f) + f = stdout; + + HASHMAP_FOREACH(i, cache->by_key, iterator) { + DnsCacheItem *j; + + LIST_FOREACH(by_key, j, i) { + _cleanup_free_ char *t = NULL; + + fputc('\t', f); + + if (j->rr) { + r = dns_resource_record_to_string(j->rr, &t); + if (r < 0) { + log_oom(); + continue; + } + + fputs(t, f); + fputc('\n', f); + } else { + r = dns_resource_key_to_string(j->key, &t); + if (r < 0) { + log_oom(); + continue; + } + + fputs(t, f); + fputs(" -- ", f); + fputs(j->type == DNS_CACHE_NODATA ? "NODATA" : "NXDOMAIN", f); + fputc('\n', f); + } + } + } +} + +bool dns_cache_is_empty(DnsCache *cache) { + if (!cache) + return true; + + return hashmap_isempty(cache->by_key); +} diff --git a/src/resolve/resolved-dns-cache.h b/src/resolve/resolved-dns-cache.h index fd583a775f6..1225e58de4c 100644 --- a/src/resolve/resolved-dns-cache.h +++ b/src/resolve/resolved-dns-cache.h @@ -43,3 +43,6 @@ int dns_cache_put(DnsCache *c, DnsQuestion *q, int rcode, DnsAnswer *answer, uns int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **answer); int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address); + +void dns_cache_dump(DnsCache *cache, FILE *f); +bool dns_cache_is_empty(DnsCache *cache); diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index eaa099341f8..9e6f595a1b7 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -812,3 +812,35 @@ void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p) { dns_scope_notify_conflict(scope, p->answer->items[i].rr); } } + +void dns_scope_dump(DnsScope *s, FILE *f) { + assert(s); + + if (!f) + f = stdout; + + fputs("[Scope protocol=", f); + fputs(dns_protocol_to_string(s->protocol), f); + + if (s->link) { + fputs(" interface=", f); + fputs(s->link->name, f); + } + + if (s->family != AF_UNSPEC) { + fputs(" family=", f); + fputs(af_to_name(s->family), f); + } + + fputs("]\n", f); + + if (!dns_zone_is_empty(&s->zone)) { + fputs("ZONE:\n", f); + dns_zone_dump(&s->zone, f); + } + + if (!dns_cache_is_empty(&s->cache)) { + fputs("CACHE:\n", f); + dns_cache_dump(&s->cache, f); + } +} diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h index 88fb8224e24..b75f212897c 100644 --- a/src/resolve/resolved-dns-scope.h +++ b/src/resolve/resolved-dns-scope.h @@ -89,3 +89,5 @@ DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr); void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p); + +void dns_scope_dump(DnsScope *s, FILE *f); diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c index fc212f48f4a..674bb6af281 100644 --- a/src/resolve/resolved-dns-zone.c +++ b/src/resolve/resolved-dns-zone.c @@ -636,3 +636,40 @@ void dns_zone_verify_all(DnsZone *zone) { dns_zone_item_verify(j); } } + +void dns_zone_dump(DnsZone *zone, FILE *f) { + Iterator iterator; + DnsZoneItem *i; + int r; + + if (!zone) + return; + + if (!f) + f = stdout; + + HASHMAP_FOREACH(i, zone->by_key, iterator) { + DnsZoneItem *j; + + LIST_FOREACH(by_key, j, i) { + _cleanup_free_ char *t = NULL; + + r = dns_resource_record_to_string(j->rr, &t); + if (r < 0) { + log_oom(); + continue; + } + + fputc('\t', f); + fputs(t, f); + fputc('\n', f); + } + } +} + +bool dns_zone_is_empty(DnsZone *zone) { + if (!zone) + return true; + + return hashmap_isempty(zone->by_key); +} diff --git a/src/resolve/resolved-dns-zone.h b/src/resolve/resolved-dns-zone.h index 71851265c61..495d17cdb12 100644 --- a/src/resolve/resolved-dns-zone.h +++ b/src/resolve/resolved-dns-zone.h @@ -78,3 +78,6 @@ int dns_zone_verify_conflicts(DnsZone *zone, DnsResourceKey *key); void dns_zone_verify_all(DnsZone *zone); void dns_zone_item_probe_stop(DnsZoneItem *i); + +void dns_zone_dump(DnsZone *zone, FILE *f); +bool dns_zone_is_empty(DnsZone *zone); diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index fb2a06b517e..1407c637e88 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -430,6 +430,31 @@ static int manager_watch_hostname(Manager *m) { return 0; } +static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + _cleanup_free_ char *buffer = NULL; + _cleanup_fclose_ FILE *f = NULL; + Manager *m = userdata; + size_t size = 0; + DnsScope *scope; + + assert(s); + assert(si); + assert(m); + + f = open_memstream(&buffer, &size); + if (!f) + return log_oom(); + + LIST_FOREACH(scopes, scope, m->dns_scopes) + dns_scope_dump(scope, f); + + if (fflush_and_check(f) < 0) + return log_oom(); + + log_dump(LOG_INFO, buffer); + return 0; +} + int manager_new(Manager **ret) { _cleanup_(manager_freep) Manager *m = NULL; int r; @@ -480,6 +505,8 @@ int manager_new(Manager **ret) { if (r < 0) return r; + (void) sd_event_add_signal(m->event, &m->sigusr1_event_source, SIGUSR1, manager_sigusr1, m); + *ret = m; m = NULL; @@ -527,6 +554,8 @@ Manager *manager_free(Manager *m) { sd_event_source_unref(m->bus_retry_event_source); sd_bus_unref(m->bus); + sd_event_source_unref(m->sigusr1_event_source); + sd_event_unref(m->event); dns_resource_key_unref(m->llmnr_host_ipv4_key); diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index 6f7972bbf34..fe7fe995058 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -102,6 +102,8 @@ struct Manager { /* Watch for system suspends */ sd_bus_slot *prepare_for_sleep_slot; + + sd_event_source *sigusr1_event_source; }; /* Manager */ diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c index 0af5545f8e4..32e61af9251 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, -1) >= 0); + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, -1) >= 0); r = manager_new(&m); if (r < 0) { -- 2.39.2