summary refs log tree commit diff
path: root/src/libnm-platform/nmp-object.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnm-platform/nmp-object.c')
-rw-r--r--src/libnm-platform/nmp-object.c204
1 files changed, 128 insertions, 76 deletions
diff --git a/src/libnm-platform/nmp-object.c b/src/libnm-platform/nmp-object.c
index 6c177b4c..d06aa9cd 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
 
 /*****************************************************************************/
@@ -380,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);
@@ -805,13 +807,9 @@ _nmp_object_stackinit_from_class(NMPObject *obj, const NMPClass *klass)
     nm_assert(obj);
     nm_assert(klass);
 
-    *obj = (NMPObject){
-        .parent =
-            {
-                .klass      = (const NMDedupMultiObjClass *) klass,
-                ._ref_count = NM_OBJ_REF_COUNT_STACKINIT,
-            },
-    };
+    memset(obj, 0, sizeof(NMPObject));
+    obj->_class            = klass;
+    obj->parent._ref_count = NM_OBJ_REF_COUNT_STACKINIT;
     return obj;
 }
 
@@ -844,6 +842,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;
 }
 
@@ -904,7 +913,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);
@@ -912,9 +921,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) ? '+' : '-',
@@ -943,14 +952,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) {
@@ -988,15 +998,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) ? '+' : '-',
@@ -1052,17 +1062,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) ? '+' : '-',
@@ -1153,10 +1163,7 @@ _vt_cmd_obj_hash_update_link(const NMPObject *obj, NMHashState *h)
     nm_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_LINK);
 
     nm_platform_link_hash_update(&obj->link, h);
-    nm_hash_update_vals(h,
-                        obj->_link.netlink.is_in_netlink,
-                        obj->_link.wireguard_family_id,
-                        obj->_link.udev.device);
+    nm_hash_update_vals(h, obj->_link.netlink.is_in_netlink, obj->_link.udev.device);
     if (obj->_link.netlink.lnk)
         nmp_object_hash_update(obj->_link.netlink.lnk, h);
 }
@@ -1236,7 +1243,6 @@ _vt_cmd_obj_cmp_link(const NMPObject *obj1, const NMPObject *obj2)
     NM_CMP_RETURN(nm_platform_link_cmp(&obj1->link, &obj2->link));
     NM_CMP_DIRECT(obj1->_link.netlink.is_in_netlink, obj2->_link.netlink.is_in_netlink);
     NM_CMP_RETURN(nmp_object_cmp(obj1->_link.netlink.lnk, obj2->_link.netlink.lnk));
-    NM_CMP_DIRECT(obj1->_link.wireguard_family_id, obj2->_link.wireguard_family_id);
 
     if (obj1->_link.udev.device != obj2->_link.udev.device) {
         if (!obj1->_link.udev.device)
@@ -1428,21 +1434,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.
  * */
@@ -1561,6 +1552,37 @@ _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, {
+    /* The primary key of an MPTCP endpoint is only the address:port@ifindex.
+     *
+     * Which does not fully correspond to kernel's view. Kernel's view is determined
+     * by the question whether you can add two objects that only differ by one
+     * attribute. If you can, the attribute is part of the ID otherwise it isn't.
+     *
+     * Note that for kernel, the "ifindex" is not part of the identity.
+     * That is, you cannot two add two endpoints that only differ by
+     * ifindex. However, for our purpose, it is very useful to make
+     * the "ifindex" part of the identity. For example, NMPGlobalTracker will use
+     * this to track MPTCP addresses from independent callers (NML3Cfg).
+     * It would be bad, if objects that differ by "ifindex" would be
+     * combined.
+     *
+     * The "id" is intentionally not part of the identity for us. Note however, that kernel
+     * does not allow configuring duplicates "id" -- so the "id" could be a primary key
+     * as far as kernel is concerned. However, when we track MPTCP endpoints that
+     * we want to configure, the "id" is left undefined (and we let kernel choose it).
+     * If the "id" would be part of the NMPObject's ID, we could not lookup
+     * an object unless we know the "id" -- which we often don't.
+     */
+    NM_CMP_FIELD(obj1, obj2, ifindex);
+    NM_CMP_FIELD(obj1, obj2, addr_family);
+    NM_CMP_FIELD_MEMCMP_LEN(obj1,
+                            obj2,
+                            addr,
+                            nm_utils_addr_family_to_size_untrusted(obj1->addr_family));
+    NM_CMP_FIELD(obj1, obj2, port);
+});
+
 void
 nmp_object_id_hash_update(const NMPObject *obj, NMHashState *h)
 {
@@ -1646,6 +1668,12 @@ _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, {
+    /* See the corresponding ID cmp function for details. */
+    nm_hash_update_vals(h, obj->addr_family, obj->port, obj->ifindex);
+    nm_hash_update(h, &obj->addr, nm_utils_addr_family_to_size_untrusted(obj->addr_family));
+});
+
 static void
 _vt_cmd_plobj_hash_update_ip4_route(const NMPlatformObject *obj, NMHashState *h)
 {
@@ -1754,6 +1782,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, AF_UNSPEC);
+}
+
 gboolean
 nmp_object_is_visible(const NMPObject *obj)
 {
@@ -2099,6 +2133,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);
@@ -2122,7 +2157,7 @@ nmp_lookup_init_link_by_ifname(NMPLookup *lookup, const char *ifname)
 }
 
 const NMPLookup *
-nmp_lookup_init_object(NMPLookup *lookup, NMPObjectType obj_type, int ifindex)
+nmp_lookup_init_object_by_ifindex(NMPLookup *lookup, NMPObjectType obj_type, int ifindex)
 {
     NMPObject *o;
 
@@ -2133,19 +2168,11 @@ nmp_lookup_init_object(NMPLookup *lookup, NMPObjectType obj_type, int ifindex)
                         NMP_OBJECT_TYPE_IP4_ROUTE,
                         NMP_OBJECT_TYPE_IP6_ROUTE,
                         NMP_OBJECT_TYPE_QDISC,
-                        NMP_OBJECT_TYPE_TFILTER));
-
-    if (G_UNLIKELY(
-            (ifindex < 0)
-            || (ifindex == 0
-                && !NM_IN_SET(obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)))) {
-        /* This function used to have a fallback that meant to lookup all objects, if
-         * ifindex is non-positive. As routes can have a zero ifindex, that fallback is
-         * confusing and no longer supported. Only have this code, to catch accidental bugs
-         * after the API change. */
-        nm_assert_not_reached();
-        return nmp_lookup_init_obj_type(lookup, obj_type);
-    }
+                        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)));
 
     o                           = _nmp_object_stackinit_from_type(&lookup->selector_obj, obj_type);
     o->obj_with_ifindex.ifindex = ifindex;
@@ -3183,7 +3210,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,
@@ -3204,7 +3230,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,
@@ -3224,7 +3249,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,
@@ -3485,4 +3509,32 @@ 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_LNK_BOND - 1] =
+        {
+            .parent                = DEDUP_MULTI_OBJ_CLASS_INIT(),
+            .obj_type              = NMP_OBJECT_TYPE_LNK_BOND,
+            .sizeof_data           = sizeof(NMPObjectLnkBond),
+            .sizeof_public         = sizeof(NMPlatformLnkBond),
+            .obj_type_name         = "bond",
+            .lnk_link_type         = NM_LINK_TYPE_BOND,
+            .cmd_plobj_to_string   = (CmdPlobjToStringFunc) nm_platform_lnk_bond_to_string,
+            .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_bond_hash_update,
+            .cmd_plobj_cmp         = (CmdPlobjCmpFunc) nm_platform_lnk_bond_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,
+        },
 };