]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
json: introduce json_dispatch_byte_array_iovec() and json_dispatch_in_addr()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 2 Jan 2024 21:07:10 +0000 (06:07 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 11 Jan 2024 08:03:25 +0000 (17:03 +0900)
src/shared/json.c
src/shared/json.h

index 073bf31acde8c86db5c0c7e5be67fbac446a3985..47cd78b3965de052a715e7375306256085927783 100644 (file)
@@ -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;
 
index a40e9496c2d06ba3dfeb4016dc6002645065a9a7..3c20f94b5874fc33584c950eb5e41986807660db 100644 (file)
@@ -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