From: Yu Watanabe Date: Tue, 5 Sep 2023 07:51:39 +0000 (+0900) Subject: sd-radv: make sd_radv always take timespan in usec X-Git-Tag: v255-rc1~468^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=eca280c8c099a0cfe90b47ed9b37d356c507535e;p=thirdparty%2Fsystemd.git sd-radv: make sd_radv always take timespan in usec --- diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h index af0be7a5b7c..d6cec904b03 100644 --- a/src/libsystemd-network/radv-internal.h +++ b/src/libsystemd-network/radv-internal.h @@ -42,6 +42,10 @@ #define RADV_MIN_ROUTER_LIFETIME_USEC RADV_MIN_MAX_TIMEOUT_USEC #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 4.2. + * Retrans Timer + * 32-bit unsigned integer. The time, in milliseconds. */ +#define RADV_MAX_RETRANSMIT_USEC (UINT32_MAX * USEC_PER_MSEC) /* draft-ietf-6man-slaac-renum-02 section 4.1.1. * AdvPreferredLifetime: max(AdvDefaultLifetime, 3 * MaxRtrAdvInterval) * AdvValidLifetime: 2 * AdvPreferredLifetime */ @@ -60,7 +64,14 @@ #define RADV_MAX_RA_DELAY_TIME_USEC (500 * USEC_PER_MSEC) /* From RFC 8781 section 4.1 * By default, the value of the Scaled Lifetime field SHOULD be set to the lesser of 3 x MaxRtrAdvInterval */ -#define RADV_DEFAULT_PRE64_LIFETIME_USEC (3 * RADV_DEFAULT_MAX_TIMEOUT_USEC) +#define RADV_PREF64_DEFAULT_LIFETIME_USEC (3 * RADV_DEFAULT_MAX_TIMEOUT_USEC) + +#define RADV_RDNSS_MAX_LIFETIME_USEC (UINT32_MAX * USEC_PER_SEC) +#define RADV_DNSSL_MAX_LIFETIME_USEC (UINT32_MAX * USEC_PER_SEC) +/* rfc6275 7.4 Neighbor Discovery Home Agent Lifetime. + * The default value is the same as the Router Lifetime. + * The maximum value corresponds to 18.2 hours. 0 MUST NOT be used. */ +#define RADV_HOME_AGENT_MAX_LIFETIME_USEC (UINT16_MAX * USEC_PER_SEC) #define RADV_OPT_ROUTE_INFORMATION 24 #define RADV_OPT_RDNSS 25 @@ -68,11 +79,6 @@ /* Pref64 option type (RFC8781, section 4) */ #define RADV_OPT_PREF64 38 -/* rfc6275 7.4 Neighbor Discovery Home Agent Lifetime. - * The default value is the same as the Router Lifetime - * The maximum value corresponds to 18.2 hours. value of 0 MUST NOT be used.*/ -#define RADV_MAX_HOME_AGENT_LIFETIME_USEC (65535 * USEC_PER_SEC) - enum RAdvState { RADV_STATE_IDLE = 0, RADV_STATE_ADVERTISING = 1, @@ -100,7 +106,7 @@ struct sd_radv { uint8_t hop_limit; uint8_t flags; uint32_t mtu; - uint32_t retransmit_msec; + usec_t retransmit_usec; usec_t lifetime_usec; /* timespan */ int fd; diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index 1226781637e..e77d4b4f596 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -169,10 +169,10 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_us adv.nd_ra_type = ND_ROUTER_ADVERT; adv.nd_ra_curhoplimit = ra->hop_limit; - adv.nd_ra_retransmit = htobe32(ra->retransmit_msec); + adv.nd_ra_retransmit = usec_to_be32_msec(ra->retransmit_usec); adv.nd_ra_flags_reserved = ra->flags; 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)); + adv.nd_ra_router_lifetime = usec_to_be16_sec(lifetime_usec); iov[msg.msg_iovlen++] = IOVEC_MAKE(&adv, sizeof(adv)); /* MAC address is optional, either because the link does not use L2 @@ -501,34 +501,35 @@ int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit) { return 0; } -int sd_radv_set_retransmit(sd_radv *ra, uint32_t retransmit_msec) { +int sd_radv_set_retransmit(sd_radv *ra, uint64_t usec) { assert_return(ra, -EINVAL); if (ra->state != RADV_STATE_IDLE) return -EBUSY; - ra->retransmit_msec = retransmit_msec; + if (usec > RADV_MAX_RETRANSMIT_USEC) + return -EINVAL; + ra->retransmit_usec = usec; return 0; } -int sd_radv_set_router_lifetime(sd_radv *ra, uint64_t lifetime_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(lifetime_usec)) + 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 (lifetime_usec == 0 && + if (usec == 0 && (ra->flags & (0x3 << 3)) != (SD_NDISC_PREFERENCE_MEDIUM << 3)) return -EINVAL; - ra->lifetime_usec = lifetime_usec; - + ra->lifetime_usec = usec; return 0; } @@ -593,14 +594,16 @@ int sd_radv_set_home_agent_preference(sd_radv *ra, uint16_t preference) { return 0; } -int sd_radv_set_home_agent_lifetime(sd_radv *ra, uint16_t lifetime) { +int sd_radv_set_home_agent_lifetime(sd_radv *ra, uint64_t lifetime_usec) { assert_return(ra, -EINVAL); if (ra->state != RADV_STATE_IDLE) return -EBUSY; - ra->home_agent.nd_opt_home_agent_info_lifetime = htobe16(lifetime); + if (lifetime_usec > RADV_HOME_AGENT_MAX_LIFETIME_USEC) + return -EINVAL; + ra->home_agent.nd_opt_home_agent_info_lifetime = usec_to_be16_sec(lifetime_usec); return 0; } @@ -851,7 +854,7 @@ int sd_radv_add_pref64_prefix(sd_radv *ra, sd_radv_pref64_prefix *p) { int sd_radv_set_rdnss( sd_radv *ra, - uint32_t lifetime, + uint64_t lifetime_usec, const struct in6_addr *dns, size_t n_dns) { @@ -861,6 +864,9 @@ int sd_radv_set_rdnss( assert_return(ra, -EINVAL); assert_return(n_dns < 128, -EINVAL); + if (lifetime_usec > RADV_RDNSS_MAX_LIFETIME_USEC) + return -EINVAL; + if (!dns || n_dns == 0) { ra->rdnss = mfree(ra->rdnss); ra->n_rdnss = 0; @@ -876,7 +882,7 @@ int sd_radv_set_rdnss( opt_rdnss->type = RADV_OPT_RDNSS; opt_rdnss->length = len / 8; - opt_rdnss->lifetime = htobe32(lifetime); + opt_rdnss->lifetime = usec_to_be32_sec(lifetime_usec); memcpy(opt_rdnss + 1, dns, n_dns * sizeof(struct in6_addr)); @@ -889,7 +895,7 @@ int sd_radv_set_rdnss( int sd_radv_set_dnssl( sd_radv *ra, - uint32_t lifetime, + uint64_t lifetime_usec, char **search_list) { _cleanup_free_ struct sd_radv_opt_dns *opt_dnssl = NULL; @@ -898,6 +904,9 @@ int sd_radv_set_dnssl( assert_return(ra, -EINVAL); + if (lifetime_usec > RADV_DNSSL_MAX_LIFETIME_USEC) + return -EINVAL; + if (strv_isempty(search_list)) { ra->dnssl = mfree(ra->dnssl); return 0; @@ -914,7 +923,7 @@ int sd_radv_set_dnssl( opt_dnssl->type = RADV_OPT_DNSSL; opt_dnssl->length = len / 8; - opt_dnssl->lifetime = htobe32(lifetime); + opt_dnssl->lifetime = usec_to_be32_sec(lifetime_usec); p = (uint8_t *)(opt_dnssl + 1); len -= sizeof(struct sd_radv_opt_dns); @@ -1134,7 +1143,7 @@ int sd_radv_pref64_prefix_set_prefix( if (r < 0) return log_radv_errno(NULL, r, "Unsupported PREF64 prefix length %u. Valid lengths are 32, 40, 48, 56, 64 and 96", prefixlen); - if (lifetime_usec == USEC_INFINITY || DIV_ROUND_UP(lifetime_usec, 8 * USEC_PER_SEC) >= UINT64_C(1) << 13) + if (lifetime_usec > PREF64_MAX_LIFETIME_USEC) return -EINVAL; /* RFC 8781 - 4.1 rounding up lifetime to multiply of 8 */ diff --git a/src/libsystemd-network/test-ndisc-ra.c b/src/libsystemd-network/test-ndisc-ra.c index 18004f64665..6f4619943c1 100644 --- a/src/libsystemd-network/test-ndisc-ra.c +++ b/src/libsystemd-network/test-ndisc-ra.c @@ -193,15 +193,15 @@ TEST(radv) { assert_se(sd_radv_set_rdnss(NULL, 0, NULL, 0) < 0); assert_se(sd_radv_set_rdnss(ra, 0, NULL, 0) >= 0); assert_se(sd_radv_set_rdnss(ra, 0, NULL, 128) < 0); - assert_se(sd_radv_set_rdnss(ra, 600, &test_rdnss, 0) >= 0); - assert_se(sd_radv_set_rdnss(ra, 600, &test_rdnss, 1) >= 0); + assert_se(sd_radv_set_rdnss(ra, 600 * USEC_PER_SEC, &test_rdnss, 0) >= 0); + assert_se(sd_radv_set_rdnss(ra, 600 * USEC_PER_SEC, &test_rdnss, 1) >= 0); assert_se(sd_radv_set_rdnss(ra, 0, &test_rdnss, 1) >= 0); assert_se(sd_radv_set_rdnss(ra, 0, NULL, 0) >= 0); assert_se(sd_radv_set_dnssl(ra, 0, NULL) >= 0); - assert_se(sd_radv_set_dnssl(ra, 600, NULL) >= 0); + assert_se(sd_radv_set_dnssl(ra, 600 * USEC_PER_SEC, NULL) >= 0); assert_se(sd_radv_set_dnssl(ra, 0, (char **)test_dnssl) >= 0); - assert_se(sd_radv_set_dnssl(ra, 600, (char **)test_dnssl) >= 0); + assert_se(sd_radv_set_dnssl(ra, 600 * USEC_PER_SEC, (char **)test_dnssl) >= 0); ra = sd_radv_unref(ra); assert_se(!ra); @@ -273,8 +273,8 @@ TEST(ra) { 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); - assert_se(sd_radv_set_rdnss(ra, 60, &test_rdnss, 1) >= 0); - assert_se(sd_radv_set_dnssl(ra, 60, (char **)test_dnssl) >= 0); + assert_se(sd_radv_set_rdnss(ra, 60 * USEC_PER_SEC, &test_rdnss, 1) >= 0); + assert_se(sd_radv_set_dnssl(ra, 60 * USEC_PER_SEC, (char **)test_dnssl) >= 0); for (unsigned i = 0; i < ELEMENTSOF(prefix); i++) { sd_radv_prefix *p; diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index d6a8d36152b..80c0fe43a84 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -222,7 +222,7 @@ static int pref64_prefix_new_static(Network *network, const char *filename, unsi .network = network, .section = TAKE_PTR(n), - .lifetime = RADV_DEFAULT_PRE64_LIFETIME_USEC, + .lifetime = RADV_PREF64_DEFAULT_LIFETIME_USEC, }; r = hashmap_ensure_put(&network->pref64_prefixes_by_section, &config_section_hash_ops, prefix->section, prefix); @@ -279,19 +279,6 @@ int link_request_radv_addresses(Link *link) { return 0; } -static uint32_t usec_to_lifetime(usec_t usec) { - uint64_t t; - - if (usec == USEC_INFINITY) - return UINT32_MAX; - - t = DIV_ROUND_UP(usec, USEC_PER_SEC); - if (t >= UINT32_MAX) - return UINT32_MAX; - - return (uint32_t) t; -} - static int radv_set_prefix(Link *link, Prefix *prefix) { _cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL; int r; @@ -446,7 +433,7 @@ static int radv_set_dns(Link *link, Link *uplink) { set_dns: return sd_radv_set_rdnss(link->radv, - usec_to_lifetime(link->network->router_dns_lifetime_usec), + link->network->router_dns_lifetime_usec, dns, n_dns); } @@ -482,7 +469,7 @@ set_domains: return log_oom(); return sd_radv_set_dnssl(link->radv, - usec_to_lifetime(link->network->router_dns_lifetime_usec), + link->network->router_dns_lifetime_usec, s); } @@ -567,7 +554,7 @@ static int radv_configure(Link *link) { } if (link->network->router_retransmit_usec > 0) { - r = sd_radv_set_retransmit(link->radv, DIV_ROUND_UP(link->network->router_retransmit_usec, USEC_PER_MSEC)); + r = sd_radv_set_retransmit(link->radv, link->network->router_retransmit_usec); if (r < 0) return r; } @@ -608,7 +595,7 @@ static int radv_configure(Link *link) { if (r < 0) return r; - r = sd_radv_set_home_agent_lifetime(link->radv, DIV_ROUND_UP(link->network->home_agent_lifetime_usec, USEC_PER_SEC)); + r = sd_radv_set_home_agent_lifetime(link->radv, link->network->home_agent_lifetime_usec); if (r < 0) return r; @@ -1545,9 +1532,9 @@ int config_parse_router_retransmit( } if (usec != USEC_INFINITY && - DIV_ROUND_UP(usec, USEC_PER_MSEC) > UINT32_MAX) { + usec > RADV_MAX_RETRANSMIT_USEC) { log_syntax(unit, LOG_WARNING, filename, line, 0, - "Invalid %s= must be in the range 0...%"PRIu32"Sec, ignoring: %s", lvalue, UINT32_MAX, rvalue); + "Invalid [%s] %s=, ignoring assignment: %s", section, lvalue, rvalue); return 0; } @@ -1621,10 +1608,9 @@ int config_parse_router_home_agent_lifetime( } if (usec == USEC_INFINITY || usec == 0 || - DIV_ROUND_UP(usec, USEC_PER_SEC) > RADV_MAX_HOME_AGENT_LIFETIME_USEC) { + usec > RADV_HOME_AGENT_MAX_LIFETIME_USEC) { log_syntax(unit, LOG_WARNING, filename, line, 0, - "Invalid %s= must be in the range 1…%s, ignoring: %s", lvalue, - FORMAT_TIMESPAN(RADV_MAX_HOME_AGENT_LIFETIME_USEC, USEC_PER_SEC), rvalue); + "Invalid [%s] %s=, ignoring assignment: %s", section, lvalue, rvalue); return 0; } diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h index 295b8846f5a..8ea0838ee65 100644 --- a/src/systemd/sd-radv.h +++ b/src/systemd/sd-radv.h @@ -54,8 +54,8 @@ int sd_radv_get_ifname(sd_radv *ra, const char **ret); int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr); 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, uint32_t retransmit_msec); -int sd_radv_set_router_lifetime(sd_radv *ra, uint64_t lifetime_usec); +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); @@ -63,9 +63,9 @@ 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); void sd_radv_remove_prefix(sd_radv *ra, const struct in6_addr *prefix, unsigned char prefixlen); -int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime, +int sd_radv_set_rdnss(sd_radv *ra, uint64_t lifetime_usec, const struct in6_addr *dns, size_t n_dns); -int sd_radv_set_dnssl(sd_radv *ra, uint32_t lifetime, char **search_list); +int sd_radv_set_dnssl(sd_radv *ra, uint64_t lifetime_usec, char **search_list); /* Advertised prefixes */ int sd_radv_prefix_new(sd_radv_prefix **ret); @@ -98,7 +98,7 @@ sd_radv_pref64_prefix *sd_radv_pref64_prefix_unref(sd_radv_pref64_prefix *ra); /* Mobile IPv6 extension: Home Agent Info. */ int sd_radv_set_home_agent_information(sd_radv *ra, int home_agent); int sd_radv_set_home_agent_preference(sd_radv *ra, uint16_t preference); -int sd_radv_set_home_agent_lifetime(sd_radv *ra, uint16_t lifetime); +int sd_radv_set_home_agent_lifetime(sd_radv *ra, uint64_t usec); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv, sd_radv_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_prefix, sd_radv_prefix_unref);