summary refs log tree commit diff
path: root/src/libnm-core-impl/nm-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnm-core-impl/nm-utils.c')
-rw-r--r--src/libnm-core-impl/nm-utils.c275
1 files changed, 156 insertions, 119 deletions
diff --git a/src/libnm-core-impl/nm-utils.c b/src/libnm-core-impl/nm-utils.c
index 12e3bd40..ccdd4b92 100644
--- a/src/libnm-core-impl/nm-utils.c
+++ b/src/libnm-core-impl/nm-utils.c
@@ -29,6 +29,7 @@
 #include "nm-setting-private.h"
 #include "nm-crypto.h"
 #include "nm-setting-bond.h"
+#include "nm-setting-bond-port.h"
 #include "nm-setting-bridge.h"
 #include "nm-setting-bridge-port.h"
 #include "nm-setting-infiniband.h"
@@ -759,25 +760,28 @@ _nm_utils_hash_values_to_slist(GHashTable *hash)
 }
 
 void
-_nm_utils_strdict_from_dbus(GVariant *dbus_value, GValue *prop_value)
+_nm_utils_strdict_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_GPROP_FCN_ARGS _nm_nil)
 {
     GVariantIter iter;
     const char * key, *value;
     GHashTable * hash;
 
     hash = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
-    g_variant_iter_init(&iter, dbus_value);
+    g_variant_iter_init(&iter, from);
     while (g_variant_iter_next(&iter, "{&s&s}", &key, &value))
         g_hash_table_insert(hash, g_strdup(key), g_strdup(value));
 
-    g_value_take_boxed(prop_value, hash);
+    g_value_take_boxed(to, hash);
 }
 
 const NMSettInfoPropertType nm_sett_info_propert_type_strdict =
     NM_SETT_INFO_PROPERT_TYPE_GPROP_INIT(NM_G_VARIANT_TYPE("a{ss}"),
-                                         .gprop_from_dbus_fcn = _nm_utils_strdict_from_dbus,
+                                         .typdata_from_dbus.gprop_fcn = _nm_utils_strdict_from_dbus,
                                          .typdata_to_dbus.gprop_type =
-                                             NM_SETTING_PROPERTY_TO_DBUS_FCN_GPROP_TYPE_STRDICT);
+                                             NM_SETTING_PROPERTY_TO_DBUS_FCN_GPROP_TYPE_STRDICT,
+                                         .compare_fcn   = _nm_setting_property_compare_fcn_default,
+                                         .from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop,
+                                         .from_dbus_is_full = TRUE);
 
 GHashTable *
 _nm_utils_copy_strdict(GHashTable *strdict)
@@ -835,7 +839,7 @@ _nm_utils_bytes_from_dbus(GVariant *dbus_value, GValue *prop_value)
 /*****************************************************************************/
 
 GSList *
-_nm_utils_strv_to_slist(char **strv, gboolean deep_copy)
+nm_strv_to_gslist(char **strv, gboolean deep_copy)
 {
     GSList *list = NULL;
     gsize   i;
@@ -884,7 +888,7 @@ _nm_utils_slist_to_strv(const GSList *slist, gboolean deep_copy)
 }
 
 GPtrArray *
-_nm_utils_strv_to_ptrarray(char **strv)
+nm_strv_to_ptrarray(char **strv)
 {
     GPtrArray *ptrarray;
     gsize      i, l;
@@ -1283,18 +1287,28 @@ nm_utils_wpa_psk_valid(const char *psk)
 GVariant *
 nm_utils_ip4_dns_to_variant(char **dns)
 {
+    return _nm_utils_ip4_dns_to_variant(NM_CAST_STRV_CC(dns), -1);
+}
+
+GVariant *
+_nm_utils_ip4_dns_to_variant(const char *const *dns, gssize len)
+{
     GVariantBuilder builder;
+    gsize           l;
     gsize           i;
 
+    if (len < 0)
+        l = NM_PTRARRAY_LEN(dns);
+    else
+        l = len;
+
     g_variant_builder_init(&builder, G_VARIANT_TYPE("au"));
 
-    if (dns) {
-        for (i = 0; dns[i]; i++) {
-            guint32 ip = 0;
+    for (i = 0; i < l; i++) {
+        in_addr_t ip;
 
-            inet_pton(AF_INET, dns[i], &ip);
+        if (inet_pton(AF_INET, dns[i], &ip) == 1)
             g_variant_builder_add(&builder, "u", ip);
-        }
     }
 
     return g_variant_builder_end(&builder);
@@ -1592,18 +1606,28 @@ nm_utils_ip4_get_default_prefix(guint32 ip)
 GVariant *
 nm_utils_ip6_dns_to_variant(char **dns)
 {
+    return _nm_utils_ip6_dns_to_variant(NM_CAST_STRV_CC(dns), -1);
+}
+
+GVariant *
+_nm_utils_ip6_dns_to_variant(const char *const *dns, gssize len)
+{
     GVariantBuilder builder;
     gsize           i;
+    gsize           l;
+
+    if (len < 0)
+        l = NM_PTRARRAY_LEN(dns);
+    else
+        l = len;
 
     g_variant_builder_init(&builder, G_VARIANT_TYPE("aay"));
-    if (dns) {
-        for (i = 0; dns[i]; i++) {
-            struct in6_addr ip;
+    for (i = 0; i < l; i++) {
+        struct in6_addr ip;
 
-            if (inet_pton(AF_INET6, dns[i], &ip) != 1)
-                continue;
-            g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(&ip));
-        }
+        if (inet_pton(AF_INET6, dns[i], &ip) != 1)
+            continue;
+        g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(&ip));
     }
     return g_variant_builder_end(&builder);
 }
@@ -2859,7 +2883,7 @@ _nm_sriov_vf_parse_vlans(NMSriovVF *vf, const char *str, GError **error)
     gs_free const char **vlans = NULL;
     guint                i;
 
-    vlans = nm_utils_strsplit_set(str, ";");
+    vlans = nm_strsplit_set(str, ";");
     if (!vlans) {
         g_set_error_literal(error,
                             NM_CONNECTION_ERROR,
@@ -3625,6 +3649,23 @@ nm_utils_wifi_strength_bars(guint8 strength)
         return "    ";
 }
 
+gboolean
+_nm_property_variant_to_gvalue(GVariant *src_value, GValue *dst_value)
+{
+    GValue   tmp = G_VALUE_INIT;
+    gboolean success;
+
+    g_dbus_gvariant_to_gvalue(src_value, &tmp);
+    if (G_VALUE_TYPE(&tmp) == G_VALUE_TYPE(dst_value)) {
+        *dst_value = tmp;
+        return TRUE;
+    }
+
+    success = g_value_transform(&tmp, dst_value);
+    g_value_unset(&tmp);
+    return success;
+}
+
 /**
  * nm_utils_hwaddr_len:
  * @type: the type of address; either <literal>ARPHRD_ETHER</literal> or
@@ -3857,6 +3898,25 @@ _nm_utils_hwaddr_canonical_or_invalid(const char *mac, gssize length)
         return g_strdup(mac);
 }
 
+char *
+_nm_utils_ipaddr_canonical_or_invalid(int addr_family, const char *ip)
+{
+    NMIPAddr addr_bin;
+
+    nm_assert_addr_family(addr_family);
+
+    if (!ip)
+        return NULL;
+
+    if (!nm_utils_parse_inaddr_bin(addr_family, ip, NULL, &addr_bin))
+        return g_strdup(ip);
+
+    if (nm_ip_addr_is_null(addr_family, &addr_bin))
+        return NULL;
+
+    return nm_utils_inet_ntop_dup(addr_family, &addr_bin);
+}
+
 /*
  * Determine if given Ethernet address is link-local
  *
@@ -4002,47 +4062,41 @@ nm_utils_hwaddr_to_dbus(const char *str)
     return nm_g_variant_new_ay(buf, len);
 }
 
-static GVariant *
-_nm_utils_hwaddr_cloned_get(const NMSettInfoSetting *               sett_info,
-                            guint                                   property_idx,
-                            NMConnection *                          connection,
-                            NMSetting *                             setting,
-                            NMConnectionSerializationFlags          flags,
-                            const NMConnectionSerializationOptions *options)
+GVariant *
+_nm_utils_hwaddr_cloned_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil)
 {
     gs_free char *addr = NULL;
 
-    nm_assert(nm_streq(sett_info->property_infos[property_idx].name, "cloned-mac-address"));
+    nm_assert(nm_streq(property_info->name, "cloned-mac-address"));
 
     g_object_get(setting, "cloned-mac-address", &addr, NULL);
     return nm_utils_hwaddr_to_dbus(addr);
 }
 
-static gboolean
-_nm_utils_hwaddr_cloned_set(NMSetting *         setting,
-                            GVariant *          connection_dict,
-                            const char *        property,
-                            GVariant *          value,
-                            NMSettingParseFlags parse_flags,
-                            GError **           error)
+gboolean
+_nm_utils_hwaddr_cloned_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil)
 {
     gsize         length;
     const guint8 *array;
     char *        str;
 
-    nm_assert(nm_streq0(property, "cloned-mac-address"));
+    nm_assert(nm_streq0(property_info->name, "cloned-mac-address"));
 
     if (!_nm_setting_use_legacy_property(setting,
                                          connection_dict,
                                          "cloned-mac-address",
-                                         "assigned-mac-address"))
+                                         "assigned-mac-address")) {
+        *out_is_modified = FALSE;
         return TRUE;
+    }
 
     length = 0;
     array  = g_variant_get_fixed_array(value, &length, 1);
 
-    if (!length)
+    if (!length) {
+        *out_is_modified = FALSE;
         return TRUE;
+    }
 
     str = nm_utils_hwaddr_ntoa(array, length);
     g_object_set(setting, "cloned-mac-address", str, NULL);
@@ -4050,37 +4104,22 @@ _nm_utils_hwaddr_cloned_set(NMSetting *         setting,
     return TRUE;
 }
 
-static gboolean
-_nm_utils_hwaddr_cloned_not_set(NMSetting *         setting,
-                                GVariant *          connection_dict,
-                                const char *        property,
-                                NMSettingParseFlags parse_flags,
-                                GError **           error)
+gboolean
+_nm_utils_hwaddr_cloned_not_set(_NM_SETT_INFO_PROP_MISSING_FROM_DBUS_FCN_ARGS _nm_nil)
 {
     nm_assert(nm_streq0(property, "cloned-mac-address"));
     return TRUE;
 }
 
-const NMSettInfoPropertType nm_sett_info_propert_type_cloned_mac_address =
-    NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_BYTESTRING,
-                                        .to_dbus_fcn           = _nm_utils_hwaddr_cloned_get,
-                                        .from_dbus_fcn         = _nm_utils_hwaddr_cloned_set,
-                                        .missing_from_dbus_fcn = _nm_utils_hwaddr_cloned_not_set, );
-
 static GVariant *
-_nm_utils_hwaddr_cloned_data_synth(const NMSettInfoSetting *               sett_info,
-                                   guint                                   property_idx,
-                                   NMConnection *                          connection,
-                                   NMSetting *                             setting,
-                                   NMConnectionSerializationFlags          flags,
-                                   const NMConnectionSerializationOptions *options)
+_nm_utils_hwaddr_cloned_data_synth(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil)
 {
     gs_free char *addr = NULL;
 
     if (!_nm_connection_serialize_non_secret(flags))
         return NULL;
 
-    nm_assert(nm_streq0(sett_info->property_infos[property_idx].name, "assigned-mac-address"));
+    nm_assert(nm_streq0(property_info->name, "assigned-mac-address"));
 
     g_object_get(setting, "cloned-mac-address", &addr, NULL);
 
@@ -4102,20 +4141,17 @@ _nm_utils_hwaddr_cloned_data_synth(const NMSettInfoSetting *               sett_
 }
 
 static gboolean
-_nm_utils_hwaddr_cloned_data_set(NMSetting *         setting,
-                                 GVariant *          connection_dict,
-                                 const char *        property,
-                                 GVariant *          value,
-                                 NMSettingParseFlags parse_flags,
-                                 GError **           error)
+_nm_utils_hwaddr_cloned_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil)
 {
-    nm_assert(nm_streq0(property, "assigned-mac-address"));
+    nm_assert(nm_streq0(property_info->name, "assigned-mac-address"));
 
     if (_nm_setting_use_legacy_property(setting,
                                         connection_dict,
                                         "cloned-mac-address",
-                                        "assigned-mac-address"))
+                                        "assigned-mac-address")) {
+        *out_is_modified = FALSE;
         return TRUE;
+    }
 
     g_object_set(setting,
                  "cloned-mac-address",
@@ -4126,26 +4162,10 @@ _nm_utils_hwaddr_cloned_data_set(NMSetting *         setting,
 
 const NMSettInfoPropertType nm_sett_info_propert_type_assigned_mac_address =
     NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_STRING,
+                                        .compare_fcn   = _nm_setting_property_compare_fcn_ignore,
                                         .to_dbus_fcn   = _nm_utils_hwaddr_cloned_data_synth,
                                         .from_dbus_fcn = _nm_utils_hwaddr_cloned_data_set, );
 
-static void
-_nm_utils_hwaddr_from_dbus(GVariant *dbus_value, GValue *prop_value)
-{
-    gsize         length = 0;
-    const guint8 *array  = g_variant_get_fixed_array(dbus_value, &length, 1);
-    char *        str;
-
-    str = length ? nm_utils_hwaddr_ntoa(array, length) : NULL;
-    g_value_take_string(prop_value, str);
-}
-
-const NMSettInfoPropertType nm_sett_info_propert_type_mac_address =
-    NM_SETT_INFO_PROPERT_TYPE_GPROP_INIT(
-        G_VARIANT_TYPE_BYTESTRING,
-        .gprop_from_dbus_fcn        = _nm_utils_hwaddr_from_dbus,
-        .typdata_to_dbus.gprop_type = NM_SETTING_PROPERTY_TO_DBUS_FCN_GPROP_TYPE_MAC_ADDRESS);
-
 /*****************************************************************************/
 
 /* Validate secret-flags. Most settings don't validate them, which is a bug.
@@ -4583,24 +4603,41 @@ nm_utils_check_virtual_device_compatibility(GType virtual_type, GType other_type
                          FALSE);
 
     if (virtual_type == NM_TYPE_SETTING_BOND) {
-        return (other_type == NM_TYPE_SETTING_INFINIBAND || other_type == NM_TYPE_SETTING_WIRED
-                || other_type == NM_TYPE_SETTING_BRIDGE || other_type == NM_TYPE_SETTING_BOND
-                || other_type == NM_TYPE_SETTING_TEAM || other_type == NM_TYPE_SETTING_VLAN);
-    } else if (virtual_type == NM_TYPE_SETTING_BRIDGE) {
-        return (other_type == NM_TYPE_SETTING_WIRED || other_type == NM_TYPE_SETTING_BOND
-                || other_type == NM_TYPE_SETTING_TEAM || other_type == NM_TYPE_SETTING_VLAN);
-    } else if (virtual_type == NM_TYPE_SETTING_TEAM) {
-        return (other_type == NM_TYPE_SETTING_WIRED || other_type == NM_TYPE_SETTING_BRIDGE
-                || other_type == NM_TYPE_SETTING_BOND || other_type == NM_TYPE_SETTING_TEAM
-                || other_type == NM_TYPE_SETTING_VLAN);
-    } else if (virtual_type == NM_TYPE_SETTING_VLAN) {
-        return (other_type == NM_TYPE_SETTING_WIRED || other_type == NM_TYPE_SETTING_WIRELESS
-                || other_type == NM_TYPE_SETTING_BRIDGE || other_type == NM_TYPE_SETTING_BOND
-                || other_type == NM_TYPE_SETTING_TEAM || other_type == NM_TYPE_SETTING_VLAN);
-    } else {
-        g_warn_if_reached();
-        return FALSE;
+        return NM_IN_SET(other_type,
+                         NM_TYPE_SETTING_BOND,
+                         NM_TYPE_SETTING_BRIDGE,
+                         NM_TYPE_SETTING_INFINIBAND,
+                         NM_TYPE_SETTING_TEAM,
+                         NM_TYPE_SETTING_VLAN,
+                         NM_TYPE_SETTING_WIRED,
+                         NM_TYPE_SETTING_WIRELESS);
+    }
+    if (virtual_type == NM_TYPE_SETTING_BRIDGE) {
+        return NM_IN_SET(other_type,
+                         NM_TYPE_SETTING_BOND,
+                         NM_TYPE_SETTING_TEAM,
+                         NM_TYPE_SETTING_VLAN,
+                         NM_TYPE_SETTING_WIRED);
+    }
+    if (virtual_type == NM_TYPE_SETTING_TEAM) {
+        return NM_IN_SET(other_type,
+                         NM_TYPE_SETTING_BOND,
+                         NM_TYPE_SETTING_BRIDGE,
+                         NM_TYPE_SETTING_TEAM,
+                         NM_TYPE_SETTING_VLAN,
+                         NM_TYPE_SETTING_WIRED);
+    }
+    if (virtual_type == NM_TYPE_SETTING_VLAN) {
+        return NM_IN_SET(other_type,
+                         NM_TYPE_SETTING_BOND,
+                         NM_TYPE_SETTING_BRIDGE,
+                         NM_TYPE_SETTING_TEAM,
+                         NM_TYPE_SETTING_VLAN,
+                         NM_TYPE_SETTING_WIRED,
+                         NM_TYPE_SETTING_WIRELESS);
     }
+
+    return FALSE;
 }
 
 /*****************************************************************************/
@@ -5445,18 +5482,13 @@ nm_utils_base64secret_normalize(const char *base64_key,
     return TRUE;
 }
 
-static GVariant *
-_nm_utils_bridge_vlans_to_dbus(const NMSettInfoSetting *               sett_info,
-                               guint                                   property_idx,
-                               NMConnection *                          connection,
-                               NMSetting *                             setting,
-                               NMConnectionSerializationFlags          flags,
-                               const NMConnectionSerializationOptions *options)
+GVariant *
+_nm_utils_bridge_vlans_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil)
 {
     gs_unref_ptrarray GPtrArray *vlans = NULL;
     GVariantBuilder              builder;
     guint                        i;
-    const char *                 property_name = sett_info->property_infos[property_idx].name;
+    const char *                 property_name = property_info->name;
 
     nm_assert(property_name);
 
@@ -5492,13 +5524,8 @@ _nm_utils_bridge_vlans_to_dbus(const NMSettInfoSetting *               sett_info
     return g_variant_builder_end(&builder);
 }
 
-static gboolean
-_nm_utils_bridge_vlans_from_dbus(NMSetting *         setting,
-                                 GVariant *          connection_dict,
-                                 const char *        property,
-                                 GVariant *          value,
-                                 NMSettingParseFlags parse_flags,
-                                 GError **           error)
+gboolean
+_nm_utils_bridge_vlans_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil)
 {
     gs_unref_ptrarray GPtrArray *vlans = NULL;
     GVariantIter                 vlan_iter;
@@ -5539,15 +5566,25 @@ _nm_utils_bridge_vlans_from_dbus(NMSetting *         setting,
         g_ptr_array_add(vlans, vlan);
     }
 
-    g_object_set(setting, property, vlans, NULL);
+    g_object_set(setting, property_info->name, vlans, NULL);
 
     return TRUE;
 }
 
-const NMSettInfoPropertType nm_sett_info_propert_type_bridge_vlans =
-    NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(NM_G_VARIANT_TYPE("aa{sv}"),
-                                        .to_dbus_fcn   = _nm_utils_bridge_vlans_to_dbus,
-                                        .from_dbus_fcn = _nm_utils_bridge_vlans_from_dbus, );
+NMTernary
+_nm_utils_bridge_compare_vlans(GPtrArray *vlans_a, GPtrArray *vlans_b)
+{
+    guint l = nm_g_ptr_array_len(vlans_a);
+    guint i;
+
+    if (l != nm_g_ptr_array_len(vlans_b))
+        return FALSE;
+    for (i = 0; i < l; i++) {
+        if (nm_bridge_vlan_cmp(vlans_a->pdata[i], vlans_b->pdata[i]))
+            return FALSE;
+    }
+    return TRUE;
+}
 
 gboolean
 _nm_utils_bridge_vlan_verify_list(GPtrArray * vlans,