diff options
author | Andrew Zaborowski <andrew.zaborowski@intel.com> | 2018-10-05 05:35:37 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-10-11 16:07:15 +0200 |
commit | 979c632e1190aea04dae41b14c38033ab56a2285 (patch) | |
tree | e4e7e96965d4e41f0a56fc68dfaf9f8a8e45e739 | |
parent | a6f13d3c691bf4ea15e71ae76f6eaf02826f31ed (diff) | |
download | NetworkManager-979c632e1190aea04dae41b14c38033ab56a2285.tar.gz |
wifi/iwd: add Ad-hoc mode support
-rw-r--r-- | src/devices/wifi/nm-device-iwd.c | 137 |
1 files changed, 96 insertions, 41 deletions
diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c index dddbe881a7..2e6ca1ce1e 100644 --- a/src/devices/wifi/nm-device-iwd.c +++ b/src/devices/wifi/nm-device-iwd.c @@ -71,6 +71,7 @@ typedef struct { GDBusProxy * dbus_device_proxy; GDBusProxy * dbus_station_proxy; GDBusProxy * dbus_ap_proxy; + GDBusProxy * dbus_adhoc_proxy; CList aps_lst_head; NMWifiAP * current_ap; GCancellable * cancellable; @@ -637,6 +638,18 @@ check_connection_compatible (NMDevice *device, NMConnection *connection, GError "IWD backend only supports PSK authentication in AP mode"); return FALSE; } + } else if (nm_streq (mode, NM_SETTING_WIRELESS_MODE_ADHOC)) { + if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_ADHOC)) { + nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "device does not support Ad-Hoc mode"); + return FALSE; + } + + if (!NM_IN_SET (security, NM_IWD_NETWORK_SECURITY_NONE, NM_IWD_NETWORK_SECURITY_PSK)) { + nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "IWD backend only supports Open and PSK authentication in Ad-Hoc mode"); + return FALSE; + } } else { nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, "%s type profiles not supported by IWD backend"); @@ -680,17 +693,11 @@ check_connection_available (NMDevice *device, } } - /* AP connections can be activated independent of the scan list */ + /* AP and Ad-Hoc connections can be activated independent of the scan list */ mode = nm_setting_wireless_get_mode (s_wifi); - if (NM_IN_STRSET (mode, NM_SETTING_WIRELESS_MODE_AP)) + if (NM_IN_STRSET (mode, NM_SETTING_WIRELESS_MODE_AP, NM_SETTING_WIRELESS_MODE_ADHOC)) return TRUE; - if (!NM_IN_STRSET (mode, NULL, NM_SETTING_WIRELESS_MODE_INFRA)) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "only AP and infrastructure modes supported by IWD backend"); - return FALSE; - } - /* 8021x networks can only be used if they've been provisioned on the IWD side and * thus are Known Networks. */ @@ -762,11 +769,16 @@ complete_connection (NMDevice *device, /* Find a compatible AP in the scan list */ ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); if (!ap) { - g_set_error_literal (error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "No compatible AP in the scan list and hidden SSIDs not supported."); - return FALSE; + if (!nm_streq0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC)) { + g_set_error_literal (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "No compatible AP in the scan list and hidden SSIDs not supported."); + return FALSE; + } + + if (!nm_setting_verify (NM_SETTING (s_wifi), connection, error)) + return FALSE; } } else { ap = nm_wifi_ap_lookup_for_device (NM_DEVICE (self), specific_object); @@ -1485,9 +1497,9 @@ error: reset_mode (self, priv->cancellable, act_failed_cb, self); } -/* Check if we're activating an AP connection and if the target - * DBus interface has appeared already. If so proceed to call Start on - * that interface. +/* Check if we're activating an AP/AdHoc connection and if the target + * DBus interface has appeared already. If so proceed to call Start or + * StartOpen on that interface. */ static void act_check_interface (NMDeviceIwd *self) { @@ -1497,12 +1509,10 @@ static void act_check_interface (NMDeviceIwd *self) NMConnection *connection; NMSettingWireless *s_wireless; NMSettingWirelessSecurity *s_wireless_sec; + GDBusProxy *proxy = NULL; GBytes *ssid; gs_free char *ssid_utf8 = NULL; - const char *psk; - - if (!priv->dbus_ap_proxy) - return; + const char *mode; if (!priv->act_mode_switch) return; @@ -1510,6 +1520,15 @@ static void act_check_interface (NMDeviceIwd *self) connection = nm_device_get_settings_connection_get_connection (device); s_wireless = nm_connection_get_setting_wireless (connection); + mode = nm_setting_wireless_get_mode (s_wireless); + if (nm_streq0 (mode, NM_SETTING_WIRELESS_MODE_AP)) + proxy = priv->dbus_ap_proxy; + else if (nm_streq0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC)) + proxy = priv->dbus_adhoc_proxy; + + if (!proxy) + return; + priv->act_mode_switch = FALSE; if (!NM_IN_SET (nm_device_get_state (device), NM_DEVICE_STATE_CONFIG)) @@ -1523,18 +1542,26 @@ static void act_check_interface (NMDeviceIwd *self) s_wireless_sec = nm_connection_get_setting_wireless_security (connection); - psk = nm_setting_wireless_security_get_psk (s_wireless_sec); - if (!psk) { - _LOGE (LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) No PSK for '%s'.", - ssid_utf8); - goto failed; - } + if (!s_wireless_sec) { + g_dbus_proxy_call (proxy, "StartOpen", + g_variant_new ("(s)", ssid_utf8), + G_DBUS_CALL_FLAGS_NONE, G_MAXINT, + priv->cancellable, act_start_cb, self); + } else { + const char *psk = nm_setting_wireless_security_get_psk (s_wireless_sec); - g_dbus_proxy_call (priv->dbus_ap_proxy, "Start", - g_variant_new ("(ss)", ssid_utf8, psk), - G_DBUS_CALL_FLAGS_NONE, G_MAXINT, - priv->cancellable, act_start_cb, self); + if (!psk) { + _LOGE (LOGD_DEVICE | LOGD_WIFI, + "Activation: (wifi) No PSK for '%s'.", + ssid_utf8); + goto failed; + } + + g_dbus_proxy_call (proxy, "Start", + g_variant_new ("(ss)", ssid_utf8, psk), + G_DBUS_CALL_FLAGS_NONE, G_MAXINT, + priv->cancellable, act_start_cb, self); + } _LOGD (LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) Called Start('%s').", @@ -1734,12 +1761,16 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) priv->cancellable, network_connect_cb, self); g_object_unref (network_proxy); - } else if (NM_IN_STRSET (mode, NM_SETTING_WIRELESS_MODE_AP)) { - /* We need to first set interface mode (Device.Mode) to ap. - * We can't directly queue a call to the Start method on + } else if (NM_IN_STRSET (mode, NM_SETTING_WIRELESS_MODE_AP, NM_SETTING_WIRELESS_MODE_ADHOC)) { + const char *iwd_mode; + + /* We need to first set interface mode (Device.Mode) to ap or ad-hoc. + * We can't directly queue a call to the Start/StartOpen method on * the DBus interface that's going to be created after the property * set call returns. */ + iwd_mode = nm_streq (mode, NM_SETTING_WIRELESS_MODE_AP) ? "ap" : "ad-hoc"; + if (!priv->cancellable) priv->cancellable = g_cancellable_new (); @@ -1747,7 +1778,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) DBUS_INTERFACE_PROPERTIES ".Set", g_variant_new ("(ssv)", NM_IWD_DEVICE_INTERFACE, "Mode", - g_variant_new ("s", "ap")), + g_variant_new ("s", iwd_mode)), G_DBUS_CALL_FLAGS_NONE, 2000, priv->cancellable, act_set_mode_cb, self); priv->act_mode_switch = TRUE; @@ -2102,8 +2133,8 @@ station_properties_changed (GDBusProxy *proxy, GVariant *changed_properties, } static void -ap_properties_changed (GDBusProxy *proxy, GVariant *changed_properties, - GStrv invalidate_properties, gpointer user_data) +ap_adhoc_properties_changed (GDBusProxy *proxy, GVariant *changed_properties, + GStrv invalidate_properties, gpointer user_data) { NMDeviceIwd *self = user_data; GVariantIter *iter; @@ -2115,7 +2146,7 @@ ap_properties_changed (GDBusProxy *proxy, GVariant *changed_properties, if (nm_streq (key, "Started")) { gboolean new_started = get_variant_boolean (value, "Started"); - _LOGI (LOGD_DEVICE | LOGD_WIFI, "IWD AP state is now %s", new_started ? "Started" : "Stopped"); + _LOGI (LOGD_DEVICE | LOGD_WIFI, "IWD AP/AdHoc state is now %s", new_started ? "Started" : "Stopped"); } g_variant_unref (value); @@ -2139,14 +2170,14 @@ powered_changed (NMDeviceIwd *self, gboolean new_powered) if (priv->dbus_ap_proxy) { g_signal_handlers_disconnect_by_func (priv->dbus_ap_proxy, - ap_properties_changed, self); + ap_adhoc_properties_changed, self); g_clear_object (&priv->dbus_ap_proxy); } if (interface) { priv->dbus_ap_proxy = G_DBUS_PROXY (interface); g_signal_connect (priv->dbus_ap_proxy, "g-properties-changed", - G_CALLBACK (ap_properties_changed), self); + G_CALLBACK (ap_adhoc_properties_changed), self); if (priv->act_mode_switch) act_check_interface (self); @@ -2154,7 +2185,30 @@ powered_changed (NMDeviceIwd *self, gboolean new_powered) reset_mode (self, NULL, NULL, NULL); } - if (new_powered && !priv->dbus_ap_proxy) { + interface = new_powered ? g_dbus_object_get_interface (priv->dbus_obj, NM_IWD_ADHOC_INTERFACE) : NULL; + + if (priv->dbus_adhoc_proxy) { + g_signal_handlers_disconnect_by_func (priv->dbus_adhoc_proxy, + ap_adhoc_properties_changed, self); + g_clear_object (&priv->dbus_adhoc_proxy); + } + + if (interface) { + priv->dbus_adhoc_proxy = G_DBUS_PROXY (interface); + g_signal_connect (priv->dbus_adhoc_proxy, "g-properties-changed", + G_CALLBACK (ap_adhoc_properties_changed), self); + + if (priv->act_mode_switch) + act_check_interface (self); + else + reset_mode (self, NULL, NULL, NULL); + } + + /* We expect one of the three interfaces to always be present when + * device is Powered so if AP and AdHoc are not present we should + * be in station mode. + */ + if (new_powered && !priv->dbus_ap_proxy && !priv->dbus_adhoc_proxy) { interface = g_dbus_object_get_interface (priv->dbus_obj, NM_IWD_STATION_INTERFACE); if (!interface) { /* No Station interface on the device object. Check if the @@ -2422,6 +2476,7 @@ dispose (GObject *object) g_clear_object (&priv->dbus_device_proxy); g_clear_object (&priv->dbus_station_proxy); g_clear_object (&priv->dbus_ap_proxy); + g_clear_object (&priv->dbus_adhoc_proxy); g_clear_object (&priv->dbus_obj); remove_all_aps (self); |