From: James Prestwood <prestwoj@gmail.com>
To: iwd@lists.linux.dev
Cc: James Prestwood <prestwoj@gmail.com>
Subject: [PATCH v3 2/4] dpp: add station watch to DPP
Date: Mon, 13 Nov 2023 09:53:59 -0800 [thread overview]
Message-ID: <20231113175401.343239-2-prestwoj@gmail.com> (raw)
In-Reply-To: <20231113175401.343239-1-prestwoj@gmail.com>
DPP (both DPP and PKEX) run the risk of odd behavior if station
decides to change state. DPP is completely unaware of this and
best case would just result in a protocol failure, worst case
duplicate calls to __station_connect_network.
Add a station watch and stop DPP if station changes state during
the protocol.
---
src/dpp.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
v3:
* Allow autoconnect states while enrolling. Its probably unlikely
that a state change would happen but going between DISCONNECTED,
AUTOCONNECT_QUICK, and AUTOCONNECT_FULL won't cause any issues
while enrolling.
diff --git a/src/dpp.c b/src/dpp.c
index 3a740916..06ae2929 100644
--- a/src/dpp.c
+++ b/src/dpp.c
@@ -100,6 +100,7 @@ struct dpp_sm {
char *uri;
uint8_t role;
int refcount;
+ uint32_t station_watch;
uint64_t wdev_id;
@@ -536,6 +537,8 @@ static void dpp_reset(struct dpp_sm *dpp)
static void dpp_free(struct dpp_sm *dpp)
{
+ struct station *station = station_find(netdev_get_ifindex(dpp->netdev));
+
dpp_reset(dpp);
if (dpp->own_asn1) {
@@ -553,6 +556,13 @@ static void dpp_free(struct dpp_sm *dpp)
dpp->boot_private = NULL;
}
+ /*
+ * Since this is called when the netdev goes down, station may already
+ * be gone in which case the state watch will automatically go away.
+ */
+ if (station)
+ station_remove_state_watch(station, dpp->station_watch);
+
l_free(dpp);
}
@@ -3608,6 +3618,67 @@ static void dpp_frame_watch(struct dpp_sm *dpp, uint16_t frame_type,
L_UINT_TO_PTR(frame_type), NULL);
}
+/*
+ * Station is unaware of DPP's state so we need to handle a few cases here so
+ * weird stuff doesn't happen:
+ *
+ * - While configuring we should stay connected, a disconnection/roam should
+ * stop DPP since it would fail regardless due to the hardware going idle
+ * or changing channels since configurators assume all comms will be
+ * on-channel.
+ * - While enrolling we should stay disconnected. If station connects during
+ * enrolling it would cause 2x calls to __station_connect_network after
+ * DPP finishes.
+ *
+ * Other conditions shouldn't ever happen i.e. configuring and going into a
+ * connecting state or enrolling and going to a disconnected/roaming state.
+ */
+static void dpp_station_state_watch(enum station_state state, void *user_data)
+{
+ struct dpp_sm *dpp = user_data;
+
+ switch (state) {
+ case STATION_STATE_DISCONNECTED:
+ case STATION_STATE_DISCONNECTING:
+ case STATION_STATE_ROAMING:
+ case STATION_STATE_FT_ROAMING:
+ case STATION_STATE_FW_ROAMING:
+ if (L_WARN_ON(dpp->role == DPP_CAPABILITY_ENROLLEE))
+ dpp_reset(dpp);
+
+ if (dpp->role == DPP_CAPABILITY_CONFIGURATOR) {
+ l_debug("Disconnected while configuring, stopping DPP");
+ dpp_reset(dpp);
+ }
+
+ break;
+ case STATION_STATE_CONNECTING:
+ case STATION_STATE_CONNECTED:
+ case STATION_STATE_CONNECTING_AUTO:
+ if (L_WARN_ON(dpp->role == DPP_CAPABILITY_CONFIGURATOR))
+ dpp_reset(dpp);
+
+ if (dpp->role == DPP_CAPABILITY_ENROLLEE) {
+ l_debug("Connecting while enrolling, stopping DPP");
+ dpp_reset(dpp);
+ }
+
+ break;
+
+ /*
+ * Autoconnect states are fine for enrollees. This makes it nicer for
+ * the user since they don't need to explicity Disconnect() to disable
+ * autoconnect, then re-enable it if DPP fails.
+ */
+ case STATION_STATE_AUTOCONNECT_FULL:
+ case STATION_STATE_AUTOCONNECT_QUICK:
+ if (L_WARN_ON(dpp->role == DPP_CAPABILITY_CONFIGURATOR))
+ dpp_reset(dpp);
+
+ break;
+ }
+}
+
static void dpp_create(struct netdev *netdev)
{
struct l_dbus *dbus = dbus_get_bus();
@@ -3615,6 +3686,7 @@ static void dpp_create(struct netdev *netdev)
uint8_t dpp_conf_response_prefix[] = { 0x04, 0x0b };
uint8_t dpp_conf_request_prefix[] = { 0x04, 0x0a };
uint64_t wdev_id = netdev_get_wdev_id(netdev);
+ struct station *station = station_find(netdev_get_ifindex(netdev));
dpp->netdev = netdev;
dpp->state = DPP_STATE_NOTHING;
@@ -3660,6 +3732,9 @@ static void dpp_create(struct netdev *netdev)
sizeof(dpp_conf_request_prefix),
dpp_handle_config_request_frame, dpp, NULL);
+ dpp->station_watch = station_add_state_watch(station,
+ dpp_station_state_watch, dpp, NULL);
+
l_queue_push_tail(dpp_list, dpp);
}
--
2.25.1
next prev parent reply other threads:[~2023-11-13 17:54 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-13 17:53 [PATCH v3 1/4] dpp: remove duplicate connected network check James Prestwood
2023-11-13 17:53 ` James Prestwood [this message]
2023-11-13 17:54 ` [PATCH v3 3/4] dpp: fix fragile scan/connecting logic James Prestwood
2023-11-16 15:18 ` Denis Kenzior
2023-11-16 15:51 ` James Prestwood
2023-11-13 17:54 ` [PATCH v3 4/4] dpp: scan to pick up extra frequencies when enrolling James Prestwood
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231113175401.343239-2-prestwoj@gmail.com \
--to=prestwoj@gmail.com \
--cc=iwd@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox