network/route: split out route_section_verify_nexthops()
No effective functional change, just refactoring and preparation for later commits.
This commit is contained in:
@@ -5,11 +5,128 @@
|
||||
#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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
+23
-106
@@ -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;
|
||||
}
|
||||
r = route_section_verify_nexthops(route);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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);
|
||||
|
||||
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,55 +2276,17 @@ 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->priority == 0)
|
||||
route->priority = IP6_RT_PRIO_USER;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user