Skip to content

Commit

Permalink
Merge pull request systemd#30879 from yuwata/dhcp-client-id-json
Browse files Browse the repository at this point in the history
dhcp: introduce json_dispatch_client_id() and friends
  • Loading branch information
poettering authored Jan 11, 2024
2 parents 25cbc42 + 0705e05 commit e992753
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 6 deletions.
3 changes: 3 additions & 0 deletions src/libsystemd-network/dhcp-client-id-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
26 changes: 23 additions & 3 deletions src/libsystemd-network/sd-dhcp-client-id.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "alloc-util.h"
#include "dhcp-client-id-internal.h"
#include "iovec-util.h"
#include "unaligned.h"
#include "utf8.h"

Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
12 changes: 9 additions & 3 deletions src/libsystemd-network/sd-dhcp-duid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
56 changes: 56 additions & 0 deletions src/shared/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions src/shared/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit e992753

Please sign in to comment.