From: Yu Watanabe Date: Thu, 29 Apr 2021 11:58:10 +0000 (+0900) Subject: network: do not set nexthop ID, gateway, and multipath routes simultaneously X-Git-Tag: v249-rc1~323^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F19458%2Fhead;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index c1e5f6b4b82..070131f4af7 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -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=. "