From 631ca80692e4caec0b90e2301bbe5378889ad944 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 7 Nov 2016 15:57:03 -0600 Subject: [PATCH 1/4] devices/wifi: flip meaning of scanning allowed signal Change it to return TRUE when scanning is prohibited so that we don't have to use use g_signal_emitv() and its special handling of return values. Make the return value only change when we don't want the default behavior (which would be to allow the scan). Also add a parameter to the signal indicating whether the scan is user/dbus-requested or whether it's an internal periodic scan. --- src/devices/wifi/nm-device-olpc-mesh.c | 8 +- src/devices/wifi/nm-device-wifi.c | 100 ++++++++++--------------- src/devices/wifi/nm-device-wifi.h | 2 +- 3 files changed, 45 insertions(+), 65 deletions(-) diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index 248119317e..082c573674 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -312,13 +312,13 @@ companion_state_changed_cb (NMDeviceWifi *companion, } static gboolean -companion_scan_allowed_cb (NMDeviceWifi *companion, gpointer user_data) +companion_scan_prohibited_cb (NMDeviceWifi *companion, gpointer user_data) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); NMDeviceState state = nm_device_get_state (NM_DEVICE (self)); /* Don't allow the companion to scan while configuring the mesh interface */ - return (state < NM_DEVICE_STATE_PREPARE) || (state > NM_DEVICE_STATE_IP_CONFIG); + return (state >= NM_DEVICE_STATE_PREPARE) && (state <= NM_DEVICE_STATE_IP_CONFIG); } static gboolean @@ -358,8 +358,8 @@ check_companion (NMDeviceOlpcMesh *self, NMDevice *other) g_signal_connect (G_OBJECT (other), "notify::" NM_DEVICE_WIFI_SCANNING, G_CALLBACK (companion_notify_cb), self); - g_signal_connect (G_OBJECT (other), NM_DEVICE_WIFI_SCANNING_ALLOWED, - G_CALLBACK (companion_scan_allowed_cb), self); + g_signal_connect (G_OBJECT (other), NM_DEVICE_WIFI_SCANNING_PROHIBITED, + G_CALLBACK (companion_scan_prohibited_cb), self); g_signal_connect (G_OBJECT (other), NM_DEVICE_AUTOCONNECT_ALLOWED, G_CALLBACK (companion_autoconnect_allowed_cb), self); diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 9638a40c26..3219ba6259 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -79,7 +79,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceWifi, enum { ACCESS_POINT_ADDED, ACCESS_POINT_REMOVED, - SCANNING_ALLOWED, + SCANNING_PROHIBITED, LAST_SIGNAL }; @@ -134,7 +134,7 @@ struct _NMDeviceWifiClass NMDeviceClass parent; /* Signals */ - gboolean (*scanning_allowed) (NMDeviceWifi *device); + gboolean (*scanning_prohibited) (NMDeviceWifi *device, gboolean periodic); }; /*****************************************************************************/ @@ -145,7 +145,7 @@ G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) /*****************************************************************************/ -static gboolean check_scanning_allowed (NMDeviceWifi *self); +static gboolean check_scanning_prohibited (NMDeviceWifi *self, gboolean periodic); static void schedule_scan (NMDeviceWifi *self, gboolean backoff); @@ -183,7 +183,7 @@ static void supplicant_iface_notify_current_bss (NMSupplicantInterface *iface, GParamSpec *pspec, NMDeviceWifi *self); -static void request_wireless_scan (NMDeviceWifi *self, gboolean force_if_scanning, GVariant *scan_options); +static void request_wireless_scan (NMDeviceWifi *self, gboolean periodic, gboolean force_if_scanning, GVariant *scan_options); static void ap_add_remove (NMDeviceWifi *self, guint signum, @@ -569,7 +569,7 @@ deactivate (NMDevice *device) /* Ensure we trigger a scan after deactivating a Hotspot */ if (old_mode == NM_802_11_MODE_AP) - request_wireless_scan (self, FALSE, NULL); + request_wireless_scan (self, FALSE, FALSE, NULL); } static void @@ -1193,11 +1193,11 @@ _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset) } static void -request_scan_cb (NMDevice *device, - GDBusMethodInvocation *context, - NMAuthSubject *subject, - GError *error, - gpointer user_data) +dbus_request_scan_cb (NMDevice *device, + GDBusMethodInvocation *context, + NMAuthSubject *subject, + GError *error, + gpointer user_data) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); NMDeviceWifiPrivate *priv; @@ -1208,7 +1208,7 @@ request_scan_cb (NMDevice *device, return; } - if (!check_scanning_allowed (self)) { + if (check_scanning_prohibited (self, FALSE)) { g_dbus_method_invocation_return_error_literal (context, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ALLOWED, @@ -1218,7 +1218,7 @@ request_scan_cb (NMDevice *device, priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - request_wireless_scan (self, FALSE, new_scan_options); + request_wireless_scan (self, FALSE, FALSE, new_scan_options); g_dbus_method_invocation_return_value (context, NULL); } @@ -1266,22 +1266,22 @@ impl_device_wifi_request_scan (NMDeviceWifi *self, NULL, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE, - request_scan_cb, + dbus_request_scan_cb, options ? g_variant_ref (options) : NULL); } static gboolean -scanning_allowed (NMDeviceWifi *self) +scanning_prohibited (NMDeviceWifi *self, gboolean periodic) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMSupplicantInterfaceState supplicant_state; NMConnection *connection; - g_return_val_if_fail (priv->sup_iface != NULL, FALSE); + g_return_val_if_fail (priv->sup_iface != NULL, TRUE); /* Scanning not done in AP mode */ if (priv->mode == NM_802_11_MODE_AP) - return FALSE; + return TRUE; switch (nm_device_get_state (NM_DEVICE (self))) { case NM_DEVICE_STATE_UNKNOWN: @@ -1294,25 +1294,25 @@ scanning_allowed (NMDeviceWifi *self) case NM_DEVICE_STATE_IP_CHECK: case NM_DEVICE_STATE_SECONDARIES: case NM_DEVICE_STATE_DEACTIVATING: - /* Don't scan when unusable or activating */ - return FALSE; + /* Prohibit scans when unusable or activating */ + return TRUE; case NM_DEVICE_STATE_DISCONNECTED: case NM_DEVICE_STATE_FAILED: /* Can always scan when disconnected */ - return TRUE; + return FALSE; case NM_DEVICE_STATE_ACTIVATED: /* Need to do further checks when activated */ break; } - /* Don't scan if the supplicant is busy */ + /* Prohibit scans if the supplicant is busy */ supplicant_state = nm_supplicant_interface_get_state (priv->sup_iface); if ( supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING || supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED || supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE || supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE || nm_supplicant_interface_get_scanning (priv->sup_iface)) - return FALSE; + return TRUE; connection = nm_device_get_applied_connection (NM_DEVICE (self)); if (connection) { @@ -1323,7 +1323,7 @@ scanning_allowed (NMDeviceWifi *self) ip4_method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); if (!strcmp (ip4_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) - return FALSE; + return TRUE; /* Don't scan when the connection is locked to a specifc AP, since * intra-ESS roaming (which requires periodic scanning) isn't being @@ -1332,40 +1332,20 @@ scanning_allowed (NMDeviceWifi *self) s_wifi = nm_connection_get_setting_wireless (connection); g_assert (s_wifi); if (nm_setting_wireless_get_bssid (s_wifi)) - return FALSE; + return TRUE; } - return TRUE; + /* Allow the scan */ + return FALSE; } static gboolean -scanning_allowed_accumulator (GSignalInvocationHint *ihint, - GValue *return_accu, - const GValue *handler_return, - gpointer data) +check_scanning_prohibited (NMDeviceWifi *self, gboolean periodic) { - if (!g_value_get_boolean (handler_return)) - g_value_set_boolean (return_accu, FALSE); - return TRUE; -} + gboolean prohibited = FALSE; -static gboolean -check_scanning_allowed (NMDeviceWifi *self) -{ - GValue instance = G_VALUE_INIT; - GValue retval = G_VALUE_INIT; - - g_value_init (&instance, G_TYPE_OBJECT); - g_value_take_object (&instance, self); - - g_value_init (&retval, G_TYPE_BOOLEAN); - g_value_set_boolean (&retval, TRUE); - - /* Use g_signal_emitv() rather than g_signal_emit() to avoid the return - * value being changed if no handlers are connected */ - g_signal_emitv (&instance, signals[SCANNING_ALLOWED], 0, &retval); - - return g_value_get_boolean (&retval); + g_signal_emit (self, signals[SCANNING_PROHIBITED], 0, periodic, &prohibited); + return prohibited; } static gboolean @@ -1462,7 +1442,7 @@ ssids_options_to_ptrarray (GVariant *value) } static void -request_wireless_scan (NMDeviceWifi *self, gboolean force_if_scanning, GVariant *scan_options) +request_wireless_scan (NMDeviceWifi *self, gboolean periodic, gboolean force_if_scanning, GVariant *scan_options) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); gboolean request_started = FALSE; @@ -1474,7 +1454,7 @@ request_wireless_scan (NMDeviceWifi *self, gboolean force_if_scanning, GVariant return; } - if (check_scanning_allowed (self)) { + if (!check_scanning_prohibited (self, periodic)) { gs_unref_ptrarray GPtrArray *ssids = NULL; _LOGD (LOGD_WIFI, "wifi-scan: scanning requested"); @@ -1531,7 +1511,7 @@ request_wireless_scan_periodic (gpointer user_data) NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); priv->pending_scan_id = 0; - request_wireless_scan (self, FALSE, NULL); + request_wireless_scan (self, TRUE, FALSE, NULL); return G_SOURCE_REMOVE; } @@ -2242,7 +2222,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, /* we would clear _requested_scan_set() and trigger a new scan. * However, we don't want to cancel the current pending action, so force * a new scan request. */ - request_wireless_scan (self, TRUE, NULL); + request_wireless_scan (self, FALSE, TRUE, NULL); break; default: break; @@ -3190,7 +3170,7 @@ device_state_changed (NMDevice *device, case NM_DEVICE_STATE_DISCONNECTED: /* Kick off a scan to get latest results */ priv->scan_interval = SCAN_INTERVAL_MIN; - request_wireless_scan (self, FALSE, NULL); + request_wireless_scan (self, FALSE, FALSE, NULL); break; default: break; @@ -3456,7 +3436,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) parent_class->state_changed = device_state_changed; - klass->scanning_allowed = scanning_allowed; + klass->scanning_prohibited = scanning_prohibited; obj_properties[PROP_MODE] = g_param_spec_uint (NM_DEVICE_WIFI_MODE, "", "", @@ -3517,13 +3497,13 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) G_TYPE_NONE, 1, NM_TYPE_WIFI_AP); - signals[SCANNING_ALLOWED] = - g_signal_new (NM_DEVICE_WIFI_SCANNING_ALLOWED, + signals[SCANNING_PROHIBITED] = + g_signal_new (NM_DEVICE_WIFI_SCANNING_PROHIBITED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_allowed), - scanning_allowed_accumulator, NULL, NULL, - G_TYPE_BOOLEAN, 0); + G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_prohibited), + NULL, NULL, NULL, + G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN); nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), NMDBUS_TYPE_DEVICE_WIFI_SKELETON, diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h index 024fe0efe8..09707d4f4b 100644 --- a/src/devices/wifi/nm-device-wifi.h +++ b/src/devices/wifi/nm-device-wifi.h @@ -44,7 +44,7 @@ #define NM_DEVICE_WIFI_ACCESS_POINT_REMOVED "access-point-removed" /* internal signals */ -#define NM_DEVICE_WIFI_SCANNING_ALLOWED "scanning-allowed" +#define NM_DEVICE_WIFI_SCANNING_PROHIBITED "scanning-prohibited" typedef struct _NMDeviceWifi NMDeviceWifi; typedef struct _NMDeviceWifiClass NMDeviceWifiClass; From fd6ddcc794949ded253dde063fcbddc35054081b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 7 Nov 2016 16:13:34 -0600 Subject: [PATCH 2/4] devices/wifi: delegate connected periodic scanning to the supplicant (bgo #766482) Enable background scanning for most WiFi connections except for shared/AP and BSSID-locked ones. Make the non-WPA-Enterprise interval very, very long to effectively disable periodic scanning while connected. Related: https://bugzilla.gnome.org/show_bug.cgi?id=766482 --- src/devices/wifi/nm-device-wifi.c | 40 +- src/supplicant/nm-supplicant-config.c | 57 +- src/supplicant/nm-supplicant-config.h | 4 + src/supplicant/tests/test-supplicant-config.c | 595 ++++++++---------- 4 files changed, 318 insertions(+), 378 deletions(-) diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 3219ba6259..d48513c02c 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -1275,12 +1275,13 @@ scanning_prohibited (NMDeviceWifi *self, gboolean periodic) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMSupplicantInterfaceState supplicant_state; - NMConnection *connection; g_return_val_if_fail (priv->sup_iface != NULL, TRUE); - /* Scanning not done in AP mode */ - if (priv->mode == NM_802_11_MODE_AP) + /* Don't scan when a an AP or Ad-Hoc connection is active as it will + * disrupt connected clients or peers. + */ + if (priv->mode == NM_802_11_MODE_ADHOC || priv->mode == NM_802_11_MODE_AP) return TRUE; switch (nm_device_get_state (NM_DEVICE (self))) { @@ -1301,7 +1302,12 @@ scanning_prohibited (NMDeviceWifi *self, gboolean periodic) /* Can always scan when disconnected */ return FALSE; case NM_DEVICE_STATE_ACTIVATED: - /* Need to do further checks when activated */ + /* Prohibit periodic scans when connected; we ask the supplicant to + * background scan for us, unless the connection is locked to a specifc + * BSSID. + */ + if (periodic) + return TRUE; break; } @@ -1314,27 +1320,6 @@ scanning_prohibited (NMDeviceWifi *self, gboolean periodic) || nm_supplicant_interface_get_scanning (priv->sup_iface)) return TRUE; - connection = nm_device_get_applied_connection (NM_DEVICE (self)); - if (connection) { - NMSettingWireless *s_wifi; - const char *ip4_method = NULL; - - /* Don't scan when a shared connection is active; it makes drivers mad */ - ip4_method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); - - if (!strcmp (ip4_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) - return TRUE; - - /* Don't scan when the connection is locked to a specifc AP, since - * intra-ESS roaming (which requires periodic scanning) isn't being - * used due to the specific AP lock. (bgo #513820) - */ - s_wifi = nm_connection_get_setting_wireless (connection); - g_assert (s_wifi); - if (nm_setting_wireless_get_bssid (s_wifi)) - return TRUE; - } - /* Allow the scan */ return FALSE; } @@ -2508,6 +2493,11 @@ build_supplicant_config (NMDeviceWifi *self, goto error; } + if (!nm_supplicant_config_add_bgscan (config, connection, error)) { + g_prefix_error (error, "bgscan: "); + goto error; + } + s_wireless_sec = nm_connection_get_setting_wireless_security (connection); if (s_wireless_sec) { NMSetting8021x *s_8021x; diff --git a/src/supplicant/nm-supplicant-config.c b/src/supplicant/nm-supplicant-config.c index 3f607420c6..71d2f2cc4a 100644 --- a/src/supplicant/nm-supplicant-config.c +++ b/src/supplicant/nm-supplicant-config.c @@ -31,6 +31,7 @@ #include "nm-auth-subject.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" +#include "nm-setting-ip4-config.h" typedef struct { char *value; @@ -537,6 +538,56 @@ nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self, return TRUE; } +gboolean +nm_supplicant_config_add_bgscan (NMSupplicantConfig *self, + NMConnection *connection, + GError **error) +{ + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + const char *bgscan; + + s_wifi = nm_connection_get_setting_wireless (connection); + g_assert (s_wifi); + + /* Don't scan when a shared connection (either AP or Ad-Hoc) is active; + * it will disrupt connected clients. + */ + if (NM_IN_STRSET (nm_setting_wireless_get_mode (s_wifi), + NM_SETTING_WIRELESS_MODE_AP, + NM_SETTING_WIRELESS_MODE_ADHOC)) + return TRUE; + + /* Don't scan when the connection is locked to a specifc AP, since + * intra-ESS roaming (which requires periodic scanning) isn't being + * used due to the specific AP lock. (bgo #513820) + */ + if (nm_setting_wireless_get_bssid (s_wifi)) + return TRUE; + + /* Default to a very long bgscan interval when signal is OK on the assumption + * that either (a) there aren't multiple APs and we don't need roaming, or + * (b) since EAP/802.1x isn't used and thus there are fewer steps to fail + * during a roam, we can wait longer before scanning for roam candidates. + */ + bgscan = "simple:30:-80:86400"; + + /* If using WPA Enterprise or Dynamic WEP use a shorter bgscan interval on + * the assumption that this is a multi-AP ESS in which we want more reliable + * roaming between APs. Thus trigger scans when the signal is still somewhat + * OK so we have an up-to-date roam candidate list when the signal gets bad. + */ + s_wsec = nm_connection_get_setting_wireless_security (connection); + if (s_wsec) { + if (NM_IN_STRSET (nm_setting_wireless_security_get_key_mgmt (s_wsec), + "ieee8021x", + "wpa-eap")) + bgscan = "simple:30:-65:300"; + } + + return nm_supplicant_config_add_option (self, "bgscan", bgscan, -1, FALSE, error); +} + static gboolean add_string_val (NMSupplicantConfig *self, const char *field, @@ -836,12 +887,6 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self, } if (!strcmp (key_mgmt, "wpa-eap")) { - /* If using WPA Enterprise, enable optimized background scanning - * to ensure roaming within an ESS works well. - */ - if (!nm_supplicant_config_add_option (self, "bgscan", "simple:30:-65:300", -1, NULL, error)) - return FALSE; - /* When using WPA-Enterprise, we want to use Proactive Key Caching (also * called Opportunistic Key Caching) to avoid full EAP exchanges when * roaming between access points in the same mobility group. diff --git a/src/supplicant/nm-supplicant-config.h b/src/supplicant/nm-supplicant-config.h index 93fc57ce3a..d90d82b818 100644 --- a/src/supplicant/nm-supplicant-config.h +++ b/src/supplicant/nm-supplicant-config.h @@ -55,6 +55,10 @@ gboolean nm_supplicant_config_add_setting_wireless (NMSupplicantConfig *self, guint32 fixed_freq, GError **error); +gboolean nm_supplicant_config_add_bgscan (NMSupplicantConfig *self, + NMConnection *connection, + GError **error); + gboolean nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self, NMSettingWirelessSecurity *setting, NMSetting8021x *setting_8021x, diff --git a/src/supplicant/tests/test-supplicant-config.c b/src/supplicant/tests/test-supplicant-config.c index 2583e8f0c4..4b4a4935d1 100644 --- a/src/supplicant/tests/test-supplicant-config.c +++ b/src/supplicant/tests/test-supplicant-config.c @@ -42,16 +42,11 @@ validate_opt (const char *detail, GVariant *config, const char *key, OptType val_type, - gconstpointer expected, - size_t expected_len) + gconstpointer expected) { char *config_key; GVariant *config_value; gboolean found = FALSE; - const guint8 *bytes; - gsize len; - const char *s; - const unsigned char *expected_array = expected; GVariantIter iter; g_assert (g_variant_is_of_type (config, G_VARIANT_TYPE_VARDICT)); @@ -61,25 +56,33 @@ validate_opt (const char *detail, if (!strcmp (key, config_key)) { found = TRUE; switch (val_type) { - case TYPE_INT: + case TYPE_INT: { g_assert (g_variant_is_of_type (config_value, G_VARIANT_TYPE_INT32)); g_assert_cmpint (g_variant_get_int32 (config_value), ==, GPOINTER_TO_INT (expected)); break; - case TYPE_BYTES: + } + case TYPE_BYTES: { + const guint8 *expected_bytes; + gsize expected_len = 0; + const guint8 *config_bytes; + gsize config_len = 0; + + expected_bytes = g_bytes_get_data ((GBytes *) expected, &expected_len); g_assert (g_variant_is_of_type (config_value, G_VARIANT_TYPE_BYTESTRING)); - bytes = g_variant_get_fixed_array (config_value, &len, 1); - g_assert_cmpint (len, ==, expected_len); - g_assert (memcmp (bytes, expected_array, expected_len) == 0); + config_bytes = g_variant_get_fixed_array (config_value, &config_len, 1); + g_assert_cmpmem (config_bytes, config_len, expected_bytes, expected_len); break; + } case TYPE_KEYWORD: - case TYPE_STRING: + case TYPE_STRING: { + const char *expected_str = expected; + const char *config_str; + g_assert (g_variant_is_of_type (config_value, G_VARIANT_TYPE_STRING)); - if (expected_len == -1) - expected_len = strlen ((const char *) expected); - s = g_variant_get_string (config_value, NULL); - g_assert_cmpint (strlen (s), ==, expected_len); - g_assert_cmpstr (s, ==, expected); + config_str = g_variant_get_string (config_value, NULL); + g_assert_cmpstr (config_str, ==, expected_str); break; + } default: g_assert_not_reached (); break; @@ -91,43 +94,80 @@ validate_opt (const char *detail, return found; } -static void -test_wifi_open (void) +static GVariant * +build_supplicant_config (NMConnection *connection, guint mtu, guint fixed_freq) { - gs_unref_object NMConnection *connection = NULL; gs_unref_object NMSupplicantConfig *config = NULL; - gs_unref_variant GVariant *config_dict = NULL; + gs_free_error GError *error = NULL; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSetting8021x *s_8021x; + gboolean success; + + config = nm_supplicant_config_new (); + + s_wifi = nm_connection_get_setting_wireless (connection); + g_assert (s_wifi); + success = nm_supplicant_config_add_setting_wireless (config, + s_wifi, + fixed_freq, + &error); + g_assert_no_error (error); + g_assert (success); + + s_wsec = nm_connection_get_setting_wireless_security (connection); + if (s_wsec) { + NMSettingWirelessSecurityPmf pmf = nm_setting_wireless_security_get_pmf (s_wsec); + s_8021x = nm_connection_get_setting_802_1x (connection); + success = nm_supplicant_config_add_setting_wireless_security (config, + s_wsec, + s_8021x, + nm_connection_get_uuid (connection), + mtu, + pmf, + &error); + } else { + success = nm_supplicant_config_add_no_security (config, &error); + } + g_assert_no_error (error); + g_assert (success); + + + success = nm_supplicant_config_add_bgscan (config, connection, &error); + g_assert_no_error (error); + g_assert (success); + + return nm_supplicant_config_to_variant (config); +} + +#define EXPECT(msg) g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, msg) + +static NMConnection * +new_basic_connection (const char *id, + GBytes *ssid, + const char *bssid_str) +{ + NMConnection *connection; NMSettingConnection *s_con; NMSettingWireless *s_wifi; NMSettingIPConfig *s_ip4; - char *uuid; - gboolean success; - GError *error = NULL; - GBytes *ssid; - const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 }; - const char *bssid_str = "11:22:33:44:55:66"; + gs_free char *uuid = nm_utils_uuid_generate (); connection = nm_simple_connection_new (); /* Connection setting */ s_con = (NMSettingConnection *) nm_setting_connection_new (); nm_connection_add_setting (connection, NM_SETTING (s_con)); - - uuid = nm_utils_uuid_generate (); g_object_set (s_con, - NM_SETTING_CONNECTION_ID, "Test Wifi Open", + NM_SETTING_CONNECTION_ID, id, NM_SETTING_CONNECTION_UUID, uuid, NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, NULL); - g_free (uuid); /* Wifi setting */ s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); nm_connection_add_setting (connection, NM_SETTING (s_wifi)); - - ssid = g_bytes_new (ssid_data, sizeof (ssid_data)); - g_object_set (s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NM_SETTING_WIRELESS_BSSID, bssid_str, @@ -135,163 +175,106 @@ test_wifi_open (void) NM_SETTING_WIRELESS_BAND, "bg", NULL); - g_bytes_unref (ssid); - /* IP4 setting */ s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); nm_connection_add_setting (connection, NM_SETTING (s_ip4)); - g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + return connection; +} + +static void +test_wifi_open (void) +{ + gs_unref_object NMConnection *connection = NULL; + gs_unref_variant GVariant *config_dict = NULL; + gboolean success; + GError *error = NULL; + const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 }; + gs_unref_bytes GBytes *ssid = g_bytes_new (ssid_data, sizeof (ssid_data)); + const char *bssid_str = "11:22:33:44:55:66"; + + connection = new_basic_connection ("Test Wifi Open", ssid, bssid_str); success = nm_connection_verify (connection, &error); g_assert_no_error (error); g_assert (success); - config = nm_supplicant_config_new (); - - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'ssid' value 'Test SSID'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'scan_ssid' value '1'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'bssid' value '11:22:33:44:55:66'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'freq_list' value *"); - g_assert (nm_supplicant_config_add_setting_wireless (config, - s_wifi, - 0, - &error)); - g_assert_no_error (error); + EXPECT ("*added 'ssid' value 'Test SSID'*"); + EXPECT ("*added 'scan_ssid' value '1'*"); + EXPECT ("*added 'bssid' value '11:22:33:44:55:66'*"); + EXPECT ("*added 'freq_list' value *"); + EXPECT ("*added 'key_mgmt' value 'NONE'"); + config_dict = build_supplicant_config (connection, 1500, 0); g_test_assert_expected_messages (); - - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'key_mgmt' value 'NONE'"); - g_assert (nm_supplicant_config_add_no_security (config, &error)); - g_assert_no_error (error); - g_test_assert_expected_messages (); - - config_dict = nm_supplicant_config_to_variant (config); g_assert (config_dict); - validate_opt ("wifi-open", config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1); - validate_opt ("wifi-open", config_dict, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data)); - validate_opt ("wifi-open", config_dict, "bssid", TYPE_KEYWORD, bssid_str, -1); - validate_opt ("wifi-open", config_dict, "key_mgmt", TYPE_KEYWORD, "NONE", -1); + validate_opt ("wifi-open", config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1)); + validate_opt ("wifi-open", config_dict, "ssid", TYPE_BYTES, ssid); + validate_opt ("wifi-open", config_dict, "bssid", TYPE_KEYWORD, bssid_str); + validate_opt ("wifi-open", config_dict, "key_mgmt", TYPE_KEYWORD, "NONE"); } static void test_wifi_wep_key (const char *detail, + gboolean test_bssid, NMWepKeyType wep_type, const char *key_data, const unsigned char *expected, size_t expected_size) { gs_unref_object NMConnection *connection = NULL; - gs_unref_object NMSupplicantConfig *config = NULL; gs_unref_variant GVariant *config_dict = NULL; - NMSettingConnection *s_con; - NMSettingWireless *s_wifi; NMSettingWirelessSecurity *s_wsec; - NMSettingIPConfig *s_ip4; - char *uuid; gboolean success; GError *error = NULL; - GBytes *ssid; const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 }; + gs_unref_bytes GBytes *ssid = g_bytes_new (ssid_data, sizeof (ssid_data)); const char *bssid_str = "11:22:33:44:55:66"; + gs_unref_bytes GBytes *wep_key_bytes = g_bytes_new (expected, expected_size); + const char *bgscan_data = "simple:30:-80:86400"; + gs_unref_bytes GBytes *bgscan = g_bytes_new (bgscan_data, strlen (bgscan_data)); - connection = nm_simple_connection_new (); - - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new (); - nm_connection_add_setting (connection, NM_SETTING (s_con)); - - uuid = nm_utils_uuid_generate (); - g_object_set (s_con, - NM_SETTING_CONNECTION_ID, "Test Wifi WEP Key", - NM_SETTING_CONNECTION_UUID, uuid, - NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, - NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, - NULL); - g_free (uuid); - - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); - nm_connection_add_setting (connection, NM_SETTING (s_wifi)); - - ssid = g_bytes_new (ssid_data, sizeof (ssid_data)); - - g_object_set (s_wifi, - NM_SETTING_WIRELESS_SSID, ssid, - NM_SETTING_WIRELESS_BSSID, bssid_str, - NM_SETTING_WIRELESS_MODE, "infrastructure", - NM_SETTING_WIRELESS_BAND, "bg", - NULL); - - g_bytes_unref (ssid); + connection = new_basic_connection ("Test Wifi WEP Key", ssid, test_bssid ? bssid_str : NULL); /* Wifi Security setting */ s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); nm_connection_add_setting (connection, NM_SETTING (s_wsec)); - g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, wep_type, NULL); - nm_setting_wireless_security_set_wep_key (s_wsec, 0, key_data); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); - nm_connection_add_setting (connection, NM_SETTING (s_ip4)); - - g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + nm_setting_wireless_security_set_wep_key (s_wsec, 0, key_data); success = nm_connection_verify (connection, &error); g_assert_no_error (error); g_assert (success); - config = nm_supplicant_config_new (); + EXPECT ("*added 'ssid' value 'Test SSID'*"); + EXPECT ("*added 'scan_ssid' value '1'*"); + if (test_bssid) + EXPECT ("*added 'bssid' value '11:22:33:44:55:66'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'ssid' value 'Test SSID'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'scan_ssid' value '1'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'bssid' value '11:22:33:44:55:66'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'freq_list' value *"); - g_assert (nm_supplicant_config_add_setting_wireless (config, - s_wifi, - 0, - &error)); - g_assert_no_error (error); + EXPECT ("*added 'freq_list' value *"); + EXPECT ("*added 'key_mgmt' value 'NONE'"); + EXPECT ("*added 'wep_key0' value *"); + EXPECT ("*added 'wep_tx_keyidx' value '0'"); + if (!test_bssid) + EXPECT ("*added 'bgscan' value 'simple:30:-80:86400'*"); + + config_dict = build_supplicant_config (connection, 1500, 0); g_test_assert_expected_messages (); - - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'key_mgmt' value 'NONE'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'wep_key0' value *"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'wep_tx_keyidx' value '0'"); - g_assert (nm_supplicant_config_add_setting_wireless_security (config, - s_wsec, - NULL, - "376aced7-b28c-46be-9a62-fcdf072571da", - 1500, - 0, - &error)); - g_assert_no_error (error); - g_test_assert_expected_messages (); - - config_dict = nm_supplicant_config_to_variant (config); g_assert (config_dict); - validate_opt (detail, config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1); - validate_opt (detail, config_dict, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data)); - validate_opt (detail, config_dict, "bssid", TYPE_KEYWORD, bssid_str, -1); - validate_opt (detail, config_dict, "key_mgmt", TYPE_KEYWORD, "NONE", -1); - validate_opt (detail, config_dict, "wep_tx_keyidx", TYPE_INT, GINT_TO_POINTER (0), -1); - validate_opt (detail, config_dict, "wep_key0", TYPE_BYTES, expected, expected_size); + validate_opt (detail, config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1)); + validate_opt (detail, config_dict, "ssid", TYPE_BYTES, ssid); + if (test_bssid) + validate_opt (detail, config_dict, "bssid", TYPE_KEYWORD, bssid_str); + else + validate_opt (detail, config_dict, "bgscan", TYPE_BYTES, bgscan); + + validate_opt (detail, config_dict, "key_mgmt", TYPE_KEYWORD, "NONE"); + validate_opt (detail, config_dict, "wep_tx_keyidx", TYPE_INT, GINT_TO_POINTER (0)); + validate_opt (detail, config_dict, "wep_key0", TYPE_BYTES, wep_key_bytes); } static void @@ -308,13 +291,16 @@ test_wifi_wep (void) const char *key5 = "r34lly l33t w3p p4ssphr4s3 for t3st1ng"; const unsigned char key5_expected[] = { 0xce, 0x68, 0x8b, 0x35, 0xf6, 0x0a, 0x2b, 0xbf, 0xc9, 0x8f, 0xed, 0x10, 0xda }; - test_wifi_wep_key ("wifi-wep-ascii-40", NM_WEP_KEY_TYPE_KEY, key1, key1_expected, sizeof (key1_expected)); - test_wifi_wep_key ("wifi-wep-ascii-104", NM_WEP_KEY_TYPE_KEY, key2, key2_expected, sizeof (key2_expected)); - test_wifi_wep_key ("wifi-wep-hex-40", NM_WEP_KEY_TYPE_KEY, key3, key3_expected, sizeof (key3_expected)); - test_wifi_wep_key ("wifi-wep-hex-104", NM_WEP_KEY_TYPE_KEY, key4, key4_expected, sizeof (key4_expected)); - test_wifi_wep_key ("wifi-wep-passphrase-104", NM_WEP_KEY_TYPE_PASSPHRASE, key5, key5_expected, sizeof (key5_expected)); + test_wifi_wep_key ("wifi-wep-ascii-40", TRUE, NM_WEP_KEY_TYPE_KEY, key1, key1_expected, sizeof (key1_expected)); + test_wifi_wep_key ("wifi-wep-ascii-104", TRUE, NM_WEP_KEY_TYPE_KEY, key2, key2_expected, sizeof (key2_expected)); + test_wifi_wep_key ("wifi-wep-hex-40", TRUE, NM_WEP_KEY_TYPE_KEY, key3, key3_expected, sizeof (key3_expected)); + test_wifi_wep_key ("wifi-wep-hex-104", TRUE, NM_WEP_KEY_TYPE_KEY, key4, key4_expected, sizeof (key4_expected)); + test_wifi_wep_key ("wifi-wep-passphrase-104", TRUE, NM_WEP_KEY_TYPE_PASSPHRASE, key5, key5_expected, sizeof (key5_expected)); - test_wifi_wep_key ("wifi-wep-old-hex-104", NM_WEP_KEY_TYPE_UNKNOWN, key4, key4_expected, sizeof (key4_expected)); + test_wifi_wep_key ("wifi-wep-old-hex-104", TRUE, NM_WEP_KEY_TYPE_UNKNOWN, key4, key4_expected, sizeof (key4_expected)); + + /* Unlocked BSSID to test bgscan */ + test_wifi_wep_key ("wifi-wep-hex-40", FALSE, NM_WEP_KEY_TYPE_KEY, key3, key3_expected, sizeof (key3_expected)); } static void @@ -325,59 +311,25 @@ test_wifi_wpa_psk (const char *detail, size_t expected_size) { gs_unref_object NMConnection *connection = NULL; - gs_unref_object NMSupplicantConfig *config = NULL; gs_unref_variant GVariant *config_dict = NULL; - NMSettingConnection *s_con; - NMSettingWireless *s_wifi; NMSettingWirelessSecurity *s_wsec; - NMSettingIPConfig *s_ip4; - char *uuid; gboolean success; GError *error = NULL; - GBytes *ssid; const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 }; + gs_unref_bytes GBytes *ssid = g_bytes_new (ssid_data, sizeof (ssid_data)); const char *bssid_str = "11:22:33:44:55:66"; + gs_unref_bytes GBytes *wpa_psk_bytes = g_bytes_new (expected, expected_size); - connection = nm_simple_connection_new (); - - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new (); - nm_connection_add_setting (connection, NM_SETTING (s_con)); - - uuid = nm_utils_uuid_generate (); - g_object_set (s_con, - NM_SETTING_CONNECTION_ID, "Test Wifi WEP Key", - NM_SETTING_CONNECTION_UUID, uuid, - NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, - NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, - NULL); - g_free (uuid); - - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); - nm_connection_add_setting (connection, NM_SETTING (s_wifi)); - - ssid = g_bytes_new (ssid_data, sizeof (ssid_data)); - - g_object_set (s_wifi, - NM_SETTING_WIRELESS_SSID, ssid, - NM_SETTING_WIRELESS_BSSID, bssid_str, - NM_SETTING_WIRELESS_MODE, "infrastructure", - NM_SETTING_WIRELESS_BAND, "bg", - NULL); - - g_bytes_unref (ssid); + connection = new_basic_connection ("Test Wifi WPA PSK", ssid, bssid_str); /* Wifi Security setting */ s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); nm_connection_add_setting (connection, NM_SETTING (s_wsec)); - g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", NM_SETTING_WIRELESS_SECURITY_PSK, key_data, NM_SETTING_WIRELESS_SECURITY_PMF, (int) NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL, NULL); - nm_setting_wireless_security_add_proto (s_wsec, "wpa"); nm_setting_wireless_security_add_proto (s_wsec, "rsn"); nm_setting_wireless_security_add_pairwise (s_wsec, "tkip"); @@ -385,66 +337,38 @@ test_wifi_wpa_psk (const char *detail, nm_setting_wireless_security_add_group (s_wsec, "tkip"); nm_setting_wireless_security_add_group (s_wsec, "ccmp"); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); - nm_connection_add_setting (connection, NM_SETTING (s_ip4)); - - g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - success = nm_connection_verify (connection, &error); g_assert_no_error (error); g_assert (success); - config = nm_supplicant_config_new (); + EXPECT ("*added 'ssid' value 'Test SSID'*"); + EXPECT ("*added 'scan_ssid' value '1'*"); + EXPECT ("*added 'bssid' value '11:22:33:44:55:66'*"); + EXPECT ("*added 'freq_list' value *"); + EXPECT ("*added 'key_mgmt' value 'WPA-PSK WPA-PSK-SHA256'"); + EXPECT ("*added 'psk' value *"); + EXPECT ("*added 'proto' value 'WPA RSN'"); + EXPECT ("*added 'pairwise' value 'TKIP CCMP'"); + EXPECT ("*added 'group' value 'TKIP CCMP'"); + EXPECT ("*added 'ieee80211w' value '1'"); + config_dict = build_supplicant_config (connection, 1500, 0); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'ssid' value 'Test SSID'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'scan_ssid' value '1'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'bssid' value '11:22:33:44:55:66'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'freq_list' value *"); - g_assert (nm_supplicant_config_add_setting_wireless (config, - s_wifi, - 0, - &error)); - g_assert_no_error (error); g_test_assert_expected_messages (); - - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'key_mgmt' value 'WPA-PSK WPA-PSK-SHA256'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'psk' value *"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'proto' value 'WPA RSN'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'pairwise' value 'TKIP CCMP'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'group' value 'TKIP CCMP'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'ieee80211w' value '1'"); - g_assert (nm_supplicant_config_add_setting_wireless_security (config, - s_wsec, - NULL, - "376aced7-b28c-46be-9a62-fcdf072571da", - 1500, - NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL, - &error)); - g_assert_no_error (error); - g_test_assert_expected_messages (); - - config_dict = nm_supplicant_config_to_variant (config); g_assert (config_dict); - validate_opt (detail, config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1); - validate_opt (detail, config_dict, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data)); - validate_opt (detail, config_dict, "bssid", TYPE_KEYWORD, bssid_str, -1); - validate_opt (detail, config_dict, "key_mgmt", TYPE_KEYWORD, "WPA-PSK WPA-PSK-SHA256", -1); - validate_opt (detail, config_dict, "proto", TYPE_KEYWORD, "WPA RSN", -1); - validate_opt (detail, config_dict, "pairwise", TYPE_KEYWORD, "TKIP CCMP", -1); - validate_opt (detail, config_dict, "group", TYPE_KEYWORD, "TKIP CCMP", -1); - validate_opt (detail, config_dict, "psk", key_type, expected, expected_size); + validate_opt (detail, config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1)); + validate_opt (detail, config_dict, "ssid", TYPE_BYTES, ssid); + validate_opt (detail, config_dict, "bssid", TYPE_KEYWORD, bssid_str); + validate_opt (detail, config_dict, "key_mgmt", TYPE_KEYWORD, "WPA-PSK WPA-PSK-SHA256"); + validate_opt (detail, config_dict, "proto", TYPE_KEYWORD, "WPA RSN"); + validate_opt (detail, config_dict, "pairwise", TYPE_KEYWORD, "TKIP CCMP"); + validate_opt (detail, config_dict, "group", TYPE_KEYWORD, "TKIP CCMP"); + if (key_type == TYPE_BYTES) + validate_opt (detail, config_dict, "psk", key_type, wpa_psk_bytes); + else if (key_type == TYPE_STRING) + validate_opt (detail, config_dict, "psk", key_type, expected); + else + g_assert_not_reached (); } static void @@ -461,63 +385,23 @@ test_wifi_wpa_psk_types (void) test_wifi_wpa_psk ("wifi-wep-psk-passphrase", TYPE_STRING, key2, (gconstpointer) key2, strlen (key2)); } -static void -test_wifi_eap (void) +static NMConnection * +generate_wifi_eap_connection (const char *id, GBytes *ssid, const char *bssid_str) { - gs_unref_object NMConnection *connection = NULL; - gs_unref_object NMSupplicantConfig *config = NULL; - gs_unref_variant GVariant *config_dict = NULL; - NMSettingConnection *s_con; - NMSettingWireless *s_wifi; + NMConnection *connection = NULL; NMSettingWirelessSecurity *s_wsec; NMSetting8021x *s_8021x; - NMSettingIPConfig *s_ip4; - char *uuid; gboolean success; GError *error = NULL; - GBytes *ssid; - const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 }; - const char *bssid_str = "11:22:33:44:55:66"; - guint32 mtu = 1100; - connection = nm_simple_connection_new (); - - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new (); - nm_connection_add_setting (connection, NM_SETTING (s_con)); - - uuid = nm_utils_uuid_generate (); - g_object_set (s_con, - NM_SETTING_CONNECTION_ID, "Test Wifi EAP-TLS", - NM_SETTING_CONNECTION_UUID, uuid, - NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, - NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, - NULL); - g_free (uuid); - - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); - nm_connection_add_setting (connection, NM_SETTING (s_wifi)); - - ssid = g_bytes_new (ssid_data, sizeof (ssid_data)); - - g_object_set (s_wifi, - NM_SETTING_WIRELESS_SSID, ssid, - NM_SETTING_WIRELESS_BSSID, bssid_str, - NM_SETTING_WIRELESS_MODE, "infrastructure", - NM_SETTING_WIRELESS_BAND, "bg", - NULL); - - g_bytes_unref (ssid); + connection = new_basic_connection (id, ssid, bssid_str); /* Wifi Security setting */ s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); nm_connection_add_setting (connection, NM_SETTING (s_wsec)); - g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL); - nm_setting_wireless_security_add_proto (s_wsec, "wpa"); nm_setting_wireless_security_add_proto (s_wsec, "rsn"); nm_setting_wireless_security_add_pairwise (s_wsec, "tkip"); @@ -533,75 +417,92 @@ test_wifi_eap (void) g_assert (nm_setting_802_1x_set_ca_cert (s_8021x, TEST_CERT_DIR "/test-ca-cert.pem", NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, NULL)); nm_setting_802_1x_set_private_key (s_8021x, TEST_CERT_DIR "/test-cert.p12", NULL, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); - nm_connection_add_setting (connection, NM_SETTING (s_ip4)); - - g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - success = nm_connection_verify (connection, &error); g_assert_no_error (error); g_assert (success); - config = nm_supplicant_config_new (); + return connection; +} - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'ssid' value 'Test SSID'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'scan_ssid' value '1'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'bssid' value '11:22:33:44:55:66'*"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'freq_list' value *"); - g_assert (nm_supplicant_config_add_setting_wireless (config, - s_wifi, - 0, - &error)); - g_assert_no_error (error); +static void +test_wifi_eap_locked_bssid (void) +{ + gs_unref_object NMConnection *connection = NULL; + gs_unref_variant GVariant *config_dict = NULL; + const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 }; + gs_unref_bytes GBytes *ssid = g_bytes_new (ssid_data, sizeof (ssid_data)); + const char *bssid_str = "11:22:33:44:55:66"; + guint32 mtu = 1100; + + connection = generate_wifi_eap_connection ("Test Wifi EAP-TLS Locked", ssid, bssid_str); + + EXPECT ("*added 'ssid' value 'Test SSID'*"); + EXPECT ("*added 'scan_ssid' value '1'*"); + EXPECT ("*added 'bssid' value '11:22:33:44:55:66'*"); + EXPECT ("*added 'freq_list' value *"); + EXPECT ("*added 'key_mgmt' value 'WPA-EAP'"); + EXPECT ("*added 'proto' value 'WPA RSN'"); + EXPECT ("*added 'pairwise' value 'TKIP CCMP'"); + EXPECT ("*added 'group' value 'TKIP CCMP'"); + EXPECT ("*Config: added 'eap' value 'TLS'"); + EXPECT ("*Config: added 'fragment_size' value '1086'"); + EXPECT ("* Config: added 'ca_cert' value '*/test-ca-cert.pem'"); + EXPECT ("* Config: added 'private_key' value '*/test-cert.p12'"); + EXPECT ("*Config: added 'proactive_key_caching' value '1'"); + config_dict = build_supplicant_config (connection, mtu, 0); g_test_assert_expected_messages (); - - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'key_mgmt' value 'WPA-EAP'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'proto' value 'WPA RSN'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'pairwise' value 'TKIP CCMP'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*added 'group' value 'TKIP CCMP'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*Config: added 'eap' value 'TLS'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*Config: added 'fragment_size' value '1086'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "* Config: added 'ca_cert' value '*/test-ca-cert.pem'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "* Config: added 'private_key' value '*/test-cert.p12'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*Config: added 'bgscan' value 'simple:30:-65:300'"); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, - "*Config: added 'proactive_key_caching' value '1'"); - g_assert (nm_supplicant_config_add_setting_wireless_security (config, - s_wsec, - s_8021x, - "d5b488af-9cab-41ed-bad4-97709c58430f", - mtu, - NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE, - &error)); - g_assert_no_error (error); - g_test_assert_expected_messages (); - - config_dict = nm_supplicant_config_to_variant (config); g_assert (config_dict); - validate_opt ("wifi-eap", config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1); - validate_opt ("wifi-eap", config_dict, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data)); - validate_opt ("wifi-eap", config_dict, "bssid", TYPE_KEYWORD, bssid_str, -1); - validate_opt ("wifi-eap", config_dict, "key_mgmt", TYPE_KEYWORD, "WPA-EAP", -1); - validate_opt ("wifi-eap", config_dict, "eap", TYPE_KEYWORD, "TLS", -1); - validate_opt ("wifi-eap", config_dict, "proto", TYPE_KEYWORD, "WPA RSN", -1); - validate_opt ("wifi-eap", config_dict, "pairwise", TYPE_KEYWORD, "TKIP CCMP", -1); - validate_opt ("wifi-eap", config_dict, "group", TYPE_KEYWORD, "TKIP CCMP", -1); - validate_opt ("wifi-eap", config_dict, "fragment_size", TYPE_INT, GINT_TO_POINTER(mtu-14), -1); + validate_opt ("wifi-eap", config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1)); + validate_opt ("wifi-eap", config_dict, "ssid", TYPE_BYTES, ssid); + validate_opt ("wifi-eap", config_dict, "bssid", TYPE_KEYWORD, bssid_str); + validate_opt ("wifi-eap", config_dict, "key_mgmt", TYPE_KEYWORD, "WPA-EAP"); + validate_opt ("wifi-eap", config_dict, "eap", TYPE_KEYWORD, "TLS"); + validate_opt ("wifi-eap", config_dict, "proto", TYPE_KEYWORD, "WPA RSN"); + validate_opt ("wifi-eap", config_dict, "pairwise", TYPE_KEYWORD, "TKIP CCMP"); + validate_opt ("wifi-eap", config_dict, "group", TYPE_KEYWORD, "TKIP CCMP"); + validate_opt ("wifi-eap", config_dict, "fragment_size", TYPE_INT, GINT_TO_POINTER(mtu-14)); +} + +static void +test_wifi_eap_unlocked_bssid (void) +{ + gs_unref_object NMConnection *connection = NULL; + gs_unref_variant GVariant *config_dict = NULL; + const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 }; + gs_unref_bytes GBytes *ssid = g_bytes_new (ssid_data, sizeof (ssid_data)); + const char *bgscan_data = "simple:30:-65:300"; + gs_unref_bytes GBytes *bgscan = g_bytes_new (bgscan_data, strlen (bgscan_data)); + guint32 mtu = 1100; + + connection = generate_wifi_eap_connection ("Test Wifi EAP-TLS Unlocked", ssid, NULL); + + EXPECT ("*added 'ssid' value 'Test SSID'*"); + EXPECT ("*added 'scan_ssid' value '1'*"); + EXPECT ("*added 'freq_list' value *"); + EXPECT ("*added 'key_mgmt' value 'WPA-EAP'"); + EXPECT ("*added 'proto' value 'WPA RSN'"); + EXPECT ("*added 'pairwise' value 'TKIP CCMP'"); + EXPECT ("*added 'group' value 'TKIP CCMP'"); + EXPECT ("*Config: added 'eap' value 'TLS'"); + EXPECT ("*Config: added 'fragment_size' value '1086'"); + EXPECT ("* Config: added 'ca_cert' value '*/test-ca-cert.pem'"); + EXPECT ("* Config: added 'private_key' value '*/test-cert.p12'"); + EXPECT ("*Config: added 'proactive_key_caching' value '1'"); + EXPECT ("*Config: added 'bgscan' value 'simple:30:-65:300'"); + config_dict = build_supplicant_config (connection, mtu, 0); + g_test_assert_expected_messages (); + g_assert (config_dict); + + validate_opt ("wifi-eap", config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1)); + validate_opt ("wifi-eap", config_dict, "ssid", TYPE_BYTES, ssid); + validate_opt ("wifi-eap", config_dict, "key_mgmt", TYPE_KEYWORD, "WPA-EAP"); + validate_opt ("wifi-eap", config_dict, "eap", TYPE_KEYWORD, "TLS"); + validate_opt ("wifi-eap", config_dict, "proto", TYPE_KEYWORD, "WPA RSN"); + validate_opt ("wifi-eap", config_dict, "pairwise", TYPE_KEYWORD, "TKIP CCMP"); + validate_opt ("wifi-eap", config_dict, "group", TYPE_KEYWORD, "TKIP CCMP"); + validate_opt ("wifi-eap", config_dict, "fragment_size", TYPE_INT, GINT_TO_POINTER(mtu-14)); + validate_opt ("wifi-eap", config_dict, "bgscan", TYPE_BYTES, bgscan); } NMTST_DEFINE (); @@ -613,8 +514,8 @@ int main (int argc, char **argv) g_test_add_func ("/supplicant-config/wifi-open", test_wifi_open); g_test_add_func ("/supplicant-config/wifi-wep", test_wifi_wep); g_test_add_func ("/supplicant-config/wifi-wpa-psk-types", test_wifi_wpa_psk_types); - g_test_add_func ("/supplicant-config/wifi-eap", test_wifi_eap); + g_test_add_func ("/supplicant-config/wifi-eap/locked-bssid", test_wifi_eap_locked_bssid); + g_test_add_func ("/supplicant-config/wifi-eap/unlocked-bssid", test_wifi_eap_unlocked_bssid); return g_test_run (); } - From e1da16f79950dca54bda99f736c6a62ecb6bb25b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 7 Nov 2016 16:31:19 -0600 Subject: [PATCH 3/4] supplicant: don't allow scans to trigger a supplicant roaming decision Just because the user requested a scan doesn't mean the supplicant should use the result of that scan to jump to an AP that's slightly better than the current one. Let the supplicant handle when it's supposed to roam based on it's own logic, not random scans from users or NM clients. --- src/supplicant/nm-supplicant-interface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c index b90975fb21..0c6c3f36d1 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/supplicant/nm-supplicant-interface.c @@ -1789,6 +1789,7 @@ nm_supplicant_interface_request_scan (NMSupplicantInterface *self, const GPtrArr /* Scan parameters */ g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); g_variant_builder_add (&builder, "{sv}", "Type", g_variant_new_string ("active")); + g_variant_builder_add (&builder, "{sv}", "AllowRoam", g_variant_new_boolean (FALSE)); if (ssids) { GVariantBuilder ssids_builder; From 4acc17053b2ca9edebd54709e10d6479da17c857 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 7 Aug 2017 09:56:21 -0500 Subject: [PATCH 4/4] devices/wifi: move scan option processing to D-Bus request scan handler Only the D-Bus bits use it, and we wouldn't pass a GVariant array around in internal code anyway. Also validate the scan options earlier rather than waiting for the supplicant to tell us they are invalid. --- src/devices/wifi/nm-device-wifi.c | 118 +++++++++++++++++++----------- 1 file changed, 77 insertions(+), 41 deletions(-) diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index d48513c02c..ebd5317a52 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -183,7 +183,10 @@ static void supplicant_iface_notify_current_bss (NMSupplicantInterface *iface, GParamSpec *pspec, NMDeviceWifi *self); -static void request_wireless_scan (NMDeviceWifi *self, gboolean periodic, gboolean force_if_scanning, GVariant *scan_options); +static void request_wireless_scan (NMDeviceWifi *self, + gboolean periodic, + gboolean force_if_scanning, + const GPtrArray *ssids); static void ap_add_remove (NMDeviceWifi *self, guint signum, @@ -1192,6 +1195,47 @@ _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset) } } +static GPtrArray * +ssids_options_to_ptrarray (GVariant *value, GError **error) +{ + GPtrArray *ssids = NULL; + GByteArray *ssid_array; + GVariant *v; + const guint8 *bytes; + gsize len; + int num_ssids, i; + + num_ssids = g_variant_n_children (value); + if (num_ssids > 32) { + g_set_error_literal (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ALLOWED, + "too many SSIDs requested to scan"); + return NULL; + } + + if (num_ssids) { + ssids = g_ptr_array_new_full (num_ssids, (GDestroyNotify) g_byte_array_unref); + for (i = 0; i < num_ssids; i++) { + v = g_variant_get_child_value (value, i); + bytes = g_variant_get_fixed_array (v, &len, sizeof (guint8)); + if (len > 32) { + g_set_error (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ALLOWED, + "SSID at index %d more than 32 bytes", i); + g_ptr_array_unref (ssids); + return NULL; + } + + ssid_array = g_byte_array_new (); + g_byte_array_append (ssid_array, bytes, len); + g_ptr_array_add (ssids, ssid_array); + } + } + return ssids; +} + static void dbus_request_scan_cb (NMDevice *device, GDBusMethodInvocation *context, @@ -1201,7 +1245,8 @@ dbus_request_scan_cb (NMDevice *device, { NMDeviceWifi *self = NM_DEVICE_WIFI (device); NMDeviceWifiPrivate *priv; - gs_unref_variant GVariant *new_scan_options = user_data; + gs_unref_variant GVariant *scan_options = user_data; + gs_unref_ptrarray GPtrArray *ssids = NULL; if (error) { g_dbus_method_invocation_return_gerror (context, error); @@ -1218,7 +1263,29 @@ dbus_request_scan_cb (NMDevice *device, priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - request_wireless_scan (self, FALSE, FALSE, new_scan_options); + if (scan_options) { + gs_unref_variant GVariant *val = g_variant_lookup_value (scan_options, "ssids", NULL); + + if (val) { + gs_free_error GError *ssid_error = NULL; + + if (!g_variant_is_of_type (val, G_VARIANT_TYPE ("aay"))) { + g_dbus_method_invocation_return_error_literal (context, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ALLOWED, + "Invalid 'ssid' scan option"); + return; + } + + ssids = ssids_options_to_ptrarray (val, &ssid_error); + if (ssid_error) { + g_dbus_method_invocation_return_gerror (context, ssid_error); + return; + } + } + } + + request_wireless_scan (self, FALSE, FALSE, ssids); g_dbus_method_invocation_return_value (context, NULL); } @@ -1402,32 +1469,11 @@ build_hidden_probe_list (NMDeviceWifi *self) return ssids; } -static GPtrArray * -ssids_options_to_ptrarray (GVariant *value) -{ - GPtrArray *ssids = NULL; - GByteArray *ssid_array; - GVariant *v; - const guint8 *bytes; - gsize len; - int num_ssids, i; - - num_ssids = g_variant_n_children (value); - if (num_ssids) { - ssids = g_ptr_array_new_full (num_ssids, (GDestroyNotify) g_byte_array_unref); - for (i = 0; i < num_ssids; i++) { - v = g_variant_get_child_value (value, i); - bytes = g_variant_get_fixed_array (v, &len, sizeof (guint8)); - ssid_array = g_byte_array_new (); - g_byte_array_append (ssid_array, bytes, len); - g_ptr_array_add (ssids, ssid_array); - } - } - return ssids; -} - static void -request_wireless_scan (NMDeviceWifi *self, gboolean periodic, gboolean force_if_scanning, GVariant *scan_options) +request_wireless_scan (NMDeviceWifi *self, + gboolean periodic, + gboolean force_if_scanning, + const GPtrArray *ssids) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); gboolean request_started = FALSE; @@ -1440,23 +1486,13 @@ request_wireless_scan (NMDeviceWifi *self, gboolean periodic, gboolean force_if_ } if (!check_scanning_prohibited (self, periodic)) { - gs_unref_ptrarray GPtrArray *ssids = NULL; + gs_unref_ptrarray GPtrArray *hidden_ssids = NULL; _LOGD (LOGD_WIFI, "wifi-scan: scanning requested"); - if (scan_options) { - GVariant *val = g_variant_lookup_value (scan_options, "ssids", NULL); - - if (val) { - if (g_variant_is_of_type (val, G_VARIANT_TYPE ("aay"))) - ssids = ssids_options_to_ptrarray (val); - else - _LOGD (LOGD_WIFI, "wifi-scan: ignoring invalid 'ssids' scan option"); - g_variant_unref (val); - } + if (!ssids) { + ssids = hidden_ssids = build_hidden_probe_list (self); } - if (!ssids) - ssids = build_hidden_probe_list (self); if (_LOGD_ENABLED (LOGD_WIFI)) { if (ssids) {