diff options
| author | Iain Lane <iain@orangesquash.org.uk> | 2018-09-24 09:29:55 +0100 |
|---|---|---|
| committer | Iain Lane <iain@orangesquash.org.uk> | 2018-09-24 09:29:55 +0100 |
| commit | e152ec7bf4ba252ff9d3eb13eabd417b931dac9a (patch) | |
| tree | c323cf856ee0bb8e44590670dd54c19653a55748 /src/devices/wifi/nm-device-wifi.c | |
| parent | ee9c73a923909e23a649407be77e25235d769e25 (diff) | |
Import Upstream version 1.12.2
Diffstat (limited to 'src/devices/wifi/nm-device-wifi.c')
| -rw-r--r-- | src/devices/wifi/nm-device-wifi.c | 503 |
1 files changed, 177 insertions, 326 deletions
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index bf021095..6bd06524 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -28,9 +28,11 @@ #include <unistd.h> #include <errno.h> +#include "nm-wifi-ap.h" #include "nm-common-macros.h" #include "devices/nm-device.h" #include "devices/nm-device-private.h" +#include "nm-dbus-manager.h" #include "nm-utils.h" #include "NetworkManagerUtils.h" #include "nm-act-request.h" @@ -48,11 +50,11 @@ #include "nm-auth-utils.h" #include "settings/nm-settings-connection.h" #include "settings/nm-settings.h" +#include "nm-wifi-utils.h" +#include "nm-wifi-common.h" #include "nm-core-internal.h" #include "nm-config.h" -#include "introspection/org.freedesktop.NetworkManager.Device.Wireless.h" - #include "devices/nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceWifi); @@ -72,11 +74,10 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceWifi, PROP_ACTIVE_ACCESS_POINT, PROP_CAPABILITIES, PROP_SCANNING, + PROP_LAST_SCAN, ); enum { - ACCESS_POINT_ADDED, - ACCESS_POINT_REMOVED, SCANNING_PROHIBITED, LAST_SIGNAL @@ -87,7 +88,8 @@ static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { gint8 invalid_strength_counter; - GHashTable * aps; + CList aps_lst_head; + NMWifiAP * current_ap; guint32 rate; bool enabled:1; /* rfkilled or not */ @@ -95,8 +97,8 @@ typedef struct { bool ssid_found:1; bool is_scanning:1; - gint32 last_scan; - gint32 scheduled_scan_time; + gint64 last_scan; /* milliseconds */ + gint32 scheduled_scan_time; /* seconds */ guint8 scan_interval; /* seconds */ guint pending_scan_id; guint ap_dump_id; @@ -187,7 +189,7 @@ static void request_wireless_scan (NMDeviceWifi *self, const GPtrArray *ssids); static void ap_add_remove (NMDeviceWifi *self, - guint signum, + gboolean is_adding, NMWifiAP *ap, gboolean recheck_available_connections); @@ -345,30 +347,6 @@ supplicant_interface_release (NMDeviceWifi *self) _notify_scanning (self); } -static NMWifiAP * -get_ap_by_path (NMDeviceWifi *self, const char *path) -{ - g_return_val_if_fail (path != NULL, NULL); - return g_hash_table_lookup (NM_DEVICE_WIFI_GET_PRIVATE (self)->aps, path); - -} - -static NMWifiAP * -get_ap_by_supplicant_path (NMDeviceWifi *self, const char *path) -{ - GHashTableIter iter; - NMWifiAP *ap; - - g_return_val_if_fail (path != NULL, NULL); - - g_hash_table_iter_init (&iter, NM_DEVICE_WIFI_GET_PRIVATE (self)->aps); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) { - if (g_strcmp0 (path, nm_wifi_ap_get_supplicant_path (ap)) == 0) - return ap; - } - return NULL; -} - static void update_seen_bssids_cache (NMDeviceWifi *self, NMWifiAP *ap) { @@ -415,7 +393,7 @@ set_current_ap (NMDeviceWifi *self, NMWifiAP *new_ap, gboolean recheck_available /* Remove any AP from the internal list if it was created by NM or isn't known to the supplicant */ if (mode == NM_802_11_MODE_ADHOC || mode == NM_802_11_MODE_AP || nm_wifi_ap_get_fake (old_ap)) - ap_add_remove (self, ACCESS_POINT_REMOVED, old_ap, recheck_available_connections); + ap_add_remove (self, FALSE, old_ap, recheck_available_connections); g_object_unref (old_ap); } @@ -482,32 +460,32 @@ periodic_update_cb (gpointer user_data) static void ap_add_remove (NMDeviceWifi *self, - guint signum, + gboolean is_adding, /* or else removing */ NMWifiAP *ap, gboolean recheck_available_connections) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - nm_assert (NM_IN_SET (signum, ACCESS_POINT_ADDED, ACCESS_POINT_REMOVED)); - - if (signum == ACCESS_POINT_ADDED) { - g_hash_table_insert (priv->aps, - (gpointer) nm_exported_object_export ((NMExportedObject *) ap), - g_object_ref (ap)); + if (is_adding) { + g_object_ref (ap); + ap->wifi_device = NM_DEVICE (self); + c_list_link_tail (&priv->aps_lst_head, &ap->aps_lst); + nm_dbus_object_export (NM_DBUS_OBJECT (ap)); _ap_dump (self, LOGL_DEBUG, ap, "added", 0); - } else + nm_device_wifi_emit_signal_access_point (NM_DEVICE (self), ap, TRUE); + } else { + ap->wifi_device = NULL; + c_list_unlink (&ap->aps_lst); _ap_dump (self, LOGL_DEBUG, ap, "removed", 0); - - g_signal_emit (self, signals[signum], 0, ap); - - if (signum == ACCESS_POINT_REMOVED) { - g_hash_table_remove (priv->aps, nm_exported_object_get_path ((NMExportedObject *) ap)); - nm_exported_object_unexport ((NMExportedObject *) ap); - g_object_unref (ap); } _notify (self, PROP_ACCESS_POINTS); + if (!is_adding) { + nm_device_wifi_emit_signal_access_point (NM_DEVICE (self), ap, FALSE); + nm_dbus_object_clear_and_unexport (&ap); + } + nm_device_emit_recheck_auto_activate (NM_DEVICE (self)); if (recheck_available_connections) nm_device_recheck_available_connections (NM_DEVICE (self)); @@ -517,20 +495,15 @@ static void remove_all_aps (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GHashTableIter iter; NMWifiAP *ap; - if (!g_hash_table_size (priv->aps)) + if (c_list_is_empty (&priv->aps_lst_head)) return; set_current_ap (self, NULL, FALSE); -again: - g_hash_table_iter_init (&iter, priv->aps); - if (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) { - ap_add_remove (self, ACCESS_POINT_REMOVED, ap, FALSE); - goto again; - } + while ((ap = c_list_first_entry (&priv->aps_lst_head, NMWifiAP, aps_lst))) + ap_add_remove (self, FALSE, ap, FALSE); nm_device_recheck_available_connections (NM_DEVICE (self)); } @@ -680,35 +653,14 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) return TRUE; } -static NMWifiAP * -find_first_compatible_ap (NMDeviceWifi *self, - NMConnection *connection, - gboolean allow_unstable_order) -{ - GHashTableIter iter; - NMWifiAP *ap; - NMWifiAP *cand_ap = NULL; - - g_return_val_if_fail (connection != NULL, NULL); - - g_hash_table_iter_init (&iter, NM_DEVICE_WIFI_GET_PRIVATE (self)->aps); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) { - if (!nm_wifi_ap_check_compatible (ap, connection)) - continue; - if (allow_unstable_order) - return ap; - if (!cand_ap || (nm_wifi_ap_get_id (cand_ap) < nm_wifi_ap_get_id (ap))) - cand_ap = ap; - } - return cand_ap; -} - static gboolean check_connection_available (NMDevice *device, NMConnection *connection, NMDeviceCheckConAvailableFlags flags, const char *specific_object) { + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMSettingWireless *s_wifi; const char *mode; @@ -721,7 +673,7 @@ check_connection_available (NMDevice *device, if (specific_object) { NMWifiAP *ap; - ap = get_ap_by_path (NM_DEVICE_WIFI (device), specific_object); + ap = nm_wifi_ap_lookup_for_device (NM_DEVICE (self), specific_object); return ap ? nm_wifi_ap_check_compatible (ap, connection) : FALSE; } @@ -745,50 +697,18 @@ check_connection_available (NMDevice *device, return TRUE; /* check at least one AP is compatible with this connection */ - return !!find_first_compatible_ap (NM_DEVICE_WIFI (device), connection, TRUE); -} - -static gboolean -is_manf_default_ssid (const GByteArray *ssid) -{ - int i; - /* - * List of manufacturer default SSIDs that are often unchanged by users. - * - * NOTE: this list should *not* contain networks that you would like to - * automatically roam to like "Starbucks" or "AT&T" or "T-Mobile HotSpot". - */ - static const char *manf_defaults[] = { - "linksys", - "linksys-a", - "linksys-g", - "default", - "belkin54g", - "NETGEAR", - "o2DSL", - "WLAN", - "ALICE-WLAN", - "Speedport W 501V", - "TURBONETT", - }; - - for (i = 0; i < G_N_ELEMENTS (manf_defaults); i++) { - if (ssid->len == strlen (manf_defaults[i])) { - if (memcmp (manf_defaults[i], ssid->data, ssid->len) == 0) - return TRUE; - } - } - return FALSE; + return !!nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); } static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - const GSList *existing_connections, + NMConnection *const*existing_connections, GError **error) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMSettingWireless *s_wifi; const char *setting_mac; char *str_ssid = NULL; @@ -825,7 +745,7 @@ complete_connection (NMDevice *device, if (!nm_streq0 (mode, NM_SETTING_WIRELESS_MODE_AP)) { /* Find a compatible AP in the scan list */ - ap = find_first_compatible_ap (self, connection, FALSE); + ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); /* If we still don't have an AP, then the WiFI settings needs to be * fully specified by the client. Might not be able to find an AP @@ -847,7 +767,7 @@ complete_connection (NMDevice *device, return FALSE; ap = NULL; } else { - ap = get_ap_by_path (self, specific_object); + ap = nm_wifi_ap_lookup_for_device (NM_DEVICE (self), specific_object); if (!ap) { g_set_error (error, NM_DEVICE_ERROR, @@ -900,7 +820,7 @@ complete_connection (NMDevice *device, */ if (!nm_wifi_ap_complete_connection (ap, connection, - is_manf_default_ssid (ssid), + nm_wifi_utils_is_manf_default_ssid (ssid), error)) { if (tmp_ssid) g_byte_array_unref (tmp_ssid); @@ -1007,6 +927,7 @@ can_auto_connect (NMDevice *device, char **specific_object) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMSettingWireless *s_wifi; NMWifiAP *ap; const char *method, *mode; @@ -1038,102 +959,20 @@ can_auto_connect (NMDevice *device, return FALSE; } - ap = find_first_compatible_ap (self, connection, FALSE); + ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); if (ap) { /* All good; connection is usable */ - NM_SET_OUT (specific_object, g_strdup (nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap)))); + NM_SET_OUT (specific_object, g_strdup (nm_dbus_object_get_path (NM_DBUS_OBJECT (ap)))); return TRUE; } return FALSE; } -static int -ap_id_compare (gconstpointer p_a, gconstpointer p_b, gpointer user_data) +const CList * +_nm_device_wifi_get_aps (NMDeviceWifi *self) { - guint64 a_id = nm_wifi_ap_get_id (*((NMWifiAP **) p_a)); - guint64 b_id = nm_wifi_ap_get_id (*((NMWifiAP **) p_b)); - - return a_id < b_id ? -1 : (a_id == b_id ? 0 : 1); -} - -static NMWifiAP ** -ap_list_get_sorted (NMDeviceWifi *self, gboolean include_without_ssid) -{ - NMDeviceWifiPrivate *priv; - NMWifiAP **list; - GHashTableIter iter; - NMWifiAP *ap; - gsize i, n; - - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - n = g_hash_table_size (priv->aps); - list = g_new (NMWifiAP *, n + 1); - - i = 0; - if (n > 0) { - g_hash_table_iter_init (&iter, priv->aps); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) { - nm_assert (i < n); - if ( include_without_ssid - || nm_wifi_ap_get_ssid (ap)) - list[i++] = ap; - } - nm_assert (i <= n); - nm_assert (!include_without_ssid || i == n); - - g_qsort_with_data (list, - i, - sizeof (gpointer), - ap_id_compare, - NULL); - } - list[i] = NULL; - return list; -} - -static const char ** -ap_list_get_sorted_paths (NMDeviceWifi *self, gboolean include_without_ssid) -{ - gpointer *list; - gsize i, j; - - list = (gpointer *) ap_list_get_sorted (self, include_without_ssid); - for (i = 0, j = 0; list[i]; i++) { - NMWifiAP *ap = list[i]; - const char *path; - - /* update @list inplace to hold instead the export-path. */ - path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap)); - nm_assert (path); - list[j++] = (gpointer) path; - } - return (const char **) list; -} - -static void -impl_device_wifi_get_access_points (NMDeviceWifi *self, - GDBusMethodInvocation *context) -{ - gs_free const char **list = NULL; - GVariant *v; - - list = ap_list_get_sorted_paths (self, FALSE); - v = g_variant_new_objv (list, -1); - g_dbus_method_invocation_return_value (context, g_variant_new_tuple (&v, 1)); -} - -static void -impl_device_wifi_get_all_access_points (NMDeviceWifi *self, - GDBusMethodInvocation *context) -{ - gs_free const char **list = NULL; - GVariant *v; - - list = ap_list_get_sorted_paths (self, TRUE); - v = g_variant_new_objv (list, -1); - g_dbus_method_invocation_return_value (context, g_variant_new_tuple (&v, 1)); + return &NM_DEVICE_WIFI_GET_PRIVATE (self)->aps_lst_head; } static void @@ -1153,7 +992,7 @@ _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset) priv = NM_DEVICE_WIFI_GET_PRIVATE (self); randomize = nm_config_data_get_device_config_boolean (NM_CONFIG_GET_DATA, - "wifi.scan-rand-mac-address", + NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_SCAN_RAND_MAC_ADDRESS, device, TRUE, TRUE); @@ -1239,7 +1078,6 @@ dbus_request_scan_cb (NMDevice *device, gpointer user_data) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); - NMDeviceWifiPrivate *priv; gs_unref_variant GVariant *scan_options = user_data; gs_unref_ptrarray GPtrArray *ssids = NULL; @@ -1256,8 +1094,6 @@ dbus_request_scan_cb (NMDevice *device, return; } - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - if (scan_options) { gs_unref_variant GVariant *val = g_variant_lookup_value (scan_options, "ssids", NULL); @@ -1284,20 +1120,20 @@ dbus_request_scan_cb (NMDevice *device, g_dbus_method_invocation_return_value (context, NULL); } -static void -impl_device_wifi_request_scan (NMDeviceWifi *self, - GDBusMethodInvocation *context, - GVariant *options) +void +_nm_device_wifi_request_scan (NMDeviceWifi *self, + GVariant *options, + GDBusMethodInvocation *invocation) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMDevice *device = NM_DEVICE (self); - gint32 last_scan; + gint64 last_scan; if ( !priv->enabled || !priv->sup_iface || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED || nm_device_is_activating (device)) { - g_dbus_method_invocation_return_error_literal (context, + g_dbus_method_invocation_return_error_literal (invocation, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ALLOWED, "Scanning not allowed while unavailable or activating"); @@ -1305,26 +1141,25 @@ impl_device_wifi_request_scan (NMDeviceWifi *self, } if (nm_supplicant_interface_get_scanning (priv->sup_iface)) { - g_dbus_method_invocation_return_error_literal (context, + g_dbus_method_invocation_return_error_literal (invocation, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ALLOWED, "Scanning not allowed while already scanning"); return; } - last_scan = nm_supplicant_interface_get_last_scan_time (priv->sup_iface); - if (last_scan && (nm_utils_get_monotonic_timestamp_s () - last_scan) < 10) { - g_dbus_method_invocation_return_error_literal (context, + last_scan = nm_supplicant_interface_get_last_scan (priv->sup_iface); + if (last_scan && (nm_utils_get_monotonic_timestamp_ms () - last_scan) < 10 * NM_UTILS_MSEC_PER_SECOND) { + g_dbus_method_invocation_return_error_literal (invocation, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ALLOWED, "Scanning not allowed immediately following previous scan"); return; } - /* Ask the manager to authenticate this request for us */ g_signal_emit_by_name (device, NM_DEVICE_AUTH_REQUEST, - context, + invocation, NULL, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE, @@ -1588,7 +1423,8 @@ supplicant_iface_scan_done_cb (NMSupplicantInterface *iface, _LOGD (LOGD_WIFI, "wifi-scan: scan-done callback: %s", success ? "successful" : "failed"); - priv->last_scan = nm_utils_get_monotonic_timestamp_s (); + priv->last_scan = nm_utils_get_monotonic_timestamp_ms (); + _notify (self, PROP_LAST_SCAN); schedule_scan (self, success); _requested_scan_set (self, FALSE); @@ -1608,17 +1444,15 @@ ap_list_dump (gpointer user_data) priv->ap_dump_id = 0; if (_LOGD_ENABLED (LOGD_WIFI_SCAN)) { - gs_free NMWifiAP **list = NULL; - gsize i; + NMWifiAP *ap; gint32 now_s = nm_utils_get_monotonic_timestamp_s (); - _LOGD (LOGD_WIFI_SCAN, "APs: [now:%u last:%u next:%u]", + _LOGD (LOGD_WIFI_SCAN, "APs: [now:%u last:%" G_GINT64_FORMAT " next:%u]", now_s, - priv->last_scan, + priv->last_scan / NM_UTILS_MSEC_PER_SECOND, priv->scheduled_scan_time); - list = ap_list_get_sorted (self, TRUE); - for (i = 0; list[i]; i++) - _ap_dump (self, LOGL_DEBUG, list[i], "dump", now_s); + c_list_for_each_entry (ap, &priv->aps_lst_head, aps_lst) + _ap_dump (self, LOGL_DEBUG, ap, "dump", now_s); } return G_SOURCE_REMOVE; } @@ -1689,7 +1523,7 @@ supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP) return; - found_ap = get_ap_by_supplicant_path (self, object_path); + found_ap = nm_wifi_aps_find_by_supplicant_path (&priv->aps_lst_head, object_path); if (found_ap) { if (!nm_wifi_ap_update_from_properties (found_ap, object_path, properties)) return; @@ -1721,7 +1555,7 @@ supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, } } - ap_add_remove (self, ACCESS_POINT_ADDED, ap, TRUE); + ap_add_remove (self, TRUE, ap, TRUE); } /* Update the current AP if the supplicant notified a current BSS change @@ -1745,7 +1579,7 @@ supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface, g_return_if_fail (object_path != NULL); priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - ap = get_ap_by_supplicant_path (self, object_path); + ap = nm_wifi_aps_find_by_supplicant_path (&priv->aps_lst_head, object_path); if (!ap) return; @@ -1758,7 +1592,7 @@ supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface, if (nm_wifi_ap_set_fake (ap, TRUE)) _ap_dump (self, LOGL_DEBUG, ap, "updated", 0); } else { - ap_add_remove (self, ACCESS_POINT_REMOVED, ap, TRUE); + ap_add_remove (self, FALSE, ap, TRUE); schedule_ap_list_dump (self); } } @@ -2289,7 +2123,7 @@ supplicant_iface_notify_current_bss (NMSupplicantInterface *iface, current_bss = nm_supplicant_interface_get_current_bss (iface); if (current_bss) - new_ap = get_ap_by_supplicant_path (self, current_bss); + new_ap = nm_wifi_aps_find_by_supplicant_path (&priv->aps_lst_head, current_bss); if (new_ap != priv->current_ap) { const char *new_bssid = NULL; @@ -2315,9 +2149,9 @@ supplicant_iface_notify_current_bss (NMSupplicantInterface *iface, } _LOGD (LOGD_WIFI, "roamed from BSSID %s (%s) to %s (%s)", - old_bssid ? old_bssid : "(none)", + old_bssid ?: "(none)", old_ssid ? nm_utils_escape_ssid (old_ssid->data, old_ssid->len) : "(none)", - new_bssid ? new_bssid : "(none)", + new_bssid ?: "(none)", new_ssid ? nm_utils_escape_ssid (new_ssid->data, new_ssid->len) : "(none)"); set_current_ap (self, new_ap, TRUE); @@ -2497,6 +2331,7 @@ build_supplicant_config (NMDeviceWifi *self, NMSettingWireless *s_wireless; NMSettingWirelessSecurity *s_wireless_sec; NMSettingWirelessSecurityPmf pmf; + NMSettingWirelessSecurityFils fils; gs_free char *value = NULL; g_return_val_if_fail (priv->sup_iface, NULL); @@ -2504,7 +2339,9 @@ build_supplicant_config (NMDeviceWifi *self, s_wireless = nm_connection_get_setting_wireless (connection); g_return_val_if_fail (s_wireless != NULL, NULL); - config = nm_supplicant_config_new (); + config = nm_supplicant_config_new ( + nm_supplicant_interface_get_pmf_support (priv->sup_iface) == NM_SUPPLICANT_FEATURE_YES, + nm_supplicant_interface_get_fils_support (priv->sup_iface) == NM_SUPPLICANT_FEATURE_YES); /* Warn if AP mode may not be supported */ if ( g_strcmp0 (nm_setting_wireless_get_mode (s_wireless), NM_SETTING_WIRELESS_MODE_AP) == 0 @@ -2546,24 +2383,16 @@ build_supplicant_config (NMDeviceWifi *self, NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL); } - /* Don't try to enable PMF on non-WPA networks */ - if (!NM_IN_STRSET (nm_setting_wireless_security_get_key_mgmt (s_wireless_sec), - "wpa-eap", - "wpa-psk")) - pmf = NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE; - - /* Check if we actually support PMF */ - if (nm_supplicant_interface_get_pmf_support (priv->sup_iface) != NM_SUPPLICANT_FEATURE_YES) { - if (pmf == NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) { - g_set_error_literal (error, NM_SUPPLICANT_ERROR, NM_SUPPLICANT_ERROR_CONFIG, - "Supplicant does not support PMF"); - goto error; - } else if (pmf == NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL) { - /* To be on the safe side, assume no support if we can't determine - * capabilities. - */ - pmf = NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE; - } + /* Configure FILS (802.11ai) */ + fils = nm_setting_wireless_security_get_fils (s_wireless_sec); + if (fils == NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT) { + value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "wifi-sec.fils", + NM_DEVICE (self)); + fils = _nm_utils_ascii_str_to_int64 (value, 10, + NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE, + NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED, + NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL); } s_8021x = nm_connection_get_setting_802_1x (connection); @@ -2573,6 +2402,7 @@ build_supplicant_config (NMDeviceWifi *self, con_uuid, mtu, pmf, + fils, error)) { g_prefix_error (error, "802-11-wireless-security: "); goto error; @@ -2593,6 +2423,48 @@ error: /*****************************************************************************/ +static gboolean +wake_on_wlan_enable (NMDeviceWifi *self) +{ + NMSettingWirelessWakeOnWLan wowl; + NMSettingWireless *s_wireless; + gs_free char *value = NULL; + + s_wireless = (NMSettingWireless *) nm_device_get_applied_setting (NM_DEVICE (self), NM_TYPE_SETTING_WIRELESS); + if (s_wireless) { + wowl = nm_setting_wireless_get_wake_on_wlan (s_wireless); + if (wowl != NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT) + goto found; + } + + value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "wifi.wake-on-wlan", + NM_DEVICE (self)); + + if (value) { + wowl = _nm_utils_ascii_str_to_int64 (value, 10, + NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE, + G_MAXINT32, + NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT); + + if (NM_FLAGS_ANY (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_EXCLUSIVE_FLAGS)) { + if (!nm_utils_is_power_of_two (wowl)) { + _LOGD (LOGD_WIFI, "invalid default value %u for wake-on-wlan: " + "'default' and 'ignore' are exclusive flags", (guint) wowl); + wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT; + } + } else if (NM_FLAGS_ANY (wowl, ~NM_SETTING_WIRELESS_WAKE_ON_WLAN_ALL)) { + _LOGD (LOGD_WIFI, "invalid default value %u for wake-on-wlan", (guint) wowl); + wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT; + } + if (wowl != NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT) + goto found; + } + wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE; +found: + return nm_platform_wifi_set_wake_on_wlan (NM_PLATFORM_GET, nm_device_get_ifindex (NM_DEVICE (self)), wowl); +} + static NMActStageReturn act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { @@ -2654,16 +2526,16 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) /* AP mode never uses a specific object or existing scanned AP */ if (priv->mode != NM_802_11_MODE_AP) { ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req)); - ap = ap_path ? get_ap_by_path (self, ap_path) : NULL; + ap = ap_path ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path) : NULL; if (ap) goto done; - ap = find_first_compatible_ap (self, connection, FALSE); + ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); } if (ap) { nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), - nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap))); + nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))); goto done; } @@ -2680,11 +2552,11 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) nm_wifi_ap_set_address (ap, nm_device_get_hw_address (device)); g_object_freeze_notify (G_OBJECT (self)); - ap_add_remove (self, ACCESS_POINT_ADDED, ap, TRUE); + ap_add_remove (self, TRUE, ap, TRUE); g_object_thaw_notify (G_OBJECT (self)); set_current_ap (self, ap, FALSE); nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), - nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap))); + nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))); return NM_ACT_STAGE_RETURN_SUCCESS; done: @@ -2786,6 +2658,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) s_wireless = nm_connection_get_setting_wireless (connection); g_assert (s_wireless); + wake_on_wlan_enable (self); + /* If we need secrets, get them */ setting_name = nm_connection_need_secrets (connection, NULL); if (setting_name) { @@ -2912,29 +2786,11 @@ act_stage3_ip6_config_start (NMDevice *device, } static guint32 -get_configured_mtu (NMDevice *device, gboolean *out_is_user_config) +get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source) { - NMSettingWireless *setting; - gint64 mtu_default; - guint32 mtu; - - nm_assert (NM_IS_DEVICE (device)); - nm_assert (out_is_user_config); - - setting = NM_SETTING_WIRELESS (nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRELESS)); - if (!setting) - g_return_val_if_reached (0); - - mtu = nm_setting_wireless_get_mtu (setting); - if (mtu == 0) { - mtu_default = nm_device_get_configured_mtu_from_connection_default (device, "wifi.mtu"); - if (mtu_default >= 0) { - *out_is_user_config = TRUE; - return (guint32) mtu_default; - } - } - *out_is_user_config = (mtu != 0); - return mtu; + return nm_device_get_configured_mtu_from_connection (device, + NM_TYPE_SETTING_WIRELESS, + out_source); } static gboolean @@ -3005,7 +2861,6 @@ handle_ip_config_timeout (NMDeviceWifi *self, return ret; } - static NMActStageReturn act_stage4_ip4_config_timeout (NMDevice *device, NMDeviceStateReason *out_failure_reason) { @@ -3055,13 +2910,10 @@ activation_success_handler (NMDevice *device) NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); int ifindex = nm_device_get_ifindex (device); NMActRequest *req; - NMConnection *applied_connection; req = nm_device_get_act_request (device); g_assert (req); - applied_connection = nm_act_request_get_applied_connection (req); - /* Clear any critical protocol notification in the wifi stack */ nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), ifindex, FALSE); @@ -3099,7 +2951,7 @@ activation_success_handler (NMDevice *device) } nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), - nm_exported_object_get_path (NM_EXPORTED_OBJECT (priv->current_ap))); + nm_dbus_object_get_path (NM_DBUS_OBJECT (priv->current_ap))); } periodic_update (self); @@ -3257,7 +3109,8 @@ can_reapply_change (NMDevice *device, return nm_device_hash_check_invalid_keys (diffs, NM_SETTING_WIRELESS_SETTING_NAME, error, - NM_SETTING_WIRELESS_MTU); /* reapplied with IP config */ + NM_SETTING_WIRELESS_MTU, /* reapplied with IP config */ + NM_SETTING_WIRELESS_WAKE_ON_WLAN); } device_class = NM_DEVICE_CLASS (nm_device_wifi_parent_class); @@ -3269,6 +3122,20 @@ can_reapply_change (NMDevice *device, error); } +static void +reapply_connection (NMDevice *device, NMConnection *con_old, NMConnection *con_new) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + + NM_DEVICE_CLASS (nm_device_wifi_parent_class)->reapply_connection (device, + con_old, + con_new); + + _LOGD (LOGD_DEVICE, "reapplying wireless settings"); + + wake_on_wlan_enable (self); +} + /*****************************************************************************/ static void @@ -3277,8 +3144,7 @@ get_property (GObject *object, guint prop_id, { NMDeviceWifi *self = NM_DEVICE_WIFI (object); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - gsize i; - char **list; + const char **list; switch (prop_id) { case PROP_MODE: @@ -3291,17 +3157,21 @@ get_property (GObject *object, guint prop_id, g_value_set_uint (value, priv->capabilities); break; case PROP_ACCESS_POINTS: - list = (char **) ap_list_get_sorted_paths (self, TRUE); - for (i = 0; list[i]; i++) - list[i] = g_strdup (list[i]); - g_value_take_boxed (value, list); + list = nm_wifi_aps_get_paths (&priv->aps_lst_head, TRUE); + g_value_take_boxed (value, nm_utils_strv_make_deep_copied (list)); break; case PROP_ACTIVE_ACCESS_POINT: - nm_utils_g_value_set_object_path (value, priv->current_ap); + nm_dbus_utils_g_value_set_object_path (value, priv->current_ap); break; case PROP_SCANNING: g_value_set_boolean (value, priv->is_scanning); break; + case PROP_LAST_SCAN: + g_value_set_int64 (value, + priv->last_scan > 0 + ? nm_utils_monotonic_timestamp_as_boottime (priv->last_scan, NM_UTILS_NS_PER_MSEC) + : (gint64) -1); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3333,8 +3203,9 @@ nm_device_wifi_init (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + c_list_init (&priv->aps_lst_head); + priv->mode = NM_802_11_MODE_INFRA; - priv->aps = g_hash_table_new (nm_str_hash, g_str_equal); } static void @@ -3392,9 +3263,7 @@ finalize (GObject *object) NMDeviceWifi *self = NM_DEVICE_WIFI (object); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - nm_assert (g_hash_table_size (priv->aps) == 0); - - g_hash_table_unref (priv->aps); + nm_assert (c_list_is_empty (&priv->aps_lst_head)); G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object); } @@ -3403,6 +3272,7 @@ static void nm_device_wifi_class_init (NMDeviceWifiClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRELESS_SETTING_NAME, NM_LINK_TYPE_WIFI) @@ -3413,6 +3283,8 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) object_class->dispose = dispose; object_class->finalize = finalize; + dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&nm_interface_info_device_wireless); + parent_class->can_auto_connect = can_auto_connect; parent_class->get_autoconnect_allowed = get_autoconnect_allowed; parent_class->is_available = is_available; @@ -3433,6 +3305,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) parent_class->deactivate_reset_hw_addr = deactivate_reset_hw_addr; parent_class->unmanaged_on_quit = unmanaged_on_quit; parent_class->can_reapply_change = can_reapply_change; + parent_class->reapply_connection = reapply_connection; parent_class->state_changed = device_state_changed; @@ -3477,25 +3350,12 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - signals[ACCESS_POINT_ADDED] = - g_signal_new (NM_DEVICE_WIFI_ACCESS_POINT_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - NM_TYPE_WIFI_AP); + obj_properties[PROP_LAST_SCAN] = + g_param_spec_int64 (NM_DEVICE_WIFI_LAST_SCAN, "", "", + -1, G_MAXINT64, -1, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - signals[ACCESS_POINT_REMOVED] = - g_signal_new (NM_DEVICE_WIFI_ACCESS_POINT_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - NM_TYPE_WIFI_AP); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); signals[SCANNING_PROHIBITED] = g_signal_new (NM_DEVICE_WIFI_SCANNING_PROHIBITED, @@ -3504,13 +3364,4 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) 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, - "GetAccessPoints", impl_device_wifi_get_access_points, - "GetAllAccessPoints", impl_device_wifi_get_all_access_points, - "RequestScan", impl_device_wifi_request_scan, - NULL); } - - |