wifi/iwd: merge branch 'balrog-kun/NetworkManager:iwd-fixes'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1338
This commit is contained in:
@@ -70,6 +70,7 @@ typedef struct {
|
|||||||
bool secrets_failed : 1;
|
bool secrets_failed : 1;
|
||||||
bool networks_requested : 1;
|
bool networks_requested : 1;
|
||||||
bool networks_changed : 1;
|
bool networks_changed : 1;
|
||||||
|
bool assuming : 1;
|
||||||
gint64 last_scan;
|
gint64 last_scan;
|
||||||
uint32_t ap_id;
|
uint32_t ap_id;
|
||||||
guint32 rate;
|
guint32 rate;
|
||||||
@@ -77,6 +78,7 @@ typedef struct {
|
|||||||
GDBusMethodInvocation *pending_agent_request;
|
GDBusMethodInvocation *pending_agent_request;
|
||||||
NMActiveConnection *assumed_ac;
|
NMActiveConnection *assumed_ac;
|
||||||
guint assumed_ac_timeout;
|
guint assumed_ac_timeout;
|
||||||
|
NMIwdManager *manager;
|
||||||
} NMDeviceIwdPrivate;
|
} NMDeviceIwdPrivate;
|
||||||
|
|
||||||
struct _NMDeviceIwd {
|
struct _NMDeviceIwd {
|
||||||
@@ -289,6 +291,7 @@ insert_ap_from_network(NMDeviceIwd *self,
|
|||||||
gint64 last_seen_msec,
|
gint64 last_seen_msec,
|
||||||
int16_t signal)
|
int16_t signal)
|
||||||
{
|
{
|
||||||
|
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
|
||||||
gs_unref_object GDBusProxy *network_proxy = NULL;
|
gs_unref_object GDBusProxy *network_proxy = NULL;
|
||||||
nm_auto_ref_string NMRefString *bss_path = nm_ref_string_new(path);
|
nm_auto_ref_string NMRefString *bss_path = nm_ref_string_new(path);
|
||||||
NMWifiAP *ap;
|
NMWifiAP *ap;
|
||||||
@@ -299,7 +302,7 @@ insert_ap_from_network(NMDeviceIwd *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
network_proxy =
|
network_proxy =
|
||||||
nm_iwd_manager_get_dbus_interface(nm_iwd_manager_get(), path, NM_IWD_NETWORK_INTERFACE);
|
nm_iwd_manager_get_dbus_interface(priv->manager, path, NM_IWD_NETWORK_INTERFACE);
|
||||||
|
|
||||||
ap = ap_from_network(self, network_proxy, bss_path, last_seen_msec, signal);
|
ap = ap_from_network(self, network_proxy, bss_path, last_seen_msec, signal);
|
||||||
if (!ap)
|
if (!ap)
|
||||||
@@ -581,6 +584,10 @@ deactivate(NMDevice *device)
|
|||||||
if (!priv->dbus_obj)
|
if (!priv->dbus_obj)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Don't cause IWD to break the connection being assumed */
|
||||||
|
if (priv->assuming)
|
||||||
|
return;
|
||||||
|
|
||||||
if (priv->dbus_station_proxy) {
|
if (priv->dbus_station_proxy) {
|
||||||
gs_unref_variant GVariant *value =
|
gs_unref_variant GVariant *value =
|
||||||
g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State");
|
g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State");
|
||||||
@@ -673,7 +680,7 @@ deactivate_async(NMDevice *device,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
is_connection_known_network(NMConnection *connection)
|
is_connection_known_network(NMIwdManager *manager, NMConnection *connection)
|
||||||
{
|
{
|
||||||
NMIwdNetworkSecurity security;
|
NMIwdNetworkSecurity security;
|
||||||
gs_free char *ssid = NULL;
|
gs_free char *ssid = NULL;
|
||||||
@@ -681,17 +688,17 @@ is_connection_known_network(NMConnection *connection)
|
|||||||
if (!nm_wifi_connection_get_iwd_ssid_and_security(connection, &ssid, &security))
|
if (!nm_wifi_connection_get_iwd_ssid_and_security(connection, &ssid, &security))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return nm_iwd_manager_is_known_network(nm_iwd_manager_get(), ssid, security);
|
return nm_iwd_manager_is_known_network(manager, ssid, security);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
is_ap_known_network(NMWifiAP *ap)
|
is_ap_known_network(NMIwdManager *manager, NMWifiAP *ap)
|
||||||
{
|
{
|
||||||
gs_unref_object GDBusProxy *network_proxy = NULL;
|
gs_unref_object GDBusProxy *network_proxy = NULL;
|
||||||
gs_unref_variant GVariant *known_network = NULL;
|
gs_unref_variant GVariant *known_network = NULL;
|
||||||
|
|
||||||
network_proxy =
|
network_proxy =
|
||||||
nm_iwd_manager_get_dbus_interface(nm_iwd_manager_get(),
|
nm_iwd_manager_get_dbus_interface(manager,
|
||||||
nm_ref_string_get_str(nm_wifi_ap_get_supplicant_path(ap)),
|
nm_ref_string_get_str(nm_wifi_ap_get_supplicant_path(ap)),
|
||||||
NM_IWD_NETWORK_INTERFACE);
|
NM_IWD_NETWORK_INTERFACE);
|
||||||
if (!network_proxy)
|
if (!network_proxy)
|
||||||
@@ -794,7 +801,8 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError *
|
|||||||
* thus are Known Networks.
|
* thus are Known Networks.
|
||||||
*/
|
*/
|
||||||
if (security == NM_IWD_NETWORK_SECURITY_8021X) {
|
if (security == NM_IWD_NETWORK_SECURITY_8021X) {
|
||||||
if (!is_connection_known_network(connection)) {
|
if (!is_connection_known_network(priv->manager, connection)
|
||||||
|
&& !nm_iwd_manager_is_recently_mirrored(priv->manager, ssid)) {
|
||||||
nm_utils_error_set_literal(error,
|
nm_utils_error_set_literal(error,
|
||||||
NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
|
NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
|
||||||
"802.1x connections must have IWD provisioning files");
|
"802.1x connections must have IWD provisioning files");
|
||||||
@@ -927,7 +935,9 @@ check_connection_available(NMDevice *device,
|
|||||||
*/
|
*/
|
||||||
if (nm_wifi_connection_get_iwd_ssid_and_security(connection, NULL, &security)
|
if (nm_wifi_connection_get_iwd_ssid_and_security(connection, NULL, &security)
|
||||||
&& security == NM_IWD_NETWORK_SECURITY_8021X) {
|
&& security == NM_IWD_NETWORK_SECURITY_8021X) {
|
||||||
if (!is_ap_known_network(ap)) {
|
if (!is_ap_known_network(priv->manager, ap)
|
||||||
|
&& !nm_iwd_manager_is_recently_mirrored(priv->manager,
|
||||||
|
nm_setting_wireless_get_ssid(s_wifi))) {
|
||||||
nm_utils_error_set_literal(
|
nm_utils_error_set_literal(
|
||||||
error,
|
error,
|
||||||
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
|
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
|
||||||
@@ -2044,7 +2054,7 @@ assume_connection(NMDeviceIwd *self, NMWifiAP *ap)
|
|||||||
* becomes "managed" only when ACTIVATED but for IWD it's really
|
* becomes "managed" only when ACTIVATED but for IWD it's really
|
||||||
* managed when IP_CONFIG starts.
|
* managed when IP_CONFIG starts.
|
||||||
*/
|
*/
|
||||||
sett_conn = nm_iwd_manager_get_ap_mirror_connection(nm_iwd_manager_get(), ap);
|
sett_conn = nm_iwd_manager_get_ap_mirror_connection(priv->manager, ap);
|
||||||
if (!sett_conn)
|
if (!sett_conn)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@@ -2217,7 +2227,8 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||||||
* for a first-time connection to a hidden network. If a hidden network is
|
* for a first-time connection to a hidden network. If a hidden network is
|
||||||
* a Known Network it should still have been in the AP list.
|
* a Known Network it should still have been in the AP list.
|
||||||
*/
|
*/
|
||||||
if (!nm_setting_wireless_get_hidden(s_wireless) || is_connection_known_network(connection))
|
if (!nm_setting_wireless_get_hidden(s_wireless)
|
||||||
|
|| is_connection_known_network(priv->manager, connection))
|
||||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||||
|
|
||||||
add_new:
|
add_new:
|
||||||
@@ -2270,6 +2281,18 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* With priv->iwd_autoconnect we have to let IWD handle retries for
|
||||||
|
* infrastructure networks. IWD will not necessarily retry the same
|
||||||
|
* network after a failure but it will likely go into an autoconnect
|
||||||
|
* mode and we don't want to try to override the logic. We don't need
|
||||||
|
* to reset the retry count so we set no timeout.
|
||||||
|
*/
|
||||||
|
if (priv->iwd_autoconnect) {
|
||||||
|
NMSettingsConnection *sett_conn = nm_act_request_get_settings_connection(req);
|
||||||
|
|
||||||
|
nm_settings_connection_autoconnect_retries_set(sett_conn, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* With priv->iwd_autoconnect, if we're assuming a connection because
|
/* With priv->iwd_autoconnect, if we're assuming a connection because
|
||||||
* of a state change to "connecting", signal stage 2 is still running.
|
* of a state change to "connecting", signal stage 2 is still running.
|
||||||
* If "connected" or "roaming", we can go right to the IP_CONFIG state
|
* If "connected" or "roaming", we can go right to the IP_CONFIG state
|
||||||
@@ -2310,7 +2333,9 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||||||
* fail, for other combinations we will let the Connect call fail
|
* fail, for other combinations we will let the Connect call fail
|
||||||
* or ask us for any missing secrets through the Agent.
|
* or ask us for any missing secrets through the Agent.
|
||||||
*/
|
*/
|
||||||
if (nm_connection_get_setting_802_1x(connection) && !is_ap_known_network(ap)) {
|
if (nm_connection_get_setting_802_1x(connection) && !is_ap_known_network(priv->manager, ap)
|
||||||
|
&& !nm_iwd_manager_is_recently_mirrored(priv->manager,
|
||||||
|
nm_setting_wireless_get_ssid(s_wireless))) {
|
||||||
_LOGI(LOGD_DEVICE | LOGD_WIFI,
|
_LOGI(LOGD_DEVICE | LOGD_WIFI,
|
||||||
"Activation: (wifi) access point '%s' has 802.1x security but is not configured "
|
"Activation: (wifi) access point '%s' has 802.1x security but is not configured "
|
||||||
"in IWD.",
|
"in IWD.",
|
||||||
@@ -2351,7 +2376,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||||||
}
|
}
|
||||||
|
|
||||||
network_proxy = nm_iwd_manager_get_dbus_interface(
|
network_proxy = nm_iwd_manager_get_dbus_interface(
|
||||||
nm_iwd_manager_get(),
|
priv->manager,
|
||||||
nm_ref_string_get_str(nm_wifi_ap_get_supplicant_path(ap)),
|
nm_ref_string_get_str(nm_wifi_ap_get_supplicant_path(ap)),
|
||||||
NM_IWD_NETWORK_INTERFACE);
|
NM_IWD_NETWORK_INTERFACE);
|
||||||
if (!network_proxy) {
|
if (!network_proxy) {
|
||||||
@@ -2719,11 +2744,19 @@ state_changed(NMDeviceIwd *self, const char *new_state)
|
|||||||
"IWD is connecting to the wrong AP, %s activation",
|
"IWD is connecting to the wrong AP, %s activation",
|
||||||
switch_ap ? "replacing" : "aborting");
|
switch_ap ? "replacing" : "aborting");
|
||||||
cleanup_association_attempt(self, !switch_ap);
|
cleanup_association_attempt(self, !switch_ap);
|
||||||
|
|
||||||
|
if (!switch_ap) {
|
||||||
nm_device_state_changed(device,
|
nm_device_state_changed(device,
|
||||||
NM_DEVICE_STATE_FAILED,
|
NM_DEVICE_STATE_FAILED,
|
||||||
NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
|
NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (switch_ap)
|
priv->assuming = TRUE; /* Don't send Station.Disconnect() */
|
||||||
|
nm_device_state_changed(device,
|
||||||
|
NM_DEVICE_STATE_DISCONNECTED,
|
||||||
|
NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
|
||||||
|
priv->assuming = FALSE;
|
||||||
assume_connection(self, ap);
|
assume_connection(self, ap);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3101,7 +3134,7 @@ nm_device_iwd_set_dbus_object(NMDeviceIwd *self, GDBusObject *object)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter_proxy = nm_iwd_manager_get_dbus_interface(nm_iwd_manager_get(),
|
adapter_proxy = nm_iwd_manager_get_dbus_interface(priv->manager,
|
||||||
g_variant_get_string(value, NULL),
|
g_variant_get_string(value, NULL),
|
||||||
NM_IWD_WIPHY_INTERFACE);
|
NM_IWD_WIPHY_INTERFACE);
|
||||||
if (!adapter_proxy) {
|
if (!adapter_proxy) {
|
||||||
@@ -3411,7 +3444,7 @@ nm_device_iwd_init(NMDeviceIwd *self)
|
|||||||
g_signal_connect(self, "notify::" NM_DEVICE_AUTOCONNECT, G_CALLBACK(autoconnect_changed), self);
|
g_signal_connect(self, "notify::" NM_DEVICE_AUTOCONNECT, G_CALLBACK(autoconnect_changed), self);
|
||||||
|
|
||||||
/* Make sure the manager is running */
|
/* Make sure the manager is running */
|
||||||
(void) nm_iwd_manager_get();
|
priv->manager = g_object_ref(nm_iwd_manager_get());
|
||||||
}
|
}
|
||||||
|
|
||||||
NMDevice *
|
NMDevice *
|
||||||
@@ -3443,6 +3476,8 @@ dispose(GObject *object)
|
|||||||
G_OBJECT_CLASS(nm_device_iwd_parent_class)->dispose(object);
|
G_OBJECT_CLASS(nm_device_iwd_parent_class)->dispose(object);
|
||||||
|
|
||||||
nm_assert(c_list_is_empty(&priv->aps_lst_head));
|
nm_assert(c_list_is_empty(&priv->aps_lst_head));
|
||||||
|
|
||||||
|
g_clear_object(&priv->manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -46,6 +46,11 @@ typedef struct {
|
|||||||
const KnownNetworkId *id;
|
const KnownNetworkId *id;
|
||||||
} KnownNetworkData;
|
} KnownNetworkData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GBytes *ssid;
|
||||||
|
gint64 timestamp;
|
||||||
|
} RecentlyMirroredData;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NMManager *manager;
|
NMManager *manager;
|
||||||
NMSettings *settings;
|
NMSettings *settings;
|
||||||
@@ -62,6 +67,7 @@ typedef struct {
|
|||||||
GHashTable *p2p_devices;
|
GHashTable *p2p_devices;
|
||||||
NMIwdWfdInfo wfd_info;
|
NMIwdWfdInfo wfd_info;
|
||||||
guint wfd_use_count;
|
guint wfd_use_count;
|
||||||
|
GSList *recently_mirrored;
|
||||||
} NMIwdManagerPrivate;
|
} NMIwdManagerPrivate;
|
||||||
|
|
||||||
struct _NMIwdManager {
|
struct _NMIwdManager {
|
||||||
@@ -353,6 +359,70 @@ register_agent(NMIwdManager *self)
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
recently_mirrored_data_free(void *data)
|
||||||
|
{
|
||||||
|
RecentlyMirroredData *rmd = data;
|
||||||
|
|
||||||
|
g_bytes_unref(rmd->ssid);
|
||||||
|
g_free(rmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When we mirror an 802.1x connection to an IWD config file, and there's an
|
||||||
|
* AP in range with matching SSID, that connection should become available
|
||||||
|
* for activation. In IWD terms when an 802.1x network becomes a Known
|
||||||
|
* Network, it can be connected to using the .Connect D-Bus method.
|
||||||
|
*
|
||||||
|
* However there's a delay between writing the IWD config file and receiving
|
||||||
|
* the InterfaceAdded event for the Known Network so we don't immediately
|
||||||
|
* find out that the network can now be used. If an NM client creates a
|
||||||
|
* new connection for an 802.1x AP and tries to activate it immediately,
|
||||||
|
* NMDeviceIWD will not allow it to because it doesn't know the network is
|
||||||
|
* known yet. To work around this, we save the SSIDs of 802.1x connections
|
||||||
|
* we recently mirrored to IWD config files, for 2 seconds, and we treat
|
||||||
|
* them as Known Networks in that period since in theory activations should
|
||||||
|
* succeed.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
nm_iwd_manager_is_recently_mirrored(NMIwdManager *self, const GBytes *ssid)
|
||||||
|
{
|
||||||
|
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self);
|
||||||
|
gint64 now = nm_utils_get_monotonic_timestamp_nsec();
|
||||||
|
GSList *iter;
|
||||||
|
RecentlyMirroredData *rmd;
|
||||||
|
|
||||||
|
/* Drop entries older than 2 seconds */
|
||||||
|
while (priv->recently_mirrored) {
|
||||||
|
rmd = priv->recently_mirrored->data;
|
||||||
|
if (now < rmd->timestamp + 2000000000)
|
||||||
|
break;
|
||||||
|
|
||||||
|
priv->recently_mirrored = g_slist_remove(priv->recently_mirrored, rmd);
|
||||||
|
recently_mirrored_data_free(rmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (iter = priv->recently_mirrored; iter; iter = iter->next) {
|
||||||
|
rmd = iter->data;
|
||||||
|
if (g_bytes_equal(ssid, rmd->ssid))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
save_mirrored(NMIwdManager *self, GBytes *ssid)
|
||||||
|
{
|
||||||
|
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self);
|
||||||
|
RecentlyMirroredData *rmd = g_malloc(sizeof(RecentlyMirroredData));
|
||||||
|
|
||||||
|
rmd->ssid = g_bytes_ref(ssid);
|
||||||
|
rmd->timestamp = nm_utils_get_monotonic_timestamp_nsec();
|
||||||
|
priv->recently_mirrored = g_slist_append(priv->recently_mirrored, rmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
static KnownNetworkId *
|
static KnownNetworkId *
|
||||||
known_network_id_new(const char *name, NMIwdNetworkSecurity security)
|
known_network_id_new(const char *name, NMIwdNetworkSecurity security)
|
||||||
{
|
{
|
||||||
@@ -721,6 +791,9 @@ sett_conn_changed(NMSettingsConnection *sett_conn,
|
|||||||
"iwd: changed Wi-Fi connection %s mirrored as IWD profile %s",
|
"iwd: changed Wi-Fi connection %s mirrored as IWD profile %s",
|
||||||
nm_settings_connection_get_id(sett_conn),
|
nm_settings_connection_get_id(sett_conn),
|
||||||
full_path);
|
full_path);
|
||||||
|
|
||||||
|
if (security == NM_IWD_NETWORK_SECURITY_8021X)
|
||||||
|
save_mirrored(nm_iwd_manager_get(), ssid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look up an existing NMSettingsConnection for a network that has been
|
/* Look up an existing NMSettingsConnection for a network that has been
|
||||||
@@ -1283,6 +1356,7 @@ connection_added(NMSettings *settings, NMSettingsConnection *sett_conn, gpointer
|
|||||||
gs_free_error GError *error = NULL;
|
gs_free_error GError *error = NULL;
|
||||||
nm_auto_unref_keyfile GKeyFile *iwd_config = NULL;
|
nm_auto_unref_keyfile GKeyFile *iwd_config = NULL;
|
||||||
NMSettingsConnectionIntFlags flags;
|
NMSettingsConnectionIntFlags flags;
|
||||||
|
NMIwdNetworkSecurity security;
|
||||||
|
|
||||||
if (!nm_streq(nm_settings_connection_get_connection_type(sett_conn), "802-11-wireless"))
|
if (!nm_streq(nm_settings_connection_get_connection_type(sett_conn), "802-11-wireless"))
|
||||||
return;
|
return;
|
||||||
@@ -1338,6 +1412,12 @@ connection_added(NMSettings *settings, NMSettingsConnection *sett_conn, gpointer
|
|||||||
_LOGD("New Wi-Fi connection %s mirrored as IWD profile %s",
|
_LOGD("New Wi-Fi connection %s mirrored as IWD profile %s",
|
||||||
nm_settings_connection_get_id(sett_conn),
|
nm_settings_connection_get_id(sett_conn),
|
||||||
full_path);
|
full_path);
|
||||||
|
|
||||||
|
if (nm_wifi_connection_get_iwd_ssid_and_security(conn, NULL, &security)
|
||||||
|
&& security == NM_IWD_NETWORK_SECURITY_8021X) {
|
||||||
|
NMSettingWireless *s_wifi = nm_connection_get_setting_wireless(conn);
|
||||||
|
save_mirrored(nm_iwd_manager_get(), nm_setting_wireless_get_ssid(s_wifi));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -1952,6 +2032,8 @@ dispose(GObject *object)
|
|||||||
|
|
||||||
g_hash_table_unref(nm_steal_pointer(&priv->p2p_devices));
|
g_hash_table_unref(nm_steal_pointer(&priv->p2p_devices));
|
||||||
|
|
||||||
|
g_slist_free_full(nm_steal_pointer(&priv->recently_mirrored), recently_mirrored_data_free);
|
||||||
|
|
||||||
G_OBJECT_CLASS(nm_iwd_manager_parent_class)->dispose(object);
|
G_OBJECT_CLASS(nm_iwd_manager_parent_class)->dispose(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -63,4 +63,6 @@ gboolean nm_iwd_manager_check_wfd_info_compatible(NMIwdManager *self, const NMIw
|
|||||||
gboolean nm_iwd_manager_register_wfd(NMIwdManager *self, const NMIwdWfdInfo *wfd_info);
|
gboolean nm_iwd_manager_register_wfd(NMIwdManager *self, const NMIwdWfdInfo *wfd_info);
|
||||||
void nm_iwd_manager_unregister_wfd(NMIwdManager *self);
|
void nm_iwd_manager_unregister_wfd(NMIwdManager *self);
|
||||||
|
|
||||||
|
bool nm_iwd_manager_is_recently_mirrored(NMIwdManager *self, const GBytes *ssid);
|
||||||
|
|
||||||
#endif /* __NETWORKMANAGER_IWD_MANAGER_H__ */
|
#endif /* __NETWORKMANAGER_IWD_MANAGER_H__ */
|
||||||
|
Reference in New Issue
Block a user