platform: fix handling the onlink route attribute for routes without gateway

For IPv6, kernel doesn't care. If the gateway is ::, you may or may
not set the onlink attribute. But for IPv4 routes, that gets rejected:

  # ip route add 1.2.3.4/32 dev v onlink
  Error: Invalid flags for nexthop - PERVASIVE and ONLINK can not be set.

Silently suppress setting the flag in that case and ignore the user
request. After all, the effect is probably the same (that is, the route
is onlink anyway).

(cherry picked from commit 8b14849877)
This commit is contained in:
Thomas Haller 2023-02-01 21:42:03 +01:00
parent 41d667ba2a
commit 09d5c4e22e
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728

View file

@ -5346,7 +5346,7 @@ _nl_msg_new_route(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPObject *ob
const guint32 lock = ip_route_get_lock_flag(NMP_OBJECT_CAST_IP_ROUTE(obj));
const guint32 table =
nm_platform_route_table_uncoerce(NMP_OBJECT_CAST_IP_ROUTE(obj)->table_coerced, TRUE);
const struct rtmsg rtmsg = {
struct rtmsg rtmsg = {
.rtm_family = klass->addr_family,
.rtm_tos = IS_IPv4 ? obj->ip4_route.tos : 0,
.rtm_table = table <= 0xFF ? table : RT_TABLE_UNSPEC,
@ -5354,7 +5354,7 @@ _nl_msg_new_route(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPObject *ob
.rtm_scope =
IS_IPv4 ? nm_platform_route_scope_inv(obj->ip4_route.scope_inv) : RT_SCOPE_NOWHERE,
.rtm_type = nm_platform_route_type_uncoerce(NMP_OBJECT_CAST_IP_ROUTE(obj)->type_coerced),
.rtm_flags = obj->ip_route.r_rtm_flags & ((unsigned) (RTNH_F_ONLINK)),
.rtm_flags = 0,
.rtm_dst_len = obj->ip_route.plen,
.rtm_src_len = IS_IPv4 ? 0 : NMP_OBJECT_CAST_IP6_ROUTE(obj)->src_plen,
};
@ -5365,6 +5365,17 @@ _nl_msg_new_route(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPObject *ob
NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
nm_assert(NM_IN_SET(nlmsg_type, RTM_NEWROUTE, RTM_DELROUTE));
if (NM_FLAGS_HAS(obj->ip_route.r_rtm_flags, ((unsigned) (RTNH_F_ONLINK)))) {
if (IS_IPv4 && obj->ip4_route.gateway == 0) {
/* Kernel does not allow setting the onlink flag, if there is no gateway.
* We silently don't configure the flag.
*
* For multi-hop routes, we will set the flag for each next-hop (which
* has a gateway set). */
} else
rtmsg.rtm_flags |= ((unsigned) RTNH_F_ONLINK);
}
msg = nlmsg_alloc_new(0, nlmsg_type, nlmsg_flags);
if (nlmsg_append_struct(msg, &rtmsg) < 0)