static void gas_serv_req_local_processing(struct hostapd_data *hapd, const u8 *sa, u8 dialog_token, struct anqp_query_info *qi) { struct wpabuf *buf, *tx_buf; buf = gas_serv_build_gas_resp_payload(hapd, qi->request, NULL, qi->home_realm_query, qi->home_realm_query_len); wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Locally generated ANQP responses", buf); if (!buf) return; if (wpabuf_len(buf) > hapd->gas_frag_limit || hapd->conf->gas_comeback_delay) { struct gas_dialog_info *di; u16 comeback_delay = 1; if (hapd->conf->gas_comeback_delay) { /* Testing - allow overriding of the delay value */ comeback_delay = hapd->conf->gas_comeback_delay; } wpa_printf(MSG_DEBUG, "ANQP: Too long response to fit in " "initial response - use GAS comeback"); di = gas_dialog_create(hapd, sa, dialog_token); if (!di) { wpa_printf(MSG_INFO, "ANQP: Could not create dialog " "for " MACSTR " (dialog token %u)", MAC2STR(sa), dialog_token); wpabuf_free(buf); return; } di->sd_resp = buf; di->sd_resp_pos = 0; tx_buf = gas_anqp_build_initial_resp_buf( dialog_token, WLAN_STATUS_SUCCESS, comeback_delay, NULL); } else { wpa_printf(MSG_DEBUG, "ANQP: Initial response (no comeback)"); tx_buf = gas_anqp_build_initial_resp_buf( dialog_token, WLAN_STATUS_SUCCESS, 0, buf); wpabuf_free(buf); } if (!tx_buf) return; hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, wpabuf_head(tx_buf), wpabuf_len(tx_buf)); wpabuf_free(tx_buf); }
static void gas_serv_req_remote_processing(struct hostapd_data *hapd, const u8 *sa, u8 dialog_token, struct anqp_query_info *qi) { struct gas_dialog_info *di; struct wpabuf *tx_buf = NULL; di = gas_dialog_create(hapd, sa, dialog_token); if (!di) { wpa_msg(hapd->msg_ctx, MSG_ERROR, "GAS: Could not create dialog for " MACSTR " (dialog token %u) ", MAC2STR(sa), dialog_token); return; } di->requested = qi->remote_request; di->received = 0; di->all_requested = qi->request; /* send the request to external agent */ if (gas_serv_get_info(hapd, qi->remote_request, qi->param, qi->param_arg, sa, dialog_token) < 0) { gas_serv_dialog_clear(di); tx_buf = gas_anqp_build_initial_resp_buf( dialog_token, WLAN_STATUS_ADV_SRV_UNREACHABLE, 0, NULL); } else if (qi->remote_delay >= GAS_SERV_MIN_COMEBACK_DELAY) { di->comeback_delay = qi->remote_delay; wpa_printf(MSG_DEBUG, "GAS: Tx GAS Initial Resp (comeback = " "%d TU)", qi->remote_delay + GAS_SERV_COMEBACK_DELAY_FUDGE); tx_buf = gas_anqp_build_initial_resp_buf( dialog_token, WLAN_STATUS_SUCCESS, qi->remote_delay + GAS_SERV_COMEBACK_DELAY_FUDGE, NULL); } if (!tx_buf) return; hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, wpabuf_head(tx_buf), wpabuf_len(tx_buf)); wpabuf_free(tx_buf); }
void gas_serv_tx_gas_response(struct hostapd_data *hapd, const u8 *dst, struct gas_dialog_info *dialog) { struct wpabuf *buf, *tx_buf; u8 dialog_token = dialog->dialog_token; size_t frag_len; if (dialog->sd_resp == NULL) { 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 tx_gas_response_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 || dialog->comeback_delay || hapd->conf->gas_comeback_delay) { u16 comeback_delay_tus = dialog->comeback_delay + GAS_SERV_COMEBACK_DELAY_FUDGE; u32 comeback_delay_secs, comeback_delay_usecs; if (hapd->conf->gas_comeback_delay) { /* Testing - allow overriding of the delay value */ comeback_delay_tus = hapd->conf->gas_comeback_delay; } wpa_printf(MSG_DEBUG, "GAS: Response frag_len %u (frag limit " "%u) and comeback delay %u, " "requesting comebacks", (unsigned int) frag_len, (unsigned int) hapd->gas_frag_limit, dialog->comeback_delay); tx_buf = gas_anqp_build_initial_resp_buf(dialog_token, WLAN_STATUS_SUCCESS, comeback_delay_tus, NULL); if (tx_buf) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Initial Resp (comeback = 10TU)"); hostapd_drv_send_action(hapd, hapd->iface->freq, 0, dst, wpabuf_head(tx_buf), wpabuf_len(tx_buf)); } wpabuf_free(tx_buf); /* start a timer of 1.5 * comeback-delay */ comeback_delay_tus = comeback_delay_tus + (comeback_delay_tus / 2); comeback_delay_secs = (comeback_delay_tus * 1024) / 1000000; comeback_delay_usecs = (comeback_delay_tus * 1024) - (comeback_delay_secs * 1000000); eloop_register_timeout(comeback_delay_secs, comeback_delay_usecs, gas_serv_clear_cached_ies, dialog, NULL); goto tx_gas_response_done; } 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: Buffer allocation " "failed"); goto tx_gas_response_done; } tx_buf = gas_anqp_build_initial_resp_buf(dialog_token, WLAN_STATUS_SUCCESS, 0, buf); wpabuf_free(buf); if (tx_buf == NULL) goto tx_gas_response_done; wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Initial " "Response (frag_id %d frag_len %d)", dialog->sd_frag_id, (int) frag_len); dialog->sd_frag_id++; hostapd_drv_send_action(hapd, hapd->iface->freq, 0, dst, wpabuf_head(tx_buf), wpabuf_len(tx_buf)); wpabuf_free(tx_buf); tx_gas_response_done: gas_serv_clear_cached_ies(dialog, NULL); }
static void gas_serv_req_local_processing(struct hostapd_data *hapd, const u8 *sa, u8 dialog_token, struct anqp_query_info *qi, int prot, int std_addr3) { struct wpabuf *buf, *tx_buf; buf = gas_serv_build_gas_resp_payload(hapd, qi->request, qi->home_realm_query, qi->home_realm_query_len, qi->icon_name, qi->icon_name_len, qi->extra_req, qi->num_extra_req); wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Locally generated ANQP responses", buf); if (!buf) return; #ifdef CONFIG_P2P if (wpabuf_len(buf) == 0 && qi->p2p_sd) { wpa_printf(MSG_DEBUG, "ANQP: Do not send response to P2P SD from generic GAS service (P2P SD implementation will process this)"); wpabuf_free(buf); return; } #endif /* CONFIG_P2P */ if (wpabuf_len(buf) > hapd->gas_frag_limit || hapd->conf->gas_comeback_delay) { struct gas_dialog_info *di; u16 comeback_delay = 1; if (hapd->conf->gas_comeback_delay) { /* Testing - allow overriding of the delay value */ comeback_delay = hapd->conf->gas_comeback_delay; } wpa_printf(MSG_DEBUG, "ANQP: Too long response to fit in " "initial response - use GAS comeback"); di = gas_dialog_create(hapd, sa, dialog_token); if (!di) { wpa_printf(MSG_INFO, "ANQP: Could not create dialog " "for " MACSTR " (dialog token %u)", MAC2STR(sa), dialog_token); wpabuf_free(buf); tx_buf = gas_anqp_build_initial_resp_buf( dialog_token, WLAN_STATUS_UNSPECIFIED_FAILURE, 0, NULL); } else { di->prot = prot; di->sd_resp = buf; di->sd_resp_pos = 0; tx_buf = gas_anqp_build_initial_resp_buf( dialog_token, WLAN_STATUS_SUCCESS, comeback_delay, NULL); } } else { wpa_printf(MSG_DEBUG, "ANQP: Initial response (no comeback)"); tx_buf = gas_anqp_build_initial_resp_buf( dialog_token, WLAN_STATUS_SUCCESS, 0, buf); wpabuf_free(buf); } if (!tx_buf) return; 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); }