summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Zaborowski <andrew.zaborowski@intel.com>2018-09-08 04:03:47 +0200
committerThomas Haller <thaller@redhat.com>2018-09-11 14:10:30 +0200
commit32506c8788c4481f7b33448c3e31661d4b50ab1a (patch)
tree79e59413388c8095258a277cf1e4c7d0a60ae67e
parentc87faf07a10900804b914057a2673e0e070b0af4 (diff)
downloadNetworkManager-32506c8788c4481f7b33448c3e31661d4b50ab1a.tar.gz
wifi/iwd: handle new GetOrderedNetworks() return type
The Station.GetOrderedNetworks dbus method's return type has changed in IWD commit 0a42f63d42be903a46c595693884772c1c84d39f as the last incompatible API change before IWD 0.8 (docs change was made earlier in 0453308134a3aadb6a2ec6a78ea642e19427704c) so that network names and types are no longer included in the reply. Expect this new reply signature although still handle the old signature if we're using the Device interface for IWD <= 0.7 compatibility. It may be good idea to eventually pass the object manager instance from nm-iwd-manager.c to nm-device-iwd.c to avoid using g_dbus_proxy_new_sync and g_dbus_proxy_new_for_bus_sync in act_stage2_config, which possibly generates a lot of DBus property queries. https://github.com/NetworkManager/NetworkManager/pull/197
-rw-r--r--src/devices/wifi/nm-device-iwd.c148
1 files changed, 94 insertions, 54 deletions
diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c
index 56b1f85311..32d4991679 100644
--- a/src/devices/wifi/nm-device-iwd.c
+++ b/src/devices/wifi/nm-device-iwd.c
@@ -229,6 +229,85 @@ vardict_from_network_type (const char *type)
}
static void
+insert_ap_from_network (GHashTable *aps, GDBusProxy *proxy, const char *path, int16_t signal, uint32_t ap_id)
+{
+ gs_unref_object GDBusProxy *network_proxy = NULL;
+ gs_unref_variant GVariant *name_value = NULL, *type_value = NULL;
+ const char *name, *type;
+ GVariantBuilder builder;
+ gs_unref_variant GVariant *props = NULL;
+ GVariant *rsn;
+ uint8_t bssid[6];
+ NMWifiAP *ap;
+ GError *error;
+
+ network_proxy = g_dbus_proxy_new_sync (g_dbus_proxy_get_connection (proxy),
+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+ NULL,
+ NM_IWD_SERVICE,
+ path,
+ NM_IWD_NETWORK_INTERFACE,
+ NULL, &error);
+ if (!network_proxy) {
+ g_clear_error (&error);
+ return;
+ }
+
+ name_value = g_dbus_proxy_get_cached_property (network_proxy, "Name");
+ type_value = g_dbus_proxy_get_cached_property (network_proxy, "Type");
+ if ( !name_value
+ || !g_variant_is_of_type (name_value, G_VARIANT_TYPE_STRING)
+ || !type_value
+ || !g_variant_is_of_type (type_value, G_VARIANT_TYPE_STRING))
+ return;
+
+ name = g_variant_get_string (name_value, NULL);
+ type = g_variant_get_string (type_value, NULL);
+
+ /* What we get from IWD are networks, or ESSs, that may contain
+ * multiple APs, or BSSs, each. We don't get information about any
+ * specific BSSs within an ESS but we can safely present each ESS
+ * as an individual BSS to NM, which will be seen as ESSs comprising
+ * a single BSS each. NM won't be able to handle roaming but IWD
+ * already does that. We fake the BSSIDs as they don't play any
+ * role either.
+ */
+ bssid[0] = 0x00;
+ bssid[1] = 0x01;
+ bssid[2] = 0x02;
+ bssid[3] = ap_id >> 16;
+ bssid[4] = ap_id >> 8;
+ bssid[5] = ap_id;
+
+ /* WEP not supported */
+ if (nm_streq (type, "wep"))
+ return;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add (&builder, "{sv}", "BSSID",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, bssid, 6, 1));
+ g_variant_builder_add (&builder, "{sv}", "Mode",
+ g_variant_new_string ("infrastructure"));
+
+ rsn = vardict_from_network_type (type);
+ if (rsn)
+ g_variant_builder_add (&builder, "{sv}", "RSN", rsn);
+
+ props = g_variant_new ("a{sv}", &builder);
+
+ ap = nm_wifi_ap_new_from_properties (path, props);
+
+ nm_wifi_ap_set_ssid_arr (ap,
+ (const guint8 *) name,
+ NM_MIN (32, strlen (name)));
+
+ nm_wifi_ap_set_strength (ap, nm_wifi_utils_level_to_quality (signal / 100));
+ nm_wifi_ap_set_freq (ap, 2417);
+ nm_wifi_ap_set_max_bitrate (ap, 65000);
+ g_hash_table_insert (aps, (gpointer) nm_wifi_ap_get_supplicant_path (ap), ap);
+}
+
+static void
get_ordered_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data)
{
NMDeviceIwd *self = user_data;
@@ -242,9 +321,16 @@ get_ordered_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data)
gboolean changed = FALSE;
GHashTableIter ap_iter;
gs_unref_hashtable GHashTable *new_aps = NULL;
+ /* Depending on whether we're using the Station interface or the Device
+ * interface for compatibility with IWD <= 0.7, the return signature of
+ * GetOrderedNetworks will be different.
+ */
+ gboolean compat = priv->dbus_station_proxy == priv->dbus_device_proxy;
+ const char *return_sig = compat ? "(a(osns))" : "(a(on))";
+ static uint32_t ap_id = 0;
variant = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (source), res,
- G_VARIANT_TYPE ("(a(osns))"),
+ G_VARIANT_TYPE (return_sig),
&error);
if (!variant) {
_LOGE (LOGD_WIFI, "Station.GetOrderedNetworks failed: %s",
@@ -254,60 +340,14 @@ get_ordered_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data)
new_aps = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_object_unref);
- g_variant_get (variant, "(a(osns))", &networks);
-
- while (g_variant_iter_next (networks, "(&o&sn&s)", &path, &name, &signal, &type)) {
- GVariantBuilder builder;
- gs_unref_variant GVariant *props = NULL;
- GVariant *rsn;
- static uint32_t ap_id = 0;
- uint8_t bssid[6];
+ g_variant_get (variant, return_sig, &networks);
- /*
- * What we get from IWD are networks, or ESSs, that may
- * contain multiple APs, or BSSs, each. We don't get
- * information about any specific BSSs within an ESS but
- * we can safely present each ESS as an individual BSS to
- * NM, which will be seen as ESSs comprising a single BSS
- * each. NM won't be able to handle roaming but IWD already
- * does that. We fake the BSSIDs as they don't play any
- * role either.
- */
- bssid[0] = 0x00;
- bssid[1] = 0x01;
- bssid[2] = 0x02;
- bssid[3] = ap_id >> 16;
- bssid[4] = ap_id >> 8;
- bssid[5] = ap_id++;
-
- /* WEP not supported */
- if (!strcmp (type, "wep"))
- continue;
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
- g_variant_builder_add (&builder, "{sv}", "BSSID",
- g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, bssid, 6, 1));
- g_variant_builder_add (&builder, "{sv}", "Mode",
- g_variant_new_string ("infrastructure"));
-
- rsn = vardict_from_network_type (type);
- if (rsn)
- g_variant_builder_add (&builder, "{sv}", "RSN", rsn);
-
- props = g_variant_new ("a{sv}", &builder);
-
- ap = nm_wifi_ap_new_from_properties (path, props);
-
- nm_wifi_ap_set_ssid_arr (ap,
- (const guint8 *) name,
- NM_MIN (32, strlen (name)));
-
- nm_wifi_ap_set_strength (ap, nm_wifi_utils_level_to_quality (signal / 100));
- nm_wifi_ap_set_freq (ap, 2417);
- nm_wifi_ap_set_max_bitrate (ap, 65000);
- g_hash_table_insert (new_aps,
- (gpointer) nm_wifi_ap_get_supplicant_path (ap),
- ap);
+ if (compat) {
+ while (g_variant_iter_next (networks, "(&o&sn&s)", &path, &name, &signal, &type))
+ insert_ap_from_network (new_aps, priv->dbus_station_proxy, path, signal, ap_id++);
+ } else {
+ while (g_variant_iter_next (networks, "(&on)", &path, &signal))
+ insert_ap_from_network (new_aps, priv->dbus_station_proxy, path, signal, ap_id++);
}
g_variant_iter_free (networks);