ndisc-option: fix parsing/building extended flags
The flags part of the option is 6 bytes. Let's read/write one by one.
Fixes https://github.com/systemd/systemd/pull/43620#discussion_r3913713018.
(cherry picked from commit b628909430)
This commit is contained in:
committed by
Luca Boccassi
parent
4bc4705b6b
commit
220ab61cd2
@@ -871,7 +871,10 @@ static int ndisc_option_parse_flags_extension(Set **options, size_t offset, size
|
||||
if (opt[0] != SD_NDISC_OPTION_FLAGS_EXTENSION)
|
||||
return -EBADMSG;
|
||||
|
||||
uint64_t flags = (unaligned_read_be64(opt) & UINT64_C(0xffffffffffff0000)) >> 8;
|
||||
uint64_t flags = 0;
|
||||
for (size_t i = 2; i < 8; i++)
|
||||
flags |= ((uint64_t) opt[i]) << ((i - 1) * 8);
|
||||
|
||||
return ndisc_option_add_flags_extension(options, offset, flags);
|
||||
}
|
||||
|
||||
@@ -884,10 +887,12 @@ static int ndisc_option_build_flags_extension(const sd_ndisc_option *option, uin
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
unaligned_write_be64(buf, (option->extended_flags & UINT64_C(0x00ffffffffffff00)) << 8);
|
||||
buf[0] = SD_NDISC_OPTION_FLAGS_EXTENSION;
|
||||
buf[1] = 1;
|
||||
|
||||
for (size_t i = 2; i < 8; i++)
|
||||
buf[i] = (option->extended_flags >> ((i - 1) * 8)) & 0xff;
|
||||
|
||||
*ret = TAKE_PTR(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@ static void router_dump(sd_ndisc_router *rt) {
|
||||
log_info("Hop limit: %u", hop_limit);
|
||||
|
||||
assert_se(sd_ndisc_router_get_flags(rt, &flags) >= 0);
|
||||
ASSERT_EQ(flags & UINT64_C(0x00ffffffffffff00), UINT64_C(0x0066554433221100));
|
||||
log_info("Flags: <%s|%s>",
|
||||
flags & ND_RA_FLAG_OTHER ? "OTHER" : "",
|
||||
flags & ND_RA_FLAG_MANAGED ? "MANAGED" : "");
|
||||
@@ -218,7 +219,7 @@ static void router_dump(sd_ndisc_router *rt) {
|
||||
static int send_ra(uint8_t flags) {
|
||||
uint8_t advertisement[] = {
|
||||
/* struct nd_router_advert */
|
||||
0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
|
||||
0x86, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x00, 0xb4,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* type = 0x03 (SD_NDISC_OPTION_PREFIX_INFORMATION), length = 32 */
|
||||
0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
|
||||
@@ -235,6 +236,8 @@ static int send_ra(uint8_t flags) {
|
||||
0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* type = 0x01 (SD_NDISC_OPTION_SOURCE_LL_ADDRESS), length = 8 */
|
||||
0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
|
||||
/* type = 0x1a (SD_NDISC_OPTION_FLAGS_EXTENSION), length = 8 */
|
||||
0x1a, 0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
|
||||
};
|
||||
|
||||
advertisement[5] = flags;
|
||||
@@ -269,7 +272,7 @@ static void test_callback_ra(sd_ndisc *nd, sd_ndisc_event_t event, void *message
|
||||
router_dump(rt);
|
||||
|
||||
assert_se(sd_ndisc_router_get_flags(rt, &flags) >= 0);
|
||||
assert_se(flags == flags_array[idx]);
|
||||
ASSERT_EQ(flags & 0xff, flags_array[idx]);
|
||||
idx++;
|
||||
|
||||
log_debug("%s: Got event 0x%02" PRIx64, __func__, flags);
|
||||
@@ -404,7 +407,7 @@ TEST(rs) {
|
||||
static int send_ra_invalid_domain(uint8_t flags) {
|
||||
uint8_t advertisement[] = {
|
||||
/* struct nd_router_advert */
|
||||
0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
|
||||
0x86, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x00, 0xb4,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* type = 0x03 (SD_NDISC_OPTION_PREFIX_INFORMATION), length = 32 */
|
||||
0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
|
||||
@@ -432,6 +435,8 @@ static int send_ra_invalid_domain(uint8_t flags) {
|
||||
0xdb, 0x12, 0x9c, 0x75, 0x22, 0x5f, 0x12, 0x00,
|
||||
/* type = 0x01 (SD_NDISC_OPTION_SOURCE_LL_ADDRESS), length = 8 */
|
||||
0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
|
||||
/* type = 0x1a (SD_NDISC_OPTION_FLAGS_EXTENSION), length = 8 */
|
||||
0x1a, 0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
|
||||
};
|
||||
|
||||
advertisement[5] = flags;
|
||||
|
||||
Reference in New Issue
Block a user