945 lines
39 KiB
Diff
945 lines
39 KiB
Diff
|
From a92665de198ca2ace3f5835f6c819b6e669cbb77 Mon Sep 17 00:00:00 2001
|
||
|
From: Lennart Poettering <lennart@poettering.net>
|
||
|
Date: Wed, 1 Nov 2023 18:36:12 +0100
|
||
|
Subject: [PATCH] varlink,json: introduce new varlink_dispatch() helper
|
||
|
|
||
|
varlink_dispatch() is a simple wrapper around json_dispatch() that
|
||
|
returns clean, standards-compliant InvalidParameter error back to
|
||
|
clients, if the specified JSON cannot be parsed properly.
|
||
|
|
||
|
For this json_dispatch() is extended to return the offending field's
|
||
|
name. Because it already has quite a few parameters, I then renamed
|
||
|
json_dispatch() to json_dispatch_full() and made json_dispatch() a
|
||
|
wrapper around it that passes the new argument as NULL. While doing so I
|
||
|
figured we should also get rid of the bad= argument in the short
|
||
|
wrapper, since it's only used in the OCI code.
|
||
|
|
||
|
To simplify the OCI code this adds a second wrapper oci_dispatch()
|
||
|
around json_dispatch_full(), that fills in bad= the way we want.
|
||
|
|
||
|
Net result: instead of one json_dispatch() call there are now:
|
||
|
|
||
|
1. json_dispatch_full() for the fully feature mother of all dispathers.
|
||
|
2. json_dispatch() for the simpler version that you want to use most of
|
||
|
the time.
|
||
|
3. varlink_dispatch() that generates nice Varlink errors
|
||
|
4. oci_dispatch() that does the OCI specific error handling
|
||
|
|
||
|
And that's all there is.
|
||
|
|
||
|
(cherry picked from commit f1b622a00ce614654fcdff309a2394cfae3b3a88)
|
||
|
|
||
|
Related: RHEL-55266
|
||
|
---
|
||
|
src/core/core-varlink.c | 12 ++++----
|
||
|
src/fuzz/fuzz-bootspec.c | 2 +-
|
||
|
src/home/homed-varlink.c | 12 ++++----
|
||
|
src/machine/machined-varlink.c | 12 ++++----
|
||
|
src/nspawn/nspawn-oci.c | 54 ++++++++++++++++++----------------
|
||
|
src/nss-resolve/nss-resolve.c | 18 ++++++------
|
||
|
src/oom/oomd-manager.c | 2 +-
|
||
|
src/resolve/resolvectl.c | 4 +--
|
||
|
src/resolve/resolved-varlink.c | 8 ++---
|
||
|
src/shared/group-record.c | 10 +++----
|
||
|
src/shared/json.c | 41 ++++++++++++++++++++++++--
|
||
|
src/shared/json.h | 3 +-
|
||
|
src/shared/user-record.c | 18 ++++++------
|
||
|
src/shared/userdb.c | 6 ++--
|
||
|
src/shared/varlink.c | 20 +++++++++++++
|
||
|
src/shared/varlink.h | 3 ++
|
||
|
src/userdb/userwork.c | 12 ++++----
|
||
|
17 files changed, 150 insertions(+), 87 deletions(-)
|
||
|
|
||
|
diff --git a/src/core/core-varlink.c b/src/core/core-varlink.c
|
||
|
index 843271593d..776a3eebab 100644
|
||
|
--- a/src/core/core-varlink.c
|
||
|
+++ b/src/core/core-varlink.c
|
||
|
@@ -281,8 +281,8 @@ static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, Var
|
||
|
|
||
|
assert(parameters);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
if (!streq_ptr(p.service, "io.systemd.DynamicUser"))
|
||
|
@@ -388,8 +388,8 @@ static int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, Va
|
||
|
|
||
|
assert(parameters);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
if (!streq_ptr(p.service, "io.systemd.DynamicUser"))
|
||
|
@@ -464,8 +464,8 @@ static int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, Var
|
||
|
|
||
|
assert(parameters);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
if (!streq_ptr(p.service, "io.systemd.DynamicUser"))
|
||
|
diff --git a/src/fuzz/fuzz-bootspec.c b/src/fuzz/fuzz-bootspec.c
|
||
|
index c08f76c14a..c6d24e7b55 100644
|
||
|
--- a/src/fuzz/fuzz-bootspec.c
|
||
|
+++ b/src/fuzz/fuzz-bootspec.c
|
||
|
@@ -98,7 +98,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||
|
if (r < 0)
|
||
|
return 0;
|
||
|
|
||
|
- r = json_dispatch(v, data_dispatch, NULL, 0, &config);
|
||
|
+ r = json_dispatch(v, data_dispatch, 0, &config);
|
||
|
if (r < 0)
|
||
|
return 0;
|
||
|
|
||
|
diff --git a/src/home/homed-varlink.c b/src/home/homed-varlink.c
|
||
|
index 540a612554..1cef25f563 100644
|
||
|
--- a/src/home/homed-varlink.c
|
||
|
+++ b/src/home/homed-varlink.c
|
||
|
@@ -90,8 +90,8 @@ int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, VarlinkMet
|
||
|
|
||
|
assert(parameters);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
if (!streq_ptr(p.service, m->userdb_service))
|
||
|
@@ -204,8 +204,8 @@ int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, VarlinkMe
|
||
|
|
||
|
assert(parameters);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
if (!streq_ptr(p.service, m->userdb_service))
|
||
|
@@ -270,8 +270,8 @@ int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, VarlinkMet
|
||
|
|
||
|
assert(parameters);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
if (!streq_ptr(p.service, m->userdb_service))
|
||
|
diff --git a/src/machine/machined-varlink.c b/src/machine/machined-varlink.c
|
||
|
index ec625ad7b4..8b230b0078 100644
|
||
|
--- a/src/machine/machined-varlink.c
|
||
|
+++ b/src/machine/machined-varlink.c
|
||
|
@@ -156,8 +156,8 @@ static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, Var
|
||
|
|
||
|
assert(parameters);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
if (!streq_ptr(p.service, "io.systemd.Machine"))
|
||
|
@@ -321,8 +321,8 @@ static int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, Va
|
||
|
|
||
|
assert(parameters);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
if (!streq_ptr(p.service, "io.systemd.Machine"))
|
||
|
@@ -366,8 +366,8 @@ static int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, Var
|
||
|
|
||
|
assert(parameters);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
if (!streq_ptr(p.service, "io.systemd.Machine"))
|
||
|
diff --git a/src/nspawn/nspawn-oci.c b/src/nspawn/nspawn-oci.c
|
||
|
index 117a31e6b2..7fbc4dd6f0 100644
|
||
|
--- a/src/nspawn/nspawn-oci.c
|
||
|
+++ b/src/nspawn/nspawn-oci.c
|
||
|
@@ -84,6 +84,10 @@ static int oci_unexpected(const char *name, JsonVariant *v, JsonDispatchFlags fl
|
||
|
"Unexpected OCI element '%s' of type '%s'.", name, json_variant_type_to_string(json_variant_type(v)));
|
||
|
}
|
||
|
|
||
|
+static int oci_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchFlags flags, void *userdata) {
|
||
|
+ return json_dispatch_full(v, table, oci_unexpected, flags, userdata, /* reterr_bad_field= */ NULL);
|
||
|
+}
|
||
|
+
|
||
|
static int oci_unsupported(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
|
||
|
return json_log(v, flags, SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||
|
"Unsupported OCI element '%s' of type '%s'.", name, json_variant_type_to_string(json_variant_type(v)));
|
||
|
@@ -122,7 +126,7 @@ static int oci_console_size(const char *name, JsonVariant *v, JsonDispatchFlags
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
- return json_dispatch(v, table, oci_unexpected, flags, userdata);
|
||
|
+ return oci_dispatch(v, table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
static int oci_absolute_path(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
|
||
|
@@ -251,7 +255,7 @@ static int oci_rlimits(const char *name, JsonVariant *v, JsonDispatchFlags flags
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
- r = json_dispatch(e, table, oci_unexpected, flags, &data);
|
||
|
+ r = oci_dispatch(e, table, flags, &data);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
@@ -319,7 +323,7 @@ static int oci_capabilities(const char *name, JsonVariant *v, JsonDispatchFlags
|
||
|
Settings *s = ASSERT_PTR(userdata);
|
||
|
int r;
|
||
|
|
||
|
- r = json_dispatch(v, table, oci_unexpected, flags, &s->full_capabilities);
|
||
|
+ r = oci_dispatch(v, table, flags, &s->full_capabilities);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
@@ -402,7 +406,7 @@ static int oci_user(const char *name, JsonVariant *v, JsonDispatchFlags flags, v
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
- return json_dispatch(v, table, oci_unexpected, flags, userdata);
|
||
|
+ return oci_dispatch(v, table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
static int oci_process(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
|
||
|
@@ -423,7 +427,7 @@ static int oci_process(const char *name, JsonVariant *v, JsonDispatchFlags flags
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
- return json_dispatch(v, table, oci_unexpected, flags, userdata);
|
||
|
+ return oci_dispatch(v, table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
static int oci_root(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
|
||
|
@@ -436,7 +440,7 @@ static int oci_root(const char *name, JsonVariant *v, JsonDispatchFlags flags, v
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
- r = json_dispatch(v, table, oci_unexpected, flags, s);
|
||
|
+ r = oci_dispatch(v, table, flags, s);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
@@ -536,7 +540,7 @@ static int oci_mounts(const char *name, JsonVariant *v, JsonDispatchFlags flags,
|
||
|
CustomMount *m;
|
||
|
_cleanup_(cleanup_oci_mount_data) oci_mount_data data = {};
|
||
|
|
||
|
- r = json_dispatch(e, table, oci_unexpected, flags, &data);
|
||
|
+ r = oci_dispatch(e, table, flags, &data);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
@@ -631,7 +635,7 @@ static int oci_namespaces(const char *name, JsonVariant *v, JsonDispatchFlags fl
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
- r = json_dispatch(e, table, oci_unexpected, flags, &data);
|
||
|
+ r = oci_dispatch(e, table, flags, &data);
|
||
|
if (r < 0) {
|
||
|
free(data.path);
|
||
|
return r;
|
||
|
@@ -729,7 +733,7 @@ static int oci_uid_gid_mappings(const char *name, JsonVariant *v, JsonDispatchFl
|
||
|
|
||
|
assert_se(e = json_variant_by_index(v, 0));
|
||
|
|
||
|
- r = json_dispatch(e, table, oci_unexpected, flags, &data);
|
||
|
+ r = oci_dispatch(e, table, flags, &data);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
@@ -858,7 +862,7 @@ static int oci_devices(const char *name, JsonVariant *v, JsonDispatchFlags flags
|
||
|
.mode = 0644,
|
||
|
};
|
||
|
|
||
|
- r = json_dispatch(e, table, oci_unexpected, flags, node);
|
||
|
+ r = oci_dispatch(e, table, flags, node);
|
||
|
if (r < 0)
|
||
|
goto fail_element;
|
||
|
|
||
|
@@ -1008,7 +1012,7 @@ static int oci_cgroup_devices(const char *name, JsonVariant *v, JsonDispatchFlag
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
- r = json_dispatch(e, table, oci_unexpected, flags, &data);
|
||
|
+ r = oci_dispatch(e, table, flags, &data);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
@@ -1190,7 +1194,7 @@ static int oci_cgroup_memory(const char *name, JsonVariant *v, JsonDispatchFlags
|
||
|
Settings *s = userdata;
|
||
|
int r;
|
||
|
|
||
|
- r = json_dispatch(v, table, oci_unexpected, flags, &data);
|
||
|
+ r = oci_dispatch(v, table, flags, &data);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
@@ -1306,7 +1310,7 @@ static int oci_cgroup_cpu(const char *name, JsonVariant *v, JsonDispatchFlags fl
|
||
|
Settings *s = userdata;
|
||
|
int r;
|
||
|
|
||
|
- r = json_dispatch(v, table, oci_unexpected, flags, &data);
|
||
|
+ r = oci_dispatch(v, table, flags, &data);
|
||
|
if (r < 0) {
|
||
|
cpu_set_reset(&data.cpu_set);
|
||
|
return r;
|
||
|
@@ -1388,7 +1392,7 @@ static int oci_cgroup_block_io_weight_device(const char *name, JsonVariant *v, J
|
||
|
|
||
|
_cleanup_free_ char *path = NULL;
|
||
|
|
||
|
- r = json_dispatch(e, table, oci_unexpected, flags, &data);
|
||
|
+ r = oci_dispatch(e, table, flags, &data);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
@@ -1445,7 +1449,7 @@ static int oci_cgroup_block_io_throttle(const char *name, JsonVariant *v, JsonDi
|
||
|
|
||
|
_cleanup_free_ char *path = NULL;
|
||
|
|
||
|
- r = json_dispatch(e, table, oci_unexpected, flags, &data);
|
||
|
+ r = oci_dispatch(e, table, flags, &data);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
@@ -1482,7 +1486,7 @@ static int oci_cgroup_block_io(const char *name, JsonVariant *v, JsonDispatchFla
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
- return json_dispatch(v, table, oci_unexpected, flags, userdata);
|
||
|
+ return oci_dispatch(v, table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
static int oci_cgroup_pids(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
|
||
|
@@ -1497,7 +1501,7 @@ static int oci_cgroup_pids(const char *name, JsonVariant *v, JsonDispatchFlags f
|
||
|
uint64_t m;
|
||
|
int r;
|
||
|
|
||
|
- r = json_dispatch(v, table, oci_unexpected, flags, &k);
|
||
|
+ r = oci_dispatch(v, table, flags, &k);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
@@ -1540,7 +1544,7 @@ static int oci_resources(const char *name, JsonVariant *v, JsonDispatchFlags fla
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
- return json_dispatch(v, table, oci_unexpected, flags, userdata);
|
||
|
+ return oci_dispatch(v, table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
static bool sysctl_key_valid(const char *s) {
|
||
|
@@ -1801,7 +1805,7 @@ static int oci_seccomp_args(const char *name, JsonVariant *v, JsonDispatchFlags
|
||
|
.op = 0,
|
||
|
};
|
||
|
|
||
|
- r = json_dispatch(e, table, oci_unexpected, flags, p);
|
||
|
+ r = oci_dispatch(e, table, flags, p);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
@@ -1834,7 +1838,7 @@ static int oci_seccomp_syscalls(const char *name, JsonVariant *v, JsonDispatchFl
|
||
|
.action = UINT32_MAX,
|
||
|
};
|
||
|
|
||
|
- r = json_dispatch(e, table, oci_unexpected, flags, &rule);
|
||
|
+ r = oci_dispatch(e, table, flags, &rule);
|
||
|
if (r < 0)
|
||
|
goto fail_rule;
|
||
|
|
||
|
@@ -1901,7 +1905,7 @@ static int oci_seccomp(const char *name, JsonVariant *v, JsonDispatchFlags flags
|
||
|
if (!sc)
|
||
|
return json_log(v, flags, SYNTHETIC_ERRNO(ENOMEM), "Couldn't allocate seccomp object.");
|
||
|
|
||
|
- r = json_dispatch(v, table, oci_unexpected, flags, sc);
|
||
|
+ r = oci_dispatch(v, table, flags, sc);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
@@ -2026,7 +2030,7 @@ static int oci_linux(const char *name, JsonVariant *v, JsonDispatchFlags flags,
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
- return json_dispatch(v, table, oci_unexpected, flags, userdata);
|
||
|
+ return oci_dispatch(v, table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
static int oci_hook_timeout(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
|
||
|
@@ -2083,7 +2087,7 @@ static int oci_hooks_array(const char *name, JsonVariant *v, JsonDispatchFlags f
|
||
|
.timeout = USEC_INFINITY,
|
||
|
};
|
||
|
|
||
|
- r = json_dispatch(e, table, oci_unexpected, flags, new_item);
|
||
|
+ r = oci_dispatch(e, table, flags, new_item);
|
||
|
if (r < 0) {
|
||
|
free(new_item->path);
|
||
|
strv_free(new_item->args);
|
||
|
@@ -2106,7 +2110,7 @@ static int oci_hooks(const char *name, JsonVariant *v, JsonDispatchFlags flags,
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
- return json_dispatch(v, table, oci_unexpected, flags, userdata);
|
||
|
+ return oci_dispatch(v, table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
static int oci_annotations(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
|
||
|
@@ -2191,7 +2195,7 @@ int oci_load(FILE *f, const char *bundle, Settings **ret) {
|
||
|
if (!s->bundle)
|
||
|
return log_oom();
|
||
|
|
||
|
- r = json_dispatch(oci, table, oci_unexpected, 0, s);
|
||
|
+ r = oci_dispatch(oci, table, 0, s);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c
|
||
|
index 0226752275..350bbffb04 100644
|
||
|
--- a/src/nss-resolve/nss-resolve.c
|
||
|
+++ b/src/nss-resolve/nss-resolve.c
|
||
|
@@ -272,7 +272,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
|
||
|
goto not_found;
|
||
|
}
|
||
|
|
||
|
- r = json_dispatch(rparams, resolve_hostname_reply_dispatch_table, NULL, json_dispatch_flags, &p);
|
||
|
+ r = json_dispatch(rparams, resolve_hostname_reply_dispatch_table, json_dispatch_flags, &p);
|
||
|
if (r < 0)
|
||
|
goto fail;
|
||
|
if (json_variant_is_blank_object(p.addresses))
|
||
|
@@ -282,7 +282,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
|
||
|
JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) {
|
||
|
AddressParameters q = {};
|
||
|
|
||
|
- r = json_dispatch(entry, address_parameters_dispatch_table, NULL, json_dispatch_flags, &q);
|
||
|
+ r = json_dispatch(entry, address_parameters_dispatch_table, json_dispatch_flags, &q);
|
||
|
if (r < 0)
|
||
|
goto fail;
|
||
|
|
||
|
@@ -320,7 +320,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
|
||
|
JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) {
|
||
|
AddressParameters q = {};
|
||
|
|
||
|
- r = json_dispatch(entry, address_parameters_dispatch_table, NULL, json_dispatch_flags, &q);
|
||
|
+ r = json_dispatch(entry, address_parameters_dispatch_table, json_dispatch_flags, &q);
|
||
|
if (r < 0)
|
||
|
goto fail;
|
||
|
|
||
|
@@ -428,7 +428,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
|
||
|
goto not_found;
|
||
|
}
|
||
|
|
||
|
- r = json_dispatch(rparams, resolve_hostname_reply_dispatch_table, NULL, json_dispatch_flags, &p);
|
||
|
+ r = json_dispatch(rparams, resolve_hostname_reply_dispatch_table, json_dispatch_flags, &p);
|
||
|
if (r < 0)
|
||
|
goto fail;
|
||
|
if (json_variant_is_blank_object(p.addresses))
|
||
|
@@ -438,7 +438,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
|
||
|
JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) {
|
||
|
AddressParameters q = {};
|
||
|
|
||
|
- r = json_dispatch(entry, address_parameters_dispatch_table, NULL, json_dispatch_flags, &q);
|
||
|
+ r = json_dispatch(entry, address_parameters_dispatch_table, json_dispatch_flags, &q);
|
||
|
if (r < 0)
|
||
|
goto fail;
|
||
|
|
||
|
@@ -484,7 +484,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
|
||
|
JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) {
|
||
|
AddressParameters q = {};
|
||
|
|
||
|
- r = json_dispatch(entry, address_parameters_dispatch_table, NULL, json_dispatch_flags, &q);
|
||
|
+ r = json_dispatch(entry, address_parameters_dispatch_table, json_dispatch_flags, &q);
|
||
|
if (r < 0)
|
||
|
goto fail;
|
||
|
|
||
|
@@ -640,7 +640,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
|
||
|
goto not_found;
|
||
|
}
|
||
|
|
||
|
- r = json_dispatch(rparams, resolve_address_reply_dispatch_table, NULL, json_dispatch_flags, &p);
|
||
|
+ r = json_dispatch(rparams, resolve_address_reply_dispatch_table, json_dispatch_flags, &p);
|
||
|
if (r < 0)
|
||
|
goto fail;
|
||
|
if (json_variant_is_blank_object(p.names))
|
||
|
@@ -651,7 +651,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
|
||
|
JSON_VARIANT_ARRAY_FOREACH(entry, p.names) {
|
||
|
_cleanup_(name_parameters_destroy) NameParameters q = {};
|
||
|
|
||
|
- r = json_dispatch(entry, name_parameters_dispatch_table, NULL, json_dispatch_flags, &q);
|
||
|
+ r = json_dispatch(entry, name_parameters_dispatch_table, json_dispatch_flags, &q);
|
||
|
if (r < 0)
|
||
|
goto fail;
|
||
|
|
||
|
@@ -692,7 +692,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
|
||
|
JSON_VARIANT_ARRAY_FOREACH(entry, p.names) {
|
||
|
_cleanup_(name_parameters_destroy) NameParameters q = {};
|
||
|
|
||
|
- r = json_dispatch(entry, name_parameters_dispatch_table, NULL, json_dispatch_flags, &q);
|
||
|
+ r = json_dispatch(entry, name_parameters_dispatch_table, json_dispatch_flags, &q);
|
||
|
if (r < 0)
|
||
|
goto fail;
|
||
|
|
||
|
diff --git a/src/oom/oomd-manager.c b/src/oom/oomd-manager.c
|
||
|
index 4a43807b87..66c41c1cfa 100644
|
||
|
--- a/src/oom/oomd-manager.c
|
||
|
+++ b/src/oom/oomd-manager.c
|
||
|
@@ -72,7 +72,7 @@ static int process_managed_oom_message(Manager *m, uid_t uid, JsonVariant *param
|
||
|
if (!json_variant_is_object(c))
|
||
|
continue;
|
||
|
|
||
|
- r = json_dispatch(c, dispatch_table, NULL, 0, &message);
|
||
|
+ r = json_dispatch(c, dispatch_table, 0, &message);
|
||
|
if (r == -ENOMEM)
|
||
|
return r;
|
||
|
if (r < 0)
|
||
|
diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c
|
||
|
index e22e06d054..0782e48e04 100644
|
||
|
--- a/src/resolve/resolvectl.c
|
||
|
+++ b/src/resolve/resolvectl.c
|
||
|
@@ -2598,7 +2598,7 @@ static int monitor_rkey_from_json(JsonVariant *v, DnsResourceKey **ret_key) {
|
||
|
assert(v);
|
||
|
assert(ret_key);
|
||
|
|
||
|
- r = json_dispatch(v, dispatch_table, NULL, 0, NULL);
|
||
|
+ r = json_dispatch(v, dispatch_table, 0, NULL);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
@@ -2697,7 +2697,7 @@ static void monitor_query_dump(JsonVariant *v) {
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
- r = json_dispatch(v, dispatch_table, NULL, 0, NULL);
|
||
|
+ r = json_dispatch(v, dispatch_table, 0, NULL);
|
||
|
if (r < 0)
|
||
|
return (void) log_warning("Received malformed monitor message, ignoring.");
|
||
|
|
||
|
diff --git a/src/resolve/resolved-varlink.c b/src/resolve/resolved-varlink.c
|
||
|
index 8ba5eb9833..1c5ce8315c 100644
|
||
|
--- a/src/resolve/resolved-varlink.c
|
||
|
+++ b/src/resolve/resolved-varlink.c
|
||
|
@@ -312,8 +312,8 @@ static int vl_method_resolve_hostname(Varlink *link, JsonVariant *parameters, Va
|
||
|
if (FLAGS_SET(flags, VARLINK_METHOD_ONEWAY))
|
||
|
return -EINVAL;
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
if (p.ifindex < 0)
|
||
|
@@ -492,8 +492,8 @@ static int vl_method_resolve_address(Varlink *link, JsonVariant *parameters, Var
|
||
|
if (FLAGS_SET(flags, VARLINK_METHOD_ONEWAY))
|
||
|
return -EINVAL;
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
if (p.ifindex < 0)
|
||
|
diff --git a/src/shared/group-record.c b/src/shared/group-record.c
|
||
|
index 2f12ac1c22..728471b2b6 100644
|
||
|
--- a/src/shared/group-record.c
|
||
|
+++ b/src/shared/group-record.c
|
||
|
@@ -50,7 +50,7 @@ static int dispatch_privileged(const char *name, JsonVariant *variant, JsonDispa
|
||
|
{},
|
||
|
};
|
||
|
|
||
|
- return json_dispatch(variant, privileged_dispatch_table, NULL, flags, userdata);
|
||
|
+ return json_dispatch(variant, privileged_dispatch_table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
static int dispatch_binding(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
|
||
|
@@ -78,7 +78,7 @@ static int dispatch_binding(const char *name, JsonVariant *variant, JsonDispatch
|
||
|
if (!m)
|
||
|
return 0;
|
||
|
|
||
|
- return json_dispatch(m, binding_dispatch_table, NULL, flags, userdata);
|
||
|
+ return json_dispatch(m, binding_dispatch_table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
static int dispatch_per_machine(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
|
||
|
@@ -131,7 +131,7 @@ static int dispatch_per_machine(const char *name, JsonVariant *variant, JsonDisp
|
||
|
if (!matching)
|
||
|
continue;
|
||
|
|
||
|
- r = json_dispatch(e, per_machine_dispatch_table, NULL, flags, userdata);
|
||
|
+ r = json_dispatch(e, per_machine_dispatch_table, flags, userdata);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
}
|
||
|
@@ -164,7 +164,7 @@ static int dispatch_status(const char *name, JsonVariant *variant, JsonDispatchF
|
||
|
if (!m)
|
||
|
return 0;
|
||
|
|
||
|
- return json_dispatch(m, status_dispatch_table, NULL, flags, userdata);
|
||
|
+ return json_dispatch(m, status_dispatch_table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
static int group_record_augment(GroupRecord *h, JsonDispatchFlags json_flags) {
|
||
|
@@ -230,7 +230,7 @@ int group_record_load(
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
- r = json_dispatch(h->json, group_dispatch_table, NULL, json_flags, h);
|
||
|
+ r = json_dispatch(h->json, group_dispatch_table, json_flags, h);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
diff --git a/src/shared/json.c b/src/shared/json.c
|
||
|
index eda7bb1956..e346bb0a01 100644
|
||
|
--- a/src/shared/json.c
|
||
|
+++ b/src/shared/json.c
|
||
|
@@ -4227,7 +4227,13 @@ static void *dispatch_userdata(const JsonDispatch *p, void *userdata) {
|
||
|
return SIZE_TO_PTR(p->offset);
|
||
|
}
|
||
|
|
||
|
-int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata) {
|
||
|
+int json_dispatch_full(
|
||
|
+ JsonVariant *v,
|
||
|
+ const JsonDispatch table[],
|
||
|
+ JsonDispatchCallback bad,
|
||
|
+ JsonDispatchFlags flags,
|
||
|
+ void *userdata,
|
||
|
+ const char **reterr_bad_field) {
|
||
|
size_t m;
|
||
|
int r, done = 0;
|
||
|
bool *found;
|
||
|
@@ -4238,6 +4244,9 @@ int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallba
|
||
|
if (flags & JSON_PERMISSIVE)
|
||
|
return 0;
|
||
|
|
||
|
+ if (reterr_bad_field)
|
||
|
+ *reterr_bad_field = NULL;
|
||
|
+
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
@@ -4260,7 +4269,7 @@ int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallba
|
||
|
streq_ptr(json_variant_string(key), p->name))
|
||
|
break;
|
||
|
|
||
|
- if (p->name) { /* Found a matching entry! :-) */
|
||
|
+ if (p->name) { /* Found a matching entry! 🙂 */
|
||
|
JsonDispatchFlags merged_flags;
|
||
|
|
||
|
merged_flags = flags | p->flags;
|
||
|
@@ -4275,6 +4284,9 @@ int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallba
|
||
|
if (merged_flags & JSON_PERMISSIVE)
|
||
|
continue;
|
||
|
|
||
|
+ if (reterr_bad_field)
|
||
|
+ *reterr_bad_field = p->name;
|
||
|
+
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
@@ -4284,6 +4296,9 @@ int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallba
|
||
|
if (merged_flags & JSON_PERMISSIVE)
|
||
|
continue;
|
||
|
|
||
|
+ if (reterr_bad_field)
|
||
|
+ *reterr_bad_field = p->name;
|
||
|
+
|
||
|
return -ENOTUNIQ;
|
||
|
}
|
||
|
|
||
|
@@ -4295,13 +4310,16 @@ int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallba
|
||
|
if (merged_flags & JSON_PERMISSIVE)
|
||
|
continue;
|
||
|
|
||
|
+ if (reterr_bad_field)
|
||
|
+ *reterr_bad_field = json_variant_string(key);
|
||
|
+
|
||
|
return r;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
done ++;
|
||
|
|
||
|
- } else { /* Didn't find a matching entry! :-( */
|
||
|
+ } else { /* Didn't find a matching entry! ☹️ */
|
||
|
|
||
|
if (bad) {
|
||
|
r = bad(json_variant_string(key), value, flags, userdata);
|
||
|
@@ -4309,6 +4327,9 @@ int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallba
|
||
|
if (flags & JSON_PERMISSIVE)
|
||
|
continue;
|
||
|
|
||
|
+ if (reterr_bad_field)
|
||
|
+ *reterr_bad_field = json_variant_string(key);
|
||
|
+
|
||
|
return r;
|
||
|
} else
|
||
|
done ++;
|
||
|
@@ -4319,6 +4340,9 @@ int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallba
|
||
|
if (flags & JSON_PERMISSIVE)
|
||
|
continue;
|
||
|
|
||
|
+ if (reterr_bad_field)
|
||
|
+ *reterr_bad_field = json_variant_string(key);
|
||
|
+
|
||
|
return -EADDRNOTAVAIL;
|
||
|
}
|
||
|
}
|
||
|
@@ -4333,6 +4357,9 @@ int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallba
|
||
|
if ((merged_flags & JSON_PERMISSIVE))
|
||
|
continue;
|
||
|
|
||
|
+ if (reterr_bad_field)
|
||
|
+ *reterr_bad_field = p->name;
|
||
|
+
|
||
|
return -ENXIO;
|
||
|
}
|
||
|
}
|
||
|
@@ -4340,6 +4367,14 @@ int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallba
|
||
|
return done;
|
||
|
}
|
||
|
|
||
|
+int json_dispatch(
|
||
|
+ JsonVariant *v,
|
||
|
+ const JsonDispatch table[],
|
||
|
+ JsonDispatchFlags flags,
|
||
|
+ void *userdata) {
|
||
|
+ return json_dispatch_full(v, table, NULL, flags, userdata, NULL);
|
||
|
+}
|
||
|
+
|
||
|
int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
|
||
|
bool *b = ASSERT_PTR(userdata);
|
||
|
|
||
|
diff --git a/src/shared/json.h b/src/shared/json.h
|
||
|
index 5993e05299..e62c71a249 100644
|
||
|
--- a/src/shared/json.h
|
||
|
+++ b/src/shared/json.h
|
||
|
@@ -363,7 +363,8 @@ typedef struct JsonDispatch {
|
||
|
JsonDispatchFlags flags;
|
||
|
} JsonDispatch;
|
||
|
|
||
|
-int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata);
|
||
|
+int json_dispatch_full(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata, const char **reterr_bad_field);
|
||
|
+int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchFlags flags, void *userdata);
|
||
|
|
||
|
int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
|
||
|
int json_dispatch_const_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
|
||
|
diff --git a/src/shared/user-record.c b/src/shared/user-record.c
|
||
|
index 84cbdb1d30..1c37444349 100644
|
||
|
--- a/src/shared/user-record.c
|
||
|
+++ b/src/shared/user-record.c
|
||
|
@@ -653,7 +653,7 @@ static int dispatch_secret(const char *name, JsonVariant *variant, JsonDispatchF
|
||
|
{},
|
||
|
};
|
||
|
|
||
|
- return json_dispatch(variant, secret_dispatch_table, NULL, flags, userdata);
|
||
|
+ return json_dispatch(variant, secret_dispatch_table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
static int dispatch_pkcs11_uri(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
|
||
|
@@ -782,7 +782,7 @@ static int dispatch_pkcs11_key(const char *name, JsonVariant *variant, JsonDispa
|
||
|
k = h->pkcs11_encrypted_key + h->n_pkcs11_encrypted_key;
|
||
|
*k = (Pkcs11EncryptedKey) {};
|
||
|
|
||
|
- r = json_dispatch(e, pkcs11_key_dispatch_table, NULL, flags, k);
|
||
|
+ r = json_dispatch(e, pkcs11_key_dispatch_table, flags, k);
|
||
|
if (r < 0) {
|
||
|
pkcs11_encrypted_key_done(k);
|
||
|
return r;
|
||
|
@@ -916,7 +916,7 @@ static int dispatch_fido2_hmac_salt(const char *name, JsonVariant *variant, Json
|
||
|
.client_pin = -1,
|
||
|
};
|
||
|
|
||
|
- r = json_dispatch(e, fido2_hmac_salt_dispatch_table, NULL, flags, k);
|
||
|
+ r = json_dispatch(e, fido2_hmac_salt_dispatch_table, flags, k);
|
||
|
if (r < 0) {
|
||
|
fido2_hmac_salt_done(k);
|
||
|
return r;
|
||
|
@@ -956,7 +956,7 @@ static int dispatch_recovery_key(const char *name, JsonVariant *variant, JsonDis
|
||
|
k = h->recovery_key + h->n_recovery_key;
|
||
|
*k = (RecoveryKey) {};
|
||
|
|
||
|
- r = json_dispatch(e, recovery_key_dispatch_table, NULL, flags, k);
|
||
|
+ r = json_dispatch(e, recovery_key_dispatch_table, flags, k);
|
||
|
if (r < 0) {
|
||
|
recovery_key_done(k);
|
||
|
return r;
|
||
|
@@ -1038,7 +1038,7 @@ static int dispatch_privileged(const char *name, JsonVariant *variant, JsonDispa
|
||
|
{},
|
||
|
};
|
||
|
|
||
|
- return json_dispatch(variant, privileged_dispatch_table, NULL, flags, userdata);
|
||
|
+ return json_dispatch(variant, privileged_dispatch_table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
static int dispatch_binding(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
|
||
|
@@ -1077,7 +1077,7 @@ static int dispatch_binding(const char *name, JsonVariant *variant, JsonDispatch
|
||
|
if (!m)
|
||
|
return 0;
|
||
|
|
||
|
- return json_dispatch(m, binding_dispatch_table, NULL, flags, userdata);
|
||
|
+ return json_dispatch(m, binding_dispatch_table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
int per_machine_id_match(JsonVariant *ids, JsonDispatchFlags flags) {
|
||
|
@@ -1276,7 +1276,7 @@ static int dispatch_per_machine(const char *name, JsonVariant *variant, JsonDisp
|
||
|
if (!matching)
|
||
|
continue;
|
||
|
|
||
|
- r = json_dispatch(e, per_machine_dispatch_table, NULL, flags, userdata);
|
||
|
+ r = json_dispatch(e, per_machine_dispatch_table, flags, userdata);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
}
|
||
|
@@ -1325,7 +1325,7 @@ static int dispatch_status(const char *name, JsonVariant *variant, JsonDispatchF
|
||
|
if (!m)
|
||
|
return 0;
|
||
|
|
||
|
- return json_dispatch(m, status_dispatch_table, NULL, flags, userdata);
|
||
|
+ return json_dispatch(m, status_dispatch_table, flags, userdata);
|
||
|
}
|
||
|
|
||
|
int user_record_build_image_path(UserStorage storage, const char *user_name_and_realm, char **ret) {
|
||
|
@@ -1615,7 +1615,7 @@ int user_record_load(UserRecord *h, JsonVariant *v, UserRecordLoadFlags load_fla
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
- r = json_dispatch(h->json, user_dispatch_table, NULL, json_flags, h);
|
||
|
+ r = json_dispatch(h->json, user_dispatch_table, json_flags, h);
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
diff --git a/src/shared/userdb.c b/src/shared/userdb.c
|
||
|
index 3f64ec8942..4ea4ac4d72 100644
|
||
|
--- a/src/shared/userdb.c
|
||
|
+++ b/src/shared/userdb.c
|
||
|
@@ -189,7 +189,7 @@ static int userdb_on_query_reply(
|
||
|
|
||
|
assert_se(!iterator->found_user);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &user_data);
|
||
|
+ r = json_dispatch(parameters, dispatch_table, 0, &user_data);
|
||
|
if (r < 0)
|
||
|
goto finish;
|
||
|
|
||
|
@@ -246,7 +246,7 @@ static int userdb_on_query_reply(
|
||
|
|
||
|
assert_se(!iterator->found_group);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &group_data);
|
||
|
+ r = json_dispatch(parameters, dispatch_table, 0, &group_data);
|
||
|
if (r < 0)
|
||
|
goto finish;
|
||
|
|
||
|
@@ -302,7 +302,7 @@ static int userdb_on_query_reply(
|
||
|
assert(!iterator->found_user_name);
|
||
|
assert(!iterator->found_group_name);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &membership_data);
|
||
|
+ r = json_dispatch(parameters, dispatch_table, 0, &membership_data);
|
||
|
if (r < 0)
|
||
|
goto finish;
|
||
|
|
||
|
diff --git a/src/shared/varlink.c b/src/shared/varlink.c
|
||
|
index 4d2cfee491..49593aa05a 100644
|
||
|
--- a/src/shared/varlink.c
|
||
|
+++ b/src/shared/varlink.c
|
||
|
@@ -1771,6 +1771,26 @@ int varlink_notifyb(Varlink *v, ...) {
|
||
|
return varlink_notify(v, parameters);
|
||
|
}
|
||
|
|
||
|
+int varlink_dispatch(Varlink *v, JsonVariant *parameters, const JsonDispatch table[], void *userdata) {
|
||
|
+ const char *bad_field = NULL;
|
||
|
+ int r;
|
||
|
+
|
||
|
+ assert_return(v, -EINVAL);
|
||
|
+ assert_return(table, -EINVAL);
|
||
|
+
|
||
|
+ /* A wrapper around json_dispatch_full() that returns a nice InvalidParameter error if we hit a problem with some field. */
|
||
|
+
|
||
|
+ r = json_dispatch_full(parameters, table, /* bad= */ NULL, /* flags= */ 0, userdata, &bad_field);
|
||
|
+ if (r < 0) {
|
||
|
+ if (bad_field)
|
||
|
+ return varlink_errorb(v, VARLINK_ERROR_INVALID_PARAMETER,
|
||
|
+ JSON_BUILD_OBJECT(JSON_BUILD_PAIR("parameter", JSON_BUILD_STRING(bad_field))));
|
||
|
+ return r;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
int varlink_bind_reply(Varlink *v, VarlinkReply callback) {
|
||
|
assert_return(v, -EINVAL);
|
||
|
|
||
|
diff --git a/src/shared/varlink.h b/src/shared/varlink.h
|
||
|
index 9518cd9098..e51ccd9107 100644
|
||
|
--- a/src/shared/varlink.h
|
||
|
+++ b/src/shared/varlink.h
|
||
|
@@ -107,6 +107,9 @@ int varlink_error_errno(Varlink *v, int error);
|
||
|
int varlink_notify(Varlink *v, JsonVariant *parameters);
|
||
|
int varlink_notifyb(Varlink *v, ...);
|
||
|
|
||
|
+/* Parsing incoming data via json_dispatch() and generate a nice error on parse errors */
|
||
|
+int varlink_dispatch(Varlink *v, JsonVariant *parameters, const JsonDispatch table[], void *userdata);
|
||
|
+
|
||
|
/* Bind a disconnect, reply or timeout callback */
|
||
|
int varlink_bind_reply(Varlink *v, VarlinkReply reply);
|
||
|
|
||
|
diff --git a/src/userdb/userwork.c b/src/userdb/userwork.c
|
||
|
index 21a869df1b..569dba3285 100644
|
||
|
--- a/src/userdb/userwork.c
|
||
|
+++ b/src/userdb/userwork.c
|
||
|
@@ -147,8 +147,8 @@ static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, Var
|
||
|
|
||
|
assert(parameters);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
r = userdb_flags_from_service(link, p.service, &userdb_flags);
|
||
|
@@ -283,8 +283,8 @@ static int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, Va
|
||
|
|
||
|
assert(parameters);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
r = userdb_flags_from_service(link, p.service, &userdb_flags);
|
||
|
@@ -366,8 +366,8 @@ static int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, Var
|
||
|
|
||
|
assert(parameters);
|
||
|
|
||
|
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
|
||
|
- if (r < 0)
|
||
|
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
|
||
|
+ if (r != 0)
|
||
|
return r;
|
||
|
|
||
|
r = userdb_flags_from_service(link, p.service, &userdb_flags);
|