* [PATCH] iwd: Always disconnect connection completely
[not found] <20220119133927.1245607-1-Emmanuel.VAUTRIN@cpexterne.org>
@ 2022-01-19 13:43 ` VAUTRIN Emmanuel (Canal Plus Prestataire)
2022-01-21 7:47 ` Daniel Wagner
0 siblings, 1 reply; 6+ messages in thread
From: VAUTRIN Emmanuel (Canal Plus Prestataire) @ 2022-01-19 13:43 UTC (permalink / raw)
To: connman
[-- Attachment #1: Type: text/plain, Size: 6584 bytes --]
Before being able to connect to a new network, finish disconnecting
the old connection. The network can change while the
cm_network_disconnect_cb is scheduled.
Commit 024309a9e04a ("wifi: Reset disconnecting status of any network")
Commit 795883e98eba ("wifi: Check valid network in disconnect callback")
Commit dd86f09107e8 ("wifi: Always disconnect connection completely")
---
plugins/iwd.c | 114 ++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 102 insertions(+), 12 deletions(-)
diff --git a/plugins/iwd.c b/plugins/iwd.c
index b0e17a4d6396..48f1f7136e24 100644
--- a/plugins/iwd.c
+++ b/plugins/iwd.c
@@ -82,6 +82,10 @@ struct iwd_device {
char *mode;
struct connman_device *device;
+
+ char *network;
+ char *pending_network;
+ bool disconnecting;
};
struct iwd_network {
@@ -219,12 +223,6 @@ static void update_network_connected(struct iwd_network *iwdn)
connman_network_set_connected(iwdn->network, true);
}
-static void update_network_disconnected(struct iwd_network *iwdn)
-{
- DBG("interface name %s", iwdn->name);
- connman_network_set_connected(iwdn->network, false);
-}
-
static void cm_network_connect_cb(DBusMessage *message, void *user_data)
{
const char *path = user_data;
@@ -253,21 +251,93 @@ static void cm_network_connect_cb(DBusMessage *message, void *user_data)
update_network_connected(iwdn);
}
+void abort_pending_network(struct iwd_device *iwdd,
+ enum connman_network_error error) {
+ struct iwd_network *iwdn;
+
+ if (!iwdd->pending_network)
+ return;
+
+ iwdn = g_hash_table_lookup(networks, iwdd->pending_network);
+ if (iwdn)
+ connman_network_set_error(iwdn->network, error);
+
+ g_free(iwdd->pending_network);
+ iwdd->pending_network = NULL;
+}
+
static int cm_network_connect(struct connman_network *network)
{
struct iwd_network *iwdn = connman_network_get_data(network);
+ struct iwd_device *iwdd;
+ int err;
- if (!iwdn)
+ if (!iwdn || !iwdn->iwdd)
return -EINVAL;
+ iwdd = iwdn->iwdd;
+ if (iwdd->disconnecting) {
+ if (g_strcmp0(iwdn->path, iwdd->pending_network)) {
+ abort_pending_network(iwdd,
+ CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
+ iwdd->pending_network = g_strdup(iwdn->path);
+ }
+ return -EINPROGRESS;
+ }
+
if (!g_dbus_proxy_method_call(iwdn->proxy, "Connect",
NULL, cm_network_connect_cb,
- g_strdup(iwdn->path), g_free))
- return -EIO;
+ g_strdup(iwdn->path), g_free)) {
+ err = -EIO;
+ goto out;
+ }
connman_network_set_associating(iwdn->network, true);
- return -EINPROGRESS;
+ g_free(iwdd->network);
+ iwdd->network = g_strdup(iwdn->path);
+
+ err = -EINPROGRESS;
+
+out:
+ abort_pending_network(iwdd, CONNMAN_NETWORK_ERROR_UNKNOWN);
+ return err;
+}
+
+static void update_network_disconnected(struct iwd_network *iwdn)
+{
+ struct iwd_device *iwdd;
+
+ if (!iwdn || !iwdn->iwdd)
+ return;
+
+ iwdd = iwdn->iwdd;
+
+ DBG("interface name %s", iwdn->name);
+ connman_network_set_connected(iwdn->network, false);
+
+ iwdd->disconnecting = false;
+
+ if (g_strcmp0(iwdn->path, iwdd->network)) {
+ if (!g_strcmp0(iwdn->path, iwdd->pending_network)) {
+ abort_pending_network(iwdd,
+ CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
+ }
+ DBG("current wifi network has changed since disconnection");
+ return;
+ }
+
+ g_free(iwdd->network);
+ iwdd->network = NULL;
+
+ if (iwdd->pending_network) {
+ struct iwd_network *iwdn_pending =
+ g_hash_table_lookup(networks, iwdd->pending_network);
+ if (!iwdn_pending)
+ return;
+
+ cm_network_connect(iwdn_pending->network);
+ }
}
static void cm_network_disconnect_cb(DBusMessage *message, void *user_data)
@@ -279,6 +349,9 @@ static void cm_network_disconnect_cb(DBusMessage *message, void *user_data)
if (!iwdn)
return;
+ if(iwdn->iwdd)
+ iwdn->iwdd->disconnecting = false;
+
if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR) {
const char *dbus_error = dbus_message_get_error_name(message);
@@ -303,11 +376,16 @@ static int cm_network_disconnect(struct connman_network *network)
{
struct iwd_network *iwdn = connman_network_get_data(network);
struct iwd_station *iwds;
+ struct iwd_device *iwdd;
- if (!iwdn && !iwdn->iwdd)
+ if (!iwdn || !iwdn->iwdd)
return -EINVAL;
- iwds = g_hash_table_lookup(stations, iwdn->iwdd->path);
+ iwdd = iwdn->iwdd;
+ if (iwdd->disconnecting)
+ return -EALREADY;
+
+ iwds = g_hash_table_lookup(stations, iwdd->path);
if (!iwds)
return -EIO;
@@ -317,6 +395,8 @@ static int cm_network_disconnect(struct connman_network *network)
NULL, cm_network_disconnect_cb, g_strdup(iwdn->path), g_free))
return -EIO;
+ iwdd->disconnecting = true;
+
return 0;
}
@@ -515,6 +595,12 @@ static void device_powered_cb(const DBusError *error, void *user_data)
}
connman_device_set_powered(iwdd->device, cbd->powered);
+
+ if(!cbd->powered) {
+ abort_pending_network(iwdd,
+ CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
+ iwdd->disconnecting = false;
+ }
out:
g_free(cbd->path);
g_free(cbd);
@@ -1307,6 +1393,10 @@ static void device_free(gpointer data)
g_free(iwdd->adapter);
g_free(iwdd->name);
g_free(iwdd->address);
+
+ g_free(iwdd->network);
+ g_free(iwdd->pending_network);
+
g_free(iwdd);
}
--
2.25.1
Hi,
Please find the right formatted patch in attachment.
Emmanuel
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-iwd-Always-disconnect-connection-completely.patch --]
[-- Type: text/x-patch; name="0001-iwd-Always-disconnect-connection-completely.patch", Size: 5426 bytes --]
From c3d36262db113abb9967f2998f7ba0f7f9d46851 Mon Sep 17 00:00:00 2001
From: Emmanuel VAUTRIN <Emmanuel.VAUTRIN@cpexterne.org>
Date: Wed, 19 Jan 2022 10:38:07 +0100
Subject: [PATCH] iwd: Always disconnect connection completely
Before being able to connect to a new network, finish disconnecting
the old connection. The network can change while the
cm_network_disconnect_cb is scheduled.
Commit 024309a9e04a ("wifi: Reset disconnecting status of any network")
Commit 795883e98eba ("wifi: Check valid network in disconnect callback")
Commit dd86f09107e8 ("wifi: Always disconnect connection completely")
---
plugins/iwd.c | 114 ++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 102 insertions(+), 12 deletions(-)
diff --git a/plugins/iwd.c b/plugins/iwd.c
index b0e17a4d6396..48f1f7136e24 100644
--- a/plugins/iwd.c
+++ b/plugins/iwd.c
@@ -82,6 +82,10 @@ struct iwd_device {
char *mode;
struct connman_device *device;
+
+ char *network;
+ char *pending_network;
+ bool disconnecting;
};
struct iwd_network {
@@ -219,12 +223,6 @@ static void update_network_connected(struct iwd_network *iwdn)
connman_network_set_connected(iwdn->network, true);
}
-static void update_network_disconnected(struct iwd_network *iwdn)
-{
- DBG("interface name %s", iwdn->name);
- connman_network_set_connected(iwdn->network, false);
-}
-
static void cm_network_connect_cb(DBusMessage *message, void *user_data)
{
const char *path = user_data;
@@ -253,21 +251,93 @@ static void cm_network_connect_cb(DBusMessage *message, void *user_data)
update_network_connected(iwdn);
}
+void abort_pending_network(struct iwd_device *iwdd,
+ enum connman_network_error error) {
+ struct iwd_network *iwdn;
+
+ if (!iwdd->pending_network)
+ return;
+
+ iwdn = g_hash_table_lookup(networks, iwdd->pending_network);
+ if (iwdn)
+ connman_network_set_error(iwdn->network, error);
+
+ g_free(iwdd->pending_network);
+ iwdd->pending_network = NULL;
+}
+
static int cm_network_connect(struct connman_network *network)
{
struct iwd_network *iwdn = connman_network_get_data(network);
+ struct iwd_device *iwdd;
+ int err;
- if (!iwdn)
+ if (!iwdn || !iwdn->iwdd)
return -EINVAL;
+ iwdd = iwdn->iwdd;
+ if (iwdd->disconnecting) {
+ if (g_strcmp0(iwdn->path, iwdd->pending_network)) {
+ abort_pending_network(iwdd,
+ CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
+ iwdd->pending_network = g_strdup(iwdn->path);
+ }
+ return -EINPROGRESS;
+ }
+
if (!g_dbus_proxy_method_call(iwdn->proxy, "Connect",
NULL, cm_network_connect_cb,
- g_strdup(iwdn->path), g_free))
- return -EIO;
+ g_strdup(iwdn->path), g_free)) {
+ err = -EIO;
+ goto out;
+ }
connman_network_set_associating(iwdn->network, true);
- return -EINPROGRESS;
+ g_free(iwdd->network);
+ iwdd->network = g_strdup(iwdn->path);
+
+ err = -EINPROGRESS;
+
+out:
+ abort_pending_network(iwdd, CONNMAN_NETWORK_ERROR_UNKNOWN);
+ return err;
+}
+
+static void update_network_disconnected(struct iwd_network *iwdn)
+{
+ struct iwd_device *iwdd;
+
+ if (!iwdn || !iwdn->iwdd)
+ return;
+
+ iwdd = iwdn->iwdd;
+
+ DBG("interface name %s", iwdn->name);
+ connman_network_set_connected(iwdn->network, false);
+
+ iwdd->disconnecting = false;
+
+ if (g_strcmp0(iwdn->path, iwdd->network)) {
+ if (!g_strcmp0(iwdn->path, iwdd->pending_network)) {
+ abort_pending_network(iwdd,
+ CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
+ }
+ DBG("current wifi network has changed since disconnection");
+ return;
+ }
+
+ g_free(iwdd->network);
+ iwdd->network = NULL;
+
+ if (iwdd->pending_network) {
+ struct iwd_network *iwdn_pending =
+ g_hash_table_lookup(networks, iwdd->pending_network);
+ if (!iwdn_pending)
+ return;
+
+ cm_network_connect(iwdn_pending->network);
+ }
}
static void cm_network_disconnect_cb(DBusMessage *message, void *user_data)
@@ -279,6 +349,9 @@ static void cm_network_disconnect_cb(DBusMessage *message, void *user_data)
if (!iwdn)
return;
+ if(iwdn->iwdd)
+ iwdn->iwdd->disconnecting = false;
+
if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR) {
const char *dbus_error = dbus_message_get_error_name(message);
@@ -303,11 +376,16 @@ static int cm_network_disconnect(struct connman_network *network)
{
struct iwd_network *iwdn = connman_network_get_data(network);
struct iwd_station *iwds;
+ struct iwd_device *iwdd;
- if (!iwdn && !iwdn->iwdd)
+ if (!iwdn || !iwdn->iwdd)
return -EINVAL;
- iwds = g_hash_table_lookup(stations, iwdn->iwdd->path);
+ iwdd = iwdn->iwdd;
+ if (iwdd->disconnecting)
+ return -EALREADY;
+
+ iwds = g_hash_table_lookup(stations, iwdd->path);
if (!iwds)
return -EIO;
@@ -317,6 +395,8 @@ static int cm_network_disconnect(struct connman_network *network)
NULL, cm_network_disconnect_cb, g_strdup(iwdn->path), g_free))
return -EIO;
+ iwdd->disconnecting = true;
+
return 0;
}
@@ -515,6 +595,12 @@ static void device_powered_cb(const DBusError *error, void *user_data)
}
connman_device_set_powered(iwdd->device, cbd->powered);
+
+ if(!cbd->powered) {
+ abort_pending_network(iwdd,
+ CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
+ iwdd->disconnecting = false;
+ }
out:
g_free(cbd->path);
g_free(cbd);
@@ -1307,6 +1393,10 @@ static void device_free(gpointer data)
g_free(iwdd->adapter);
g_free(iwdd->name);
g_free(iwdd->address);
+
+ g_free(iwdd->network);
+ g_free(iwdd->pending_network);
+
g_free(iwdd);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread