static struct wmm_ac_addts_request * wmm_ac_build_addts_req(struct wpa_supplicant *wpa_s, const struct wmm_ac_ts_setup_params *params, const u8 *address) { struct wmm_ac_addts_request *addts_req; struct wmm_tspec_element *tspec; u8 ac = up_to_ac[params->user_priority]; u8 uapsd = wpa_s->wmm_ac_assoc_info->ac_params[ac].uapsd; addts_req = os_zalloc(sizeof(*addts_req)); if (!addts_req) return NULL; tspec = &addts_req->tspec; os_memcpy(addts_req->address, address, ETH_ALEN); /* The dialog token cannot be zero */ if (++wpa_s->wmm_ac_last_dialog_token == 0) wpa_s->wmm_ac_last_dialog_token++; addts_req->dialog_token = wpa_s->wmm_ac_last_dialog_token; tspec->eid = WLAN_EID_VENDOR_SPECIFIC; tspec->length = sizeof(*tspec) - 2; /* reduce eid and length */ tspec->oui[0] = 0x00; tspec->oui[1] = 0x50; tspec->oui[2] = 0xf2; tspec->oui_type = WMM_OUI_TYPE; tspec->oui_subtype = WMM_OUI_SUBTYPE_TSPEC_ELEMENT; tspec->version = WMM_VERSION; tspec->ts_info[0] = params->tsid << 1; tspec->ts_info[0] |= params->direction << 5; tspec->ts_info[0] |= WMM_AC_ACCESS_POLICY_EDCA << 7; tspec->ts_info[1] = uapsd << 2; tspec->ts_info[1] |= params->user_priority << 3; tspec->ts_info[2] = 0; tspec->nominal_msdu_size = host_to_le16(params->nominal_msdu_size); if (params->fixed_nominal_msdu) tspec->nominal_msdu_size |= host_to_le16(WMM_AC_FIXED_MSDU_SIZE); tspec->mean_data_rate = host_to_le32(params->mean_data_rate); tspec->minimum_phy_rate = host_to_le32(params->minimum_phy_rate); tspec->surplus_bandwidth_allowance = host_to_le16(params->surplus_bandwidth_allowance); return addts_req; }
int fst_test_req_send_fst_request(const char *params) { int fsts_id; Boolean is_valid; char *endp; struct fst_setup_req req; struct fst_session s; struct fst_group *g; enum hostapd_hw_mode hw_mode; u8 channel; char additional_param[FST_MAX_COMMAND_WORD_NAME_LENGTH]; if (params[0] != ' ') return -EINVAL; params++; fsts_id = fst_read_next_int_param(params, &is_valid, &endp); if (!is_valid) return -EINVAL; if (get_group_fill_session(&g, &s)) return -EINVAL; req.action = FST_ACTION_SETUP_REQUEST; req.dialog_token = g->dialog_token; req.llt = host_to_le32(FST_LLT_MS_DEFAULT); /* 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); fst_iface_get_channel_info(s.data.new_iface, &hw_mode, &channel); req.stie.new_band_id = fst_hw_mode_to_band(hw_mode); req.stie.new_band_op = 1; req.stie.new_band_setup = 0; fst_iface_get_channel_info(s.data.old_iface, &hw_mode, &channel); req.stie.old_band_id = fst_hw_mode_to_band(hw_mode); req.stie.old_band_op = 1; req.stie.old_band_setup = 0; if (!fst_read_next_text_param(endp, additional_param, sizeof(additional_param), &endp)) { if (!os_strcasecmp(additional_param, FST_CTR_PVAL_BAD_NEW_BAND)) req.stie.new_band_id = req.stie.old_band_id; } return fst_session_send_action(&s, TRUE, &req, sizeof(req), s.data.old_iface->mb_ie); }
void mwrite32(struct memfile *mf, int32_t value) { int32_t le_value = host_to_le32(value); mwrite(mf, &le_value, 4); }
static int fst_session_send_tear_down(struct fst_session *s) { struct fst_tear_down td; int res; if (!fst_session_is_in_progress(s)) { fst_printf_session(s, MSG_ERROR, "No FST setup to tear down"); return -1; } WPA_ASSERT(s->data.old_iface != NULL); WPA_ASSERT(s->data.new_iface != NULL); os_memset(&td, 0, sizeof(td)); td.action = FST_ACTION_TEAR_DOWN; td.fsts_id = host_to_le32(s->data.fsts_id); res = fst_session_send_action(s, TRUE, &td, sizeof(td), NULL); if (!res) fst_printf_sframe(s, TRUE, MSG_INFO, "FST TearDown sent"); else fst_printf_sframe(s, TRUE, MSG_ERROR, "failed to send FST TearDown"); return res; }
int fst_test_req_send_tear_down(const char *params) { int fsts_id; Boolean is_valid; char *endp; struct fst_tear_down td; struct fst_session s; struct fst_group *g; if (params[0] != ' ') return -EINVAL; params++; fsts_id = fst_read_next_int_param(params, &is_valid, &endp); if (!is_valid) return -EINVAL; if (get_group_fill_session(&g, &s)) return -EINVAL; os_memset(&td, 0, sizeof(td)); td.action = FST_ACTION_TEAR_DOWN; td.fsts_id = host_to_le32(fsts_id); return fst_session_send_action(&s, TRUE, &td, sizeof(td), NULL); }
int fst_test_req_send_ack_response(const char *params) { int fsts_id; Boolean is_valid; char *endp; struct fst_ack_res res; struct fst_session s; struct fst_group *g; if (params[0] != ' ') return -EINVAL; params++; fsts_id = fst_read_next_int_param(params, &is_valid, &endp); if (!is_valid) return -EINVAL; if (get_group_fill_session(&g, &s)) return -EINVAL; os_memset(&res, 0, sizeof(res)); res.action = FST_ACTION_ACK_RESPONSE; res.dialog_token = g->dialog_token; res.fsts_id = host_to_le32(fsts_id); return fst_session_send_action(&s, FALSE, &res, sizeof(res), NULL); }
int fst_session_initiate_switch(struct fst_session *s) { struct fst_ack_req req; int res; u8 dialog_token; if (!fst_session_is_ready(s)) { fst_printf_session(s, MSG_ERROR, "cannot initiate switch due to wrong setup state (%d)", s->state); return -1; } dialog_token = fst_group_assign_dialog_token(s->group); WPA_ASSERT(s->data.new_iface != NULL); WPA_ASSERT(s->data.old_iface != NULL); fst_printf_session(s, MSG_INFO, "initiating FST switch: %s => %s", fst_iface_get_name(s->data.old_iface), fst_iface_get_name(s->data.new_iface)); os_memset(&req, 0, sizeof(req)); req.action = FST_ACTION_ACK_REQUEST; req.dialog_token = dialog_token; req.fsts_id = host_to_le32(s->data.fsts_id); res = fst_session_send_action(s, FALSE, &req, sizeof(req), NULL); if (!res) { fst_printf_sframe(s, FALSE, MSG_INFO, "FST Ack Request sent"); fst_session_set_state(s, FST_SESSION_STATE_TRANSITION_DONE, NULL); fst_session_stt_arm(s); } else { fst_printf_sframe(s, FALSE, MSG_ERROR, "Cannot send FST Ack Request"); } return res; }
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; }
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 = host_to_le32(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_test_req_send_fst_response(const char *params) { int fsts_id; Boolean is_valid; char *endp; struct fst_setup_res res; struct fst_session s; struct fst_group *g; enum hostapd_hw_mode hw_mode; u8 status_code; u8 channel; char response[FST_MAX_COMMAND_WORD_NAME_LENGTH]; struct fst_session *_s; if (params[0] != ' ') return -EINVAL; params++; fsts_id = fst_read_next_int_param(params, &is_valid, &endp); if (!is_valid) return -EINVAL; if (get_group_fill_session(&g, &s)) return -EINVAL; status_code = WLAN_STATUS_SUCCESS; if (!fst_read_next_text_param(endp, response, sizeof(response), &endp)) { if (!os_strcasecmp(response, FST_CS_PVAL_RESPONSE_REJECT)) status_code = WLAN_STATUS_PENDING_ADMITTING_FST_SESSION; } os_memset(&res, 0, sizeof(res)); res.action = FST_ACTION_SETUP_RESPONSE; /* * If some session has just received an FST Setup Request, then * use the correct dialog token copied from this request. */ _s = fst_find_session_in_progress(fst_session_get_peer_addr(&s, TRUE), g); res.dialog_token = (_s && fst_session_is_ready_pending(_s)) ? _s->data.pending_setup_req_dlgt : g->dialog_token; res.status_code = status_code; res.stie.element_id = WLAN_EID_SESSION_TRANSITION; res.stie.length = sizeof(res.stie) - 2; if (res.status_code == WLAN_STATUS_SUCCESS) { res.stie.fsts_id = host_to_le32(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; } if (!fst_read_next_text_param(endp, response, sizeof(response), &endp)) { if (!os_strcasecmp(response, FST_CTR_PVAL_BAD_NEW_BAND)) res.stie.new_band_id = res.stie.old_band_id; } return fst_session_send_action(&s, TRUE, &res, sizeof(res), s.data.old_iface->mb_ie); }