network: do not set nexthop ID, gateway, and multipath routes simultaneously

See kernel's rtm_to_fib_config() in net/ipv4/fib_frontend.c and
rtm_to_fib6_config() in net/ipv6/route.c.

Note that if both gateway and multipath routes are specified, then
kernel ignores gateway. So, strictly speaking, setting both gateway and
multipath routes is allowed by kernel. But such situation is mostly
user's misconfiguration. Let's refuse it.

Note that the conditions newly added in route_configure() are redundant,
as all static configurations are already verified in
route_section_verify(), and dynamic configurations do not set
nexthop_id or multipath routes. Just for safety.
This commit is contained in:
Yu Watanabe 2021-04-29 20:58:10 +09:00
parent 8a9ce525d1
commit 3c7f1c0757

View file

@ -645,7 +645,7 @@ static int route_set_netlink_message(const Route *route, sd_netlink_message *req
/* link may be NULL */
if (in_addr_is_set(route->gw_family, &route->gw)) {
if (in_addr_is_set(route->gw_family, &route->gw) && route->nexthop_id == 0) {
if (route->gw_family == route->family) {
r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->gw_family, &route->gw);
if (r < 0)
@ -1100,8 +1100,8 @@ int route_configure(
Route **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r, k = 0;
Route *nr;
int r, k;
assert(link);
assert(link->manager);
@ -1188,19 +1188,22 @@ int route_configure(
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
r = append_nexthops(route, req);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
if (ordered_set_isempty(route->multipath_routes)) {
if (route->nexthop_id != 0 ||
in_addr_is_set(route->gw_family, &route->gw) ||
ordered_set_isempty(route->multipath_routes)) {
k = route_add_and_setup_timer(link, route, NULL, &nr);
if (k < 0)
return k;
} else {
MultipathRoute *m;
r = append_nexthops(route, req);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
assert(!ret);
k = 0;
ORDERED_SET_FOREACH(m, route->multipath_routes) {
r = route_add_and_setup_timer(link, route, m, NULL);
if (r < 0)
@ -2766,8 +2769,17 @@ static int route_section_verify(Route *route, Network *network) {
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 &&
(in_addr_is_set(route->gw_family, &route->gw) ||
(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=. "