diff options
author | Daan De Meyer <daan.j.demeyer@gmail.com> | 2021-01-23 17:33:24 +0000 |
---|---|---|
committer | Daan De Meyer <daan.j.demeyer@gmail.com> | 2021-01-30 13:51:41 +0000 |
commit | 69988fee43302545113c6fd9241b1e65eb2fc491 (patch) | |
tree | e7f15852eae4ef6203bc86729fa654b345a29f43 | |
parent | d8067d40412935e5a317181fb5ea8365819271a1 (diff) | |
download | systemd-69988fee43302545113c6fd9241b1e65eb2fc491.tar.gz |
resolve: Add GetMulticastHosts() D-Bus method
GetMulticastHosts() returns an array of hostnames/addresses discovered via
LLMNR or Multicast DNS. It does not trigger any discovery on its own.
Instead, it simply returns whatever is already in resolved's cache.
-rw-r--r-- | man/org.freedesktop.resolve1.xml | 5 | ||||
-rw-r--r-- | src/resolve/resolved-bus.c | 99 | ||||
-rw-r--r-- | src/resolve/resolved-dns-cache.c | 50 | ||||
-rw-r--r-- | src/resolve/resolved-dns-cache.h | 3 | ||||
-rw-r--r-- | src/resolve/resolved-dns-scope.c | 2 |
5 files changed, 146 insertions, 13 deletions
diff --git a/man/org.freedesktop.resolve1.xml b/man/org.freedesktop.resolve1.xml index 860a14877d..9036f7d11f 100644 --- a/man/org.freedesktop.resolve1.xml +++ b/man/org.freedesktop.resolve1.xml @@ -115,6 +115,7 @@ node /org/freedesktop/resolve1 { ResetStatistics(); FlushCaches(); ResetServerFeatures(); + GetMulticastHosts(out a(stiiay) UNNAMED); properties: readonly s LLMNRHostname = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") @@ -164,6 +165,8 @@ node /org/freedesktop/resolve1 { <!--method ResetServerFeatures is not documented!--> + <!--method GetMulticastHosts is not documented!--> + <!--property DNSSECNegativeTrustAnchors is not documented!--> <!--Autogenerated cross-references for systemd.directives, do not edit--> @@ -212,6 +215,8 @@ node /org/freedesktop/resolve1 { <variablelist class="dbus-method" generated="True" extra-ref="ResetServerFeatures()"/> + <variablelist class="dbus-method" generated="True" extra-ref="GetMulticastHosts()"/> + <variablelist class="dbus-property" generated="True" extra-ref="LLMNRHostname"/> <variablelist class="dbus-property" generated="True" extra-ref="LLMNR"/> diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index dd27c50b49..49e23ae450 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -132,15 +132,17 @@ static int reply_query_state(DnsQuery *q) { } } -static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) { +static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex, bool is_container) { int r; assert(reply); assert(rr); - r = sd_bus_message_open_container(reply, 'r', "iiay"); - if (r < 0) - return r; + if (is_container) { + r = sd_bus_message_open_container(reply, 'r', "iiay"); + if (r < 0) + return r; + } r = sd_bus_message_append(reply, "i", ifindex); if (r < 0) @@ -165,9 +167,11 @@ static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifin if (r < 0) return r; - r = sd_bus_message_close_container(reply); - if (r < 0) - return r; + if (is_container) { + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + } return 0; } @@ -216,7 +220,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) { if (r == 0) continue; - r = append_address(reply, rr, ifindex); + r = append_address(reply, rr, ifindex, true); if (r < 0) goto finish; @@ -851,7 +855,7 @@ static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) if (r == 0) continue; - r = append_address(reply, zz, ifindex); + r = append_address(reply, zz, ifindex, true); if (r < 0) return r; } @@ -2000,6 +2004,76 @@ static int bus_method_unregister_service(sd_bus_message *message, void *userdata return call_dnssd_method(m, message, bus_dnssd_method_unregister, error); } +static int bus_method_get_multicast_hosts(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + DnsScope *s; + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(stiiay)"); + if (r < 0) + return r; + + LIST_FOREACH(scopes, s, m->dns_scopes) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + DnsResourceRecord *rr; + DnsAnswerFlags flags; + int ifindex; + + if (s->protocol == DNS_PROTOCOL_DNS) + continue; + + r = dns_cache_dump_to_answer(&s->cache, &answer); + if (r < 0) + return r; + if (r == 0) + continue; + + DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer) { + _cleanup_free_ char *normalized = NULL; + bool authenticated = FLAGS_SET(flags, DNS_ANSWER_AUTHENTICATED); + + r = dns_name_normalize(dns_resource_key_name(rr->key), 0, &normalized); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'r', "stiiay"); + if (r < 0) + return r; + + r = sd_bus_message_append( + reply, + "st", + normalized, + SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, authenticated)); + if (r < 0) + return r; + + r = append_address(reply, rr, ifindex, false); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + } + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_reply(message, reply); +} + +/* clang-format off */ static const sd_bus_vtable resolve_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), @@ -2138,9 +2212,14 @@ static const sd_bus_vtable resolve_vtable[] = { SD_BUS_NO_RESULT, bus_method_reset_server_features, SD_BUS_VTABLE_UNPRIVILEGED), - + SD_BUS_METHOD_WITH_ARGS("GetMulticastHosts", + SD_BUS_NO_ARGS, + SD_BUS_RESULT("a(stiiay)", addresses), + bus_method_get_multicast_hosts, + SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END, }; +/* clang-format on */ const BusObjectImplementation manager_object = { "/org/freedesktop/resolve1", diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index 75f1ccb649..e199e8f00c 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -1066,7 +1066,55 @@ int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) { return 0; } -void dns_cache_dump(DnsCache *cache, FILE *f) { +int dns_cache_dump_to_answer(DnsCache *cache, DnsAnswer **ret) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + DnsCacheItem *i; + size_t n = 0; + int r; + + assert(cache); + assert(ret); + + HASHMAP_FOREACH(i, cache->by_key) { + DnsCacheItem *j; + + LIST_FOREACH(by_key, j, i) { + if (!j->rr) + continue; + + n++; + } + } + + if (n == 0) { + *ret = NULL; + return 0; + } + + answer = dns_answer_new(n); + if (!answer) + return -ENOMEM; + + HASHMAP_FOREACH(i, cache->by_key) { + DnsCacheItem *j; + + LIST_FOREACH(by_key, j, i) { + if (!j->rr) + continue; + + r = dns_answer_add( + answer, j->rr, j->ifindex, j->authenticated ? DNS_ANSWER_AUTHENTICATED : 0); + if (r < 0) + return r; + } + } + + *ret = TAKE_PTR(answer); + + return n; +} + +void dns_cache_dump_to_file(DnsCache *cache, FILE *f) { DnsCacheItem *i; if (!cache) diff --git a/src/resolve/resolved-dns-cache.h b/src/resolve/resolved-dns-cache.h index 4ab213dc9c..6de44cfd05 100644 --- a/src/resolve/resolved-dns-cache.h +++ b/src/resolve/resolved-dns-cache.h @@ -27,7 +27,8 @@ int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, bool clamp_ttl, int *rcod 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); +void dns_cache_dump_to_file(DnsCache *cache, FILE *f); +int dns_cache_dump_to_answer(DnsCache *cache, DnsAnswer **answer); bool dns_cache_is_empty(DnsCache *cache); unsigned dns_cache_size(DnsCache *cache); diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index d77e81ae39..d27a19145f 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -1159,7 +1159,7 @@ void dns_scope_dump(DnsScope *s, FILE *f) { if (!dns_cache_is_empty(&s->cache)) { fputs("CACHE:\n", f); - dns_cache_dump(&s->cache, f); + dns_cache_dump_to_file(&s->cache, f); } } |