summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/devices/wifi/nm-device-wifi.c12
-rw-r--r--src/supplicant/nm-supplicant-config.c12
-rw-r--r--src/supplicant/nm-supplicant-config.h4
-rw-r--r--src/supplicant/nm-supplicant-interface.c119
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);
+ }
}
/*****************************************************************************/