From 7ebb14313f50e51887d9440fb35ce74472565b20 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 27 Sep 2021 21:05:07 +0900 Subject: [PATCH 1/6] sd-radv: rename sd_radv_prefix_set_route_prefix() -> sd_radv_route_prefix_set_prefix() --- src/libsystemd-network/sd-radv.c | 2 +- src/network/networkd-radv.c | 2 +- src/systemd/sd-radv.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index ae33894302..2d91a406f8 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -936,7 +936,7 @@ _public_ int sd_radv_route_prefix_new(sd_radv_route_prefix **ret) { DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_route_prefix, sd_radv_route_prefix, mfree); -_public_ int sd_radv_prefix_set_route_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, +_public_ int sd_radv_route_prefix_set_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, unsigned char prefixlen) { assert_return(p, -EINVAL); assert_return(in6_addr, -EINVAL); diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 34e6a41c34..471f6d78e8 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -952,7 +952,7 @@ int config_parse_route_prefix( return 0; } - r = sd_radv_prefix_set_route_prefix(p->radv_route_prefix, &in6addr.in6, prefixlen); + r = sd_radv_route_prefix_set_prefix(p->radv_route_prefix, &in6addr.in6, prefixlen); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to set route prefix, ignoring assignment: %m"); return 0; diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h index 6bf56def40..f597c2c33d 100644 --- a/src/systemd/sd-radv.h +++ b/src/systemd/sd-radv.h @@ -91,7 +91,7 @@ int sd_radv_route_prefix_new(sd_radv_route_prefix **ret); sd_radv_route_prefix *sd_radv_route_prefix_ref(sd_radv_route_prefix *ra); sd_radv_route_prefix *sd_radv_route_prefix_unref(sd_radv_route_prefix *ra); -int sd_radv_prefix_set_route_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, unsigned char prefixlen); +int sd_radv_route_prefix_set_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, unsigned char prefixlen); int sd_radv_route_prefix_set_lifetime(sd_radv_route_prefix *p, uint32_t valid_lifetime); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv, sd_radv_unref); From 2ac416790035898b6568320c457ddb12f41ada23 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 27 Sep 2021 21:07:27 +0900 Subject: [PATCH 2/6] network: radv: make conf parsers not set values into sd_radv_prefix/sd_radv_route_prefix Preparation for later commits. --- src/network/networkd-network-gperf.gperf | 6 +- src/network/networkd-radv.c | 326 +++++++++++------------ src/network/networkd-radv.h | 15 +- 3 files changed, 168 insertions(+), 179 deletions(-) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index b670038d2a..a207e374d5 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -342,11 +342,11 @@ IPv6SendRA.Domains, config_parse_radv_search_domains, IPv6SendRA.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec) IPv6SendRA.UplinkInterface, config_parse_uplink, 0, 0 IPv6Prefix.Prefix, config_parse_prefix, 0, 0 -IPv6Prefix.OnLink, config_parse_prefix_flags, 0, 0 -IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_flags, 0, 0 +IPv6Prefix.OnLink, config_parse_prefix_boolean, 0, 0 +IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_boolean, 0, 0 IPv6Prefix.ValidLifetimeSec, config_parse_prefix_lifetime, 0, 0 IPv6Prefix.PreferredLifetimeSec, config_parse_prefix_lifetime, 0, 0 -IPv6Prefix.Assign, config_parse_prefix_assign, 0, 0 +IPv6Prefix.Assign, config_parse_prefix_boolean, 0, 0 IPv6Prefix.RouteMetric, config_parse_prefix_metric, 0, 0 IPv6Prefix.Token, config_parse_prefix_token, 0, 0 IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0 diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 471f6d78e8..5475ed787e 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -68,7 +68,6 @@ Prefix *prefix_free(Prefix *prefix) { } network_config_section_free(prefix->section); - sd_radv_prefix_unref(prefix->radv_prefix); set_free(prefix->tokens); return mfree(prefix); @@ -76,21 +75,6 @@ Prefix *prefix_free(Prefix *prefix) { DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free); -static int prefix_new(Prefix **ret) { - _cleanup_(prefix_freep) Prefix *prefix = NULL; - - prefix = new0(Prefix, 1); - if (!prefix) - return -ENOMEM; - - if (sd_radv_prefix_new(&prefix->radv_prefix) < 0) - return -ENOMEM; - - *ret = TAKE_PTR(prefix); - - return 0; -} - static int prefix_new_static(Network *network, const char *filename, unsigned section_line, Prefix **ret) { _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; _cleanup_(prefix_freep) Prefix *prefix = NULL; @@ -111,19 +95,25 @@ static int prefix_new_static(Network *network, const char *filename, unsigned se return 0; } - r = prefix_new(&prefix); - if (r < 0) - return r; + prefix = new(Prefix, 1); + if (!prefix) + return -ENOMEM; - prefix->network = network; - prefix->section = TAKE_PTR(n); + *prefix = (Prefix) { + .network = network, + .section = TAKE_PTR(n), + + .preferred_lifetime = 7 * USEC_PER_DAY, + .valid_lifetime = 30 * USEC_PER_DAY, + .onlink = true, + .address_auto_configuration = true, + }; r = hashmap_ensure_put(&network->prefixes_by_section, &network_config_hash_ops, prefix->section, prefix); if (r < 0) return r; *ret = TAKE_PTR(prefix); - return 0; } @@ -137,28 +127,12 @@ RoutePrefix *route_prefix_free(RoutePrefix *prefix) { } network_config_section_free(prefix->section); - sd_radv_route_prefix_unref(prefix->radv_route_prefix); return mfree(prefix); } DEFINE_NETWORK_SECTION_FUNCTIONS(RoutePrefix, route_prefix_free); -static int route_prefix_new(RoutePrefix **ret) { - _cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL; - - prefix = new0(RoutePrefix, 1); - if (!prefix) - return -ENOMEM; - - if (sd_radv_route_prefix_new(&prefix->radv_route_prefix) < 0) - return -ENOMEM; - - *ret = TAKE_PTR(prefix); - - return 0; -} - static int route_prefix_new_static(Network *network, const char *filename, unsigned section_line, RoutePrefix **ret) { _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; _cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL; @@ -179,19 +153,22 @@ static int route_prefix_new_static(Network *network, const char *filename, unsig return 0; } - r = route_prefix_new(&prefix); - if (r < 0) - return r; + prefix = new(RoutePrefix, 1); + if (!prefix) + return -ENOMEM; - prefix->network = network; - prefix->section = TAKE_PTR(n); + *prefix = (RoutePrefix) { + .network = network, + .section = TAKE_PTR(n), + + .lifetime = 7 * USEC_PER_DAY, + }; r = hashmap_ensure_put(&network->route_prefixes_by_section, &network_config_hash_ops, prefix->section, prefix); if (r < 0) return r; *ret = TAKE_PTR(prefix); - return 0; } @@ -206,28 +183,23 @@ int link_request_radv_addresses(Link *link) { HASHMAP_FOREACH(p, link->network->prefixes_by_section) { _cleanup_set_free_ Set *addresses = NULL; - struct in6_addr prefix, *a; - uint8_t prefixlen; + struct in6_addr *a; if (!p->assign) continue; - r = sd_radv_prefix_get_prefix(p->radv_prefix, &prefix, &prefixlen); - if (r < 0) - return r; - /* radv_generate_addresses() below requires the prefix length <= 64. */ - if (prefixlen > 64) { + if (p->prefixlen > 64) { _cleanup_free_ char *str = NULL; - (void) in6_addr_prefix_to_string(&prefix, prefixlen, &str); + (void) in6_addr_prefix_to_string(&p->prefix, p->prefixlen, &str); log_link_debug(link, "Prefix is longer than 64, refusing to assign an address in %s.", strna(str)); continue; } - r = radv_generate_addresses(link, p->tokens, &prefix, prefixlen, &addresses); + r = radv_generate_addresses(link, p->tokens, &p->prefix, p->prefixlen, &addresses); if (r < 0) return r; @@ -241,7 +213,7 @@ int link_request_radv_addresses(Link *link) { address->source = NETWORK_CONFIG_SOURCE_STATIC; address->family = AF_INET6; address->in_addr.in6 = *a; - address->prefixlen = prefixlen; + address->prefixlen = p->prefixlen; address->route_metric = p->route_metric; r = link_request_static_address(link, TAKE_PTR(address), true); @@ -253,6 +225,77 @@ 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; + + assert(link); + assert(link->radv); + assert(prefix); + + r = sd_radv_prefix_new(&p); + if (r < 0) + return r; + + r = sd_radv_prefix_set_prefix(p, &prefix->prefix, prefix->prefixlen); + if (r < 0) + return r; + + r = sd_radv_prefix_set_preferred_lifetime(p, usec_to_lifetime(prefix->preferred_lifetime)); + if (r < 0) + return r; + + r = sd_radv_prefix_set_valid_lifetime(p, usec_to_lifetime(prefix->valid_lifetime)); + if (r < 0) + return r; + + r = sd_radv_prefix_set_onlink(p, prefix->onlink); + if (r < 0) + return r; + + r = sd_radv_prefix_set_address_autoconfiguration(p, prefix->address_auto_configuration); + if (r < 0) + return r; + + return sd_radv_add_prefix(link->radv, p, false); +} + +static int radv_set_route_prefix(Link *link, RoutePrefix *prefix) { + _cleanup_(sd_radv_route_prefix_unrefp) sd_radv_route_prefix *p = NULL; + int r; + + assert(link); + assert(link->radv); + assert(prefix); + + r = sd_radv_route_prefix_new(&p); + if (r < 0) + return r; + + r = sd_radv_route_prefix_set_prefix(p, &prefix->prefix, prefix->prefixlen); + if (r < 0) + return r; + + r = sd_radv_route_prefix_set_lifetime(p, usec_to_lifetime(prefix->lifetime)); + if (r < 0) + return r; + + return sd_radv_add_route_prefix(link->radv, p, false); +} + static int network_get_ipv6_dns(Network *network, struct in6_addr **ret_addresses, size_t *ret_size) { _cleanup_free_ struct in6_addr *addresses = NULL; size_t n_addresses = 0; @@ -455,22 +498,14 @@ static int radv_configure(Link *link) { } HASHMAP_FOREACH(p, link->network->prefixes_by_section) { - r = sd_radv_add_prefix(link->radv, p->radv_prefix, false); - if (r == -EEXIST) - continue; - if (r == -ENOEXEC) { - log_link_warning_errno(link, r, "[IPv6Prefix] section configured without Prefix= setting, ignoring section."); - continue; - } - if (r < 0) + r = radv_set_prefix(link, p); + if (r < 0 && r != -EEXIST) return r; } HASHMAP_FOREACH(q, link->network->route_prefixes_by_section) { - r = sd_radv_add_route_prefix(link->radv, q->radv_route_prefix, false); - if (r == -EEXIST) - continue; - if (r < 0) + r = radv_set_route_prefix(link, q); + if (r < 0 && r != -EEXIST) return r; } @@ -675,40 +710,34 @@ int config_parse_prefix( void *data, void *userdata) { - Network *network = userdata; _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; - uint8_t prefixlen = 64; - union in_addr_union in6addr; + Network *network = userdata; + union in_addr_union a; int r; assert(filename); assert(section); assert(lvalue); assert(rvalue); - assert(data); + assert(userdata); r = prefix_new_static(network, filename, section_line, &p); if (r < 0) return log_oom(); - r = in_addr_prefix_from_string(rvalue, AF_INET6, &in6addr, &prefixlen); + r = in_addr_prefix_from_string(rvalue, AF_INET6, &a, &p->prefixlen); if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Prefix is invalid, ignoring assignment: %s", rvalue); + log_syntax(unit, LOG_WARNING, filename, line, r, + "Prefix is invalid, ignoring assignment: %s", rvalue); return 0; } + p->prefix = a.in6; - r = sd_radv_prefix_set_prefix(p->radv_prefix, &in6addr.in6, prefixlen); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to set radv prefix, ignoring assignment: %s", rvalue); - return 0; - } - - p = NULL; - + TAKE_PTR(p); return 0; } -int config_parse_prefix_flags( +int config_parse_prefix_boolean( const char *unit, const char *filename, unsigned line, @@ -720,15 +749,15 @@ int config_parse_prefix_flags( void *data, void *userdata) { - Network *network = userdata; _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; + Network *network = userdata; int r; assert(filename); assert(section); assert(lvalue); assert(rvalue); - assert(data); + assert(userdata); r = prefix_new_static(network, filename, section_line, &p); if (r < 0) @@ -736,21 +765,21 @@ int config_parse_prefix_flags( r = parse_boolean(rvalue); if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue); + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue); return 0; } if (streq(lvalue, "OnLink")) - r = sd_radv_prefix_set_onlink(p->radv_prefix, r); + p->onlink = r; else if (streq(lvalue, "AddressAutoconfiguration")) - r = sd_radv_prefix_set_address_autoconfiguration(p->radv_prefix, r); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to set %s=, ignoring assignment: %m", lvalue); - return 0; - } - - p = NULL; + p->address_auto_configuration = r; + else if (streq(lvalue, "Assign")) + p->assign = r; + else + assert_not_reached(); + TAKE_PTR(p); return 0; } @@ -766,8 +795,8 @@ int config_parse_prefix_lifetime( void *data, void *userdata) { - Network *network = userdata; _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; + Network *network = userdata; usec_t usec; int r; @@ -775,72 +804,33 @@ int config_parse_prefix_lifetime( assert(section); assert(lvalue); assert(rvalue); - assert(data); + assert(userdata); r = prefix_new_static(network, filename, section_line, &p); if (r < 0) return log_oom(); r = parse_sec(rvalue, &usec); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Lifetime is invalid, ignoring assignment: %s", rvalue); - return 0; - } - - /* a value of 0xffffffff represents infinity */ - if (streq(lvalue, "PreferredLifetimeSec")) - r = sd_radv_prefix_set_preferred_lifetime(p->radv_prefix, - DIV_ROUND_UP(usec, USEC_PER_SEC)); - else if (streq(lvalue, "ValidLifetimeSec")) - r = sd_radv_prefix_set_valid_lifetime(p->radv_prefix, - DIV_ROUND_UP(usec, USEC_PER_SEC)); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to set %s=, ignoring assignment: %m", lvalue); - return 0; - } - - p = NULL; - - return 0; -} - -int config_parse_prefix_assign( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - Network *network = userdata; - _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; - int r; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = prefix_new_static(network, filename, section_line, &p); - if (r < 0) - return log_oom(); - - r = parse_boolean(rvalue); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to parse %s=, ignoring assignment: %s", - lvalue, rvalue); + "Lifetime is invalid, ignoring assignment: %s", rvalue); return 0; } - p->assign = r; - p = NULL; + if (usec != USEC_INFINITY && DIV_ROUND_UP(usec, USEC_PER_SEC) >= UINT32_MAX) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Lifetime is too long, ignoring assignment: %s", rvalue); + return 0; + } + if (streq(lvalue, "PreferredLifetimeSec")) + p->preferred_lifetime = usec; + else if (streq(lvalue, "ValidLifetimeSec")) + p->valid_lifetime = usec; + else + assert_not_reached(); + + TAKE_PTR(p); return 0; } @@ -856,15 +846,15 @@ int config_parse_prefix_metric( void *data, void *userdata) { - Network *network = userdata; _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; + Network *network = userdata; int r; assert(filename); assert(section); assert(lvalue); assert(rvalue); - assert(data); + assert(userdata); r = prefix_new_static(network, filename, section_line, &p); if (r < 0) @@ -879,7 +869,6 @@ int config_parse_prefix_metric( } TAKE_PTR(p); - return 0; } @@ -930,36 +919,30 @@ int config_parse_route_prefix( void *data, void *userdata) { - Network *network = userdata; _cleanup_(route_prefix_free_or_set_invalidp) RoutePrefix *p = NULL; - uint8_t prefixlen = 64; - union in_addr_union in6addr; + Network *network = userdata; + union in_addr_union a; int r; assert(filename); assert(section); assert(lvalue); assert(rvalue); - assert(data); + assert(userdata); r = route_prefix_new_static(network, filename, section_line, &p); if (r < 0) return log_oom(); - r = in_addr_prefix_from_string(rvalue, AF_INET6, &in6addr, &prefixlen); + r = in_addr_prefix_from_string(rvalue, AF_INET6, &a, &p->prefixlen); if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Route prefix is invalid, ignoring assignment: %s", rvalue); + log_syntax(unit, LOG_WARNING, filename, line, r, + "Route prefix is invalid, ignoring assignment: %s", rvalue); return 0; } + p->prefix = a.in6; - r = sd_radv_route_prefix_set_prefix(p->radv_route_prefix, &in6addr.in6, prefixlen); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to set route prefix, ignoring assignment: %m"); - return 0; - } - - p = NULL; - + TAKE_PTR(p); return 0; } @@ -975,8 +958,8 @@ int config_parse_route_prefix_lifetime( void *data, void *userdata) { - Network *network = userdata; _cleanup_(route_prefix_free_or_set_invalidp) RoutePrefix *p = NULL; + Network *network = userdata; usec_t usec; int r; @@ -984,7 +967,7 @@ int config_parse_route_prefix_lifetime( assert(section); assert(lvalue); assert(rvalue); - assert(data); + assert(userdata); r = route_prefix_new_static(network, filename, section_line, &p); if (r < 0) @@ -997,16 +980,15 @@ int config_parse_route_prefix_lifetime( return 0; } - /* a value of 0xffffffff represents infinity */ - r = sd_radv_route_prefix_set_lifetime(p->radv_route_prefix, DIV_ROUND_UP(usec, USEC_PER_SEC)); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to set route lifetime, ignoring assignment: %m"); + if (usec != USEC_INFINITY && DIV_ROUND_UP(usec, USEC_PER_SEC) >= UINT32_MAX) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Lifetime is too long, ignoring assignment: %s", rvalue); return 0; } - p = NULL; + p->lifetime = usec; + TAKE_PTR(p); return 0; } diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index 5c869d8623..d51fe323dc 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -31,7 +31,13 @@ typedef struct Prefix { Network *network; NetworkConfigSection *section; - sd_radv_prefix *radv_prefix; + struct in6_addr prefix; + uint8_t prefixlen; + usec_t preferred_lifetime; + usec_t valid_lifetime; + + bool onlink; + bool address_auto_configuration; bool assign; uint32_t route_metric; @@ -42,7 +48,9 @@ typedef struct RoutePrefix { Network *network; NetworkConfigSection *section; - sd_radv_route_prefix *radv_route_prefix; + struct in6_addr prefix; + uint8_t prefixlen; + usec_t lifetime; } RoutePrefix; Prefix *prefix_free(Prefix *prefix); @@ -67,9 +75,8 @@ RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_; CONFIG_PARSER_PROTOTYPE(config_parse_router_prefix_delegation); CONFIG_PARSER_PROTOTYPE(config_parse_router_preference); CONFIG_PARSER_PROTOTYPE(config_parse_prefix); -CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags); +CONFIG_PARSER_PROTOTYPE(config_parse_prefix_boolean); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime); -CONFIG_PARSER_PROTOTYPE(config_parse_prefix_assign); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_metric); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_token); CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns); From cf72568ae479ba5953eb23aff5d47e1d3fc203ba Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 27 Sep 2021 22:00:00 +0900 Subject: [PATCH 3/6] network: radv: mask unnecessary part of specified addresses --- src/network/networkd-radv.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 5475ed787e..1cd605a722 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -731,6 +731,8 @@ int config_parse_prefix( "Prefix is invalid, ignoring assignment: %s", rvalue); return 0; } + + (void) in6_addr_mask(&a.in6, p->prefixlen); p->prefix = a.in6; TAKE_PTR(p); @@ -940,6 +942,8 @@ int config_parse_route_prefix( "Route prefix is invalid, ignoring assignment: %s", rvalue); return 0; } + + (void) in6_addr_mask(&a.in6, p->prefixlen); p->prefix = a.in6; TAKE_PTR(p); From 2110040b2d0001ce40f259b7d352b4ebe64e389c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 27 Sep 2021 22:01:14 +0900 Subject: [PATCH 4/6] network: radv: verify [IPv6Prefix] and [IPv6RoutePrefix] sections --- src/network/networkd-radv.c | 95 ++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 16 deletions(-) diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 1cd605a722..54a0d667c8 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -189,15 +189,8 @@ int link_request_radv_addresses(Link *link) { continue; /* radv_generate_addresses() below requires the prefix length <= 64. */ - if (p->prefixlen > 64) { - _cleanup_free_ char *str = NULL; - - (void) in6_addr_prefix_to_string(&p->prefix, p->prefixlen, &str); - log_link_debug(link, - "Prefix is longer than 64, refusing to assign an address in %s.", - strna(str)); + if (p->prefixlen > 64) continue; - } r = radv_generate_addresses(link, p->tokens, &p->prefix, p->prefixlen, &addresses); if (r < 0) @@ -678,24 +671,94 @@ int radv_add_prefix( return 0; } +static int prefix_section_verify(Prefix *p) { + assert(p); + + if (section_is_invalid(p->section)) + return -EINVAL; + + if (in6_addr_is_null(&p->prefix)) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: [IPv6Prefix] section without Prefix= field configured, " + "or specified prefix is the null address. " + "Ignoring [IPv6Prefix] section from line %u.", + p->section->filename, p->section->line); + + if (p->prefixlen < 3 || p->prefixlen > 128) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Invalid prefix length %u is specified in [IPv6Prefix] section. " + "Valid range is 3…128. Ignoring [IPv6Prefix] section from line %u.", + p->section->filename, p->prefixlen, p->section->line); + + if (p->prefixlen > 64) { + _cleanup_free_ char *str = NULL; + + if (p->assign) + (void) in6_addr_prefix_to_string(&p->prefix, p->prefixlen, &str); + + log_info("%s: Unusual prefix length %u (> 64) is specified in [IPv6Prefix] section from line %u%s%s.", + p->section->filename, p->prefixlen, p->section->line, + p->assign ? ", refusing to assign an address in " : "", + p->assign ? strna(str) : ""); + + p->assign = false; + } + + if (p->valid_lifetime == 0) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: The valid lifetime of prefix cannot be zero. " + "Ignoring [IPv6Prefix] section from line %u.", + p->section->filename, p->section->line); + + if (p->preferred_lifetime > p->valid_lifetime) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: The preferred lifetime %s is longer than the valid lifetime %s. " + "Ignoring [IPv6Prefix] section from line %u.", + p->section->filename, + FORMAT_TIMESPAN(p->preferred_lifetime, USEC_PER_SEC), + FORMAT_TIMESPAN(p->valid_lifetime, USEC_PER_SEC), + p->section->line); + + return 0; +} + void network_drop_invalid_prefixes(Network *network) { - Prefix *prefix; + Prefix *p; assert(network); - HASHMAP_FOREACH(prefix, network->prefixes_by_section) - if (section_is_invalid(prefix->section)) - prefix_free(prefix); + HASHMAP_FOREACH(p, network->prefixes_by_section) + if (prefix_section_verify(p) < 0) + prefix_free(p); +} + +static int route_prefix_section_verify(RoutePrefix *p) { + if (section_is_invalid(p->section)) + return -EINVAL; + + if (p->prefixlen > 128) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Invalid prefix length %u is specified in [IPv6RoutePrefix] section. " + "Valid range is 0…128. Ignoring [IPv6RoutePrefix] section from line %u.", + p->section->filename, p->prefixlen, p->section->line); + + if (p->lifetime == 0) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: The lifetime of route cannot be zero. " + "Ignoring [IPv6RoutePrefix] section from line %u.", + p->section->filename, p->section->line); + + return 0; } void network_drop_invalid_route_prefixes(Network *network) { - RoutePrefix *prefix; + RoutePrefix *p; assert(network); - HASHMAP_FOREACH(prefix, network->route_prefixes_by_section) - if (section_is_invalid(prefix->section)) - route_prefix_free(prefix); + HASHMAP_FOREACH(p, network->route_prefixes_by_section) + if (route_prefix_section_verify(p) < 0) + route_prefix_free(p); } int config_parse_prefix( From 9fa25e0791cb9a48987ba7f483db20041d1cdf75 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 28 Sep 2021 11:44:27 +0900 Subject: [PATCH 5/6] network: radv: set non-zero lifetime for DNS servers and domains by default Closes #20850. --- man/systemd.network.xml | 6 +++--- src/network/networkd-network.c | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 77ed77918c..abd0abbf9b 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2676,9 +2676,9 @@ Token=prefixstable:2002:da8:1:: DNSLifetimeSec= - Lifetime in seconds for the DNS server addresses listed - in DNS= and search domains listed in - Domains=. + Lifetime in seconds for the DNS server addresses listed in + DNS= and search domains listed in Domains=. Defaults to + 604800 seconds (one week). diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index afbb9d61db..c3b408c4e9 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -420,6 +420,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .dhcp_server_emit_timezone = true, .router_lifetime_usec = 30 * USEC_PER_MINUTE, + .router_dns_lifetime_usec = 7 * USEC_PER_DAY, .router_emit_dns = true, .router_emit_domains = true, From 165a654e29c055e5645f1857d13bc39c73193762 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 28 Sep 2021 11:45:24 +0900 Subject: [PATCH 6/6] network: radv: extends lifetime for DNS servers or domains propagated from uplink Previously, the lifetime was 30 minutes. But it is not necessary to set to such short time compared with prefix or route prefix lifetime. Note that the propagated DNS servers and domains are all 'static', that is, configured in a .network file, and not provided dynamically. So, it should be safe to use longer lifetime. --- src/network/networkd-radv.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 54a0d667c8..73e9bce52a 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -324,7 +324,6 @@ static int network_get_ipv6_dns(Network *network, struct in6_addr **ret_addresse static int radv_set_dns(Link *link, Link *uplink) { _cleanup_free_ struct in6_addr *dns = NULL; - usec_t lifetime_usec; size_t n_dns; int r; @@ -347,13 +346,10 @@ static int radv_set_dns(Link *link, Link *uplink) { *(p++) = link->network->router_dns[i]; n_dns = p - dns; - lifetime_usec = link->network->router_dns_lifetime_usec; goto set_dns; } - lifetime_usec = SD_RADV_DEFAULT_DNS_LIFETIME_USEC; - r = network_get_ipv6_dns(link->network, &dns, &n_dns); if (r > 0) goto set_dns; @@ -370,26 +366,22 @@ static int radv_set_dns(Link *link, Link *uplink) { set_dns: return sd_radv_set_rdnss(link->radv, - DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC), + usec_to_lifetime(link->network->router_dns_lifetime_usec), dns, n_dns); } static int radv_set_domains(Link *link, Link *uplink) { - OrderedSet *search_domains; - usec_t lifetime_usec; _cleanup_free_ char **s = NULL; /* just free() because the strings are owned by the set */ + OrderedSet *search_domains; if (!link->network->router_emit_domains) return 0; search_domains = link->network->router_search_domains; - lifetime_usec = link->network->router_dns_lifetime_usec; if (search_domains) goto set_domains; - lifetime_usec = SD_RADV_DEFAULT_DNS_LIFETIME_USEC; - search_domains = link->network->search_domains; if (search_domains) goto set_domains; @@ -410,7 +402,7 @@ set_domains: return log_oom(); return sd_radv_set_dnssl(link->radv, - DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC), + usec_to_lifetime(link->network->router_dns_lifetime_usec), s); }