diff options
Diffstat (limited to 'src/libnm-platform')
| -rw-r--r-- | src/libnm-platform/nm-linux-platform.c | 56 | ||||
| -rw-r--r-- | src/libnm-platform/nm-platform.c | 25 | ||||
| -rw-r--r-- | src/libnm-platform/nm-platform.h | 15 | ||||
| -rw-r--r-- | src/libnm-platform/nmp-ethtool.c | 2 | ||||
| -rw-r--r-- | src/libnm-platform/nmp-object.c | 2 |
5 files changed, 86 insertions, 14 deletions
diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 0c1097c2..cc5b99e0 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -59,6 +59,7 @@ G_STATIC_ASSERT(NM_MPTCP_PM_ADDR_FLAG_SUBFLOW == MPTCP_PM_ADDR_FLAG_SUBFLOW); G_STATIC_ASSERT(NM_MPTCP_PM_ADDR_FLAG_BACKUP == MPTCP_PM_ADDR_FLAG_BACKUP); G_STATIC_ASSERT(NM_MPTCP_PM_ADDR_FLAG_FULLMESH == MPTCP_PM_ADDR_FLAG_FULLMESH); G_STATIC_ASSERT(NM_MPTCP_PM_ADDR_FLAG_IMPLICIT == MPTCP_PM_ADDR_FLAG_IMPLICIT); +G_STATIC_ASSERT(NM_MPTCP_PM_ADDR_FLAG_LAMINAR == MPTCP_PM_ADDR_FLAG_LAMINAR); /*****************************************************************************/ @@ -4014,6 +4015,7 @@ _new_from_nl_route(const struct nlmsghdr *nlh, gboolean id_only, ParseNlmsgIter [RTA_PREF] = {.type = NLA_U8}, [RTA_FLOW] = {.type = NLA_U32}, [RTA_CACHEINFO] = {.minlen = nm_offsetofend(struct rta_cacheinfo, rta_tsage)}, + [RTA_VIA] = {.minlen = nm_offsetofend(struct rtvia, rtvia_family)}, [RTA_METRICS] = {.type = NLA_NESTED}, [RTA_MULTIPATH] = {.type = NLA_NESTED}, }; @@ -4030,9 +4032,11 @@ _new_from_nl_route(const struct nlmsghdr *nlh, gboolean id_only, ParseNlmsgIter guint8 weight; int ifindex; NMIPAddr gateway; + gboolean is_via; } nh = { .found = FALSE, .has_more = FALSE, + .is_via = FALSE, }; guint v4_n_nexthops = 0; NMPlatformIP4RtNextHop v4_nh_extra_nexthops_stack[10]; @@ -4201,13 +4205,26 @@ rta_multipath_done: return nm_assert_unreachable_val(NULL); } - if (tb[RTA_OIF] || tb[RTA_GATEWAY] || tb[RTA_FLOW]) { + if (tb[RTA_OIF] || tb[RTA_GATEWAY] || tb[RTA_FLOW] || tb[RTA_VIA]) { int ifindex = 0; NMIPAddr gateway = {}; if (tb[RTA_OIF]) ifindex = nla_get_u32(tb[RTA_OIF]); - if (_check_addr_or_return_null(tb, RTA_GATEWAY, addr_len)) + + if (tb[RTA_VIA]) { + struct rtvia *rtvia; + + /* Used when the gateway family doesn't match the route family */ + rtvia = nla_data(tb[RTA_VIA]); + if (rtvia->rtvia_family != AF_INET6) + return NULL; + if (nla_len(tb[RTA_VIA]) < sizeof(struct rtvia) + sizeof(struct in6_addr)) + return NULL; + + nh.is_via = TRUE; + memcpy(&gateway, rtvia->rtvia_addr, sizeof(struct in6_addr)); + } else if (_check_addr_or_return_null(tb, RTA_GATEWAY, addr_len)) memcpy(&gateway, nla_data(tb[RTA_GATEWAY]), addr_len); if (!nh.found) { @@ -4223,6 +4240,9 @@ rta_multipath_done: } else { /* Kernel supports new style nexthop configuration, * verify that it is a duplicate and ignore old-style nexthop. */ + if (nh.is_via) + return NULL; + if (nh.ifindex != ifindex || memcmp(&nh.gateway, &gateway, addr_len) != 0) { /* we have a RTA_MULTIPATH attribute that does not agree. * That seems not right. Error out. */ @@ -4238,7 +4258,7 @@ rta_multipath_done: * 1 (lo). Of course it does!! */ if (nh.found) { if (IS_IPv4) { - if (nh.ifindex != 0 || nh.gateway.addr4 != 0) { + if (nh.ifindex != 0 || nh.gateway.addr4 != 0 || nh.is_via) { /* we only accept kernel to notify about the ifindex/gateway, if it * is zero. This is only to be a bit forgiving, but we really don't * know how to handle such routes that have an ifindex. */ @@ -4337,9 +4357,14 @@ rta_multipath_done: if (tb[RTA_PRIORITY]) obj->ip_route.metric = nla_get_u32(tb[RTA_PRIORITY]); - if (IS_IPv4) - obj->ip4_route.gateway = nh.gateway.addr4; - else + if (IS_IPv4) { + if (nh.is_via) { + obj->ip4_route.via.addr_family = AF_INET6; + obj->ip4_route.via.addr = nh.gateway; + } else { + obj->ip4_route.gateway = nh.gateway.addr4; + } + } else obj->ip6_route.gateway = nh.gateway.addr6; if (IS_IPv4) @@ -5838,7 +5863,24 @@ _nl_msg_new_route(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPObject *ob /* We currently don't have need for multi-hop routes... */ if (IS_IPv4) { - NLA_PUT(msg, RTA_GATEWAY, addr_len, &obj->ip4_route.gateway); + if (obj->ip4_route.gateway == INADDR_ANY && obj->ip4_route.via.addr_family != AF_UNSPEC) { + struct rtvia *rtvia; + + nm_assert(obj->ip4_route.via.addr_family == AF_INET6); + + rtvia = nla_data(nla_reserve( + msg, + RTA_VIA, + sizeof(*rtvia) + nm_utils_addr_family_to_size(obj->ip4_route.via.addr_family))); + if (!rtvia) + goto nla_put_failure; + rtvia->rtvia_family = obj->ip4_route.via.addr_family; + memcpy(rtvia->rtvia_addr, + obj->ip4_route.via.addr.addr_ptr, + nm_utils_addr_family_to_size(obj->ip4_route.via.addr_family)); + } else { + NLA_PUT(msg, RTA_GATEWAY, addr_len, &obj->ip4_route.gateway); + } } else { if (!IN6_IS_ADDR_UNSPECIFIED(&obj->ip6_route.gateway)) NLA_PUT(msg, RTA_GATEWAY, addr_len, &obj->ip6_route.gateway); diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index 33c763c3..853157d2 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -7206,7 +7206,7 @@ nm_platform_ip4_route_to_string_full(const NMPlatformIP4Route *route, { char *buf0; char s_network[INET_ADDRSTRLEN]; - char s_gateway[INET_ADDRSTRLEN]; + char s_gateway[INET6_ADDRSTRLEN]; char s_pref_src[INET_ADDRSTRLEN]; char str_dev[30]; char str_mss[32]; @@ -7235,10 +7235,13 @@ nm_platform_ip4_route_to_string_full(const NMPlatformIP4Route *route, inet_ntop(AF_INET, &route->network, s_network, sizeof(s_network)); - if (route->gateway == 0) - s_gateway[0] = '\0'; - else + if (route->gateway != INADDR_ANY) { inet_ntop(AF_INET, &route->gateway, s_gateway, sizeof(s_gateway)); + } else if (route->via.addr_family == AF_INET6) { + inet_ntop(AF_INET6, route->via.addr.addr_ptr, s_gateway, sizeof(s_gateway)); + } else { + s_gateway[0] = '\0'; + } nm_strbuf_append( &buf, @@ -7979,7 +7982,8 @@ static NM_UTILS_FLAGS2STR_DEFINE(_mptcp_flags_to_string, NM_UTILS_FLAGS2STR(NM_MPTCP_PM_ADDR_FLAG_SIGNAL, "signal"), NM_UTILS_FLAGS2STR(NM_MPTCP_PM_ADDR_FLAG_SUBFLOW, "subflow"), NM_UTILS_FLAGS2STR(NM_MPTCP_PM_ADDR_FLAG_BACKUP, "backup"), - NM_UTILS_FLAGS2STR(NM_MPTCP_PM_ADDR_FLAG_FULLMESH, "fullmesh")); + NM_UTILS_FLAGS2STR(NM_MPTCP_PM_ADDR_FLAG_FULLMESH, "fullmesh"), + NM_UTILS_FLAGS2STR(NM_MPTCP_PM_ADDR_FLAG_LAMINAR, "laminar")); const char * nm_platform_mptcp_addr_to_string(const NMPlatformMptcpAddr *mptcp_addr, char *buf, gsize len) @@ -8978,6 +8982,9 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, nm_hash_update_vals(h, obj->ifindex, n_nexthops, + obj->via.addr_family, + obj->via.addr_family == AF_INET6 ? obj->via.addr.addr6 + : in6addr_any, obj->gateway, _ip4_route_weight_normalize(n_nexthops, obj->weight, FALSE)); } @@ -9128,6 +9135,10 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a, if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { NM_CMP_FIELD(a, b, ifindex); NM_CMP_FIELD(a, b, gateway); + NM_CMP_FIELD(a, b, via.addr_family); + if (a->via.addr_family == AF_INET6) { + NM_CMP_FIELD_IN6ADDR(a, b, via.addr.addr6); + } n_nexthops = nm_platform_ip4_route_get_n_nexthops(a); NM_CMP_DIRECT(n_nexthops, nm_platform_ip4_route_get_n_nexthops(b)); NM_CMP_DIRECT(_ip4_route_weight_normalize(n_nexthops, a->weight, FALSE), @@ -9153,6 +9164,10 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a, NM_CMP_FIELD_UNSAFE(a, b, metric_any); NM_CMP_FIELD(a, b, metric); NM_CMP_FIELD(a, b, gateway); + NM_CMP_FIELD(a, b, via.addr_family); + if (a->via.addr_family == AF_INET6) { + NM_CMP_FIELD_IN6ADDR(a, b, via.addr.addr6); + } if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { n_nexthops = nm_platform_ip4_route_get_n_nexthops(a); NM_CMP_DIRECT(n_nexthops, nm_platform_ip4_route_get_n_nexthops(b)); diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index a63f40c7..033dc515 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -46,6 +46,7 @@ typedef gboolean (*NMPObjectPredicateFunc)(const NMPObject *obj, gpointer user_d #define NM_MPTCP_PM_ADDR_FLAG_BACKUP ((guint32) (1 << 2)) #define NM_MPTCP_PM_ADDR_FLAG_FULLMESH ((guint32) (1 << 3)) #define NM_MPTCP_PM_ADDR_FLAG_IMPLICIT ((guint32) (1 << 4)) +#define NM_MPTCP_PM_ADDR_FLAG_LAMINAR ((guint32) (1 << 5)) /* Redefine this in host's endianness */ #define NM_GRE_KEY 0x2000 @@ -443,6 +444,12 @@ struct _NMPlatformIP4Route { * the first hop. */ in_addr_t gateway; + /* RTA_VIA. Part of the primary key for a route. Allows a gateway for a + * route to exist in a different address family. + * Only valid if: n_nexthops == 1, gateway == 0, via.family != AF_UNSPEC + */ + NMIPAddrTyped via; + /* RTA_PREFSRC (called "src" by iproute2). * * pref_src is part of the ID of an IPv4 route. When deleting a route, @@ -2406,6 +2413,14 @@ nm_platform_ip_route_get_gateway(int addr_family, const NMPlatformIPRoute *route return &((NMPlatformIP6Route *) route)->gateway; } +static inline const NMIPAddrTyped * +nm_platform_ip4_route_get_via(const NMPlatformIP4Route *route) +{ + nm_assert(route); + + return &route->via; +} + static inline gconstpointer nm_platform_ip_route_get_pref_src(int addr_family, const NMPlatformIPRoute *route) { diff --git a/src/libnm-platform/nmp-ethtool.c b/src/libnm-platform/nmp-ethtool.c index ed028f6a..28d12ffb 100644 --- a/src/libnm-platform/nmp-ethtool.c +++ b/src/libnm-platform/nmp-ethtool.c @@ -153,7 +153,7 @@ ethtool_send_and_recv(struct nl_sock *sock, out: if (nle < 0 && err_msg && *err_msg == NULL) - *err_msg = strdup(nm_strerror(nle)); + *err_msg = g_strdup(nm_strerror(nle)); if (nle >= 0 && cb_result < 0) nle = cb_result; diff --git a/src/libnm-platform/nmp-object.c b/src/libnm-platform/nmp-object.c index e11bfb3f..56533c99 100644 --- a/src/libnm-platform/nmp-object.c +++ b/src/libnm-platform/nmp-object.c @@ -893,7 +893,7 @@ const NMPObject * nmp_object_stackinit_id_ip6_address(NMPObject *obj, int ifindex, const struct in6_addr *address) { _nmp_object_stackinit_from_type(obj, NMP_OBJECT_TYPE_IP6_ADDRESS); - obj->ip4_address.ifindex = ifindex; + obj->ip6_address.ifindex = ifindex; if (address) obj->ip6_address.address = *address; return obj; |