void fst_rx_action(struct fst_iface *iface, const struct ieee80211_mgmt *mgmt, size_t len) { if (fst_iface_is_connected(iface, mgmt->sa)) fst_session_on_action_rx(iface, mgmt, len); else wpa_printf(MSG_DEBUG, "FST: Ignore FST Action frame - no FST connection with " MACSTR, MAC2STR(mgmt->sa)); }
int fst_session_respond(struct fst_session *s, u8 status_code) { struct fst_setup_res res; enum hostapd_hw_mode hw_mode; u8 channel; if (!fst_session_is_ready_pending(s)) { fst_printf_session(s, MSG_ERROR, "incorrect state: %s", fst_session_state_name(s->state)); return -EINVAL; } if (is_zero_ether_addr(s->data.old_peer_addr)) { fst_printf_session(s, MSG_ERROR, "No peer MAC address"); return -EINVAL; } if (!s->data.old_iface) { fst_printf_session(s, MSG_ERROR, "No old interface defined"); return -EINVAL; } if (!s->data.new_iface) { fst_printf_session(s, MSG_ERROR, "No new interface defined"); return -EINVAL; } if (s->data.new_iface == s->data.old_iface) { fst_printf_session(s, MSG_ERROR, "Same interface set as old and new"); return -EINVAL; } 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; } fst_session_stt_disarm(s); os_memset(&res, 0, sizeof(res)); res.action = FST_ACTION_SETUP_RESPONSE; res.dialog_token = s->data.pending_setup_req_dlgt; res.status_code = status_code; res.stie.element_id = WLAN_EID_SESSION_TRANSITION; res.stie.length = sizeof(res.stie) - 2; if (status_code == WLAN_STATUS_SUCCESS) { res.stie.fsts_id = s->data.fsts_id; res.stie.session_control = SESSION_CONTROL(SESSION_TYPE_BSS, 0); fst_iface_get_channel_info(s->data.new_iface, &hw_mode, &channel); res.stie.new_band_id = fst_hw_mode_to_band(hw_mode); res.stie.new_band_op = 1; res.stie.new_band_setup = 0; fst_iface_get_channel_info(s->data.old_iface, &hw_mode, &channel); res.stie.old_band_id = fst_hw_mode_to_band(hw_mode); res.stie.old_band_op = 1; res.stie.old_band_setup = 0; fst_printf_session(s, MSG_INFO, "%s: FST Setup Request accepted for %s (llt=%u)", fst_iface_get_name(s->data.old_iface), fst_iface_get_name(s->data.new_iface), s->data.llt_ms); } else { fst_printf_session(s, MSG_WARNING, "%s: FST Setup Request rejected with code %d", fst_iface_get_name(s->data.old_iface), status_code); } if (fst_session_send_action(s, TRUE, &res, sizeof(res), fst_iface_get_mbie(s->data.old_iface))) { fst_printf_sframe(s, TRUE, MSG_ERROR, "cannot send FST Setup Response with code %d", status_code); return -EINVAL; } fst_printf_sframe(s, TRUE, MSG_INFO, "FST Setup Response sent"); if (status_code != WLAN_STATUS_SUCCESS) { union fst_session_state_switch_extra evext = { .to_initial = { .reason = REASON_REJECT, .reject_code = status_code, .initiator = FST_INITIATOR_LOCAL, }, }; fst_session_set_state(s, FST_SESSION_STATE_INITIAL, &evext); } return 0; }
int fst_session_initiate_setup(struct fst_session *s) { struct fst_setup_req req; int res; u32 fsts_id; u8 dialog_token; struct fst_session *_s; if (fst_session_is_in_progress(s)) { fst_printf_session(s, MSG_ERROR, "Session in progress"); return -EINVAL; } if (is_zero_ether_addr(s->data.old_peer_addr)) { fst_printf_session(s, MSG_ERROR, "No old peer MAC address"); return -EINVAL; } if (is_zero_ether_addr(s->data.new_peer_addr)) { fst_printf_session(s, MSG_ERROR, "No new peer MAC address"); return -EINVAL; } if (!s->data.old_iface) { fst_printf_session(s, MSG_ERROR, "No old interface defined"); return -EINVAL; } if (!s->data.new_iface) { fst_printf_session(s, MSG_ERROR, "No new interface defined"); return -EINVAL; } if (s->data.new_iface == s->data.old_iface) { fst_printf_session(s, MSG_ERROR, "Same interface set as old and new"); return -EINVAL; } 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, FALSE)) { fst_printf_session(s, MSG_ERROR, "The preset new peer address is not connected"); return -EINVAL; } _s = fst_find_session_in_progress(s->data.old_peer_addr, s->group); if (_s) { fst_printf_session(s, MSG_ERROR, "There is another session in progress (old): %u", _s->id); return -EINVAL; } _s = fst_find_session_in_progress(s->data.new_peer_addr, s->group); if (_s) { fst_printf_session(s, MSG_ERROR, "There is another session in progress (new): %u", _s->id); return -EINVAL; } dialog_token = fst_group_assign_dialog_token(s->group); fsts_id = fst_group_assign_fsts_id(s->group); os_memset(&req, 0, sizeof(req)); fst_printf_siface(s, s->data.old_iface, MSG_INFO, "initiating FST setup for %s (llt=%u ms)", fst_iface_get_name(s->data.new_iface), s->data.llt_ms); req.action = FST_ACTION_SETUP_REQUEST; req.dialog_token = dialog_token; req.llt = host_to_le32(FST_LLT_MS_TO_VAL(s->data.llt_ms)); /* 8.4.2.147 Session Transition element */ req.stie.element_id = WLAN_EID_SESSION_TRANSITION; req.stie.length = sizeof(req.stie) - 2; req.stie.fsts_id = host_to_le32(fsts_id); req.stie.session_control = SESSION_CONTROL(SESSION_TYPE_BSS, 0); req.stie.new_band_id = fst_iface_get_band_id(s->data.new_iface); req.stie.new_band_op = 1; req.stie.new_band_setup = 0; req.stie.old_band_id = fst_iface_get_band_id(s->data.old_iface); req.stie.old_band_op = 1; req.stie.old_band_setup = 0; res = fst_session_send_action(s, TRUE, &req, sizeof(req), fst_iface_get_mbie(s->data.old_iface)); if (!res) { s->data.fsts_id = fsts_id; s->data.pending_setup_req_dlgt = dialog_token; fst_printf_sframe(s, TRUE, MSG_INFO, "FST Setup Request sent"); fst_session_set_state(s, FST_SESSION_STATE_SETUP_COMPLETION, NULL); fst_session_stt_arm(s); } return res; }