sd-radv: router lifetime must be 0 or between 4 seconds and 9000 seconds
See RFC 4861 section 6.2.1.
This commit is contained in:
@@ -34,6 +34,8 @@
|
||||
* point-to-point link the peers may have enough information about the number and status of devices at
|
||||
* the other end so that advertisements are needed less frequently.
|
||||
* Default: 3 * MaxRtrAdvInterval */
|
||||
#define RADV_MIN_ROUTER_LIFETIME_USEC (4 * USEC_PER_SEC)
|
||||
#define RADV_MAX_ROUTER_LIFETIME_USEC (9000 * USEC_PER_SEC)
|
||||
#define RADV_DEFAULT_ROUTER_LIFETIME_USEC (3 * RADV_DEFAULT_MAX_TIMEOUT_USEC)
|
||||
/* RFC 4861 section 10.
|
||||
* MAX_INITIAL_RTR_ADVERT_INTERVAL 16 seconds
|
||||
|
||||
@@ -129,6 +129,12 @@ static sd_radv *radv_free(sd_radv *ra) {
|
||||
|
||||
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv, sd_radv, radv_free);
|
||||
|
||||
static bool router_lifetime_is_valid(usec_t lifetime_usec) {
|
||||
return lifetime_usec == 0 ||
|
||||
(lifetime_usec >= RADV_MIN_ROUTER_LIFETIME_USEC &&
|
||||
lifetime_usec <= RADV_MAX_ROUTER_LIFETIME_USEC);
|
||||
}
|
||||
|
||||
static int radv_send(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_usec) {
|
||||
sd_radv_route_prefix *rt;
|
||||
sd_radv_prefix *p;
|
||||
@@ -159,31 +165,24 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_us
|
||||
.msg_namelen = sizeof(dst_addr),
|
||||
.msg_iov = iov,
|
||||
};
|
||||
uint16_t lifetime_sec;
|
||||
usec_t time_now;
|
||||
int r;
|
||||
|
||||
assert(ra);
|
||||
assert(router_lifetime_is_valid(lifetime_usec));
|
||||
|
||||
r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* a value of UINT16_MAX represents infinity, 0x0 means this host is not a router */
|
||||
if (lifetime_usec == USEC_INFINITY)
|
||||
lifetime_sec = UINT16_MAX;
|
||||
else if (lifetime_usec > (UINT16_MAX - 1) * USEC_PER_SEC)
|
||||
lifetime_sec = UINT16_MAX - 1;
|
||||
else
|
||||
lifetime_sec = DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC);
|
||||
|
||||
if (dst && in6_addr_is_set(dst))
|
||||
dst_addr.sin6_addr = *dst;
|
||||
|
||||
adv.nd_ra_type = ND_ROUTER_ADVERT;
|
||||
adv.nd_ra_curhoplimit = ra->hop_limit;
|
||||
adv.nd_ra_flags_reserved = ra->flags;
|
||||
adv.nd_ra_router_lifetime = htobe16(lifetime_sec);
|
||||
assert_cc(RADV_MAX_ROUTER_LIFETIME_USEC <= UINT16_MAX * USEC_PER_SEC);
|
||||
adv.nd_ra_router_lifetime = htobe16(DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC));
|
||||
iov[msg.msg_iovlen++] = IOVEC_MAKE(&adv, sizeof(adv));
|
||||
|
||||
/* MAC address is optional, either because the link does not use L2
|
||||
@@ -504,11 +503,14 @@ _public_ int sd_radv_set_router_lifetime(sd_radv *ra, uint64_t lifetime_usec) {
|
||||
if (ra->state != RADV_STATE_IDLE)
|
||||
return -EBUSY;
|
||||
|
||||
if (!router_lifetime_is_valid(lifetime_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 (lifetime_usec == 0 &&
|
||||
(ra->flags & (0x3 << 3)) != (SD_NDISC_PREFERENCE_MEDIUM << 3))
|
||||
return -ETIME;
|
||||
return -EINVAL;
|
||||
|
||||
ra->lifetime_usec = lifetime_usec;
|
||||
|
||||
|
||||
@@ -180,7 +180,9 @@ static void test_radv(void) {
|
||||
|
||||
assert_se(sd_radv_set_router_lifetime(NULL, 0) < 0);
|
||||
assert_se(sd_radv_set_router_lifetime(ra, 0) >= 0);
|
||||
assert_se(sd_radv_set_router_lifetime(ra, ~0) >= 0);
|
||||
assert_se(sd_radv_set_router_lifetime(ra, USEC_INFINITY) < 0);
|
||||
assert_se(sd_radv_set_router_lifetime(ra, USEC_PER_YEAR) < 0);
|
||||
assert_se(sd_radv_set_router_lifetime(ra, 300 * USEC_PER_SEC) >= 0);
|
||||
|
||||
assert_se(sd_radv_set_preference(NULL, 0) < 0);
|
||||
assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_LOW) >= 0);
|
||||
@@ -189,7 +191,7 @@ static void test_radv(void) {
|
||||
assert_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, 42000) >= 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);
|
||||
@@ -308,7 +310,7 @@ static void test_ra(void) {
|
||||
|
||||
assert_se(sd_radv_set_ifindex(ra, 42) >= 0);
|
||||
assert_se(sd_radv_set_mac(ra, &mac_addr) >= 0);
|
||||
assert_se(sd_radv_set_router_lifetime(ra, 180) >= 0);
|
||||
assert_se(sd_radv_set_router_lifetime(ra, 180 * USEC_PER_SEC) >= 0);
|
||||
assert_se(sd_radv_set_hop_limit(ra, 64) >= 0);
|
||||
assert_se(sd_radv_set_managed_information(ra, true) >= 0);
|
||||
assert_se(sd_radv_set_other_information(ra, true) >= 0);
|
||||
|
||||
Reference in New Issue
Block a user