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(