summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2024-01-02 22:07:10 +0100
committerYu Watanabe <watanabe.yu+github@gmail.com>2024-01-11 09:03:25 +0100
commit72278e62d990d81a05756ef2a33e11aec1beb4e5 (patch)
treecfbfedbca5c3675499d701b7498258266414d74a /src
parentsd-dhcp-client-id/duid: do not trigger assertion when invalid size is passed (diff)
downloadsystemd-72278e62d990d81a05756ef2a33e11aec1beb4e5.tar.xz
systemd-72278e62d990d81a05756ef2a33e11aec1beb4e5.zip
json: introduce json_dispatch_byte_array_iovec() and json_dispatch_in_addr()
Diffstat (limited to 'src')
-rw-r--r--src/shared/json.c56
-rw-r--r--src/shared/json.h2
2 files changed, 58 insertions, 0 deletions
diff --git a/src/shared/json.c b/src/shared/json.c
index 073bf31acd..47cd78b396 100644
--- a/src/shared/json.c
+++ b/src/shared/json.c
@@ -14,7 +14,9 @@
#include "fd-util.h"
#include "fileio.h"
#include "float.h"
+#include "glyph-util.h"
#include "hexdecoct.h"
+#include "iovec-util.h"
#include "json-internal.h"
#include "json.h"
#include "macro.h"
@@ -4993,6 +4995,60 @@ int json_dispatch_unbase64_iovec(const char *name, JsonVariant *variant, JsonDis
return 0;
}
+int json_dispatch_byte_array_iovec(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
+ _cleanup_free_ uint8_t *buffer = NULL;
+ struct iovec *iov = ASSERT_PTR(userdata);
+ size_t sz, k = 0;
+
+ assert(variant);
+
+ if (!json_variant_is_array(variant))
+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an array.", strna(name));
+
+ sz = json_variant_elements(variant);
+
+ buffer = new(uint8_t, sz);
+ if (!buffer)
+ return json_log(variant, flags, SYNTHETIC_ERRNO(ENOMEM), "Out of memory.");
+
+ JsonVariant *i;
+ JSON_VARIANT_ARRAY_FOREACH(i, variant) {
+ uint64_t b;
+
+ if (!json_variant_is_unsigned(i))
+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Element %zu of JSON field '%s' is not an unsigned integer.", k, strna(name));
+
+ b = json_variant_unsigned(i);
+ if (b > 0xff)
+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL),
+ "Element %zu of JSON field '%s' is out of range 0%s255.",
+ k, strna(name), special_glyph(SPECIAL_GLYPH_ELLIPSIS));
+
+ buffer[k++] = (uint8_t) b;
+ }
+ assert(k == sz);
+
+ free_and_replace(iov->iov_base, buffer);
+ iov->iov_len = sz;
+ return 0;
+}
+
+int json_dispatch_in_addr(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
+ struct in_addr *address = ASSERT_PTR(userdata);
+ _cleanup_(iovec_done) struct iovec iov = {};
+ int r;
+
+ r = json_dispatch_byte_array_iovec(name, variant, flags, &iov);
+ if (r < 0)
+ return r;
+
+ if (iov.iov_len != sizeof(struct in_addr))
+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is array of unexpected size.", strna(name));
+
+ memcpy(address, iov.iov_base, iov.iov_len);
+ return 0;
+}
+
static int json_cmp_strings(const void *x, const void *y) {
JsonVariant *const *a = x, *const *b = y;
diff --git a/src/shared/json.h b/src/shared/json.h
index a40e9496c2..3c20f94b58 100644
--- a/src/shared/json.h
+++ b/src/shared/json.h
@@ -425,6 +425,8 @@ int json_dispatch_user_group_name(const char *name, JsonVariant *variant, JsonDi
int json_dispatch_id128(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_unsupported(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_unbase64_iovec(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
+int json_dispatch_byte_array_iovec(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
+int json_dispatch_in_addr(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
assert_cc(sizeof(uint32_t) == sizeof(unsigned));
#define json_dispatch_uint json_dispatch_uint32