diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h index d2ec912d49..cf3fe9e226 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 cc8d144e6d..f5f3c9656c 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 @@ -541,23 +543,13 @@ int sd_radv_set_mtu(sd_radv *ra, uint32_t mtu) { int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit) { assert_return(ra, -EINVAL); - if (ra->state != RADV_STATE_IDLE) - return -EBUSY; - ra->hop_limit = hop_limit; - return 0; } int sd_radv_set_retransmit(sd_radv *ra, uint64_t usec) { assert_return(ra, -EINVAL); - if (ra->state != RADV_STATE_IDLE) - return -EBUSY; - - if (usec > RADV_MAX_RETRANSMIT_USEC) - return -EINVAL; - ra->retransmit_usec = usec; return 0; } @@ -565,58 +557,35 @@ int sd_radv_set_retransmit(sd_radv *ra, uint64_t usec) { int sd_radv_set_router_lifetime(sd_radv *ra, uint64_t usec) { assert_return(ra, -EINVAL); - if (ra->state != RADV_STATE_IDLE) - return -EBUSY; - 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; } -int sd_radv_set_managed_information(sd_radv *ra, int managed) { +int sd_radv_set_managed_information(sd_radv *ra, int b) { assert_return(ra, -EINVAL); - if (ra->state != RADV_STATE_IDLE) - return -EBUSY; - - SET_FLAG(ra->flags, ND_RA_FLAG_MANAGED, managed); - + SET_FLAG(ra->flags, ND_RA_FLAG_MANAGED, b); return 0; } -int sd_radv_set_other_information(sd_radv *ra, int other) { +int sd_radv_set_other_information(sd_radv *ra, int b) { assert_return(ra, -EINVAL); - if (ra->state != RADV_STATE_IDLE) - return -EBUSY; - - SET_FLAG(ra->flags, ND_RA_FLAG_OTHER, other); - + SET_FLAG(ra->flags, ND_RA_FLAG_OTHER, 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 76f4d7ba3f..78635ee657 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); @@ -208,7 +202,7 @@ TEST(radv) { ASSERT_RETURN_EXPECTED_SE(sd_radv_set_retransmit(NULL, 10 * USEC_PER_MSEC) < 0); assert_se(sd_radv_set_retransmit(ra, 10 * USEC_PER_MSEC) >= 0); assert_se(sd_radv_set_retransmit(ra, 0) >= 0); - assert_se(sd_radv_set_retransmit(ra, usec_add(UINT32_MAX * USEC_PER_MSEC, USEC_PER_MSEC)) < 0); + assert_se(sd_radv_set_retransmit(ra, USEC_INFINITY) >= 0); ASSERT_RETURN_EXPECTED_SE(sd_radv_set_rdnss(NULL, 0, NULL, 0) < 0); assert_se(sd_radv_set_rdnss(ra, 0, NULL, 0) >= 0); diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h index 32ea3bd4ed..f25622fceb 100644 --- a/src/systemd/sd-radv.h +++ b/src/systemd/sd-radv.h @@ -59,9 +59,9 @@ int sd_radv_set_mtu(sd_radv *ra, uint32_t mtu); int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit); 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 managed); -int sd_radv_set_other_information(sd_radv *ra, int other); -int sd_radv_set_preference(sd_radv *ra, unsigned preference); +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, 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);