static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd, const u8 *sa, const u8 *data, size_t len) { struct gas_dialog_info *dialog; struct wpabuf *buf, *tx_buf; u8 dialog_token; size_t frag_len; int more = 0; wpa_hexdump(MSG_DEBUG, "GAS: RX GAS Comeback Request", data, len); if (len < 1) return; dialog_token = *data; wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Dialog Token: %u", dialog_token); dialog = gas_serv_dialog_find(hapd, sa, dialog_token); if (!dialog) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: No pending SD " "response fragment for " MACSTR " dialog token %u", MAC2STR(sa), dialog_token); if (sa[0] & 0x01) return; /* Invalid source address - drop silently */ tx_buf = gas_anqp_build_comeback_resp_buf( dialog_token, WLAN_STATUS_NO_OUTSTANDING_GAS_REQ, 0, 0, 0, NULL); if (tx_buf == NULL) return; goto send_resp; } if (dialog->sd_resp == NULL) { wpa_printf(MSG_DEBUG, "GAS: Remote request 0x%x received 0x%x", dialog->requested, dialog->received); if ((dialog->requested & dialog->received) != dialog->requested) { wpa_printf(MSG_DEBUG, "GAS: Did not receive response " "from remote processing"); gas_serv_dialog_clear(dialog); tx_buf = gas_anqp_build_comeback_resp_buf( dialog_token, WLAN_STATUS_GAS_RESP_NOT_RECEIVED, 0, 0, 0, NULL); if (tx_buf == NULL) return; goto send_resp; } buf = gas_serv_build_gas_resp_payload(hapd, dialog->all_requested, dialog, NULL, 0); wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Generated ANQP responses", buf); if (!buf) goto rx_gas_comeback_req_done; dialog->sd_resp = buf; dialog->sd_resp_pos = 0; } frag_len = wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos; if (frag_len > hapd->gas_frag_limit) { frag_len = hapd->gas_frag_limit; more = 1; } wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: resp frag_len %u", (unsigned int) frag_len); buf = wpabuf_alloc_copy(wpabuf_head_u8(dialog->sd_resp) + dialog->sd_resp_pos, frag_len); if (buf == NULL) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Failed to allocate " "buffer"); goto rx_gas_comeback_req_done; } tx_buf = gas_anqp_build_comeback_resp_buf(dialog_token, WLAN_STATUS_SUCCESS, dialog->sd_frag_id, more, 0, buf); wpabuf_free(buf); if (tx_buf == NULL) goto rx_gas_comeback_req_done; wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Comeback Response " "(frag_id %d more=%d frag_len=%d)", dialog->sd_frag_id, more, (int) frag_len); dialog->sd_frag_id++; dialog->sd_resp_pos += frag_len; if (more) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: %d more bytes remain " "to be sent", (int) (wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos)); } else { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: All fragments of " "SD response sent"); gas_serv_dialog_clear(dialog); gas_serv_free_dialogs(hapd, sa); } send_resp: hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, wpabuf_head(tx_buf), wpabuf_len(tx_buf)); wpabuf_free(tx_buf); return; rx_gas_comeback_req_done: gas_serv_clear_cached_ies(dialog, NULL); }
static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd, const u8 *sa, const u8 *data, size_t len, int prot, int std_addr3) { struct gas_dialog_info *dialog; struct wpabuf *buf, *tx_buf; u8 dialog_token; size_t frag_len; int more = 0; wpa_hexdump(MSG_DEBUG, "GAS: RX GAS Comeback Request", data, len); if (len < 1) return; dialog_token = *data; wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Dialog Token: %u", dialog_token); dialog = gas_serv_dialog_find(hapd, sa, dialog_token); if (!dialog) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: No pending SD " "response fragment for " MACSTR " dialog token %u", MAC2STR(sa), dialog_token); if (sa[0] & 0x01) return; /* Invalid source address - drop silently */ tx_buf = gas_anqp_build_comeback_resp_buf( dialog_token, WLAN_STATUS_NO_OUTSTANDING_GAS_REQ, 0, 0, 0, NULL); if (tx_buf == NULL) return; goto send_resp; } frag_len = wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos; if (frag_len > hapd->gas_frag_limit) { frag_len = hapd->gas_frag_limit; more = 1; } wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: resp frag_len %u", (unsigned int) frag_len); buf = wpabuf_alloc_copy(wpabuf_head_u8(dialog->sd_resp) + dialog->sd_resp_pos, frag_len); if (buf == NULL) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Failed to allocate " "buffer"); gas_serv_dialog_clear(dialog); return; } tx_buf = gas_anqp_build_comeback_resp_buf(dialog_token, WLAN_STATUS_SUCCESS, dialog->sd_frag_id, more, 0, buf); wpabuf_free(buf); if (tx_buf == NULL) { gas_serv_dialog_clear(dialog); return; } wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Comeback Response " "(frag_id %d more=%d frag_len=%d)", dialog->sd_frag_id, more, (int) frag_len); dialog->sd_frag_id++; dialog->sd_resp_pos += frag_len; if (more) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: %d more bytes remain " "to be sent", (int) (wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos)); } else { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: All fragments of " "SD response sent"); gas_serv_dialog_clear(dialog); gas_serv_free_dialogs(hapd, sa); } send_resp: if (prot) convert_to_protected_dual(tx_buf); if (std_addr3) hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, wpabuf_head(tx_buf), wpabuf_len(tx_buf)); else hostapd_drv_send_action_addr3_ap(hapd, hapd->iface->freq, 0, sa, wpabuf_head(tx_buf), wpabuf_len(tx_buf)); wpabuf_free(tx_buf); }