}
}
+int dns_cache_dump_to_json(DnsCache *cache, JsonVariant **ret) {
+ _cleanup_(json_variant_unrefp) JsonVariant *c = NULL;
+ DnsCacheItem *i;
+ int r;
+
+ assert(cache);
+ assert(ret);
+
+ HASHMAP_FOREACH(i, cache->by_key) {
+ _cleanup_(json_variant_unrefp) JsonVariant *d = NULL, *k = NULL;
+
+ r = dns_resource_key_to_json(i->key, &k);
+ if (r < 0)
+ return r;
+
+ if (i->rr) {
+ _cleanup_(json_variant_unrefp) JsonVariant *l = NULL;
+
+ LIST_FOREACH(by_key, j, i) {
+ _cleanup_(json_variant_unrefp) JsonVariant *rj = NULL, *item = NULL;
+
+ assert(j->rr);
+
+ r = dns_resource_record_to_json(j->rr, &rj);
+ if (r < 0)
+ return r;
+
+ r = dns_resource_record_to_wire_format(j->rr, /* canonical= */ false); /* don't use DNSSEC canonical format, since it removes casing, but we want that for DNS_SD compat */
+ if (r < 0)
+ return r;
+
+ r = json_build(&item, JSON_BUILD_OBJECT(
+ JSON_BUILD_PAIR_VARIANT("rr", rj),
+ JSON_BUILD_PAIR_BASE64("raw", j->rr->wire_format, j->rr->wire_format_size)));
+ if (r < 0)
+ return r;
+
+ r = json_variant_append_array(&l, item);
+ if (r < 0)
+ return r;
+ }
+
+ if (!l) {
+ r = json_variant_new_array(&l, NULL, 0);
+ if (r < 0)
+ return r;
+ }
+
+ r = json_build(&d,
+ JSON_BUILD_OBJECT(
+ JSON_BUILD_PAIR_VARIANT("key", k),
+ JSON_BUILD_PAIR_VARIANT("rrs", l),
+ JSON_BUILD_PAIR_UNSIGNED("until", i->until)));
+ } else if (i->type == DNS_CACHE_NODATA) {
+ r = json_build(&d,
+ JSON_BUILD_OBJECT(
+ JSON_BUILD_PAIR_VARIANT("key", k),
+ JSON_BUILD_PAIR_EMPTY_ARRAY("rrs"),
+ JSON_BUILD_PAIR_UNSIGNED("until", i->until)));
+ } else
+ r = json_build(&d,
+ JSON_BUILD_OBJECT(
+ JSON_BUILD_PAIR_VARIANT("key", k),
+ JSON_BUILD_PAIR_STRING("type", dns_cache_item_type_to_string(i)),
+ JSON_BUILD_PAIR_UNSIGNED("until", i->until)));
+ if (r < 0)
+ return r;
+
+ r = json_variant_append_array(&c, d);
+ if (r < 0)
+ return r;
+ }
+
+ if (!c)
+ return json_variant_new_array(ret, NULL, 0);
+
+ *ret = TAKE_PTR(c);
+ return 0;
+}
+
bool dns_cache_is_empty(DnsCache *cache) {
if (!cache)
return true;
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);
+int dns_cache_dump_to_json(DnsCache *cache, JsonVariant **ret);
+
bool dns_cache_is_empty(DnsCache *cache);
unsigned dns_cache_size(DnsCache *cache);
* volunteer as default route. */
return !dns_scope_has_route_only_domains(scope);
}
+
+int dns_scope_dump_cache_to_json(DnsScope *scope, JsonVariant **ret) {
+ _cleanup_(json_variant_unrefp) JsonVariant *cache = NULL;
+ int r;
+
+ assert(scope);
+ assert(ret);
+
+ r = dns_cache_dump_to_json(&scope->cache, &cache);
+ if (r < 0)
+ return r;
+
+ return json_build(ret,
+ JSON_BUILD_OBJECT(
+ JSON_BUILD_PAIR_STRING("protocol", dns_protocol_to_string(scope->protocol)),
+ JSON_BUILD_PAIR_CONDITION(scope->family != AF_UNSPEC, "family", JSON_BUILD_INTEGER(scope->family)),
+ JSON_BUILD_PAIR_CONDITION(scope->link, "ifindex", JSON_BUILD_INTEGER(scope->link ? scope->link->ifindex : 0)),
+ JSON_BUILD_PAIR_CONDITION(scope->link, "ifname", JSON_BUILD_STRING(scope->link ? scope->link->ifname : NULL)),
+ JSON_BUILD_PAIR_VARIANT("cache", cache)));
+}
int dns_scope_remove_dnssd_services(DnsScope *scope);
bool dns_scope_is_default_route(DnsScope *scope);
+
+int dns_scope_dump_cache_to_json(DnsScope *scope, JsonVariant **ret);
return 1;
}
+static int vl_method_dump_cache(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+ _cleanup_(json_variant_unrefp) JsonVariant *list = NULL;
+ Manager *m;
+ int r;
+
+ assert(link);
+
+ if (json_variant_elements(parameters) > 0)
+ return varlink_error_invalid_parameter(link, parameters);
+
+ m = ASSERT_PTR(varlink_server_get_userdata(varlink_get_server(link)));
+
+ LIST_FOREACH(scopes, s, m->dns_scopes) {
+ _cleanup_(json_variant_unrefp) JsonVariant *j = NULL;
+
+ r = dns_scope_dump_cache_to_json(s, &j);
+ if (r < 0)
+ return r;
+
+ r = json_variant_append_array(&list, j);
+ if (r < 0)
+ return r;
+ }
+
+ if (!list) {
+ r = json_variant_new_array(&list, NULL, 0);
+ if (r < 0)
+ return r;
+ }
+
+ return varlink_replyb(link, JSON_BUILD_OBJECT(
+ JSON_BUILD_PAIR("dump", JSON_BUILD_VARIANT(list))));
+}
+
static int varlink_monitor_server_init(Manager *m) {
_cleanup_(varlink_server_unrefp) VarlinkServer *server = NULL;
int r;
varlink_server_set_userdata(server, m);
- r = varlink_server_bind_method(
+ r = varlink_server_bind_method_many(
server,
- "io.systemd.Resolve.Monitor.SubscribeQueryResults",
- vl_method_subscribe_dns_resolves);
+ "io.systemd.Resolve.Monitor.SubscribeQueryResults", vl_method_subscribe_dns_resolves,
+ "io.systemd.Resolve.Monitor.DumpCache", vl_method_dump_cache);
if (r < 0)
return log_error_errno(r, "Failed to register varlink methods: %m");