diff options
-rw-r--r-- | src/devices/wifi/nm-device-wifi.c | 12 | ||||
-rw-r--r-- | src/supplicant/nm-supplicant-config.c | 12 | ||||
-rw-r--r-- | src/supplicant/nm-supplicant-config.h | 4 | ||||
-rw-r--r-- | src/supplicant/nm-supplicant-interface.c | 119 |
4 files changed, 132 insertions, 15 deletions
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index cf849bcdc8..3872a39efb 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -2810,6 +2810,7 @@ build_supplicant_config (NMDeviceWifi *self, NMSettingWirelessSecurity *s_wireless_sec; NMSettingWirelessSecurityPmf pmf; NMSettingWirelessSecurityFils fils; + NMTernary ap_isolation; g_return_val_if_fail (priv->sup_iface, NULL); @@ -2837,6 +2838,17 @@ build_supplicant_config (NMDeviceWifi *self, goto error; } + ap_isolation = nm_setting_wireless_get_ap_isolation (s_wireless); + if (ap_isolation == NM_TERNARY_DEFAULT) { + ap_isolation = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA, + "wifi.ap-isolation", + NM_DEVICE (self), + NM_TERNARY_FALSE, + NM_TERNARY_TRUE, + NM_TERNARY_FALSE); + } + nm_supplicant_config_set_ap_isolation (config, ap_isolation == NM_TERNARY_TRUE); + 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 1e09697721..2949f32f68 100644 --- a/src/supplicant/nm-supplicant-config.c +++ b/src/supplicant/nm-supplicant-config.c @@ -34,6 +34,7 @@ typedef struct { guint32 ap_scan; bool fast_required:1; bool dispose_has_run:1; + bool ap_isolation:1; } NMSupplicantConfigPrivate; struct _NMSupplicantConfig { @@ -1521,3 +1522,14 @@ nm_supplicant_config_add_no_security (NMSupplicantConfig *self, GError **error) return nm_supplicant_config_add_option (self, "key_mgmt", "NONE", -1, NULL, error); } +gboolean +nm_supplicant_config_get_ap_isolation (NMSupplicantConfig *self) +{ + return self->_priv.ap_isolation; +} + +void +nm_supplicant_config_set_ap_isolation (NMSupplicantConfig *self, gboolean ap_isolation) +{ + self->_priv.ap_isolation = ap_isolation; +} diff --git a/src/supplicant/nm-supplicant-config.h b/src/supplicant/nm-supplicant-config.h index e1da9a1eca..530c2cdd0b 100644 --- a/src/supplicant/nm-supplicant-config.h +++ b/src/supplicant/nm-supplicant-config.h @@ -69,4 +69,8 @@ gboolean nm_supplicant_config_add_setting_macsec (NMSupplicantConfig *self, gboolean nm_supplicant_config_enable_pmf_akm (NMSupplicantConfig *self, GError **error); + +void nm_supplicant_config_set_ap_isolation (NMSupplicantConfig *self, gboolean ap_isolation); +gboolean nm_supplicant_config_get_ap_isolation (NMSupplicantConfig *self); + #endif /* __NETWORKMANAGER_SUPPLICANT_CONFIG_H__ */ diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c index 3dda0fbf25..933afb2974 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/supplicant/nm-supplicant-interface.c @@ -44,6 +44,7 @@ typedef struct { gpointer user_data; guint fail_on_idle_id; guint blobs_left; + guint calls_left; struct _AddNetworkData *add_network_data; } AssocData; @@ -157,6 +158,8 @@ typedef struct _NMSupplicantInterfacePrivate { bool prop_scan_active:1; bool prop_scan_ssid:1; + bool ap_isolate_supported:1; + bool ap_isolate_needs_reset:1; } NMSupplicantInterfacePrivate; struct _NMSupplicantInterfaceClass { @@ -436,6 +439,20 @@ _remove_network (NMSupplicantInterface *self) g_variant_new ("(o)", net_path), G_VARIANT_TYPE ("()"), "remove-network"); + + if ( priv->ap_isolate_supported + && priv->ap_isolate_needs_reset) { + _dbus_connection_call_simple (self, + DBUS_INTERFACE_PROPERTIES, + "Set", + g_variant_new ("(ssv)", + NM_WPAS_DBUS_IFACE_INTERFACE, + "ApIsolate", + g_variant_new_string ("0")), + G_VARIANT_TYPE ("()"), + "reset-ap-isolation"); + } + priv->ap_isolate_needs_reset = FALSE; } /*****************************************************************************/ @@ -1868,6 +1885,9 @@ _properties_changed_main (NMSupplicantInterface *self, } } + if (nm_g_variant_lookup (properties, "ApIsolate", "&s", &v_s)) + priv->ap_isolate_supported = TRUE; + if (do_log_driver_info) { _LOGD ("supplicant interface for ifindex=%d, ifname=%s%s%s, driver=%s%s%s (requested %s)", priv->ifindex, @@ -2227,27 +2247,13 @@ assoc_add_network_cb (GObject *source, GAsyncResult *result, gpointer user_data) } static void -assoc_set_ap_scan_cb (GVariant *ret, GError *error, gpointer user_data) +add_network (NMSupplicantInterface *self) { - NMSupplicantInterface *self; NMSupplicantInterfacePrivate *priv; AddNetworkData *add_network_data; - if (nm_utils_error_is_cancelled (error)) - return; - - self = NM_SUPPLICANT_INTERFACE (user_data); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - if (error) { - assoc_return (self, error, "failure to set AP scan mode"); - return; - } - - _LOGT ("assoc["NM_HASH_OBFUSCATE_PTR_FMT"]: interface ap_scan set to %d", - NM_HASH_OBFUSCATE_PTR (priv->assoc_data), - nm_supplicant_config_get_ap_scan (priv->assoc_data->cfg)); - /* the association does not keep @self alive. We want to be able to remove * the network again, even if @self is already gone. Hence, track the data * separately. @@ -2276,6 +2282,62 @@ assoc_set_ap_scan_cb (GVariant *ret, GError *error, gpointer user_data) add_network_data); } +static void +assoc_set_ap_isolation (GVariant *ret, GError *error, gpointer user_data) +{ + NMSupplicantInterface *self; + NMSupplicantInterfacePrivate *priv; + gboolean value; + + if (nm_utils_error_is_cancelled (error)) + return; + + self = NM_SUPPLICANT_INTERFACE (user_data); + priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + if (error) { + assoc_return (self, error, "failure to set AP isolation"); + return; + } + + value = nm_supplicant_config_get_ap_isolation (priv->assoc_data->cfg); + _LOGT ("assoc["NM_HASH_OBFUSCATE_PTR_FMT"]: interface AP isolation set to %d", + NM_HASH_OBFUSCATE_PTR (priv->assoc_data), + value); + + priv->ap_isolate_needs_reset = value; + + nm_assert (priv->assoc_data->calls_left > 0); + if (--priv->assoc_data->calls_left == 0) + add_network (self); +} + +static void +assoc_set_ap_scan_cb (GVariant *ret, GError *error, gpointer user_data) +{ + NMSupplicantInterface *self; + NMSupplicantInterfacePrivate *priv; + + if (nm_utils_error_is_cancelled (error)) + return; + + self = NM_SUPPLICANT_INTERFACE (user_data); + priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + if (error) { + assoc_return (self, error, "failure to set AP scan mode"); + return; + } + + _LOGT ("assoc["NM_HASH_OBFUSCATE_PTR_FMT"]: interface ap_scan set to %d", + NM_HASH_OBFUSCATE_PTR (priv->assoc_data), + nm_supplicant_config_get_ap_scan (priv->assoc_data->cfg)); + + nm_assert (priv->assoc_data->calls_left > 0); + if (--priv->assoc_data->calls_left == 0) + add_network (self); +} + static gboolean assoc_fail_on_idle_cb (gpointer user_data) { @@ -2312,6 +2374,7 @@ nm_supplicant_interface_assoc (NMSupplicantInterface *self, { NMSupplicantInterfacePrivate *priv; AssocData *assoc_data; + gboolean ap_isolation; g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self)); g_return_if_fail (NM_IS_SUPPLICANT_CONFIG (cfg)); @@ -2343,6 +2406,7 @@ nm_supplicant_interface_assoc (NMSupplicantInterface *self, } assoc_data->cancellable = g_cancellable_new(); + assoc_data->calls_left++; nm_dbus_connection_call_set (priv->dbus_connection, priv->name_owner->str, priv->object_path->str, @@ -2353,6 +2417,31 @@ nm_supplicant_interface_assoc (NMSupplicantInterface *self, assoc_data->cancellable, assoc_set_ap_scan_cb, self); + + ap_isolation = nm_supplicant_config_get_ap_isolation (priv->assoc_data->cfg); + if (!priv->ap_isolate_supported) { + if (ap_isolation) { + _LOGW ("assoc["NM_HASH_OBFUSCATE_PTR_FMT"]: requested AP isolation but the supplicant doesn't support it", + NM_HASH_OBFUSCATE_PTR (assoc_data)); + } + } else { + assoc_data->calls_left++; + /* It would be smarter to change the property only when necessary. + * However, wpa_supplicant doesn't send the PropertiesChanged + * signal for ApIsolate, and so to know the current value we would + * need first a Get call. It seems simpler to just set the value + * we want. */ + nm_dbus_connection_call_set (priv->dbus_connection, + priv->name_owner->str, + priv->object_path->str, + NM_WPAS_DBUS_IFACE_INTERFACE, + "ApIsolate", + g_variant_new_string (ap_isolation ? "1" : "0"), + DBUS_TIMEOUT_MSEC, + assoc_data->cancellable, + assoc_set_ap_isolation, + self); + } } /*****************************************************************************/ |