mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-21 05:44:01 +00:00
mac80211: receive and process S1G beacons
S1G beacons are 802.11 Extension Frames, so the fixed header part differs from regular beacons. Add a handler to process S1G beacons and abstract out the fetching of BSSID and element start locations in the beacon body handler. Signed-off-by: Thomas Pedersen <thomas@adapt-ip.com> Link: https://lore.kernel.org/r/20200922022818.15855-14-thomas@adapt-ip.com [don't rename, small coding style cleanups] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
cac8c526ae
commit
09a740ce35
5 changed files with 159 additions and 65 deletions
|
@ -1656,6 +1656,8 @@ int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata);
|
||||||
void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);
|
void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);
|
||||||
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
|
void ieee80211_sta_rx_queued_ext(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct sk_buff *skb);
|
||||||
void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata);
|
void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata);
|
||||||
void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
|
void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
|
||||||
void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata);
|
void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata);
|
||||||
|
@ -2301,6 +2303,8 @@ void ieee80211_tdls_handle_disconnect(struct ieee80211_sub_if_data *sdata,
|
||||||
const u8 *peer, u16 reason);
|
const u8 *peer, u16 reason);
|
||||||
const char *ieee80211_get_reason_code_string(u16 reason_code);
|
const char *ieee80211_get_reason_code_string(u16 reason_code);
|
||||||
u16 ieee80211_encode_usf(int val);
|
u16 ieee80211_encode_usf(int val);
|
||||||
|
u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
|
||||||
|
enum nl80211_iftype type);
|
||||||
|
|
||||||
extern const struct ethtool_ops ieee80211_ethtool_ops;
|
extern const struct ethtool_ops ieee80211_ethtool_ops;
|
||||||
|
|
||||||
|
|
|
@ -1433,6 +1433,11 @@ static void ieee80211_iface_work(struct work_struct *work)
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (ieee80211_is_ext(mgmt->frame_control)) {
|
||||||
|
if (sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||||
|
ieee80211_sta_rx_queued_ext(sdata, skb);
|
||||||
|
else
|
||||||
|
WARN_ON(1);
|
||||||
} else if (ieee80211_is_data_qos(mgmt->frame_control)) {
|
} else if (ieee80211_is_data_qos(mgmt->frame_control)) {
|
||||||
struct ieee80211_hdr *hdr = (void *)mgmt;
|
struct ieee80211_hdr *hdr = (void *)mgmt;
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1602,6 +1602,9 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
|
||||||
int new_ap_level;
|
int new_ap_level;
|
||||||
__le16 capab = mgmt->u.probe_resp.capab_info;
|
__le16 capab = mgmt->u.probe_resp.capab_info;
|
||||||
|
|
||||||
|
if (ieee80211_is_s1g_beacon(mgmt->frame_control))
|
||||||
|
return 0; /* TODO */
|
||||||
|
|
||||||
if (country_ie &&
|
if (country_ie &&
|
||||||
(capab & cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT) ||
|
(capab & cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT) ||
|
||||||
capab & cpu_to_le16(WLAN_CAPABILITY_RADIO_MEASURE))) {
|
capab & cpu_to_le16(WLAN_CAPABILITY_RADIO_MEASURE))) {
|
||||||
|
@ -3896,11 +3899,12 @@ static bool ieee80211_rx_our_beacon(const u8 *tx_bssid,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
struct ieee80211_mgmt *mgmt, size_t len,
|
struct ieee80211_hdr *hdr, size_t len,
|
||||||
struct ieee80211_rx_status *rx_status)
|
struct ieee80211_rx_status *rx_status)
|
||||||
{
|
{
|
||||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||||
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
|
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
|
||||||
|
struct ieee80211_mgmt *mgmt = (void *) hdr;
|
||||||
size_t baselen;
|
size_t baselen;
|
||||||
struct ieee802_11_elems elems;
|
struct ieee802_11_elems elems;
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
@ -3910,14 +3914,24 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
u32 changed = 0;
|
u32 changed = 0;
|
||||||
bool erp_valid;
|
bool erp_valid;
|
||||||
u8 erp_value = 0;
|
u8 erp_value = 0;
|
||||||
u32 ncrc;
|
u32 ncrc = 0;
|
||||||
u8 *bssid;
|
u8 *bssid, *variable = mgmt->u.beacon.variable;
|
||||||
u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
|
u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
|
||||||
|
|
||||||
sdata_assert_lock(sdata);
|
sdata_assert_lock(sdata);
|
||||||
|
|
||||||
/* Process beacon from the current BSS */
|
/* Process beacon from the current BSS */
|
||||||
baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
|
bssid = ieee80211_get_bssid(hdr, len, sdata->vif.type);
|
||||||
|
if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
|
||||||
|
struct ieee80211_ext *ext = (void *) mgmt;
|
||||||
|
|
||||||
|
if (ieee80211_is_s1g_short_beacon(ext->frame_control))
|
||||||
|
variable = ext->u.s1g_short_beacon.variable;
|
||||||
|
else
|
||||||
|
variable = ext->u.s1g_beacon.variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
baselen = (u8 *) variable - (u8 *) mgmt;
|
||||||
if (baselen > len)
|
if (baselen > len)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -3937,10 +3951,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
|
if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
|
||||||
ieee80211_rx_our_beacon(mgmt->bssid, ifmgd->assoc_data->bss)) {
|
ieee80211_rx_our_beacon(bssid, ifmgd->assoc_data->bss)) {
|
||||||
ieee802_11_parse_elems(mgmt->u.beacon.variable,
|
ieee802_11_parse_elems(variable,
|
||||||
len - baselen, false, &elems,
|
len - baselen, false, &elems,
|
||||||
mgmt->bssid,
|
bssid,
|
||||||
ifmgd->assoc_data->bss->bssid);
|
ifmgd->assoc_data->bss->bssid);
|
||||||
|
|
||||||
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
|
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
|
||||||
|
@ -3973,7 +3987,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ifmgd->associated ||
|
if (!ifmgd->associated ||
|
||||||
!ieee80211_rx_our_beacon(mgmt->bssid, ifmgd->associated))
|
!ieee80211_rx_our_beacon(bssid, ifmgd->associated))
|
||||||
return;
|
return;
|
||||||
bssid = ifmgd->associated->bssid;
|
bssid = ifmgd->associated->bssid;
|
||||||
|
|
||||||
|
@ -3993,8 +4007,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
*/
|
*/
|
||||||
ieee80211_sta_reset_beacon_monitor(sdata);
|
ieee80211_sta_reset_beacon_monitor(sdata);
|
||||||
|
|
||||||
ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
|
/* TODO: CRC urrently not calculated on S1G Beacon Compatibility
|
||||||
ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
|
* element (which carries the beacon interval). Don't forget to add a
|
||||||
|
* bit to care_about_ies[] above if mac80211 is interested in a
|
||||||
|
* changing S1G element.
|
||||||
|
*/
|
||||||
|
if (!ieee80211_is_s1g_beacon(hdr->frame_control))
|
||||||
|
ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
|
||||||
|
ncrc = ieee802_11_parse_elems_crc(variable,
|
||||||
len - baselen, false, &elems,
|
len - baselen, false, &elems,
|
||||||
care_about_ies, ncrc,
|
care_about_ies, ncrc,
|
||||||
mgmt->bssid, bssid);
|
mgmt->bssid, bssid);
|
||||||
|
@ -4028,7 +4048,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
struct ieee80211_p2p_noa_attr noa = {};
|
struct ieee80211_p2p_noa_attr noa = {};
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = cfg80211_get_p2p_attr(mgmt->u.beacon.variable,
|
ret = cfg80211_get_p2p_attr(variable,
|
||||||
len - baselen,
|
len - baselen,
|
||||||
IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
|
IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
|
||||||
(u8 *) &noa, sizeof(noa));
|
(u8 *) &noa, sizeof(noa));
|
||||||
|
@ -4064,7 +4084,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
* the driver will use them. The synchronized view is currently
|
* the driver will use them. The synchronized view is currently
|
||||||
* guaranteed only in certain callbacks.
|
* guaranteed only in certain callbacks.
|
||||||
*/
|
*/
|
||||||
if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
|
if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY) &&
|
||||||
|
!ieee80211_is_s1g_beacon(hdr->frame_control)) {
|
||||||
sdata->vif.bss_conf.sync_tsf =
|
sdata->vif.bss_conf.sync_tsf =
|
||||||
le64_to_cpu(mgmt->u.beacon.timestamp);
|
le64_to_cpu(mgmt->u.beacon.timestamp);
|
||||||
sdata->vif.bss_conf.sync_device_ts =
|
sdata->vif.bss_conf.sync_device_ts =
|
||||||
|
@ -4072,7 +4093,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
|
sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
|
if ((ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) ||
|
||||||
|
ieee80211_is_s1g_short_beacon(mgmt->frame_control))
|
||||||
return;
|
return;
|
||||||
ifmgd->beacon_crc = ncrc;
|
ifmgd->beacon_crc = ncrc;
|
||||||
ifmgd->beacon_crc_valid = true;
|
ifmgd->beacon_crc_valid = true;
|
||||||
|
@ -4113,9 +4135,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
} else {
|
} else {
|
||||||
erp_valid = false;
|
erp_valid = false;
|
||||||
}
|
}
|
||||||
changed |= ieee80211_handle_bss_capability(sdata,
|
|
||||||
le16_to_cpu(mgmt->u.beacon.capab_info),
|
if (!ieee80211_is_s1g_beacon(hdr->frame_control))
|
||||||
erp_valid, erp_value);
|
changed |= ieee80211_handle_bss_capability(sdata,
|
||||||
|
le16_to_cpu(mgmt->u.beacon.capab_info),
|
||||||
|
erp_valid, erp_value);
|
||||||
|
|
||||||
mutex_lock(&local->sta_mtx);
|
mutex_lock(&local->sta_mtx);
|
||||||
sta = sta_info_get(sdata, bssid);
|
sta = sta_info_get(sdata, bssid);
|
||||||
|
@ -4153,6 +4177,26 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
ieee80211_bss_info_change_notify(sdata, changed);
|
ieee80211_bss_info_change_notify(sdata, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ieee80211_sta_rx_queued_ext(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct ieee80211_rx_status *rx_status;
|
||||||
|
struct ieee80211_hdr *hdr;
|
||||||
|
u16 fc;
|
||||||
|
|
||||||
|
rx_status = (struct ieee80211_rx_status *) skb->cb;
|
||||||
|
hdr = (struct ieee80211_hdr *) skb->data;
|
||||||
|
fc = le16_to_cpu(hdr->frame_control);
|
||||||
|
|
||||||
|
sdata_lock(sdata);
|
||||||
|
switch (fc & IEEE80211_FCTL_STYPE) {
|
||||||
|
case IEEE80211_STYPE_S1G_BEACON:
|
||||||
|
ieee80211_rx_mgmt_beacon(sdata, hdr, skb->len, rx_status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sdata_unlock(sdata);
|
||||||
|
}
|
||||||
|
|
||||||
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
@ -4170,7 +4214,8 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
||||||
|
|
||||||
switch (fc & IEEE80211_FCTL_STYPE) {
|
switch (fc & IEEE80211_FCTL_STYPE) {
|
||||||
case IEEE80211_STYPE_BEACON:
|
case IEEE80211_STYPE_BEACON:
|
||||||
ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status);
|
ieee80211_rx_mgmt_beacon(sdata, (void *)mgmt,
|
||||||
|
skb->len, rx_status);
|
||||||
break;
|
break;
|
||||||
case IEEE80211_STYPE_PROBE_RESP:
|
case IEEE80211_STYPE_PROBE_RESP:
|
||||||
ieee80211_rx_mgmt_probe_resp(sdata, skb);
|
ieee80211_rx_mgmt_probe_resp(sdata, skb);
|
||||||
|
|
|
@ -42,51 +42,6 @@ static inline void ieee80211_rx_stats(struct net_device *dev, u32 len)
|
||||||
u64_stats_update_end(&tstats->syncp);
|
u64_stats_update_end(&tstats->syncp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
|
|
||||||
enum nl80211_iftype type)
|
|
||||||
{
|
|
||||||
__le16 fc = hdr->frame_control;
|
|
||||||
|
|
||||||
if (ieee80211_is_data(fc)) {
|
|
||||||
if (len < 24) /* drop incorrect hdr len (data) */
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (ieee80211_has_a4(fc))
|
|
||||||
return NULL;
|
|
||||||
if (ieee80211_has_tods(fc))
|
|
||||||
return hdr->addr1;
|
|
||||||
if (ieee80211_has_fromds(fc))
|
|
||||||
return hdr->addr2;
|
|
||||||
|
|
||||||
return hdr->addr3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ieee80211_is_mgmt(fc)) {
|
|
||||||
if (len < 24) /* drop incorrect hdr len (mgmt) */
|
|
||||||
return NULL;
|
|
||||||
return hdr->addr3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ieee80211_is_ctl(fc)) {
|
|
||||||
if (ieee80211_is_pspoll(fc))
|
|
||||||
return hdr->addr1;
|
|
||||||
|
|
||||||
if (ieee80211_is_back_req(fc)) {
|
|
||||||
switch (type) {
|
|
||||||
case NL80211_IFTYPE_STATION:
|
|
||||||
return hdr->addr2;
|
|
||||||
case NL80211_IFTYPE_AP:
|
|
||||||
case NL80211_IFTYPE_AP_VLAN:
|
|
||||||
return hdr->addr1;
|
|
||||||
default:
|
|
||||||
break; /* fall through to the return */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* monitor mode reception
|
* monitor mode reception
|
||||||
*
|
*
|
||||||
|
@ -1802,7 +1757,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
||||||
}
|
}
|
||||||
} else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) {
|
} else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) {
|
||||||
sta->rx_stats.last_rx = jiffies;
|
sta->rx_stats.last_rx = jiffies;
|
||||||
} else if (!is_multicast_ether_addr(hdr->addr1)) {
|
} else if (!ieee80211_is_s1g_beacon(hdr->frame_control) &&
|
||||||
|
is_multicast_ether_addr(hdr->addr1)) {
|
||||||
/*
|
/*
|
||||||
* Mesh beacons will update last_rx when if they are found to
|
* Mesh beacons will update last_rx when if they are found to
|
||||||
* match the current local configuration when processed.
|
* match the current local configuration when processed.
|
||||||
|
@ -1837,6 +1793,9 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ieee80211_is_s1g_beacon(hdr->frame_control))
|
||||||
|
return RX_CONTINUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change STA power saving mode only at the end of a frame
|
* Change STA power saving mode only at the end of a frame
|
||||||
* exchange sequence, and only for a data or management
|
* exchange sequence, and only for a data or management
|
||||||
|
@ -1947,6 +1906,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
||||||
__le16 fc;
|
__le16 fc;
|
||||||
const struct ieee80211_cipher_scheme *cs = NULL;
|
const struct ieee80211_cipher_scheme *cs = NULL;
|
||||||
|
|
||||||
|
if (ieee80211_is_ext(hdr->frame_control))
|
||||||
|
return RX_CONTINUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Key selection 101
|
* Key selection 101
|
||||||
*
|
*
|
||||||
|
@ -2255,7 +2217,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
||||||
hdr = (struct ieee80211_hdr *)rx->skb->data;
|
hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||||
fc = hdr->frame_control;
|
fc = hdr->frame_control;
|
||||||
|
|
||||||
if (ieee80211_is_ctl(fc))
|
if (ieee80211_is_ctl(fc) || ieee80211_is_ext(fc))
|
||||||
return RX_CONTINUE;
|
return RX_CONTINUE;
|
||||||
|
|
||||||
sc = le16_to_cpu(hdr->seq_ctrl);
|
sc = le16_to_cpu(hdr->seq_ctrl);
|
||||||
|
@ -3129,6 +3091,9 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
|
||||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
|
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
|
||||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||||
|
|
||||||
|
if (ieee80211_is_s1g_beacon(mgmt->frame_control))
|
||||||
|
return RX_CONTINUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* From here on, look only at management frames.
|
* From here on, look only at management frames.
|
||||||
* Data and control frames are already handled,
|
* Data and control frames are already handled,
|
||||||
|
@ -3595,6 +3560,27 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
|
||||||
return RX_QUEUED;
|
return RX_QUEUED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ieee80211_rx_result debug_noinline
|
||||||
|
ieee80211_rx_h_ext(struct ieee80211_rx_data *rx)
|
||||||
|
{
|
||||||
|
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||||
|
struct ieee80211_hdr *hdr = (void *)rx->skb->data;
|
||||||
|
|
||||||
|
if (!ieee80211_is_ext(hdr->frame_control))
|
||||||
|
return RX_CONTINUE;
|
||||||
|
|
||||||
|
if (sdata->vif.type != NL80211_IFTYPE_STATION)
|
||||||
|
return RX_DROP_MONITOR;
|
||||||
|
|
||||||
|
/* for now only beacons are ext, so queue them */
|
||||||
|
skb_queue_tail(&sdata->skb_queue, rx->skb);
|
||||||
|
ieee80211_queue_work(&rx->local->hw, &sdata->work);
|
||||||
|
if (rx->sta)
|
||||||
|
rx->sta->rx_stats.packets++;
|
||||||
|
|
||||||
|
return RX_QUEUED;
|
||||||
|
}
|
||||||
|
|
||||||
static ieee80211_rx_result debug_noinline
|
static ieee80211_rx_result debug_noinline
|
||||||
ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
|
ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
|
||||||
{
|
{
|
||||||
|
@ -3814,6 +3800,7 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
|
||||||
CALL_RXH(ieee80211_rx_h_userspace_mgmt);
|
CALL_RXH(ieee80211_rx_h_userspace_mgmt);
|
||||||
CALL_RXH(ieee80211_rx_h_action_post_userspace);
|
CALL_RXH(ieee80211_rx_h_action_post_userspace);
|
||||||
CALL_RXH(ieee80211_rx_h_action_return);
|
CALL_RXH(ieee80211_rx_h_action_return);
|
||||||
|
CALL_RXH(ieee80211_rx_h_ext);
|
||||||
CALL_RXH(ieee80211_rx_h_mgmt);
|
CALL_RXH(ieee80211_rx_h_mgmt);
|
||||||
|
|
||||||
rxh_next:
|
rxh_next:
|
||||||
|
@ -3980,7 +3967,8 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
|
||||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||||
u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
|
u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
|
||||||
bool multicast = is_multicast_ether_addr(hdr->addr1);
|
bool multicast = is_multicast_ether_addr(hdr->addr1) ||
|
||||||
|
ieee80211_is_s1g_beacon(hdr->frame_control);
|
||||||
|
|
||||||
switch (sdata->vif.type) {
|
switch (sdata->vif.type) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
|
|
|
@ -45,6 +45,58 @@ struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(wiphy_to_ieee80211_hw);
|
EXPORT_SYMBOL(wiphy_to_ieee80211_hw);
|
||||||
|
|
||||||
|
u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
|
||||||
|
enum nl80211_iftype type)
|
||||||
|
{
|
||||||
|
__le16 fc = hdr->frame_control;
|
||||||
|
|
||||||
|
if (ieee80211_is_data(fc)) {
|
||||||
|
if (len < 24) /* drop incorrect hdr len (data) */
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (ieee80211_has_a4(fc))
|
||||||
|
return NULL;
|
||||||
|
if (ieee80211_has_tods(fc))
|
||||||
|
return hdr->addr1;
|
||||||
|
if (ieee80211_has_fromds(fc))
|
||||||
|
return hdr->addr2;
|
||||||
|
|
||||||
|
return hdr->addr3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ieee80211_is_s1g_beacon(fc)) {
|
||||||
|
struct ieee80211_ext *ext = (void *) hdr;
|
||||||
|
|
||||||
|
return ext->u.s1g_beacon.sa;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ieee80211_is_mgmt(fc)) {
|
||||||
|
if (len < 24) /* drop incorrect hdr len (mgmt) */
|
||||||
|
return NULL;
|
||||||
|
return hdr->addr3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ieee80211_is_ctl(fc)) {
|
||||||
|
if (ieee80211_is_pspoll(fc))
|
||||||
|
return hdr->addr1;
|
||||||
|
|
||||||
|
if (ieee80211_is_back_req(fc)) {
|
||||||
|
switch (type) {
|
||||||
|
case NL80211_IFTYPE_STATION:
|
||||||
|
return hdr->addr2;
|
||||||
|
case NL80211_IFTYPE_AP:
|
||||||
|
case NL80211_IFTYPE_AP_VLAN:
|
||||||
|
return hdr->addr1;
|
||||||
|
default:
|
||||||
|
break; /* fall through to the return */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ieee80211_get_bssid);
|
||||||
|
|
||||||
void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
|
void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
|
Loading…
Add table
Reference in a new issue