summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2021-06-24 22:37:36 +0200
committerThomas Haller <thaller@redhat.com>2021-07-01 11:04:22 +0200
commit4a4f214722e29ae437f428dcb803e4b63f74f617 (patch)
tree07793fa405700ae23a03f4fcf75bb4843f411670
parentd9ebcc8646ebd815e5b47d04aff8e9921adb7d6c (diff)
downloadNetworkManager-4a4f214722e29ae437f428dcb803e4b63f74f617.tar.gz
libnm: special handle serialization to D-Bus for "wifi.seen-bssid"
"wifi.seen-bssid" is an unusual property, therefore very ugly due to the inconsistency. It is not a regular user configuration that makes sense to store to disk or modify by the user. It gets populated by the daemon, and stored in "/var/lib/NetworkManager/seen-bssids" file. As such, how to convert this to/from D-Bus needs special handling. This means, that the to/from D-Bus functions will only serialize the property when the seen-bssids are specified via NMConnectionSerializationOptions, which is what the daemon does. Also, the daemon ignores seen-bssids when parsing the variant. This has the odd effect that when the client converts a setting to GVariant, the seen-bssids gets lost. That means, a conversion to GVariant and back looses information. I think that is OK in this case, because the main point of to/from D-Bus is not to have a lossless GVariant representation of a setting, but to transfer the setting via D-Bus between client and daemon. And transferring seen-bssids via D-Bus makes only sense from the daemon to the client.
-rw-r--r--src/libnm-core-impl/nm-setting-wireless.c60
1 files changed, 51 insertions, 9 deletions
diff --git a/src/libnm-core-impl/nm-setting-wireless.c b/src/libnm-core-impl/nm-setting-wireless.c
index 111116965a..5bdedf9bfb 100644
--- a/src/libnm-core-impl/nm-setting-wireless.c
+++ b/src/libnm-core-impl/nm-setting-wireless.c
@@ -750,19 +750,54 @@ _to_dbus_fcn_seen_bssids(const NMSettInfoSetting * sett_info,
NMConnectionSerializationFlags flags,
const NMConnectionSerializationOptions *options)
{
+ if (options && options->seen_bssids)
+ return options->seen_bssids[0] ? g_variant_new_strv(options->seen_bssids, -1) : NULL;
+
+ /* The seen-bssid property is special. It cannot be converted to D-Bus
+ * like regular properties, only via the "options".
+ *
+ * This basically means, that only the daemon can provide seen-bssids as GVariant,
+ * while when a client converts the property to GVariant, it gets lost.
+ *
+ * This has the odd effect, that when the client converts the setting to GVariant
+ * and back, the seen-bssids gets lost. That is kinda desired here, because the to_dbus_fcn()
+ * and from_dbus_fcn() have the meaning of how a setting gets transferred via D-Bus,
+ * and not necessarily a loss-less conversion into another format and back. And when
+ * transferring via D-Bus, then the option makes only sense when sending it from
+ * the daemon to the client, not otherwise. */
+ return NULL;
+}
+
+static gboolean
+_from_dbus_fcn_seen_bssids(NMSetting * setting,
+ GVariant * connection_dict,
+ const char * property,
+ GVariant * value,
+ NMSettingParseFlags parse_flags,
+ GError ** error)
+{
NMSettingWirelessPrivate *priv;
+ gs_free const char ** s = NULL;
+ gsize len;
+ gsize i;
- if (options && options->seen_bssids) {
- return options->seen_bssids[0] ? g_variant_new_strv(options->seen_bssids, -1) : NULL;
+ if (_nm_utils_is_manager_process) {
+ /* in the manager process, we don't accept seen-bssid from the client.
+ * Do nothing. */
+ return TRUE;
}
priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting);
- if (!priv->seen_bssids || priv->seen_bssids->len == 0)
- return NULL;
+ nm_clear_pointer(&priv->seen_bssids, g_ptr_array_unref);
- return g_variant_new_strv((const char *const *) priv->seen_bssids->pdata,
- priv->seen_bssids->len);
+ s = g_variant_get_strv(value, &len);
+ if (len > 0) {
+ priv->seen_bssids = g_ptr_array_new_full(len, g_free);
+ for (i = 0; i < len; i++)
+ g_ptr_array_add(priv->seen_bssids, g_strdup(s[i]));
+ }
+ return TRUE;
}
/**
@@ -1075,12 +1110,18 @@ compare_property(const NMSettInfoSetting *sett_info,
NMSetting * set_b,
NMSettingCompareFlags flags)
{
- if (nm_streq(sett_info->property_infos[property_idx].name,
- NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS)) {
+ if (sett_info->property_infos[property_idx].param_spec
+ == obj_properties[PROP_CLONED_MAC_ADDRESS]) {
return !set_b
|| nm_streq0(NM_SETTING_WIRELESS_GET_PRIVATE(set_a)->cloned_mac_address,
NM_SETTING_WIRELESS_GET_PRIVATE(set_b)->cloned_mac_address);
}
+ if (sett_info->property_infos[property_idx].param_spec == obj_properties[PROP_SEEN_BSSIDS]) {
+ return !set_b
+ || (nm_strv_ptrarray_cmp(NM_SETTING_WIRELESS_GET_PRIVATE(set_a)->seen_bssids,
+ NM_SETTING_WIRELESS_GET_PRIVATE(set_b)->seen_bssids)
+ == 0);
+ }
return NM_SETTING_CLASS(nm_setting_wireless_parent_class)
->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags);
@@ -1744,7 +1785,8 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass)
properties_override,
obj_properties[PROP_SEEN_BSSIDS],
NM_SETT_INFO_PROPERT_TYPE_DBUS(G_VARIANT_TYPE_STRING_ARRAY,
- .to_dbus_fcn = _to_dbus_fcn_seen_bssids, ));
+ .to_dbus_fcn = _to_dbus_fcn_seen_bssids,
+ .from_dbus_fcn = _from_dbus_fcn_seen_bssids, ));
/**
* NMSettingWireless:mtu: