TDLS: Pass peer's Supported channel and oper class info during sta_add
The information of the peer's supported channel and operating class is required for the driver to do TDLS off channel operations with a compatible peer. Pass this information to the driver when the peer station is getting added. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
eed65aad14
commit
3ed97271ba
8 changed files with 116 additions and 7 deletions
|
@ -227,6 +227,7 @@
|
||||||
#define WLAN_EID_FAST_BSS_TRANSITION 55
|
#define WLAN_EID_FAST_BSS_TRANSITION 55
|
||||||
#define WLAN_EID_TIMEOUT_INTERVAL 56
|
#define WLAN_EID_TIMEOUT_INTERVAL 56
|
||||||
#define WLAN_EID_RIC_DATA 57
|
#define WLAN_EID_RIC_DATA 57
|
||||||
|
#define WLAN_EID_SUPPORTED_OPERATING_CLASSES 59
|
||||||
#define WLAN_EID_HT_OPERATION 61
|
#define WLAN_EID_HT_OPERATION 61
|
||||||
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
|
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
|
||||||
#define WLAN_EID_WAPI 68
|
#define WLAN_EID_WAPI 68
|
||||||
|
|
|
@ -1012,6 +1012,10 @@ struct hostapd_sta_add_params {
|
||||||
u8 qosinfo;
|
u8 qosinfo;
|
||||||
const u8 *ext_capab;
|
const u8 *ext_capab;
|
||||||
size_t ext_capab_len;
|
size_t ext_capab_len;
|
||||||
|
const u8 *supp_channels;
|
||||||
|
size_t supp_channels_len;
|
||||||
|
const u8 *supp_oper_classes;
|
||||||
|
size_t supp_oper_classes_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hostapd_freq_params {
|
struct hostapd_freq_params {
|
||||||
|
|
|
@ -136,6 +136,12 @@ struct wpa_tdls_peer {
|
||||||
|
|
||||||
u8 *ext_capab;
|
u8 *ext_capab;
|
||||||
size_t ext_capab_len;
|
size_t ext_capab_len;
|
||||||
|
|
||||||
|
u8 *supp_channels;
|
||||||
|
size_t supp_channels_len;
|
||||||
|
|
||||||
|
u8 *supp_oper_classes;
|
||||||
|
size_t supp_oper_classes_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -633,6 +639,10 @@ static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
|
||||||
peer->vht_capabilities = NULL;
|
peer->vht_capabilities = NULL;
|
||||||
os_free(peer->ext_capab);
|
os_free(peer->ext_capab);
|
||||||
peer->ext_capab = NULL;
|
peer->ext_capab = NULL;
|
||||||
|
os_free(peer->supp_channels);
|
||||||
|
peer->supp_channels = NULL;
|
||||||
|
os_free(peer->supp_oper_classes);
|
||||||
|
peer->supp_oper_classes = NULL;
|
||||||
peer->rsnie_i_len = peer->rsnie_p_len = 0;
|
peer->rsnie_i_len = peer->rsnie_p_len = 0;
|
||||||
peer->cipher = 0;
|
peer->cipher = 0;
|
||||||
peer->tpk_set = peer->tpk_success = 0;
|
peer->tpk_set = peer->tpk_success = 0;
|
||||||
|
@ -1456,6 +1466,58 @@ static int copy_peer_ext_capab(const struct wpa_eapol_ie_parse *kde,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int copy_peer_supp_channels(const struct wpa_eapol_ie_parse *kde,
|
||||||
|
struct wpa_tdls_peer *peer)
|
||||||
|
{
|
||||||
|
if (!kde->supp_channels) {
|
||||||
|
wpa_printf(MSG_DEBUG, "TDLS: No supported channels received");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!peer->supp_channels ||
|
||||||
|
peer->supp_channels_len < kde->supp_channels_len) {
|
||||||
|
os_free(peer->supp_channels);
|
||||||
|
peer->supp_channels = os_zalloc(kde->supp_channels_len);
|
||||||
|
if (peer->supp_channels == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
peer->supp_channels_len = kde->supp_channels_len;
|
||||||
|
|
||||||
|
os_memcpy(peer->supp_channels, kde->supp_channels,
|
||||||
|
peer->supp_channels_len);
|
||||||
|
wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Channels",
|
||||||
|
(u8 *) peer->supp_channels, peer->supp_channels_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int copy_peer_supp_oper_classes(const struct wpa_eapol_ie_parse *kde,
|
||||||
|
struct wpa_tdls_peer *peer)
|
||||||
|
{
|
||||||
|
if (!kde->supp_oper_classes) {
|
||||||
|
wpa_printf(MSG_DEBUG, "TDLS: No supported operating classes received");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!peer->supp_oper_classes ||
|
||||||
|
peer->supp_oper_classes_len < kde->supp_oper_classes_len) {
|
||||||
|
os_free(peer->supp_oper_classes);
|
||||||
|
peer->supp_oper_classes = os_zalloc(kde->supp_oper_classes_len);
|
||||||
|
if (peer->supp_oper_classes == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
peer->supp_oper_classes_len = kde->supp_oper_classes_len;
|
||||||
|
os_memcpy(peer->supp_oper_classes, kde->supp_oper_classes,
|
||||||
|
peer->supp_oper_classes_len);
|
||||||
|
wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Operating Classes",
|
||||||
|
(u8 *) peer->supp_oper_classes,
|
||||||
|
peer->supp_oper_classes_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
|
static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
|
||||||
const u8 *buf, size_t len)
|
const u8 *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -1568,6 +1630,12 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
|
||||||
if (copy_peer_ext_capab(&kde, peer) < 0)
|
if (copy_peer_ext_capab(&kde, peer) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if (copy_peer_supp_channels(&kde, peer) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (copy_peer_supp_oper_classes(&kde, peer) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
peer->qos_info = kde.qosinfo;
|
peer->qos_info = kde.qosinfo;
|
||||||
|
|
||||||
peer->aid = kde.aid;
|
peer->aid = kde.aid;
|
||||||
|
@ -1761,7 +1829,7 @@ skip_rsn:
|
||||||
skip_rsn_check:
|
skip_rsn_check:
|
||||||
/* add the peer to the driver as a "setup in progress" peer */
|
/* add the peer to the driver as a "setup in progress" peer */
|
||||||
wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
|
wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
|
||||||
NULL, 0);
|
NULL, 0, NULL, 0, NULL, 0);
|
||||||
peer->tpk_in_progress = 1;
|
peer->tpk_in_progress = 1;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
|
wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
|
||||||
|
@ -1810,7 +1878,11 @@ static int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
|
||||||
peer->ht_capabilities,
|
peer->ht_capabilities,
|
||||||
peer->vht_capabilities,
|
peer->vht_capabilities,
|
||||||
peer->qos_info, peer->ext_capab,
|
peer->qos_info, peer->ext_capab,
|
||||||
peer->ext_capab_len) < 0)
|
peer->ext_capab_len,
|
||||||
|
peer->supp_channels,
|
||||||
|
peer->supp_channels_len,
|
||||||
|
peer->supp_oper_classes,
|
||||||
|
peer->supp_oper_classes_len) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) {
|
if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) {
|
||||||
|
@ -1938,6 +2010,12 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr,
|
||||||
if (copy_peer_ext_capab(&kde, peer) < 0)
|
if (copy_peer_ext_capab(&kde, peer) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if (copy_peer_supp_channels(&kde, peer) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (copy_peer_supp_oper_classes(&kde, peer) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
peer->qos_info = kde.qosinfo;
|
peer->qos_info = kde.qosinfo;
|
||||||
|
|
||||||
peer->aid = kde.aid;
|
peer->aid = kde.aid;
|
||||||
|
@ -2289,7 +2367,7 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
|
||||||
|
|
||||||
/* add the peer to the driver as a "setup in progress" peer */
|
/* add the peer to the driver as a "setup in progress" peer */
|
||||||
wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
|
wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
|
||||||
NULL, 0);
|
NULL, 0, NULL, 0, NULL, 0);
|
||||||
|
|
||||||
peer->tpk_in_progress = 1;
|
peer->tpk_in_progress = 1;
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,10 @@ struct wpa_sm_ctx {
|
||||||
const struct ieee80211_ht_capabilities *ht_capab,
|
const struct ieee80211_ht_capabilities *ht_capab,
|
||||||
const struct ieee80211_vht_capabilities *vht_capab,
|
const struct ieee80211_vht_capabilities *vht_capab,
|
||||||
u8 qosinfo, const u8 *ext_capab,
|
u8 qosinfo, const u8 *ext_capab,
|
||||||
size_t ext_capab_len);
|
size_t ext_capab_len, const u8 *supp_channels,
|
||||||
|
size_t supp_channels_len,
|
||||||
|
const u8 *supp_oper_classes,
|
||||||
|
size_t supp_oper_classes_len);
|
||||||
#endif /* CONFIG_TDLS */
|
#endif /* CONFIG_TDLS */
|
||||||
void (*set_rekey_offload)(void *ctx, const u8 *kek, const u8 *kck,
|
void (*set_rekey_offload)(void *ctx, const u8 *kek, const u8 *kck,
|
||||||
const u8 *replay_ctr);
|
const u8 *replay_ctr);
|
||||||
|
|
|
@ -286,14 +286,21 @@ wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add,
|
||||||
size_t supp_rates_len,
|
size_t supp_rates_len,
|
||||||
const struct ieee80211_ht_capabilities *ht_capab,
|
const struct ieee80211_ht_capabilities *ht_capab,
|
||||||
const struct ieee80211_vht_capabilities *vht_capab,
|
const struct ieee80211_vht_capabilities *vht_capab,
|
||||||
u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len)
|
u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len,
|
||||||
|
const u8 *supp_channels, size_t supp_channels_len,
|
||||||
|
const u8 *supp_oper_classes,
|
||||||
|
size_t supp_oper_classes_len)
|
||||||
{
|
{
|
||||||
if (sm->ctx->tdls_peer_addset)
|
if (sm->ctx->tdls_peer_addset)
|
||||||
return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
|
return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
|
||||||
aid, capability, supp_rates,
|
aid, capability, supp_rates,
|
||||||
supp_rates_len, ht_capab,
|
supp_rates_len, ht_capab,
|
||||||
vht_capab, qosinfo,
|
vht_capab, qosinfo,
|
||||||
ext_capab, ext_capab_len);
|
ext_capab, ext_capab_len,
|
||||||
|
supp_channels,
|
||||||
|
supp_channels_len,
|
||||||
|
supp_oper_classes,
|
||||||
|
supp_oper_classes_len);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_TDLS */
|
#endif /* CONFIG_TDLS */
|
||||||
|
|
|
@ -434,6 +434,12 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
|
||||||
ie->vht_capabilities_len = pos[1];
|
ie->vht_capabilities_len = pos[1];
|
||||||
} else if (*pos == WLAN_EID_QOS && pos[1] >= 1) {
|
} else if (*pos == WLAN_EID_QOS && pos[1] >= 1) {
|
||||||
ie->qosinfo = pos[2];
|
ie->qosinfo = pos[2];
|
||||||
|
} else if (*pos == WLAN_EID_SUPPORTED_CHANNELS) {
|
||||||
|
ie->supp_channels = pos + 2;
|
||||||
|
ie->supp_channels_len = pos[1];
|
||||||
|
} else if (*pos == WLAN_EID_SUPPORTED_OPERATING_CLASSES) {
|
||||||
|
ie->supp_oper_classes = pos + 2;
|
||||||
|
ie->supp_oper_classes_len = pos[1];
|
||||||
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
|
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
|
||||||
ret = wpa_parse_generic(pos, end, ie);
|
ret = wpa_parse_generic(pos, end, ie);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
|
@ -53,6 +53,10 @@ struct wpa_eapol_ie_parse {
|
||||||
size_t ht_capabilities_len;
|
size_t ht_capabilities_len;
|
||||||
const u8 *vht_capabilities;
|
const u8 *vht_capabilities;
|
||||||
size_t vht_capabilities_len;
|
size_t vht_capabilities_len;
|
||||||
|
const u8 *supp_channels;
|
||||||
|
size_t supp_channels_len;
|
||||||
|
const u8 *supp_oper_classes;
|
||||||
|
size_t supp_oper_classes_len;
|
||||||
u8 qosinfo;
|
u8 qosinfo;
|
||||||
u16 aid;
|
u16 aid;
|
||||||
};
|
};
|
||||||
|
|
|
@ -579,7 +579,9 @@ static int wpa_supplicant_tdls_peer_addset(
|
||||||
const u8 *supp_rates, size_t supp_rates_len,
|
const u8 *supp_rates, size_t supp_rates_len,
|
||||||
const struct ieee80211_ht_capabilities *ht_capab,
|
const struct ieee80211_ht_capabilities *ht_capab,
|
||||||
const struct ieee80211_vht_capabilities *vht_capab,
|
const struct ieee80211_vht_capabilities *vht_capab,
|
||||||
u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len)
|
u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len,
|
||||||
|
const u8 *supp_channels, size_t supp_channels_len,
|
||||||
|
const u8 *supp_oper_classes, size_t supp_oper_classes_len)
|
||||||
{
|
{
|
||||||
struct wpa_supplicant *wpa_s = ctx;
|
struct wpa_supplicant *wpa_s = ctx;
|
||||||
struct hostapd_sta_add_params params;
|
struct hostapd_sta_add_params params;
|
||||||
|
@ -607,6 +609,10 @@ static int wpa_supplicant_tdls_peer_addset(
|
||||||
params.set = !add;
|
params.set = !add;
|
||||||
params.ext_capab = ext_capab;
|
params.ext_capab = ext_capab;
|
||||||
params.ext_capab_len = ext_capab_len;
|
params.ext_capab_len = ext_capab_len;
|
||||||
|
params.supp_channels = supp_channels;
|
||||||
|
params.supp_channels_len = supp_channels_len;
|
||||||
|
params.supp_oper_classes = supp_oper_classes;
|
||||||
|
params.supp_oper_classes_len = supp_oper_classes_len;
|
||||||
|
|
||||||
return wpa_drv_sta_add(wpa_s, ¶ms);
|
return wpa_drv_sta_add(wpa_s, ¶ms);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue