3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-12-22 21:22:37 +01:00

dpp: fix dpp_offchannel_start corner cases

The purpose of this was to have a single utility to both cancel an
existing offchannel operation (if one exists) and start a new one.

The problem was the previous offchannel operation was being canceled
first which opened up the radio work queue to other items. This is
not desireable as, for example, a scan would end up breaking the
DPP protocol most likely.

Starting the new offchannel then canceling is the correct order of
operations but to do this required saving the new ID, canceling, then
setting offchannel_id to the new ID so dpp_presence_timeout wouldn't
overwrite the new ID to zero.

This also removes an explicit call to offchannel_cancel which is
already done by dpp_offchannel_start.
This commit is contained in:
James Prestwood 2022-01-18 13:25:12 -08:00 committed by Denis Kenzior
parent 8ce491fbb2
commit 76b6aa66b3

View File

@ -1353,12 +1353,28 @@ protocol_failed:
static void dpp_start_offchannel(struct dpp_sm *dpp, uint32_t freq) static void dpp_start_offchannel(struct dpp_sm *dpp, uint32_t freq)
{ {
/*
* This needs to be handled carefully for a few reasons:
*
* First, the next offchannel operation needs to be started prior to
* canceling an existing one. This is so the offchannel work can
* continue uninterrupted without any other work items starting in
* between canceling and starting the next (e.g. if a scan request is
* sitting in the queue).
*
* Second, dpp_presence_timeout resets dpp->offchannel_id to zero which
* is why the new ID is saved and only set to dpp->offchannel_id once
* the previous offchannel work is cancelled (i.e. destroy() has been
* called).
*/
uint32_t id = offchannel_start(netdev_get_wdev_id(dpp->netdev),
freq, dpp->dwell, dpp_roc_started,
dpp, dpp_presence_timeout);
if (dpp->offchannel_id) if (dpp->offchannel_id)
offchannel_cancel(dpp->wdev_id, dpp->offchannel_id); offchannel_cancel(dpp->wdev_id, dpp->offchannel_id);
dpp->offchannel_id = offchannel_start(netdev_get_wdev_id(dpp->netdev), dpp->offchannel_id = id;
freq, dpp->dwell, dpp_roc_started,
dpp, dpp_presence_timeout);
} }
static void authenticate_request(struct dpp_sm *dpp, const uint8_t *from, static void authenticate_request(struct dpp_sm *dpp, const uint8_t *from,
@ -1451,7 +1467,6 @@ static void authenticate_request(struct dpp_sm *dpp, const uint8_t *from,
l_debug("Configurator requested a new frequency %u", l_debug("Configurator requested a new frequency %u",
dpp->new_freq); dpp->new_freq);
offchannel_cancel(dpp->wdev_id, dpp->offchannel_id);
dpp_start_offchannel(dpp, dpp->new_freq); dpp_start_offchannel(dpp, dpp->new_freq);
break; break;