supplicant,device: support AP isolation

Support setting the ApIsolate property of the supplicant interface
during association and resetting it to zero during disconnection.
This commit is contained in:
Beniamino Galvani 2020-06-29 17:46:37 +02:00
parent dbfe219d5b
commit 4db4801038
4 changed files with 132 additions and 15 deletions

View file

@ -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;

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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);
}
}
/*****************************************************************************/