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.
This commit is contained in:
committed by
Luca Boccassi
parent
1299c9cc9e
commit
b628909430
@@ -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)
|
if (opt[0] != SD_NDISC_OPTION_FLAGS_EXTENSION)
|
||||||
return -EBADMSG;
|
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);
|
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)
|
if (!buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
unaligned_write_be64(buf, (option->extended_flags & UINT64_C(0x00ffffffffffff00)) << 8);
|
|
||||||
buf[0] = SD_NDISC_OPTION_FLAGS_EXTENSION;
|
buf[0] = SD_NDISC_OPTION_FLAGS_EXTENSION;
|
||||||
buf[1] = 1;
|
buf[1] = 1;
|
||||||
|
|
||||||
|
for (size_t i = 2; i < 8; i++)
|
||||||
|
buf[i] = (option->extended_flags >> ((i - 1) * 8)) & 0xff;
|
||||||
|
|
||||||
*ret = TAKE_PTR(buf);
|
*ret = TAKE_PTR(buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ static void router_dump(sd_ndisc_router *rt) {
|
|||||||
log_info("Hop limit: %u", hop_limit);
|
log_info("Hop limit: %u", hop_limit);
|
||||||
|
|
||||||
assert_se(sd_ndisc_router_get_flags(rt, &flags) >= 0);
|
assert_se(sd_ndisc_router_get_flags(rt, &flags) >= 0);
|
||||||
|
ASSERT_EQ(flags & UINT64_C(0x00ffffffffffff00), UINT64_C(0x0066554433221100));
|
||||||
log_info("Flags: <%s|%s>",
|
log_info("Flags: <%s|%s>",
|
||||||
flags & ND_RA_FLAG_OTHER ? "OTHER" : "",
|
flags & ND_RA_FLAG_OTHER ? "OTHER" : "",
|
||||||
flags & ND_RA_FLAG_MANAGED ? "MANAGED" : "");
|
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) {
|
static int send_ra(uint8_t flags) {
|
||||||
uint8_t advertisement[] = {
|
uint8_t advertisement[] = {
|
||||||
/* struct nd_router_advert */
|
/* 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,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
/* type = 0x03 (SD_NDISC_OPTION_PREFIX_INFORMATION), length = 32 */
|
/* type = 0x03 (SD_NDISC_OPTION_PREFIX_INFORMATION), length = 32 */
|
||||||
0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
|
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,
|
0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
/* type = 0x01 (SD_NDISC_OPTION_SOURCE_LL_ADDRESS), length = 8 */
|
/* type = 0x01 (SD_NDISC_OPTION_SOURCE_LL_ADDRESS), length = 8 */
|
||||||
0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
|
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;
|
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);
|
router_dump(rt);
|
||||||
|
|
||||||
assert_se(sd_ndisc_router_get_flags(rt, &flags) >= 0);
|
assert_se(sd_ndisc_router_get_flags(rt, &flags) >= 0);
|
||||||
assert_se(flags == flags_array[idx]);
|
ASSERT_EQ(flags & 0xff, flags_array[idx]);
|
||||||
idx++;
|
idx++;
|
||||||
|
|
||||||
log_debug("%s: Got event 0x%02" PRIx64, __func__, flags);
|
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) {
|
static int send_ra_invalid_domain(uint8_t flags) {
|
||||||
uint8_t advertisement[] = {
|
uint8_t advertisement[] = {
|
||||||
/* struct nd_router_advert */
|
/* 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,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
/* type = 0x03 (SD_NDISC_OPTION_PREFIX_INFORMATION), length = 32 */
|
/* type = 0x03 (SD_NDISC_OPTION_PREFIX_INFORMATION), length = 32 */
|
||||||
0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
|
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,
|
0xdb, 0x12, 0x9c, 0x75, 0x22, 0x5f, 0x12, 0x00,
|
||||||
/* type = 0x01 (SD_NDISC_OPTION_SOURCE_LL_ADDRESS), length = 8 */
|
/* type = 0x01 (SD_NDISC_OPTION_SOURCE_LL_ADDRESS), length = 8 */
|
||||||
0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
|
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;
|
advertisement[5] = flags;
|
||||||
|
|||||||
Reference in New Issue
Block a user