From 2ebc3ac7d9d9ef5886c433d2e8df9d058631b524 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 14 Jul 2022 20:08:39 +0200 Subject: [PATCH 01/10] std-aux: add nm_memcmp() helper --- src/libnm-std-aux/nm-std-aux.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libnm-std-aux/nm-std-aux.h b/src/libnm-std-aux/nm-std-aux.h index 059b6b83fa..8072e606c9 100644 --- a/src/libnm-std-aux/nm-std-aux.h +++ b/src/libnm-std-aux/nm-std-aux.h @@ -487,6 +487,17 @@ nm_streq0(const char *s1, const char *s2) return (s1 == s2) || (s1 && s2 && strcmp(s1, s2) == 0); } +static inline int +nm_memcmp(const void *s1, const void *s2, size_t n) +{ + /* Workaround undefined behavior in memcmp() with NULL pointers. */ + if (n == 0) + return 0; + nm_assert(s1); + nm_assert(s2); + return memcmp(s1, s2, n); +} + /* * Very similar to g_str_has_prefix() with the obvious meaning. * Differences: From c4992c75f7baad55d179592896700d9fd03a48a8 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 14 Jul 2022 20:09:06 +0200 Subject: [PATCH 02/10] std-aux: use nm_memcmp() in NM_CMP_DIRECT_MEMCMP() NM_CMP_DIRECT_MEMCMP() gets called by NM_CMP_FIELD_MEMCMP_LEN(). For example, if you want to compare a NMIPAddr, it seems sensible to call NM_CMP_FIELD_MEMCMP_LEN(obj1, obj2, addr, nm_utils_addr_family_to_size(obj1->addr_family)); Granted, nm_utils_addr_family_to_size() asserts that addr_family is either AF_INET or AF_INET6. However, if the assertion fails, we don't want yet another undefined behavior here and do the sensible thing about n zero. In general, for a low-level function that uses memcmp(), it's non obvious to ensure that the caller does not accidentally invoke undefined behavior. nm_memcmp() avoids that. --- src/libnm-std-aux/nm-std-aux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libnm-std-aux/nm-std-aux.h b/src/libnm-std-aux/nm-std-aux.h index 8072e606c9..02a2942f8f 100644 --- a/src/libnm-std-aux/nm-std-aux.h +++ b/src/libnm-std-aux/nm-std-aux.h @@ -1174,7 +1174,7 @@ nm_ptr_to_uintptr(const void *p) #define NM_CMP_DIRECT_BOOL(a, b) NM_CMP_DIRECT(!!(a), !!(b)) -#define NM_CMP_DIRECT_MEMCMP(a, b, size) NM_CMP_RETURN(memcmp((a), (b), (size))) +#define NM_CMP_DIRECT_MEMCMP(a, b, size) NM_CMP_RETURN(nm_memcmp((a), (b), (size))) #define NM_CMP_DIRECT_STRCMP(a, b) NM_CMP_RETURN_DIRECT(strcmp((a), (b))) From 22f6ac039d8b4c6c63cd1e8e92ae289c7b75b755 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 14 Jul 2022 20:29:43 +0200 Subject: [PATCH 03/10] glib-aux: use max_align_t in NM_HASH_COMBINE_VALS() macro The _nm_alignas() exists to choose a suitable alignment. Since it's on the stack, it has (almost) no overhead to just use the maximum alignment. That's why gint64 was chosen before. But that isn't the largest alignment. We rely on C11 already, and we also always include . So use max_align_t instead. --- src/libnm-glib-aux/nm-hash-utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libnm-glib-aux/nm-hash-utils.h b/src/libnm-glib-aux/nm-hash-utils.h index b7ee4dd17a..e6c7e74adc 100644 --- a/src/libnm-glib-aux/nm-hash-utils.h +++ b/src/libnm-glib-aux/nm-hash-utils.h @@ -140,7 +140,7 @@ nm_hash_update_bool(NMHashState *state, bool val) #define NM_HASH_COMBINE_VALS(var, ...) \ const struct _nm_packed { \ NM_VA_ARGS_FOREACH(, , , _NM_HASH_COMBINE_VALS_TYPE_OP, __VA_ARGS__) \ - } var _nm_alignas(guint64) = { \ + } var _nm_alignas(max_align_t) = { \ NM_VA_ARGS_FOREACH(, , , _NM_HASH_COMBINE_VALS_INIT_OP, __VA_ARGS__)} /* nm_hash_update_vals() is faster then nm_hash_update_val() as it combines multiple From 8d0b30b243ac5fee50a36c640a0f5bb0890eef22 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 15 Jul 2022 10:02:45 +0200 Subject: [PATCH 04/10] linux-headers: include "mptcp.h" kernel header Taken from v5.18, 4b0986a3613c ('Linux 5.18') from 20220522. --- Makefile.am | 3 +- src/linux-headers/mptcp.h | 232 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 src/linux-headers/mptcp.h diff --git a/Makefile.am b/Makefile.am index eac85f15b1..f78d60d4d1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -590,8 +590,9 @@ src_libnm_platform_libnm_platform_la_CPPFLAGS = \ src_libnm_platform_libnm_platform_la_SOURCES = \ \ src/linux-headers/ethtool.h \ - src/linux-headers/nl802154.h \ + src/linux-headers/mptcp.h \ src/linux-headers/nl80211-vnd-intel.h \ + src/linux-headers/nl802154.h \ \ src/libnm-platform/nm-linux-platform.c \ src/libnm-platform/nm-linux-platform.h \ diff --git a/src/linux-headers/mptcp.h b/src/linux-headers/mptcp.h new file mode 100644 index 0000000000..ca502f1edc --- /dev/null +++ b/src/linux-headers/mptcp.h @@ -0,0 +1,232 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +#ifndef _MPTCP_H +#define _MPTCP_H + +#include +#include +#include /* for sockaddr_in */ +#include /* for sockaddr_in6 */ +#include /* for sockaddr_storage and sa_family */ + +#include /* for struct sockaddr */ + +#define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0) +#define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1) +#define MPTCP_SUBFLOW_FLAG_JOIN_REM _BITUL(2) +#define MPTCP_SUBFLOW_FLAG_JOIN_LOC _BITUL(3) +#define MPTCP_SUBFLOW_FLAG_BKUP_REM _BITUL(4) +#define MPTCP_SUBFLOW_FLAG_BKUP_LOC _BITUL(5) +#define MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED _BITUL(6) +#define MPTCP_SUBFLOW_FLAG_CONNECTED _BITUL(7) +#define MPTCP_SUBFLOW_FLAG_MAPVALID _BITUL(8) + +enum { + MPTCP_SUBFLOW_ATTR_UNSPEC, + MPTCP_SUBFLOW_ATTR_TOKEN_REM, + MPTCP_SUBFLOW_ATTR_TOKEN_LOC, + MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ, + MPTCP_SUBFLOW_ATTR_MAP_SEQ, + MPTCP_SUBFLOW_ATTR_MAP_SFSEQ, + MPTCP_SUBFLOW_ATTR_SSN_OFFSET, + MPTCP_SUBFLOW_ATTR_MAP_DATALEN, + MPTCP_SUBFLOW_ATTR_FLAGS, + MPTCP_SUBFLOW_ATTR_ID_REM, + MPTCP_SUBFLOW_ATTR_ID_LOC, + MPTCP_SUBFLOW_ATTR_PAD, + __MPTCP_SUBFLOW_ATTR_MAX +}; + +#define MPTCP_SUBFLOW_ATTR_MAX (__MPTCP_SUBFLOW_ATTR_MAX - 1) + +/* netlink interface */ +#define MPTCP_PM_NAME "mptcp_pm" +#define MPTCP_PM_CMD_GRP_NAME "mptcp_pm_cmds" +#define MPTCP_PM_EV_GRP_NAME "mptcp_pm_events" +#define MPTCP_PM_VER 0x1 + +/* + * ATTR types defined for MPTCP + */ +enum { + MPTCP_PM_ATTR_UNSPEC, + + MPTCP_PM_ATTR_ADDR, /* nested address */ + MPTCP_PM_ATTR_RCV_ADD_ADDRS, /* u32 */ + MPTCP_PM_ATTR_SUBFLOWS, /* u32 */ + + __MPTCP_PM_ATTR_MAX +}; + +#define MPTCP_PM_ATTR_MAX (__MPTCP_PM_ATTR_MAX - 1) + +enum { + MPTCP_PM_ADDR_ATTR_UNSPEC, + + MPTCP_PM_ADDR_ATTR_FAMILY, /* u16 */ + MPTCP_PM_ADDR_ATTR_ID, /* u8 */ + MPTCP_PM_ADDR_ATTR_ADDR4, /* struct in_addr */ + MPTCP_PM_ADDR_ATTR_ADDR6, /* struct in6_addr */ + MPTCP_PM_ADDR_ATTR_PORT, /* u16 */ + MPTCP_PM_ADDR_ATTR_FLAGS, /* u32 */ + MPTCP_PM_ADDR_ATTR_IF_IDX, /* s32 */ + + __MPTCP_PM_ADDR_ATTR_MAX +}; + +#define MPTCP_PM_ADDR_ATTR_MAX (__MPTCP_PM_ADDR_ATTR_MAX - 1) + +#define MPTCP_PM_ADDR_FLAG_SIGNAL (1 << 0) +#define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1) +#define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2) +#define MPTCP_PM_ADDR_FLAG_FULLMESH (1 << 3) +#define MPTCP_PM_ADDR_FLAG_IMPLICIT (1 << 4) + +enum { + MPTCP_PM_CMD_UNSPEC, + + MPTCP_PM_CMD_ADD_ADDR, + MPTCP_PM_CMD_DEL_ADDR, + MPTCP_PM_CMD_GET_ADDR, + MPTCP_PM_CMD_FLUSH_ADDRS, + MPTCP_PM_CMD_SET_LIMITS, + MPTCP_PM_CMD_GET_LIMITS, + MPTCP_PM_CMD_SET_FLAGS, + + __MPTCP_PM_CMD_AFTER_LAST +}; + +#define MPTCP_INFO_FLAG_FALLBACK _BITUL(0) +#define MPTCP_INFO_FLAG_REMOTE_KEY_RECEIVED _BITUL(1) + +struct mptcp_info { + __u8 mptcpi_subflows; + __u8 mptcpi_add_addr_signal; + __u8 mptcpi_add_addr_accepted; + __u8 mptcpi_subflows_max; + __u8 mptcpi_add_addr_signal_max; + __u8 mptcpi_add_addr_accepted_max; + __u32 mptcpi_flags; + __u32 mptcpi_token; + __u64 mptcpi_write_seq; + __u64 mptcpi_snd_una; + __u64 mptcpi_rcv_nxt; + __u8 mptcpi_local_addr_used; + __u8 mptcpi_local_addr_max; + __u8 mptcpi_csum_enabled; +}; + +/* + * MPTCP_EVENT_CREATED: token, family, saddr4 | saddr6, daddr4 | daddr6, + * sport, dport + * A new MPTCP connection has been created. It is the good time to allocate + * memory and send ADD_ADDR if needed. Depending on the traffic-patterns + * it can take a long time until the MPTCP_EVENT_ESTABLISHED is sent. + * + * MPTCP_EVENT_ESTABLISHED: token, family, saddr4 | saddr6, daddr4 | daddr6, + * sport, dport + * A MPTCP connection is established (can start new subflows). + * + * MPTCP_EVENT_CLOSED: token + * A MPTCP connection has stopped. + * + * MPTCP_EVENT_ANNOUNCED: token, rem_id, family, daddr4 | daddr6 [, dport] + * A new address has been announced by the peer. + * + * MPTCP_EVENT_REMOVED: token, rem_id + * An address has been lost by the peer. + * + * MPTCP_EVENT_SUB_ESTABLISHED: token, family, loc_id, rem_id, + * saddr4 | saddr6, daddr4 | daddr6, sport, + * dport, backup, if_idx [, error] + * A new subflow has been established. 'error' should not be set. + * + * MPTCP_EVENT_SUB_CLOSED: token, family, loc_id, rem_id, saddr4 | saddr6, + * daddr4 | daddr6, sport, dport, backup, if_idx + * [, error] + * A subflow has been closed. An error (copy of sk_err) could be set if an + * error has been detected for this subflow. + * + * MPTCP_EVENT_SUB_PRIORITY: token, family, loc_id, rem_id, saddr4 | saddr6, + * daddr4 | daddr6, sport, dport, backup, if_idx + * [, error] + * The priority of a subflow has changed. 'error' should not be set. + */ +enum mptcp_event_type { + MPTCP_EVENT_UNSPEC = 0, + MPTCP_EVENT_CREATED = 1, + MPTCP_EVENT_ESTABLISHED = 2, + MPTCP_EVENT_CLOSED = 3, + + MPTCP_EVENT_ANNOUNCED = 6, + MPTCP_EVENT_REMOVED = 7, + + MPTCP_EVENT_SUB_ESTABLISHED = 10, + MPTCP_EVENT_SUB_CLOSED = 11, + + MPTCP_EVENT_SUB_PRIORITY = 13, +}; + +enum mptcp_event_attr { + MPTCP_ATTR_UNSPEC = 0, + + MPTCP_ATTR_TOKEN, /* u32 */ + MPTCP_ATTR_FAMILY, /* u16 */ + MPTCP_ATTR_LOC_ID, /* u8 */ + MPTCP_ATTR_REM_ID, /* u8 */ + MPTCP_ATTR_SADDR4, /* be32 */ + MPTCP_ATTR_SADDR6, /* struct in6_addr */ + MPTCP_ATTR_DADDR4, /* be32 */ + MPTCP_ATTR_DADDR6, /* struct in6_addr */ + MPTCP_ATTR_SPORT, /* be16 */ + MPTCP_ATTR_DPORT, /* be16 */ + MPTCP_ATTR_BACKUP, /* u8 */ + MPTCP_ATTR_ERROR, /* u8 */ + MPTCP_ATTR_FLAGS, /* u16 */ + MPTCP_ATTR_TIMEOUT, /* u32 */ + MPTCP_ATTR_IF_IDX, /* s32 */ + MPTCP_ATTR_RESET_REASON,/* u32 */ + MPTCP_ATTR_RESET_FLAGS, /* u32 */ + + __MPTCP_ATTR_AFTER_LAST +}; + +#define MPTCP_ATTR_MAX (__MPTCP_ATTR_AFTER_LAST - 1) + +/* MPTCP Reset reason codes, rfc8684 */ +#define MPTCP_RST_EUNSPEC 0 +#define MPTCP_RST_EMPTCP 1 +#define MPTCP_RST_ERESOURCE 2 +#define MPTCP_RST_EPROHIBIT 3 +#define MPTCP_RST_EWQ2BIG 4 +#define MPTCP_RST_EBADPERF 5 +#define MPTCP_RST_EMIDDLEBOX 6 + +struct mptcp_subflow_data { + __u32 size_subflow_data; /* size of this structure in userspace */ + __u32 num_subflows; /* must be 0, set by kernel */ + __u32 size_kernel; /* must be 0, set by kernel */ + __u32 size_user; /* size of one element in data[] */ +} __attribute__((aligned(8))); + +struct mptcp_subflow_addrs { + union { + __kernel_sa_family_t sa_family; + struct sockaddr sa_local; + struct sockaddr_in sin_local; + struct sockaddr_in6 sin6_local; + struct __kernel_sockaddr_storage ss_local; + }; + union { + struct sockaddr sa_remote; + struct sockaddr_in sin_remote; + struct sockaddr_in6 sin6_remote; + struct __kernel_sockaddr_storage ss_remote; + }; +}; + +/* MPTCP socket options */ +#define MPTCP_INFO 1 +#define MPTCP_TCPINFO 2 +#define MPTCP_SUBFLOW_ADDRS 3 + +#endif /* _MPTCP_H */ From 45ca7dfaf3babb4ba44e8e28177d80ed29cc64d0 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 15 Jul 2022 11:43:14 +0200 Subject: [PATCH 05/10] platform/netlink: add NLA_S32 enum value for attribute type --- src/libnm-platform/nm-netlink.c | 1 + src/libnm-platform/nm-netlink.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libnm-platform/nm-netlink.c b/src/libnm-platform/nm-netlink.c index cb5bd4a896..ecb700fc9b 100644 --- a/src/libnm-platform/nm-netlink.c +++ b/src/libnm-platform/nm-netlink.c @@ -619,6 +619,7 @@ nla_nest_end(struct nl_msg *msg, struct nlattr *start) static const uint8_t nla_attr_minlen[NLA_TYPE_MAX + 1] = { [NLA_U8] = sizeof(uint8_t), [NLA_U16] = sizeof(uint16_t), + [NLA_S32] = sizeof(int32_t), [NLA_U32] = sizeof(uint32_t), [NLA_U64] = sizeof(uint64_t), [NLA_STRING] = 1, diff --git a/src/libnm-platform/nm-netlink.h b/src/libnm-platform/nm-netlink.h index 852c9c8f6d..ccd4b787c7 100644 --- a/src/libnm-platform/nm-netlink.h +++ b/src/libnm-platform/nm-netlink.h @@ -31,6 +31,7 @@ enum { NLA_UNSPEC, /* Unspecified type, binary data chunk */ NLA_U8, /* 8 bit integer */ NLA_U16, /* 16 bit integer */ + NLA_S32, /* 32 bit integer */ NLA_U32, /* 32 bit integer */ NLA_U64, /* 64 bit integer */ NLA_STRING, /* NUL terminated character string */ From 52c8ee2c9dfe080155d3129eba69d19119e296a1 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 18 Jul 2022 21:24:04 +0200 Subject: [PATCH 06/10] platform: drop detecting address scope in _nl_msg_new_address() All callers explicitly set a scope, like they should. Drop guessing the scope. Also, use the proper integer type. --- src/libnm-platform/nm-linux-platform.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 185c9aed3e..3c873c9ea7 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -4780,7 +4780,7 @@ _nl_msg_new_address(uint16_t nlmsg_type, guint8 plen, gconstpointer peer_address, guint32 flags, - int scope, + guint8 scope, guint32 lifetime, guint32 preferred, in_addr_t ip4_broadcast_address, @@ -4792,6 +4792,7 @@ _nl_msg_new_address(uint16_t nlmsg_type, .ifa_index = ifindex, .ifa_prefixlen = plen, .ifa_flags = flags, + .ifa_scope = scope, }; gsize addr_len; @@ -4800,15 +4801,6 @@ _nl_msg_new_address(uint16_t nlmsg_type, msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags); - if (scope == -1) { - /* Allow having scope unset, and detect the scope (including IPv4 compatibility hack). */ - if (family == AF_INET && address && *((char *) address) == 127) - scope = RT_SCOPE_HOST; - else - scope = RT_SCOPE_UNIVERSE; - } - am.ifa_scope = scope, - addr_len = family == AF_INET ? sizeof(in_addr_t) : sizeof(struct in6_addr); if (nlmsg_append_struct(msg, &am) < 0) From a242d41cc026d10ea11744d75ee3f5fdb834e464 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 14 Jul 2022 18:14:07 +0200 Subject: [PATCH 07/10] platform: improve nmp_object_stackinit_id() for types that don't implement cmd_plobj_id_copy() An object type that doesn't implement cmd_plobj_id_copy(), either: - implements cmd_obj_copy(), but then we cannot copy the ID only to a stack instance, because that cannot track ownership. This is a bug in the caller. We cannot use stackinit for an object of a type that is not a plain old data (in C++ terms). - fallback to plain memcpy(). That is in line with nmp_object_clone(). and nmp_object_copy(). --- src/libnm-platform/nmp-object.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libnm-platform/nmp-object.c b/src/libnm-platform/nmp-object.c index d411043d0f..4c0b19aa9a 100644 --- a/src/libnm-platform/nmp-object.c +++ b/src/libnm-platform/nmp-object.c @@ -840,6 +840,17 @@ nmp_object_stackinit_id(NMPObject *obj, const NMPObject *src) _nmp_object_stackinit_from_class(obj, klass); if (klass->cmd_plobj_id_copy) klass->cmd_plobj_id_copy(&obj->object, &src->object); + else { + /* This object must not implement cmd_obj_copy(). + * If it would, it would mean that we require a deep copy + * of the data. As @obj is stack-allocated, it cannot track + * ownership. The caller must not use nmp_object_stackinit_id() + * with an object of such a type. */ + nm_assert(!klass->cmd_obj_copy); + + /* plain memcpy of the public part suffices. */ + memcpy(&obj->object, &src->object, klass->sizeof_data); + } return obj; } From 543a22af0a1080841e92a5d7105501f20714e6df Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 14 Jul 2022 18:09:04 +0200 Subject: [PATCH 08/10] platform: drop unnecessary cmd_plobj_id_copy implementations The default implementation just uses memcpy() of the public part. That is just what we want. No need to implement those functions. --- src/libnm-platform/nmp-object.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/libnm-platform/nmp-object.c b/src/libnm-platform/nmp-object.c index 4c0b19aa9a..bb4a4441e4 100644 --- a/src/libnm-platform/nmp-object.c +++ b/src/libnm-platform/nmp-object.c @@ -1431,21 +1431,6 @@ _vt_cmd_plobj_id_copy(ip6_address, NMPlatformIP6Address, { dst->address = src->address; }); -_vt_cmd_plobj_id_copy(ip4_route, NMPlatformIP4Route, { - *dst = *src; - nm_assert(nm_platform_ip4_route_cmp(dst, src, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) == 0); -}); - -_vt_cmd_plobj_id_copy(ip6_route, NMPlatformIP6Route, { - *dst = *src; - nm_assert(nm_platform_ip6_route_cmp(dst, src, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) == 0); -}); - -_vt_cmd_plobj_id_copy(routing_rule, NMPlatformRoutingRule, { - *dst = *src; - nm_assert(nm_platform_routing_rule_cmp(dst, src, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0); -}); - /* Uses internally nmp_object_copy(), hence it also violates the const * promise for @obj. * */ @@ -3177,7 +3162,6 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .signal_type = NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, .supported_cache_ids = _supported_cache_ids_ipx_route, .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip4_route, .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip4_route, .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip4_route, .cmd_plobj_to_string_id = (CmdPlobjToStringIdFunc) nm_platform_ip4_route_to_string, @@ -3198,7 +3182,6 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .signal_type = NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, .supported_cache_ids = _supported_cache_ids_ipx_route, .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_route, .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip6_route, .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip6_route, .cmd_plobj_to_string_id = (CmdPlobjToStringIdFunc) nm_platform_ip6_route_to_string, @@ -3218,7 +3201,6 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .signal_type = NM_PLATFORM_SIGNAL_ROUTING_RULE_CHANGED, .supported_cache_ids = _supported_cache_ids_routing_rules, .cmd_obj_is_alive = _vt_cmd_obj_is_alive_routing_rule, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_routing_rule, .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_routing_rule, .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_routing_rule, .cmd_plobj_to_string_id = (CmdPlobjToStringIdFunc) nm_platform_routing_rule_to_string, From be4b775585a7cddf0a35edacbe04be591dfde4e9 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 14 Jul 2022 20:19:00 +0200 Subject: [PATCH 09/10] platform: avoid logging plain pointer values in "nmp-object.c" --- src/libnm-platform/nmp-object.c | 64 +++++++++++++++++---------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/src/libnm-platform/nmp-object.c b/src/libnm-platform/nmp-object.c index bb4a4441e4..d281cc7be0 100644 --- a/src/libnm-platform/nmp-object.c +++ b/src/libnm-platform/nmp-object.c @@ -20,25 +20,26 @@ /*****************************************************************************/ #define _NMLOG_DOMAIN LOGD_PLATFORM -#define _NMLOG(level, obj, ...) \ - G_STMT_START \ - { \ - const NMLogLevel __level = (level); \ - \ - if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \ - const NMPObject *const __obj = (obj); \ - \ - _nm_log(__level, \ - _NMLOG_DOMAIN, \ - 0, \ - NULL, \ - NULL, \ - "nmp-object[%p/%s]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - __obj, \ - (__obj ? NMP_OBJECT_GET_CLASS(__obj)->obj_type_name \ - : "???") _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - } \ +#define _NMLOG(level, obj, ...) \ + G_STMT_START \ + { \ + const NMLogLevel __level = (level); \ + \ + if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \ + const NMPObject *const __obj = (obj); \ + \ + _nm_log(__level, \ + _NMLOG_DOMAIN, \ + 0, \ + NULL, \ + NULL, \ + "nmp-object[" NM_HASH_OBFUSCATE_PTR_FMT "" \ + "/%s]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + NM_HASH_OBFUSCATE_PTR(__obj), \ + (__obj ? NMP_OBJECT_GET_CLASS(__obj)->obj_type_name \ + : "???") _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ G_STMT_END /*****************************************************************************/ @@ -911,7 +912,7 @@ nmp_object_to_string(const NMPObject *obj, switch (to_string_mode) { case NMP_OBJECT_TO_STRING_ID: if (!klass->cmd_plobj_to_string_id) { - g_snprintf(buf, buf_size, "%p", obj); + g_snprintf(buf, buf_size, NM_HASH_OBFUSCATE_PTR_FMT, NM_HASH_OBFUSCATE_PTR(obj)); return buf; } return klass->cmd_plobj_to_string_id(&obj->object, buf, buf_size); @@ -919,9 +920,9 @@ nmp_object_to_string(const NMPObject *obj, g_snprintf( buf, buf_size, - "[%s,%p,%u,%calive,%cvisible; %s]", + "[%s," NM_HASH_OBFUSCATE_PTR_FMT ",%u,%calive,%cvisible; %s]", klass->obj_type_name, - obj, + NM_HASH_OBFUSCATE_PTR(obj), obj->parent._ref_count, nmp_object_is_alive(obj) ? '+' : '-', nmp_object_is_visible(obj) ? '+' : '-', @@ -950,14 +951,15 @@ _vt_cmd_obj_to_string_link(const NMPObject *obj, case NMP_OBJECT_TO_STRING_ALL: nm_strbuf_append(&b, &buf_size, - "[%s,%p,%u,%calive,%cvisible,%cin-nl,%p; ", + "[%s," NM_HASH_OBFUSCATE_PTR_FMT + ",%u,%calive,%cvisible,%cin-nl," NM_HASH_OBFUSCATE_PTR_FMT "; ", klass->obj_type_name, - obj, + NM_HASH_OBFUSCATE_PTR(obj), obj->parent._ref_count, nmp_object_is_alive(obj) ? '+' : '-', nmp_object_is_visible(obj) ? '+' : '-', obj->_link.netlink.is_in_netlink ? '+' : '-', - obj->_link.udev.device); + NM_HASH_OBFUSCATE_PTR(obj->_link.udev.device)); NMP_OBJECT_GET_CLASS(obj)->cmd_plobj_to_string(&obj->object, b, buf_size); nm_strbuf_seek_end(&b, &buf_size); if (obj->_link.netlink.lnk) { @@ -995,15 +997,15 @@ _vt_cmd_obj_to_string_lnk_vlan(const NMPObject *obj, switch (to_string_mode) { case NMP_OBJECT_TO_STRING_ID: - g_snprintf(buf, buf_size, "%p", obj); + g_snprintf(buf, buf_size, NM_HASH_OBFUSCATE_PTR_FMT, NM_HASH_OBFUSCATE_PTR(obj)); return buf; case NMP_OBJECT_TO_STRING_ALL: g_snprintf(buf, buf_size, - "[%s,%p,%u,%calive,%cvisible; %s]", + "[%s," NM_HASH_OBFUSCATE_PTR_FMT ",%u,%calive,%cvisible; %s]", klass->obj_type_name, - obj, + NM_HASH_OBFUSCATE_PTR(obj), obj->parent._ref_count, nmp_object_is_alive(obj) ? '+' : '-', nmp_object_is_visible(obj) ? '+' : '-', @@ -1059,17 +1061,17 @@ _vt_cmd_obj_to_string_lnk_wireguard(const NMPObject *obj, switch (to_string_mode) { case NMP_OBJECT_TO_STRING_ID: - g_snprintf(buf, buf_size, "%p", obj); + g_snprintf(buf, buf_size, NM_HASH_OBFUSCATE_PTR_FMT, NM_HASH_OBFUSCATE_PTR(obj)); return buf; case NMP_OBJECT_TO_STRING_ALL: b = buf; nm_strbuf_append(&b, &buf_size, - "[%s,%p,%u,%calive,%cvisible; %s" + "[%s," NM_HASH_OBFUSCATE_PTR_FMT ",%u,%calive,%cvisible; %s" "%s", klass->obj_type_name, - obj, + NM_HASH_OBFUSCATE_PTR(obj), obj->parent._ref_count, nmp_object_is_alive(obj) ? '+' : '-', nmp_object_is_visible(obj) ? '+' : '-', From 1a0c8772b0d9bfce14e8f1bd8d290d00d824dbb5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 13 Jul 2022 16:24:05 +0200 Subject: [PATCH 10/10] platform: add NMPlatformMptcpAddr object An NMPObject is hashable, can be compared and printed. That is useful. Make an NMPObject for MPTCP addresses. It will hold the content of MPTCP_PM_ATTR_ADDR netlink attribute. But like other NMPObject types it will also be used to represent the data as NetworkManager tracks it. --- src/libnm-platform/nm-linux-platform.c | 9 +++ src/libnm-platform/nm-platform.c | 87 ++++++++++++++++++++++++++ src/libnm-platform/nm-platform.h | 36 ++++++++++- src/libnm-platform/nmp-base.h | 2 + src/libnm-platform/nmp-object.c | 54 +++++++++++++++- src/libnm-platform/nmp-object.h | 11 ++++ 6 files changed, 195 insertions(+), 4 deletions(-) diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 3c873c9ea7..01505c5b82 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,14 @@ /*****************************************************************************/ +G_STATIC_ASSERT(NM_MPTCP_PM_ADDR_FLAG_SIGNAL == MPTCP_PM_ADDR_FLAG_SIGNAL); +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); + +/*****************************************************************************/ + /* re-implement to build against kernel * headers that lack this. */ diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index 961c617cc6..bfe80c0d4c 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -7586,6 +7586,93 @@ nm_platform_tfilter_cmp(const NMPlatformTfilter *a, const NMPlatformTfilter *b) return 0; } +static NM_UTILS_FLAGS2STR_DEFINE(_mptcp_flags_to_string, + guint32, + 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")); + +const char * +nm_platform_mptcp_addr_to_string(const NMPlatformMptcpAddr *mptcp_addr, char *buf, gsize len) +{ + char str_addr[30 + NM_UTILS_INET_ADDRSTRLEN]; + char str_port[30]; + char str_id[30]; + char str_flags[200]; + char str_flags2[30 + sizeof(str_flags)]; + char str_ifindex[30]; + + if (!nm_utils_to_string_buffer_init_null(mptcp_addr, &buf, &len)) + return buf; + + if (mptcp_addr->addr_family == 0) + nm_sprintf_buf(str_addr, "no-addr"); + else if (NM_IN_SET(mptcp_addr->addr_family, AF_INET, AF_INET6)) + nm_utils_inet_ntop(mptcp_addr->addr_family, &mptcp_addr->addr, str_addr); + else + nm_sprintf_buf(str_addr, "af %d", mptcp_addr->addr_family); + + if (mptcp_addr->flags != 0) + _mptcp_flags_to_string(mptcp_addr->flags, str_flags, sizeof(str_flags)); + else + str_flags[0] = '\0'; + + g_snprintf(buf, + len, + "%s" /* in_kernel */ + "%s" /* address */ + "%s" /* port */ + "%s" /* id */ + "%s" /* flags */ + "%s" /* ifindex */ + "", + mptcp_addr->in_kernel ? "" : "[nm] ", + str_addr, + mptcp_addr->port == 0 ? "" : nm_sprintf_buf(str_port, " port %u", mptcp_addr->port), + mptcp_addr->id == 0 ? "" : nm_sprintf_buf(str_id, " id %u", mptcp_addr->id), + str_flags[0] == '\0' ? "" : nm_sprintf_buf(str_flags2, " flags %s", str_flags), + mptcp_addr->ifindex == 0 + ? "" + : nm_sprintf_buf(str_ifindex, " ifindex %d", mptcp_addr->ifindex)); + return buf; +} + +void +nm_platform_mptcp_addr_hash_update(const NMPlatformMptcpAddr *obj, NMHashState *h) +{ + nm_assert(obj); + nm_assert_addr_family_or_unspec(obj->addr_family); + + nm_hash_update_vals(h, + obj->id, + obj->flags, + obj->port, + obj->addr_family, + (bool) obj->in_kernel, + obj->ifindex); + if (NM_IN_SET(obj->addr_family, AF_INET, AF_INET6)) + nm_hash_update(h, &obj->addr, nm_utils_addr_family_to_size(obj->addr_family)); +} + +int +nm_platform_mptcp_addr_cmp(const NMPlatformMptcpAddr *a, const NMPlatformMptcpAddr *b) +{ + NM_CMP_SELF(a, b); + + nm_assert_addr_family_or_unspec(a->addr_family); + nm_assert_addr_family_or_unspec(b->addr_family); + + NM_CMP_FIELD(a, b, id); + NM_CMP_FIELD_UNSAFE(a, b, in_kernel); + NM_CMP_FIELD(a, b, addr_family); + if (NM_IN_SET(a->addr_family, AF_INET, AF_INET6)) + NM_CMP_FIELD_MEMCMP_LEN(a, b, addr, nm_utils_addr_family_to_size(a->addr_family)); + NM_CMP_FIELD(a, b, ifindex); + + return 0; +} + const char * nm_platform_vf_to_string(const NMPlatformVF *vf, char *buf, gsize len) { diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index 984ad79cba..19b00c961d 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -61,6 +61,12 @@ typedef gboolean (*NMPObjectPredicateFunc)(const NMPObject *obj, gpointer user_d #define NM_IFF_MULTI_QUEUE 0x0100 /* IFF_MULTI_QUEUE */ +#define NM_MPTCP_PM_ADDR_FLAG_SIGNAL ((guint32) (1 << 0)) +#define NM_MPTCP_PM_ADDR_FLAG_SUBFLOW ((guint32) (1 << 1)) +#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)) + /* Redefine this in host's endianness */ #define NM_GRE_KEY 0x2000 @@ -782,8 +788,6 @@ typedef struct { NMPlatformAction action; } NMPlatformTfilter; -#undef __NMPlatformObjWithIfindex_COMMON - typedef struct { bool is_ip4; NMPObjectType obj_type; @@ -1045,6 +1049,27 @@ typedef enum { typedef void (*NMPlatformAsyncCallback)(GError *error, gpointer user_data); +typedef struct { + __NMPlatformObjWithIfindex_COMMON; + + guint32 id; + guint32 flags; + guint16 port; + NMIPAddr addr; + gint8 addr_family; + + /* If TRUE, then the instance was received by kernel and is inside NMPlatform + * cache. In that case, the "id" is set and acts as primary key for the instance. + * + * If FALSE, this instance is not yet configured in kernel. In this case, + * the tuple (id, addr_family, addr) is the primary key of the instance. + * This way, we can track mptcp addresses in NetworkManager internally, + * before configuring them in kernel. */ + bool in_kernel : 1; +} NMPlatformMptcpAddr; + +#undef __NMPlatformObjWithIfindex_COMMON + /*****************************************************************************/ typedef struct _NMPlatformCsmeConnInfo { @@ -2355,6 +2380,9 @@ const char *nm_platform_vlan_qos_mapping_to_string(const char *name, const char * nm_platform_wireguard_peer_to_string(const struct _NMPWireGuardPeer *peer, char *buf, gsize len); +const char * +nm_platform_mptcp_addr_to_string(const NMPlatformMptcpAddr *mptcp_addr, char *buf, gsize len); + int nm_platform_link_cmp(const NMPlatformLink *a, const NMPlatformLink *b); int nm_platform_lnk_bridge_cmp(const NMPlatformLnkBridge *a, const NMPlatformLnkBridge *b); int nm_platform_lnk_gre_cmp(const NMPlatformLnkGre *a, const NMPlatformLnkGre *b); @@ -2433,6 +2461,8 @@ int nm_platform_qdisc_cmp_full(const NMPlatformQdisc *a, gboolean compare_handle); int nm_platform_tfilter_cmp(const NMPlatformTfilter *a, const NMPlatformTfilter *b); +int nm_platform_mptcp_addr_cmp(const NMPlatformMptcpAddr *a, const NMPlatformMptcpAddr *b); + void nm_platform_link_hash_update(const NMPlatformLink *obj, NMHashState *h); void nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState *h); void nm_platform_ip6_address_hash_update(const NMPlatformIP6Address *obj, NMHashState *h); @@ -2462,6 +2492,8 @@ void nm_platform_lnk_wireguard_hash_update(const NMPlatformLnkWireGuard *obj, NM void nm_platform_qdisc_hash_update(const NMPlatformQdisc *obj, NMHashState *h); void nm_platform_tfilter_hash_update(const NMPlatformTfilter *obj, NMHashState *h); +void nm_platform_mptcp_addr_hash_update(const NMPlatformMptcpAddr *obj, NMHashState *h); + #define NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN ((gsize) 162) const char *nm_platform_link_flags2str(unsigned flags, char *buf, gsize len); diff --git a/src/libnm-platform/nmp-base.h b/src/libnm-platform/nmp-base.h index 4863168855..02420ebf4b 100644 --- a/src/libnm-platform/nmp-base.h +++ b/src/libnm-platform/nmp-base.h @@ -148,6 +148,8 @@ typedef enum _nm_packed { NMP_OBJECT_TYPE_LNK_VXLAN, NMP_OBJECT_TYPE_LNK_WIREGUARD, + NMP_OBJECT_TYPE_MPTCP_ADDR, + __NMP_OBJECT_TYPE_LAST, NMP_OBJECT_TYPE_MAX = __NMP_OBJECT_TYPE_LAST - 1, } NMPObjectType; diff --git a/src/libnm-platform/nmp-object.c b/src/libnm-platform/nmp-object.c index d281cc7be0..eb5306a66d 100644 --- a/src/libnm-platform/nmp-object.c +++ b/src/libnm-platform/nmp-object.c @@ -381,7 +381,8 @@ _idx_obj_part(const DedupMultiIdxType *idx_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE, NMP_OBJECT_TYPE_QDISC, - NMP_OBJECT_TYPE_TFILTER) + NMP_OBJECT_TYPE_TFILTER, + NMP_OBJECT_TYPE_MPTCP_ADDR) || !nmp_object_is_visible(obj_a)) { if (h) nm_hash_update_val(h, obj_a); @@ -1551,6 +1552,21 @@ _vt_cmd_plobj_id_cmp_routing_rule(const NMPlatformObject *obj1, const NMPlatform NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID); } +_vt_cmd_plobj_id_cmp(mptcp_addr, NMPlatformMptcpAddr, { + NM_CMP_FIELD(obj1, obj2, id); + NM_CMP_FIELD_UNSAFE(obj1, obj2, in_kernel); + if (!obj1->in_kernel) { + /* See comment NMPlatformMptcpAddr.in_kernel for why. */ + NM_CMP_FIELD(obj1, obj2, addr_family); + + /* nm_utils_addr_family_to_size() asserts that addr-family is either AF_INET or AF_INET6. + * This means, we cannot compare totally bogus objects. That is in particular fine + * for instances which are not "in_kernel". While we might receive unexpected values + * from kernel, we should not create them for internal purposes. */ + NM_CMP_FIELD_MEMCMP_LEN(obj1, obj2, addr, nm_utils_addr_family_to_size(obj1->addr_family)); + } +}); + void nmp_object_id_hash_update(const NMPObject *obj, NMHashState *h) { @@ -1636,6 +1652,16 @@ _vt_cmd_plobj_id_hash_update(tfilter, NMPlatformTfilter, { nm_hash_update_vals(h, obj->ifindex, obj->handle); }); +_vt_cmd_plobj_id_hash_update(mptcp_addr, NMPlatformMptcpAddr, { + if (obj->in_kernel) { + nm_hash_update_val(h, obj->id); + } else { + /* _vt_cmd_plobj_id_cmp_mptcp_addr for why. */ + nm_hash_update_vals(h, obj->id, obj->addr_family); + nm_hash_update(h, &obj->addr, nm_utils_addr_family_to_size(obj->addr_family)); + } +}); + static void _vt_cmd_plobj_hash_update_ip4_route(const NMPlatformObject *obj, NMHashState *h) { @@ -1744,6 +1770,12 @@ _vt_cmd_obj_is_alive_tfilter(const NMPObject *obj) return NMP_OBJECT_CAST_TFILTER(obj)->ifindex > 0; } +static gboolean +_vt_cmd_obj_is_alive_mptcp_addr(const NMPObject *obj) +{ + return NM_IN_SET(obj->mptcp_addr.addr_family, AF_INET, AF_INET6); +} + gboolean nmp_object_is_visible(const NMPObject *obj) { @@ -2089,6 +2121,7 @@ nmp_lookup_init_obj_type(NMPLookup *lookup, NMPObjectType obj_type) case NMP_OBJECT_TYPE_ROUTING_RULE: case NMP_OBJECT_TYPE_QDISC: case NMP_OBJECT_TYPE_TFILTER: + case NMP_OBJECT_TYPE_MPTCP_ADDR: _nmp_object_stackinit_from_type(&lookup->selector_obj, obj_type); lookup->cache_id_type = NMP_CACHE_ID_TYPE_OBJECT_TYPE; return _L(lookup); @@ -2123,7 +2156,8 @@ nmp_lookup_init_object_by_ifindex(NMPLookup *lookup, NMPObjectType obj_type, int NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE, NMP_OBJECT_TYPE_QDISC, - NMP_OBJECT_TYPE_TFILTER)); + NMP_OBJECT_TYPE_TFILTER, + NMP_OBJECT_TYPE_MPTCP_ADDR)); nm_assert(ifindex > 0 || (ifindex == 0 && NM_IN_SET(obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE))); @@ -3463,4 +3497,20 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_wireguard_hash_update, .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_wireguard_cmp, }, + [NMP_OBJECT_TYPE_MPTCP_ADDR - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_MPTCP_ADDR, + .sizeof_data = sizeof(NMPObjectMptcpAddr), + .sizeof_public = sizeof(NMPlatformMptcpAddr), + .obj_type_name = "mptcp-addr", + .supported_cache_ids = _supported_cache_ids_object, + .cmd_obj_is_alive = _vt_cmd_obj_is_alive_mptcp_addr, + .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_mptcp_addr, + .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_mptcp_addr, + .cmd_plobj_to_string_id = (CmdPlobjToStringIdFunc) nm_platform_mptcp_addr_to_string, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_mptcp_addr_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_mptcp_addr_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_mptcp_addr_cmp, + }, }; diff --git a/src/libnm-platform/nmp-object.h b/src/libnm-platform/nmp-object.h index 7d2ebf979a..5b789404a4 100644 --- a/src/libnm-platform/nmp-object.h +++ b/src/libnm-platform/nmp-object.h @@ -331,6 +331,10 @@ typedef struct { NMPlatformTfilter _public; } NMPObjectTfilter; +typedef struct { + NMPlatformMptcpAddr _public; +} NMPObjectMptcpAddr; + struct _NMPObject { union { NMDedupMultiObj parent; @@ -404,6 +408,9 @@ struct _NMPObject { NMPObjectQdisc _qdisc; NMPlatformTfilter tfilter; NMPObjectTfilter _tfilter; + + NMPlatformMptcpAddr mptcp_addr; + NMPObjectMptcpAddr _mptcp_addr; }; }; @@ -504,6 +511,8 @@ _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX(NMPObjectType obj_type) case NMP_OBJECT_TYPE_LNK_VRF: case NMP_OBJECT_TYPE_LNK_VXLAN: case NMP_OBJECT_TYPE_LNK_WIREGUARD: + + case NMP_OBJECT_TYPE_MPTCP_ADDR: return TRUE; case NMP_OBJECT_TYPE_ROUTING_RULE: @@ -565,6 +574,8 @@ _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX(NMPObjectType obj_type) _NMP_OBJECT_CAST(obj, lnk_wireguard, NMP_OBJECT_TYPE_LNK_WIREGUARD) #define NMP_OBJECT_CAST_LNK_BRIDGE(obj) \ _NMP_OBJECT_CAST(obj, lnk_bridge, NMP_OBJECT_TYPE_LNK_BRIDGE) +#define NMP_OBJECT_CAST_MPTCP_ADDR(obj) \ + _NMP_OBJECT_CAST(obj, mptcp_addr, NMP_OBJECT_TYPE_MPTCP_ADDR) static inline int NMP_OBJECT_TYPE_TO_ADDR_FAMILY(NMPObjectType obj_type)