diff options
Diffstat (limited to 'src/resolve')
-rw-r--r-- | src/resolve/resolved-bus.c | 16 | ||||
-rw-r--r-- | src/resolve/resolved-dns-cache.c | 81 | ||||
-rw-r--r-- | src/resolve/resolved-dns-cache.h | 3 | ||||
-rw-r--r-- | src/resolve/resolved-dns-packet.h | 27 | ||||
-rw-r--r-- | src/resolve/resolved-dns-query.c | 8 | ||||
-rw-r--r-- | src/resolve/resolved-dns-scope.c | 91 | ||||
-rw-r--r-- | src/resolve/resolved-dns-scope.h | 4 | ||||
-rw-r--r-- | src/resolve/resolved-dns-transaction.c | 64 | ||||
-rw-r--r-- | src/resolve/resolved-dns-transaction.h | 6 | ||||
-rw-r--r-- | src/resolve/resolved-dns-zone.c | 37 | ||||
-rw-r--r-- | src/resolve/resolved-dns-zone.h | 3 | ||||
-rw-r--r-- | src/resolve/resolved-manager.c | 31 | ||||
-rw-r--r-- | src/resolve/resolved-manager.h | 2 | ||||
-rw-r--r-- | src/resolve/resolved.c | 2 |
14 files changed, 278 insertions, 97 deletions
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index 1f23834ce3..12c17003e9 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -226,10 +226,6 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) { * query, this time with the cname */ if (added <= 0) { r = dns_query_go(q); - if (r == -ESRCH) { - r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found"); - goto finish; - } if (r < 0) { r = sd_bus_reply_method_errno(q->request, -r, NULL); goto finish; @@ -346,10 +342,6 @@ static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, r = dns_query_go(q); if (r < 0) { dns_query_free(q); - - if (r == -ESRCH) - sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found"); - return r; } @@ -494,10 +486,6 @@ static int bus_method_resolve_address(sd_bus_message *message, void *userdata, s r = dns_query_go(q); if (r < 0) { dns_query_free(q); - - if (r == -ESRCH) - sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found"); - return r; } @@ -647,10 +635,6 @@ static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd r = dns_query_go(q); if (r < 0) { dns_query_free(q); - - if (r == -ESRCH) - sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found"); - return r; } diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index efc407dbc6..ef6b69c768 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -411,16 +411,17 @@ int dns_cache_put( int owner_family, const union in_addr_union *owner_address) { - unsigned i; + unsigned cache_keys, i; int r; assert(c); - assert(q); - /* First, delete all matching old RRs, so that we only keep - * complete by_key in place. */ - for (i = 0; i < q->n_keys; i++) - dns_cache_remove(c, q->keys[i]); + if (q) { + /* First, if we were passed a question, delete all matching old RRs, + * so that we only keep complete by_key in place. */ + for (i = 0; i < q->n_keys; i++) + dns_cache_remove(c, q->keys[i]); + } if (!answer) return 0; @@ -435,8 +436,13 @@ int dns_cache_put( if (!IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN)) return 0; + cache_keys = answer->n_rrs; + + if (q) + cache_keys += q->n_keys; + /* Make some space for our new entries */ - dns_cache_make_space(c, answer->n_rrs + q->n_keys); + dns_cache_make_space(c, cache_keys); if (timestamp <= 0) timestamp = now(clock_boottime_or_monotonic()); @@ -448,6 +454,9 @@ int dns_cache_put( goto fail; } + if (!q) + return 0; + /* Third, add in negative entries for all keys with no RR */ for (i = 0; i < q->n_keys; i++) { DnsResourceRecord *soa = NULL; @@ -479,8 +488,11 @@ fail: /* Adding all RRs failed. Let's clean up what we already * added, just in case */ - for (i = 0; i < q->n_keys; i++) - dns_cache_remove(c, q->keys[i]); + if (q) { + for (i = 0; i < q->n_keys; i++) + dns_cache_remove(c, q->keys[i]); + } + for (i = 0; i < answer->n_rrs; i++) dns_cache_remove(c, answer->items[i].rr->key); @@ -608,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 fd583a775f..1225e58de4 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-packet.h b/src/resolve/resolved-dns-packet.h index e81f8a8202..5628e579ad 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -121,15 +121,15 @@ static inline uint8_t* DNS_PACKET_DATA(DnsPacket *p) { #define DNS_PACKET_ARCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->arcount) #define DNS_PACKET_MAKE_FLAGS(qr, opcode, aa, tc, rd, ra, ad, cd, rcode) \ - (((uint16_t) !!qr << 15) | \ - ((uint16_t) (opcode & 15) << 11) | \ - ((uint16_t) !!aa << 10) | \ - ((uint16_t) !!tc << 9) | \ - ((uint16_t) !!rd << 8) | \ - ((uint16_t) !!ra << 7) | \ - ((uint16_t) !!ad << 5) | \ - ((uint16_t) !!cd << 4) | \ - ((uint16_t) (rcode & 15))) + (((uint16_t) !!(qr) << 15) | \ + ((uint16_t) ((opcode) & 15) << 11) | \ + ((uint16_t) !!(aa) << 10) | /* on LLMNR: c */ \ + ((uint16_t) !!(tc) << 9) | \ + ((uint16_t) !!(rd) << 8) | /* on LLMNR: t */ \ + ((uint16_t) !!(ra) << 7) | \ + ((uint16_t) !!(ad) << 5) | \ + ((uint16_t) !!(cd) << 4) | \ + ((uint16_t) ((rcode) & 15))) static inline unsigned DNS_PACKET_RRCOUNT(DnsPacket *p) { return @@ -239,11 +239,16 @@ static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family) /* Converts a protocol + family into a flags field as used in queries */ - if (protocol == DNS_PROTOCOL_DNS) + switch (protocol) { + case DNS_PROTOCOL_DNS: return SD_RESOLVED_DNS; - if (protocol == DNS_PROTOCOL_LLMNR) + case DNS_PROTOCOL_LLMNR: return family == AF_INET6 ? SD_RESOLVED_LLMNR_IPV6 : SD_RESOLVED_LLMNR_IPV4; + default: + break; + } + return 0; } diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index d9f5b342b2..c0b4c8ba81 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -651,12 +651,8 @@ int dns_query_go(DnsQuery *q) { DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS; dns_query_synthesize_reply(q, &state); - if (state != DNS_TRANSACTION_NO_SERVERS) { - dns_query_complete(q, state); - return 1; - } - - return -ESRCH; + dns_query_complete(q, state); + return 1; } r = dns_query_add_transaction_split(q, first); diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 57a2c7d6c1..9e6f595a1b 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -78,8 +78,7 @@ DnsScope* dns_scope_free(DnsScope *s) { dns_scope_llmnr_membership(s, false); - while ((t = s->transactions)) { - + while ((t = hashmap_steal_first(s->transactions))) { /* Abort the transaction, but make sure it is not * freed while we still look at it */ @@ -90,6 +89,8 @@ DnsScope* dns_scope_free(DnsScope *s) { dns_transaction_free(t); } + hashmap_free(s->transactions); + while ((rr = ordered_hashmap_steal_first(s->conflict_queue))) dns_resource_record_unref(rr); @@ -165,7 +166,8 @@ int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) { } else mtu = manager_find_mtu(s->manager); - if (s->protocol == DNS_PROTOCOL_DNS) { + switch (s->protocol) { + case DNS_PROTOCOL_DNS: if (DNS_PACKET_QDCOUNT(p) > 1) return -EOPNOTSUPP; @@ -179,8 +181,9 @@ int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) { if (r < 0) return r; - } else if (s->protocol == DNS_PROTOCOL_LLMNR) { + break; + case DNS_PROTOCOL_LLMNR: if (DNS_PACKET_QDCOUNT(p) > 1) return -EOPNOTSUPP; @@ -204,8 +207,12 @@ int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) { r = manager_send(s->manager, fd, ifindex, family, &addr, port, p); if (r < 0) return r; - } else + + break; + + default: return -EAFNOSUPPORT; + } return 1; } @@ -340,16 +347,16 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co if (dns_name_endswith(domain, *i) > 0) return DNS_SCOPE_YES; - if (s->protocol == DNS_PROTOCOL_DNS) { + switch (s->protocol) { + case DNS_PROTOCOL_DNS: if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 && dns_name_endswith(domain, "0.8.e.f.ip6.arpa") == 0 && dns_name_single_label(domain) == 0) return DNS_SCOPE_MAYBE; return DNS_SCOPE_NO; - } - if (s->protocol == DNS_PROTOCOL_MDNS) { + case DNS_PROTOCOL_MDNS: if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) || (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) || (dns_name_endswith(domain, "local") > 0 && /* only resolve names ending in .local via mDNS */ @@ -358,9 +365,8 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co return DNS_SCOPE_MAYBE; return DNS_SCOPE_NO; - } - if (s->protocol == DNS_PROTOCOL_LLMNR) { + case DNS_PROTOCOL_LLMNR: if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) || (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) || (dns_name_single_label(domain) > 0 && /* only resolve single label names via LLMNR */ @@ -369,9 +375,10 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co return DNS_SCOPE_MAYBE; return DNS_SCOPE_NO; - } - assert_not_reached("Unknown scope protocol"); + default: + assert_not_reached("Unknown scope protocol"); + } } int dns_scope_good_key(DnsScope *s, DnsResourceKey *key) { @@ -623,24 +630,20 @@ DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, assert(scope); assert(key); - /* Try to find an ongoing transaction that is a equal or a - * superset of the specified question */ - - LIST_FOREACH(transactions_by_scope, t, scope->transactions) { - - /* Refuse reusing transactions that completed based on - * cached data instead of a real packet, if that's - * requested. */ - if (!cache_ok && - IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) && - !t->received) - continue; + /* Try to find an ongoing transaction that is a equal to the + * specified question */ + t = hashmap_get(scope->transactions, key); + if (!t) + return NULL; - if (dns_resource_key_equal(t->key, key) > 0) - return t; - } + /* Refuse reusing transactions that completed based on cached + * data instead of a real packet, if that's requested. */ + if (!cache_ok && + IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) && + !t->received) + return NULL; - return NULL; + return t; } static int dns_scope_make_conflict_packet( @@ -809,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 47f285db47..b75f212897 100644 --- a/src/resolve/resolved-dns-scope.h +++ b/src/resolve/resolved-dns-scope.h @@ -60,7 +60,7 @@ struct DnsScope { usec_t resend_timeout; usec_t max_rtt; - LIST_HEAD(DnsTransaction, transactions); + Hashmap *transactions; LIST_FIELDS(DnsScope, scopes); }; @@ -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-transaction.c b/src/resolve/resolved-dns-transaction.c index 81156dfa45..8092bb514d 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -35,24 +35,25 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) { sd_event_source_unref(t->timeout_event_source); - dns_resource_key_unref(t->key); dns_packet_unref(t->sent); dns_packet_unref(t->received); dns_answer_unref(t->cached); - sd_event_source_unref(t->dns_event_source); - safe_close(t->dns_fd); + sd_event_source_unref(t->dns_udp_event_source); + safe_close(t->dns_udp_fd); dns_server_unref(t->server); dns_stream_free(t->stream); if (t->scope) { - LIST_REMOVE(transactions_by_scope, t->scope->transactions, t); + hashmap_remove(t->scope->transactions, t->key); if (t->id != 0) hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id)); } + dns_resource_key_unref(t->key); + while ((q = set_steal_first(t->queries))) set_remove(q->transactions, t); set_free(t->queries); @@ -89,14 +90,18 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) if (r < 0) return r; + r = hashmap_ensure_allocated(&s->transactions, &dns_resource_key_hash_ops); + if (r < 0) + return r; + t = new0(DnsTransaction, 1); if (!t) return -ENOMEM; - t->dns_fd = -1; - + t->dns_udp_fd = -1; t->key = dns_resource_key_ref(key); + /* Find a fresh, unused transaction id */ do random_bytes(&t->id, sizeof(t->id)); while (t->id == 0 || @@ -108,7 +113,12 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) return r; } - LIST_PREPEND(transactions_by_scope, s->transactions, t); + r = hashmap_put(s->transactions, t->key, t); + if (r < 0) { + hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id)); + return r; + } + t->scope = s; if (ret) @@ -176,9 +186,6 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) { assert(t); assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING)); - if (!IN_SET(t->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING)) - return; - /* Note that this call might invalidate the query. Callers * should hence not attempt to access the query or transaction * after calling this function. */ @@ -253,10 +260,12 @@ static int dns_transaction_open_tcp(DnsTransaction *t) { if (t->stream) return 0; - if (t->scope->protocol == DNS_PROTOCOL_DNS) + switch (t->scope->protocol) { + case DNS_PROTOCOL_DNS: fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53, &server); - else if (t->scope->protocol == DNS_PROTOCOL_LLMNR) { + break; + case DNS_PROTOCOL_LLMNR: /* When we already received a reply to this (but it was truncated), send to its sender address */ if (t->received) fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL); @@ -274,12 +283,16 @@ static int dns_transaction_open_tcp(DnsTransaction *t) { if (r == 0) return -EINVAL; if (family != t->scope->family) - return -EAFNOSUPPORT; + return -ESRCH; fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT, NULL); } - } else + + break; + + default: return -EAFNOSUPPORT; + } if (fd < 0) return fd; @@ -315,8 +328,8 @@ static void dns_transaction_next_dns_server(DnsTransaction *t) { assert(t); t->server = dns_server_unref(t->server); - t->dns_event_source = sd_event_source_unref(t->dns_event_source); - t->dns_fd = safe_close(t->dns_fd); + t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source); + t->dns_udp_fd = safe_close(t->dns_udp_fd); dns_scope_next_dns_server(t->scope); } @@ -335,7 +348,8 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { * should hence not attempt to access the query or transaction * after calling this function. */ - if (t->scope->protocol == DNS_PROTOCOL_LLMNR) { + switch (t->scope->protocol) { + case DNS_PROTOCOL_LLMNR: assert(t->scope->link); /* For LLMNR we will not accept any packets from other @@ -354,6 +368,14 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { dns_transaction_tentative(t, p); return; } + + break; + + case DNS_PROTOCOL_DNS: + break; + + default: + assert_not_reached("Invalid DNS protocol."); } if (t->received != p) { @@ -390,7 +412,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { break; default: - assert_not_reached("Invalid DNS protocol."); + break; } if (DNS_PACKET_TC(p)) { @@ -478,16 +500,16 @@ static int dns_transaction_emit(DnsTransaction *t) { if (fd < 0) return fd; - r = sd_event_add_io(t->scope->manager->event, &t->dns_event_source, fd, EPOLLIN, on_dns_packet, t); + r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t); if (r < 0) return r; - t->dns_fd = fd; + t->dns_udp_fd = fd; fd = -1; t->server = dns_server_ref(server); } - r = dns_scope_emit(t->scope, t->dns_fd, t->sent); + r = dns_scope_emit(t->scope, t->dns_udp_fd, t->sent); if (r < 0) return r; diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h index 4db9352a04..acf6a6f651 100644 --- a/src/resolve/resolved-dns-transaction.h +++ b/src/resolve/resolved-dns-transaction.h @@ -62,10 +62,10 @@ struct DnsTransaction { sd_event_source *timeout_event_source; unsigned n_attempts; - int dns_fd; - sd_event_source *dns_event_source; + int dns_udp_fd; + sd_event_source *dns_udp_event_source; - /* the active server */ + /* The active server */ DnsServer *server; /* TCP connection logic, if we need it */ diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c index fc212f48f4..674bb6af28 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 71851265c6..495d17cdb1 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 fb2a06b517..13852192c4 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,13 +554,15 @@ 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); dns_resource_key_unref(m->llmnr_host_ipv6_key); - safe_close(m->hostname_fd); sd_event_source_unref(m->hostname_event_source); + safe_close(m->hostname_fd); free(m->llmnr_hostname); free(m->mdns_hostname); diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index 6f7972bbf3..fe7fe99505 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 0af5545f8e..32e61af925 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) { |