Merge pull request #30879 from yuwata/dhcp-client-id-json

dhcp: introduce json_dispatch_client_id() and friends
This commit is contained in:
Lennart Poettering 2024-01-11 10:22:31 +01:00 committed by GitHub
commit e992753e58
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 93 additions and 6 deletions

View file

@ -4,6 +4,7 @@
#include "sd-dhcp-client-id.h"
#include "dhcp-duid-internal.h"
#include "json.h"
#include "macro.h"
#include "siphash24.h"
#include "sparse-endian.h"
@ -55,3 +56,5 @@ static inline bool client_id_data_size_is_valid(size_t size) {
void client_id_hash_func(const sd_dhcp_client_id *client_id, struct siphash *state);
int client_id_compare_func(const sd_dhcp_client_id *a, const sd_dhcp_client_id *b);
int json_dispatch_client_id(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);

View file

@ -2,6 +2,7 @@
#include "alloc-util.h"
#include "dhcp-client-id-internal.h"
#include "iovec-util.h"
#include "unaligned.h"
#include "utf8.h"
@ -51,7 +52,9 @@ int sd_dhcp_client_id_set(
assert_return(client_id, -EINVAL);
assert_return(data, -EINVAL);
assert_return(client_id_data_size_is_valid(data_size), -EINVAL);
if (!client_id_data_size_is_valid(data_size))
return -EINVAL;
client_id->id.type = type;
memcpy(client_id->id.data, data, data_size);
@ -67,10 +70,12 @@ int sd_dhcp_client_id_set_raw(
assert_return(client_id, -EINVAL);
assert_return(data, -EINVAL);
assert_return(client_id_size_is_valid(data_size), -EINVAL);
/* Unlike sd_dhcp_client_id_set(), this takes whole client ID including its type. */
if (!client_id_size_is_valid(data_size))
return -EINVAL;
memcpy(client_id->raw, data, data_size);
client_id->size = data_size;
@ -150,7 +155,6 @@ int sd_dhcp_client_id_to_string_from_raw(const void *data, size_t data_size, cha
int r;
assert_return(data, -EINVAL);
assert_return(client_id_size_is_valid(data_size), -EINVAL);
assert_return(ret, -EINVAL);
r = sd_dhcp_client_id_set_raw(&client_id, data, data_size);
@ -174,3 +178,19 @@ int client_id_compare_func(const sd_dhcp_client_id *a, const sd_dhcp_client_id *
return memcmp_nn(a->raw, a->size, b->raw, b->size);
}
int json_dispatch_client_id(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
sd_dhcp_client_id *client_id = 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;
r = sd_dhcp_client_id_set_raw(client_id, iov.iov_base, iov.iov_len);
if (r < 0)
return json_log(variant, flags, r, "Failed to set DHCP client ID from JSON field '%s': %m", strna(name));
return 0;
}

View file

@ -71,7 +71,9 @@ int sd_dhcp_duid_set(
assert_return(duid, -EINVAL);
assert_return(data, -EINVAL);
assert_return(duid_data_size_is_valid(data_size), -EINVAL);
if (!duid_data_size_is_valid(data_size))
return -EINVAL;
unaligned_write_be16(&duid->duid.type, duid_type);
memcpy(duid->duid.data, data, data_size);
@ -87,10 +89,12 @@ int sd_dhcp_duid_set_raw(
assert_return(duid, -EINVAL);
assert_return(data, -EINVAL);
assert_return(duid_size_is_valid(data_size), -EINVAL);
/* Unlike sd_dhcp_duid_set(), this takes whole DUID including its type. */
if (!duid_size_is_valid(data_size))
return -EINVAL;
memcpy(duid->raw, data, data_size);
duid->size = data_size;
@ -209,9 +213,11 @@ int dhcp_duid_to_string_internal(uint16_t type, const void *data, size_t data_si
const char *t;
assert(data);
assert(duid_data_size_is_valid(data_size));
assert(ret);
if (!duid_data_size_is_valid(data_size))
return -EINVAL;
x = hexmem(data, data_size);
if (!x)
return -ENOMEM;

View 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;

View 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