mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2025-02-21 03:23:04 -05:00
WNM: Add candidate list to BSS transition response
Add the transition candidate list to BSS Transition Management Response frame. The candidates preference is set using the regular wpa_supplicant BSS selection logic. If the BSS transition request is rejected and updated scan results are not available, the list is not added. Signed-off-by: Avraham Stern <avraham.stern@intel.com>
This commit is contained in:
parent
cf11ab7f03
commit
84d1c0fd5a
@ -94,8 +94,13 @@
|
|||||||
#define WLAN_CAPABILITY_PBCC BIT(6)
|
#define WLAN_CAPABILITY_PBCC BIT(6)
|
||||||
#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)
|
#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)
|
||||||
#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8)
|
#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8)
|
||||||
|
#define WLAN_CAPABILITY_QOS BIT(9)
|
||||||
#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10)
|
#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10)
|
||||||
|
#define WLAN_CAPABILITY_APSD BIT(11)
|
||||||
|
#define WLAN_CAPABILITY_RADIO_MEASUREMENT BIT(12)
|
||||||
#define WLAN_CAPABILITY_DSSS_OFDM BIT(13)
|
#define WLAN_CAPABILITY_DSSS_OFDM BIT(13)
|
||||||
|
#define WLAN_CAPABILITY_DELAYED_BLOCK_ACK BIT(14)
|
||||||
|
#define WLAN_CAPABILITY_IMM_BLOCK_ACK BIT(15)
|
||||||
|
|
||||||
/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */
|
/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */
|
||||||
#define WLAN_STATUS_SUCCESS 0
|
#define WLAN_STATUS_SUCCESS 0
|
||||||
@ -1534,4 +1539,20 @@ enum phy_type {
|
|||||||
PHY_TYPE_VHT = 9,
|
PHY_TYPE_VHT = 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* IEEE Std 802.11-2012, 8.4.2.39 - Neighbor Report element */
|
||||||
|
/* BSSID Information Field */
|
||||||
|
#define NEI_REP_BSSID_INFO_AP_NOT_REACH BIT(0)
|
||||||
|
#define NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH BIT(1)
|
||||||
|
#define NEI_REP_BSSID_INFO_AP_REACHABLE (BIT(0) | BIT(1))
|
||||||
|
#define NEI_REP_BSSID_INFO_SECURITY BIT(2)
|
||||||
|
#define NEI_REP_BSSID_INFO_KEY_SCOPE BIT(3)
|
||||||
|
#define NEI_REP_BSSID_INFO_SPECTRUM_MGMT BIT(4)
|
||||||
|
#define NEI_REP_BSSID_INFO_QOS BIT(5)
|
||||||
|
#define NEI_REP_BSSID_INFO_APSD BIT(6)
|
||||||
|
#define NEI_REP_BSSID_INFO_RM BIT(7)
|
||||||
|
#define NEI_REP_BSSID_INFO_DELAYED_BA BIT(8)
|
||||||
|
#define NEI_REP_BSSID_INFO_IMM_BA BIT(9)
|
||||||
|
#define NEI_REP_BSSID_INFO_MOBILITY_DOMAIN BIT(10)
|
||||||
|
#define NEI_REP_BSSID_INFO_HT BIT(11)
|
||||||
|
|
||||||
#endif /* IEEE802_11_DEFS_H */
|
#endif /* IEEE802_11_DEFS_H */
|
||||||
|
@ -816,10 +816,10 @@ static int addr_in_list(const u8 *addr, const u8 *list, size_t num)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
|
struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
|
||||||
int i, struct wpa_bss *bss,
|
int i, struct wpa_bss *bss,
|
||||||
struct wpa_ssid *group,
|
struct wpa_ssid *group,
|
||||||
int only_first_ssid)
|
int only_first_ssid)
|
||||||
{
|
{
|
||||||
u8 wpa_ie_len, rsn_ie_len;
|
u8 wpa_ie_len, rsn_ie_len;
|
||||||
int wpa;
|
int wpa;
|
||||||
|
@ -575,12 +575,190 @@ compare_scan_neighbor_results(struct wpa_supplicant *wpa_s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_bss_ies_eq(struct wpa_bss *a, struct wpa_bss *b, u8 eid)
|
||||||
|
{
|
||||||
|
const u8 *ie_a, *ie_b;
|
||||||
|
|
||||||
|
if (!a || !b)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ie_a = wpa_bss_get_ie(a, eid);
|
||||||
|
ie_b = wpa_bss_get_ie(b, eid);
|
||||||
|
|
||||||
|
if (!ie_a || !ie_b || ie_a[1] != ie_b[1])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return os_memcmp(ie_a, ie_b, ie_a[1]) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u32 wnm_get_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
||||||
|
{
|
||||||
|
u32 info = 0;
|
||||||
|
|
||||||
|
info |= NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Leave the security and key scope bits unset to indicate that the
|
||||||
|
* security information is not available.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (bss->caps & WLAN_CAPABILITY_SPECTRUM_MGMT)
|
||||||
|
info |= NEI_REP_BSSID_INFO_SPECTRUM_MGMT;
|
||||||
|
if (bss->caps & WLAN_CAPABILITY_QOS)
|
||||||
|
info |= NEI_REP_BSSID_INFO_QOS;
|
||||||
|
if (bss->caps & WLAN_CAPABILITY_APSD)
|
||||||
|
info |= NEI_REP_BSSID_INFO_APSD;
|
||||||
|
if (bss->caps & WLAN_CAPABILITY_RADIO_MEASUREMENT)
|
||||||
|
info |= NEI_REP_BSSID_INFO_RM;
|
||||||
|
if (bss->caps & WLAN_CAPABILITY_DELAYED_BLOCK_ACK)
|
||||||
|
info |= NEI_REP_BSSID_INFO_DELAYED_BA;
|
||||||
|
if (bss->caps & WLAN_CAPABILITY_IMM_BLOCK_ACK)
|
||||||
|
info |= NEI_REP_BSSID_INFO_IMM_BA;
|
||||||
|
if (wpa_bss_ies_eq(bss, wpa_s->current_bss, WLAN_EID_MOBILITY_DOMAIN))
|
||||||
|
info |= NEI_REP_BSSID_INFO_MOBILITY_DOMAIN;
|
||||||
|
if (wpa_bss_ies_eq(bss, wpa_s->current_bss, WLAN_EID_HT_CAP))
|
||||||
|
info |= NEI_REP_BSSID_INFO_HT;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wnm_add_nei_rep(u8 *buf, size_t len, const u8 *bssid, u32 bss_info,
|
||||||
|
u8 op_class, u8 chan, u8 phy_type, u8 pref)
|
||||||
|
{
|
||||||
|
u8 *pos = buf;
|
||||||
|
|
||||||
|
if (len < 18) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Not enough room for Neighbor Report element");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pos++ = WLAN_EID_NEIGHBOR_REPORT;
|
||||||
|
/* length: 13 for basic neighbor report + 3 for preference subelement */
|
||||||
|
*pos++ = 16;
|
||||||
|
os_memcpy(pos, bssid, ETH_ALEN);
|
||||||
|
pos += ETH_ALEN;
|
||||||
|
WPA_PUT_LE32(pos, bss_info);
|
||||||
|
pos += 4;
|
||||||
|
*pos++ = op_class;
|
||||||
|
*pos++ = chan;
|
||||||
|
*pos++ = phy_type;
|
||||||
|
*pos++ = WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE;
|
||||||
|
*pos++ = 1;
|
||||||
|
*pos++ = pref;
|
||||||
|
return pos - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wnm_nei_rep_add_bss(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss, u8 *buf, size_t len,
|
||||||
|
u8 pref)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
u8 op_class, chan;
|
||||||
|
int sec_chan = 0, vht = 0;
|
||||||
|
enum phy_type phy_type;
|
||||||
|
u32 info;
|
||||||
|
struct ieee80211_ht_operation *ht_oper = NULL;
|
||||||
|
struct ieee80211_vht_operation *vht_oper = NULL;
|
||||||
|
|
||||||
|
ie = wpa_bss_get_ie(bss, WLAN_EID_HT_OPERATION);
|
||||||
|
if (ie && ie[1] >= 2) {
|
||||||
|
ht_oper = (struct ieee80211_ht_operation *) (ie + 2);
|
||||||
|
|
||||||
|
if (ht_oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
|
||||||
|
sec_chan = 1;
|
||||||
|
else if (ht_oper->ht_param &
|
||||||
|
HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
|
||||||
|
sec_chan = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ie = wpa_bss_get_ie(bss, WLAN_EID_VHT_OPERATION);
|
||||||
|
if (ie && ie[1] >= 1) {
|
||||||
|
vht_oper = (struct ieee80211_vht_operation *) (ie + 2);
|
||||||
|
|
||||||
|
if (vht_oper->vht_op_info_chwidth == VHT_CHANWIDTH_80MHZ ||
|
||||||
|
vht_oper->vht_op_info_chwidth == VHT_CHANWIDTH_160MHZ ||
|
||||||
|
vht_oper->vht_op_info_chwidth == VHT_CHANWIDTH_80P80MHZ)
|
||||||
|
vht = vht_oper->vht_op_info_chwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ieee80211_freq_to_channel_ext(bss->freq, sec_chan, vht, &op_class,
|
||||||
|
&chan) == NUM_HOSTAPD_MODES) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Cannot determine operating class and channel");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
phy_type = ieee80211_get_phy_type(bss->freq, (ht_oper != NULL),
|
||||||
|
(vht_oper != NULL));
|
||||||
|
if (phy_type == PHY_TYPE_UNSPECIFIED) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Cannot determine BSS phy type for Neighbor Report");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
info = wnm_get_bss_info(wpa_s, bss);
|
||||||
|
|
||||||
|
return wnm_add_nei_rep(buf, len, bss->bssid, info, op_class, chan,
|
||||||
|
phy_type, pref);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wnm_add_cand_list(struct wpa_supplicant *wpa_s, u8 *buf, size_t len)
|
||||||
|
{
|
||||||
|
u8 *pos = buf;
|
||||||
|
unsigned int i, pref = 255;
|
||||||
|
struct os_reltime now;
|
||||||
|
struct wpa_ssid *ssid = wpa_s->current_ssid;
|
||||||
|
|
||||||
|
if (!ssid)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Define when scan results are no longer valid for the candidate
|
||||||
|
* list.
|
||||||
|
*/
|
||||||
|
os_get_reltime(&now);
|
||||||
|
if (os_reltime_expired(&now, &wpa_s->last_scan, 10))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Add candidate list to BSS Transition Management Response frame");
|
||||||
|
for (i = 0; i < wpa_s->last_scan_res_used && pref; i++) {
|
||||||
|
struct wpa_bss *bss = wpa_s->last_scan_res[i];
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (wpa_scan_res_match(wpa_s, i, bss, ssid, 1)) {
|
||||||
|
res = wnm_nei_rep_add_bss(wpa_s, bss, pos, len, pref--);
|
||||||
|
if (res == -2)
|
||||||
|
continue; /* could not build entry for BSS */
|
||||||
|
if (res < 0)
|
||||||
|
break; /* no more room for candidates */
|
||||||
|
if (pref == 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pos += res;
|
||||||
|
len -= res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_hexdump(MSG_DEBUG,
|
||||||
|
"WNM: BSS Transition Management Response candidate list",
|
||||||
|
buf, pos - buf);
|
||||||
|
|
||||||
|
return pos - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wnm_send_bss_transition_mgmt_resp(
|
static void wnm_send_bss_transition_mgmt_resp(
|
||||||
struct wpa_supplicant *wpa_s, u8 dialog_token,
|
struct wpa_supplicant *wpa_s, u8 dialog_token,
|
||||||
enum bss_trans_mgmt_status_code status, u8 delay,
|
enum bss_trans_mgmt_status_code status, u8 delay,
|
||||||
const u8 *target_bssid)
|
const u8 *target_bssid)
|
||||||
{
|
{
|
||||||
u8 buf[1000], *pos;
|
u8 buf[2000], *pos;
|
||||||
struct ieee80211_mgmt *mgmt;
|
struct ieee80211_mgmt *mgmt;
|
||||||
size_t len;
|
size_t len;
|
||||||
int res;
|
int res;
|
||||||
@ -620,6 +798,9 @@ static void wnm_send_bss_transition_mgmt_resp(
|
|||||||
pos += ETH_ALEN;
|
pos += ETH_ALEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status == WNM_BSS_TM_ACCEPT)
|
||||||
|
pos += wnm_add_cand_list(wpa_s, pos, buf + sizeof(buf) - pos);
|
||||||
|
|
||||||
#ifdef CONFIG_MBO
|
#ifdef CONFIG_MBO
|
||||||
if (status != WNM_BSS_TM_ACCEPT) {
|
if (status != WNM_BSS_TM_ACCEPT) {
|
||||||
pos += wpas_mbo_ie_bss_trans_reject(
|
pos += wpas_mbo_ie_bss_trans_reject(
|
||||||
|
@ -1253,4 +1253,9 @@ void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
|||||||
unsigned int sec);
|
unsigned int sec);
|
||||||
int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid);
|
int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid);
|
||||||
|
|
||||||
|
struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
|
||||||
|
int i, struct wpa_bss *bss,
|
||||||
|
struct wpa_ssid *group,
|
||||||
|
int only_first_ssid);
|
||||||
|
|
||||||
#endif /* WPA_SUPPLICANT_I_H */
|
#endif /* WPA_SUPPLICANT_I_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user