plen = frame_len - IEEE80211_HDRLEN - 1;
req = (const struct fst_setup_req *)
(((const u8 *) mgmt) + IEEE80211_HDRLEN + 1);
+ if (req->stie.element_id != WLAN_EID_SESSION_TRANSITION ||
+ req->stie.length < 11) {
+ fst_printf_iface(iface, MSG_WARNING,
+ "FST Request dropped: invalid STIE");
+ return;
+ }
if (req->stie.new_band_id == req->stie.old_band_id) {
fst_printf_iface(iface, MSG_WARNING,
* the initiator’s MAC address, in which case, the responder
* shall delete the received FST Setup Request.
*/
- if (os_memcmp(mgmt->da, mgmt->sa, ETH_ALEN) > 0) {
+ if (fst_session_is_ready_pending(s) &&
+ /* waiting for Setup Response */
+ os_memcmp(mgmt->da, mgmt->sa, ETH_ALEN) > 0) {
fst_printf_session(s, MSG_WARNING,
"FST Request dropped due to MAC comparison (our MAC is "
MACSTR ")",
return;
}
- if (!fst_session_is_ready_pending(s)) {
- fst_printf_session(s, MSG_WARNING,
- "FST Request from " MACSTR
- " dropped due to inappropriate state %s",
- MAC2STR(mgmt->da),
- fst_session_state_name(s->state));
- return;
- }
+ /*
+ * State is SETUP_COMPLETION (either in transition or not) or
+ * TRANSITION_DONE (in transition).
+ * Setup Request arriving in this state could mean:
+ * 1. peer sent it before receiving our Setup Request (race
+ * condition)
+ * 2. peer didn't receive our Setup Response. Peer is retrying
+ * after STT timeout
+ * 3. peer's FST state machines are out of sync due to some
+ * other reason
+ *
+ * We will reset our session and create a new one instead.
+ */
+ fst_printf_session(s, MSG_WARNING,
+ "resetting due to FST request");
/*
* If FST Setup Request arrived with the same FSTS ID as one we
- * initialized before, it means the other side either didn't
- * receive our FST Request or skipped it for some reason (for
- * example, due to numerical MAC comparison).
- *
- * In this case, there's no need to tear down the session.
+ * initialized before, there's no need to tear down the session.
* Moreover, as FSTS ID is the same, the other side will
* associate this tear down with the session it initiated that
* will break the sync.
"Skipping TearDown as the FST request has the same FSTS ID as initiated");
fst_session_set_state(s, FST_SESSION_STATE_INITIAL, &evext);
fst_session_stt_disarm(s);
- fst_printf_session(s, MSG_WARNING, "reset due to FST request");
}
s = fst_session_create(g);
}
res = (const struct fst_setup_res *)
(((const u8 *) mgmt) + IEEE80211_HDRLEN + 1);
+ if (res->stie.element_id != WLAN_EID_SESSION_TRANSITION ||
+ res->stie.length < 11) {
+ fst_printf_iface(iface, MSG_WARNING,
+ "FST Response dropped: invalid STIE");
+ return;
+ }
if (res->dialog_token != s->data.pending_setup_req_dlgt) {
fst_printf_session(s, MSG_WARNING,
return -EINVAL;
}
- if (!fst_iface_is_connected(s->data.old_iface, s->data.old_peer_addr)) {
+ if (!fst_iface_is_connected(s->data.old_iface, s->data.old_peer_addr,
+ FALSE)) {
fst_printf_session(s, MSG_ERROR,
"The preset old peer address is not connected");
return -EINVAL;
}
- if (!fst_iface_is_connected(s->data.new_iface, s->data.new_peer_addr)) {
+ if (!fst_iface_is_connected(s->data.new_iface, s->data.new_peer_addr,
+ FALSE)) {
fst_printf_session(s, MSG_ERROR,
"The preset new peer address is not connected");
return -EINVAL;
return -EINVAL;
}
- if (!fst_iface_is_connected(s->data.old_iface, s->data.old_peer_addr)) {
+ if (!fst_iface_is_connected(s->data.old_iface,
+ s->data.old_peer_addr, FALSE)) {
fst_printf_session(s, MSG_ERROR,
"The preset peer address is not in the peer list");
return -EINVAL;
struct fst_get_peer_ctx *ctx;
os_memset(s, 0, sizeof(*s));
- *g = dl_list_first(&fst_global_groups_list,
- struct fst_group, global_groups_lentry);
- if (!*g)
- return -EINVAL;
-
- s->data.new_iface = dl_list_first(&(*g)->ifaces, struct fst_iface,
- group_lentry);
+ foreach_fst_group(*g) {
+ s->data.new_iface = fst_group_first_iface(*g);
+ if (s->data.new_iface)
+ break;
+ }
if (!s->data.new_iface)
return -EINVAL;