dpp: handle CHANNEL attribute in auth request

When this attribute is included, the initiator is requesting all
future frames be sent on this channel. There is no reason for a
configurator to act on this attribute (at least for now) so the
request frame will be dropped in this case. Enrollees will act
on it by switching to the new channel and sending the authentication
response.
This commit is contained in:
James Prestwood 2022-01-07 16:13:32 -08:00 committed by Denis Kenzior
parent 235042fcd5
commit e6ecc078a1
1 changed files with 58 additions and 19 deletions

View File

@ -91,6 +91,7 @@ struct dpp_sm {
size_t freqs_idx;
uint32_t dwell;
uint32_t current_freq;
uint32_t new_freq;
struct scan_freq_set *presence_list;
uint32_t offchannel_id;
@ -169,6 +170,7 @@ static void dpp_reset(struct dpp_sm *dpp)
}
dpp->state = DPP_STATE_NOTHING;
dpp->new_freq = 0;
explicit_bzero(dpp->r_nonce, dpp->nonce_len);
explicit_bzero(dpp->i_nonce, dpp->nonce_len);
@ -1238,14 +1240,29 @@ static void dpp_roc_started(void *user_data)
struct dpp_sm *dpp = user_data;
/*
* If not in presence procedure or in a configurator role, just stay
* on channel.
* - If a configurator, nothing to do but wait for a request
* - If in the presence state continue sending announcements.
* - If authenticating, and this is a result of a channel switch send
* the authenticate response now.
*/
if (dpp->state != DPP_STATE_PRESENCE ||
dpp->role == DPP_CAPABILITY_CONFIGURATOR)
if (dpp->role == DPP_CAPABILITY_CONFIGURATOR)
return;
dpp_presence_announce(dpp);
switch (dpp->state) {
case DPP_STATE_PRESENCE:
dpp_presence_announce(dpp);
break;
case DPP_STATE_AUTHENTICATING:
if (dpp->new_freq) {
dpp->current_freq = dpp->new_freq;
dpp->new_freq = 0;
send_authenticate_response(dpp);
}
break;
default:
break;
}
}
static void dpp_start_offchannel(struct dpp_sm *dpp, uint32_t freq);
@ -1332,6 +1349,7 @@ static void authenticate_request(struct dpp_sm *dpp, const uint8_t *from,
uint64_t k1[L_ECC_MAX_DIGITS];
const void *ad0 = body + 2;
const void *ad1 = body + 8;
uint32_t freq;
if (dpp->state != DPP_STATE_PRESENCE)
return;
@ -1371,20 +1389,39 @@ static void authenticate_request(struct dpp_sm *dpp, const uint8_t *from,
}
break;
/*
* TODO: Go on this channel for remainder of auth protocol.
*
* "the Responder determines whether it can use the requested
* channel for the following exchanges. If so, it sends the DPP
* Authentication Response frame on that channel. If not, it
* discards the DPP Authentication Request frame without
* replying to it."
*
* For the time being this feature is not being implemented and
* the frame will be dropped.
*/
case DPP_ATTR_CHANNEL:
return;
if (len != 2)
return;
freq = oci_to_frequency(l_get_u8(data),
l_get_u8(data + 1));
if (freq == dpp->current_freq)
break;
/*
* Configurators are already connected to a network, so
* to preserve wireless performance the enrollee will
* be required to be on this channel, not a channel it
* requests.
*/
if (dpp->role == DPP_CAPABILITY_CONFIGURATOR)
return;
/*
* Otherwise, as an enrollee, we can jump to whatever
* channel the configurator requests
*/
dpp->new_freq = freq;
l_debug("Configurator requested a new frequency %u",
dpp->new_freq);
offchannel_cancel(dpp->wdev_id, dpp->offchannel_id);
dpp_start_offchannel(dpp, dpp->new_freq);
break;
default:
break;
}
@ -1478,7 +1515,9 @@ static void authenticate_request(struct dpp_sm *dpp, const uint8_t *from,
dpp->state = DPP_STATE_AUTHENTICATING;
dpp_reset_protocol_timer(dpp);
send_authenticate_response(dpp);
/* Don't send if the frequency is changing */
if (!dpp->new_freq)
send_authenticate_response(dpp);
return;