11f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/* 21f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * hostapd / IEEE 802.11 Management 304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> 41f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 71f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 81f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 91f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "utils/includes.h" 101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "utils/common.h" 121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common/ieee802_11_defs.h" 131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "hostapd.h" 141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "sta_info.h" 151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "ap_config.h" 161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "ap_drv_ops.h" 171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "ieee802_11.h" 181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_IEEE80211W 211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd, 231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct sta_info *sta, u8 *eid) 241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos = eid; 261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u32 timeout, tu; 2704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt struct os_reltime now, passed; 281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_EID_TIMEOUT_INTERVAL; 301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 5; 311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK; 3204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt os_get_reltime(&now); 3304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt os_reltime_sub(&now, &sta->sa_query_start, &passed); 341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt tu = (passed.sec * 1000000 + passed.usec) / 1024; 351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->assoc_sa_query_max_timeout > tu) 361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt timeout = hapd->conf->assoc_sa_query_max_timeout - tu; 371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt else 381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt timeout = 0; 391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (timeout < hapd->conf->assoc_sa_query_max_timeout) 401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt timeout++; /* add some extra time for local timers */ 411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_LE32(pos, timeout); 421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 4; 431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return pos; 451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/* MLME-SAQuery.request */ 491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid ieee802_11_send_sa_query_req(struct hostapd_data *hapd, 501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *addr, const u8 *trans_id) 511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct ieee80211_mgmt mgmt; 531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *end; 541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to " 561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(addr)); 571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", 581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt trans_id, WLAN_SA_QUERY_TR_ID_LEN); 591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(&mgmt, 0, sizeof(mgmt)); 611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_FC_STYPE_ACTION); 631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(mgmt.da, addr, ETH_ALEN); 641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); 651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); 661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt mgmt.u.action.category = WLAN_ACTION_SA_QUERY; 671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST; 681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id, 691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_SA_QUERY_TR_ID_LEN); 701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; 711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0) 72cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "ieee802_11_send_sa_query_req: send failed"); 731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd, 771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *sa, const u8 *trans_id) 781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct sta_info *sta; 801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct ieee80211_mgmt resp; 811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *end; 821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from " 841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(sa)); 851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", 861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt trans_id, WLAN_SA_QUERY_TR_ID_LEN); 871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sta = ap_get_sta(hapd, sa); 891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) { 901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request " 911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "from unassociated STA " MACSTR, MAC2STR(sa)); 921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to " 961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(sa)); 971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(&resp, 0, sizeof(resp)); 991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 1001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_FC_STYPE_ACTION); 1011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(resp.da, sa, ETH_ALEN); 1021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN); 1031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN); 1041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt resp.u.action.category = WLAN_ACTION_SA_QUERY; 1051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE; 1061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(resp.u.action.u.sa_query_req.trans_id, trans_id, 1071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_SA_QUERY_TR_ID_LEN); 1081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; 1091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp, 0) < 0) 110cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "ieee80211_mgmt_sa_query_request: send failed"); 1111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid ieee802_11_sa_query_action(struct hostapd_data *hapd, const u8 *sa, 1151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 action_type, const u8 *trans_id) 1161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct sta_info *sta; 1181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int i; 1191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (action_type == WLAN_SA_QUERY_REQUEST) { 1211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ieee802_11_send_sa_query_resp(hapd, sa, trans_id); 1221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 1231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (action_type != WLAN_SA_QUERY_RESPONSE) { 1261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query " 1271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Action %d", action_type); 1281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 1291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from " 1321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(sa)); 1331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", 1341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt trans_id, WLAN_SA_QUERY_TR_ID_LEN); 1351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* MLME-SAQuery.confirm */ 1371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sta = ap_get_sta(hapd, sa); 1391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sta == NULL || sta->sa_query_trans_id == NULL) { 1401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with " 1411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "pending SA Query request found"); 1421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 1431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < sta->sa_query_count; i++) { 1461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_memcmp(sta->sa_query_trans_id + 1471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt i * WLAN_SA_QUERY_TR_ID_LEN, 1481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt trans_id, WLAN_SA_QUERY_TR_ID_LEN) == 0) 1491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 1501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (i >= sta->sa_query_count) { 1531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query " 1541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "transaction identifier found"); 1551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 1561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 1591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt HOSTAPD_LEVEL_DEBUG, 1601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Reply to pending SA Query received"); 1611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ap_sta_stop_sa_query(hapd, sta); 1621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 1651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 167444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidtstatic void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx) 168444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt{ 169444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt *pos = 0x00; 170444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt 171444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt switch (idx) { 172444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt case 0: /* Bits 0-7 */ 173b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (hapd->iconf->obss_interval) 174b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt *pos |= 0x01; /* Bit 0 - Coexistence management */ 175d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) 176d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt *pos |= 0x04; /* Bit 2 - Extended Channel Switching */ 177444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt break; 178444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt case 1: /* Bits 8-15 */ 179fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (hapd->conf->proxy_arp) 180fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt *pos |= 0x10; /* Bit 12 - Proxy ARP */ 181444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt break; 182444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt case 2: /* Bits 16-23 */ 183444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (hapd->conf->wnm_sleep_mode) 184444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */ 185444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (hapd->conf->bss_transition) 186444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt *pos |= 0x08; /* Bit 19 - BSS Transition */ 187444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt break; 188444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt case 3: /* Bits 24-31 */ 189d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#ifdef CONFIG_WNM_AP 190444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt *pos |= 0x02; /* Bit 25 - SSID List */ 191d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* CONFIG_WNM_AP */ 192444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (hapd->conf->time_advertisement == 2) 193444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt *pos |= 0x08; /* Bit 27 - UTC TSF Offset */ 194444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (hapd->conf->interworking) 195444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt *pos |= 0x80; /* Bit 31 - Interworking */ 196444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt break; 197444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt case 4: /* Bits 32-39 */ 198051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (hapd->conf->qos_map_set_len) 199051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt *pos |= 0x01; /* Bit 32 - QoS Map */ 200444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (hapd->conf->tdls & TDLS_PROHIBIT) 201444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt *pos |= 0x40; /* Bit 38 - TDLS Prohibited */ 202444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH) { 203444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt /* Bit 39 - TDLS Channel Switching Prohibited */ 204444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt *pos |= 0x80; 205444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 206444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt break; 207444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt case 5: /* Bits 40-47 */ 208f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_HS20 209f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (hapd->conf->hs20) 210f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt *pos |= 0x40; /* Bit 46 - WNM-Notification */ 211f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_HS20 */ 21257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#ifdef CONFIG_MBO 21357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (hapd->conf->mbo_enabled) 21457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt *pos |= 0x40; /* Bit 46 - WNM-Notification */ 21557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#endif /* CONFIG_MBO */ 216444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt break; 217444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt case 6: /* Bits 48-55 */ 218444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (hapd->conf->ssid.utf8_ssid) 219444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt *pos |= 0x01; /* Bit 48 - UTF-8 SSID */ 220444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt break; 2219839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt case 7: /* Bits 56-63 */ 2229839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt break; 2237d17530e229db79208e99741071df97ea4faeec6Dmitry Shmidt case 8: /* Bits 64-71 */ 2247d17530e229db79208e99741071df97ea4faeec6Dmitry Shmidt if (hapd->conf->ftm_responder) 2257d17530e229db79208e99741071df97ea4faeec6Dmitry Shmidt *pos |= 0x40; /* Bit 70 - FTM responder */ 2267d17530e229db79208e99741071df97ea4faeec6Dmitry Shmidt if (hapd->conf->ftm_initiator) 2277d17530e229db79208e99741071df97ea4faeec6Dmitry Shmidt *pos |= 0x80; /* Bit 71 - FTM initiator */ 2289839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt case 9: /* Bits 72-79 */ 2299839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt#ifdef CONFIG_FILS 2309839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if ((hapd->conf->wpa & WPA_PROTO_RSN) && 2319839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) 2329839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt *pos |= 0x01; 2339839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt#endif /* CONFIG_FILS */ 2347d17530e229db79208e99741071df97ea4faeec6Dmitry Shmidt break; 235444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 236444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt} 237444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt 238444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt 2391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) 2401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos = eid; 242444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt u8 len = 0, i; 2431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)) 2451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = 5; 2461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 4 && hapd->conf->interworking) 2471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = 4; 248a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (len < 3 && hapd->conf->wnm_sleep_mode) 249a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt len = 3; 250b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (len < 1 && hapd->iconf->obss_interval) 251b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt len = 1; 252a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (len < 7 && hapd->conf->ssid.utf8_ssid) 253a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt len = 7; 2547d17530e229db79208e99741071df97ea4faeec6Dmitry Shmidt if (len < 9 && 2557d17530e229db79208e99741071df97ea4faeec6Dmitry Shmidt (hapd->conf->ftm_initiator || hapd->conf->ftm_responder)) 2567d17530e229db79208e99741071df97ea4faeec6Dmitry Shmidt len = 9; 257d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#ifdef CONFIG_WNM_AP 258a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (len < 4) 259a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt len = 4; 260d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* CONFIG_WNM_AP */ 261f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_HS20 262f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (hapd->conf->hs20 && len < 6) 263f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt len = 6; 264f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_HS20 */ 26557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#ifdef CONFIG_MBO 26657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (hapd->conf->mbo_enabled && len < 6) 26757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt len = 6; 26857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#endif /* CONFIG_MBO */ 2699839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt#ifdef CONFIG_FILS 2709839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if ((!(hapd->conf->wpa & WPA_PROTO_RSN) || 2719839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10) 2729839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt len = 10; 2739839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt#endif /* CONFIG_FILS */ 274444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (len < hapd->iface->extended_capa_len) 275444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt len = hapd->iface->extended_capa_len; 2761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len == 0) 2771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 2781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_EID_EXT_CAPAB; 2801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = len; 281444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt for (i = 0; i < len; i++, pos++) { 282444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt hostapd_ext_capab_byte(hapd, pos, i); 2831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 284444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (i < hapd->iface->extended_capa_len) { 285444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt *pos &= ~hapd->iface->extended_capa_mask[i]; 286444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt *pos |= hapd->iface->extended_capa[i]; 287444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 288444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 289a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 290444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt while (len > 0 && eid[1 + len] == 0) { 291444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt len--; 292444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt eid[1] = len; 293444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 294444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (len == 0) 295444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt return eid; 296a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 297444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt return eid + 2 + len; 2981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 301051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtu8 * hostapd_eid_qos_map_set(struct hostapd_data *hapd, u8 *eid) 302051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 303051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt u8 *pos = eid; 304051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt u8 len = hapd->conf->qos_map_set_len; 305051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 306051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (!len) 307051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return eid; 308051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 309051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt *pos++ = WLAN_EID_QOS_MAP_SET; 310051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt *pos++ = len; 311051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt os_memcpy(pos, hapd->conf->qos_map_set, len); 312051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos += len; 313051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 314051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return pos; 315051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 316051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 317051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 3181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid) 3191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos = eid; 3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_INTERWORKING 3221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *len; 3231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!hapd->conf->interworking) 3251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 3261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_EID_INTERWORKING; 3281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = pos++; 3291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos = hapd->conf->access_network_type; 3311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->internet) 3321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= INTERWORKING_ANO_INTERNET; 3331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->asra) 3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= INTERWORKING_ANO_ASRA; 3351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->esr) 3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= INTERWORKING_ANO_ESR; 3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->uesa) 3381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= INTERWORKING_ANO_UESA; 3391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos++; 3401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->venue_info_set) { 3421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = hapd->conf->venue_group; 3431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = hapd->conf->venue_type; 3441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!is_zero_ether_addr(hapd->conf->hessid)) { 3471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); 3481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += ETH_ALEN; 3491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *len = pos - len - 1; 3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_INTERWORKING */ 3531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return pos; 3551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid) 3591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos = eid; 3611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_INTERWORKING 3621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* TODO: Separate configuration for ANQP? */ 3641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!hapd->conf->interworking) 3651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 3661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_EID_ADV_PROTO; 3681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 2; 3691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0x7F; /* Query Response Length Limit | PAME-BI */ 3701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = ACCESS_NETWORK_QUERY_PROTOCOL; 3711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_INTERWORKING */ 3721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return pos; 3741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid) 3781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos = eid; 3801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_INTERWORKING 3811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *len; 3821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt unsigned int i, count; 3831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!hapd->conf->interworking || 3851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hapd->conf->roaming_consortium == NULL || 3861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hapd->conf->roaming_consortium_count == 0) 3871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 3881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_EID_ROAMING_CONSORTIUM; 3901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = pos++; 3911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Number of ANQP OIs (in addition to the max 3 listed here) */ 3931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->roaming_consortium_count > 3 + 255) 3941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 255; 3951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt else if (hapd->conf->roaming_consortium_count > 3) 3961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = hapd->conf->roaming_consortium_count - 3; 3971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt else 3981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; 3991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* OU #1 and #2 Lengths */ 4011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos = hapd->conf->roaming_consortium[0].len; 4021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->roaming_consortium_count > 1) 4031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos |= hapd->conf->roaming_consortium[1].len << 4; 4041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos++; 4051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->roaming_consortium_count > 3) 4071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt count = 3; 4081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt else 4091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt count = hapd->conf->roaming_consortium_count; 4101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < count; i++) { 4121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(pos, hapd->conf->roaming_consortium[i].oi, 4131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hapd->conf->roaming_consortium[i].len); 4141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += hapd->conf->roaming_consortium[i].len; 4151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *len = pos - len - 1; 4181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_INTERWORKING */ 4191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return pos; 4211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid) 4251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 4261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->time_advertisement != 2) 4271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 4281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->time_adv == NULL && 4301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hostapd_update_time_adv(hapd) < 0) 4311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 4321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->time_adv == NULL) 4341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 4351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(eid, wpabuf_head(hapd->time_adv), 4371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_len(hapd->time_adv)); 4381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eid += wpabuf_len(hapd->time_adv); 4391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 4411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid) 4451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 4461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t len; 4471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->time_advertisement != 2) 4491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 4501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = os_strlen(hapd->conf->time_zone); 4521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *eid++ = WLAN_EID_TIME_ZONE; 4541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *eid++ = len; 4551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(eid, hapd->conf->time_zone, len); 4561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eid += len; 4571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eid; 4591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint hostapd_update_time_adv(struct hostapd_data *hapd) 4631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 4641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const int elen = 2 + 1 + 10 + 5 + 1; 4651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct os_time t; 4661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct os_tm tm; 4671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos; 4681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->conf->time_advertisement != 2) 4701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 4711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0) 4731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 4741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!hapd->time_adv) { 4761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hapd->time_adv = wpabuf_alloc(elen); 4771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (hapd->time_adv == NULL) 4781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 4791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_put(hapd->time_adv, elen); 4801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else 4811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_mhead_u8(hapd->time_adv); 4821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = WLAN_EID_TIME_ADVERTISEMENT; 4841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 1 + 10 + 5 + 1; 4851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 2; /* UTC time at which the TSF timer is 0 */ 4871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Time Value at TSF 0 */ 4891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* FIX: need to calculate this based on the current TSF value */ 4901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_LE16(pos, tm.year); /* Year */ 4911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 4921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = tm.month; /* Month */ 4931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = tm.day; /* Day of month */ 4941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = tm.hour; /* Hours */ 4951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = tm.min; /* Minutes */ 4961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = tm.sec; /* Seconds */ 4971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */ 4981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 4991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; /* Reserved */ 5001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Time Error */ 5021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* TODO: fill in an estimate on the error */ 5031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; 5041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; 5051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; 5061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; 5071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = 0; 5081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = hapd->time_update_counter++; 5101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 51304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 51404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 51504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtu8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid) 51604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 51704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 *pos = eid; 51804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 519d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#ifdef CONFIG_WNM_AP 52004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (hapd->conf->ap_max_inactivity > 0) { 52104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt unsigned int val; 52204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD; 52304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *pos++ = 3; 52404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt val = hapd->conf->ap_max_inactivity; 52504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (val > 68000) 52604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt val = 68000; 52704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt val *= 1000; 52804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt val /= 1024; 52904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (val == 0) 53004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt val = 1; 53104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (val > 65535) 53204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt val = 65535; 53304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt WPA_PUT_LE16(pos, val); 53404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += 2; 53504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *pos++ = 0x00; /* TODO: Protected Keep-Alive Required */ 53604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 537d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt#endif /* CONFIG_WNM_AP */ 53804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 53904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return pos; 54004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 54157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 54257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 54357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#ifdef CONFIG_MBO 54457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 54557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtu8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len) 54657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{ 547d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt u8 mbo[9], *mbo_pos = mbo; 54857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt u8 *pos = eid; 54957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 550d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (!hapd->conf->mbo_enabled && !hapd->enable_oce) 55157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return eid; 55257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 553d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (hapd->conf->mbo_enabled) { 554d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt *mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND; 555d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt *mbo_pos++ = 1; 556d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt /* Not Cellular aware */ 557d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt *mbo_pos++ = 0; 558d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 55957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 560d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) { 56157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt *mbo_pos++ = MBO_ATTR_ID_ASSOC_DISALLOW; 56257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt *mbo_pos++ = 1; 56357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt *mbo_pos++ = hapd->mbo_assoc_disallow; 56457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 56557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 566d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (hapd->enable_oce & (OCE_AP | OCE_STA_CFON)) { 567d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt u8 ctrl; 568d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 569d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ctrl = OCE_RELEASE; 570d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if ((hapd->enable_oce & (OCE_AP | OCE_STA_CFON)) == 571d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt OCE_STA_CFON) 572d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ctrl |= OCE_IS_STA_CFON; 573d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 574d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt *mbo_pos++ = OCE_ATTR_ID_CAPA_IND; 575d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt *mbo_pos++ = 1; 576d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt *mbo_pos++ = ctrl; 577d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 578d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 57957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pos += mbo_add_ie(pos, len, mbo, mbo_pos - mbo); 58057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 58157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return pos; 58257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt} 58357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 58457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 58557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtu8 hostapd_mbo_ie_len(struct hostapd_data *hapd) 58657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{ 587d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt u8 len; 588d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 589d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (!hapd->conf->mbo_enabled && !hapd->enable_oce) 59057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return 0; 59157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 59257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt /* 59357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * MBO IE header (6) + Capability Indication attribute (3) + 59457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * Association Disallowed attribute (3) = 12 59557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt */ 596d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt len = 6; 597d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (hapd->conf->mbo_enabled) 598d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt len += 3 + (hapd->mbo_assoc_disallow ? 3 : 0); 599d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 600d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt /* OCE capability indication attribute (3) */ 601d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (hapd->enable_oce & (OCE_AP | OCE_STA_CFON)) 602d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt len += 3; 603d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 604d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt return len; 60557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt} 60657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 60757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt#endif /* CONFIG_MBO */ 6089c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 6099c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 6109c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidtvoid ap_copy_sta_supp_op_classes(struct sta_info *sta, 6119c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt const u8 *supp_op_classes, 6129c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt size_t supp_op_classes_len) 6139c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt{ 6149c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt if (!supp_op_classes) 6159c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt return; 6169c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt os_free(sta->supp_op_classes); 6179c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt sta->supp_op_classes = os_malloc(1 + supp_op_classes_len); 6189c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt if (!sta->supp_op_classes) 6199c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt return; 6209c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 6219c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt sta->supp_op_classes[0] = supp_op_classes_len; 6229c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt os_memcpy(sta->supp_op_classes + 1, supp_op_classes, 6239c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt supp_op_classes_len); 6249c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt} 6259839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt 6269839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt 6279839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidtu8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid) 6289839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt{ 6299839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt u8 *pos = eid; 6309839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt#ifdef CONFIG_FILS 6319839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt u8 *len; 6329839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt u16 fils_info = 0; 633293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt size_t realms; 634293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt struct fils_realm *realm; 6359839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt 6369839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if (!(hapd->conf->wpa & WPA_PROTO_RSN) || 6379839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) 6389839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt return pos; 6399839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt 640293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt realms = dl_list_len(&hapd->conf->fils_realms); 641293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (realms > 7) 642293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt realms = 7; /* 3 bit count field limits this to max 7 */ 643293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 6449839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt *pos++ = WLAN_EID_FILS_INDICATION; 6459839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt len = pos++; 6469839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt /* TODO: B0..B2: Number of Public Key Identifiers */ 6479839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if (hapd->conf->erp_domain) { 6489839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt /* B3..B5: Number of Realm Identifiers */ 649293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt fils_info |= realms << 3; 6509839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt } 6519839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt /* TODO: B6: FILS IP Address Configuration */ 6529839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if (hapd->conf->fils_cache_id_set) 6539839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt fils_info |= BIT(7); 6549839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) 6559839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt fils_info |= BIT(8); /* HESSID Included */ 6569839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt /* FILS Shared Key Authentication without PFS Supported */ 6579839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt fils_info |= BIT(9); 658d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (hapd->conf->fils_dh_group) { 659d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt /* FILS Shared Key Authentication with PFS Supported */ 660d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt fils_info |= BIT(10); 661d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 6629839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt /* TODO: B11: FILS Public Key Authentication Supported */ 6639839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt /* B12..B15: Reserved */ 6649839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt WPA_PUT_LE16(pos, fils_info); 6659839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt pos += 2; 6669839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if (hapd->conf->fils_cache_id_set) { 6679839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt os_memcpy(pos, hapd->conf->fils_cache_id, FILS_CACHE_ID_LEN); 6689839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt pos += FILS_CACHE_ID_LEN; 6699839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt } 6709839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) { 6719839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); 6729839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt pos += ETH_ALEN; 6739839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt } 6749839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt 675293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt dl_list_for_each(realm, &hapd->conf->fils_realms, struct fils_realm, 676293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt list) { 677293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (realms == 0) 678293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt break; 679293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt realms--; 680293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt os_memcpy(pos, realm->hash, 2); 6819839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt pos += 2; 6829839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt } 6839839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt *len = pos - len - 1; 6849839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt#endif /* CONFIG_FILS */ 6859839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt 6869839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt return pos; 6879839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt} 688