1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-11 20:58:27 +03:00

ndisc-option: add a way to specify invalid or unsupported options

Mostly for testing.
This commit is contained in:
Yu Watanabe 2024-03-13 12:31:35 +09:00
parent 8430c4d91d
commit af0d593b32
2 changed files with 58 additions and 0 deletions

View File

@ -65,6 +65,13 @@ static sd_ndisc_option* ndisc_option_new(uint8_t type, size_t offset) {
return p;
}
static void ndisc_raw_done(sd_ndisc_raw *raw) {
if (!raw)
return;
free(raw->bytes);
}
static void ndisc_rdnss_done(sd_ndisc_rdnss *rdnss) {
if (!rdnss)
return;
@ -84,6 +91,10 @@ sd_ndisc_option* ndisc_option_free(sd_ndisc_option *option) {
return NULL;
switch (option->type) {
case 0:
ndisc_raw_done(&option->raw);
break;
case SD_NDISC_OPTION_RDNSS:
ndisc_rdnss_done(&option->rdnss);
break;
@ -111,6 +122,9 @@ static int ndisc_option_compare_func(const sd_ndisc_option *x, const sd_ndisc_op
return r;
switch (x->type) {
case 0:
return memcmp_nn(x->raw.bytes, x->raw.length, y->raw.bytes, y->raw.length);
case SD_NDISC_OPTION_SOURCE_LL_ADDRESS:
case SD_NDISC_OPTION_TARGET_LL_ADDRESS:
case SD_NDISC_OPTION_REDIRECTED_HEADER:
@ -155,6 +169,10 @@ static void ndisc_option_hash_func(const sd_ndisc_option *option, struct siphash
siphash24_compress_typesafe(option->type, state);
switch (option->type) {
case 0:
siphash24_compress(option->raw.bytes, option->raw.length, state);
break;
case SD_NDISC_OPTION_SOURCE_LL_ADDRESS:
case SD_NDISC_OPTION_TARGET_LL_ADDRESS:
case SD_NDISC_OPTION_REDIRECTED_HEADER:
@ -199,6 +217,31 @@ static int ndisc_option_consume(Set **options, sd_ndisc_option *p) {
return set_ensure_consume(options, &ndisc_option_hash_ops, p);
}
int ndisc_option_add_raw(Set **options, size_t offset, size_t length, const uint8_t *bytes) {
_cleanup_free_ uint8_t *copy = NULL;
assert(options);
assert(bytes);
if (length == 0)
return -EINVAL;
copy = newdup(uint8_t, bytes, length);
if (!copy)
return -ENOMEM;
sd_ndisc_option *p = ndisc_option_new(/* type = */ 0, offset);
if (!p)
return -ENOMEM;
p->raw = (sd_ndisc_raw) {
.bytes = TAKE_PTR(copy),
.length = length,
};
return ndisc_option_consume(options, p);
}
int ndisc_option_add_link_layer_address(Set **options, uint8_t opt, size_t offset, const struct ether_addr *mac) {
assert(options);
assert(IN_SET(opt, SD_NDISC_OPTION_SOURCE_LL_ADDRESS, SD_NDISC_OPTION_TARGET_LL_ADDRESS));
@ -788,6 +831,10 @@ int ndisc_parse_options(ICMP6Packet *packet, Set **ret_options) {
return log_debug_errno(r, "Failed to parse NDisc option header: %m");
switch (type) {
case 0:
r = -EBADMSG;
break;
case SD_NDISC_OPTION_SOURCE_LL_ADDRESS:
case SD_NDISC_OPTION_TARGET_LL_ADDRESS:
r = ndisc_option_parse_link_layer_address(&options, offset, length, opt);

View File

@ -13,6 +13,11 @@
#include "set.h"
#include "time-util.h"
typedef struct sd_ndisc_raw {
uint8_t *bytes;
size_t length;
} sd_ndisc_raw;
/* Mostly equivalent to struct nd_opt_prefix_info, but using usec_t. */
typedef struct sd_ndisc_prefix {
uint8_t flags;
@ -51,6 +56,7 @@ typedef struct sd_ndisc_option {
size_t offset;
union {
sd_ndisc_raw raw; /* for testing or unsupported options */
struct ether_addr mac; /* SD_NDISC_OPTION_SOURCE_LL_ADDRESS or SD_NDISC_OPTION_TARGET_LL_ADDRESS */
sd_ndisc_prefix prefix; /* SD_NDISC_OPTION_PREFIX_INFORMATION */
struct ip6_hdr hdr; /* SD_NDISC_OPTION_REDIRECTED_HEADER */
@ -107,6 +113,11 @@ static inline sd_ndisc_option* ndisc_option_get(Set *options, uint8_t type) {
int ndisc_option_get_mac(Set *options, uint8_t type, struct ether_addr *ret);
int ndisc_option_add_raw(
Set **options,
size_t offset,
size_t length,
const uint8_t *bytes);
int ndisc_option_add_link_layer_address(
Set **options,
uint8_t opt,