From: Yu Watanabe Date: Mon, 15 Apr 2024 03:04:23 +0000 (+0900) Subject: sd-radv: set router preference gracefully X-Git-Tag: v256-rc1~104^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F32346%2Fhead;p=thirdparty%2Fsystemd.git sd-radv: set router preference gracefully Rather than refusing to set non-zero preference, when lifetime is zero, let's handle that gracefully on send. --- diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h index d2ec912d496..cf3fe9e226e 100644 --- a/src/libsystemd-network/radv-internal.h +++ b/src/libsystemd-network/radv-internal.h @@ -106,6 +106,7 @@ struct sd_radv { struct ether_addr mac_addr; uint8_t hop_limit; uint8_t flags; + uint8_t preference; uint32_t mtu; usec_t retransmit_usec; usec_t lifetime_usec; /* timespan */ diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index 0709a55c138..e6c375f311e 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -201,7 +201,9 @@ static int radv_send_router(sd_radv *ra, const struct in6_addr *dst) { /* The nd_ra_curhoplimit and nd_ra_flags_reserved fields cannot specified with nd_ra_router_lifetime * simultaneously in the structured initializer in the above. */ adv.nd_ra_curhoplimit = ra->hop_limit; - adv.nd_ra_flags_reserved = ra->flags; + /* RFC 4191, Section 2.2, + * "...If the Router Lifetime is zero, the preference value MUST be set to (00) by the sender..." */ + adv.nd_ra_flags_reserved = ra->flags | (ra->lifetime_usec > 0 ? (ra->preference << 3) : 0); iov[msg.msg_iovlen++] = IOVEC_MAKE(&adv, sizeof(adv)); /* MAC address is optional, either because the link does not use L2 addresses or load sharing is @@ -554,12 +556,6 @@ int sd_radv_set_router_lifetime(sd_radv *ra, uint64_t usec) { if (!router_lifetime_is_valid(usec)) return -EINVAL; - /* RFC 4191, Section 2.2, "...If the Router Lifetime is zero, the preference value MUST be set - * to (00) by the sender..." */ - if (usec == 0 && - (ra->flags & (0x3 << 3)) != (SD_NDISC_PREFERENCE_MEDIUM << 3)) - return -EINVAL; - ra->lifetime_usec = usec; return 0; } @@ -578,20 +574,14 @@ int sd_radv_set_other_information(sd_radv *ra, int b) { return 0; } -int sd_radv_set_preference(sd_radv *ra, unsigned preference) { +int sd_radv_set_preference(sd_radv *ra, uint8_t preference) { assert_return(ra, -EINVAL); assert_return(IN_SET(preference, SD_NDISC_PREFERENCE_LOW, SD_NDISC_PREFERENCE_MEDIUM, SD_NDISC_PREFERENCE_HIGH), -EINVAL); - /* RFC 4191, Section 2.2, "...If the Router Lifetime is zero, the preference value MUST be set - * to (00) by the sender..." */ - if (ra->lifetime_usec == 0 && preference != SD_NDISC_PREFERENCE_MEDIUM) - return -EINVAL; - - ra->flags = (ra->flags & ~(0x3 << 3)) | (preference << 3); - + ra->preference = preference; return 0; } diff --git a/src/libsystemd-network/test-ndisc-ra.c b/src/libsystemd-network/test-ndisc-ra.c index c63d9dfdabf..78635ee6576 100644 --- a/src/libsystemd-network/test-ndisc-ra.c +++ b/src/libsystemd-network/test-ndisc-ra.c @@ -191,12 +191,6 @@ TEST(radv) { assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_HIGH) >= 0); ASSERT_RETURN_EXPECTED_SE(sd_radv_set_preference(ra, ~0) < 0); - assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_HIGH) >= 0); - assert_se(sd_radv_set_router_lifetime(ra, 300 * USEC_PER_SEC) >= 0); - assert_se(sd_radv_set_router_lifetime(ra, 0) < 0); - assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_MEDIUM) >= 0); - assert_se(sd_radv_set_router_lifetime(ra, 0) >= 0); - ASSERT_RETURN_EXPECTED_SE(sd_radv_set_managed_information(NULL, true) < 0); assert_se(sd_radv_set_managed_information(ra, true) >= 0); assert_se(sd_radv_set_managed_information(ra, false) >= 0); diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h index 2538f2ab6fa..55b123973e9 100644 --- a/src/systemd/sd-radv.h +++ b/src/systemd/sd-radv.h @@ -60,7 +60,7 @@ int sd_radv_set_retransmit(sd_radv *ra, uint64_t usec); int sd_radv_set_router_lifetime(sd_radv *ra, uint64_t usec); int sd_radv_set_managed_information(sd_radv *ra, int b); int sd_radv_set_other_information(sd_radv *ra, int b); -int sd_radv_set_preference(sd_radv *ra, unsigned preference); +int sd_radv_set_preference(sd_radv *ra, uint8_t preference); int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p); int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p); int sd_radv_add_pref64_prefix(sd_radv *ra, sd_radv_pref64_prefix *p);