104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt/* 204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Generic advertisement service (GAS) server 31846323989242844f0e857458a8939fa5836429cDmitry Shmidt * Copyright (c) 2011-2014, Qualcomm Atheros, Inc. 404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * 504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * This software may be distributed under the terms of the BSD license. 604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * See README for more details. 704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "includes.h" 1004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 1104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "common.h" 1204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "common/ieee802_11_defs.h" 1304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "common/gas.h" 1404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "utils/eloop.h" 1504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "hostapd.h" 1604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "ap_config.h" 1704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "ap_drv_ops.h" 1804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "sta_info.h" 1904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "gas_serv.h" 2004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 221846323989242844f0e857458a8939fa5836429cDmitry Shmidtstatic void convert_to_protected_dual(struct wpabuf *msg) 231846323989242844f0e857458a8939fa5836429cDmitry Shmidt{ 241846323989242844f0e857458a8939fa5836429cDmitry Shmidt u8 *categ = wpabuf_mhead_u8(msg); 251846323989242844f0e857458a8939fa5836429cDmitry Shmidt *categ = WLAN_ACTION_PROTECTED_DUAL; 261846323989242844f0e857458a8939fa5836429cDmitry Shmidt} 271846323989242844f0e857458a8939fa5836429cDmitry Shmidt 281846323989242844f0e857458a8939fa5836429cDmitry Shmidt 2904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic struct gas_dialog_info * 3004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtgas_dialog_create(struct hostapd_data *hapd, const u8 *addr, u8 dialog_token) 3104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 3204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct sta_info *sta; 3304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct gas_dialog_info *dia = NULL; 3404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int i, j; 3504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 3604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sta = ap_get_sta(hapd, addr); 3704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!sta) { 3804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 3904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * We need a STA entry to be able to maintain state for 4004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * the GAS query. 4104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 4204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Add a temporary STA entry for " 4304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "GAS query"); 4404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sta = ap_sta_add(hapd, addr); 4504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!sta) { 4604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to add STA " MACSTR 4704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt " for GAS query", MAC2STR(addr)); 4804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 4904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 5004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sta->flags |= WLAN_STA_GAS; 5104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 5204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * The default inactivity is 300 seconds. We don't need 5304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * it to be that long. 5404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 5504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ap_sta_session_timeout(hapd, sta, 5); 565460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } else { 575460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ap_sta_replenish_timeout(hapd, sta, 5); 5804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 5904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 6004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sta->gas_dialog == NULL) { 6104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sta->gas_dialog = os_zalloc(GAS_DIALOG_MAX * 6204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sizeof(struct gas_dialog_info)); 6304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sta->gas_dialog == NULL) 6404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 6504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 6604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 6704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = sta->gas_dialog_next, j = 0; j < GAS_DIALOG_MAX; i++, j++) { 6804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (i == GAS_DIALOG_MAX) 6904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt i = 0; 7004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sta->gas_dialog[i].valid) 7104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 7204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dia = &sta->gas_dialog[i]; 7304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dia->valid = 1; 7404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dia->dialog_token = dialog_token; 7504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sta->gas_dialog_next = (++i == GAS_DIALOG_MAX) ? 0 : i; 7604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return dia; 7704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 7804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 7904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(hapd->msg_ctx, MSG_ERROR, "ANQP: Could not create dialog for " 8004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt MACSTR " dialog_token %u. Consider increasing " 8104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "GAS_DIALOG_MAX.", MAC2STR(addr), dialog_token); 8204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 8304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 8404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 8504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 8604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 8704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstruct gas_dialog_info * 8804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtgas_serv_dialog_find(struct hostapd_data *hapd, const u8 *addr, 8904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 dialog_token) 9004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 9104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct sta_info *sta; 9204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int i; 9304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 9404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sta = ap_get_sta(hapd, addr); 9504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!sta) { 9604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: could not find STA " MACSTR, 9704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt MAC2STR(addr)); 9804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 9904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 10004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; sta->gas_dialog && i < GAS_DIALOG_MAX; i++) { 10104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sta->gas_dialog[i].dialog_token != dialog_token || 10204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt !sta->gas_dialog[i].valid) 10304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 10404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return &sta->gas_dialog[i]; 10504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 10604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Could not find dialog for " 10704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt MACSTR " dialog_token %u", MAC2STR(addr), dialog_token); 10804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 10904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 11004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 11104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 11204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid gas_serv_dialog_clear(struct gas_dialog_info *dia) 11304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 11404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(dia->sd_resp); 11504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memset(dia, 0, sizeof(*dia)); 11604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 11704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 11804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 11904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void gas_serv_free_dialogs(struct hostapd_data *hapd, 12004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *sta_addr) 12104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 12204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct sta_info *sta; 12304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int i; 12404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 12504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sta = ap_get_sta(hapd, sta_addr); 12604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sta == NULL || sta->gas_dialog == NULL) 12704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 12804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 12904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < GAS_DIALOG_MAX; i++) { 13004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sta->gas_dialog[i].valid) 13104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 13204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 13304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 13404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_free(sta->gas_dialog); 13504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sta->gas_dialog = NULL; 13604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 13704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 13804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 139aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt#ifdef CONFIG_HS20 14061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void anqp_add_hs_capab_list(struct hostapd_data *hapd, 14161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *buf) 14261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 14361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *len; 14461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 14561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); 14661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_be24(buf, OUI_WFA); 14761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); 14861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST); 14961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, 0); /* Reserved */ 15061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST); 15161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->hs20_oper_friendly_name) 15261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME); 15361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->hs20_wan_metrics) 15461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS); 15561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->hs20_connection_capability) 15661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY); 15761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->nai_realm_data) 15861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY); 15961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->hs20_operating_class) 16061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS); 161f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (hapd->conf->hs20_osu_providers_count) 162f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_LIST); 163f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (hapd->conf->hs20_icons_count) 164f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_ICON_REQUEST); 16561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gas_anqp_set_element_len(buf, len); 16661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 167aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt#endif /* CONFIG_HS20 */ 16861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 16961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 17004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void anqp_add_capab_list(struct hostapd_data *hapd, 17104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *buf) 17204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 17304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 *len; 17404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 17504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len = gas_anqp_add_element(buf, ANQP_CAPABILITY_LIST); 17604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_le16(buf, ANQP_CAPABILITY_LIST); 17704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (hapd->conf->venue_name) 17804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_le16(buf, ANQP_VENUE_NAME); 17961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->network_auth_type) 18061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE); 18104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (hapd->conf->roaming_consortium) 18204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_le16(buf, ANQP_ROAMING_CONSORTIUM); 18361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->ipaddr_type_configured) 18461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY); 18561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->nai_realm_data) 18661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, ANQP_NAI_REALM); 18761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->anqp_3gpp_cell_net) 18861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK); 18961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->domain_name) 19061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, ANQP_DOMAIN_NAME); 191aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt#ifdef CONFIG_HS20 19261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_hs_capab_list(hapd, buf); 193aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt#endif /* CONFIG_HS20 */ 19404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt gas_anqp_set_element_len(buf, len); 19504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 19604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 19704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 19804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void anqp_add_venue_name(struct hostapd_data *hapd, struct wpabuf *buf) 19904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 20004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (hapd->conf->venue_name) { 20104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 *len; 20204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt unsigned int i; 20304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len = gas_anqp_add_element(buf, ANQP_VENUE_NAME); 20404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(buf, hapd->conf->venue_group); 20504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(buf, hapd->conf->venue_type); 20604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < hapd->conf->venue_name_count; i++) { 20761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct hostapd_lang_string *vn; 20804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt vn = &hapd->conf->venue_name[i]; 20904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(buf, 3 + vn->name_len); 21004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_data(buf, vn->lang, 3); 21104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_data(buf, vn->name, vn->name_len); 21204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 21304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt gas_anqp_set_element_len(buf, len); 21404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 21504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 21604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 21704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 21861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void anqp_add_network_auth_type(struct hostapd_data *hapd, 21961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *buf) 22061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 22161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->network_auth_type) { 22261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE); 22361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, hapd->conf->network_auth_type_len); 22461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, hapd->conf->network_auth_type, 22561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hapd->conf->network_auth_type_len); 22661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 22761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 22861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 22961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 23004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void anqp_add_roaming_consortium(struct hostapd_data *hapd, 23104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *buf) 23204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 23304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt unsigned int i; 23404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 *len; 23504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 23604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len = gas_anqp_add_element(buf, ANQP_ROAMING_CONSORTIUM); 23704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < hapd->conf->roaming_consortium_count; i++) { 23804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct hostapd_roaming_consortium *rc; 23904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt rc = &hapd->conf->roaming_consortium[i]; 24004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(buf, rc->len); 24104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_data(buf, rc->oi, rc->len); 24204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 24304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt gas_anqp_set_element_len(buf, len); 24404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 24504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 24604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 24761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void anqp_add_ip_addr_type_availability(struct hostapd_data *hapd, 24861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *buf) 24961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 25061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->ipaddr_type_configured) { 25161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY); 25261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, 1); 25361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, hapd->conf->ipaddr_type_availability); 25461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 25561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 25661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 25761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 25861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void anqp_add_nai_realm_eap(struct wpabuf *buf, 25961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct hostapd_nai_realm_data *realm) 26061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 26161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt unsigned int i, j; 26261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 26361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, realm->eap_method_count); 26461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 26561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (i = 0; i < realm->eap_method_count; i++) { 26661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct hostapd_nai_realm_eap *eap = &realm->eap_method[i]; 26761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, 2 + (3 * eap->num_auths)); 26861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, eap->eap_method); 26961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, eap->num_auths); 27061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (j = 0; j < eap->num_auths; j++) { 27161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, eap->auth_id[j]); 27261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, 1); 27361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, eap->auth_val[j]); 27461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 27561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 27661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 27761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 27861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 27961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void anqp_add_nai_realm_data(struct wpabuf *buf, 28061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct hostapd_nai_realm_data *realm, 28161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt unsigned int realm_idx) 28261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 28361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *realm_data_len; 28461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 28561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "realm=%s, len=%d", realm->realm[realm_idx], 28661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt (int) os_strlen(realm->realm[realm_idx])); 28761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm_data_len = wpabuf_put(buf, 2); 28861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, realm->encoding); 28961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, os_strlen(realm->realm[realm_idx])); 29061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_str(buf, realm->realm[realm_idx]); 29161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_nai_realm_eap(buf, realm); 29261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gas_anqp_set_element_len(buf, realm_data_len); 29361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 29461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 29561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 29661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int hs20_add_nai_home_realm_matches(struct hostapd_data *hapd, 29761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *buf, 29861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *home_realm, 29961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t home_realm_len) 30061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 30161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt unsigned int i, j, k; 30261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 num_realms, num_matching = 0, encoding, realm_len, *realm_list_len; 30361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct hostapd_nai_realm_data *realm; 30461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *pos, *realm_name, *end; 30561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct { 30661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt unsigned int realm_data_idx; 30761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt unsigned int realm_idx; 30861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } matches[10]; 30961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 31061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = home_realm; 31161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt end = pos + home_realm_len; 31261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos + 1 > end) { 31361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "Too short NAI Home Realm Query", 31461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt home_realm, home_realm_len); 31561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 31661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 31761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt num_realms = *pos++; 31861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 31961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (i = 0; i < num_realms && num_matching < 10; i++) { 32061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos + 2 > end) { 32161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 32261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "Truncated NAI Home Realm Query", 32361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt home_realm, home_realm_len); 32461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 32561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 32661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt encoding = *pos++; 32761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm_len = *pos++; 32861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos + realm_len > end) { 32961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 33061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "Truncated NAI Home Realm Query", 33161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt home_realm, home_realm_len); 33261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 33361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 33461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm_name = pos; 33561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (j = 0; j < hapd->conf->nai_realm_count && 33661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt num_matching < 10; j++) { 33761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *rpos, *rend; 33861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm = &hapd->conf->nai_realm_data[j]; 33961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (encoding != realm->encoding) 34061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt continue; 34161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 34261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt rpos = realm_name; 34361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt while (rpos < realm_name + realm_len && 34461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt num_matching < 10) { 34561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (rend = rpos; 34661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt rend < realm_name + realm_len; rend++) { 34761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (*rend == ';') 34861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 34961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 35061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (k = 0; k < MAX_NAI_REALMS && 35161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm->realm[k] && 35261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt num_matching < 10; k++) { 35361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if ((int) os_strlen(realm->realm[k]) != 35461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt rend - rpos || 35561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_strncmp((char *) rpos, 35661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm->realm[k], 35761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt rend - rpos) != 0) 35861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt continue; 35961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt matches[num_matching].realm_data_idx = 36061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt j; 36161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt matches[num_matching].realm_idx = k; 36261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt num_matching++; 36361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 36461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt rpos = rend + 1; 36561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 36661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 36761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += realm_len; 36861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 36961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 37061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm_list_len = gas_anqp_add_element(buf, ANQP_NAI_REALM); 37161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, num_matching); 37261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 37361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 37461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * There are two ways to format. 1. each realm in a NAI Realm Data unit 37561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * 2. all realms that share the same EAP methods in a NAI Realm Data 37661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * unit. The first format is likely to be bigger in size than the 37761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * second, but may be easier to parse and process by the receiver. 37861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 37961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (i = 0; i < num_matching; i++) { 38061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "realm_idx %d, realm_data_idx %d", 38161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt matches[i].realm_data_idx, matches[i].realm_idx); 38261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm = &hapd->conf->nai_realm_data[matches[i].realm_data_idx]; 38361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_nai_realm_data(buf, realm, matches[i].realm_idx); 38461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 38561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gas_anqp_set_element_len(buf, realm_list_len); 38661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 38761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 38861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 38961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 39061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void anqp_add_nai_realm(struct hostapd_data *hapd, struct wpabuf *buf, 39161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *home_realm, size_t home_realm_len, 39261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int nai_realm, int nai_home_realm) 39361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 39461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (nai_realm && hapd->conf->nai_realm_data) { 39561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *len; 39661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt unsigned int i, j; 39761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len = gas_anqp_add_element(buf, ANQP_NAI_REALM); 39861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, hapd->conf->nai_realm_count); 39961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (i = 0; i < hapd->conf->nai_realm_count; i++) { 40061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *realm_data_len, *realm_len; 40161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct hostapd_nai_realm_data *realm; 40261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 40361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm = &hapd->conf->nai_realm_data[i]; 40461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm_data_len = wpabuf_put(buf, 2); 40561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, realm->encoding); 40661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm_len = wpabuf_put(buf, 1); 40761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (j = 0; realm->realm[j]; j++) { 40861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (j > 0) 40961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, ';'); 41061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_str(buf, realm->realm[j]); 41161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 41261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *realm_len = (u8 *) wpabuf_put(buf, 0) - realm_len - 1; 41361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_nai_realm_eap(buf, realm); 41461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gas_anqp_set_element_len(buf, realm_data_len); 41561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 41661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gas_anqp_set_element_len(buf, len); 41709f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt } else if (nai_home_realm && hapd->conf->nai_realm_data && home_realm) { 41861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hs20_add_nai_home_realm_matches(hapd, buf, home_realm, 41961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt home_realm_len); 42061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 42161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 42261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 42361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 42461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void anqp_add_3gpp_cellular_network(struct hostapd_data *hapd, 42561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *buf) 42661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 42761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->anqp_3gpp_cell_net) { 42861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK); 42961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, 43061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hapd->conf->anqp_3gpp_cell_net_len); 43161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, hapd->conf->anqp_3gpp_cell_net, 43261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hapd->conf->anqp_3gpp_cell_net_len); 43361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 43461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 43561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 43661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 43761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void anqp_add_domain_name(struct hostapd_data *hapd, struct wpabuf *buf) 43861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 43961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->domain_name) { 44061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, ANQP_DOMAIN_NAME); 44161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, hapd->conf->domain_name_len); 44261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, hapd->conf->domain_name, 44361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hapd->conf->domain_name_len); 44461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 44561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 44661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 44761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 448aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt#ifdef CONFIG_HS20 449aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt 45061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void anqp_add_operator_friendly_name(struct hostapd_data *hapd, 45161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *buf) 45261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 45361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->hs20_oper_friendly_name) { 45461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *len; 45561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt unsigned int i; 45661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); 45761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_be24(buf, OUI_WFA); 45861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); 45961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME); 46061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, 0); /* Reserved */ 46161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (i = 0; i < hapd->conf->hs20_oper_friendly_name_count; i++) 46261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt { 46361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct hostapd_lang_string *vn; 46461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt vn = &hapd->conf->hs20_oper_friendly_name[i]; 46561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, 3 + vn->name_len); 46661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, vn->lang, 3); 46761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, vn->name, vn->name_len); 46861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 46961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gas_anqp_set_element_len(buf, len); 47061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 47161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 47261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 47361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 47461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void anqp_add_wan_metrics(struct hostapd_data *hapd, 47561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *buf) 47661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 47761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->hs20_wan_metrics) { 47861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); 47961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_be24(buf, OUI_WFA); 48061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); 48161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS); 48261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, 0); /* Reserved */ 48361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, hapd->conf->hs20_wan_metrics, 13); 48461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gas_anqp_set_element_len(buf, len); 48561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 48661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 48761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 48861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 48961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void anqp_add_connection_capability(struct hostapd_data *hapd, 49061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *buf) 49161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 49261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->hs20_connection_capability) { 49361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); 49461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_be24(buf, OUI_WFA); 49561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); 49661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY); 49761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, 0); /* Reserved */ 49861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, hapd->conf->hs20_connection_capability, 49961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hapd->conf->hs20_connection_capability_len); 50061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gas_anqp_set_element_len(buf, len); 50161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 50261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 50361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 50461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 50561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void anqp_add_operating_class(struct hostapd_data *hapd, 50661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *buf) 50761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 50861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->hs20_operating_class) { 50961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); 51061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_be24(buf, OUI_WFA); 51161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); 51261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS); 51361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, 0); /* Reserved */ 51461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_data(buf, hapd->conf->hs20_operating_class, 51561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hapd->conf->hs20_operating_class_len); 51661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt gas_anqp_set_element_len(buf, len); 51761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 51861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 51961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 520f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 521f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic void anqp_add_osu_provider(struct wpabuf *buf, 522f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct hostapd_bss_config *bss, 523f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct hs20_osu_provider *p) 524f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 525f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u8 *len, *len2, *count; 526f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt unsigned int i; 527f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 528f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt len = wpabuf_put(buf, 2); /* OSU Provider Length to be filled */ 529f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 530f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* OSU Friendly Name Duples */ 531f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt len2 = wpabuf_put(buf, 2); 532f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (i = 0; i < p->friendly_name_count; i++) { 533f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct hostapd_lang_string *s = &p->friendly_name[i]; 534f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 3 + s->name_len); 535f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_data(buf, s->lang, 3); 536f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_data(buf, s->name, s->name_len); 537f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 538f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2); 539f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 540f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* OSU Server URI */ 541f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (p->server_uri) { 542f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, os_strlen(p->server_uri)); 543f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_str(buf, p->server_uri); 544f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else 545f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 0); 546f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 547f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* OSU Method List */ 548f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt count = wpabuf_put(buf, 1); 549f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (i = 0; p->method_list[i] >= 0; i++) 550f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, p->method_list[i]); 551f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt *count = i; 552f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 553f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* Icons Available */ 554f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt len2 = wpabuf_put(buf, 2); 555f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (i = 0; i < p->icons_count; i++) { 556f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt size_t j; 557f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct hs20_icon *icon = NULL; 558f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 559f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (j = 0; j < bss->hs20_icons_count && !icon; j++) { 560f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (os_strcmp(p->icons[i], bss->hs20_icons[j].name) == 561f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 0) 562f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt icon = &bss->hs20_icons[j]; 563f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 564f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!icon) 565f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; /* icon info not found */ 566f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 567f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_le16(buf, icon->width); 568f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_le16(buf, icon->height); 569f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_data(buf, icon->language, 3); 570f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, os_strlen(icon->type)); 571f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_str(buf, icon->type); 572f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, os_strlen(icon->name)); 573f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_str(buf, icon->name); 574f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 575f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2); 576f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 577f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* OSU_NAI */ 578f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (p->osu_nai) { 579f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, os_strlen(p->osu_nai)); 580f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_str(buf, p->osu_nai); 581f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else 582f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 0); 583f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 584f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* OSU Service Description Duples */ 585f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt len2 = wpabuf_put(buf, 2); 586f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (i = 0; i < p->service_desc_count; i++) { 587f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct hostapd_lang_string *s = &p->service_desc[i]; 588f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 3 + s->name_len); 589f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_data(buf, s->lang, 3); 590f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_data(buf, s->name, s->name_len); 591f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 592f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2); 593f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 594f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2); 595f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 596f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 597f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 598f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic void anqp_add_osu_providers_list(struct hostapd_data *hapd, 599f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpabuf *buf) 600f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 601f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (hapd->conf->hs20_osu_providers_count) { 602f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt size_t i; 603f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); 604f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_be24(buf, OUI_WFA); 605f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); 606f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_LIST); 607f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 0); /* Reserved */ 608f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 609f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* OSU SSID */ 610f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, hapd->conf->osu_ssid_len); 611f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_data(buf, hapd->conf->osu_ssid, 612f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hapd->conf->osu_ssid_len); 613f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 614f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* Number of OSU Providers */ 615f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, hapd->conf->hs20_osu_providers_count); 616f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 617f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (i = 0; i < hapd->conf->hs20_osu_providers_count; i++) { 618f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt anqp_add_osu_provider( 619f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt buf, hapd->conf, 620f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt &hapd->conf->hs20_osu_providers[i]); 621f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 622f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 623f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt gas_anqp_set_element_len(buf, len); 624f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 625f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 626f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 627f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 628f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic void anqp_add_icon_binary_file(struct hostapd_data *hapd, 629f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpabuf *buf, 630f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const u8 *name, size_t name_len) 631f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 632f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct hs20_icon *icon; 633f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt size_t i; 634f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u8 *len; 635f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 636f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "HS 2.0: Requested Icon Filename", 637f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt name, name_len); 638f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (i = 0; i < hapd->conf->hs20_icons_count; i++) { 639f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt icon = &hapd->conf->hs20_icons[i]; 640f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (name_len == os_strlen(icon->name) && 641f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt os_memcmp(name, icon->name, name_len) == 0) 642f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt break; 643f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 644f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 645f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (i < hapd->conf->hs20_icons_count) 646f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt icon = &hapd->conf->hs20_icons[i]; 647f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt else 648f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt icon = NULL; 649f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 650f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); 651f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_be24(buf, OUI_WFA); 652f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); 653f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, HS20_STYPE_ICON_BINARY_FILE); 654f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 0); /* Reserved */ 655f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 656f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (icon) { 657f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt char *data; 658f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt size_t data_len; 659f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 660f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt data = os_readfile(icon->file, &data_len); 661f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (data == NULL || data_len > 65535) { 662f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 2); /* Download Status: 663f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt * Unspecified file error */ 664f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 0); 665f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_le16(buf, 0); 666f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 667f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 0); /* Download Status: Success */ 668f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, os_strlen(icon->type)); 669f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_str(buf, icon->type); 670f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_le16(buf, data_len); 671f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_data(buf, data, data_len); 672f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 673f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt os_free(data); 674f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 675f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 1); /* Download Status: File not found */ 676f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(buf, 0); 677f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_le16(buf, 0); 678f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 679f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 680f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt gas_anqp_set_element_len(buf, len); 681f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 682f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 683aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt#endif /* CONFIG_HS20 */ 684aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt 68561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 68604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic struct wpabuf * 68704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtgas_serv_build_gas_resp_payload(struct hostapd_data *hapd, 68804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt unsigned int request, 689f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const u8 *home_realm, size_t home_realm_len, 690f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const u8 *icon_name, size_t icon_name_len) 69104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 69204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *buf; 693f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt size_t len; 694f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 695f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt len = 1400; 696f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (request & (ANQP_REQ_NAI_REALM | ANQP_REQ_NAI_HOME_REALM)) 697f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt len += 1000; 698f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (request & ANQP_REQ_ICON_REQUEST) 699f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt len += 65536; 70004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 701f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt buf = wpabuf_alloc(len); 70204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (buf == NULL) 70304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 70404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 70504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (request & ANQP_REQ_CAPABILITY_LIST) 70604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt anqp_add_capab_list(hapd, buf); 70704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (request & ANQP_REQ_VENUE_NAME) 70804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt anqp_add_venue_name(hapd, buf); 70961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (request & ANQP_REQ_NETWORK_AUTH_TYPE) 71061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_network_auth_type(hapd, buf); 71104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (request & ANQP_REQ_ROAMING_CONSORTIUM) 71204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt anqp_add_roaming_consortium(hapd, buf); 71361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (request & ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY) 71461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_ip_addr_type_availability(hapd, buf); 71561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (request & (ANQP_REQ_NAI_REALM | ANQP_REQ_NAI_HOME_REALM)) 71661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_nai_realm(hapd, buf, home_realm, home_realm_len, 71761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt request & ANQP_REQ_NAI_REALM, 71861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt request & ANQP_REQ_NAI_HOME_REALM); 71961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (request & ANQP_REQ_3GPP_CELLULAR_NETWORK) 72061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_3gpp_cellular_network(hapd, buf); 72161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (request & ANQP_REQ_DOMAIN_NAME) 72261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_domain_name(hapd, buf); 72361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 724aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt#ifdef CONFIG_HS20 72561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (request & ANQP_REQ_HS_CAPABILITY_LIST) 72661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_hs_capab_list(hapd, buf); 72761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (request & ANQP_REQ_OPERATOR_FRIENDLY_NAME) 72861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_operator_friendly_name(hapd, buf); 72961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (request & ANQP_REQ_WAN_METRICS) 73061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_wan_metrics(hapd, buf); 73161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (request & ANQP_REQ_CONNECTION_CAPABILITY) 73261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_connection_capability(hapd, buf); 73361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (request & ANQP_REQ_OPERATING_CLASS) 73461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anqp_add_operating_class(hapd, buf); 735f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (request & ANQP_REQ_OSU_PROVIDERS_LIST) 736f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt anqp_add_osu_providers_list(hapd, buf); 737f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (request & ANQP_REQ_ICON_REQUEST) 738f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt anqp_add_icon_binary_file(hapd, buf, icon_name, icon_name_len); 739aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt#endif /* CONFIG_HS20 */ 74004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 74104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return buf; 74204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 74304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 74404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 74504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstruct anqp_query_info { 74604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt unsigned int request; 74761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *home_realm_query; 74861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t home_realm_query_len; 749f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const u8 *icon_name; 750f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt size_t icon_name_len; 75104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}; 75204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 75304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 75404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void set_anqp_req(unsigned int bit, const char *name, int local, 75504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct anqp_query_info *qi) 75604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 75704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt qi->request |= bit; 75804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (local) { 75904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: %s (local)", name); 76004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else { 76104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: %s not available", name); 76204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 76304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 76404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 76504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 76604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void rx_anqp_query_list_id(struct hostapd_data *hapd, u16 info_id, 76704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct anqp_query_info *qi) 76804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 76904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt switch (info_id) { 77004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case ANQP_CAPABILITY_LIST: 771b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt set_anqp_req(ANQP_REQ_CAPABILITY_LIST, "Capability List", 1, 772b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt qi); 77304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 77404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case ANQP_VENUE_NAME: 77504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt set_anqp_req(ANQP_REQ_VENUE_NAME, "Venue Name", 776b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt hapd->conf->venue_name != NULL, qi); 77704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 77861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case ANQP_NETWORK_AUTH_TYPE: 77961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt set_anqp_req(ANQP_REQ_NETWORK_AUTH_TYPE, "Network Auth Type", 780b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt hapd->conf->network_auth_type != NULL, qi); 78161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 78204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case ANQP_ROAMING_CONSORTIUM: 78304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt set_anqp_req(ANQP_REQ_ROAMING_CONSORTIUM, "Roaming Consortium", 784b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt hapd->conf->roaming_consortium != NULL, qi); 78504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 78661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case ANQP_IP_ADDR_TYPE_AVAILABILITY: 78761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt set_anqp_req(ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY, 78861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "IP Addr Type Availability", 789b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt hapd->conf->ipaddr_type_configured, qi); 79061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 79161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case ANQP_NAI_REALM: 79261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt set_anqp_req(ANQP_REQ_NAI_REALM, "NAI Realm", 793b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt hapd->conf->nai_realm_data != NULL, qi); 79461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 79561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case ANQP_3GPP_CELLULAR_NETWORK: 79661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt set_anqp_req(ANQP_REQ_3GPP_CELLULAR_NETWORK, 79761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "3GPP Cellular Network", 798b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt hapd->conf->anqp_3gpp_cell_net != NULL, qi); 79961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 80061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case ANQP_DOMAIN_NAME: 80161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt set_anqp_req(ANQP_REQ_DOMAIN_NAME, "Domain Name", 802b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt hapd->conf->domain_name != NULL, qi); 80361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 80404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt default: 80504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Unsupported Info Id %u", 80604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt info_id); 80704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 80804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 80904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 81004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 81104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 81204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void rx_anqp_query_list(struct hostapd_data *hapd, 81304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *pos, const u8 *end, 81404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct anqp_query_info *qi) 81504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 81604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: %u Info IDs requested in Query list", 81704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (unsigned int) (end - pos) / 2); 81804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 81904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt while (pos + 2 <= end) { 82004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt rx_anqp_query_list_id(hapd, WPA_GET_LE16(pos), qi); 82104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += 2; 82204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 82304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 82404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 82504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 826aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt#ifdef CONFIG_HS20 827aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt 82861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void rx_anqp_hs_query_list(struct hostapd_data *hapd, u8 subtype, 82961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct anqp_query_info *qi) 83061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 83161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt switch (subtype) { 83261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case HS20_STYPE_CAPABILITY_LIST: 83361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt set_anqp_req(ANQP_REQ_HS_CAPABILITY_LIST, "HS Capability List", 834b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 1, qi); 83561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 83661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case HS20_STYPE_OPERATOR_FRIENDLY_NAME: 83761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt set_anqp_req(ANQP_REQ_OPERATOR_FRIENDLY_NAME, 83861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "Operator Friendly Name", 839b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt hapd->conf->hs20_oper_friendly_name != NULL, qi); 84061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 84161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case HS20_STYPE_WAN_METRICS: 84261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt set_anqp_req(ANQP_REQ_WAN_METRICS, "WAN Metrics", 843b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt hapd->conf->hs20_wan_metrics != NULL, qi); 84461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 84561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case HS20_STYPE_CONNECTION_CAPABILITY: 84661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt set_anqp_req(ANQP_REQ_CONNECTION_CAPABILITY, 84761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "Connection Capability", 84861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hapd->conf->hs20_connection_capability != NULL, 849b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt qi); 85061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 85161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case HS20_STYPE_OPERATING_CLASS: 85261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt set_anqp_req(ANQP_REQ_OPERATING_CLASS, "Operating Class", 853b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt hapd->conf->hs20_operating_class != NULL, qi); 85461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 855f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt case HS20_STYPE_OSU_PROVIDERS_LIST: 856f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt set_anqp_req(ANQP_REQ_OSU_PROVIDERS_LIST, "OSU Providers list", 857b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt hapd->conf->hs20_osu_providers_count, qi); 858f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt break; 85961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt default: 86061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 subtype %u", 86161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt subtype); 86261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 86361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 86461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 86561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 86661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 86761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void rx_anqp_hs_nai_home_realm(struct hostapd_data *hapd, 86861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *pos, const u8 *end, 86961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct anqp_query_info *qi) 87061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 87161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt qi->request |= ANQP_REQ_NAI_HOME_REALM; 87261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt qi->home_realm_query = pos; 87361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt qi->home_realm_query_len = end - pos; 87461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hapd->conf->nai_realm_data != NULL) { 87561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 NAI Home Realm Query " 87661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "(local)"); 87761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else { 87861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 NAI Home Realm Query not " 87961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "available"); 88061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 88161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 88261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 88361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 884f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic void rx_anqp_hs_icon_request(struct hostapd_data *hapd, 885f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const u8 *pos, const u8 *end, 886f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct anqp_query_info *qi) 887f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 888f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt qi->request |= ANQP_REQ_ICON_REQUEST; 889f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt qi->icon_name = pos; 890f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt qi->icon_name_len = end - pos; 891f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (hapd->conf->hs20_icons_count) { 892f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Icon Request Query " 893f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "(local)"); 894f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 895f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Icon Request Query not " 896f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "available"); 897f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 898f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 899f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 900f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 90161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void rx_anqp_vendor_specific(struct hostapd_data *hapd, 90261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *pos, const u8 *end, 90361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct anqp_query_info *qi) 90461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 90561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u32 oui; 90661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 subtype; 90761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 90861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos + 4 > end) { 90961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Too short vendor specific ANQP " 91061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "Query element"); 91161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 91261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 91361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 91461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt oui = WPA_GET_BE24(pos); 91561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += 3; 91661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (oui != OUI_WFA) { 91761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Unsupported vendor OUI %06x", 91861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt oui); 91961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 92061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 92161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 92261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (*pos != HS20_ANQP_OUI_TYPE) { 92361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Unsupported WFA vendor type %u", 92461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *pos); 92561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 92661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 92761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos++; 92861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 92961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos + 1 >= end) 93061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 93161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 93261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt subtype = *pos++; 93361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos++; /* Reserved */ 93461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt switch (subtype) { 93561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case HS20_STYPE_QUERY_LIST: 93661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Query List"); 93761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt while (pos < end) { 93861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt rx_anqp_hs_query_list(hapd, *pos, qi); 93961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos++; 94061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 94161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 94261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case HS20_STYPE_NAI_HOME_REALM_QUERY: 94361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt rx_anqp_hs_nai_home_realm(hapd, pos, end, qi); 94461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 945f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt case HS20_STYPE_ICON_REQUEST: 946f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt rx_anqp_hs_icon_request(hapd, pos, end, qi); 947f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt break; 94861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt default: 94961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 query subtype " 95061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "%u", subtype); 95161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 95261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 95361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 95461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 955aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt#endif /* CONFIG_HS20 */ 956aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt 95761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 95804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void gas_serv_req_local_processing(struct hostapd_data *hapd, 95904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *sa, u8 dialog_token, 9601846323989242844f0e857458a8939fa5836429cDmitry Shmidt struct anqp_query_info *qi, int prot) 96104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 96204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *buf, *tx_buf; 96304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 96409f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt buf = gas_serv_build_gas_resp_payload(hapd, qi->request, 96561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt qi->home_realm_query, 966f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt qi->home_realm_query_len, 967f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt qi->icon_name, qi->icon_name_len); 96804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Locally generated ANQP responses", 96904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt buf); 97004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!buf) 97104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 97204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 97304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpabuf_len(buf) > hapd->gas_frag_limit || 97404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hapd->conf->gas_comeback_delay) { 97504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct gas_dialog_info *di; 97604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u16 comeback_delay = 1; 97704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 97804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (hapd->conf->gas_comeback_delay) { 97904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Testing - allow overriding of the delay value */ 98004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt comeback_delay = hapd->conf->gas_comeback_delay; 98104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 98204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 98304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Too long response to fit in " 98404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "initial response - use GAS comeback"); 98504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt di = gas_dialog_create(hapd, sa, dialog_token); 98604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!di) { 98704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_INFO, "ANQP: Could not create dialog " 98804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "for " MACSTR " (dialog token %u)", 98904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt MAC2STR(sa), dialog_token); 99004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(buf); 99176cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt tx_buf = gas_anqp_build_initial_resp_buf( 99276cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt dialog_token, WLAN_STATUS_UNSPECIFIED_FAILURE, 99376cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt 0, NULL); 99476cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt } else { 99576cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt di->prot = prot; 99676cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt di->sd_resp = buf; 99776cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt di->sd_resp_pos = 0; 99876cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt tx_buf = gas_anqp_build_initial_resp_buf( 99976cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt dialog_token, WLAN_STATUS_SUCCESS, 100076cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt comeback_delay, NULL); 100104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 100204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else { 100304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Initial response (no comeback)"); 100404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt tx_buf = gas_anqp_build_initial_resp_buf( 100504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dialog_token, WLAN_STATUS_SUCCESS, 0, buf); 100604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(buf); 100704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 100804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!tx_buf) 100904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 10101846323989242844f0e857458a8939fa5836429cDmitry Shmidt if (prot) 10111846323989242844f0e857458a8939fa5836429cDmitry Shmidt convert_to_protected_dual(tx_buf); 101204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, 101304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_head(tx_buf), wpabuf_len(tx_buf)); 101404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(tx_buf); 101504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 101604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 101704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 101804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd, 101904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *sa, 10201846323989242844f0e857458a8939fa5836429cDmitry Shmidt const u8 *data, size_t len, int prot) 102104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 102204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *pos = data; 102304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *end = data + len; 102404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *next; 102504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 dialog_token; 102604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u16 slen; 102704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct anqp_query_info qi; 102804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *adv_proto; 102904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 103004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (len < 1 + 2) 103104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 103204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 103304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memset(&qi, 0, sizeof(qi)); 103404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 103504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dialog_token = *pos++; 103604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(hapd->msg_ctx, MSG_DEBUG, 103704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "GAS: GAS Initial Request from " MACSTR " (dialog token %u) ", 103804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt MAC2STR(sa), dialog_token); 103904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 104004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (*pos != WLAN_EID_ADV_PROTO) { 104104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(hapd->msg_ctx, MSG_DEBUG, 104204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "GAS: Unexpected IE in GAS Initial Request: %u", *pos); 104304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 104404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 104504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt adv_proto = pos++; 104604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 104704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt slen = *pos++; 104804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt next = pos + slen; 104904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (next > end || slen < 2) { 105004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(hapd->msg_ctx, MSG_DEBUG, 105104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "GAS: Invalid IE in GAS Initial Request"); 105204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 105304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 105404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos++; /* skip QueryRespLenLimit and PAME-BI */ 105504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 105604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) { 105704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *buf; 105804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(hapd->msg_ctx, MSG_DEBUG, 105904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "GAS: Unsupported GAS advertisement protocol id %u", 106004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *pos); 106104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sa[0] & 0x01) 106204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; /* Invalid source address - drop silently */ 106304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt buf = gas_build_initial_resp( 106404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dialog_token, WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED, 106504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 0, 2 + slen + 2); 106604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (buf == NULL) 106704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 106804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_data(buf, adv_proto, 2 + slen); 106904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_le16(buf, 0); /* Query Response Length */ 10701846323989242844f0e857458a8939fa5836429cDmitry Shmidt if (prot) 10711846323989242844f0e857458a8939fa5836429cDmitry Shmidt convert_to_protected_dual(buf); 107204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, 107304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_head(buf), wpabuf_len(buf)); 107404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(buf); 107504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 107604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 107704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 107804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos = next; 107904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Query Request */ 108004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (pos + 2 > end) 108104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 108204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt slen = WPA_GET_LE16(pos); 108304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += 2; 108404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (pos + slen > end) 108504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 108604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt end = pos + slen; 108704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 108804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* ANQP Query Request */ 108904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt while (pos < end) { 109004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u16 info_id, elen; 109104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 109204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (pos + 4 > end) 109304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 109404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 109504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt info_id = WPA_GET_LE16(pos); 109604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += 2; 109704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt elen = WPA_GET_LE16(pos); 109804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += 2; 109904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 110004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (pos + elen > end) { 110104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Invalid Query Request"); 110204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 110304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 110404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 110504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt switch (info_id) { 110604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case ANQP_QUERY_LIST: 110704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt rx_anqp_query_list(hapd, pos, pos + elen, &qi); 110804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 1109aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt#ifdef CONFIG_HS20 111061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case ANQP_VENDOR_SPECIFIC: 111161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt rx_anqp_vendor_specific(hapd, pos, pos + elen, &qi); 111261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 1113aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt#endif /* CONFIG_HS20 */ 111404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt default: 111504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Unsupported Query " 111604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "Request element %u", info_id); 111704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 111804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 111904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 112004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += elen; 112104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 112204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 11231846323989242844f0e857458a8939fa5836429cDmitry Shmidt gas_serv_req_local_processing(hapd, sa, dialog_token, &qi, prot); 112404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 112504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 112604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 112704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd, 112804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *sa, 11291846323989242844f0e857458a8939fa5836429cDmitry Shmidt const u8 *data, size_t len, int prot) 113004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 113104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct gas_dialog_info *dialog; 113204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *buf, *tx_buf; 113304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 dialog_token; 113404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t frag_len; 113504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int more = 0; 113604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 113704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_hexdump(MSG_DEBUG, "GAS: RX GAS Comeback Request", data, len); 113804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (len < 1) 113904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 114004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dialog_token = *data; 114104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Dialog Token: %u", 114204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dialog_token); 114304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 114404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dialog = gas_serv_dialog_find(hapd, sa, dialog_token); 114504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!dialog) { 114604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: No pending SD " 114704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "response fragment for " MACSTR " dialog token %u", 114804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt MAC2STR(sa), dialog_token); 114904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 115004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sa[0] & 0x01) 115104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; /* Invalid source address - drop silently */ 115204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt tx_buf = gas_anqp_build_comeback_resp_buf( 115304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dialog_token, WLAN_STATUS_NO_OUTSTANDING_GAS_REQ, 0, 0, 115404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 0, NULL); 115504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (tx_buf == NULL) 115604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 115704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto send_resp; 115804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 115904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 116004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt frag_len = wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos; 116104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (frag_len > hapd->gas_frag_limit) { 116204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt frag_len = hapd->gas_frag_limit; 116304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt more = 1; 116404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 116504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: resp frag_len %u", 116604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (unsigned int) frag_len); 116704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt buf = wpabuf_alloc_copy(wpabuf_head_u8(dialog->sd_resp) + 116804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dialog->sd_resp_pos, frag_len); 116904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (buf == NULL) { 117004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Failed to allocate " 117104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "buffer"); 1172b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt gas_serv_dialog_clear(dialog); 1173b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return; 117404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 117504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt tx_buf = gas_anqp_build_comeback_resp_buf(dialog_token, 117604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt WLAN_STATUS_SUCCESS, 117704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dialog->sd_frag_id, 117804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt more, 0, buf); 117904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(buf); 1180b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (tx_buf == NULL) { 1181b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt gas_serv_dialog_clear(dialog); 1182b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return; 1183b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt } 118404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Comeback Response " 118504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "(frag_id %d more=%d frag_len=%d)", 118604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dialog->sd_frag_id, more, (int) frag_len); 118704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dialog->sd_frag_id++; 118804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dialog->sd_resp_pos += frag_len; 118904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 119004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (more) { 119104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: %d more bytes remain " 119204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "to be sent", 119304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (int) (wpabuf_len(dialog->sd_resp) - 119404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dialog->sd_resp_pos)); 119504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else { 119604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: All fragments of " 119704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "SD response sent"); 119804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt gas_serv_dialog_clear(dialog); 119904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt gas_serv_free_dialogs(hapd, sa); 120004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 120104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 120204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtsend_resp: 12031846323989242844f0e857458a8939fa5836429cDmitry Shmidt if (prot) 12041846323989242844f0e857458a8939fa5836429cDmitry Shmidt convert_to_protected_dual(tx_buf); 120504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, 120604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_head(tx_buf), wpabuf_len(tx_buf)); 120704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(tx_buf); 120804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 120904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 121004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 121104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void gas_serv_rx_public_action(void *ctx, const u8 *buf, size_t len, 121204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int freq) 121304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 121404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct hostapd_data *hapd = ctx; 121504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const struct ieee80211_mgmt *mgmt; 121604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *sa, *data; 12171846323989242844f0e857458a8939fa5836429cDmitry Shmidt int prot; 121804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 121904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mgmt = (const struct ieee80211_mgmt *) buf; 1220623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt if (len < IEEE80211_HDRLEN + 2) 122104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 12221846323989242844f0e857458a8939fa5836429cDmitry Shmidt if (mgmt->u.action.category != WLAN_ACTION_PUBLIC && 12231846323989242844f0e857458a8939fa5836429cDmitry Shmidt mgmt->u.action.category != WLAN_ACTION_PROTECTED_DUAL) 122404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 12251846323989242844f0e857458a8939fa5836429cDmitry Shmidt /* 12261846323989242844f0e857458a8939fa5836429cDmitry Shmidt * Note: Public Action and Protected Dual of Public Action frames share 12271846323989242844f0e857458a8939fa5836429cDmitry Shmidt * the same payload structure, so it is fine to use definitions of 12281846323989242844f0e857458a8939fa5836429cDmitry Shmidt * Public Action frames to process both. 12291846323989242844f0e857458a8939fa5836429cDmitry Shmidt */ 12301846323989242844f0e857458a8939fa5836429cDmitry Shmidt prot = mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL; 123104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sa = mgmt->sa; 1232623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt len -= IEEE80211_HDRLEN + 1; 1233623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt data = buf + IEEE80211_HDRLEN + 1; 123404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt switch (data[0]) { 123504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case WLAN_PA_GAS_INITIAL_REQ: 12361846323989242844f0e857458a8939fa5836429cDmitry Shmidt gas_serv_rx_gas_initial_req(hapd, sa, data + 1, len - 1, prot); 123704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 123804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case WLAN_PA_GAS_COMEBACK_REQ: 12391846323989242844f0e857458a8939fa5836429cDmitry Shmidt gas_serv_rx_gas_comeback_req(hapd, sa, data + 1, len - 1, prot); 124004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 124104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 124204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 124304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 124404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 124504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint gas_serv_init(struct hostapd_data *hapd) 124604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 12474b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt hapd->public_action_cb2 = gas_serv_rx_public_action; 12484b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt hapd->public_action_cb2_ctx = hapd; 124904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hapd->gas_frag_limit = 1400; 125004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (hapd->conf->gas_frag_limit > 0) 125104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hapd->gas_frag_limit = hapd->conf->gas_frag_limit; 125204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 125304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 125404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 125504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 125604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid gas_serv_deinit(struct hostapd_data *hapd) 125704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 125804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 1259