summaryrefslogtreecommitdiff
path: root/src/libsystemd-network
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-10-25 01:21:22 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2021-10-27 19:27:07 +0900
commit0945767012413d4212df25370a14286fa1425d10 (patch)
treeb60ba55c89ae3e6ea530327a2185e6f9f8b146e4 /src/libsystemd-network
parent72db0a714b3fe181d06cccaae27d62b92ea5c196 (diff)
downloadsystemd-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.h2
-rw-r--r--src/libsystemd-network/sd-radv.c24
-rw-r--r--src/libsystemd-network/test-ndisc-ra.c8
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);