mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
Merge pull request #28012 from poettering/resolvectl-dump-cache
add "resolvectl show-cache" call and IPC backend for that
This commit is contained in:
@@ -212,6 +212,13 @@
|
||||
output.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>show-cache</command></term>
|
||||
|
||||
<listitem><para>Show current cache content, per scope. Use <option>--json=</option> to enable JSON
|
||||
output.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="systemctl.xml" xpointer="log-level" />
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
@@ -2586,34 +2586,6 @@ static int verb_log_level(int argc, char *argv[], void *userdata) {
|
||||
return verb_log_control_common(bus, "org.freedesktop.resolve1", argv[0], argc == 2 ? argv[1] : NULL);
|
||||
}
|
||||
|
||||
static int monitor_rkey_from_json(JsonVariant *v, DnsResourceKey **ret_key) {
|
||||
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
|
||||
uint16_t type = 0, class = 0;
|
||||
const char *name = NULL;
|
||||
int r;
|
||||
|
||||
JsonDispatch dispatch_table[] = {
|
||||
{ "class", JSON_VARIANT_INTEGER, json_dispatch_uint16, PTR_TO_SIZE(&class), JSON_MANDATORY },
|
||||
{ "type", JSON_VARIANT_INTEGER, json_dispatch_uint16, PTR_TO_SIZE(&type), JSON_MANDATORY },
|
||||
{ "name", JSON_VARIANT_STRING, json_dispatch_const_string, PTR_TO_SIZE(&name), JSON_MANDATORY },
|
||||
{}
|
||||
};
|
||||
|
||||
assert(v);
|
||||
assert(ret_key);
|
||||
|
||||
r = json_dispatch(v, dispatch_table, NULL, 0, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
key = dns_resource_key_new(class, type, name);
|
||||
if (!key)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret_key = TAKE_PTR(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_question(char prefix, const char *color, JsonVariant *question) {
|
||||
JsonVariant *q = NULL;
|
||||
int r;
|
||||
@@ -2624,7 +2596,7 @@ static int print_question(char prefix, const char *color, JsonVariant *question)
|
||||
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
|
||||
char buf[DNS_RESOURCE_KEY_STRING_MAX];
|
||||
|
||||
r = monitor_rkey_from_json(q, &key);
|
||||
r = dns_resource_key_from_json(q, &key);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Received monitor message with invalid question key, ignoring: %m");
|
||||
continue;
|
||||
@@ -2807,6 +2779,157 @@ static int verb_monitor(int argc, char *argv[], void *userdata) {
|
||||
return c;
|
||||
}
|
||||
|
||||
static int dump_cache_item(JsonVariant *item) {
|
||||
|
||||
struct item_info {
|
||||
JsonVariant *key;
|
||||
JsonVariant *rrs;
|
||||
const char *type;
|
||||
uint64_t until;
|
||||
} item_info = {};
|
||||
|
||||
static const JsonDispatch dispatch_table[] = {
|
||||
{ "key", JSON_VARIANT_OBJECT, json_dispatch_variant_noref, offsetof(struct item_info, key), JSON_MANDATORY },
|
||||
{ "rrs", JSON_VARIANT_ARRAY, json_dispatch_variant_noref, offsetof(struct item_info, rrs), 0 },
|
||||
{ "type", JSON_VARIANT_STRING, json_dispatch_const_string, offsetof(struct item_info, type), 0 },
|
||||
{ "until", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(struct item_info, until), 0 },
|
||||
{},
|
||||
};
|
||||
|
||||
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL;
|
||||
int r, c = 0;
|
||||
|
||||
r = json_dispatch(item, dispatch_table, NULL, JSON_LOG, &item_info);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dns_resource_key_from_json(item_info.key, &k);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to turn JSON data to resource key: %m");
|
||||
|
||||
if (item_info.type)
|
||||
printf("%s %s%s%s\n", DNS_RESOURCE_KEY_TO_STRING(k), ansi_highlight_red(), item_info.type, ansi_normal());
|
||||
else {
|
||||
JsonVariant *i;
|
||||
|
||||
JSON_VARIANT_ARRAY_FOREACH(i, item_info.rrs) {
|
||||
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
|
||||
_cleanup_free_ void *data = NULL;
|
||||
JsonVariant *raw;
|
||||
size_t size;
|
||||
|
||||
raw = json_variant_by_key(i, "raw");
|
||||
if (!raw)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "raw field missing from RR JSON data.");
|
||||
|
||||
r = json_variant_unbase64(raw, &data, &size);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Unable to decode raw RR JSON data: %m");
|
||||
|
||||
r = dns_resource_record_new_from_raw(&rr, data, size);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse DNS data: %m");
|
||||
|
||||
printf("%s\n", dns_resource_record_to_string(rr));
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static int dump_cache_scope(JsonVariant *scope) {
|
||||
|
||||
struct scope_info {
|
||||
const char *protocol;
|
||||
int family;
|
||||
int ifindex;
|
||||
const char *ifname;
|
||||
JsonVariant *cache;
|
||||
} scope_info = {
|
||||
.family = AF_UNSPEC,
|
||||
};
|
||||
JsonVariant *i;
|
||||
int r, c = 0;
|
||||
|
||||
static const JsonDispatch dispatch_table[] = {
|
||||
{ "protocol", JSON_VARIANT_STRING, json_dispatch_const_string, offsetof(struct scope_info, protocol), JSON_MANDATORY },
|
||||
{ "family", JSON_VARIANT_INTEGER, json_dispatch_int, offsetof(struct scope_info, family), 0 },
|
||||
{ "ifindex", JSON_VARIANT_INTEGER, json_dispatch_int, offsetof(struct scope_info, ifindex), 0 },
|
||||
{ "ifname", JSON_VARIANT_STRING, json_dispatch_const_string, offsetof(struct scope_info, ifname), 0 },
|
||||
{ "cache", JSON_VARIANT_ARRAY, json_dispatch_variant_noref, offsetof(struct scope_info, cache), JSON_MANDATORY },
|
||||
{},
|
||||
};
|
||||
|
||||
r = json_dispatch(scope, dispatch_table, NULL, JSON_LOG, &scope_info);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("%sScope protocol=%s", ansi_underline(), scope_info.protocol);
|
||||
|
||||
if (scope_info.family != AF_UNSPEC)
|
||||
printf(" family=%s", af_to_name(scope_info.family));
|
||||
|
||||
if (scope_info.ifindex > 0)
|
||||
printf(" ifindex=%i", scope_info.ifindex);
|
||||
if (scope_info.ifname)
|
||||
printf(" ifname=%s", scope_info.ifname);
|
||||
|
||||
printf("%s\n", ansi_normal());
|
||||
|
||||
JSON_VARIANT_ARRAY_FOREACH(i, scope_info.cache) {
|
||||
r = dump_cache_item(i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
c += r;
|
||||
}
|
||||
|
||||
if (c == 0)
|
||||
printf("%sNo entries.%s\n\n", ansi_grey(), ansi_normal());
|
||||
else
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verb_show_cache(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *d = NULL, *reply = NULL;
|
||||
_cleanup_(varlink_unrefp) Varlink *vl = NULL;
|
||||
int r;
|
||||
|
||||
r = varlink_connect_address(&vl, "/run/systemd/resolve/io.systemd.Resolve.Monitor");
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to connect to query monitoring service /run/systemd/resolve/io.systemd.Resolve.Monitor: %m");
|
||||
|
||||
r = varlink_call(vl, "io.systemd.Resolve.Monitor.DumpCache", NULL, &reply, NULL, 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to issue DumpCache() varlink call: %m");
|
||||
|
||||
d = json_variant_by_key(reply, "dump");
|
||||
if (!d)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"DumpCache() response is missing 'dump' key.");
|
||||
|
||||
if (!json_variant_is_array(d))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"DumpCache() response 'dump' field not an array");
|
||||
|
||||
if (FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) {
|
||||
JsonVariant *i;
|
||||
|
||||
JSON_VARIANT_ARRAY_FOREACH(i, d) {
|
||||
r = dump_cache_scope(i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return json_variant_dump(d, arg_json_format_flags, NULL, NULL);
|
||||
}
|
||||
|
||||
static void help_protocol_types(void) {
|
||||
if (arg_legend)
|
||||
puts("Known protocol types:");
|
||||
@@ -2913,6 +3036,7 @@ static int native_help(void) {
|
||||
" flush-caches Flush all local DNS caches\n"
|
||||
" reset-server-features Forget learnt DNS server feature levels\n"
|
||||
" monitor Monitor DNS queries\n"
|
||||
" show-cache Show cache contents\n"
|
||||
" dns [LINK [SERVER...]] Get/set per-interface DNS server address\n"
|
||||
" domain [LINK [DOMAIN...]] Get/set per-interface search domain\n"
|
||||
" default-route [LINK [BOOL]] Get/set per-interface default route flag\n"
|
||||
@@ -3559,6 +3683,7 @@ static int native_main(int argc, char *argv[], sd_bus *bus) {
|
||||
{ "revert", VERB_ANY, 2, 0, verb_revert_link },
|
||||
{ "log-level", VERB_ANY, 2, 0, verb_log_level },
|
||||
{ "monitor", VERB_ANY, 1, 0, verb_monitor },
|
||||
{ "show-cache", VERB_ANY, 1, 0, verb_show_cache },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -1351,6 +1351,86 @@ void dns_cache_dump(DnsCache *cache, FILE *f) {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -50,6 +50,8 @@ int dns_cache_lookup(
|
||||
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);
|
||||
|
||||
@@ -1853,6 +1853,34 @@ int dns_resource_key_to_json(DnsResourceKey *key, JsonVariant **ret) {
|
||||
JSON_BUILD_PAIR("name", JSON_BUILD_STRING(dns_resource_key_name(key)))));
|
||||
}
|
||||
|
||||
int dns_resource_key_from_json(JsonVariant *v, DnsResourceKey **ret) {
|
||||
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
|
||||
uint16_t type = 0, class = 0;
|
||||
const char *name = NULL;
|
||||
int r;
|
||||
|
||||
JsonDispatch dispatch_table[] = {
|
||||
{ "class", JSON_VARIANT_INTEGER, json_dispatch_uint16, PTR_TO_SIZE(&class), JSON_MANDATORY },
|
||||
{ "type", JSON_VARIANT_INTEGER, json_dispatch_uint16, PTR_TO_SIZE(&type), JSON_MANDATORY },
|
||||
{ "name", JSON_VARIANT_STRING, json_dispatch_const_string, PTR_TO_SIZE(&name), JSON_MANDATORY },
|
||||
{}
|
||||
};
|
||||
|
||||
assert(v);
|
||||
assert(ret);
|
||||
|
||||
r = json_dispatch(v, dispatch_table, NULL, 0, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
key = dns_resource_key_new(class, type, name);
|
||||
if (!key)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = TAKE_PTR(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int type_bitmap_to_json(Bitmap *b, JsonVariant **ret) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *l = NULL;
|
||||
unsigned t;
|
||||
|
||||
@@ -317,6 +317,9 @@ int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *
|
||||
char* dns_resource_key_to_string(const DnsResourceKey *key, char *buf, size_t buf_size);
|
||||
ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out);
|
||||
|
||||
#define DNS_RESOURCE_KEY_TO_STRING(key) \
|
||||
dns_resource_key_to_string(key, (char[DNS_RESOURCE_KEY_STRING_MAX]) {}, DNS_RESOURCE_KEY_STRING_MAX)
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceKey*, dns_resource_key_unref);
|
||||
|
||||
static inline bool dns_key_is_shared(const DnsResourceKey *key) {
|
||||
@@ -368,6 +371,7 @@ int dns_txt_item_new_empty(DnsTxtItem **ret);
|
||||
int dns_resource_record_new_from_raw(DnsResourceRecord **ret, const void *data, size_t size);
|
||||
|
||||
int dns_resource_key_to_json(DnsResourceKey *key, JsonVariant **ret);
|
||||
int dns_resource_key_from_json(JsonVariant *v, DnsResourceKey **ret);
|
||||
int dns_resource_record_to_json(DnsResourceRecord *rr, JsonVariant **ret);
|
||||
|
||||
void dns_resource_record_hash_func(const DnsResourceRecord *i, struct siphash *state);
|
||||
|
||||
@@ -1643,3 +1643,23 @@ bool dns_scope_is_default_route(DnsScope *scope) {
|
||||
* 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)));
|
||||
}
|
||||
|
||||
@@ -110,3 +110,5 @@ int dns_scope_add_dnssd_services(DnsScope *scope);
|
||||
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);
|
||||
|
||||
@@ -563,6 +563,40 @@ static int vl_method_subscribe_dns_resolves(Varlink *link, JsonVariant *paramete
|
||||
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;
|
||||
@@ -578,10 +612,10 @@ static int varlink_monitor_server_init(Manager *m) {
|
||||
|
||||
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");
|
||||
|
||||
|
||||
@@ -4642,10 +4642,20 @@ int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFl
|
||||
JsonVariant **p = ASSERT_PTR(userdata);
|
||||
assert(variant);
|
||||
|
||||
/* Takes a reference */
|
||||
JSON_VARIANT_REPLACE(*p, json_variant_ref(variant));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int json_dispatch_variant_noref(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
|
||||
JsonVariant **p = ASSERT_PTR(userdata);
|
||||
assert(variant);
|
||||
|
||||
/* Doesn't take a reference */
|
||||
*p = variant;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int json_dispatch_uid_gid(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
|
||||
uid_t *uid = userdata;
|
||||
uint64_t k;
|
||||
|
||||
@@ -387,6 +387,7 @@ int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags
|
||||
int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
|
||||
int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
|
||||
int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
|
||||
int json_dispatch_variant_noref(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
|
||||
int json_dispatch_int64(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
|
||||
int json_dispatch_uint64(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
|
||||
int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
|
||||
|
||||
Reference in New Issue
Block a user