]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: radv: verify [IPv6Prefix] and [IPv6RoutePrefix] sections
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 27 Sep 2021 13:01:14 +0000 (22:01 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 11 Oct 2021 18:10:30 +0000 (03:10 +0900)
src/network/networkd-radv.c

index 1cd605a722f0014b35fa4a6d8715577ef7ac9d7c..54a0d667c831a65fe753002b77b2e7ea8743763c 100644 (file)
@@ -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(