diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-10-25 01:21:22 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-10-27 19:27:07 +0900 |
commit | 0945767012413d4212df25370a14286fa1425d10 (patch) | |
tree | b60ba55c89ae3e6ea530327a2185e6f9f8b146e4 /src/libsystemd-network | |
parent | 72db0a714b3fe181d06cccaae27d62b92ea5c196 (diff) | |
download | systemd-0945767012413d4212df25370a14286fa1425d10.tar.gz |
sd-radv: router lifetime must be 0 or between 4 seconds and 9000 seconds
See RFC 4861 section 6.2.1.
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r-- | src/libsystemd-network/radv-internal.h | 2 | ||||
-rw-r--r-- | src/libsystemd-network/sd-radv.c | 24 | ||||
-rw-r--r-- | src/libsystemd-network/test-ndisc-ra.c | 8 |
3 files changed, 20 insertions, 14 deletions
diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h index 6d8ad60b48..1f1c248c0a 100644 --- a/src/libsystemd-network/radv-internal.h +++ b/src/libsystemd-network/radv-internal.h @@ -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 diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index 0468b5268f..823b6f40e0 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -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; diff --git a/src/libsystemd-network/test-ndisc-ra.c b/src/libsystemd-network/test-ndisc-ra.c index 4713bc99b5..45902862d3 100644 --- a/src/libsystemd-network/test-ndisc-ra.c +++ b/src/libsystemd-network/test-ndisc-ra.c @@ -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); |