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:
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user