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:
parent
8430c4d91d
commit
af0d593b32
@ -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);
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user