18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant - TDLS 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2010-2011, Atheros Communications 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/os.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 15d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "common/ieee802_11_common.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa_ie.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa_i.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "drivers/driver.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "l2_packet/l2_packet.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_LONG_FRAME BIT(0) 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_ALT_RSN_IE BIT(1) 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_DIFF_BSSID BIT(2) 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_SHORT_LIFETIME BIT(3) 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_WRONG_LIFETIME_RESP BIT(4) 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_WRONG_LIFETIME_CONF BIT(5) 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_LONG_LIFETIME BIT(6) 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_CONCURRENT_INIT BIT(7) 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_NO_TPK_EXPIRATION BIT(8) 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_DECLINE_RESP BIT(9) 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_IGNORE_AP_PROHIBIT BIT(10) 3721de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#define TDLS_TESTING_WRONG_MIC BIT(11) 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int tdls_testing = 0; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TPK_LIFETIME 43200 /* 12 hours */ 42f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt#define TPK_M1_RETRY_COUNT 3 43f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt#define TPK_M1_TIMEOUT 5000 /* in milliseconds */ 44f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt#define TPK_M2_RETRY_COUNT 10 45f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt#define TPK_M2_TIMEOUT 500 /* in milliseconds */ 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_MIC_LEN 16 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TIMEOUT_LEN 4 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_ftie { 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_type; /* FTIE */ 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_len; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic_ctrl[2]; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[TDLS_MIC_LEN]; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 Anonce[WPA_NONCE_LEN]; /* Responder Nonce in TDLS */ 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 Snonce[WPA_NONCE_LEN]; /* Initiator Nonce in TDLS */ 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* followed by optional elements */ 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_timeoutie { 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_type; /* Timeout IE */ 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_len; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 interval_type; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 value[TDLS_TIMEOUT_LEN]; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_lnkid { 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_type; /* Link Identifier IE */ 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_len; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 bssid[ETH_ALEN]; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 init_sta[ETH_ALEN]; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 resp_sta[ETH_ALEN]; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* TDLS frame headers as per IEEE Std 802.11z-2010 */ 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_frame { 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 payloadtype; /* IEEE80211_TDLS_RFTYPE */ 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 category; /* Category */ 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 action; /* Action (enum tdls_frame_type) */ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs); 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer); 86d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Duttstatic void wpa_tdls_disable_peer_link(struct wpa_sm *sm, 87d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt struct wpa_tdls_peer *peer); 88b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidtstatic int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr, 89b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt u16 reason_code); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_MAX_IE_LEN 80 931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define IEEE80211_MAX_SUPP_RATES 32 941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_peer { 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *next; 978da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt unsigned int reconfig_key:1; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int initiator; /* whether this end was initiator for TDLS setup */ 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 addr[ETH_ALEN]; /* other end MAC address */ 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */ 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rnonce[WPA_NONCE_LEN]; /* Responder Nonce */ 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsnie_i[TDLS_MAX_IE_LEN]; /* Initiator RSN IE */ 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rsnie_i_len; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsnie_p[TDLS_MAX_IE_LEN]; /* Peer RSN IE */ 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rsnie_p_len; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; /* Selected cipher (WPA_CIPHER_*) */ 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dtoken; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tpk { 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 kck[16]; /* TPK-KCK */ 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */ 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } tpk; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tpk_set; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tpk_success; 11673b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt int tpk_in_progress; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tpk_timer { 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dest[ETH_ALEN]; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int count; /* Retry Count */ 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int timer; /* Timeout in milliseconds */ 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 action_code; /* TDLS frame type */ 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dialog_token; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status_code; 125df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt u32 peer_capab; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int buf_len; /* length of TPK message for retransmission */ 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; /* buffer for TPK message */ 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } sm_tmr; 1291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 capability; 1311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; 1331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t supp_rates_len; 134f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 135f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct ieee80211_ht_capabilities *ht_capabilities; 13633e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt struct ieee80211_vht_capabilities *vht_capabilities; 137f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 138f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt u8 qos_info; 139f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 14051b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt u16 aid; 14151b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt 142f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt u8 *ext_capab; 143f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt size_t ext_capab_len; 144344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 145344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt u8 *supp_channels; 146344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt size_t supp_channels_len; 147344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 148344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt u8 *supp_oper_classes; 149344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt size_t supp_oper_classes_len; 150df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 151df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt u8 wmm_capable; 1526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* channel switch currently enabled */ 1546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int chan_switch_enabled; 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_get_privacy(struct wpa_sm *sm) 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Get info needed from supplicant to check if the current BSS supports 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * security. Other than OPEN mode, rest are considered secured 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WEP/WPA/WPA2 hence TDLS frames are processed for TPK handshake. 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->pairwise_cipher != WPA_CIPHER_NONE; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len) 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ie, ie_len); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos + ie_len; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_del_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, WPA_ALG_NONE, peer->addr, 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, 0, NULL, 0, NULL, 0) < 0) { 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: Failed to delete TPK-TK from " 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the driver"); 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 key_len; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsc[6]; 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg alg; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, 6); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (peer->cipher) { 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_CCMP: 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alg = WPA_ALG_CCMP; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = 16; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_NONE: 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Pairwise Cipher Suite: " 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "NONE - do not use pairwise keys"); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: Unsupported pairwise cipher %d", 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_cipher); 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1, 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) { 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the " 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver"); 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst, 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 action_code, u8 dialog_token, 224df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt u16 status_code, u32 peer_capab, 2259ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt int initiator, const u8 *buf, size_t len) 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token, 2289ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt status_code, peer_capab, initiator, buf, 2299ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt len); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code, 234df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt u8 dialog_token, u16 status_code, u32 peer_capab, 2359ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt int initiator, const u8 *msg, size_t msg_len) 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u " 2409ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt "dialog_token=%u status_code=%u peer_capab=%u initiator=%d " 2419ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt "msg_len=%u", 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(dest), action_code, dialog_token, status_code, 2439ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt peer_capab, initiator, (unsigned int) msg_len); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token, 2469ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt status_code, peer_capab, initiator, msg, 2479ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt msg_len)) { 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to send message " 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(action_code=%u)", action_code); 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (action_code == WLAN_TDLS_SETUP_CONFIRM || 2541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt action_code == WLAN_TDLS_TEARDOWN || 2551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt action_code == WLAN_TDLS_DISCOVERY_REQUEST || 2561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt action_code == WLAN_TDLS_DISCOVERY_RESPONSE) 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; /* No retries */ 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, dest, ETH_ALEN) == 0) 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching entry found for " 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "retry " MACSTR, MAC2STR(dest)); 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 272f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt if (action_code == WLAN_TDLS_SETUP_RESPONSE) { 273f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt peer->sm_tmr.count = TPK_M2_RETRY_COUNT; 274f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt peer->sm_tmr.timer = TPK_M2_TIMEOUT; 275f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt } else { 276f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt peer->sm_tmr.count = TPK_M1_RETRY_COUNT; 277f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt peer->sm_tmr.timer = TPK_M1_TIMEOUT; 278f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt } 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Copy message to resend on timeout */ 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->sm_tmr.dest, dest, ETH_ALEN); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code = action_code; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.dialog_token = dialog_token; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.status_code = status_code; 285df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer->sm_tmr.peer_capab = peer_capab; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf_len = msg_len; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peer->sm_tmr.buf); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf = os_malloc(msg_len); 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->sm_tmr.buf == NULL) 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->sm_tmr.buf, msg, msg_len); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Retry timeout registered " 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(action_code=%u)", action_code); 295f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt eloop_register_timeout(peer->sm_tmr.timer / 1000, 296f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt (peer->sm_tmr.timer % 1000) * 1000, 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_retry_timeout, sm, peer); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpa_tdls_do_teardown(struct wpa_sm *sm, struct wpa_tdls_peer *peer, 3036a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt u16 reason_code) 3041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret; 3061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3076a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt ret = wpa_tdls_send_teardown(sm, peer->addr, reason_code); 3086a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt /* disable the link after teardown was sent */ 309d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 3101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 3121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx) 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer = timeout_ctx; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->sm_tmr.count) { 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.count--; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Retrying sending of message " 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(action_code=%u)", 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code); 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->sm_tmr.buf == NULL) { 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No retry buffer available " 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for action_code=%u", 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* resend TPK Handshake Message to Peer */ 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_send_tpk_msg(sm, peer->sm_tmr.dest, 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code, 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.dialog_token, 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.status_code, 342df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer->sm_tmr.peer_capab, 3439ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt peer->initiator, 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf, 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf_len)) { 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to retry " 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "transmission"); 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 351f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt eloop_register_timeout(peer->sm_tmr.timer / 1000, 352f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt (peer->sm_tmr.timer % 1000) * 1000, 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_retry_timeout, sm, peer); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending Teardown Request"); 3581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_tdls_do_teardown(sm, peer, 3596a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_tpk_retry_timeout_cancel(struct wpa_sm *sm, 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer, 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 action_code) 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (action_code == peer->sm_tmr.action_code) { 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Retry timeout cancelled for " 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "action_code=%u", action_code); 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Cancel Timeout registered */ 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* free all resources meant for retry */ 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peer->sm_tmr.buf); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf = NULL; 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.count = 0; 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.timer = 0; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf_len = 0; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code = 0xff; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Error in cancelling retry timeout " 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Unknown action_code=%u)", action_code); 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_generate_tpk(struct wpa_tdls_peer *peer, 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *own_addr, const u8 *bssid) 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 key_input[SHA256_MAC_LEN]; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nonce[2]; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 data[3 * ETH_ALEN]; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IEEE Std 802.11z-2010 8.5.9.1: 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce)) 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = WPA_NONCE_LEN; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = WPA_NONCE_LEN; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->inonce, peer->rnonce, WPA_NONCE_LEN) < 0) { 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonce[0] = peer->inonce; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonce[1] = peer->rnonce; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonce[0] = peer->rnonce; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonce[1] = peer->inonce; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: min(Nonce)", nonce[0], WPA_NONCE_LEN); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: max(Nonce)", nonce[1], WPA_NONCE_LEN); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(2, nonce, len, key_input); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-Key-Input", 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_input, SHA256_MAC_LEN); 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TPK-Key-Data = KDF-N_KEY(TPK-Key-Input, "TDLS PMK", 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID || N_KEY) 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: is N_KEY really included in KDF Context and if so, in which 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * presentation format (little endian 16-bit?) is it used? It gets 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * added by the KDF anyway.. 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(own_addr, peer->addr, ETH_ALEN) < 0) { 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data, own_addr, ETH_ALEN); 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + ETH_ALEN, peer->addr, ETH_ALEN); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data, peer->addr, ETH_ALEN); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + ETH_ALEN, own_addr, ETH_ALEN); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: KDF Context", data, sizeof(data)); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data), 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &peer->tpk, sizeof(peer->tpk)); 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-KCK", 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk.kck, sizeof(peer->tpk.kck)); 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-TK", 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk.tk, sizeof(peer->tpk.tk)); 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk_set = 1; 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_ftie_mic - Calculate TDLS FTIE MIC 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kck: TPK-KCK 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @lnkid: Pointer to the beginning of Link Identifier IE 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @rsnie: Pointer to the beginning of RSN IE used for handshake 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @timeoutie: Pointer to the beginning of Timeout IE used for handshake 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ftie: Pointer to the beginning of FT IE 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mic: Pointer for writing MIC 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Calculate MIC for TDLS frame. 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_ftie_mic(const u8 *kck, u8 trans_seq, const u8 *lnkid, 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *rsnie, const u8 *timeoutie, 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ftie, u8 *mic) 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *_ftie; 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_tdls_lnkid *_lnkid; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len = 2 * ETH_ALEN + 1 + 2 + lnkid[1] + 2 + rsnie[1] + 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + timeoutie[1] + 2 + ftie[1]; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(len); 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!buf) { 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation"); 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _lnkid = (const struct wpa_tdls_lnkid *) lnkid; 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1) TDLS initiator STA MAC address */ 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, _lnkid->init_sta, ETH_ALEN); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2) TDLS responder STA MAC address */ 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, _lnkid->resp_sta, ETH_ALEN); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3) Transaction Sequence number */ 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = trans_seq; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4) Link Identifier IE */ 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, lnkid, 2 + lnkid[1]); 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + lnkid[1]; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5) RSN IE */ 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, rsnie, 2 + rsnie[1]); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + rsnie[1]; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6) Timeout Interval IE */ 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, timeoutie, 2 + timeoutie[1]); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + timeoutie[1]; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7) FTIE, with the MIC field of the FTIE set to 0 */ 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ftie, 2 + ftie[1]); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ftie = (struct wpa_tdls_ftie *) pos; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(_ftie->mic, 0, TDLS_MIC_LEN); 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + ftie[1]; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf); 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16); 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = omac1_aes_128(kck, buf, pos - buf, mic); 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16); 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_key_mic_teardown - Calculate TDLS FTIE MIC for Teardown frame 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kck: TPK-KCK 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @trans_seq: Transaction Sequence Number (4 - Teardown) 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @rcode: Reason code for Teardown 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dtoken: Dialog Token used for that particular link 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @lnkid: Pointer to the beginning of Link Identifier IE 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ftie: Pointer to the beginning of FT IE 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mic: Pointer for writing MIC 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Calculate MIC for TDLS frame. 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_key_mic_teardown(const u8 *kck, u8 trans_seq, u16 rcode, 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dtoken, const u8 *lnkid, 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ftie, u8 *mic) 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *_ftie; 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lnkid == NULL) 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = 2 + lnkid[1] + sizeof(rcode) + sizeof(dtoken) + 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(trans_seq) + 2 + ftie[1]; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(len); 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!buf) { 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation"); 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1) Link Identifier IE */ 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, lnkid, 2 + lnkid[1]); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + lnkid[1]; 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2) Reason Code */ 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, rcode); 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += sizeof(rcode); 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3) Dialog token */ 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = dtoken; 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4) Transaction Sequence number */ 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = trans_seq; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7) FTIE, with the MIC field of the FTIE set to 0 */ 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ftie, 2 + ftie[1]); 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ftie = (struct wpa_tdls_ftie *) pos; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(_ftie->mic, 0, TDLS_MIC_LEN); 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + ftie[1]; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf); 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16); 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = omac1_aes_128(kck, buf, pos - buf, mic); 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16); 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_verify_tdls_mic(u8 trans_seq, 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer, 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *lnkid, const u8 *timeoutie, 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_tdls_ftie *ftie) 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[16]; 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->tpk_set) { 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_ftie_mic(peer->tpk.kck, trans_seq, lnkid, 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p, timeoutie, (u8 *) ftie, 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mic); 575c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(mic, ftie->mic, 16) != 0) { 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Invalid MIC in FTIE - " 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Received MIC", 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->mic, 16); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Calculated MIC", 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mic, 16); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: Could not verify TDLS MIC, " 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK not set - dropping packet"); 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_verify_tdls_mic_teardown( 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 trans_seq, u16 rcode, u8 dtoken, struct wpa_tdls_peer *peer, 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *lnkid, const struct wpa_tdls_ftie *ftie) 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[16]; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->tpk_set) { 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_key_mic_teardown(peer->tpk.kck, trans_seq, rcode, 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dtoken, lnkid, (u8 *) ftie, mic); 602c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(mic, ftie->mic, 16) != 0) { 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Invalid MIC in Teardown - " 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Could not verify TDLS Teardown " 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "MIC, TPK not set - dropping packet"); 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_tpk_timeout(void *eloop_ctx, void *timeout_ctx) 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer = timeout_ctx; 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * On TPK lifetime expiration, we have an option of either tearing down 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the direct link or trying to re-initiate it. The selection of what 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to do is not strictly speaking controlled by our role in the expired 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * link, but for now, use that to select whether to renew or tear down 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the link. 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->initiator) { 630d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt u8 addr[ETH_ALEN]; 631d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " - try to renew", MAC2STR(peer->addr)); 634d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt /* cache the peer address before do_teardown */ 635d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt os_memcpy(addr, peer->addr, ETH_ALEN); 636d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_tdls_do_teardown(sm, peer, 637d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 638d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_tdls_start(sm, addr); 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " - tear down", MAC2STR(peer->addr)); 6421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_tdls_do_teardown(sm, peer, 6436a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidtstatic void wpa_tdls_peer_remove_from_list(struct wpa_sm *sm, 649d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt struct wpa_tdls_peer *peer) 650d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt{ 651d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt struct wpa_tdls_peer *cur, *prev; 652d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 653d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt cur = sm->tdls; 654d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt prev = NULL; 655d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt while (cur && cur != peer) { 656d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt prev = cur; 657d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt cur = cur->next; 658d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt } 659d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 660d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (cur != peer) { 661d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt wpa_printf(MSG_ERROR, "TDLS: Could not find peer " MACSTR 662d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt " to remove it from the list", 663d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt MAC2STR(peer->addr)); 664d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt return; 665d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt } 666d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 667d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (prev) 668d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt prev->next = peer->next; 669d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt else 670d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt sm->tdls = peer->next; 671d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt} 672d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 673d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 674d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidtstatic void wpa_tdls_peer_clear(struct wpa_sm *sm, struct wpa_tdls_peer *peer) 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Clear state for peer " MACSTR, 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer->addr)); 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 6808da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt peer->reconfig_key = 0; 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->initiator = 0; 68273b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt peer->tpk_in_progress = 0; 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peer->sm_tmr.buf); 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf = NULL; 685f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_free(peer->ht_capabilities); 686f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->ht_capabilities = NULL; 68733e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt os_free(peer->vht_capabilities); 68833e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt peer->vht_capabilities = NULL; 689f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_free(peer->ext_capab); 690f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->ext_capab = NULL; 691344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt os_free(peer->supp_channels); 692344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_channels = NULL; 693344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt os_free(peer->supp_oper_classes); 694344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes = NULL; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = peer->rsnie_p_len = 0; 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = 0; 697df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer->qos_info = 0; 698df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer->wmm_capable = 0; 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk_set = peer->tpk_success = 0; 7006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt peer->chan_switch_enabled = 0; 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&peer->tpk, 0, sizeof(peer->tpk)); 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(peer->inonce, 0, WPA_NONCE_LEN); 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(peer->rnonce, 0, WPA_NONCE_LEN); 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 707d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidtstatic void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer) 708d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt{ 709d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt wpa_tdls_peer_clear(sm, peer); 710d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt wpa_tdls_peer_remove_from_list(sm, peer); 711d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt os_free(peer); 712d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt} 713d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 714d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_linkid(struct wpa_sm *sm, struct wpa_tdls_peer *peer, 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid) 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid->ie_type = WLAN_EID_LINK_ID; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid->ie_len = 3 * ETH_ALEN; 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->bssid, sm->bssid, ETH_ALEN); 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->initiator) { 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->init_sta, sm->own_addr, ETH_ALEN); 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->resp_sta, peer->addr, ETH_ALEN); 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->init_sta, peer->addr, ETH_ALEN); 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->resp_sta, sm->own_addr, ETH_ALEN); 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 731b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidtstatic int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr, 732b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt u16 reason_code) 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid lnkid; 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dialog_token; 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos; 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ielen; 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find the node and free from the list */ 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching entry found for " 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Teardown " MACSTR, MAC2STR(addr)); 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Cancel active channel switch before teardown */ 7576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (peer->chan_switch_enabled) { 7586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: First returning link with " MACSTR 7596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt " to base channel", MAC2STR(addr)); 7606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_sm_tdls_disable_channel_switch(sm, peer->addr); 7616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dialog_token = peer->dtoken; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown for " MACSTR, 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(addr)); 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = 0; 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm) && peer->tpk_set && peer->tpk_success) { 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* To add FTIE for Teardown request and compute MIC */ 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen += sizeof(*ftie); 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen += 170; 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = os_zalloc(ielen + 1); 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rbuf; 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 78351b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success) 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ies; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) pos; 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Using the recent nonce which should be for CONFIRM frame */ 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN); 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (ftie + 1); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) { 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FTIE"); 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len += 170; 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 255; /* FTIE subelem */ 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 168; /* FTIE subelem length */ 8001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 168; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TDLS Teardown handshake", 8041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (u8 *) ftie, pos - (u8 *) ftie); 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* compute MIC before sending */ 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_linkid(sm, peer, &lnkid); 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_key_mic_teardown(peer->tpk.kck, 4, reason_code, 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dialog_token, (u8 *) &lnkid, (u8 *) ftie, 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->mic); 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_ies: 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: register for a Timeout handler, if Teardown is not received at 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the other end, then try again another time */ 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* request driver to send Teardown using this FTIE */ 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0, 8189ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt reason_code, 0, peer->initiator, rbuf, pos - rbuf); 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code) 8261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 8271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_tdls_peer *peer; 8281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 8301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 8311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 8331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 8341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 8351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 8361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (peer == NULL) { 8381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Could not find peer " MACSTR 8391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " for link Teardown", MAC2STR(addr)); 8401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 8411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 8421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!peer->tpk_success) { 8441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR 8451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " not connected - cannot Teardown link", MAC2STR(addr)); 8461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 8471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 8481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8496a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt return wpa_tdls_do_teardown(sm, peer, reason_code); 8501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 8511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 85338ffd8879e7990491033bf20568212e8c3472b48Sunil Duttstatic void wpa_tdls_disable_peer_link(struct wpa_sm *sm, 85438ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt struct wpa_tdls_peer *peer) 85538ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt{ 85638ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr); 85738ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt wpa_tdls_peer_free(sm, peer); 85838ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt} 85938ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt 86038ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt 86143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidtvoid wpa_tdls_disable_unreachable_link(struct wpa_sm *sm, const u8 *addr) 8621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 8631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_tdls_peer *peer; 8641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 8661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 8671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 8681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 8691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 87043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (!peer || !peer->tpk_success) { 87143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR 87243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt " not connected - cannot teardown unreachable link", 87343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt MAC2STR(addr)); 87443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt return; 87543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt } 87643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt 87743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (wpa_tdls_is_external_setup(sm)) { 87843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt /* 8796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Get us on the base channel, disable the link, send a 8806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * teardown packet through the AP, and then reset link data. 88143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt */ 8826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (peer->chan_switch_enabled) 8836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_sm_tdls_disable_channel_switch(sm, peer->addr); 88443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, addr); 88543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_tdls_send_teardown(sm, addr, 88643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE); 88743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_tdls_peer_free(sm, peer); 88843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt } else { 88938ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 89043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt } 8911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 8921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 894e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidtconst char * wpa_tdls_get_link_status(struct wpa_sm *sm, const u8 *addr) 895e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt{ 896e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt struct wpa_tdls_peer *peer; 897e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 898e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 899e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return "disabled"; 900e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 901e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 902e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 903e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt break; 904e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt } 905e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 906e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt if (peer == NULL) 907e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return "peer does not exist"; 908e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 909e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt if (!peer->tpk_success) 910e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return "peer not connected"; 911e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 912e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return "connected"; 913e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt} 914e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 915e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_recv_teardown(struct wpa_sm *sm, const u8 *src_addr, 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer = NULL; 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid; 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 reason_code; 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ielen; 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find the node and free from the list */ 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching entry found for " 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Teardown " MACSTR, MAC2STR(src_addr)); 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reason_code = WPA_GET_LE16(pos); 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown Request from " MACSTR 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (reason code %u)", MAC2STR(src_addr), reason_code); 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = len - (pos - buf); /* start of IE in buf */ 9497f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 9507f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt /* 9517f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * Don't reject the message if failing to parse IEs. The IEs we need are 9527f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * explicitly checked below. Some APs may add arbitrary padding to the 9537f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * end of short TDLS frames and that would look like invalid IEs. 9547f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt */ 9557f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) 9567f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, 9577f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "TDLS: Failed to parse IEs in Teardown - ignore as an interop workaround"); 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TDLS " 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Teardown"); 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success) 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ftie; 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) { 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No FTIE in TDLS Teardown"); 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) kde.ftie; 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process MIC check to see if TDLS Teardown is right */ 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_verify_tdls_mic_teardown(4, reason_code, 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->dtoken, peer, 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) lnkid, ftie) < 0) { 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: MIC failure for TDLS " 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Teardown Request from " MACSTR, MAC2STR(src_addr)); 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_ftie: 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request the driver to disable the direct link and clear associated 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * keys. 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 99038ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_send_error - To send suitable TDLS status response with 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * appropriate status code mentioning reason for error/failure. 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst - MAC addr of Peer station 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @tdls_action - TDLS frame type for which error code is sent 10009ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt * @initiator - was this end the initiator of the connection 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @status - status code mentioning reason 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst, 10059ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt u8 tdls_action, u8 dialog_token, int initiator, 10069ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt u16 status) 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (action=%u status=%u)", 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(dst), tdls_action, status); 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status, 10129ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 0, initiator, NULL, 0); 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct wpa_tdls_peer * 10174b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtwpa_tdls_add_peer(struct wpa_sm *sm, const u8 *addr, int *existing) 10181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 10191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_tdls_peer *peer; 10201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10214b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (existing) 10224b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt *existing = 0; 10234b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 10244b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) { 10254b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (existing) 10264b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt *existing = 1; 10274b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return peer; /* re-use existing entry */ 10284b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt } 10294b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt } 10304b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 10311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Creating peer entry for " MACSTR, 10321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(addr)); 10331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt peer = os_zalloc(sizeof(*peer)); 10351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (peer == NULL) 10361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 10371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(peer->addr, addr, ETH_ALEN); 10391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt peer->next = sm->tdls; 10401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->tdls = peer; 10411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return peer; 10431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 10441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_tpk_m1(struct wpa_sm *sm, 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer) 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie timeoutie; 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 rsn_capab; 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos, *count_pos; 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 count; 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 1056d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt int status; 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) { 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No security used on the link"); 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = 0; 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsnie; 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TPK Handshake Message 1: 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FTIE: ANonce=0, SNonce=initiator nonce MIC=0, DataKDs=(RSNIE_I, 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Timeout Interval IE)) 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Filling RSN IE */ 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) peer->rsnie_i; 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, RSN_VERSION); 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count_pos = pos; 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = 0; 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AES-CCMP is the default Encryption preferred for TDLS, so 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RSN IE is filled only with CCMP CIPHER 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: TKIP is not used to encrypt TDLS link. 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Regardless of the cipher used on the AP connection, select CCMP 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * here. 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(count_pos, count); 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 1); 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE); 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2; 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) { 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Use alternative RSN IE for " 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "testing"); 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, rsn_capab); 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) { 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Number of PMKIDs */ 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 0x00; 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 0x00; 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - peer->rsnie_i) - 2; 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = pos - peer->rsnie_i; 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake", 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i, peer->rsnie_i_len); 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsnie: 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 0; 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm)) 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) + 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wpa_tdls_timeoutie); 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm) && 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (tdls_testing & TDLS_TESTING_LONG_FRAME)) 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += 170; 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_DIFF_BSSID) 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += sizeof(struct wpa_tdls_lnkid); 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = os_zalloc(buf_len + 1); 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) { 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rbuf; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ies; 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator RSN IE */ 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len); 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) pos; 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_get_random(peer->inonce, WPA_NONCE_LEN)) { 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TDLS: Failed to get random data for initiator Nonce"); 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake", 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->inonce, WPA_NONCE_LEN); 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK Handshake M1", 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) ftie, sizeof(struct wpa_tdls_ftie)); 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (ftie + 1); 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) { 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FTIE"); 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len += 170; 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 255; /* FTIE subelem */ 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 168; /* FTIE subelem length */ 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 168; 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->lifetime = TPK_LIFETIME; 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_SHORT_LIFETIME) { 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use short TPK " 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "lifetime"); 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->lifetime = 301; 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_LIFETIME) { 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use long TPK " 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "lifetime"); 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->lifetime = 0xffffffff; 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(timeoutie), peer->lifetime); 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime); 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_ies: 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_DIFF_BSSID) { 1204092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos; 1205092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use incorrect BSSID in " 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Link Identifier"); 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_linkid(sm, peer, l); 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l->bssid[5] ^= 0x01; 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += sizeof(*l); 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Request / TPK " 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Handshake Message 1 (peer " MACSTR ")", 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer->addr)); 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST, 12199ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 1, 0, 0, peer->initiator, rbuf, pos - rbuf); 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1222d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt return status; 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_tpk_m2(struct wpa_sm *sm, 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, u8 dtoken, 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid, 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_tdls_peer *peer) 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos; 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie timeoutie; 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 1236d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt int status; 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 0; 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm)) { 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce), 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Lifetime */ 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) + 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wpa_tdls_timeoutie); 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += 170; 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = os_zalloc(buf_len + 1); 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rbuf; 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ies; 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE */ 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len); 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) pos; 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: ftie->mic_control to set 2-RESPONSE */ 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN); 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK M2", 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) ftie, sizeof(*ftie)); 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (ftie + 1); 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) { 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FTIE"); 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len += 170; 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 255; /* FTIE subelem */ 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 168; /* FTIE subelem length */ 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 168; 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = peer->lifetime; 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_RESP) { 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK " 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "lifetime in response"); 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime++; 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(timeoutie), lifetime); 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds from initiator", 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime); 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* compute MIC before sending */ 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_ftie_mic(peer->tpk.kck, 2, (u8 *) lnkid, peer->rsnie_p, 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &timeoutie, (u8 *) ftie, ftie->mic); 130021de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 130121de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt if (tdls_testing & TDLS_TESTING_WRONG_MIC) { 130221de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong MIC"); 130321de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt ftie->mic[0] ^= 0x01; 130421de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt } 130521de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_ies: 1308d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, 13099ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt dtoken, 0, 0, peer->initiator, rbuf, 13109ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt pos - rbuf); 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1313d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt return status; 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_tpk_m3(struct wpa_sm *sm, 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, u8 dtoken, 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid, 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_tdls_peer *peer) 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos; 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie timeoutie; 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 1327d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt int status; 1328df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt u32 peer_capab = 0; 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 0; 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm)) { 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce), 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Lifetime */ 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) + 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wpa_tdls_timeoutie); 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += 170; 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = os_zalloc(buf_len + 1); 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rbuf; 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ies; 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE */ 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len); 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) pos; 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /*TODO: ftie->mic_control to set 3-CONFIRM */ 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN); 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (ftie + 1); 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) { 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FTIE"); 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len += 170; 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 255; /* FTIE subelem */ 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 168; /* FTIE subelem length */ 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 168; 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = peer->lifetime; 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_CONF) { 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK " 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "lifetime in confirm"); 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime++; 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(timeoutie), lifetime); 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime); 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* compute MIC before sending */ 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_ftie_mic(peer->tpk.kck, 3, (u8 *) lnkid, peer->rsnie_p, 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &timeoutie, (u8 *) ftie, ftie->mic); 139021de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 139121de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt if (tdls_testing & TDLS_TESTING_WRONG_MIC) { 139221de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong MIC"); 139321de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt ftie->mic[0] ^= 0x01; 139421de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt } 139521de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1397b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidtskip_ies: 1398b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 1399df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (peer->vht_capabilities) 1400df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer_capab |= TDLS_PEER_VHT; 1401b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt if (peer->ht_capabilities) 1402df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer_capab |= TDLS_PEER_HT; 1403b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt if (peer->wmm_capable) 1404df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer_capab |= TDLS_PEER_WMM; 1405df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1406d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, 14079ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt dtoken, 0, peer_capab, peer->initiator, 14089ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt rbuf, pos - rbuf); 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1411d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt return status; 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpa_tdls_send_discovery_response(struct wpa_sm *sm, 14161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_tdls_peer *peer, 14171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 dialog_token) 14181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1419661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt size_t buf_len = 0; 1420661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt struct wpa_tdls_timeoutie timeoutie; 1421661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt u16 rsn_capab; 1422661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt u8 *rbuf, *pos, *count_pos; 1423661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt u16 count; 1424661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt struct rsn_ie_hdr *hdr; 1425661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt int status; 1426661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 14271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Discovery Response " 14281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "(peer " MACSTR ")", MAC2STR(peer->addr)); 1429661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 1430661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt goto skip_rsn_ies; 1431661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 1432661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt /* Filling RSN IE */ 1433661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt hdr = (struct rsn_ie_hdr *) peer->rsnie_i; 1434661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 1435661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt WPA_PUT_LE16(hdr->version, RSN_VERSION); 1436661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos = (u8 *) (hdr + 1); 1437661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); 1438661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1439661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt count_pos = pos; 1440661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos += 2; 1441661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt count = 0; 14421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1443661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt /* 1444661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt * AES-CCMP is the default encryption preferred for TDLS, so 1445661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt * RSN IE is filled only with CCMP cipher suite. 1446661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt * Note: TKIP is not used to encrypt TDLS link. 1447661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt * 1448661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt * Regardless of the cipher used on the AP connection, select CCMP 1449661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt * here. 1450661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt */ 1451661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 1452661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1453661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt count++; 1454661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt WPA_PUT_LE16(count_pos, count); 1455661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt WPA_PUT_LE16(pos, 1); 1456661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos += 2; 1457661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE); 1458661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1459661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 1460661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; 1461661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2; 1462661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt WPA_PUT_LE16(pos, rsn_capab); 1463661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos += 2; 1464661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt hdr->len = (pos - (u8 *) hdr) - 2; 1465661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt peer->rsnie_i_len = pos - peer->rsnie_i; 1466661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 1467661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for Discovery Response", 1468661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt (u8 *) hdr, hdr->len + 2); 1469661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidtskip_rsn_ies: 1470661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt buf_len = 0; 1471661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (wpa_tdls_get_privacy(sm)) { 1472661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt /* Peer RSN IE, Lifetime */ 1473661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt buf_len += peer->rsnie_i_len + 1474661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt sizeof(struct wpa_tdls_timeoutie); 1475661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 1476661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt rbuf = os_zalloc(buf_len + 1); 1477661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (rbuf == NULL) { 1478661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 1479661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return -1; 1480661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 1481661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos = rbuf; 1482661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 1483661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 1484661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt goto skip_ies; 1485661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt /* Initiator RSN IE */ 1486661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len); 1487661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt /* Lifetime */ 1488661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt peer->lifetime = TPK_LIFETIME; 1489661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, 1490661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt sizeof(timeoutie), peer->lifetime); 1491661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime); 1492661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidtskip_ies: 1493661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE, 14949ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt dialog_token, 0, 0, 0, rbuf, pos - rbuf); 1495661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt os_free(rbuf); 1496661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 1497661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return status; 14981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 14991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int 15021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtwpa_tdls_process_discovery_request(struct wpa_sm *sm, const u8 *addr, 15031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *buf, size_t len) 15041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 15051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_eapol_ie_parse kde; 15061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpa_tdls_lnkid *lnkid; 15071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_tdls_peer *peer; 15081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t min_req_len = sizeof(struct wpa_tdls_frame) + 15091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1 /* dialog token */ + sizeof(struct wpa_tdls_lnkid); 15101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 dialog_token; 15111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from " MACSTR, 15131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(addr)); 15141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < min_req_len) { 15161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS Discovery Request is too short: " 15171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "%d", (int) len); 15181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 15191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 15201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dialog_token = buf[sizeof(struct wpa_tdls_frame)]; 15221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15230c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt /* 15240c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt * Some APs will tack on a weird IE to the end of a TDLS 15250c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt * discovery request packet. This needn't fail the response, 15260c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt * since the required IE are verified separately. 15270c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt */ 15281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_supplicant_parse_ies(buf + sizeof(struct wpa_tdls_frame) + 1, 15291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len - (sizeof(struct wpa_tdls_frame) + 1), 15300c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt &kde) < 0) { 15310c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt wpa_printf(MSG_DEBUG, 15320c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt "TDLS: Failed to parse IEs in Discovery Request - ignore as an interop workaround"); 15330c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt } 15341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!kde.lnkid) { 15361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Link ID not found in Discovery " 15371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Request"); 15381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 15391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 15401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt lnkid = (const struct wpa_tdls_lnkid *) kde.lnkid; 15421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { 15441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from different " 15451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " BSS " MACSTR, MAC2STR(lnkid->bssid)); 15461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 15471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 15481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15494b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt peer = wpa_tdls_add_peer(sm, addr, NULL); 15501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (peer == NULL) 15511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 15521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return wpa_tdls_send_discovery_response(sm, peer, dialog_token); 15541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 15551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr) 15581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 15591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 15601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 15611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer " 15631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(addr)); 15641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST, 15659ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 1, 0, 0, 1, NULL, 0); 15661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 15671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int copy_supp_rates(const struct wpa_eapol_ie_parse *kde, 15701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_tdls_peer *peer) 15711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 15721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!kde->supp_rates) { 15731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No supported rates received"); 15741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 15751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1576a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt peer->supp_rates_len = merge_byte_arrays( 1577a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt peer->supp_rates, sizeof(peer->supp_rates), 1578a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt kde->supp_rates + 2, kde->supp_rates_len - 2, 157934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt kde->ext_supp_rates ? kde->ext_supp_rates + 2 : NULL, 158034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt kde->ext_supp_rates_len - 2); 15811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 15821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 15831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1585f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstatic int copy_peer_ht_capab(const struct wpa_eapol_ie_parse *kde, 1586f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpa_tdls_peer *peer) 1587f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 15889d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt if (!kde->ht_capabilities) { 1589f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No supported ht capabilities " 1590f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt "received"); 1591f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return 0; 1592f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1593f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1594f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (!peer->ht_capabilities) { 1595f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->ht_capabilities = 1596f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_zalloc(sizeof(struct ieee80211_ht_capabilities)); 1597f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (peer->ht_capabilities == NULL) 1598f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return -1; 1599f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1600f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1601f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_memcpy(peer->ht_capabilities, kde->ht_capabilities, 1602f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt sizeof(struct ieee80211_ht_capabilities)); 1603f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Peer HT capabilities", 1604f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt (u8 *) peer->ht_capabilities, 1605f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt sizeof(struct ieee80211_ht_capabilities)); 1606f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1607f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return 0; 1608f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt} 1609f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1610f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 161133e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidtstatic int copy_peer_vht_capab(const struct wpa_eapol_ie_parse *kde, 161233e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt struct wpa_tdls_peer *peer) 161333e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt{ 16149d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt if (!kde->vht_capabilities) { 161533e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No supported vht capabilities " 161633e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt "received"); 161733e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt return 0; 161833e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt } 161933e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 162033e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt if (!peer->vht_capabilities) { 162133e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt peer->vht_capabilities = 162233e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt os_zalloc(sizeof(struct ieee80211_vht_capabilities)); 162333e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt if (peer->vht_capabilities == NULL) 162433e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt return -1; 162533e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt } 162633e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 162733e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt os_memcpy(peer->vht_capabilities, kde->vht_capabilities, 162833e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt sizeof(struct ieee80211_vht_capabilities)); 162933e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Peer VHT capabilities", 163033e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt (u8 *) peer->vht_capabilities, 163133e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt sizeof(struct ieee80211_vht_capabilities)); 163233e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 163333e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt return 0; 163433e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt} 163533e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 163633e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 1637f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstatic int copy_peer_ext_capab(const struct wpa_eapol_ie_parse *kde, 1638f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpa_tdls_peer *peer) 1639f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 1640f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (!kde->ext_capab) { 1641f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No extended capabilities " 1642f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt "received"); 1643f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return 0; 1644f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1645f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1646f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (!peer->ext_capab || peer->ext_capab_len < kde->ext_capab_len - 2) { 1647f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt /* Need to allocate buffer to fit the new information */ 1648f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_free(peer->ext_capab); 1649f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->ext_capab = os_zalloc(kde->ext_capab_len - 2); 1650f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (peer->ext_capab == NULL) 1651f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return -1; 1652f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1653f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1654f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->ext_capab_len = kde->ext_capab_len - 2; 1655f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_memcpy(peer->ext_capab, kde->ext_capab + 2, peer->ext_capab_len); 1656f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1657f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return 0; 1658f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt} 1659f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1660f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1661b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidtstatic int copy_peer_wmm_capab(const struct wpa_eapol_ie_parse *kde, 1662b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt struct wpa_tdls_peer *peer) 1663b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt{ 1664b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt struct wmm_information_element *wmm; 1665b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 1666b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (!kde->wmm) { 1667b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No supported WMM capabilities received"); 1668b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return 0; 1669b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt } 1670b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 1671b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (kde->wmm_len < sizeof(struct wmm_information_element)) { 1672b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Invalid supported WMM capabilities received"); 1673b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return -1; 1674b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt } 1675b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 1676b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt wmm = (struct wmm_information_element *) kde->wmm; 1677b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt peer->qos_info = wmm->qos_info; 1678b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 1679df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer->wmm_capable = 1; 1680df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1681b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Peer WMM QOS Info 0x%x", peer->qos_info); 1682b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return 0; 1683b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt} 1684b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 1685b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 1686344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidtstatic int copy_peer_supp_channels(const struct wpa_eapol_ie_parse *kde, 1687344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt struct wpa_tdls_peer *peer) 1688344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt{ 1689344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (!kde->supp_channels) { 1690344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No supported channels received"); 1691344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt return 0; 1692344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt } 1693344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1694344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (!peer->supp_channels || 1695344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_channels_len < kde->supp_channels_len) { 1696344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt os_free(peer->supp_channels); 1697344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_channels = os_zalloc(kde->supp_channels_len); 1698344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (peer->supp_channels == NULL) 1699344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt return -1; 1700344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt } 1701344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1702344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_channels_len = kde->supp_channels_len; 1703344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1704344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt os_memcpy(peer->supp_channels, kde->supp_channels, 1705344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_channels_len); 1706344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Channels", 1707344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt (u8 *) peer->supp_channels, peer->supp_channels_len); 1708344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt return 0; 1709344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt} 1710344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1711344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1712344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidtstatic int copy_peer_supp_oper_classes(const struct wpa_eapol_ie_parse *kde, 1713344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt struct wpa_tdls_peer *peer) 1714344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt{ 1715344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (!kde->supp_oper_classes) { 1716344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No supported operating classes received"); 1717344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt return 0; 1718344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt } 1719344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1720344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (!peer->supp_oper_classes || 1721344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes_len < kde->supp_oper_classes_len) { 1722344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt os_free(peer->supp_oper_classes); 1723344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes = os_zalloc(kde->supp_oper_classes_len); 1724344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (peer->supp_oper_classes == NULL) 1725344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt return -1; 1726344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt } 1727344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1728344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes_len = kde->supp_oper_classes_len; 1729344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt os_memcpy(peer->supp_oper_classes, kde->supp_oper_classes, 1730344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes_len); 1731344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Operating Classes", 1732344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt (u8 *) peer->supp_oper_classes, 1733344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes_len); 1734344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt return 0; 1735344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt} 1736344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1737344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1738d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidtstatic int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer, 1739d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt int add) 1740d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt{ 1741d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt return wpa_sm_tdls_peer_addset(sm, peer->addr, add, peer->aid, 1742d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt peer->capability, 1743d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt peer->supp_rates, peer->supp_rates_len, 1744d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt peer->ht_capabilities, 1745d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt peer->vht_capabilities, 17469ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt peer->qos_info, peer->wmm_capable, 17479ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt peer->ext_capab, peer->ext_capab_len, 1748d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt peer->supp_channels, 1749d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt peer->supp_channels_len, 1750d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt peer->supp_oper_classes, 1751d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt peer->supp_oper_classes_len); 1752d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt} 1753d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 1754d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *cpos; 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie = NULL; 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie *timeoutie; 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid; 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime = 0; 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 rsn_capab; 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 rsn_ver; 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dtoken; 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ielen; 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status = WLAN_STATUS_UNSPECIFIED_FAILURE; 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tdls_prohibited = sm->tdls_prohibited; 17771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int existing_peer = 0; 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 3 + 3) 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cpos = buf; 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cpos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* driver had already verified the frame format */ 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dtoken = *cpos++; /* dialog token */ 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Dialog Token in TPK M1 %d", dtoken); 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17904b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt peer = wpa_tdls_add_peer(sm, src_addr, &existing_peer); 17914b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (peer == NULL) 17924b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt goto error; 17931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17940ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt /* If found, use existing entry instead of adding a new one; 17950ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * how to handle the case where both ends initiate at the 17960ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * same time? */ 17970ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt if (existing_peer) { 17980ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt if (peer->tpk_success) { 17990ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while " 18000ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt "direct link is enabled - tear down the " 18010ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt "old link first"); 1802d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr); 1803d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt wpa_tdls_peer_clear(sm, peer); 1804d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt } else if (peer->initiator) { 1805d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt /* 1806d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt * An entry is already present, so check if we already 1807d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt * sent a TDLS Setup Request. If so, compare MAC 1808d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt * addresses and let the STA with the lower MAC address 1809d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt * continue as the initiator. The other negotiation is 1810d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt * terminated. 1811d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt */ 18120ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt if (os_memcmp(sm->own_addr, src_addr, ETH_ALEN) < 0) { 18130ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Discard request " 18140ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt "from peer with higher address " 18150ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt MACSTR, MAC2STR(src_addr)); 18160ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt return -1; 18170ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt } else { 18180ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Accept request " 18190ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt "from peer with lower address " 18200ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt MACSTR " (terminate previously " 18210ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt "initiated negotiation", 18220ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt MAC2STR(src_addr)); 1823d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, 1824d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt peer->addr); 1825d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt wpa_tdls_peer_clear(sm, peer); 18260ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt } 18270ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt } 18280ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt } 18290ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt 18301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* capability information */ 18311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt peer->capability = WPA_GET_LE16(cpos); 18321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cpos += 2; 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = len - (cpos - buf); /* start of IE in buf */ 18357f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 18367f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt /* 18377f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * Don't reject the message if failing to parse IEs. The IEs we need are 18387f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * explicitly checked below. Some APs may add arbitrary padding to the 18397f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * end of short TDLS frames and that would look like invalid IEs. 18407f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt */ 18417f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (wpa_supplicant_parse_ies(cpos, ielen, &kde) < 0) 18427f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, 18437f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "TDLS: Failed to parse IEs in TPK M1 - ignore as an interop workaround"); 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { 18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in " 18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M1"); 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M1", 18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.lnkid, kde.lnkid_len); 18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: TPK M1 from diff BSS"); 1855661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt status = WLAN_STATUS_REQUEST_DECLINED; 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK M1 - TPK initiator " MACSTR, 18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(src_addr)); 18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (copy_supp_rates(&kde, peer) < 0) 18631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto error; 18641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1865f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (copy_peer_ht_capab(&kde, peer) < 0) 1866f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt goto error; 1867f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 186833e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt if (copy_peer_vht_capab(&kde, peer) < 0) 186933e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt goto error; 187033e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 1871f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (copy_peer_ext_capab(&kde, peer) < 0) 1872f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt goto error; 1873f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1874344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (copy_peer_supp_channels(&kde, peer) < 0) 1875344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt goto error; 1876344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1877344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (copy_peer_supp_oper_classes(&kde, peer) < 0) 1878344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt goto error; 1879344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1880f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->qos_info = kde.qosinfo; 1881f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1882b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt /* Overwrite with the qos_info obtained in WMM IE */ 1883b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (copy_peer_wmm_capab(&kde, peer) < 0) 1884b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt goto error; 1885b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 188651b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt peer->aid = kde.aid; 188751b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) { 18904b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt peer = wpa_tdls_add_peer(sm, src_addr, NULL); 18914b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (peer == NULL) 18924b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt goto error; 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of " 18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TDLS setup - send own request"); 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->initiator = 1; 18969ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, 18979ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0); 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_send_tpk_m1(sm, peer); 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) && 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tdls_prohibited) { 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition " 19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "on TDLS"); 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tdls_prohibited = 0; 19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_prohibited) { 19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: TDLS prohibited in this BSS"); 19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_REQUEST_DECLINED; 19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) { 19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie) { 19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M1 while " 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "security is disabled"); 19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_SECURITY_DISABLED; 19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsn; 19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) || 19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie == NULL) { 19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M1"); 19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_PARAMETERS; 19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) { 19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Too long Initiator RSN IE in " 19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M1"); 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { 19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M1"); 19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = ie.pairwise_cipher; 19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher & WPA_CIPHER_CCMP) { 19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link"); 19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WPA_CIPHER_CCMP; 19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M1"); 19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; 19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((ie.capabilities & 19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WPA_CAPABILITY_NO_PAIRWISE | WPA_CAPABILITY_PEERKEY_ENABLED)) != 19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_CAPABILITY_PEERKEY_ENABLED) { 19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Invalid RSN Capabilities in " 19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M1"); 19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSN_IE_CAPAB; 19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.key_lifetime == NULL) { 19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M1"); 19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; 19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime; 19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_LE32(timeoutie->value); 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", lifetime); 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime < 300) { 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Too short TPK lifetime"); 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsn: 19801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TDLS_TESTING 19811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) { 19821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_memcmp(sm->own_addr, peer->addr, ETH_ALEN) < 0) { 19831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 19841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * The request frame from us is going to win, so do not 19851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * replace information based on this request frame from 19861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * the peer. 19871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 19881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto skip_rsn_check; 19891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 19901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 19911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 19921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->initiator = 0; /* Need to check */ 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->dtoken = dtoken; 19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) { 19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = 0; 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = 0; 19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = WPA_CIPHER_NONE; 20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsn_check; 20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) kde.ftie; 20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->rsnie_i, kde.rsn_ie, kde.rsn_ie_len); 20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = kde.rsn_ie_len; 20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = cipher; 20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20086102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) { 20096102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt /* 20106102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt * There is no point in updating the RNonce for every obtained 20116102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt * TPK M1 frame (e.g., retransmission due to timeout) with the 20126102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt * same INonce (SNonce in FTIE). However, if the TPK M1 is 20136102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt * retransmitted with a different INonce, update the RNonce 20146102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt * since this is for a new TDLS session. 20156102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt */ 20166102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt wpa_printf(MSG_DEBUG, 20176102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt "TDLS: New TPK M1 INonce - generate new RNonce"); 20186102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt os_memcpy(peer->inonce, ftie->Snonce, WPA_NONCE_LEN); 20196102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt if (os_get_random(peer->rnonce, WPA_NONCE_LEN)) { 20206102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt wpa_msg(sm->ctx->ctx, MSG_WARNING, 20216102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt "TDLS: Failed to get random data for responder nonce"); 20226102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt goto error; 20236102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt } 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* get version info from RSNIE received from Peer */ 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) kde.rsn_ie; 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_ver = WPA_GET_LE16(hdr->version); 20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* use min(peer's version, out version) */ 20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_ver > RSN_VERSION) 20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_ver = RSN_VERSION; 20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) peer->rsnie_p; 20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, rsn_ver); 20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); 20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Include only the selected cipher in pairwise cipher suite */ 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 1); 20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher == WPA_CIPHER_CCMP) 20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 1); 20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE); 20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; 20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2; 20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, rsn_capab); 20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - peer->rsnie_p) - 2; 20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = pos - peer->rsnie_p; 20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* temp fix: validation of RSNIE later */ 20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->rsnie_p, peer->rsnie_i, peer->rsnie_i_len); 20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = peer->rsnie_i_len; 20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake", 20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p, peer->rsnie_p_len); 20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->lifetime = lifetime; 20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid); 20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsn_check: 20769ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 20779ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) 20789ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt goto skip_add_peer; 20799ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 20809ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 2081d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt /* add supported rates, capabilities, and qos_info to the TDLS peer */ 2082d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (wpa_tdls_addset_peer(sm, peer, 1) < 0) 208343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt goto error; 208443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt 20859ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 20869ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidtskip_add_peer: 20879ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 208873b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt peer->tpk_in_progress = 1; 20891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2"); 20911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer) < 0) { 2092d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr); 20931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto error; 20941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterror: 20999ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 0, 21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status); 210143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (peer) 210243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_tdls_peer_free(sm, peer); 21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21078da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidtstatic int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer) 21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk_success = 1; 211073b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt peer->tpk_in_progress = 0; 21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); 21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm)) { 21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime = peer->lifetime; 21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Start the initiator process a bit earlier to avoid race 21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * condition with the responder sending teardown request. 21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime > 3 && peer->initiator) 21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime -= 3; 21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(lifetime, 0, wpa_tdls_tpk_timeout, 21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, peer); 21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_NO_TPK_EXPIRATION) { 21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - disable TPK " 21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "expiration"); 21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); 21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 21318da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) { 21328da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Could not configure key to the " 21338da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt "driver"); 21348da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt return -1; 21358da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt } 21368da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt peer->reconfig_key = 0; 21378da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt 21388da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt return wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr); 21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr, 21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie *timeoutie; 21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid; 21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dtoken; 21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ielen; 21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status; 21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 2157292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt int ret = 0; 21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 " 21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Peer " MACSTR ")", MAC2STR(src_addr)); 21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) 21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching peer found for " 21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M2: " MACSTR, MAC2STR(src_addr)); 21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21700ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt if (!peer->initiator) { 21710ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt /* 21720ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * This may happen if both devices try to initiate TDLS at the 21730ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * same time and we accept the TPK M1 from the peer in 21740ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * wpa_tdls_process_tpk_m1() and clear our previous state. 21750ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt */ 21760ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_INFO, "TDLS: We were not the initiator, so " 21770ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt "ignore TPK M2 from " MACSTR, MAC2STR(src_addr)); 21780ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt return -1; 21790ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt } 21807d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt 21817d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt if (peer->tpk_success) { 21827d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Ignore incoming TPK M2 retry, from " 21837d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt MACSTR " as TPK M3 was already sent", 21847d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt MAC2STR(src_addr)); 21857d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt return 0; 21867d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt } 21877d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt 21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_REQUEST); 21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2190adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt if (len < 3 + 2 + 1) { 2191d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2193adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt } 2194adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt 21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; 21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WPA_GET_LE16(pos); 21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 /* status code */; 21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status != WLAN_STATUS_SUCCESS) { 22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Status code in TPK M2: %u", 22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status); 2203d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNSPECIFIED_FAILURE; 22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: need to verify dialog token matches here or in kernel */ 22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dtoken = *pos++; /* dialog token */ 22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Dialog Token in TPK M2 %d", dtoken); 22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2214adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt if (len < 3 + 2 + 1 + 2) { 2215d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2217adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt } 22181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 22191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* capability information */ 22201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt peer->capability = WPA_GET_LE16(pos); 22211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = len - (pos - buf); /* start of IE in buf */ 22247f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 22257f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt /* 22267f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * Don't reject the message if failing to parse IEs. The IEs we need are 22277f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * explicitly checked below. Some APs may add arbitrary padding to the 22287f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * end of short TDLS frames and that would look like invalid IEs. 22297f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt */ 22307f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (wpa_supplicant_parse_ies(pos, ielen, &kde) < 0) 22317f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, 22327f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "TDLS: Failed to parse IEs in TPK M2 - ignore as an interop workaround"); 22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_DECLINE_RESP) { 22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - decline response"); 22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_REQUEST_DECLINED; 22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { 22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in " 22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M2"); 22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M2", 22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.lnkid, kde.lnkid_len); 22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; 22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { 22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: TPK M2 from different BSS"); 22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_NOT_IN_SAME_BSS; 22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (copy_supp_rates(&kde, peer) < 0) 22581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto error; 22591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2260f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (copy_peer_ht_capab(&kde, peer) < 0) 2261f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt goto error; 2262f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 226333e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt if (copy_peer_vht_capab(&kde, peer) < 0) 226433e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt goto error; 226533e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 2266f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (copy_peer_ext_capab(&kde, peer) < 0) 2267f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt goto error; 2268f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2269344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (copy_peer_supp_channels(&kde, peer) < 0) 2270344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt goto error; 2271344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 2272344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (copy_peer_supp_oper_classes(&kde, peer) < 0) 2273344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt goto error; 2274344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 2275f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->qos_info = kde.qosinfo; 2276f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2277b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt /* Overwrite with the qos_info obtained in WMM IE */ 2278b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (copy_peer_wmm_capab(&kde, peer) < 0) 2279b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt goto error; 2280b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 228151b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt peer->aid = kde.aid; 228251b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt 22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) { 22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = 0; 22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = WPA_CIPHER_NONE; 22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsn; 22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) || 22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie == NULL) { 22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M2"); 22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_PARAMETERS; 22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2", 22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 229809f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) { 229909f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt wpa_printf(MSG_INFO, 230009f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt "TDLS: Too long Responder RSN IE in TPK M2"); 230109f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 230209f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt goto error; 230309f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt } 230409f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt 23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FIX: bitwise comparison of RSN IE is not the correct way of 23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * validation this. It can be different, but certain fields must 23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * match. Since we list only a single pairwise cipher in TPK M1, the 23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * memcmp is likely to work in most cases, though. 23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len != peer->rsnie_i_len || 23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(peer->rsnie_i, kde.rsn_ie, peer->rsnie_i_len) != 0) { 23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M2 does " 23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with RSN IE used in TPK M1"); 23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Sent in TPK M1", 23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i, peer->rsnie_i_len); 23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2", 23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { 23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M2"); 23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = ie.pairwise_cipher; 23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher == WPA_CIPHER_CCMP) { 23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link"); 23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WPA_CIPHER_CCMP; 23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M2"); 23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; 23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M2", 23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.ftie, sizeof(*ftie)); 23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) kde.ftie; 23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 234357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) { 23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M2 does " 23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with FTIE SNonce used in TPK M1"); 23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Silently discard the frame */ 23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Responder Nonce and RSN IE */ 23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN); 23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->rsnie_p, kde.rsn_ie, kde.rsn_ie_len); 23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = kde.rsn_ie_len; 23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = cipher; 23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.key_lifetime == NULL) { 23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M2"); 23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; 23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime; 23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_LE32(timeoutie->value); 23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M2", 23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime); 23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime != peer->lifetime) { 23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in " 23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M2 (expected %u)", lifetime, peer->lifetime); 23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; 23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid); 23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process MIC check to see if TPK M2 is right */ 23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_verify_tdls_mic(2, peer, (u8 *) lnkid, 23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) timeoutie, ftie) < 0) { 23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Discard the frame */ 23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_del_key(sm, peer); 238038ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23848da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt if (wpa_tdls_set_key(sm, peer) < 0) { 23858da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt /* 23868da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt * Some drivers may not be able to config the key prior to full 23878da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt * STA entry having been configured. 23888da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt */ 23898da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after " 23908da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt "STA entry is complete"); 23918da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt peer->reconfig_key = 1; 23928da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt } 23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsn: 23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->dtoken = dtoken; 23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2397d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt /* add supported rates, capabilities, and qos_info to the TDLS peer */ 2398d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (wpa_tdls_addset_peer(sm, peer, 0) < 0) 2399d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt goto error; 2400d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Confirm / " 24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK Handshake Message 3"); 2403d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer) < 0) 2404d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt goto error_no_msg; 24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2406292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt if (!peer->tpk_success) { 2407292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt /* 2408292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt * Enable Link only when tpk_success is 0, signifying that this 2409292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt * processing of TPK M2 frame is not because of a retransmission 2410292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt * during TDLS setup handshake. 2411292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt */ 2412292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt ret = wpa_tdls_enable_link(sm, peer); 2413292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt if (ret < 0) { 2414292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Could not enable link"); 2415292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt wpa_tdls_do_teardown( 2416292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt sm, peer, 2417292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 2418292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt } 24198da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt } 24208da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt return ret; 24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterror: 24239ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 1, 24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status); 2425d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidterror_no_msg: 2426d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_process_tpk_m3(struct wpa_sm *sm, const u8 *src_addr, 24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie *timeoutie; 24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid; 24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ielen; 24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status; 24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 2443292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt int ret = 0; 24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 " 24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Peer " MACSTR ")", MAC2STR(src_addr)); 24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) 24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching peer found for " 24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M3: " MACSTR, MAC2STR(src_addr)); 24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_RESPONSE); 24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 3 + 3) 2459adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; 24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WPA_GET_LE16(pos); 24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status != 0) { 24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Status code in TPK M3: %u", 24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status); 2468adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 /* status code */ + 1 /* dialog token */; 24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = len - (pos - buf); /* start of IE in buf */ 24730c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt 24740c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt /* 24750c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt * Don't reject the message if failing to parse IEs. The IEs we need are 24760c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt * explicitly checked below. Some APs piggy-back broken IEs to the end 24770c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt * of a TDLS Confirm packet, which will fail the link if we don't ignore 24780c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt * this error. 24790c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt */ 24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) { 24810c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt wpa_printf(MSG_DEBUG, 24820c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt "TDLS: Failed to parse KDEs in TPK M3 - ignore as an interop workaround"); 24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { 24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TPK M3"); 2487adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M3", 24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) kde.lnkid, kde.lnkid_len); 24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; 24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { 24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: TPK M3 from diff BSS"); 2495adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsn; 25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) { 25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No FTIE in TPK M3"); 2503adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M3", 25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.ftie, sizeof(*ftie)); 25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) kde.ftie; 25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie == NULL) { 25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No RSN IE in TPK M3"); 2511adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M3", 25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len != peer->rsnie_p_len || 25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(kde.rsn_ie, peer->rsnie_p, peer->rsnie_p_len) != 0) { 25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M3 does not match " 25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with the one sent in TPK M2"); 2519adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 252257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (os_memcmp(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN) != 0) { 25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: FTIE ANonce in TPK M3 does " 25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with FTIE ANonce used in TPK M2"); 2525adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 252857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) { 25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M3 does not " 25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with FTIE SNonce used in TPK M1"); 2531adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.key_lifetime == NULL) { 25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M3"); 2536adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime; 25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Timeout IE Received from TPK M3", 25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) timeoutie, sizeof(*timeoutie)); 25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_LE32(timeoutie->value); 25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M3", 25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime); 25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime != peer->lifetime) { 25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in " 25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M3 (expected %u)", lifetime, peer->lifetime); 2547adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_verify_tdls_mic(3, peer, (u8 *) lnkid, 25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) timeoutie, ftie) < 0) { 25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_del_key(sm, peer); 2553adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25568da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt if (wpa_tdls_set_key(sm, peer) < 0) { 25578da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt /* 25588da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt * Some drivers may not be able to config the key prior to full 25598da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt * STA entry having been configured. 25608da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt */ 25618da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after " 25628da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt "STA entry is complete"); 25638da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt peer->reconfig_key = 1; 25648da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt } 25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsn: 2567d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt /* add supported rates, capabilities, and qos_info to the TDLS peer */ 2568d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (wpa_tdls_addset_peer(sm, peer, 0) < 0) 2569d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt goto error; 2570d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 2571292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt if (!peer->tpk_success) { 2572292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt /* 2573292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt * Enable Link only when tpk_success is 0, signifying that this 2574292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt * processing of TPK M3 frame is not because of a retransmission 2575292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt * during TDLS setup handshake. 2576292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt */ 2577292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt ret = wpa_tdls_enable_link(sm, peer); 2578292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt if (ret < 0) { 2579292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Could not enable link"); 2580d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt goto error; 2581292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt } 25828da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt } 25838da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt return ret; 2584adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutterror: 2585d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt wpa_tdls_do_teardown(sm, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 2586adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt return -1; 25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs) 25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie *lifetime = (struct wpa_tdls_timeoutie *) ie; 25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(lifetime, 0, ie_len); 25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime->ie_type = WLAN_EID_TIMEOUT_INTERVAL; 25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime->ie_len = sizeof(struct wpa_tdls_timeoutie) - 2; 25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime->interval_type = WLAN_TIMEOUT_KEY_LIFETIME; 25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE32(lifetime->value, tsecs); 25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ie, ie_len); 26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos + ie_len; 26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_start - Initiate TDLS handshake (send TPK Handshake Message 1) 26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer: MAC address of the peer STA 26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, or -1 on failure 26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Send TPK Handshake Message 1 info to driver to start TDLS 26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake with the peer. 26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_tdls_start(struct wpa_sm *sm, const u8 *addr) 26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tdls_prohibited = sm->tdls_prohibited; 26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) && 26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tdls_prohibited) { 26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition " 26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "on TDLS"); 26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tdls_prohibited = 0; 26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_prohibited) { 26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS is prohibited in this BSS - " 26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "reject request to start setup"); 26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26364b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt peer = wpa_tdls_add_peer(sm, addr, NULL); 26374b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (peer == NULL) 26384b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return -1; 26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 264073b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt if (peer->tpk_in_progress) { 264173b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt wpa_printf(MSG_DEBUG, "TDLS: Setup is already in progress with the peer"); 264273b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt return 0; 264373b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt } 264473b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt 26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->initiator = 1; 26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* add the peer to the driver as a "setup in progress" peer */ 2648d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, 26499ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0)) { 2650d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt wpa_tdls_disable_peer_link(sm, peer); 2651d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt return -1; 2652d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt } 26531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 265473b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt peer->tpk_in_progress = 1; 265573b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt 26561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_tdls_send_tpk_m1(sm, peer) < 0) { 2657d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 26581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 26591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 26601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26654b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtvoid wpa_tdls_remove(struct wpa_sm *sm, const u8 *addr) 26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 26704b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return; 26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL || !peer->tpk_success) 26784b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return; 26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_external_setup) { 26811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 26821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Disable previous link to allow renegotiation to be completed 26831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * on AP path. 26841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 2685b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt wpa_tdls_do_teardown(sm, peer, 2686b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 26871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_rx_tdls - Receive TDLS data frame 26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to receive TDLS (ethertype = 0x890d) data frames. 26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_rx_tdls(void *ctx, const u8 *src_addr, 26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = ctx; 27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_frame *tf; 27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Received Data frame encapsulation", 27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, len); 27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) { 27061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Discard message - TDLS disabled " 27071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "or unsupported by driver"); 27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(src_addr, sm->own_addr, ETH_ALEN) == 0) { 27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Discard copy of own message"); 27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*tf)) { 27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Drop too short frame"); 27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Check to make sure its a valid encapsulated TDLS frame */ 27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tf = (struct wpa_tdls_frame *) buf; 27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tf->payloadtype != 2 /* TDLS_RFTYPE */ || 27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tf->category != WLAN_ACTION_TDLS) { 27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Invalid frame - payloadtype=%u " 27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "category=%u action=%u", 27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tf->payloadtype, tf->category, tf->action); 27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (tf->action) { 27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_TDLS_SETUP_REQUEST: 27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_process_tpk_m1(sm, src_addr, buf, len); 27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_TDLS_SETUP_RESPONSE: 27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_process_tpk_m2(sm, src_addr, buf, len); 27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_TDLS_SETUP_CONFIRM: 27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_process_tpk_m3(sm, src_addr, buf, len); 27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_TDLS_TEARDOWN: 27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_recv_teardown(sm, src_addr, buf, len); 27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 27441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_TDLS_DISCOVERY_REQUEST: 27451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_tdls_process_discovery_request(sm, src_addr, buf, len); 27461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 27478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 27488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Kernel code will process remaining frames */ 27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Ignore TDLS frame action code %u", 27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tf->action); 27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_init - Initialize driver interface parameters for TDLS 27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to initialize driver interface parameters for TDLS. 27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_drv_init() must have been called before this function to initialize the 27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * driver interface. 27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_tdls_init(struct wpa_sm *sm) 27668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 27688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 27698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 277004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sm->l2_tdls = l2_packet_init(sm->bridge_ifname ? sm->bridge_ifname : 277104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sm->ifname, 277204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sm->own_addr, 27738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_P_80211_ENCAP, wpa_supplicant_rx_tdls, 27748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, 0); 27758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_tdls == NULL) { 27768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "TDLS: Failed to open l2_packet " 27778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "connection"); 27788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 27798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 27821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Drivers that support TDLS but don't implement the get_capa callback 27831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * are assumed to perform everything internally 27841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 27851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_sm_tdls_get_capa(sm, &sm->tdls_supported, 27866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt &sm->tdls_external_setup, 27876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt &sm->tdls_chan_switch) < 0) { 27881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->tdls_supported = 1; 27891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->tdls_external_setup = 0; 27901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 27911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 27921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS operation%s supported by " 27931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "driver", sm->tdls_supported ? "" : " not"); 27941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Driver uses %s link setup", 27951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->tdls_external_setup ? "external" : "internal"); 27966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Driver %s TDLS channel switching", 27976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->tdls_chan_switch ? "supports" : "does not support"); 27981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 27998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2803f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtvoid wpa_tdls_teardown_peers(struct wpa_sm *sm) 2804f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 2805d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt struct wpa_tdls_peer *peer, *tmp; 2806f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2807ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (!sm) 2808ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return; 2809f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer = sm->tdls; 2810f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2811f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Tear down peers"); 2812f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2813f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt while (peer) { 2814d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt tmp = peer->next; 2815f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Tear down peer " MACSTR, 2816f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt MAC2STR(peer->addr)); 2817f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (sm->tdls_external_setup) 2818b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt wpa_tdls_do_teardown(sm, peer, 2819b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt WLAN_REASON_DEAUTH_LEAVING); 2820f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt else 2821f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr); 2822f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2823d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt peer = tmp; 2824f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 2825f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt} 2826f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2827f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_remove_peers(struct wpa_sm *sm) 28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer, *tmp; 28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = sm->tdls; 28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (peer) { 28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = peer->next; 28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr); 28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Remove peer " MACSTR " (res=%d)", 28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer->addr), res); 28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = tmp; 28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_deinit - Deinitialize driver interface parameters for TDLS 28488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 28498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to recover driver interface parameters for TDLS 28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and frees resources allocated for it. 28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_deinit(struct wpa_sm *sm) 28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_tdls) 28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_packet_deinit(sm->l2_tdls); 28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->l2_tdls = NULL; 28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_remove_peers(sm); 28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_assoc(struct wpa_sm *sm) 28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Remove peers on association"); 28688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_remove_peers(sm); 28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_disassoc(struct wpa_sm *sm) 28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Remove peers on disassociation"); 28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_remove_peers(sm); 28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2879d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int wpa_tdls_prohibited(struct ieee802_11_elems *elems) 28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* bit 38 - TDLS Prohibited */ 28829839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt return !!(elems->ext_capab[4] & 0x40); 28836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2886d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int wpa_tdls_chan_switch_prohibited(struct ieee802_11_elems *elems) 28876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 28886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* bit 39 - TDLS Channel Switch Prohibited */ 28899839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt return !!(elems->ext_capab[4] & 0x80); 28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len) 28948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2895d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct ieee802_11_elems elems; 28966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 28976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->tdls_prohibited = 0; 28986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->tdls_chan_switch_prohibited = 0; 28996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2900d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (ies == NULL || 2901d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ieee802_11_parse_elems(ies, len, &elems, 0) == ParseFailed || 29029839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt elems.ext_capab == NULL || elems.ext_capab_len < 5) 29036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 29046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 29056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->tdls_prohibited = wpa_tdls_prohibited(&elems); 29068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS is %s in the target BSS", 29078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls_prohibited ? "prohibited" : "allowed"); 29086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->tdls_chan_switch_prohibited = 29096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_tdls_chan_switch_prohibited(&elems); 29106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS channel switch %s in the target BSS", 29116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->tdls_chan_switch_prohibited ? "prohibited" : "allowed"); 29128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len) 29168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2917d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct ieee802_11_elems elems; 29186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2919d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (ies == NULL || 2920d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ieee802_11_parse_elems(ies, len, &elems, 0) == ParseFailed || 29219839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt elems.ext_capab == NULL || elems.ext_capab_len < 5) 29226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 29236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 29246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!sm->tdls_prohibited && wpa_tdls_prohibited(&elems)) { 29258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS prohibited based on " 29268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Re)Association Response IEs"); 29278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls_prohibited = 1; 29288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 29296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 29306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!sm->tdls_chan_switch_prohibited && 29316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_tdls_chan_switch_prohibited(&elems)) { 29326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 29336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "TDLS: TDLS channel switch prohibited based on (Re)Association Response IEs"); 29346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->tdls_chan_switch_prohibited = 1; 29356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_enable(struct wpa_sm *sm, int enabled) 29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: %s", enabled ? "enabled" : "disabled"); 29428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls_disabled = !enabled; 29438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 29451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 29461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_tdls_is_external_setup(struct wpa_sm *sm) 29471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 29481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return sm->tdls_external_setup; 29491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 29506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 29516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 29526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint wpa_tdls_enable_chan_switch(struct wpa_sm *sm, const u8 *addr, 29536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u8 oper_class, 29546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct hostapd_freq_params *freq_params) 29556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 29566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_tdls_peer *peer; 29576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 29586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 29596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 29606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 29616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 29626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!sm->tdls_chan_switch) { 29636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 29646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "TDLS: Channel switching not supported by the driver"); 29656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 29666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 29676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 29686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (sm->tdls_chan_switch_prohibited) { 29696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 29706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "TDLS: Channel switching is prohibited in this BSS - reject request to switch channel"); 29716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 29726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 29736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 29746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 29756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 29766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 29776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 29786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 29796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (peer == NULL || !peer->tpk_success) { 29806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, "TDLS: Peer " MACSTR 29816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt " not found for channel switching", MAC2STR(addr)); 29826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 29836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 29846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 29856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (peer->chan_switch_enabled) { 29866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR 29876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt " already has channel switching enabled", 29886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(addr)); 29896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 29906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 29916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 29926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = wpa_sm_tdls_enable_channel_switch(sm, peer->addr, 29936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt oper_class, freq_params); 29946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!ret) 29956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt peer->chan_switch_enabled = 1; 29966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 29976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 29986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 29996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 30006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 30016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint wpa_tdls_disable_chan_switch(struct wpa_sm *sm, const u8 *addr) 30026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 30036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_tdls_peer *peer; 30046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 30056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 30066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 30076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 30086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 30096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 30106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 30116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 30126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 30136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!peer || !peer->chan_switch_enabled) { 30146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, "TDLS: Channel switching not enabled for " 30156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MACSTR, MAC2STR(addr)); 30166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 30176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 30186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 30196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* ignore the return value */ 30206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_sm_tdls_disable_channel_switch(sm, peer->addr); 30216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 30226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt peer->chan_switch_enabled = 0; 30236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 30246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 3025