network/route: split out route_section_verify_nexthops()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 13 Jan 2024 01:06:21 +0000 (10:06 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 13 Jan 2024 01:10:32 +0000 (10:10 +0900)
No effective functional change, just refactoring and preparation for
later commits.

src/network/networkd-route-nexthop.c
src/network/networkd-route-nexthop.h
src/network/networkd-route.c

index f1d81f2014f255148247465e52ca7b8fd4f4c246..4dc86d3b76dbf7a6859d2e6680216384d4037571 100644 (file)
 #include "alloc-util.h"
 #include "extract-word.h"
 #include "netlink-util.h"
+#include "networkd-network.h"
 #include "networkd-route.h"
 #include "networkd-route-nexthop.h"
+#include "networkd-route-util.h"
 #include "parse-util.h"
 #include "string-util.h"
 
+int route_section_verify_nexthops(Route *route) {
+        assert(route);
+        assert(route->section);
+        assert(route->network);
+
+        if (route->gateway_from_dhcp_or_ra) {
+                if (route->gw_family == AF_UNSPEC)
+                        /* When deprecated Gateway=_dhcp is set, then assume gateway family based on other settings. */
+                        switch (route->family) {
+                        case AF_UNSPEC:
+                                log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
+                                            "Please use \"_dhcp4\" or \"_ipv6ra\" instead. Assuming \"_dhcp4\".",
+                                            route->section->filename, route->section->line);
+
+                                route->gw_family = route->family = AF_INET;
+                                break;
+                        case AF_INET:
+                        case AF_INET6:
+                                log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
+                                            "Assuming \"%s\" based on Destination=, Source=, or PreferredSource= setting.",
+                                            route->section->filename, route->section->line, route->family == AF_INET ? "_dhcp4" : "_ipv6ra");
+
+                                route->gw_family = route->family;
+                                break;
+                        default:
+                                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                         "%s: Invalid route family. Ignoring [Route] section from line %u.",
+                                                         route->section->filename, route->section->line);
+                        }
+
+                if (route->gw_family == AF_INET && !FLAGS_SET(route->network->dhcp, ADDRESS_FAMILY_IPV4))
+                        return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                 "%s: Gateway=\"_dhcp4\" is specified but DHCPv4 client is disabled. "
+                                                 "Ignoring [Route] section from line %u.",
+                                                 route->section->filename, route->section->line);
+
+                if (route->gw_family == AF_INET6 && !route->network->ipv6_accept_ra)
+                        return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                 "%s: Gateway=\"_ipv6ra\" is specified but IPv6AcceptRA= is disabled. "
+                                                 "Ignoring [Route] section from line %u.",
+                                                 route->section->filename, route->section->line);
+        }
+
+        /* When only Gateway= is specified, assume the route family based on the Gateway address. */
+        if (route->family == AF_UNSPEC)
+                route->family = route->gw_family;
+
+        if (route->family == AF_UNSPEC) {
+                assert(route->section);
+
+                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+                                         "%s: Route section without Gateway=, Destination=, Source=, "
+                                         "or PreferredSource= field configured. "
+                                         "Ignoring [Route] section from line %u.",
+                                         route->section->filename, route->section->line);
+        }
+
+        if (route->gateway_onlink < 0 && in_addr_is_set(route->gw_family, &route->gw) &&
+            ordered_hashmap_isempty(route->network->addresses_by_section)) {
+                /* If no address is configured, in most cases the gateway cannot be reachable.
+                 * TODO: we may need to improve the condition above. */
+                log_warning("%s: Gateway= without static address configured. "
+                            "Enabling GatewayOnLink= option.",
+                            route->section->filename);
+                route->gateway_onlink = true;
+        }
+
+        if (route->gateway_onlink >= 0)
+                SET_FLAG(route->flags, RTNH_F_ONLINK, route->gateway_onlink);
+
+        if (route->family == AF_INET6) {
+                if (route->gw_family == AF_INET)
+                        return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                 "%s: IPv4 gateway is configured for IPv6 route. "
+                                                 "Ignoring [Route] section from line %u.",
+                                                 route->section->filename, route->section->line);
+
+                MultipathRoute *m;
+                ORDERED_SET_FOREACH(m, route->multipath_routes)
+                        if (m->gateway.family == AF_INET)
+                                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                         "%s: IPv4 multipath route is specified for IPv6 route. "
+                                                         "Ignoring [Route] section from line %u.",
+                                                         route->section->filename, route->section->line);
+        }
+
+        if (route->nexthop_id != 0 &&
+            (route->gateway_from_dhcp_or_ra ||
+             in_addr_is_set(route->gw_family, &route->gw) ||
+             !ordered_set_isempty(route->multipath_routes)))
+                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+                                         "%s: NextHopId= cannot be specified with Gateway= or MultiPathRoute=. "
+                                         "Ignoring [Route] section from line %u.",
+                                         route->section->filename, route->section->line);
+
+        if (route_type_is_reject(route) &&
+            (route->gateway_from_dhcp_or_ra ||
+             in_addr_is_set(route->gw_family, &route->gw) ||
+             !ordered_set_isempty(route->multipath_routes)))
+                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+                                         "%s: reject type route cannot be specified with Gateway= or MultiPathRoute=. "
+                                         "Ignoring [Route] section from line %u.",
+                                         route->section->filename, route->section->line);
+
+        if ((route->gateway_from_dhcp_or_ra ||
+             in_addr_is_set(route->gw_family, &route->gw)) &&
+            !ordered_set_isempty(route->multipath_routes))
+                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+                                         "%s: Gateway= cannot be specified with MultiPathRoute=. "
+                                         "Ignoring [Route] section from line %u.",
+                                         route->section->filename, route->section->line);
+
+        return 0;
+}
+
 int config_parse_gateway(
                 const char *unit,
                 const char *filename,
index df5265c508277c0db5bc2fd7acf1a6279a4a0b19..fb935749865322babb2b8de4aeb97851db53fa1b 100644 (file)
@@ -3,6 +3,10 @@
 
 #include "conf-parser.h"
 
+typedef struct Route Route;
+
+int route_section_verify_nexthops(Route *route);
+
 CONFIG_PARSER_PROTOTYPE(config_parse_gateway);
 CONFIG_PARSER_PROTOTYPE(config_parse_route_gateway_onlink);
 CONFIG_PARSER_PROTOTYPE(config_parse_route_nexthop);
index e890d0a2e969284c8ac3c6148e8da62f052c8a49..04b6380513755e3d1fc7f4b75645112f361e3522 100644 (file)
@@ -2236,79 +2236,34 @@ int config_parse_route_type(
         return 0;
 }
 
-static int route_section_verify(Route *route, Network *network) {
+static int route_section_verify(Route *route) {
+        int r;
+
+        assert(route);
+        assert(route->section);
+        assert(route->network);
+
         if (section_is_invalid(route->section))
                 return -EINVAL;
 
         /* Currently, we do not support static route with finite lifetime. */
         assert(route->lifetime_usec == USEC_INFINITY);
 
-        if (route->gateway_from_dhcp_or_ra) {
-                if (route->gw_family == AF_UNSPEC) {
-                        /* When deprecated Gateway=_dhcp is set, then assume gateway family based on other settings. */
-                        switch (route->family) {
-                        case AF_UNSPEC:
-                                log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
-                                            "Please use \"_dhcp4\" or \"_ipv6ra\" instead. Assuming \"_dhcp4\".",
-                                            route->section->filename, route->section->line);
-                                route->family = AF_INET;
-                                break;
-                        case AF_INET:
-                        case AF_INET6:
-                                log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
-                                            "Assuming \"%s\" based on Destination=, Source=, or PreferredSource= setting.",
-                                            route->section->filename, route->section->line, route->family == AF_INET ? "_dhcp4" : "_ipv6ra");
-                                break;
-                        default:
-                                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                         "%s: Invalid route family. Ignoring [Route] section from line %u.",
-                                                         route->section->filename, route->section->line);
-                        }
-                        route->gw_family = route->family;
-                }
-
-                if (route->gw_family == AF_INET && !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4))
-                        return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                 "%s: Gateway=\"_dhcp4\" is specified but DHCPv4 client is disabled. "
-                                                 "Ignoring [Route] section from line %u.",
-                                                 route->section->filename, route->section->line);
-
-                if (route->gw_family == AF_INET6 && !network->ipv6_accept_ra)
-                        return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                 "%s: Gateway=\"_ipv6ra\" is specified but IPv6AcceptRA= is disabled. "
-                                                 "Ignoring [Route] section from line %u.",
-                                                 route->section->filename, route->section->line);
-        }
-
-        /* When only Gateway= is specified, assume the route family based on the Gateway address. */
-        if (route->family == AF_UNSPEC)
-                route->family = route->gw_family;
-
-        if (route->family == AF_UNSPEC) {
-                assert(route->section);
-
-                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
-                                         "%s: Route section without Gateway=, Destination=, Source=, "
-                                         "or PreferredSource= field configured. "
-                                         "Ignoring [Route] section from line %u.",
-                                         route->section->filename, route->section->line);
-        }
-
-        if (route->family == AF_INET6 && route->gw_family == AF_INET)
-                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
-                                         "%s: IPv4 gateway is configured for IPv6 route. "
-                                         "Ignoring [Route] section from line %u.",
-                                         route->section->filename, route->section->line);
+        r = route_section_verify_nexthops(route);
+        if (r < 0)
+                return r;
 
-        if (!route->table_set && network->vrf) {
-                route->table = VRF(network->vrf)->table;
+        /* table */
+        if (!route->table_set && route->network->vrf) {
+                route->table = VRF(route->network->vrf)->table;
                 route->table_set = true;
         }
 
         if (!route->table_set && IN_SET(route->type, RTN_LOCAL, RTN_BROADCAST, RTN_ANYCAST, RTN_NAT))
                 route->table = RT_TABLE_LOCAL;
 
-        if (!route->scope_set && route->family != AF_INET6) {
+        /* scope */
+        if (!route->scope_set && route->family == AF_INET) {
                 if (IN_SET(route->type, RTN_LOCAL, RTN_NAT))
                         route->scope = RT_SCOPE_HOST;
                 else if (IN_SET(route->type, RTN_BROADCAST, RTN_ANYCAST, RTN_MULTICAST))
@@ -2321,54 +2276,16 @@ static int route_section_verify(Route *route, Network *network) {
                         route->scope = RT_SCOPE_LINK;
         }
 
-        if (route->scope != RT_SCOPE_UNIVERSE && route->family == AF_INET6) {
-                log_warning("%s: Scope= is specified for IPv6 route. It will be ignored.", route->section->filename);
-                route->scope = RT_SCOPE_UNIVERSE;
-        }
-
-        if (route->family == AF_INET6 && route->priority == 0)
-                route->priority = IP6_RT_PRIO_USER;
-
-        if (route->gateway_onlink < 0 && in_addr_is_set(route->gw_family, &route->gw) &&
-            ordered_hashmap_isempty(network->addresses_by_section)) {
-                /* If no address is configured, in most cases the gateway cannot be reachable.
-                 * TODO: we may need to improve the condition above. */
-                log_warning("%s: Gateway= without static address configured. "
-                            "Enabling GatewayOnLink= option.",
-                            network->filename);
-                route->gateway_onlink = true;
-        }
-
-        if (route->gateway_onlink >= 0)
-                SET_FLAG(route->flags, RTNH_F_ONLINK, route->gateway_onlink);
-
+        /* IPv6 route */
         if (route->family == AF_INET6) {
-                MultipathRoute *m;
+                if (route->scope != RT_SCOPE_UNIVERSE) {
+                        log_warning("%s: Scope= is specified for IPv6 route. It will be ignored.", route->section->filename);
+                        route->scope = RT_SCOPE_UNIVERSE;
+                }
 
-                ORDERED_SET_FOREACH(m, route->multipath_routes)
-                        if (m->gateway.family == AF_INET)
-                                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                         "%s: IPv4 multipath route is specified for IPv6 route. "
-                                                         "Ignoring [Route] section from line %u.",
-                                                         route->section->filename, route->section->line);
-        }
-
-        if ((route->gateway_from_dhcp_or_ra ||
-             in_addr_is_set(route->gw_family, &route->gw)) &&
-            !ordered_set_isempty(route->multipath_routes))
-                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
-                                         "%s: Gateway= cannot be specified with MultiPathRoute=. "
-                                         "Ignoring [Route] section from line %u.",
-                                         route->section->filename, route->section->line);
-
-        if (route->nexthop_id > 0 &&
-            (route->gateway_from_dhcp_or_ra ||
-             in_addr_is_set(route->gw_family, &route->gw) ||
-             !ordered_set_isempty(route->multipath_routes)))
-                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
-                                         "%s: NextHopId= cannot be specified with Gateway= or MultiPathRoute=. "
-                                         "Ignoring [Route] section from line %u.",
-                                         route->section->filename, route->section->line);
+                if (route->priority == 0)
+                        route->priority = IP6_RT_PRIO_USER;
+        }
 
         return 0;
 }
@@ -2379,6 +2296,6 @@ void network_drop_invalid_routes(Network *network) {
         assert(network);
 
         HASHMAP_FOREACH(route, network->routes_by_section)
-                if (route_section_verify(route, network) < 0)
+                if (route_section_verify(route) < 0)
                         route_free(route);
 }