summaryrefslogtreecommitdiff
path: root/src/libsystemd-network/sd-radv.c
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/sd-radv.c
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/sd-radv.c')
-rw-r--r--src/libsystemd-network/sd-radv.c24
1 files changed, 13 insertions, 11 deletions
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;