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.
This commit is contained in:
Yu Watanabe
2024-04-19 11:44:59 +09:00
parent 03401969d4
commit ba5dc3afad
4 changed files with 7 additions and 22 deletions
+1
View File
@@ -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 */
+5 -15
View File
@@ -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;
}
-6
View File
@@ -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);
+1 -1
View File
@@ -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);