]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolve: Add GetMulticastHosts() D-Bus method
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Sat, 23 Jan 2021 17:33:24 +0000 (17:33 +0000)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Sat, 30 Jan 2021 13:51:41 +0000 (13:51 +0000)
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.

man/org.freedesktop.resolve1.xml
src/resolve/resolved-bus.c
src/resolve/resolved-dns-cache.c
src/resolve/resolved-dns-cache.h
src/resolve/resolved-dns-scope.c

index 860a14877d19bf89ba2e83de4f7f633164d187a9..9036f7d11fd4be5e3d76ecf56c9348c8bd63116b 100644 (file)
@@ -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"/>
index dd27c50b498289b82c593efcf49c8ecc2cbd21f4..49e23ae4503fb4e00f8b925e65b43399ca0e1156 100644 (file)
@@ -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",
index 75f1ccb6498ef9987d272aebd46bce1e8473c3d9..e199e8f00ce0f122d261a318681dabe9cd2fc71c 100644 (file)
@@ -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)
index 4ab213dc9cd5317d610f0924f41f187d274de42c..6de44cfd054dd6945adbc283f56ce40721afde68 100644 (file)
@@ -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);
index d77e81ae3986d8f92adae43cdd8465dfea1c1696..d27a19145fc216ddacc81614ede6b319815f719b 100644 (file)
@@ -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);
         }
 }