[prev in list] [next in list] [prev in thread] [next in thread]
List: linux-backports
Subject: spatch missing a transformation
From: Johannes Berg <johannes () sipsolutions ! net>
Date: 2015-05-05 13:13:39
Message-ID: 1430831619.1950.16.camel () sipsolutions ! net
[Download RAW message or body]
Hi Julia,
With the attached file that I'm working on, against mac80211's tx.c and
rx.c (also attached), I'm getting some very strange spatch behaviour.
If I run
spatch --sp-file test.cocci rx.c tx.c
it will happily modify both files.
If I run it on just rx.c, it will modify the code there. If I run it
only on tx.c, it will not modify it. If I run it on a whole directory,
it only modifies rx.c as well.
Unfortunately I'm still on rc24 right now, I'll try to update and see if
the issue persists.
johannes
["rx.c" (rx.c)]
/*
* Copyright 2002-2005, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/jiffies.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/rcupdate.h>
#include <linux/export.h>
#include <net/mac80211.h>
#include <net/ieee80211_radiotap.h>
#include <asm/unaligned.h>
#include "ieee80211_i.h"
#include "driver-ops.h"
#include "led.h"
#include "mesh.h"
#include "wep.h"
#include "wpa.h"
#include "tkip.h"
#include "wme.h"
#include "rate.h"
static inline void ieee80211_rx_stats(struct net_device *dev, u32 len)
{
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
u64_stats_update_begin(&tstats->syncp);
tstats->rx_packets++;
tstats->rx_bytes += len;
u64_stats_update_end(&tstats->syncp);
}
/*
* monitor mode reception
*
* This function cleans up the SKB, i.e. it removes all the stuff
* only useful for monitoring.
*/
static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
struct sk_buff *skb,
unsigned int rtap_vendor_space)
{
if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) {
if (likely(skb->len > FCS_LEN))
__pskb_trim(skb, skb->len - FCS_LEN);
else {
/* driver bug */
WARN_ON(1);
dev_kfree_skb(skb);
return NULL;
}
}
__pskb_pull(skb, rtap_vendor_space);
return skb;
}
static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len,
unsigned int rtap_vendor_space)
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr;
hdr = (void *)(skb->data + rtap_vendor_space);
if (status->flag & (RX_FLAG_FAILED_FCS_CRC |
RX_FLAG_FAILED_PLCP_CRC |
RX_FLAG_AMPDU_IS_ZEROLEN))
return true;
if (unlikely(skb->len < 16 + present_fcs_len + rtap_vendor_space))
return true;
if (ieee80211_is_ctl(hdr->frame_control) &&
!ieee80211_is_pspoll(hdr->frame_control) &&
!ieee80211_is_back_req(hdr->frame_control))
return true;
return false;
}
static int
ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
struct ieee80211_rx_status *status,
struct sk_buff *skb)
{
int len;
/* always present fields */
len = sizeof(struct ieee80211_radiotap_header) + 8;
/* allocate extra bitmaps */
if (status->chains)
len += 4 * hweight8(status->chains);
if (ieee80211_have_rx_timestamp(status)) {
len = ALIGN(len, 8);
len += 8;
}
if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
len += 1;
/* antenna field, if we don't have per-chain info */
if (!status->chains)
len += 1;
/* padding for RX_FLAGS if necessary */
len = ALIGN(len, 2);
if (status->flag & RX_FLAG_HT) /* HT info */
len += 3;
if (status->flag & RX_FLAG_AMPDU_DETAILS) {
len = ALIGN(len, 4);
len += 8;
}
if (status->flag & RX_FLAG_VHT) {
len = ALIGN(len, 2);
len += 12;
}
if (status->chains) {
/* antenna and antenna signal fields */
len += 2 * hweight8(status->chains);
}
if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
struct ieee80211_vendor_radiotap *rtap = (void *)skb->data;
/* vendor presence bitmap */
len += 4;
/* alignment for fixed 6-byte vendor data header */
len = ALIGN(len, 2);
/* vendor data header */
len += 6;
if (WARN_ON(rtap->align == 0))
rtap->align = 1;
len = ALIGN(len, rtap->align);
len += rtap->len + rtap->pad;
}
return len;
}
/*
* ieee80211_add_rx_radiotap_header - add radiotap header
*
* add a radiotap header containing all the fields which the hardware provided.
*/
static void
ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
struct sk_buff *skb,
struct ieee80211_rate *rate,
int rtap_len, bool has_fcs)
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_radiotap_header *rthdr;
unsigned char *pos;
__le32 *it_present;
u32 it_present_val;
u16 rx_flags = 0;
u16 channel_flags = 0;
int mpdulen, chain;
unsigned long chains = status->chains;
struct ieee80211_vendor_radiotap rtap = {};
if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
rtap = *(struct ieee80211_vendor_radiotap *)skb->data;
/* rtap.len and rtap.pad are undone immediately */
skb_pull(skb, sizeof(rtap) + rtap.len + rtap.pad);
}
mpdulen = skb->len;
if (!(has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)))
mpdulen += FCS_LEN;
rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
memset(rthdr, 0, rtap_len - rtap.len - rtap.pad);
it_present = &rthdr->it_present;
/* radiotap header, set always present flags */
rthdr->it_len = cpu_to_le16(rtap_len);
it_present_val = BIT(IEEE80211_RADIOTAP_FLAGS) |
BIT(IEEE80211_RADIOTAP_CHANNEL) |
BIT(IEEE80211_RADIOTAP_RX_FLAGS);
if (!status->chains)
it_present_val |= BIT(IEEE80211_RADIOTAP_ANTENNA);
for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) {
it_present_val |=
BIT(IEEE80211_RADIOTAP_EXT) |
BIT(IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE);
put_unaligned_le32(it_present_val, it_present);
it_present++;
it_present_val = BIT(IEEE80211_RADIOTAP_ANTENNA) |
BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
}
if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
it_present_val |= BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE) |
BIT(IEEE80211_RADIOTAP_EXT);
put_unaligned_le32(it_present_val, it_present);
it_present++;
it_present_val = rtap.present;
}
put_unaligned_le32(it_present_val, it_present);
pos = (void *)(it_present + 1);
/* the order of the following fields is important */
/* IEEE80211_RADIOTAP_TSFT */
if (ieee80211_have_rx_timestamp(status)) {
/* padding */
while ((pos - (u8 *)rthdr) & 7)
*pos++ = 0;
put_unaligned_le64(
ieee80211_calculate_rx_timestamp(local, status,
mpdulen, 0),
pos);
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
pos += 8;
}
/* IEEE80211_RADIOTAP_FLAGS */
if (has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS))
*pos |= IEEE80211_RADIOTAP_F_FCS;
if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
*pos |= IEEE80211_RADIOTAP_F_BADFCS;
if (status->flag & RX_FLAG_SHORTPRE)
*pos |= IEEE80211_RADIOTAP_F_SHORTPRE;
pos++;
/* IEEE80211_RADIOTAP_RATE */
if (!rate || status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) {
/*
* Without rate information don't add it. If we have,
* MCS information is a separate field in radiotap,
* added below. The byte here is needed as padding
* for the channel though, so initialise it to 0.
*/
*pos = 0;
} else {
int shift = 0;
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
if (status->flag & RX_FLAG_10MHZ)
shift = 1;
else if (status->flag & RX_FLAG_5MHZ)
shift = 2;
*pos = DIV_ROUND_UP(rate->bitrate, 5 * (1 << shift));
}
pos++;
/* IEEE80211_RADIOTAP_CHANNEL */
put_unaligned_le16(status->freq, pos);
pos += 2;
if (status->flag & RX_FLAG_10MHZ)
channel_flags |= IEEE80211_CHAN_HALF;
else if (status->flag & RX_FLAG_5MHZ)
channel_flags |= IEEE80211_CHAN_QUARTER;
if (status->band == IEEE80211_BAND_5GHZ)
channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ;
else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
channel_flags |= IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
else if (rate && rate->flags & IEEE80211_RATE_ERP_G)
channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ;
else if (rate)
channel_flags |= IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ;
else
channel_flags |= IEEE80211_CHAN_2GHZ;
put_unaligned_le16(channel_flags, pos);
pos += 2;
/* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM &&
!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
*pos = status->signal;
rthdr->it_present |=
cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
pos++;
}
/* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */
if (!status->chains) {
/* IEEE80211_RADIOTAP_ANTENNA */
*pos = status->antenna;
pos++;
}
/* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */
/* IEEE80211_RADIOTAP_RX_FLAGS */
/* ensure 2 byte alignment for the 2 byte field as required */
if ((pos - (u8 *)rthdr) & 1)
*pos++ = 0;
if (status->flag & RX_FLAG_FAILED_PLCP_CRC)
rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP;
put_unaligned_le16(rx_flags, pos);
pos += 2;
if (status->flag & RX_FLAG_HT) {
unsigned int stbc;
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
*pos++ = local->hw.radiotap_mcs_details;
*pos = 0;
if (status->flag & RX_FLAG_SHORT_GI)
*pos |= IEEE80211_RADIOTAP_MCS_SGI;
if (status->flag & RX_FLAG_40MHZ)
*pos |= IEEE80211_RADIOTAP_MCS_BW_40;
if (status->flag & RX_FLAG_HT_GF)
*pos |= IEEE80211_RADIOTAP_MCS_FMT_GF;
if (status->flag & RX_FLAG_LDPC)
*pos |= IEEE80211_RADIOTAP_MCS_FEC_LDPC;
stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT;
*pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT;
pos++;
*pos++ = status->rate_idx;
}
if (status->flag & RX_FLAG_AMPDU_DETAILS) {
u16 flags = 0;
/* ensure 4 byte alignment */
while ((pos - (u8 *)rthdr) & 3)
pos++;
rthdr->it_present |=
cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS);
put_unaligned_le32(status->ampdu_reference, pos);
pos += 4;
if (status->flag & RX_FLAG_AMPDU_REPORT_ZEROLEN)
flags |= IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN;
if (status->flag & RX_FLAG_AMPDU_IS_ZEROLEN)
flags |= IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN;
if (status->flag & RX_FLAG_AMPDU_LAST_KNOWN)
flags |= IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN;
if (status->flag & RX_FLAG_AMPDU_IS_LAST)
flags |= IEEE80211_RADIOTAP_AMPDU_IS_LAST;
if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_ERROR)
flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR;
if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN)
flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN;
put_unaligned_le16(flags, pos);
pos += 2;
if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN)
*pos++ = status->ampdu_delimiter_crc;
else
*pos++ = 0;
*pos++ = 0;
}
if (status->flag & RX_FLAG_VHT) {
u16 known = local->hw.radiotap_vht_details;
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
put_unaligned_le16(known, pos);
pos += 2;
/* flags */
if (status->flag & RX_FLAG_SHORT_GI)
*pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
/* in VHT, STBC is binary */
if (status->flag & RX_FLAG_STBC_MASK)
*pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC;
if (status->vht_flag & RX_VHT_FLAG_BF)
*pos |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED;
pos++;
/* bandwidth */
if (status->vht_flag & RX_VHT_FLAG_80MHZ)
*pos++ = 4;
else if (status->vht_flag & RX_VHT_FLAG_160MHZ)
*pos++ = 11;
else if (status->flag & RX_FLAG_40MHZ)
*pos++ = 1;
else /* 20 MHz */
*pos++ = 0;
/* MCS/NSS */
*pos = (status->rate_idx << 4) | status->vht_nss;
pos += 4;
/* coding field */
if (status->flag & RX_FLAG_LDPC)
*pos |= IEEE80211_RADIOTAP_CODING_LDPC_USER0;
pos++;
/* group ID */
pos++;
/* partial_aid */
pos += 2;
}
for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) {
*pos++ = status->chain_signal[chain];
*pos++ = chain;
}
if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
/* ensure 2 byte alignment for the vendor field as required */
if ((pos - (u8 *)rthdr) & 1)
*pos++ = 0;
*pos++ = rtap.oui[0];
*pos++ = rtap.oui[1];
*pos++ = rtap.oui[2];
*pos++ = rtap.subns;
put_unaligned_le16(rtap.len, pos);
pos += 2;
/* align the actual payload as requested */
while ((pos - (u8 *)rthdr) & (rtap.align - 1))
*pos++ = 0;
/* data (and possible padding) already follows */
}
}
/*
* This function copies a received frame to all monitor interfaces and
* returns a cleaned-up SKB that no longer includes the FCS nor the
* radiotap header the driver might have added.
*/
static struct sk_buff *
ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
struct ieee80211_rate *rate)
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb);
struct ieee80211_sub_if_data *sdata;
int rt_hdrlen, needed_headroom;
struct sk_buff *skb, *skb2;
struct net_device *prev_dev = NULL;
int present_fcs_len = 0;
unsigned int rtap_vendor_space = 0;
if (unlikely(status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA)) {
struct ieee80211_vendor_radiotap *rtap = (void *)origskb->data;
rtap_vendor_space = sizeof(*rtap) + rtap->len + rtap->pad;
}
/*
* First, we may need to make a copy of the skb because
* (1) we need to modify it for radiotap (if not present), and
* (2) the other RX handlers will modify the skb we got.
*
* We don't need to, of course, if we aren't going to return
* the SKB because it has a bad FCS/PLCP checksum.
*/
if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
present_fcs_len = FCS_LEN;
/* ensure hdr->frame_control and vendor radiotap data are in skb head */
if (!pskb_may_pull(origskb, 2 + rtap_vendor_space)) {
dev_kfree_skb(origskb);
return NULL;
}
if (!local->monitors) {
if (should_drop_frame(origskb, present_fcs_len,
rtap_vendor_space)) {
dev_kfree_skb(origskb);
return NULL;
}
return remove_monitor_info(local, origskb, rtap_vendor_space);
}
/* room for the radiotap header based on driver features */
rt_hdrlen = ieee80211_rx_radiotap_hdrlen(local, status, origskb);
needed_headroom = rt_hdrlen - rtap_vendor_space;
if (should_drop_frame(origskb, present_fcs_len, rtap_vendor_space)) {
/* only need to expand headroom if necessary */
skb = origskb;
origskb = NULL;
/*
* This shouldn't trigger often because most devices have an
* RX header they pull before we get here, and that should
* be big enough for our radiotap information. We should
* probably export the length to drivers so that we can have
* them allocate enough headroom to start with.
*/
if (skb_headroom(skb) < needed_headroom &&
pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC)) {
dev_kfree_skb(skb);
return NULL;
}
} else {
/*
* Need to make a copy and possibly remove radiotap header
* and FCS from the original.
*/
skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC);
origskb = remove_monitor_info(local, origskb,
rtap_vendor_space);
if (!skb)
return origskb;
}
/* prepend radiotap information */
ieee80211_add_rx_radiotap_header(local, skb, rate, rt_hdrlen, true);
skb_reset_mac_header(skb);
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = htons(ETH_P_802_2);
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
continue;
if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
continue;
if (!ieee80211_sdata_running(sdata))
continue;
if (prev_dev) {
skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2) {
skb2->dev = prev_dev;
netif_receive_skb(skb2);
}
}
prev_dev = sdata->dev;
ieee80211_rx_stats(sdata->dev, skb->len);
}
if (prev_dev) {
skb->dev = prev_dev;
netif_receive_skb(skb);
} else
dev_kfree_skb(skb);
return origskb;
}
static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
int tid, seqno_idx, security_idx;
/* does the frame have a qos control field? */
if (ieee80211_is_data_qos(hdr->frame_control)) {
u8 *qc = ieee80211_get_qos_ctl(hdr);
/* frame has qos control */
tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
status->rx_flags |= IEEE80211_RX_AMSDU;
seqno_idx = tid;
security_idx = tid;
} else {
/*
* IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"):
*
* Sequence numbers for management frames, QoS data
* frames with a broadcast/multicast address in the
* Address 1 field, and all non-QoS data frames sent
* by QoS STAs are assigned using an additional single
* modulo-4096 counter, [...]
*
* We also use that counter for non-QoS STAs.
*/
seqno_idx = IEEE80211_NUM_TIDS;
security_idx = 0;
if (ieee80211_is_mgmt(hdr->frame_control))
security_idx = IEEE80211_NUM_TIDS;
tid = 0;
}
rx->seqno_idx = seqno_idx;
rx->security_idx = security_idx;
/* Set skb->priority to 1d tag if highest order bit of TID is not set.
* For now, set skb->priority to 0 for other cases. */
rx->skb->priority = (tid > 7) ? 0 : tid;
}
/**
* DOC: Packet alignment
*
* Drivers always need to pass packets that are aligned to two-byte boundaries
* to the stack.
*
* Additionally, should, if possible, align the payload data in a way that
* guarantees that the contained IP header is aligned to a four-byte
* boundary. In the case of regular frames, this simply means aligning the
* payload to a four-byte boundary (because either the IP header is directly
* contained, or IV/RFC1042 headers that have a length divisible by four are
* in front of it). If the payload data is not properly aligned and the
* architecture doesn't support efficient unaligned operations, mac80211
* will align the data.
*
* With A-MSDU frames, however, the payload data address must yield two modulo
* four because there are 14-byte 802.3 headers within the A-MSDU frames that
* push the IP header further back to a multiple of four again. Thankfully, the
* specs were sane enough this time around to require padding each A-MSDU
* subframe to a length that is a multiple of four.
*
* Padding like Atheros hardware adds which is between the 802.11 header and
* the payload is not supported, the driver is required to move the 802.11
* header to be directly in front of the payload in that case.
*/
static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx)
{
#ifdef CPTCFG_MAC80211_VERBOSE_DEBUG
WARN_ONCE((unsigned long)rx->skb->data & 1,
"unaligned packet at 0x%p\n", rx->skb->data);
#endif
}
/* rx handlers */
static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
if (is_multicast_ether_addr(hdr->addr1))
return 0;
return ieee80211_is_robust_mgmt_frame(skb);
}
static int ieee80211_is_multicast_robust_mgmt_frame(struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
if (!is_multicast_ether_addr(hdr->addr1))
return 0;
return ieee80211_is_robust_mgmt_frame(skb);
}
/* Get the BIP key index from MMIE; return -1 if this is not a BIP frame */
static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
{
struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data;
struct ieee80211_mmie *mmie;
struct ieee80211_mmie_16 *mmie16;
if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
return -1;
if (!ieee80211_is_robust_mgmt_frame(skb))
return -1; /* not a robust management frame */
mmie = (struct ieee80211_mmie *)
(skb->data + skb->len - sizeof(*mmie));
if (mmie->element_id == WLAN_EID_MMIE &&
mmie->length == sizeof(*mmie) - 2)
return le16_to_cpu(mmie->key_id);
mmie16 = (struct ieee80211_mmie_16 *)
(skb->data + skb->len - sizeof(*mmie16));
if (skb->len >= 24 + sizeof(*mmie16) &&
mmie16->element_id == WLAN_EID_MMIE &&
mmie16->length == sizeof(*mmie16) - 2)
return le16_to_cpu(mmie16->key_id);
return -1;
}
static int iwl80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc;
int hdrlen;
u8 keyid;
fc = hdr->frame_control;
hdrlen = ieee80211_hdrlen(fc);
if (skb->len < hdrlen + cs->hdr_len)
return -EINVAL;
skb_copy_bits(skb, hdrlen + cs->key_idx_off, &keyid, 1);
keyid &= cs->key_idx_mask;
keyid >>= cs->key_idx_shift;
return keyid;
}
static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
char *dev_addr = rx->sdata->vif.addr;
if (ieee80211_is_data(hdr->frame_control)) {
if (is_multicast_ether_addr(hdr->addr1)) {
if (ieee80211_has_tods(hdr->frame_control) ||
!ieee80211_has_fromds(hdr->frame_control))
return RX_DROP_MONITOR;
if (ether_addr_equal(hdr->addr3, dev_addr))
return RX_DROP_MONITOR;
} else {
if (!ieee80211_has_a4(hdr->frame_control))
return RX_DROP_MONITOR;
if (ether_addr_equal(hdr->addr4, dev_addr))
return RX_DROP_MONITOR;
}
}
/* If there is not an established peer link and this is not a peer link
* establisment frame, beacon or probe, drop the frame.
*/
if (!rx->sta || sta_plink_state(rx->sta) != NL80211_PLINK_ESTAB) {
struct ieee80211_mgmt *mgmt;
if (!ieee80211_is_mgmt(hdr->frame_control))
return RX_DROP_MONITOR;
if (ieee80211_is_action(hdr->frame_control)) {
u8 category;
/* make sure category field is present */
if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
return RX_DROP_MONITOR;
mgmt = (struct ieee80211_mgmt *)hdr;
category = mgmt->u.action.category;
if (category != WLAN_CATEGORY_MESH_ACTION &&
category != WLAN_CATEGORY_SELF_PROTECTED)
return RX_DROP_MONITOR;
return RX_CONTINUE;
}
if (ieee80211_is_probe_req(hdr->frame_control) ||
ieee80211_is_probe_resp(hdr->frame_control) ||
ieee80211_is_beacon(hdr->frame_control) ||
ieee80211_is_auth(hdr->frame_control))
return RX_CONTINUE;
return RX_DROP_MONITOR;
}
return RX_CONTINUE;
}
static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
struct tid_ampdu_rx *tid_agg_rx,
int index,
struct sk_buff_head *frames)
{
struct sk_buff_head *skb_list = &tid_agg_rx->reorder_buf[index];
struct sk_buff *skb;
struct ieee80211_rx_status *status;
lockdep_assert_held(&tid_agg_rx->reorder_lock);
if (skb_queue_empty(skb_list))
goto no_frame;
if (!ieee80211_rx_reorder_ready(skb_list)) {
__skb_queue_purge(skb_list);
goto no_frame;
}
/* release frames from the reorder ring buffer */
tid_agg_rx->stored_mpdu_num--;
while ((skb = __skb_dequeue(skb_list))) {
status = IEEE80211_SKB_RXCB(skb);
status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE;
__skb_queue_tail(frames, skb);
}
no_frame:
tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num);
}
static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata,
struct tid_ampdu_rx *tid_agg_rx,
u16 head_seq_num,
struct sk_buff_head *frames)
{
int index;
lockdep_assert_held(&tid_agg_rx->reorder_lock);
while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) {
index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
frames);
}
}
/*
* Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If
* the skb was added to the buffer longer than this time ago, the earlier
* frames that have not yet been received are assumed to be lost and the skb
* can be released for processing. This may also release other skb's from the
* reorder buffer if there are no additional gaps between the frames.
*
* Callers must hold tid_agg_rx->reorder_lock.
*/
#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
struct tid_ampdu_rx *tid_agg_rx,
struct sk_buff_head *frames)
{
int index, i, j;
lockdep_assert_held(&tid_agg_rx->reorder_lock);
/* release the buffer until next missing frame */
index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
if (!ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index]) &&
tid_agg_rx->stored_mpdu_num) {
/*
* No buffers ready to be released, but check whether any
* frames in the reorder buffer have timed out.
*/
int skipped = 1;
for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
j = (j + 1) % tid_agg_rx->buf_size) {
if (!ieee80211_rx_reorder_ready(
&tid_agg_rx->reorder_buf[j])) {
skipped++;
continue;
}
if (skipped &&
!time_after(jiffies, tid_agg_rx->reorder_time[j] +
HT_RX_REORDER_BUF_TIMEOUT))
goto set_release_timer;
/* don't leave incomplete A-MSDUs around */
for (i = (index + 1) % tid_agg_rx->buf_size; i != j;
i = (i + 1) % tid_agg_rx->buf_size)
__skb_queue_purge(&tid_agg_rx->reorder_buf[i]);
ht_dbg_ratelimited(sdata,
"release an RX reorder frame due to timeout on earlier frames\n");
ieee80211_release_reorder_frame(sdata, tid_agg_rx, j,
frames);
/*
* Increment the head seq# also for the skipped slots.
*/
tid_agg_rx->head_seq_num =
(tid_agg_rx->head_seq_num +
skipped) & IEEE80211_SN_MASK;
skipped = 0;
}
} else while (ieee80211_rx_reorder_ready(
&tid_agg_rx->reorder_buf[index])) {
ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
frames);
index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
}
if (tid_agg_rx->stored_mpdu_num) {
j = index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
for (; j != (index - 1) % tid_agg_rx->buf_size;
j = (j + 1) % tid_agg_rx->buf_size) {
if (ieee80211_rx_reorder_ready(
&tid_agg_rx->reorder_buf[j]))
break;
}
set_release_timer:
if (!tid_agg_rx->removed)
mod_timer(&tid_agg_rx->reorder_timer,
tid_agg_rx->reorder_time[j] + 1 +
HT_RX_REORDER_BUF_TIMEOUT);
} else {
del_timer(&tid_agg_rx->reorder_timer);
}
}
/*
* As this function belongs to the RX path it must be under
* rcu_read_lock protection. It returns false if the frame
* can be processed immediately, true if it was consumed.
*/
static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata,
struct tid_ampdu_rx *tid_agg_rx,
struct sk_buff *skb,
struct sk_buff_head *frames)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
u16 sc = le16_to_cpu(hdr->seq_ctrl);
u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
u16 head_seq_num, buf_size;
int index;
bool ret = true;
spin_lock(&tid_agg_rx->reorder_lock);
/*
* Offloaded BA sessions have no known starting sequence number so pick
* one from first Rxed frame for this tid after BA was started.
*/
if (unlikely(tid_agg_rx->auto_seq)) {
tid_agg_rx->auto_seq = false;
tid_agg_rx->ssn = mpdu_seq_num;
tid_agg_rx->head_seq_num = mpdu_seq_num;
}
buf_size = tid_agg_rx->buf_size;
head_seq_num = tid_agg_rx->head_seq_num;
/* frame with out of date sequence number */
if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
dev_kfree_skb(skb);
goto out;
}
/*
* If frame the sequence number exceeds our buffering window
* size release some previous frames to make room for this one.
*/
if (!ieee80211_sn_less(mpdu_seq_num, head_seq_num + buf_size)) {
head_seq_num = ieee80211_sn_inc(
ieee80211_sn_sub(mpdu_seq_num, buf_size));
/* release stored frames up to new head to stack */
ieee80211_release_reorder_frames(sdata, tid_agg_rx,
head_seq_num, frames);
}
/* Now the new frame is always in the range of the reordering buffer */
index = mpdu_seq_num % tid_agg_rx->buf_size;
/* check if we already stored this frame */
if (ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index])) {
dev_kfree_skb(skb);
goto out;
}
/*
* If the current MPDU is in the right order and nothing else
* is stored we can process it directly, no need to buffer it.
* If it is first but there's something stored, we may be able
* to release frames after this one.
*/
if (mpdu_seq_num == tid_agg_rx->head_seq_num &&
tid_agg_rx->stored_mpdu_num == 0) {
if (!(status->flag & RX_FLAG_AMSDU_MORE))
tid_agg_rx->head_seq_num =
ieee80211_sn_inc(tid_agg_rx->head_seq_num);
ret = false;
goto out;
}
/* put the frame in the reordering buffer */
__skb_queue_tail(&tid_agg_rx->reorder_buf[index], skb);
if (!(status->flag & RX_FLAG_AMSDU_MORE)) {
tid_agg_rx->reorder_time[index] = jiffies;
tid_agg_rx->stored_mpdu_num++;
ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames);
}
out:
spin_unlock(&tid_agg_rx->reorder_lock);
return ret;
}
/*
* Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns
* true if the MPDU was buffered, false if it should be processed.
*/
static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
struct sk_buff_head *frames)
{
struct sk_buff *skb = rx->skb;
struct ieee80211_local *local = rx->local;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct sta_info *sta = rx->sta;
struct tid_ampdu_rx *tid_agg_rx;
u16 sc;
u8 tid, ack_policy;
if (!ieee80211_is_data_qos(hdr->frame_control) ||
is_multicast_ether_addr(hdr->addr1))
goto dont_reorder;
/*
* filter the QoS data rx stream according to
* STA/TID and check if this STA/TID is on aggregation
*/
if (!sta)
goto dont_reorder;
ack_policy = *ieee80211_get_qos_ctl(hdr) &
IEEE80211_QOS_CTL_ACK_POLICY_MASK;
tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
if (!tid_agg_rx)
goto dont_reorder;
/* qos null data frames are excluded */
if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
goto dont_reorder;
/* not part of a BA session */
if (ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK &&
ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)
goto dont_reorder;
/* new, potentially un-ordered, ampdu frame - process it */
/* reset session timer */
if (tid_agg_rx->timeout)
tid_agg_rx->last_rx = jiffies;
/* if this mpdu is fragmented - terminate rx aggregation session */
sc = le16_to_cpu(hdr->seq_ctrl);
if (sc & IEEE80211_SCTL_FRAG) {
skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
skb_queue_tail(&rx->sdata->skb_queue, skb);
ieee80211_queue_work(&local->hw, &rx->sdata->work);
return;
}
/*
* No locking needed -- we will only ever process one
* RX packet at a time, and thus own tid_agg_rx. All
* other code manipulating it needs to (and does) make
* sure that we cannot get to it any more before doing
* anything with it.
*/
if (ieee80211_sta_manage_reorder_buf(rx->sdata, tid_agg_rx, skb,
frames))
return;
dont_reorder:
__skb_queue_tail(frames, skb);
}
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
/*
* Drop duplicate 802.11 retransmissions
* (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
*/
if (rx->skb->len < 24)
return RX_CONTINUE;
if (ieee80211_is_ctl(hdr->frame_control) ||
ieee80211_is_qos_nullfunc(hdr->frame_control) ||
is_multicast_ether_addr(hdr->addr1))
return RX_CONTINUE;
if (rx->sta) {
if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
rx->sta->last_seq_ctrl[rx->seqno_idx] ==
hdr->seq_ctrl)) {
I802_DEBUG_INC(rx->local->dot11FrameDuplicateCount);
rx->sta->num_duplicates++;
return RX_DROP_UNUSABLE;
} else if (!(status->flag & RX_FLAG_AMSDU_MORE)) {
rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl;
}
}
return RX_CONTINUE;
}
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
if (unlikely(rx->skb->len < 16)) {
I802_DEBUG_INC(rx->local->rx_handlers_drop_short);
return RX_DROP_MONITOR;
}
/* Drop disallowed frame classes based on STA auth/assoc state;
* IEEE 802.11, Chap 5.5.
*
* mac80211 filters only based on association state, i.e. it drops
* Class 3 frames from not associated stations. hostapd sends
* deauth/disassoc frames when needed. In addition, hostapd is
* responsible for filtering on both auth and assoc states.
*/
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
return ieee80211_rx_mesh_check(rx);
if (unlikely((ieee80211_is_data(hdr->frame_control) ||
ieee80211_is_pspoll(hdr->frame_control)) &&
rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
rx->sdata->vif.type != NL80211_IFTYPE_OCB &&
(!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) {
/*
* accept port control frames from the AP even when it's not
* yet marked ASSOC to prevent a race where we don't set the
* assoc bit quickly enough before it sends the first frame
*/
if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
ieee80211_is_data_present(hdr->frame_control)) {
unsigned int hdrlen;
__be16 ethertype;
hdrlen = ieee80211_hdrlen(hdr->frame_control);
if (rx->skb->len < hdrlen + 8)
return RX_DROP_MONITOR;
skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2);
if (ethertype == rx->sdata->control_port_protocol)
return RX_CONTINUE;
}
if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
cfg80211_rx_spurious_frame(rx->sdata->dev,
hdr->addr2,
GFP_ATOMIC))
return RX_DROP_UNUSABLE;
return RX_DROP_MONITOR;
}
return RX_CONTINUE;
}
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_check_more_data(struct ieee80211_rx_data *rx)
{
struct ieee80211_local *local;
struct ieee80211_hdr *hdr;
struct sk_buff *skb;
local = rx->local;
skb = rx->skb;
hdr = (struct ieee80211_hdr *) skb->data;
if (!local->pspolling)
return RX_CONTINUE;
if (!ieee80211_has_fromds(hdr->frame_control))
/* this is not from AP */
return RX_CONTINUE;
if (!ieee80211_is_data(hdr->frame_control))
return RX_CONTINUE;
if (!ieee80211_has_moredata(hdr->frame_control)) {
/* AP has no more frames buffered for us */
local->pspolling = false;
return RX_CONTINUE;
}
/* more data bit is set, let's request a new frame from the AP */
ieee80211_send_pspoll(local, rx->sdata);
return RX_CONTINUE;
}
static void sta_ps_start(struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_local *local = sdata->local;
struct ps_data *ps;
int tid;
if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
ps = &sdata->bss->ps;
else
return;
atomic_inc(&ps->num_sta_ps);
set_sta_flag(sta, WLAN_STA_PS_STA);
if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
ps_dbg(sdata, "STA %pM aid %d enters power save mode\n",
sta->sta.addr, sta->sta.aid);
ieee80211_clear_fast_xmit(sta);
if (!sta->sta.txq[0])
return;
for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);
if (!skb_queue_len(&txqi->queue))
set_bit(tid, &sta->txq_buffered_tids);
else
clear_bit(tid, &sta->txq_buffered_tids);
}
}
static void sta_ps_end(struct sta_info *sta)
{
ps_dbg(sta->sdata, "STA %pM aid %d exits power save mode\n",
sta->sta.addr, sta->sta.aid);
if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
/*
* Clear the flag only if the other one is still set
* so that the TX path won't start TX'ing new frames
* directly ... In the case that the driver flag isn't
* set ieee80211_sta_ps_deliver_wakeup() will clear it.
*/
clear_sta_flag(sta, WLAN_STA_PS_STA);
ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n",
sta->sta.addr, sta->sta.aid);
return;
}
set_sta_flag(sta, WLAN_STA_PS_DELIVER);
clear_sta_flag(sta, WLAN_STA_PS_STA);
ieee80211_sta_ps_deliver_wakeup(sta);
}
int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start)
{
struct sta_info *sta_inf = container_of(sta, struct sta_info, sta);
bool in_ps;
WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS));
/* Don't let the same PS state be set twice */
in_ps = test_sta_flag(sta_inf, WLAN_STA_PS_STA);
if ((start && in_ps) || (!start && !in_ps))
return -EINVAL;
if (start)
sta_ps_start(sta_inf);
else
sta_ps_end(sta_inf);
return 0;
}
EXPORT_SYMBOL(ieee80211_sta_ps_transition);
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct ieee80211_hdr *hdr = (void *)rx->skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
int tid, ac;
if (!rx->sta)
return RX_CONTINUE;
if (sdata->vif.type != NL80211_IFTYPE_AP &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
return RX_CONTINUE;
/*
* The device handles station powersave, so don't do anything about
* uAPSD and PS-Poll frames (the latter shouldn't even come up from
* it to mac80211 since they're handled.)
*/
if (sdata->local->hw.flags & IEEE80211_HW_AP_LINK_PS)
return RX_CONTINUE;
/*
* Don't do anything if the station isn't already asleep. In
* the uAPSD case, the station will probably be marked asleep,
* in the PS-Poll case the station must be confused ...
*/
if (!test_sta_flag(rx->sta, WLAN_STA_PS_STA))
return RX_CONTINUE;
if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) {
if (!test_sta_flag(rx->sta, WLAN_STA_SP)) {
if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER))
ieee80211_sta_ps_deliver_poll_response(rx->sta);
else
set_sta_flag(rx->sta, WLAN_STA_PSPOLL);
}
/* Free PS Poll skb here instead of returning RX_DROP that would
* count as an dropped frame. */
dev_kfree_skb(rx->skb);
return RX_QUEUED;
} else if (!ieee80211_has_morefrags(hdr->frame_control) &&
!(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
ieee80211_has_pm(hdr->frame_control) &&
(ieee80211_is_data_qos(hdr->frame_control) ||
ieee80211_is_qos_nullfunc(hdr->frame_control))) {
tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
ac = ieee802_1d_to_ac[tid & 7];
/*
* If this AC is not trigger-enabled do nothing.
*
* NB: This could/should check a separate bitmap of trigger-
* enabled queues, but for now we only implement uAPSD w/o
* TSPEC changes to the ACs, so they're always the same.
*/
if (!(rx->sta->sta.uapsd_queues & BIT(ac)))
return RX_CONTINUE;
/* if we are in a service period, do nothing */
if (test_sta_flag(rx->sta, WLAN_STA_SP))
return RX_CONTINUE;
if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER))
ieee80211_sta_ps_deliver_uapsd(rx->sta);
else
set_sta_flag(rx->sta, WLAN_STA_UAPSD);
}
return RX_CONTINUE;
}
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
{
struct sta_info *sta = rx->sta;
struct sk_buff *skb = rx->skb;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
int i;
if (!sta)
return RX_CONTINUE;
/*
* Update last_rx only for IBSS packets which are for the current
* BSSID and for station already AUTHORIZED to avoid keeping the
* current IBSS network alive in cases where other STAs start
* using different BSSID. This will also give the station another
* chance to restart the authentication/authorization in case
* something went wrong the first time.
*/
if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
NL80211_IFTYPE_ADHOC);
if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) &&
test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
sta->last_rx = jiffies;
if (ieee80211_is_data(hdr->frame_control) &&
!is_multicast_ether_addr(hdr->addr1)) {
sta->last_rx_rate_idx = status->rate_idx;
sta->last_rx_rate_flag = status->flag;
sta->last_rx_rate_vht_flag = status->vht_flag;
sta->last_rx_rate_vht_nss = status->vht_nss;
}
}
} else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) {
sta->last_rx = jiffies;
} else if (!is_multicast_ether_addr(hdr->addr1)) {
/*
* Mesh beacons will update last_rx when if they are found to
* match the current local configuration when processed.
*/
sta->last_rx = jiffies;
if (ieee80211_is_data(hdr->frame_control)) {
sta->last_rx_rate_idx = status->rate_idx;
sta->last_rx_rate_flag = status->flag;
sta->last_rx_rate_vht_flag = status->vht_flag;
sta->last_rx_rate_vht_nss = status->vht_nss;
}
}
if (rx->sdata->vif.type == NL80211_IFTYPE_STATION)
ieee80211_sta_rx_notify(rx->sdata, hdr);
sta->rx_fragments++;
sta->rx_bytes += rx->skb->len;
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
sta->last_signal = status->signal;
ewma_add(&sta->avg_signal, -status->signal);
}
if (status->chains) {
sta->chains = status->chains;
for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) {
int signal = status->chain_signal[i];
if (!(status->chains & BIT(i)))
continue;
sta->chain_signal_last[i] = signal;
ewma_add(&sta->chain_signal_avg[i], -signal);
}
}
/*
* Change STA power saving mode only at the end of a frame
* exchange sequence.
*/
if (!(sta->local->hw.flags & IEEE80211_HW_AP_LINK_PS) &&
!ieee80211_has_morefrags(hdr->frame_control) &&
!(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
(rx->sdata->vif.type == NL80211_IFTYPE_AP ||
rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
/* PM bit is only checked in frames where it isn't reserved,
* in AP mode it's reserved in non-bufferable management frames
* (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field)
*/
(!ieee80211_is_mgmt(hdr->frame_control) ||
ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
if (!ieee80211_has_pm(hdr->frame_control))
sta_ps_end(sta);
} else {
if (ieee80211_has_pm(hdr->frame_control))
sta_ps_start(sta);
}
}
/* mesh power save support */
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
ieee80211_mps_rx_h_sta_process(sta, hdr);
/*
* Drop (qos-)data::nullfunc frames silently, since they
* are used only to control station power saving mode.
*/
if (ieee80211_is_nullfunc(hdr->frame_control) ||
ieee80211_is_qos_nullfunc(hdr->frame_control)) {
I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc);
/*
* If we receive a 4-addr nullfunc frame from a STA
* that was not moved to a 4-addr STA vlan yet send
* the event to userspace and for older hostapd drop
* the frame to the monitor interface.
*/
if (ieee80211_has_a4(hdr->frame_control) &&
(rx->sdata->vif.type == NL80211_IFTYPE_AP ||
(rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
!rx->sdata->u.vlan.sta))) {
if (!test_and_set_sta_flag(sta, WLAN_STA_4ADDR_EVENT))
cfg80211_rx_unexpected_4addr_frame(
rx->sdata->dev, sta->sta.addr,
GFP_ATOMIC);
return RX_DROP_MONITOR;
}
/*
* Update counter and free packet here to avoid
* counting this as a dropped packed.
*/
sta->rx_packets++;
dev_kfree_skb(rx->skb);
return RX_QUEUED;
}
return RX_CONTINUE;
} /* ieee80211_rx_h_sta_process */
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
{
struct sk_buff *skb = rx->skb;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
int keyidx;
int hdrlen;
ieee80211_rx_result result = RX_DROP_UNUSABLE;
struct ieee80211_key *sta_ptk = NULL;
int mmie_keyidx = -1;
__le16 fc;
const struct ieee80211_cipher_scheme *cs = NULL;
/*
* Key selection 101
*
* There are four types of keys:
* - GTK (group keys)
* - IGTK (group keys for management frames)
* - PTK (pairwise keys)
* - STK (station-to-station pairwise keys)
*
* When selecting a key, we have to distinguish between multicast
* (including broadcast) and unicast frames, the latter can only
* use PTKs and STKs while the former always use GTKs and IGTKs.
* Unless, of course, actual WEP keys ("pre-RSNA") are used, then
* unicast frames can also use key indices like GTKs. Hence, if we
* don't have a PTK/STK we check the key index for a WEP key.
*
* Note that in a regular BSS, multicast frames are sent by the
* AP only, associated stations unicast the frame to the AP first
* which then multicasts it on their behalf.
*
* There is also a slight problem in IBSS mode: GTKs are negotiated
* with each station, that is something we don't currently handle.
* The spec seems to expect that one negotiates the same key with
* every station but there's no such requirement; VLANs could be
* possible.
*/
/* start without a key */
rx->key = NULL;
fc = hdr->frame_control;
if (rx->sta) {
int keyid = rx->sta->ptk_idx;
if (ieee80211_has_protected(fc) && rx->sta->cipher_scheme) {
cs = rx->sta->cipher_scheme;
keyid = iwl80211_get_cs_keyid(cs, rx->skb);
if (unlikely(keyid < 0))
return RX_DROP_UNUSABLE;
}
sta_ptk = rcu_dereference(rx->sta->ptk[keyid]);
}
if (!ieee80211_has_protected(fc))
mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
if (!is_multicast_ether_addr(hdr->addr1) && sta_ptk) {
rx->key = sta_ptk;
if ((status->flag & RX_FLAG_DECRYPTED) &&
(status->flag & RX_FLAG_IV_STRIPPED))
return RX_CONTINUE;
/* Skip decryption if the frame is not protected. */
if (!ieee80211_has_protected(fc))
return RX_CONTINUE;
} else if (mmie_keyidx >= 0) {
/* Broadcast/multicast robust management frame / BIP */
if ((status->flag & RX_FLAG_DECRYPTED) &&
(status->flag & RX_FLAG_IV_STRIPPED))
return RX_CONTINUE;
if (mmie_keyidx < NUM_DEFAULT_KEYS ||
mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
return RX_DROP_MONITOR; /* unexpected BIP keyidx */
if (rx->sta)
rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]);
if (!rx->key)
rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]);
} else if (!ieee80211_has_protected(fc)) {
/*
* The frame was not protected, so skip decryption. However, we
* need to set rx->key if there is a key that could have been
* used so that the frame may be dropped if encryption would
* have been expected.
*/
struct ieee80211_key *key = NULL;
struct ieee80211_sub_if_data *sdata = rx->sdata;
int i;
if (ieee80211_is_mgmt(fc) &&
is_multicast_ether_addr(hdr->addr1) &&
(key = rcu_dereference(rx->sdata->default_mgmt_key)))
rx->key = key;
else {
if (rx->sta) {
for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
key = rcu_dereference(rx->sta->gtk[i]);
if (key)
break;
}
}
if (!key) {
for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
key = rcu_dereference(sdata->keys[i]);
if (key)
break;
}
}
if (key)
rx->key = key;
}
return RX_CONTINUE;
} else {
u8 keyid;
/*
* The device doesn't give us the IV so we won't be
* able to look up the key. That's ok though, we
* don't need to decrypt the frame, we just won't
* be able to keep statistics accurate.
* Except for key threshold notifications, should
* we somehow allow the driver to tell us which key
* the hardware used if this flag is set?
*/
if ((status->flag & RX_FLAG_DECRYPTED) &&
(status->flag & RX_FLAG_IV_STRIPPED))
return RX_CONTINUE;
hdrlen = ieee80211_hdrlen(fc);
if (cs) {
keyidx = iwl80211_get_cs_keyid(cs, rx->skb);
if (unlikely(keyidx < 0))
return RX_DROP_UNUSABLE;
} else {
if (rx->skb->len < 8 + hdrlen)
return RX_DROP_UNUSABLE; /* TODO: count this? */
/*
* no need to call ieee80211_wep_get_keyidx,
* it verifies a bunch of things we've done already
*/
skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
keyidx = keyid >> 6;
}
/* check per-station GTK first, if multicast packet */
if (is_multicast_ether_addr(hdr->addr1) && rx->sta)
rx->key = rcu_dereference(rx->sta->gtk[keyidx]);
/* if not found, try default key */
if (!rx->key) {
rx->key = rcu_dereference(rx->sdata->keys[keyidx]);
/*
* RSNA-protected unicast frames should always be
* sent with pairwise or station-to-station keys,
* but for WEP we allow using a key index as well.
*/
if (rx->key &&
rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 &&
rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 &&
!is_multicast_ether_addr(hdr->addr1))
rx->key = NULL;
}
}
if (rx->key) {
if (unlikely(rx->key->flags & KEY_FLAG_TAINTED))
return RX_DROP_MONITOR;
rx->key->tx_rx_count++;
/* TODO: add threshold stuff again */
} else {
return RX_DROP_MONITOR;
}
switch (rx->key->conf.cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
result = ieee80211_crypto_wep_decrypt(rx);
break;
case WLAN_CIPHER_SUITE_TKIP:
result = ieee80211_crypto_tkip_decrypt(rx);
break;
case WLAN_CIPHER_SUITE_CCMP:
result = ieee80211_crypto_ccmp_decrypt(
rx, IEEE80211_CCMP_MIC_LEN);
break;
case WLAN_CIPHER_SUITE_CCMP_256:
result = ieee80211_crypto_ccmp_decrypt(
rx, IEEE80211_CCMP_256_MIC_LEN);
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
result = ieee80211_crypto_aes_cmac_decrypt(rx);
break;
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
result = ieee80211_crypto_aes_cmac_256_decrypt(rx);
break;
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
result = ieee80211_crypto_aes_gmac_decrypt(rx);
break;
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
result = ieee80211_crypto_gcmp_decrypt(rx);
break;
default:
result = ieee80211_crypto_hw_decrypt(rx);
}
/* the hdr variable is invalid after the decrypt handlers */
/* either the frame has been decrypted or will be dropped */
status->flag |= RX_FLAG_DECRYPTED;
return result;
}
static inline struct ieee80211_fragment_entry *
ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
unsigned int frag, unsigned int seq, int rx_queue,
struct sk_buff **skb)
{
struct ieee80211_fragment_entry *entry;
entry = &sdata->fragments[sdata->fragment_next++];
if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)
sdata->fragment_next = 0;
if (!skb_queue_empty(&entry->skb_list))
__skb_queue_purge(&entry->skb_list);
__skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */
*skb = NULL;
entry->first_frag_time = jiffies;
entry->seq = seq;
entry->rx_queue = rx_queue;
entry->last_frag = frag;
entry->ccmp = 0;
entry->extra_len = 0;
return entry;
}
static inline struct ieee80211_fragment_entry *
ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
unsigned int frag, unsigned int seq,
int rx_queue, struct ieee80211_hdr *hdr)
{
struct ieee80211_fragment_entry *entry;
int i, idx;
idx = sdata->fragment_next;
for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
struct ieee80211_hdr *f_hdr;
idx--;
if (idx < 0)
idx = IEEE80211_FRAGMENT_MAX - 1;
entry = &sdata->fragments[idx];
if (skb_queue_empty(&entry->skb_list) || entry->seq != seq ||
entry->rx_queue != rx_queue ||
entry->last_frag + 1 != frag)
continue;
f_hdr = (struct ieee80211_hdr *)entry->skb_list.next->data;
/*
* Check ftype and addresses are equal, else check next fragment
*/
if (((hdr->frame_control ^ f_hdr->frame_control) &
cpu_to_le16(IEEE80211_FCTL_FTYPE)) ||
!ether_addr_equal(hdr->addr1, f_hdr->addr1) ||
!ether_addr_equal(hdr->addr2, f_hdr->addr2))
continue;
if (time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
__skb_queue_purge(&entry->skb_list);
continue;
}
return entry;
}
return NULL;
}
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr;
u16 sc;
__le16 fc;
unsigned int frag, seq;
struct ieee80211_fragment_entry *entry;
struct sk_buff *skb;
struct ieee80211_rx_status *status;
hdr = (struct ieee80211_hdr *)rx->skb->data;
fc = hdr->frame_control;
if (ieee80211_is_ctl(fc))
return RX_CONTINUE;
sc = le16_to_cpu(hdr->seq_ctrl);
frag = sc & IEEE80211_SCTL_FRAG;
if (is_multicast_ether_addr(hdr->addr1)) {
I802_DEBUG_INC(rx->local->dot11MulticastReceivedFrameCount);
goto out_no_led;
}
if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
goto out;
I802_DEBUG_INC(rx->local->rx_handlers_fragments);
if (skb_linearize(rx->skb))
return RX_DROP_UNUSABLE;
/*
* skb_linearize() might change the skb->data and
* previously cached variables (in this case, hdr) need to
* be refreshed with the new data.
*/
hdr = (struct ieee80211_hdr *)rx->skb->data;
seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
if (frag == 0) {
/* This is the first fragment of a new frame. */
entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
rx->seqno_idx, &(rx->skb));
if (rx->key &&
(rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256) &&
ieee80211_has_protected(fc)) {
int queue = rx->security_idx;
/* Store CCMP PN so that we can verify that the next
* fragment has a sequential PN value. */
entry->ccmp = 1;
memcpy(entry->last_pn,
rx->key->u.ccmp.rx_pn[queue],
IEEE80211_CCMP_PN_LEN);
}
return RX_QUEUED;
}
/* This is a fragment for a frame that should already be pending in
* fragment cache. Add this fragment to the end of the pending entry.
*/
entry = ieee80211_reassemble_find(rx->sdata, frag, seq,
rx->seqno_idx, hdr);
if (!entry) {
I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
return RX_DROP_MONITOR;
}
/* Verify that MPDUs within one MSDU have sequential PN values.
* (IEEE 802.11i, 8.3.3.4.5) */
if (entry->ccmp) {
int i;
u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
int queue;
if (!rx->key ||
(rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP &&
rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256))
return RX_DROP_UNUSABLE;
memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
pn[i]++;
if (pn[i])
break;
}
queue = rx->security_idx;
rpn = rx->key->u.ccmp.rx_pn[queue];
if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN))
return RX_DROP_UNUSABLE;
memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);
}
skb_pull(rx->skb, ieee80211_hdrlen(fc));
__skb_queue_tail(&entry->skb_list, rx->skb);
entry->last_frag = frag;
entry->extra_len += rx->skb->len;
if (ieee80211_has_morefrags(fc)) {
rx->skb = NULL;
return RX_QUEUED;
}
rx->skb = __skb_dequeue(&entry->skb_list);
if (skb_tailroom(rx->skb) < entry->extra_len) {
I802_DEBUG_INC(rx->local->rx_expand_skb_head_defrag);
if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len,
GFP_ATOMIC))) {
I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
__skb_queue_purge(&entry->skb_list);
return RX_DROP_UNUSABLE;
}
}
while ((skb = __skb_dequeue(&entry->skb_list))) {
memcpy(skb_put(rx->skb, skb->len), skb->data, skb->len);
dev_kfree_skb(skb);
}
/* Complete frame has been reassembled - process it now */
status = IEEE80211_SKB_RXCB(rx->skb);
status->rx_flags |= IEEE80211_RX_FRAGMENTED;
out:
ieee80211_led_rx(rx->local);
out_no_led:
if (rx->sta)
rx->sta->rx_packets++;
return RX_CONTINUE;
}
static int ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
{
if (unlikely(!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_AUTHORIZED)))
return -EACCES;
return 0;
}
static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
{
struct sk_buff *skb = rx->skb;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
/*
* Pass through unencrypted frames if the hardware has
* decrypted them already.
*/
if (status->flag & RX_FLAG_DECRYPTED)
return 0;
/* Drop unencrypted frames if key is set. */
if (unlikely(!ieee80211_has_protected(fc) &&
!ieee80211_is_nullfunc(fc) &&
ieee80211_is_data(fc) && rx->key))
return -EACCES;
return 0;
}
static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
__le16 fc = hdr->frame_control;
/*
* Pass through unencrypted frames if the hardware has
* decrypted them already.
*/
if (status->flag & RX_FLAG_DECRYPTED)
return 0;
if (rx->sta && test_sta_flag(rx->sta, WLAN_STA_MFP)) {
if (unlikely(!ieee80211_has_protected(fc) &&
ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
rx->key)) {
if (ieee80211_is_deauth(fc) ||
ieee80211_is_disassoc(fc))
cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
rx->skb->data,
rx->skb->len);
return -EACCES;
}
/* BIP does not use Protected field, so need to check MMIE */
if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) &&
ieee80211_get_mmie_keyidx(rx->skb) < 0)) {
if (ieee80211_is_deauth(fc) ||
ieee80211_is_disassoc(fc))
cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
rx->skb->data,
rx->skb->len);
return -EACCES;
}
/*
* When using MFP, Action frames are not allowed prior to
* having configured keys.
*/
if (unlikely(ieee80211_is_action(fc) && !rx->key &&
ieee80211_is_robust_mgmt_frame(rx->skb)))
return -EACCES;
}
return 0;
}
static int
__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control)
{
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
bool check_port_control = false;
struct ethhdr *ehdr;
int ret;
*port_control = false;
if (ieee80211_has_a4(hdr->frame_control) &&
sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
return -1;
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
!!sdata->u.mgd.use_4addr != !!ieee80211_has_a4(hdr->frame_control)) {
if (!sdata->u.mgd.use_4addr)
return -1;
else
check_port_control = true;
}
if (is_multicast_ether_addr(hdr->addr1) &&
sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta)
return -1;
ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
if (ret < 0)
return ret;
ehdr = (struct ethhdr *) rx->skb->data;
if (ehdr->h_proto == rx->sdata->control_port_protocol)
*port_control = true;
else if (check_port_control)
return -1;
return 0;
}
/*
* requires that rx->skb is a frame with ethernet header
*/
static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc)
{
static const u8 pae_group_addr[ETH_ALEN] __aligned(2)
= { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 };
struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
/*
* Allow EAPOL frames to us/the PAE group address regardless
* of whether the frame was encrypted or not.
*/
if (ehdr->h_proto == rx->sdata->control_port_protocol &&
(ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) ||
ether_addr_equal(ehdr->h_dest, pae_group_addr)))
return true;
if (ieee80211_802_1x_port_control(rx) ||
ieee80211_drop_unencrypted(rx, fc))
return false;
return true;
}
/*
* requires that rx->skb is a frame with ethernet header
*/
static void
ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct net_device *dev = sdata->dev;
struct sk_buff *skb, *xmit_skb;
struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
struct sta_info *dsta;
skb = rx->skb;
xmit_skb = NULL;
ieee80211_rx_stats(dev, skb->len);
if ((sdata->vif.type == NL80211_IFTYPE_AP ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
!(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
if (is_multicast_ether_addr(ehdr->h_dest)) {
/*
* send multicast frames both to higher layers in
* local net stack and back to the wireless medium
*/
xmit_skb = skb_copy(skb, GFP_ATOMIC);
if (!xmit_skb)
net_info_ratelimited("%s: failed to clone multicast frame\n",
dev->name);
} else {
dsta = sta_info_get(sdata, skb->data);
if (dsta) {
/*
* The destination station is associated to
* this AP (in this VLAN), so send the frame
* directly to it and do not pass it to local
* net stack.
*/
xmit_skb = skb;
skb = NULL;
}
}
}
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
if (skb) {
/* 'align' will only take the values 0 or 2 here since all
* frames are required to be aligned to 2-byte boundaries
* when being passed to mac80211; the code here works just
* as well if that isn't true, but mac80211 assumes it can
* access fields as 2-byte aligned (e.g. for ether_addr_equal)
*/
int align;
align = (unsigned long)(skb->data + sizeof(struct ethhdr)) & 3;
if (align) {
if (WARN_ON(skb_headroom(skb) < 3)) {
dev_kfree_skb(skb);
skb = NULL;
} else {
u8 *data = skb->data;
size_t len = skb_headlen(skb);
skb->data -= align;
memmove(skb->data, data, len);
skb_set_tail_pointer(skb, len);
}
}
}
#endif
if (skb) {
/* deliver to local stack */
skb->protocol = eth_type_trans(skb, dev);
memset(skb->cb, 0, sizeof(skb->cb));
if (rx->local->napi)
napi_gro_receive(rx->local->napi, skb);
else
netif_receive_skb(skb);
}
if (xmit_skb) {
/*
* Send to wireless media and increase priority by 256 to
* keep the received priority instead of reclassifying
* the frame (see cfg80211_classify8021d).
*/
xmit_skb->priority += 256;
xmit_skb->protocol = htons(ETH_P_802_3);
skb_reset_network_header(xmit_skb);
skb_reset_mac_header(xmit_skb);
dev_queue_xmit(xmit_skb);
}
}
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
{
struct net_device *dev = rx->sdata->dev;
struct sk_buff *skb = rx->skb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc = hdr->frame_control;
struct sk_buff_head frame_list;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
if (unlikely(!ieee80211_is_data(fc)))
return RX_CONTINUE;
if (unlikely(!ieee80211_is_data_present(fc)))
return RX_DROP_MONITOR;
if (!(status->rx_flags & IEEE80211_RX_AMSDU))
return RX_CONTINUE;
if (ieee80211_has_a4(hdr->frame_control) &&
rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
!rx->sdata->u.vlan.sta)
return RX_DROP_UNUSABLE;
if (is_multicast_ether_addr(hdr->addr1) &&
((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
rx->sdata->u.vlan.sta) ||
(rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
rx->sdata->u.mgd.use_4addr)))
return RX_DROP_UNUSABLE;
skb->dev = dev;
__skb_queue_head_init(&frame_list);
if (skb_linearize(skb))
return RX_DROP_UNUSABLE;
ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
rx->sdata->vif.type,
rx->local->hw.extra_tx_headroom, true);
while (!skb_queue_empty(&frame_list)) {
rx->skb = __skb_dequeue(&frame_list);
if (!ieee80211_frame_allowed(rx, fc)) {
dev_kfree_skb(rx->skb);
continue;
}
ieee80211_deliver_skb(rx);
}
return RX_QUEUED;
}
#ifdef CPTCFG_MAC80211_MESH
static ieee80211_rx_result
ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *fwd_hdr, *hdr;
struct ieee80211_tx_info *info;
struct ieee80211s_hdr *mesh_hdr;
struct sk_buff *skb = rx->skb, *fwd_skb;
struct ieee80211_local *local = rx->local;
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u16 q, hdrlen;
hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = ieee80211_hdrlen(hdr->frame_control);
/* make sure fixed part of mesh header is there, also checks skb len */
if (!pskb_may_pull(rx->skb, hdrlen + 6))
return RX_DROP_MONITOR;
mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
/* make sure full mesh header is there, also checks skb len */
if (!pskb_may_pull(rx->skb,
hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
return RX_DROP_MONITOR;
/* reload pointers */
hdr = (struct ieee80211_hdr *) skb->data;
mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
if (ieee80211_drop_unencrypted(rx, hdr->frame_control))
return RX_DROP_MONITOR;
/* frame is in RMC, don't forward */
if (ieee80211_is_data(hdr->frame_control) &&
is_multicast_ether_addr(hdr->addr1) &&
mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr))
return RX_DROP_MONITOR;
if (!ieee80211_is_data(hdr->frame_control))
return RX_CONTINUE;
if (!mesh_hdr->ttl)
return RX_DROP_MONITOR;
if (mesh_hdr->flags & MESH_FLAGS_AE) {
struct mesh_path *mppath;
char *proxied_addr;
char *mpp_addr;
if (is_multicast_ether_addr(hdr->addr1)) {
mpp_addr = hdr->addr3;
proxied_addr = mesh_hdr->eaddr1;
} else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
/* has_a4 already checked in ieee80211_rx_mesh_check */
mpp_addr = hdr->addr4;
proxied_addr = mesh_hdr->eaddr2;
} else {
return RX_DROP_MONITOR;
}
rcu_read_lock();
mppath = mpp_path_lookup(sdata, proxied_addr);
if (!mppath) {
mpp_path_add(sdata, proxied_addr, mpp_addr);
} else {
spin_lock_bh(&mppath->state_lock);
if (!ether_addr_equal(mppath->mpp, mpp_addr))
memcpy(mppath->mpp, mpp_addr, ETH_ALEN);
spin_unlock_bh(&mppath->state_lock);
}
rcu_read_unlock();
}
/* Frame has reached destination. Don't forward */
if (!is_multicast_ether_addr(hdr->addr1) &&
ether_addr_equal(sdata->vif.addr, hdr->addr3))
return RX_CONTINUE;
q = ieee80211_select_queue_80211(sdata, skb, hdr);
if (ieee80211_queue_stopped(&local->hw, q)) {
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion);
return RX_DROP_MONITOR;
}
skb_set_queue_mapping(skb, q);
if (!--mesh_hdr->ttl) {
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
goto out;
}
if (!ifmsh->mshcfg.dot11MeshForwarding)
goto out;
fwd_skb = skb_copy(skb, GFP_ATOMIC);
if (!fwd_skb) {
net_info_ratelimited("%s: failed to clone mesh frame\n",
sdata->name);
goto out;
}
fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);
info = IEEE80211_SKB_CB(fwd_skb);
memset(info, 0, sizeof(*info));
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
info->control.vif = &rx->sdata->vif;
info->control.jiffies = jiffies;
if (is_multicast_ether_addr(fwd_hdr->addr1)) {
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast);
memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
/* update power mode indication when forwarding */
ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr);
} else if (!mesh_nexthop_lookup(sdata, fwd_skb)) {
/* mesh power mode flags updated in mesh_nexthop_lookup */
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
} else {
/* unable to resolve next hop */
mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl,
fwd_hdr->addr3, 0,
WLAN_REASON_MESH_PATH_NOFORWARD,
fwd_hdr->addr2);
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
kfree_skb(fwd_skb);
return RX_DROP_MONITOR;
}
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
ieee80211_add_pending_skb(local, fwd_skb);
out:
if (is_multicast_ether_addr(hdr->addr1))
return RX_CONTINUE;
return RX_DROP_MONITOR;
}
#endif
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct ieee80211_local *local = rx->local;
struct net_device *dev = sdata->dev;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
__le16 fc = hdr->frame_control;
bool port_control;
int err;
if (unlikely(!ieee80211_is_data(hdr->frame_control)))
return RX_CONTINUE;
if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
return RX_DROP_MONITOR;
if (rx->sta) {
/* The seqno index has the same property as needed
* for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS
* for non-QoS-data frames. Here we know it's a data
* frame, so count MSDUs.
*/
rx->sta->rx_msdu[rx->seqno_idx]++;
}
/*
* Send unexpected-4addr-frame event to hostapd. For older versions,
* also drop the frame to cooked monitor interfaces.
*/
if (ieee80211_has_a4(hdr->frame_control) &&
sdata->vif.type == NL80211_IFTYPE_AP) {
if (rx->sta &&
!test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT))
cfg80211_rx_unexpected_4addr_frame(
rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC);
return RX_DROP_MONITOR;
}
err = __ieee80211_data_to_8023(rx, &port_control);
if (unlikely(err))
return RX_DROP_UNUSABLE;
if (!ieee80211_frame_allowed(rx, fc))
return RX_DROP_MONITOR;
/* directly handle TDLS channel switch requests/responses */
if (unlikely(((struct ethhdr *)rx->skb->data)->h_proto ==
cpu_to_be16(ETH_P_TDLS))) {
struct ieee80211_tdls_data *tf = (void *)rx->skb->data;
if (pskb_may_pull(rx->skb,
offsetof(struct ieee80211_tdls_data, u)) &&
tf->payload_type == WLAN_TDLS_SNAP_RFTYPE &&
tf->category == WLAN_CATEGORY_TDLS &&
(tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_REQUEST ||
tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_RESPONSE)) {
rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TDLS_CHSW;
skb_queue_tail(&sdata->skb_queue, rx->skb);
ieee80211_queue_work(&rx->local->hw, &sdata->work);
if (rx->sta)
rx->sta->rx_packets++;
return RX_QUEUED;
}
}
if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
unlikely(port_control) && sdata->bss) {
sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
u.ap);
dev = sdata->dev;
rx->sdata = sdata;
}
rx->skb->dev = dev;
if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 &&
!is_multicast_ether_addr(
((struct ethhdr *)rx->skb->data)->h_dest) &&
(!local->scanning &&
!test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))) {
mod_timer(&local->dynamic_ps_timer, jiffies +
msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
}
ieee80211_deliver_skb(rx);
return RX_QUEUED;
}
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
{
struct sk_buff *skb = rx->skb;
struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data;
struct tid_ampdu_rx *tid_agg_rx;
u16 start_seq_num;
u16 tid;
if (likely(!ieee80211_is_ctl(bar->frame_control)))
return RX_CONTINUE;
if (ieee80211_is_back_req(bar->frame_control)) {
struct {
__le16 control, start_seq_num;
} __packed bar_data;
struct ieee80211_event event = {
.type = BAR_RX_EVENT,
};
if (!rx->sta)
return RX_DROP_MONITOR;
if (skb_copy_bits(skb, offsetof(struct ieee80211_bar, control),
&bar_data, sizeof(bar_data)))
return RX_DROP_MONITOR;
tid = le16_to_cpu(bar_data.control) >> 12;
tid_agg_rx = rcu_dereference(rx->sta->ampdu_mlme.tid_rx[tid]);
if (!tid_agg_rx)
return RX_DROP_MONITOR;
start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4;
event.u.ba.tid = tid;
event.u.ba.ssn = start_seq_num;
event.u.ba.sta = &rx->sta->sta;
/* reset session timer */
if (tid_agg_rx->timeout)
mod_timer(&tid_agg_rx->session_timer,
TU_TO_EXP_TIME(tid_agg_rx->timeout));
spin_lock(&tid_agg_rx->reorder_lock);
/* release stored frames up to start of BAR */
ieee80211_release_reorder_frames(rx->sdata, tid_agg_rx,
start_seq_num, frames);
spin_unlock(&tid_agg_rx->reorder_lock);
drv_event_callback(rx->local, rx->sdata, &event);
kfree_skb(skb);
return RX_QUEUED;
}
/*
* After this point, we only want management frames,
* so we can drop all remaining control frames to
* cooked monitor interfaces.
*/
return RX_DROP_MONITOR;
}
static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt,
size_t len)
{
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct ieee80211_mgmt *resp;
if (!ether_addr_equal(mgmt->da, sdata->vif.addr)) {
/* Not to own unicast address */
return;
}
if (!ether_addr_equal(mgmt->sa, sdata->u.mgd.bssid) ||
!ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid)) {
/* Not from the current AP or not associated yet. */
return;
}
if (len < 24 + 1 + sizeof(resp->u.action.u.sa_query)) {
/* Too short SA Query request frame */
return;
}
skb = dev_alloc_skb(sizeof(*resp) + local->hw.extra_tx_headroom);
if (skb == NULL)
return;
skb_reserve(skb, local->hw.extra_tx_headroom);
resp = (struct ieee80211_mgmt *) skb_put(skb, 24);
memset(resp, 0, 24);
memcpy(resp->da, mgmt->sa, ETH_ALEN);
memcpy(resp->sa, sdata->vif.addr, ETH_ALEN);
memcpy(resp->bssid, sdata->u.mgd.bssid, ETH_ALEN);
resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
skb_put(skb, 1 + sizeof(resp->u.action.u.sa_query));
resp->u.action.category = WLAN_CATEGORY_SA_QUERY;
resp->u.action.u.sa_query.action = WLAN_ACTION_SA_QUERY_RESPONSE;
memcpy(resp->u.action.u.sa_query.trans_id,
mgmt->u.action.u.sa_query.trans_id,
WLAN_SA_QUERY_TR_ID_LEN);
ieee80211_tx_skb(sdata, skb);
}
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
{
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
/*
* From here on, look only at management frames.
* Data and control frames are already handled,
* and unknown (reserved) frames are useless.
*/
if (rx->skb->len < 24)
return RX_DROP_MONITOR;
if (!ieee80211_is_mgmt(mgmt->frame_control))
return RX_DROP_MONITOR;
if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
ieee80211_is_beacon(mgmt->frame_control) &&
!(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
int sig = 0;
if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
sig = status->signal;
cfg80211_report_obss_beacon(rx->local->hw.wiphy,
rx->skb->data, rx->skb->len,
status->freq, sig);
rx->flags |= IEEE80211_RX_BEACON_REPORTED;
}
if (ieee80211_drop_unencrypted_mgmt(rx))
return RX_DROP_UNUSABLE;
return RX_CONTINUE;
}
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
{
struct ieee80211_local *local = rx->local;
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
int len = rx->skb->len;
if (!ieee80211_is_action(mgmt->frame_control))
return RX_CONTINUE;
/* drop too small frames */
if (len < IEEE80211_MIN_ACTION_SIZE)
return RX_DROP_UNUSABLE;
if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC &&
mgmt->u.action.category != WLAN_CATEGORY_SELF_PROTECTED &&
mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
return RX_DROP_UNUSABLE;
switch (mgmt->u.action.category) {
case WLAN_CATEGORY_HT:
/* reject HT action frames from stations not supporting HT */
if (!rx->sta->sta.ht_cap.ht_supported)
goto invalid;
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
sdata->vif.type != NL80211_IFTYPE_AP &&
sdata->vif.type != NL80211_IFTYPE_ADHOC)
break;
/* verify action & smps_control/chanwidth are present */
if (len < IEEE80211_MIN_ACTION_SIZE + 2)
goto invalid;
switch (mgmt->u.action.u.ht_smps.action) {
case WLAN_HT_ACTION_SMPS: {
struct ieee80211_supported_band *sband;
enum ieee80211_smps_mode smps_mode;
/* convert to HT capability */
switch (mgmt->u.action.u.ht_smps.smps_control) {
case WLAN_HT_SMPS_CONTROL_DISABLED:
smps_mode = IEEE80211_SMPS_OFF;
break;
case WLAN_HT_SMPS_CONTROL_STATIC:
smps_mode = IEEE80211_SMPS_STATIC;
break;
case WLAN_HT_SMPS_CONTROL_DYNAMIC:
smps_mode = IEEE80211_SMPS_DYNAMIC;
break;
default:
goto invalid;
}
/* if no change do nothing */
if (rx->sta->sta.smps_mode == smps_mode)
goto handled;
rx->sta->sta.smps_mode = smps_mode;
sband = rx->local->hw.wiphy->bands[status->band];
rate_control_rate_update(local, sband, rx->sta,
IEEE80211_RC_SMPS_CHANGED);
goto handled;
}
case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: {
struct ieee80211_supported_band *sband;
u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth;
enum ieee80211_sta_rx_bandwidth max_bw, new_bw;
/* If it doesn't support 40 MHz it can't change ... */
if (!(rx->sta->sta.ht_cap.cap &
IEEE80211_HT_CAP_SUP_WIDTH_20_40))
goto handled;
if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ)
max_bw = IEEE80211_STA_RX_BW_20;
else
max_bw = ieee80211_sta_cap_rx_bw(rx->sta);
/* set cur_max_bandwidth and recalc sta bw */
rx->sta->cur_max_bandwidth = max_bw;
new_bw = ieee80211_sta_cur_vht_bw(rx->sta);
if (rx->sta->sta.bandwidth == new_bw)
goto handled;
rx->sta->sta.bandwidth = new_bw;
sband = rx->local->hw.wiphy->bands[status->band];
rate_control_rate_update(local, sband, rx->sta,
IEEE80211_RC_BW_CHANGED);
goto handled;
}
default:
goto invalid;
}
break;
case WLAN_CATEGORY_PUBLIC:
if (len < IEEE80211_MIN_ACTION_SIZE + 1)
goto invalid;
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
if (!rx->sta)
break;
if (!ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid))
break;
if (mgmt->u.action.u.ext_chan_switch.action_code !=
WLAN_PUB_ACTION_EXT_CHANSW_ANN)
break;
if (len < offsetof(struct ieee80211_mgmt,
u.action.u.ext_chan_switch.variable))
goto invalid;
goto queue;
case WLAN_CATEGORY_VHT:
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
sdata->vif.type != NL80211_IFTYPE_AP &&
sdata->vif.type != NL80211_IFTYPE_ADHOC)
break;
/* verify action code is present */
if (len < IEEE80211_MIN_ACTION_SIZE + 1)
goto invalid;
switch (mgmt->u.action.u.vht_opmode_notif.action_code) {
case WLAN_VHT_ACTION_OPMODE_NOTIF: {
u8 opmode;
/* verify opmode is present */
if (len < IEEE80211_MIN_ACTION_SIZE + 2)
goto invalid;
opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
ieee80211_vht_handle_opmode(rx->sdata, rx->sta,
opmode, status->band,
false);
goto handled;
}
default:
break;
}
break;
case WLAN_CATEGORY_BACK:
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
sdata->vif.type != NL80211_IFTYPE_AP &&
sdata->vif.type != NL80211_IFTYPE_ADHOC)
break;
/* verify action_code is present */
if (len < IEEE80211_MIN_ACTION_SIZE + 1)
break;
switch (mgmt->u.action.u.addba_req.action_code) {
case WLAN_ACTION_ADDBA_REQ:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.addba_req)))
goto invalid;
break;
case WLAN_ACTION_ADDBA_RESP:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.addba_resp)))
goto invalid;
break;
case WLAN_ACTION_DELBA:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.delba)))
goto invalid;
break;
default:
goto invalid;
}
goto queue;
case WLAN_CATEGORY_SPECTRUM_MGMT:
/* verify action_code is present */
if (len < IEEE80211_MIN_ACTION_SIZE + 1)
break;
switch (mgmt->u.action.u.measurement.action_code) {
case WLAN_ACTION_SPCT_MSR_REQ:
if (status->band != IEEE80211_BAND_5GHZ)
break;
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.measurement)))
break;
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
ieee80211_process_measurement_req(sdata, mgmt, len);
goto handled;
case WLAN_ACTION_SPCT_CHL_SWITCH: {
u8 *bssid;
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.chan_switch)))
break;
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_ADHOC &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
break;
if (sdata->vif.type == NL80211_IFTYPE_STATION)
bssid = sdata->u.mgd.bssid;
else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
bssid = sdata->u.ibss.bssid;
else if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
bssid = mgmt->sa;
else
break;
if (!ether_addr_equal(mgmt->bssid, bssid))
break;
goto queue;
}
}
break;
case WLAN_CATEGORY_SA_QUERY:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.sa_query)))
break;
switch (mgmt->u.action.u.sa_query.action) {
case WLAN_ACTION_SA_QUERY_REQUEST:
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
ieee80211_process_sa_query_req(sdata, mgmt, len);
goto handled;
}
break;
case WLAN_CATEGORY_SELF_PROTECTED:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.self_prot.action_code)))
break;
switch (mgmt->u.action.u.self_prot.action_code) {
case WLAN_SP_MESH_PEERING_OPEN:
case WLAN_SP_MESH_PEERING_CLOSE:
case WLAN_SP_MESH_PEERING_CONFIRM:
if (!ieee80211_vif_is_mesh(&sdata->vif))
goto invalid;
if (sdata->u.mesh.user_mpm)
/* userspace handles this frame */
break;
goto queue;
case WLAN_SP_MGK_INFORM:
case WLAN_SP_MGK_ACK:
if (!ieee80211_vif_is_mesh(&sdata->vif))
goto invalid;
break;
}
break;
case WLAN_CATEGORY_MESH_ACTION:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.mesh_action.action_code)))
break;
if (!ieee80211_vif_is_mesh(&sdata->vif))
break;
if (mesh_action_is_path_sel(mgmt) &&
!mesh_path_sel_is_hwmp(sdata))
break;
goto queue;
}
return RX_CONTINUE;
invalid:
status->rx_flags |= IEEE80211_RX_MALFORMED_ACTION_FRM;
/* will return in the next handlers */
return RX_CONTINUE;
handled:
if (rx->sta)
rx->sta->rx_packets++;
dev_kfree_skb(rx->skb);
return RX_QUEUED;
queue:
rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
skb_queue_tail(&sdata->skb_queue, rx->skb);
ieee80211_queue_work(&local->hw, &sdata->work);
if (rx->sta)
rx->sta->rx_packets++;
return RX_QUEUED;
}
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
int sig = 0;
/* skip known-bad action frames and return them in the next handler */
if (status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM)
return RX_CONTINUE;
/*
* Getting here means the kernel doesn't know how to handle
* it, but maybe userspace does ... include returned frames
* so userspace can register for those to know whether ones
* it transmitted were processed or returned.
*/
if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
sig = status->signal;
if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig,
rx->skb->data, rx->skb->len, 0)) {
if (rx->sta)
rx->sta->rx_packets++;
dev_kfree_skb(rx->skb);
return RX_QUEUED;
}
return RX_CONTINUE;
}
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
{
struct ieee80211_local *local = rx->local;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
struct sk_buff *nskb;
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
if (!ieee80211_is_action(mgmt->frame_control))
return RX_CONTINUE;
/*
* For AP mode, hostapd is responsible for handling any action
* frames that we didn't handle, including returning unknown
* ones. For all other modes we will return them to the sender,
* setting the 0x80 bit in the action category, as required by
* 802.11-2012 9.24.4.
* Newer versions of hostapd shall also use the management frame
* registration mechanisms, but older ones still use cooked
* monitor interfaces so push all frames there.
*/
if (!(status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM) &&
(sdata->vif.type == NL80211_IFTYPE_AP ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
return RX_DROP_MONITOR;
if (is_multicast_ether_addr(mgmt->da))
return RX_DROP_MONITOR;
/* do not return rejected action frames */
if (mgmt->u.action.category & 0x80)
return RX_DROP_UNUSABLE;
nskb = skb_copy_expand(rx->skb, local->hw.extra_tx_headroom, 0,
GFP_ATOMIC);
if (nskb) {
struct ieee80211_mgmt *nmgmt = (void *)nskb->data;
nmgmt->u.action.category |= 0x80;
memcpy(nmgmt->da, nmgmt->sa, ETH_ALEN);
memcpy(nmgmt->sa, rx->sdata->vif.addr, ETH_ALEN);
memset(nskb->cb, 0, sizeof(nskb->cb));
if (rx->sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(nskb);
info->flags = IEEE80211_TX_CTL_TX_OFFCHAN |
IEEE80211_TX_INTFL_OFFCHAN_TX_OK |
IEEE80211_TX_CTL_NO_CCK_RATE;
if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
info->hw_queue =
local->hw.offchannel_tx_hw_queue;
}
__ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7,
status->band);
}
dev_kfree_skb(rx->skb);
return RX_QUEUED;
}
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct ieee80211_mgmt *mgmt = (void *)rx->skb->data;
__le16 stype;
stype = mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE);
if (!ieee80211_vif_is_mesh(&sdata->vif) &&
sdata->vif.type != NL80211_IFTYPE_ADHOC &&
sdata->vif.type != NL80211_IFTYPE_OCB &&
sdata->vif.type != NL80211_IFTYPE_STATION)
return RX_DROP_MONITOR;
switch (stype) {
case cpu_to_le16(IEEE80211_STYPE_AUTH):
case cpu_to_le16(IEEE80211_STYPE_BEACON):
case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
/* process for all: mesh, mlme, ibss */
break;
case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
if (is_multicast_ether_addr(mgmt->da) &&
!is_broadcast_ether_addr(mgmt->da))
return RX_DROP_MONITOR;
/* process only for station */
if (sdata->vif.type != NL80211_IFTYPE_STATION)
return RX_DROP_MONITOR;
break;
case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
/* process only for ibss and mesh */
if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
return RX_DROP_MONITOR;
break;
default:
return RX_DROP_MONITOR;
}
/* queue up frame and kick off work to process it */
rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
skb_queue_tail(&sdata->skb_queue, rx->skb);
ieee80211_queue_work(&rx->local->hw, &sdata->work);
if (rx->sta)
rx->sta->rx_packets++;
return RX_QUEUED;
}
/* TODO: use IEEE80211_RX_FRAGMENTED */
static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
struct ieee80211_rate *rate)
{
struct ieee80211_sub_if_data *sdata;
struct ieee80211_local *local = rx->local;
struct sk_buff *skb = rx->skb, *skb2;
struct net_device *prev_dev = NULL;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
int needed_headroom;
/*
* If cooked monitor has been processed already, then
* don't do it again. If not, set the flag.
*/
if (rx->flags & IEEE80211_RX_CMNTR)
goto out_free_skb;
rx->flags |= IEEE80211_RX_CMNTR;
/* If there are no cooked monitor interfaces, just free the SKB */
if (!local->cooked_mntrs)
goto out_free_skb;
/* vendor data is long removed here */
status->flag &= ~RX_FLAG_RADIOTAP_VENDOR_DATA;
/* room for the radiotap header based on driver features */
needed_headroom = ieee80211_rx_radiotap_hdrlen(local, status, skb);
if (skb_headroom(skb) < needed_headroom &&
pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC))
goto out_free_skb;
/* prepend radiotap information */
ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom,
false);
skb_set_mac_header(skb, 0);
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = htons(ETH_P_802_2);
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata))
continue;
if (sdata->vif.type != NL80211_IFTYPE_MONITOR ||
!(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES))
continue;
if (prev_dev) {
skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2) {
skb2->dev = prev_dev;
netif_receive_skb(skb2);
}
}
prev_dev = sdata->dev;
ieee80211_rx_stats(sdata->dev, skb->len);
}
if (prev_dev) {
skb->dev = prev_dev;
netif_receive_skb(skb);
return;
}
out_free_skb:
dev_kfree_skb(skb);
}
static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
ieee80211_rx_result res)
{
switch (res) {
case RX_DROP_MONITOR:
I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop);
if (rx->sta)
rx->sta->rx_dropped++;
/* fall through */
case RX_CONTINUE: {
struct ieee80211_rate *rate = NULL;
struct ieee80211_supported_band *sband;
struct ieee80211_rx_status *status;
status = IEEE80211_SKB_RXCB((rx->skb));
sband = rx->local->hw.wiphy->bands[status->band];
if (!(status->flag & RX_FLAG_HT) &&
!(status->flag & RX_FLAG_VHT))
rate = &sband->bitrates[status->rate_idx];
ieee80211_rx_cooked_monitor(rx, rate);
break;
}
case RX_DROP_UNUSABLE:
I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop);
if (rx->sta)
rx->sta->rx_dropped++;
dev_kfree_skb(rx->skb);
break;
case RX_QUEUED:
I802_DEBUG_INC(rx->sdata->local->rx_handlers_queued);
break;
}
}
static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
struct sk_buff_head *frames)
{
ieee80211_rx_result res = RX_DROP_MONITOR;
struct sk_buff *skb;
#define CALL_RXH(rxh) \
do { \
res = rxh(rx); \
if (res != RX_CONTINUE) \
goto rxh_next; \
} while (0);
/* Lock here to avoid hitting all of the data used in the RX
* path (e.g. key data, station data, ...) concurrently when
* a frame is released from the reorder buffer due to timeout
* from the timer, potentially concurrently with RX from the
* driver.
*/
spin_lock_bh(&rx->local->rx_path_lock);
while ((skb = __skb_dequeue(frames))) {
/*
* all the other fields are valid across frames
* that belong to an aMPDU since they are on the
* same TID from the same station
*/
rx->skb = skb;
CALL_RXH(ieee80211_rx_h_check_more_data)
CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll)
CALL_RXH(ieee80211_rx_h_sta_process)
CALL_RXH(ieee80211_rx_h_decrypt)
CALL_RXH(ieee80211_rx_h_defragment)
CALL_RXH(ieee80211_rx_h_michael_mic_verify)
/* must be after MMIC verify so header is counted in MPDU mic */
#ifdef CPTCFG_MAC80211_MESH
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
CALL_RXH(ieee80211_rx_h_mesh_fwding);
#endif
CALL_RXH(ieee80211_rx_h_amsdu)
CALL_RXH(ieee80211_rx_h_data)
/* special treatment -- needs the queue */
res = ieee80211_rx_h_ctrl(rx, frames);
if (res != RX_CONTINUE)
goto rxh_next;
CALL_RXH(ieee80211_rx_h_mgmt_check)
CALL_RXH(ieee80211_rx_h_action)
CALL_RXH(ieee80211_rx_h_userspace_mgmt)
CALL_RXH(ieee80211_rx_h_action_return)
CALL_RXH(ieee80211_rx_h_mgmt)
rxh_next:
ieee80211_rx_handlers_result(rx, res);
#undef CALL_RXH
}
spin_unlock_bh(&rx->local->rx_path_lock);
}
static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
{
struct sk_buff_head reorder_release;
ieee80211_rx_result res = RX_DROP_MONITOR;
__skb_queue_head_init(&reorder_release);
#define CALL_RXH(rxh) \
do { \
res = rxh(rx); \
if (res != RX_CONTINUE) \
goto rxh_next; \
} while (0);
CALL_RXH(ieee80211_rx_h_check_dup)
CALL_RXH(ieee80211_rx_h_check)
ieee80211_rx_reorder_ampdu(rx, &reorder_release);
ieee80211_rx_handlers(rx, &reorder_release);
return;
rxh_next:
ieee80211_rx_handlers_result(rx, res);
#undef CALL_RXH
}
/*
* This function makes calls into the RX path, therefore
* it has to be invoked under RCU read lock.
*/
void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
{
struct sk_buff_head frames;
struct ieee80211_rx_data rx = {
.sta = sta,
.sdata = sta->sdata,
.local = sta->local,
/* This is OK -- must be QoS data frame */
.security_idx = tid,
.seqno_idx = tid,
.flags = 0,
};
struct tid_ampdu_rx *tid_agg_rx;
tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
if (!tid_agg_rx)
return;
__skb_queue_head_init(&frames);
spin_lock(&tid_agg_rx->reorder_lock);
ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx, &frames);
spin_unlock(&tid_agg_rx->reorder_lock);
if (!skb_queue_empty(&frames)) {
struct ieee80211_event event = {
.type = BA_FRAME_TIMEOUT,
.u.ba.tid = tid,
.u.ba.sta = &sta->sta,
};
drv_event_callback(rx.local, rx.sdata, &event);
}
ieee80211_rx_handlers(&rx, &frames);
}
/* main receive path */
static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata = rx->sdata;
struct sk_buff *skb = rx->skb;
struct ieee80211_hdr *hdr = (void *)skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
int multicast = is_multicast_ether_addr(hdr->addr1);
switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION:
if (!bssid && !sdata->u.mgd.use_4addr)
return false;
if (multicast)
return true;
return ether_addr_equal(sdata->vif.addr, hdr->addr1);
case NL80211_IFTYPE_ADHOC:
if (!bssid)
return false;
if (ether_addr_equal(sdata->vif.addr, hdr->addr2) ||
ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2))
return false;
if (ieee80211_is_beacon(hdr->frame_control))
return true;
if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid))
return false;
if (!multicast &&
!ether_addr_equal(sdata->vif.addr, hdr->addr1))
return false;
if (!rx->sta) {
int rate_idx;
if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
rate_idx = 0; /* TODO: HT/VHT rates */
else
rate_idx = status->rate_idx;
ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2,
BIT(rate_idx));
}
return true;
case NL80211_IFTYPE_OCB:
if (!bssid)
return false;
if (ieee80211_is_beacon(hdr->frame_control))
return false;
if (!is_broadcast_ether_addr(bssid))
return false;
if (!multicast &&
!ether_addr_equal(sdata->dev->dev_addr, hdr->addr1))
return false;
if (!rx->sta) {
int rate_idx;
if (status->flag & RX_FLAG_HT)
rate_idx = 0; /* TODO: HT rates */
else
rate_idx = status->rate_idx;
ieee80211_ocb_rx_no_sta(sdata, bssid, hdr->addr2,
BIT(rate_idx));
}
return true;
case NL80211_IFTYPE_MESH_POINT:
if (multicast)
return true;
return ether_addr_equal(sdata->vif.addr, hdr->addr1);
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_AP:
if (!bssid)
return ether_addr_equal(sdata->vif.addr, hdr->addr1);
if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) {
/*
* Accept public action frames even when the
* BSSID doesn't match, this is used for P2P
* and location updates. Note that mac80211
* itself never looks at these frames.
*/
if (!multicast &&
!ether_addr_equal(sdata->vif.addr, hdr->addr1))
return false;
if (ieee80211_is_public_action(hdr, skb->len))
return true;
return ieee80211_is_beacon(hdr->frame_control);
}
if (!ieee80211_has_tods(hdr->frame_control)) {
/* ignore data frames to TDLS-peers */
if (ieee80211_is_data(hdr->frame_control))
return false;
/* ignore action frames to TDLS-peers */
if (ieee80211_is_action(hdr->frame_control) &&
!ether_addr_equal(bssid, hdr->addr1))
return false;
}
return true;
case NL80211_IFTYPE_WDS:
if (bssid || !ieee80211_is_data(hdr->frame_control))
return false;
return ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2);
case NL80211_IFTYPE_P2P_DEVICE:
return ieee80211_is_public_action(hdr, skb->len) ||
ieee80211_is_probe_req(hdr->frame_control) ||
ieee80211_is_probe_resp(hdr->frame_control) ||
ieee80211_is_beacon(hdr->frame_control);
default:
break;
}
WARN_ON_ONCE(1);
return false;
}
/*
* This function returns whether or not the SKB
* was destined for RX processing or not, which,
* if consume is true, is equivalent to whether
* or not the skb was consumed.
*/
static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
struct sk_buff *skb, bool consume)
{
struct ieee80211_local *local = rx->local;
struct ieee80211_sub_if_data *sdata = rx->sdata;
rx->skb = skb;
if (!ieee80211_accept_frame(rx))
return false;
if (!consume) {
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb) {
if (net_ratelimit())
wiphy_debug(local->hw.wiphy,
"failed to copy skb for %s\n",
sdata->name);
return true;
}
rx->skb = skb;
}
ieee80211_invoke_rx_handlers(rx);
return true;
}
/*
* This is the actual Rx frames handler. as it belongs to Rx path it must
* be called with rcu_read_lock protection.
*/
static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
struct sk_buff *skb)
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
struct ieee80211_hdr *hdr;
__le16 fc;
struct ieee80211_rx_data rx;
struct ieee80211_sub_if_data *prev;
struct sta_info *sta, *prev_sta;
struct rhash_head *tmp;
int err = 0;
fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
memset(&rx, 0, sizeof(rx));
rx.skb = skb;
rx.local = local;
if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
I802_DEBUG_INC(local->dot11ReceivedFragmentCount);
if (ieee80211_is_mgmt(fc)) {
/* drop frame if too short for header */
if (skb->len < ieee80211_hdrlen(fc))
err = -ENOBUFS;
else
err = skb_linearize(skb);
} else {
err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
}
if (err) {
dev_kfree_skb(skb);
return;
}
hdr = (struct ieee80211_hdr *)skb->data;
ieee80211_parse_qos(&rx);
ieee80211_verify_alignment(&rx);
if (unlikely(ieee80211_is_probe_resp(hdr->frame_control) ||
ieee80211_is_beacon(hdr->frame_control)))
ieee80211_scan_rx(local, skb);
if (ieee80211_is_data(fc)) {
const struct bucket_table *tbl;
prev_sta = NULL;
tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
for_each_sta_info(local, tbl, hdr->addr2, sta, tmp) {
if (!prev_sta) {
prev_sta = sta;
continue;
}
rx.sta = prev_sta;
rx.sdata = prev_sta->sdata;
ieee80211_prepare_and_rx_handle(&rx, skb, false);
prev_sta = sta;
}
if (prev_sta) {
rx.sta = prev_sta;
rx.sdata = prev_sta->sdata;
if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
return;
goto out;
}
}
prev = NULL;
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata))
continue;
if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
continue;
/*
* frame is destined for this interface, but if it's
* not also for the previous one we handle that after
* the loop to avoid copying the SKB once too much
*/
if (!prev) {
prev = sdata;
continue;
}
rx.sta = sta_info_get_bss(prev, hdr->addr2);
rx.sdata = prev;
ieee80211_prepare_and_rx_handle(&rx, skb, false);
prev = sdata;
}
if (prev) {
rx.sta = sta_info_get_bss(prev, hdr->addr2);
rx.sdata = prev;
if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
return;
}
out:
dev_kfree_skb(skb);
}
/*
* This is the receive path handler. It is called by a low level driver when an
* 802.11 MPDU is received from the hardware.
*/
void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_rate *rate = NULL;
struct ieee80211_supported_band *sband;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
WARN_ON_ONCE(softirq_count() == 0);
if (WARN_ON(status->band >= IEEE80211_NUM_BANDS))
goto drop;
sband = local->hw.wiphy->bands[status->band];
if (WARN_ON(!sband))
goto drop;
/*
* If we're suspending, it is possible although not too likely
* that we'd be receiving frames after having already partially
* quiesced the stack. We can't process such frames then since
* that might, for example, cause stations to be added or other
* driver callbacks be invoked.
*/
if (unlikely(local->quiescing || local->suspended))
goto drop;
/* We might be during a HW reconfig, prevent Rx for the same reason */
if (unlikely(local->in_reconfig))
goto drop;
/*
* The same happens when we're not even started,
* but that's worth a warning.
*/
if (WARN_ON(!local->started))
goto drop;
if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) {
/*
* Validate the rate, unless a PLCP error means that
* we probably can't have a valid rate here anyway.
*/
if (status->flag & RX_FLAG_HT) {
/*
* rate_idx is MCS index, which can be [0-76]
* as documented on:
*
* http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n
*
* Anything else would be some sort of driver or
* hardware error. The driver should catch hardware
* errors.
*/
if (WARN(status->rate_idx > 76,
"Rate marked as an HT rate but passed "
"status->rate_idx is not "
"an MCS index [0-76]: %d (0x%02x)\n",
status->rate_idx,
status->rate_idx))
goto drop;
} else if (status->flag & RX_FLAG_VHT) {
if (WARN_ONCE(status->rate_idx > 9 ||
!status->vht_nss ||
status->vht_nss > 8,
"Rate marked as a VHT rate but data is invalid: MCS: %d, NSS: %d\n",
status->rate_idx, status->vht_nss))
goto drop;
} else {
if (WARN_ON(status->rate_idx >= sband->n_bitrates))
goto drop;
rate = &sband->bitrates[status->rate_idx];
}
}
status->rx_flags = 0;
/*
* key references and virtual interfaces are protected using RCU
* and this requires that we are in a read-side RCU section during
* receive processing
*/
rcu_read_lock();
/*
* Frames with failed FCS/PLCP checksum are not returned,
* all other frames are returned without radiotap header
* if it was previously present.
* Also, frames with less than 16 bytes are dropped.
*/
skb = ieee80211_rx_monitor(local, skb, rate);
if (!skb) {
rcu_read_unlock();
return;
}
ieee80211_tpt_led_trig_rx(local,
((struct ieee80211_hdr *)skb->data)->frame_control,
skb->len);
__ieee80211_rx_handle_packet(hw, skb);
rcu_read_unlock();
return;
drop:
kfree_skb(skb);
}
EXPORT_SYMBOL(ieee80211_rx);
/* This is a version of the rx handler that can be called from hard irq
* context. Post the skb on the queue and schedule the tasklet */
void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct ieee80211_local *local = hw_to_local(hw);
BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb));
skb->pkt_type = IEEE80211_RX_MSG;
skb_queue_tail(&local->skb_queue, skb);
tasklet_schedule(&local->tasklet);
}
EXPORT_SYMBOL(ieee80211_rx_irqsafe);
["test.cocci" (test.cocci)]
@nd@
identifier dev;
@@
struct net_device *dev;
@@
identifier nd.dev;
@@
-dev->tstats
+netdev_tstats(dev)
["tx.c" (tx.c)]
/*
* Copyright 2002-2005, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*
* Transmit and frame generation functions.
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
#include <linux/etherdevice.h>
#include <linux/bitmap.h>
#include <linux/rcupdate.h>
#include <linux/export.h>
#include <net/net_namespace.h>
#include <net/ieee80211_radiotap.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <asm/unaligned.h>
#include "ieee80211_i.h"
#include "driver-ops.h"
#include "led.h"
#include "mesh.h"
#include "wep.h"
#include "wpa.h"
#include "wme.h"
#include "rate.h"
/* misc utils */
static inline void ieee80211_tx_stats(struct net_device *dev, u32 len)
{
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
u64_stats_update_begin(&tstats->syncp);
tstats->tx_packets++;
tstats->tx_bytes += len;
u64_stats_update_end(&tstats->syncp);
}
static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
struct sk_buff *skb, int group_addr,
int next_frag_len)
{
int rate, mrate, erp, dur, i, shift = 0;
struct ieee80211_rate *txrate;
struct ieee80211_local *local = tx->local;
struct ieee80211_supported_band *sband;
struct ieee80211_hdr *hdr;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_chanctx_conf *chanctx_conf;
u32 rate_flags = 0;
rcu_read_lock();
chanctx_conf = rcu_dereference(tx->sdata->vif.chanctx_conf);
if (chanctx_conf) {
shift = ieee80211_chandef_get_shift(&chanctx_conf->def);
rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
}
rcu_read_unlock();
/* assume HW handles this */
if (tx->rate.flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))
return 0;
/* uh huh? */
if (WARN_ON_ONCE(tx->rate.idx < 0))
return 0;
sband = local->hw.wiphy->bands[info->band];
txrate = &sband->bitrates[tx->rate.idx];
erp = txrate->flags & IEEE80211_RATE_ERP_G;
/*
* data and mgmt (except PS Poll):
* - during CFP: 32768
* - during contention period:
* if addr1 is group address: 0
* if more fragments = 0 and addr1 is individual address: time to
* transmit one ACK plus SIFS
* if more fragments = 1 and addr1 is individual address: time to
* transmit next fragment plus 2 x ACK plus 3 x SIFS
*
* IEEE 802.11, 9.6:
* - control response frame (CTS or ACK) shall be transmitted using the
* same rate as the immediately previous frame in the frame exchange
* sequence, if this rate belongs to the PHY mandatory rates, or else
* at the highest possible rate belonging to the PHY rates in the
* BSSBasicRateSet
*/
hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_ctl(hdr->frame_control)) {
/* TODO: These control frames are not currently sent by
* mac80211, but should they be implemented, this function
* needs to be updated to support duration field calculation.
*
* RTS: time needed to transmit pending data/mgmt frame plus
* one CTS frame plus one ACK frame plus 3 x SIFS
* CTS: duration of immediately previous RTS minus time
* required to transmit CTS and its SIFS
* ACK: 0 if immediately previous directed data/mgmt had
* more=0, with more=1 duration in ACK frame is duration
* from previous frame minus time needed to transmit ACK
* and its SIFS
* PS Poll: BIT(15) | BIT(14) | aid
*/
return 0;
}
/* data/mgmt */
if (0 /* FIX: data/mgmt during CFP */)
return cpu_to_le16(32768);
if (group_addr) /* Group address as the destination - no ACK */
return 0;
/* Individual destination address:
* IEEE 802.11, Ch. 9.6 (after IEEE 802.11g changes)
* CTS and ACK frames shall be transmitted using the highest rate in
* basic rate set that is less than or equal to the rate of the
* immediately previous frame and that is using the same modulation
* (CCK or OFDM). If no basic rate set matches with these requirements,
* the highest mandatory rate of the PHY that is less than or equal to
* the rate of the previous frame is used.
* Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps
*/
rate = -1;
/* use lowest available if everything fails */
mrate = sband->bitrates[0].bitrate;
for (i = 0; i < sband->n_bitrates; i++) {
struct ieee80211_rate *r = &sband->bitrates[i];
if (r->bitrate > txrate->bitrate)
break;
if ((rate_flags & r->flags) != rate_flags)
continue;
if (tx->sdata->vif.bss_conf.basic_rates & BIT(i))
rate = DIV_ROUND_UP(r->bitrate, 1 << shift);
switch (sband->band) {
case IEEE80211_BAND_2GHZ: {
u32 flag;
if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
flag = IEEE80211_RATE_MANDATORY_G;
else
flag = IEEE80211_RATE_MANDATORY_B;
if (r->flags & flag)
mrate = r->bitrate;
break;
}
case IEEE80211_BAND_5GHZ:
if (r->flags & IEEE80211_RATE_MANDATORY_A)
mrate = r->bitrate;
break;
case IEEE80211_BAND_60GHZ:
/* TODO, for now fall through */
case IEEE80211_NUM_BANDS:
WARN_ON(1);
break;
}
}
if (rate == -1) {
/* No matching basic rate found; use highest suitable mandatory
* PHY rate */
rate = DIV_ROUND_UP(mrate, 1 << shift);
}
/* Don't calculate ACKs for QoS Frames with NoAck Policy set */
if (ieee80211_is_data_qos(hdr->frame_control) &&
*(ieee80211_get_qos_ctl(hdr)) & IEEE80211_QOS_CTL_ACK_POLICY_NOACK)
dur = 0;
else
/* Time needed to transmit ACK
* (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up
* to closest integer */
dur = ieee80211_frame_duration(sband->band, 10, rate, erp,
tx->sdata->vif.bss_conf.use_short_preamble,
shift);
if (next_frag_len) {
/* Frame is fragmented: duration increases with time needed to
* transmit next fragment plus ACK and 2 x SIFS. */
dur *= 2; /* ACK + SIFS */
/* next fragment */
dur += ieee80211_frame_duration(sband->band, next_frag_len,
txrate->bitrate, erp,
tx->sdata->vif.bss_conf.use_short_preamble,
shift);
}
return cpu_to_le16(dur);
}
/* tx handlers */
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
{
struct ieee80211_local *local = tx->local;
struct ieee80211_if_managed *ifmgd;
/* driver doesn't support power save */
if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
return TX_CONTINUE;
/* hardware does dynamic power save */
if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
return TX_CONTINUE;
/* dynamic power save disabled */
if (local->hw.conf.dynamic_ps_timeout <= 0)
return TX_CONTINUE;
/* we are scanning, don't enable power save */
if (local->scanning)
return TX_CONTINUE;
if (!local->ps_sdata)
return TX_CONTINUE;
/* No point if we're going to suspend */
if (local->quiescing)
return TX_CONTINUE;
/* dynamic ps is supported only in managed mode */
if (tx->sdata->vif.type != NL80211_IFTYPE_STATION)
return TX_CONTINUE;
ifmgd = &tx->sdata->u.mgd;
/*
* Don't wakeup from power save if u-apsd is enabled, voip ac has
* u-apsd enabled and the frame is in voip class. This effectively
* means that even if all access categories have u-apsd enabled, in
* practise u-apsd is only used with the voip ac. This is a
* workaround for the case when received voip class packets do not
* have correct qos tag for some reason, due the network or the
* peer application.
*
* Note: ifmgd->uapsd_queues access is racy here. If the value is
* changed via debugfs, user needs to reassociate manually to have
* everything in sync.
*/
if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) &&
(ifmgd->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) &&
skb_get_queue_mapping(tx->skb) == IEEE80211_AC_VO)
return TX_CONTINUE;
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
ieee80211_stop_queues_by_reason(&local->hw,
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_PS,
false);
ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
ieee80211_queue_work(&local->hw,
&local->dynamic_ps_disable_work);
}
/* Don't restart the timer if we're not disassociated */
if (!ifmgd->associated)
return TX_CONTINUE;
mod_timer(&local->dynamic_ps_timer, jiffies +
msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
return TX_CONTINUE;
}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
bool assoc = false;
if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
return TX_CONTINUE;
if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) &&
test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) &&
!ieee80211_is_probe_req(hdr->frame_control) &&
!ieee80211_is_nullfunc(hdr->frame_control))
/*
* When software scanning only nullfunc frames (to notify
* the sleep state to the AP) and probe requests (for the
* active scan) are allowed, all other frames should not be
* sent and we should not get here, but if we do
* nonetheless, drop them to avoid sending them
* off-channel. See the link below and
* ieee80211_start_scan() for more.
*
* http://article.gmane.org/gmane.linux.kernel.wireless.general/30089
*/
return TX_DROP;
if (tx->sdata->vif.type == NL80211_IFTYPE_OCB)
return TX_CONTINUE;
if (tx->sdata->vif.type == NL80211_IFTYPE_WDS)
return TX_CONTINUE;
if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
return TX_CONTINUE;
if (tx->flags & IEEE80211_TX_PS_BUFFERED)
return TX_CONTINUE;
if (tx->sta)
assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
if (unlikely(!assoc &&
ieee80211_is_data(hdr->frame_control))) {
#ifdef CPTCFG_MAC80211_VERBOSE_DEBUG
sdata_info(tx->sdata,
"dropped data frame to not associated station %pM\n",
hdr->addr1);
#endif
I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
return TX_DROP;
}
} else if (unlikely(tx->sdata->vif.type == NL80211_IFTYPE_AP &&
ieee80211_is_data(hdr->frame_control) &&
!atomic_read(&tx->sdata->u.ap.num_mcast_sta))) {
/*
* No associated STAs - no need to send multicast
* frames.
*/
return TX_DROP;
}
return TX_CONTINUE;
}
/* This function is called whenever the AP is about to exceed the maximum limit
* of buffered frames for power saving STAs. This situation should not really
* happen often during normal operation, so dropping the oldest buffered packet
* from each queue should be OK to make some room for new frames. */
static void purge_old_ps_buffers(struct ieee80211_local *local)
{
int total = 0, purged = 0;
struct sk_buff *skb;
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
struct ps_data *ps;
if (sdata->vif.type == NL80211_IFTYPE_AP)
ps = &sdata->u.ap.ps;
else if (ieee80211_vif_is_mesh(&sdata->vif))
ps = &sdata->u.mesh.ps;
else
continue;
skb = skb_dequeue(&ps->bc_buf);
if (skb) {
purged++;
dev_kfree_skb(skb);
}
total += skb_queue_len(&ps->bc_buf);
}
/*
* Drop one frame from each station from the lowest-priority
* AC that has frames at all.
*/
list_for_each_entry_rcu(sta, &local->sta_list, list) {
int ac;
for (ac = IEEE80211_AC_BK; ac >= IEEE80211_AC_VO; ac--) {
skb = skb_dequeue(&sta->ps_tx_buf[ac]);
total += skb_queue_len(&sta->ps_tx_buf[ac]);
if (skb) {
purged++;
ieee80211_free_txskb(&local->hw, skb);
break;
}
}
}
local->total_ps_buffered = total;
ps_dbg_hw(&local->hw, "PS buffers full - purged %d frames\n", purged);
}
static ieee80211_tx_result
ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
struct ps_data *ps;
/*
* broadcast/multicast frame
*
* If any of the associated/peer stations is in power save mode,
* the frame is buffered to be sent after DTIM beacon frame.
* This is done either by the hardware or us.
*/
/* powersaving STAs currently only in AP/VLAN/mesh mode */
if (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
tx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
if (!tx->sdata->bss)
return TX_CONTINUE;
ps = &tx->sdata->bss->ps;
} else if (ieee80211_vif_is_mesh(&tx->sdata->vif)) {
ps = &tx->sdata->u.mesh.ps;
} else {
return TX_CONTINUE;
}
/* no buffering for ordered frames */
if (ieee80211_has_order(hdr->frame_control))
return TX_CONTINUE;
if (ieee80211_is_probe_req(hdr->frame_control))
return TX_CONTINUE;
if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
info->hw_queue = tx->sdata->vif.cab_queue;
/* no stations in PS mode */
if (!atomic_read(&ps->num_sta_ps))
return TX_CONTINUE;
info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
/* device releases frame after DTIM beacon */
if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING))
return TX_CONTINUE;
/* buffered in mac80211 */
if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
purge_old_ps_buffers(tx->local);
if (skb_queue_len(&ps->bc_buf) >= AP_MAX_BC_BUFFER) {
ps_dbg(tx->sdata,
"BC TX buffer full - dropping the oldest frame\n");
dev_kfree_skb(skb_dequeue(&ps->bc_buf));
} else
tx->local->total_ps_buffered++;
skb_queue_tail(&ps->bc_buf, tx->skb);
return TX_QUEUED;
}
static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta,
struct sk_buff *skb)
{
if (!ieee80211_is_mgmt(fc))
return 0;
if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP))
return 0;
if (!ieee80211_is_robust_mgmt_frame(skb))
return 0;
return 1;
}
static ieee80211_tx_result
ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
{
struct sta_info *sta = tx->sta;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
struct ieee80211_local *local = tx->local;
if (unlikely(!sta))
return TX_CONTINUE;
if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) ||
test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
test_sta_flag(sta, WLAN_STA_PS_DELIVER)) &&
!(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
int ac = skb_get_queue_mapping(tx->skb);
if (ieee80211_is_mgmt(hdr->frame_control) &&
!ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
return TX_CONTINUE;
}
ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n",
sta->sta.addr, sta->sta.aid, ac);
if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
purge_old_ps_buffers(tx->local);
/* sync with ieee80211_sta_ps_deliver_wakeup */
spin_lock(&sta->ps_lock);
/*
* STA woke up the meantime and all the frames on ps_tx_buf have
* been queued to pending queue. No reordering can happen, go
* ahead and Tx the packet.
*/
if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
!test_sta_flag(sta, WLAN_STA_PS_DRIVER) &&
!test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
spin_unlock(&sta->ps_lock);
return TX_CONTINUE;
}
if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) {
struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]);
ps_dbg(tx->sdata,
"STA %pM TX buffer for AC %d full - dropping oldest frame\n",
sta->sta.addr, ac);
ieee80211_free_txskb(&local->hw, old);
} else
tx->local->total_ps_buffered++;
info->control.jiffies = jiffies;
info->control.vif = &tx->sdata->vif;
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb);
spin_unlock(&sta->ps_lock);
if (!timer_pending(&local->sta_cleanup))
mod_timer(&local->sta_cleanup,
round_jiffies(jiffies +
STA_INFO_CLEANUP_INTERVAL));
/*
* We queued up some frames, so the TIM bit might
* need to be set, recalculate it.
*/
sta_info_recalc_tim(sta);
return TX_QUEUED;
} else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) {
ps_dbg(tx->sdata,
"STA %pM in PS mode, but polling/in SP -> send frame\n",
sta->sta.addr);
}
return TX_CONTINUE;
}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
{
if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
return TX_CONTINUE;
if (tx->flags & IEEE80211_TX_UNICAST)
return ieee80211_tx_h_unicast_ps_buf(tx);
else
return ieee80211_tx_h_multicast_ps_buf(tx);
}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
if (unlikely(tx->sdata->control_port_protocol == tx->skb->protocol)) {
if (tx->sdata->control_port_no_encrypt)
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
info->flags |= IEEE80211_TX_CTL_USE_MINRATE;
}
return TX_CONTINUE;
}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
{
struct ieee80211_key *key;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT))
tx->key = NULL;
else if (tx->sta &&
(key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
tx->key = key;
else if (ieee80211_is_mgmt(hdr->frame_control) &&
is_multicast_ether_addr(hdr->addr1) &&
ieee80211_is_robust_mgmt_frame(tx->skb) &&
(key = rcu_dereference(tx->sdata->default_mgmt_key)))
tx->key = key;
else if (is_multicast_ether_addr(hdr->addr1) &&
(key = rcu_dereference(tx->sdata->default_multicast_key)))
tx->key = key;
else if (!is_multicast_ether_addr(hdr->addr1) &&
(key = rcu_dereference(tx->sdata->default_unicast_key)))
tx->key = key;
else
tx->key = NULL;
if (tx->key) {
bool skip_hw = false;
tx->key->tx_rx_count++;
/* TODO: add threshold stuff again */
switch (tx->key->conf.cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
case WLAN_CIPHER_SUITE_TKIP:
if (!ieee80211_is_data_present(hdr->frame_control))
tx->key = NULL;
break;
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
if (!ieee80211_is_data_present(hdr->frame_control) &&
!ieee80211_use_mfp(hdr->frame_control, tx->sta,
tx->skb))
tx->key = NULL;
else
skip_hw = (tx->key->conf.flags &
IEEE80211_KEY_FLAG_SW_MGMT_TX) &&
ieee80211_is_mgmt(hdr->frame_control);
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
if (!ieee80211_is_mgmt(hdr->frame_control))
tx->key = NULL;
break;
}
if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED &&
!ieee80211_is_deauth(hdr->frame_control)))
return TX_DROP;
if (!skip_hw && tx->key &&
tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
info->control.hw_key = &tx->key->conf;
}
return TX_CONTINUE;
}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (void *)tx->skb->data;
struct ieee80211_supported_band *sband;
u32 len;
struct ieee80211_tx_rate_control txrc;
struct ieee80211_sta_rates *ratetbl = NULL;
bool assoc = false;
memset(&txrc, 0, sizeof(txrc));
sband = tx->local->hw.wiphy->bands[info->band];
len = min_t(u32, tx->skb->len + FCS_LEN,
tx->local->hw.wiphy->frag_threshold);
/* set up the tx rate control struct we give the RC algo */
txrc.hw = &tx->local->hw;
txrc.sband = sband;
txrc.bss_conf = &tx->sdata->vif.bss_conf;
txrc.skb = tx->skb;
txrc.reported_rate.idx = -1;
txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band];
if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1)
txrc.max_rate_idx = -1;
else
txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
if (tx->sdata->rc_has_mcs_mask[info->band])
txrc.rate_idx_mcs_mask =
tx->sdata->rc_rateidx_mcs_mask[info->band];
txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
tx->sdata->vif.type == NL80211_IFTYPE_ADHOC);
/* set up RTS protection if desired */
if (len > tx->local->hw.wiphy->rts_threshold) {
txrc.rts = true;
}
info->control.use_rts = txrc.rts;
info->control.use_cts_prot = tx->sdata->vif.bss_conf.use_cts_prot;
/*
* Use short preamble if the BSS can handle it, but not for
* management frames unless we know the receiver can handle
* that -- the management frame might be to a station that
* just wants a probe response.
*/
if (tx->sdata->vif.bss_conf.use_short_preamble &&
(ieee80211_is_data(hdr->frame_control) ||
(tx->sta && test_sta_flag(tx->sta, WLAN_STA_SHORT_PREAMBLE))))
txrc.short_preamble = true;
info->control.short_preamble = txrc.short_preamble;
if (tx->sta)
assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
/*
* Lets not bother rate control if we're associated and cannot
* talk to the sta. This should not happen.
*/
if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && assoc &&
!rate_usable_index_exists(sband, &tx->sta->sta),
"%s: Dropped data frame as no usable bitrate found while "
"scanning and associated. Target station: "
"%pM on %d GHz band\n",
tx->sdata->name, hdr->addr1,
info->band ? 5 : 2))
return TX_DROP;
/*
* If we're associated with the sta at this point we know we can at
* least send the frame at the lowest bit rate.
*/
rate_control_get_rate(tx->sdata, tx->sta, &txrc);
if (tx->sta && !info->control.skip_table)
ratetbl = rcu_dereference(tx->sta->sta.rates);
if (unlikely(info->control.rates[0].idx < 0)) {
if (ratetbl) {
struct ieee80211_tx_rate rate = {
.idx = ratetbl->rate[0].idx,
.flags = ratetbl->rate[0].flags,
.count = ratetbl->rate[0].count
};
if (ratetbl->rate[0].idx < 0)
return TX_DROP;
tx->rate = rate;
} else {
return TX_DROP;
}
} else {
tx->rate = info->control.rates[0];
}
if (txrc.reported_rate.idx < 0) {
txrc.reported_rate = tx->rate;
if (tx->sta && ieee80211_is_data(hdr->frame_control))
tx->sta->last_tx_rate = txrc.reported_rate;
} else if (tx->sta)
tx->sta->last_tx_rate = txrc.reported_rate;
if (ratetbl)
return TX_CONTINUE;
if (unlikely(!info->control.rates[0].count))
info->control.rates[0].count = 1;
if (WARN_ON_ONCE((info->control.rates[0].count > 1) &&
(info->flags & IEEE80211_TX_CTL_NO_ACK)))
info->control.rates[0].count = 1;
return TX_CONTINUE;
}
static __le16 ieee80211_tx_next_seq(struct sta_info *sta, int tid)
{
u16 *seq = &sta->tid_seq[tid];
__le16 ret = cpu_to_le16(*seq);
/* Increase the sequence number. */
*seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ;
return ret;
}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
u8 *qc;
int tid;
/*
* Packet injection may want to control the sequence
* number, if we have no matching interface then we
* neither assign one ourselves nor ask the driver to.
*/
if (unlikely(info->control.vif->type == NL80211_IFTYPE_MONITOR))
return TX_CONTINUE;
if (unlikely(ieee80211_is_ctl(hdr->frame_control)))
return TX_CONTINUE;
if (ieee80211_hdrlen(hdr->frame_control) < 24)
return TX_CONTINUE;
if (ieee80211_is_qos_nullfunc(hdr->frame_control))
return TX_CONTINUE;
/*
* Anything but QoS data that has a sequence number field
* (is long enough) gets a sequence number from the global
* counter. QoS data frames with a multicast destination
* also use the global counter (802.11-2012 9.3.2.10).
*/
if (!ieee80211_is_data_qos(hdr->frame_control) ||
is_multicast_ether_addr(hdr->addr1)) {
/* driver should assign sequence number */
info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
/* for pure STA mode without beacons, we can do it */
hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number);
tx->sdata->sequence_number += 0x10;
if (tx->sta)
tx->sta->tx_msdu[IEEE80211_NUM_TIDS]++;
return TX_CONTINUE;
}
/*
* This should be true for injected/management frames only, for
* management frames we have set the IEEE80211_TX_CTL_ASSIGN_SEQ
* above since they are not QoS-data frames.
*/
if (!tx->sta)
return TX_CONTINUE;
/* include per-STA, per-TID sequence counter */
qc = ieee80211_get_qos_ctl(hdr);
tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
tx->sta->tx_msdu[tid]++;
if (!tx->sta->sta.txq[0])
hdr->seq_ctrl = ieee80211_tx_next_seq(tx->sta, tid);
return TX_CONTINUE;
}
static int ieee80211_fragment(struct ieee80211_tx_data *tx,
struct sk_buff *skb, int hdrlen,
int frag_threshold)
{
struct ieee80211_local *local = tx->local;
struct ieee80211_tx_info *info;
struct sk_buff *tmp;
int per_fragm = frag_threshold - hdrlen - FCS_LEN;
int pos = hdrlen + per_fragm;
int rem = skb->len - hdrlen - per_fragm;
if (WARN_ON(rem < 0))
return -EINVAL;
/* first fragment was already added to queue by caller */
while (rem) {
int fraglen = per_fragm;
if (fraglen > rem)
fraglen = rem;
rem -= fraglen;
tmp = dev_alloc_skb(local->tx_headroom +
frag_threshold +
tx->sdata->encrypt_headroom +
IEEE80211_ENCRYPT_TAILROOM);
if (!tmp)
return -ENOMEM;
__skb_queue_tail(&tx->skbs, tmp);
skb_reserve(tmp,
local->tx_headroom + tx->sdata->encrypt_headroom);
/* copy control information */
memcpy(tmp->cb, skb->cb, sizeof(tmp->cb));
info = IEEE80211_SKB_CB(tmp);
info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
IEEE80211_TX_CTL_FIRST_FRAGMENT);
if (rem)
info->flags |= IEEE80211_TX_CTL_MORE_FRAMES;
skb_copy_queue_mapping(tmp, skb);
tmp->priority = skb->priority;
tmp->dev = skb->dev;
/* copy header and data */
memcpy(skb_put(tmp, hdrlen), skb->data, hdrlen);
memcpy(skb_put(tmp, fraglen), skb->data + pos, fraglen);
pos += fraglen;
}
/* adjust first fragment's length */
skb_trim(skb, hdrlen + per_fragm);
return 0;
}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
{
struct sk_buff *skb = tx->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (void *)skb->data;
int frag_threshold = tx->local->hw.wiphy->frag_threshold;
int hdrlen;
int fragnum;
/* no matter what happens, tx->skb moves to tx->skbs */
__skb_queue_tail(&tx->skbs, skb);
tx->skb = NULL;
if (info->flags & IEEE80211_TX_CTL_DONTFRAG)
return TX_CONTINUE;
if (tx->local->ops->set_frag_threshold)
return TX_CONTINUE;
/*
* Warn when submitting a fragmented A-MPDU frame and drop it.
* This scenario is handled in ieee80211_tx_prepare but extra
* caution taken here as fragmented ampdu may cause Tx stop.
*/
if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU))
return TX_DROP;
hdrlen = ieee80211_hdrlen(hdr->frame_control);
/* internal error, why isn't DONTFRAG set? */
if (WARN_ON(skb->len + FCS_LEN <= frag_threshold))
return TX_DROP;
/*
* Now fragment the frame. This will allocate all the fragments and
* chain them (using skb as the first fragment) to skb->next.
* During transmission, we will remove the successfully transmitted
* fragments from this list. When the low-level driver rejects one
* of the fragments then we will simply pretend to accept the skb
* but store it away as pending.
*/
if (ieee80211_fragment(tx, skb, hdrlen, frag_threshold))
return TX_DROP;
/* update duration/seq/flags of fragments */
fragnum = 0;
skb_queue_walk(&tx->skbs, skb) {
const __le16 morefrags = cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
hdr = (void *)skb->data;
info = IEEE80211_SKB_CB(skb);
if (!skb_queue_is_last(&tx->skbs, skb)) {
hdr->frame_control |= morefrags;
/*
* No multi-rate retries for fragmented frames, that
* would completely throw off the NAV at other STAs.
*/
info->control.rates[1].idx = -1;
info->control.rates[2].idx = -1;
info->control.rates[3].idx = -1;
BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 4);
info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE;
} else {
hdr->frame_control &= ~morefrags;
}
hdr->seq_ctrl |= cpu_to_le16(fragnum & IEEE80211_SCTL_FRAG);
fragnum++;
}
return TX_CONTINUE;
}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
{
struct sk_buff *skb;
int ac = -1;
if (!tx->sta)
return TX_CONTINUE;
skb_queue_walk(&tx->skbs, skb) {
ac = skb_get_queue_mapping(skb);
tx->sta->tx_bytes[ac] += skb->len;
}
if (ac >= 0)
tx->sta->tx_packets[ac]++;
return TX_CONTINUE;
}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
{
if (!tx->key)
return TX_CONTINUE;
switch (tx->key->conf.cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
return ieee80211_crypto_wep_encrypt(tx);
case WLAN_CIPHER_SUITE_TKIP:
return ieee80211_crypto_tkip_encrypt(tx);
case WLAN_CIPHER_SUITE_CCMP:
return ieee80211_crypto_ccmp_encrypt(
tx, IEEE80211_CCMP_MIC_LEN);
case WLAN_CIPHER_SUITE_CCMP_256:
return ieee80211_crypto_ccmp_encrypt(
tx, IEEE80211_CCMP_256_MIC_LEN);
case WLAN_CIPHER_SUITE_AES_CMAC:
return ieee80211_crypto_aes_cmac_encrypt(tx);
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
return ieee80211_crypto_aes_cmac_256_encrypt(tx);
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
return ieee80211_crypto_aes_gmac_encrypt(tx);
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
return ieee80211_crypto_gcmp_encrypt(tx);
default:
return ieee80211_crypto_hw_encrypt(tx);
}
return TX_DROP;
}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
{
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
int next_len;
bool group_addr;
skb_queue_walk(&tx->skbs, skb) {
hdr = (void *) skb->data;
if (unlikely(ieee80211_is_pspoll(hdr->frame_control)))
break; /* must not overwrite AID */
if (!skb_queue_is_last(&tx->skbs, skb)) {
struct sk_buff *next = skb_queue_next(&tx->skbs, skb);
next_len = next->len;
} else
next_len = 0;
group_addr = is_multicast_ether_addr(hdr->addr1);
hdr->duration_id =
ieee80211_duration(tx, skb, group_addr, next_len);
}
return TX_CONTINUE;
}
/* actual transmit path */
static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
struct sk_buff *skb,
struct ieee80211_tx_info *info,
struct tid_ampdu_tx *tid_tx,
int tid)
{
bool queued = false;
bool reset_agg_timer = false;
struct sk_buff *purge_skb = NULL;
if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
info->flags |= IEEE80211_TX_CTL_AMPDU;
reset_agg_timer = true;
} else if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
/*
* nothing -- this aggregation session is being started
* but that might still fail with the driver
*/
} else if (!tx->sta->sta.txq[tid]) {
spin_lock(&tx->sta->lock);
/*
* Need to re-check now, because we may get here
*
* 1) in the window during which the setup is actually
* already done, but not marked yet because not all
* packets are spliced over to the driver pending
* queue yet -- if this happened we acquire the lock
* either before or after the splice happens, but
* need to recheck which of these cases happened.
*
* 2) during session teardown, if the OPERATIONAL bit
* was cleared due to the teardown but the pointer
* hasn't been assigned NULL yet (or we loaded it
* before it was assigned) -- in this case it may
* now be NULL which means we should just let the
* packet pass through because splicing the frames
* back is already done.
*/
tid_tx = rcu_dereference_protected_tid_tx(tx->sta, tid);
if (!tid_tx) {
/* do nothing, let packet pass through */
} else if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
info->flags |= IEEE80211_TX_CTL_AMPDU;
reset_agg_timer = true;
} else {
queued = true;
info->control.vif = &tx->sdata->vif;
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
__skb_queue_tail(&tid_tx->pending, skb);
if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
purge_skb = __skb_dequeue(&tid_tx->pending);
}
spin_unlock(&tx->sta->lock);
if (purge_skb)
ieee80211_free_txskb(&tx->local->hw, purge_skb);
}
/* reset session timer */
if (reset_agg_timer && tid_tx->timeout)
tid_tx->last_tx = jiffies;
return queued;
}
/*
* initialises @tx
* pass %NULL for the station if unknown, a valid pointer if known
* or an ERR_PTR() if the station is known not to exist
*/
static ieee80211_tx_result
ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
struct ieee80211_tx_data *tx,
struct sta_info *sta, struct sk_buff *skb)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_hdr *hdr;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int tid;
u8 *qc;
memset(tx, 0, sizeof(*tx));
tx->skb = skb;
tx->local = local;
tx->sdata = sdata;
__skb_queue_head_init(&tx->skbs);
/*
* If this flag is set to true anywhere, and we get here,
* we are doing the needed processing, so remove the flag
* now.
*/
info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING;
hdr = (struct ieee80211_hdr *) skb->data;
if (likely(sta)) {
if (!IS_ERR(sta))
tx->sta = sta;
} else {
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
tx->sta = rcu_dereference(sdata->u.vlan.sta);
if (!tx->sta && sdata->wdev.use_4addr)
return TX_DROP;
} else if (info->flags & (IEEE80211_TX_INTFL_NL80211_FRAME_TX |
IEEE80211_TX_CTL_INJECTED) ||
tx->sdata->control_port_protocol == tx->skb->protocol) {
tx->sta = sta_info_get_bss(sdata, hdr->addr1);
}
if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
tx->sta = sta_info_get(sdata, hdr->addr1);
}
if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
!ieee80211_is_qos_nullfunc(hdr->frame_control) &&
(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) &&
!(local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) {
struct tid_ampdu_tx *tid_tx;
qc = ieee80211_get_qos_ctl(hdr);
tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]);
if (tid_tx) {
bool queued;
queued = ieee80211_tx_prep_agg(tx, skb, info,
tid_tx, tid);
if (unlikely(queued))
return TX_QUEUED;
}
}
if (is_multicast_ether_addr(hdr->addr1)) {
tx->flags &= ~IEEE80211_TX_UNICAST;
info->flags |= IEEE80211_TX_CTL_NO_ACK;
} else
tx->flags |= IEEE80211_TX_UNICAST;
if (!(info->flags & IEEE80211_TX_CTL_DONTFRAG)) {
if (!(tx->flags & IEEE80211_TX_UNICAST) ||
skb->len + FCS_LEN <= local->hw.wiphy->frag_threshold ||
info->flags & IEEE80211_TX_CTL_AMPDU)
info->flags |= IEEE80211_TX_CTL_DONTFRAG;
}
if (!tx->sta)
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT))
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT;
return TX_CONTINUE;
}
static void ieee80211_drv_tx(struct ieee80211_local *local,
struct ieee80211_vif *vif,
struct ieee80211_sta *pubsta,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_control control = {
.sta = pubsta,
};
struct ieee80211_txq *txq = NULL;
struct txq_info *txqi;
u8 ac;
if (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE)
goto tx_normal;
if (!ieee80211_is_data(hdr->frame_control))
goto tx_normal;
if (pubsta) {
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
txq = pubsta->txq[tid];
} else if (vif) {
txq = vif->txq;
}
if (!txq)
goto tx_normal;
ac = txq->ac;
txqi = to_txq_info(txq);
atomic_inc(&sdata->txqs_len[ac]);
if (atomic_read(&sdata->txqs_len[ac]) >= local->hw.txq_ac_max_pending)
netif_stop_subqueue(sdata->dev, ac);
skb_queue_tail(&txqi->queue, skb);
drv_wake_tx_queue(local, txqi);
return;
tx_normal:
drv_tx(local, &control, skb);
}
struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
struct ieee80211_txq *txq)
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
struct txq_info *txqi = container_of(txq, struct txq_info, txq);
struct ieee80211_hdr *hdr;
struct sk_buff *skb = NULL;
u8 ac = txq->ac;
spin_lock_bh(&txqi->queue.lock);
if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags))
goto out;
skb = __skb_dequeue(&txqi->queue);
if (!skb)
goto out;
atomic_dec(&sdata->txqs_len[ac]);
if (__netif_subqueue_stopped(sdata->dev, ac))
ieee80211_propagate_queue_wake(local, sdata->vif.hw_queue[ac]);
hdr = (struct ieee80211_hdr *)skb->data;
if (txq->sta && ieee80211_is_data_qos(hdr->frame_control)) {
struct sta_info *sta = container_of(txq->sta, struct sta_info,
sta);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
hdr->seq_ctrl = ieee80211_tx_next_seq(sta, txq->tid);
if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
info->flags |= IEEE80211_TX_CTL_AMPDU;
else
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
}
out:
spin_unlock_bh(&txqi->queue.lock);
return skb;
}
EXPORT_SYMBOL(ieee80211_tx_dequeue);
static bool ieee80211_tx_frags(struct ieee80211_local *local,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct sk_buff_head *skbs,
bool txpending)
{
struct sk_buff *skb, *tmp;
unsigned long flags;
skb_queue_walk_safe(skbs, skb, tmp) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int q = info->hw_queue;
#ifdef CPTCFG_MAC80211_VERBOSE_DEBUG
if (WARN_ON_ONCE(q >= local->hw.queues)) {
__skb_unlink(skb, skbs);
ieee80211_free_txskb(&local->hw, skb);
continue;
}
#endif
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
if (local->queue_stop_reasons[q] ||
(!txpending && !skb_queue_empty(&local->pending[q]))) {
if (unlikely(info->flags &
IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) {
if (local->queue_stop_reasons[q] &
~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) {
/*
* Drop off-channel frames if queues
* are stopped for any reason other
* than off-channel operation. Never
* queue them.
*/
spin_unlock_irqrestore(
&local->queue_stop_reason_lock,
flags);
ieee80211_purge_tx_queue(&local->hw,
skbs);
return true;
}
} else {
/*
* Since queue is stopped, queue up frames for
* later transmission from the tx-pending
* tasklet when the queue is woken again.
*/
if (txpending)
skb_queue_splice_init(skbs,
&local->pending[q]);
else
skb_queue_splice_tail_init(skbs,
&local->pending[q]);
spin_unlock_irqrestore(&local->queue_stop_reason_lock,
flags);
return false;
}
}
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
info->control.vif = vif;
__skb_unlink(skb, skbs);
ieee80211_drv_tx(local, vif, sta, skb);
}
return true;
}
/*
* Returns false if the frame couldn't be transmitted but was queued instead.
*/
static bool __ieee80211_tx(struct ieee80211_local *local,
struct sk_buff_head *skbs, int led_len,
struct sta_info *sta, bool txpending)
{
struct ieee80211_tx_info *info;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_vif *vif;
struct ieee80211_sta *pubsta;
struct sk_buff *skb;
bool result = true;
__le16 fc;
if (WARN_ON(skb_queue_empty(skbs)))
return true;
skb = skb_peek(skbs);
fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
info = IEEE80211_SKB_CB(skb);
sdata = vif_to_sdata(info->control.vif);
if (sta && !sta->uploaded)
sta = NULL;
if (sta)
pubsta = &sta->sta;
else
pubsta = NULL;
switch (sdata->vif.type) {
case NL80211_IFTYPE_MONITOR:
if (sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE) {
vif = &sdata->vif;
break;
}
sdata = rcu_dereference(local->monitor_sdata);
if (sdata) {
vif = &sdata->vif;
info->hw_queue =
vif->hw_queue[skb_get_queue_mapping(skb)];
} else if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) {
dev_kfree_skb(skb);
return true;
} else
vif = NULL;
break;
case NL80211_IFTYPE_AP_VLAN:
sdata = container_of(sdata->bss,
struct ieee80211_sub_if_data, u.ap);
/* fall through */
default:
vif = &sdata->vif;
break;
}
result = ieee80211_tx_frags(local, vif, pubsta, skbs,
txpending);
ieee80211_tpt_led_trig_tx(local, fc, led_len);
WARN_ON_ONCE(!skb_queue_empty(skbs));
return result;
}
/*
* Invoke TX handlers, return 0 on success and non-zero if the
* frame was dropped or queued.
*/
static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
ieee80211_tx_result res = TX_DROP;
#define CALL_TXH(txh) \
do { \
res = txh(tx); \
if (res != TX_CONTINUE) \
goto txh_done; \
} while (0)
CALL_TXH(ieee80211_tx_h_dynamic_ps);
CALL_TXH(ieee80211_tx_h_check_assoc);
CALL_TXH(ieee80211_tx_h_ps_buf);
CALL_TXH(ieee80211_tx_h_check_control_port_protocol);
CALL_TXH(ieee80211_tx_h_select_key);
if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
CALL_TXH(ieee80211_tx_h_rate_ctrl);
if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) {
__skb_queue_tail(&tx->skbs, tx->skb);
tx->skb = NULL;
goto txh_done;
}
CALL_TXH(ieee80211_tx_h_michael_mic_add);
CALL_TXH(ieee80211_tx_h_sequence);
CALL_TXH(ieee80211_tx_h_fragment);
/* handlers after fragment must be aware of tx info fragmentation! */
CALL_TXH(ieee80211_tx_h_stats);
CALL_TXH(ieee80211_tx_h_encrypt);
if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
CALL_TXH(ieee80211_tx_h_calculate_duration);
#undef CALL_TXH
txh_done:
if (unlikely(res == TX_DROP)) {
I802_DEBUG_INC(tx->local->tx_handlers_drop);
if (tx->skb)
ieee80211_free_txskb(&tx->local->hw, tx->skb);
else
ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs);
return -1;
} else if (unlikely(res == TX_QUEUED)) {
I802_DEBUG_INC(tx->local->tx_handlers_queued);
return -1;
}
return 0;
}
bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct sk_buff *skb,
int band, struct ieee80211_sta **sta)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_data tx;
struct sk_buff *skb2;
if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP)
return false;
info->band = band;
info->control.vif = vif;
info->hw_queue = vif->hw_queue[skb_get_queue_mapping(skb)];
if (invoke_tx_handlers(&tx))
return false;
if (sta) {
if (tx.sta)
*sta = &tx.sta->sta;
else
*sta = NULL;
}
/* this function isn't suitable for fragmented data frames */
skb2 = __skb_dequeue(&tx.skbs);
if (WARN_ON(skb2 != skb || !skb_queue_empty(&tx.skbs))) {
ieee80211_free_txskb(hw, skb2);
ieee80211_purge_tx_queue(hw, &tx.skbs);
return false;
}
return true;
}
EXPORT_SYMBOL(ieee80211_tx_prepare_skb);
/*
* Returns false if the frame couldn't be transmitted but was queued instead.
*/
static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta, struct sk_buff *skb,
bool txpending)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_data tx;
ieee80211_tx_result res_prepare;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
bool result = true;
int led_len;
if (unlikely(skb->len < 10)) {
dev_kfree_skb(skb);
return true;
}
/* initialises tx */
led_len = skb->len;
res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb);
if (unlikely(res_prepare == TX_DROP)) {
ieee80211_free_txskb(&local->hw, skb);
return true;
} else if (unlikely(res_prepare == TX_QUEUED)) {
return true;
}
/* set up hw_queue value early */
if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
!(local->hw.flags & IEEE80211_HW_QUEUE_CONTROL))
info->hw_queue =
sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
if (!invoke_tx_handlers(&tx))
result = __ieee80211_tx(local, &tx.skbs, led_len,
tx.sta, txpending);
return result;
}
/* device xmit handlers */
static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb,
int head_need, bool may_encrypt)
{
struct ieee80211_local *local = sdata->local;
int tail_need = 0;
if (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt) {
tail_need = IEEE80211_ENCRYPT_TAILROOM;
tail_need -= skb_tailroom(skb);
tail_need = max_t(int, tail_need, 0);
}
if (skb_cloned(skb) &&
(!(local->hw.flags & IEEE80211_HW_SUPPORTS_CLONED_SKBS) ||
!skb_clone_writable(skb, ETH_HLEN) ||
(may_encrypt && sdata->crypto_tx_tailroom_needed_cnt)))
I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
else if (head_need || tail_need)
I802_DEBUG_INC(local->tx_expand_skb_head);
else
return 0;
if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) {
wiphy_debug(local->hw.wiphy,
"failed to reallocate TX buffer\n");
return -ENOMEM;
}
return 0;
}
void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta, struct sk_buff *skb)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
int headroom;
bool may_encrypt;
may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT);
headroom = local->tx_headroom;
if (may_encrypt)
headroom += sdata->encrypt_headroom;
headroom -= skb_headroom(skb);
headroom = max_t(int, 0, headroom);
if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
ieee80211_free_txskb(&local->hw, skb);
return;
}
hdr = (struct ieee80211_hdr *) skb->data;
info->control.vif = &sdata->vif;
if (ieee80211_vif_is_mesh(&sdata->vif)) {
if (ieee80211_is_data(hdr->frame_control) &&
is_unicast_ether_addr(hdr->addr1)) {
if (mesh_nexthop_resolve(sdata, skb))
return; /* skb queued: don't free */
} else {
ieee80211_mps_set_frame_flags(sdata, NULL, hdr);
}
}
ieee80211_set_qos_hdr(sdata, skb);
ieee80211_tx(sdata, sta, skb, false);
}
static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
{
struct ieee80211_radiotap_iterator iterator;
struct ieee80211_radiotap_header *rthdr =
(struct ieee80211_radiotap_header *) skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
NULL);
u16 txflags;
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
IEEE80211_TX_CTL_DONTFRAG;
/*
* for every radiotap entry that is present
* (ieee80211_radiotap_iterator_next returns -ENOENT when no more
* entries present, or -EINVAL on error)
*/
while (!ret) {
ret = ieee80211_radiotap_iterator_next(&iterator);
if (ret)
continue;
/* see if this argument is something we can use */
switch (iterator.this_arg_index) {
/*
* You must take care when dereferencing iterator.this_arg
* for multibyte types... the pointer is not aligned. Use
* get_unaligned((type *)iterator.this_arg) to dereference
* iterator.this_arg for type "type" safely on all arches.
*/
case IEEE80211_RADIOTAP_FLAGS:
if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {
/*
* this indicates that the skb we have been
* handed has the 32-bit FCS CRC at the end...
* we should react to that by snipping it off
* because it will be recomputed and added
* on transmission
*/
if (skb->len < (iterator._max_length + FCS_LEN))
return false;
skb_trim(skb, skb->len - FCS_LEN);
}
if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
info->flags &= ~IEEE80211_TX_CTL_DONTFRAG;
break;
case IEEE80211_RADIOTAP_TX_FLAGS:
txflags = get_unaligned_le16(iterator.this_arg);
if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK)
info->flags |= IEEE80211_TX_CTL_NO_ACK;
break;
/*
* Please update the file
* Documentation/networking/mac80211-injection.txt
* when parsing new fields here.
*/
default:
break;
}
}
if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
return false;
/*
* remove the radiotap header
* iterator->_max_length was sanity-checked against
* skb->len by iterator init
*/
skb_pull(skb, iterator._max_length);
return true;
}
netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_radiotap_header *prthdr =
(struct ieee80211_radiotap_header *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr;
struct ieee80211_sub_if_data *tmp_sdata, *sdata;
struct cfg80211_chan_def *chandef;
u16 len_rthdr;
int hdrlen;
/* check for not even having the fixed radiotap header part */
if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
goto fail; /* too short to be possibly valid */
/* is it a header version we can trust to find length from? */
if (unlikely(prthdr->it_version))
goto fail; /* only version 0 is supported */
/* then there must be a radiotap header with a length we can use */
len_rthdr = ieee80211_get_radiotap_len(skb->data);
/* does the skb contain enough to deliver on the alleged length? */
if (unlikely(skb->len < len_rthdr))
goto fail; /* skb too short for claimed rt header extent */
/*
* fix up the pointers accounting for the radiotap
* header still being in there. We are being given
* a precooked IEEE80211 header so no need for
* normal processing
*/
skb_set_mac_header(skb, len_rthdr);
/*
* these are just fixed to the end of the rt area since we
* don't have any better information and at this point, nobody cares
*/
skb_set_network_header(skb, len_rthdr);
skb_set_transport_header(skb, len_rthdr);
if (skb->len < len_rthdr + 2)
goto fail;
hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
hdrlen = ieee80211_hdrlen(hdr->frame_control);
if (skb->len < len_rthdr + hdrlen)
goto fail;
/*
* Initialize skb->protocol if the injected frame is a data frame
* carrying a rfc1042 header
*/
if (ieee80211_is_data(hdr->frame_control) &&
skb->len >= len_rthdr + hdrlen + sizeof(rfc1042_header) + 2) {
u8 *payload = (u8 *)hdr + hdrlen;
if (ether_addr_equal(payload, rfc1042_header))
skb->protocol = cpu_to_be16((payload[6] << 8) |
payload[7]);
}
memset(info, 0, sizeof(*info));
info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
IEEE80211_TX_CTL_INJECTED;
/* process and remove the injection radiotap header */
if (!ieee80211_parse_tx_radiotap(skb))
goto fail;
rcu_read_lock();
/*
* We process outgoing injected frames that have a local address
* we handle as though they are non-injected frames.
* This code here isn't entirely correct, the local MAC address
* isn't always enough to find the interface to use; for proper
* VLAN/WDS support we will need a different mechanism (which
* likely isn't going to be monitor interfaces).
*/
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
list_for_each_entry_rcu(tmp_sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(tmp_sdata))
continue;
if (tmp_sdata->vif.type == NL80211_IFTYPE_MONITOR ||
tmp_sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
tmp_sdata->vif.type == NL80211_IFTYPE_WDS)
continue;
if (ether_addr_equal(tmp_sdata->vif.addr, hdr->addr2)) {
sdata = tmp_sdata;
break;
}
}
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) {
tmp_sdata = rcu_dereference(local->monitor_sdata);
if (tmp_sdata)
chanctx_conf =
rcu_dereference(tmp_sdata->vif.chanctx_conf);
}
if (chanctx_conf)
chandef = &chanctx_conf->def;
else if (!local->use_chanctx)
chandef = &local->_oper_chandef;
else
goto fail_rcu;
/*
* Frame injection is not allowed if beaconing is not allowed
* or if we need radar detection. Beaconing is usually not allowed when
* the mode or operation (Adhoc, AP, Mesh) does not support DFS.
* Passive scan is also used in world regulatory domains where
* your country is not known and as such it should be treated as
* NO TX unless the channel is explicitly allowed in which case
* your current regulatory domain would not have the passive scan
* flag.
*
* Since AP mode uses monitor interfaces to inject/TX management
* frames we can make AP mode the exception to this rule once it
* supports radar detection as its implementation can deal with
* radar detection by itself. We can do that later by adding a
* monitor flag interfaces used for AP support.
*/
if (!cfg80211_reg_can_beacon(local->hw.wiphy, chandef,
sdata->vif.type))
goto fail_rcu;
info->band = chandef->chan->band;
ieee80211_xmit(sdata, NULL, skb);
rcu_read_unlock();
return NETDEV_TX_OK;
fail_rcu:
rcu_read_unlock();
fail:
dev_kfree_skb(skb);
return NETDEV_TX_OK; /* meaning, we dealt with the skb */
}
static inline bool ieee80211_is_tdls_setup(struct sk_buff *skb)
{
u16 ethertype = (skb->data[12] << 8) | skb->data[13];
return ethertype == ETH_P_TDLS &&
skb->len > 14 &&
skb->data[14] == WLAN_TDLS_SNAP_RFTYPE;
}
static int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb,
struct sta_info **sta_out)
{
struct sta_info *sta;
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
sta = rcu_dereference(sdata->u.vlan.sta);
if (sta) {
*sta_out = sta;
return 0;
} else if (sdata->wdev.use_4addr) {
return -ENOLINK;
}
/* fall through */
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_OCB:
case NL80211_IFTYPE_ADHOC:
if (is_multicast_ether_addr(skb->data)) {
*sta_out = ERR_PTR(-ENOENT);
return 0;
}
sta = sta_info_get_bss(sdata, skb->data);
break;
case NL80211_IFTYPE_WDS:
sta = sta_info_get(sdata, sdata->u.wds.remote_addr);
break;
#ifdef CPTCFG_MAC80211_MESH
case NL80211_IFTYPE_MESH_POINT:
/* determined much later */
*sta_out = NULL;
return 0;
#endif
case NL80211_IFTYPE_STATION:
if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) {
sta = sta_info_get(sdata, skb->data);
if (sta) {
bool tdls_peer, tdls_auth;
tdls_peer = test_sta_flag(sta,
WLAN_STA_TDLS_PEER);
tdls_auth = test_sta_flag(sta,
WLAN_STA_TDLS_PEER_AUTH);
if (tdls_peer && tdls_auth) {
*sta_out = sta;
return 0;
}
/*
* TDLS link during setup - throw out frames to
* peer. Allow TDLS-setup frames to unauthorized
* peers for the special case of a link teardown
* after a TDLS sta is removed due to being
* unreachable.
*/
if (tdls_peer && !tdls_auth &&
!ieee80211_is_tdls_setup(skb))
return -EINVAL;
}
}
sta = sta_info_get(sdata, sdata->u.mgd.bssid);
if (!sta)
return -ENOLINK;
break;
default:
return -EINVAL;
}
*sta_out = sta ?: ERR_PTR(-ENOENT);
return 0;
}
/**
* ieee80211_build_hdr - build 802.11 header in the given frame
* @sdata: virtual interface to build the header for
* @skb: the skb to build the header in
* @info_flags: skb flags to set
*
* This function takes the skb with 802.3 header and reformats the header to
* the appropriate IEEE 802.11 header based on which interface the packet is
* being transmitted on.
*
* Note that this function also takes care of the TX status request and
* potential unsharing of the SKB - this needs to be interleaved with the
* header building.
*
* The function requires the read-side RCU lock held
*
* Returns: the (possibly reallocated) skb or an ERR_PTR() code
*/
static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, u32 info_flags,
struct sta_info *sta)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_info *info;
int head_need;
u16 ethertype, hdrlen, meshhdrlen = 0;
__le16 fc;
struct ieee80211_hdr hdr;
struct ieee80211s_hdr mesh_hdr __maybe_unused;
struct mesh_path __maybe_unused *mppath = NULL, *mpath = NULL;
const u8 *encaps_data;
int encaps_len, skip_header_bytes;
int nh_pos, h_pos;
bool wme_sta = false, authorized = false;
bool tdls_peer;
bool multicast;
u16 info_id = 0;
struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_sub_if_data *ap_sdata;
enum ieee80211_band band;
int ret;
if (IS_ERR(sta))
sta = NULL;
/* convert Ethernet header to proper 802.11 header (based on
* operation mode) */
ethertype = (skb->data[12] << 8) | skb->data[13];
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
if (sdata->wdev.use_4addr) {
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
/* RA TA DA SA */
memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN);
memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
memcpy(hdr.addr3, skb->data, ETH_ALEN);
memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
hdrlen = 30;
authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
wme_sta = sta->sta.wme;
}
ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
u.ap);
chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf);
if (!chanctx_conf) {
ret = -ENOTCONN;
goto free;
}
band = chanctx_conf->def.chan->band;
if (sdata->wdev.use_4addr)
break;
/* fall through */
case NL80211_IFTYPE_AP:
if (sdata->vif.type == NL80211_IFTYPE_AP)
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) {
ret = -ENOTCONN;
goto free;
}
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
/* DA BSSID SA */
memcpy(hdr.addr1, skb->data, ETH_ALEN);
memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
hdrlen = 24;
band = chanctx_conf->def.chan->band;
break;
case NL80211_IFTYPE_WDS:
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
/* RA TA DA SA */
memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN);
memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
memcpy(hdr.addr3, skb->data, ETH_ALEN);
memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
hdrlen = 30;
/*
* This is the exception! WDS style interfaces are prohibited
* when channel contexts are in used so this must be valid
*/
band = local->hw.conf.chandef.chan->band;
break;
#ifdef CPTCFG_MAC80211_MESH
case NL80211_IFTYPE_MESH_POINT:
if (!is_multicast_ether_addr(skb->data)) {
struct sta_info *next_hop;
bool mpp_lookup = true;
mpath = mesh_path_lookup(sdata, skb->data);
if (mpath) {
mpp_lookup = false;
next_hop = rcu_dereference(mpath->next_hop);
if (!next_hop ||
!(mpath->flags & (MESH_PATH_ACTIVE |
MESH_PATH_RESOLVING)))
mpp_lookup = true;
}
if (mpp_lookup)
mppath = mpp_path_lookup(sdata, skb->data);
if (mppath && mpath)
mesh_path_del(mpath->sdata, mpath->dst);
}
/*
* Use address extension if it is a packet from
* another interface or if we know the destination
* is being proxied by a portal (i.e. portal address
* differs from proxied address)
*/
if (ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN) &&
!(mppath && !ether_addr_equal(mppath->mpp, skb->data))) {
hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
skb->data, skb->data + ETH_ALEN);
meshhdrlen = ieee80211_new_mesh_header(sdata, &mesh_hdr,
NULL, NULL);
} else {
/* DS -> MBSS (802.11-2012 13.11.3.3).
* For unicast with unknown forwarding information,
* destination might be in the MBSS or if that fails
* forwarded to another mesh gate. In either case
* resolution will be handled in ieee80211_xmit(), so
* leave the original DA. This also works for mcast */
const u8 *mesh_da = skb->data;
if (mppath)
mesh_da = mppath->mpp;
else if (mpath)
mesh_da = mpath->dst;
hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
mesh_da, sdata->vif.addr);
if (is_multicast_ether_addr(mesh_da))
/* DA TA mSA AE:SA */
meshhdrlen = ieee80211_new_mesh_header(
sdata, &mesh_hdr,
skb->data + ETH_ALEN, NULL);
else
/* RA TA mDA mSA AE:DA SA */
meshhdrlen = ieee80211_new_mesh_header(
sdata, &mesh_hdr, skb->data,
skb->data + ETH_ALEN);
}
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) {
ret = -ENOTCONN;
goto free;
}
band = chanctx_conf->def.chan->band;
break;
#endif
case NL80211_IFTYPE_STATION:
/* we already did checks when looking up the RA STA */
tdls_peer = test_sta_flag(sta, WLAN_STA_TDLS_PEER);
if (tdls_peer) {
/* DA SA BSSID */
memcpy(hdr.addr1, skb->data, ETH_ALEN);
memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
memcpy(hdr.addr3, sdata->u.mgd.bssid, ETH_ALEN);
hdrlen = 24;
} else if (sdata->u.mgd.use_4addr &&
cpu_to_be16(ethertype) != sdata->control_port_protocol) {
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
IEEE80211_FCTL_TODS);
/* RA TA DA SA */
memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
memcpy(hdr.addr3, skb->data, ETH_ALEN);
memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
hdrlen = 30;
} else {
fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
/* BSSID SA DA */
memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
memcpy(hdr.addr3, skb->data, ETH_ALEN);
hdrlen = 24;
}
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) {
ret = -ENOTCONN;
goto free;
}
band = chanctx_conf->def.chan->band;
break;
case NL80211_IFTYPE_OCB:
/* DA SA BSSID */
memcpy(hdr.addr1, skb->data, ETH_ALEN);
memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
eth_broadcast_addr(hdr.addr3);
hdrlen = 24;
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) {
ret = -ENOTCONN;
goto free;
}
band = chanctx_conf->def.chan->band;
break;
case NL80211_IFTYPE_ADHOC:
/* DA SA BSSID */
memcpy(hdr.addr1, skb->data, ETH_ALEN);
memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
memcpy(hdr.addr3, sdata->u.ibss.bssid, ETH_ALEN);
hdrlen = 24;
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) {
ret = -ENOTCONN;
goto free;
}
band = chanctx_conf->def.chan->band;
break;
default:
ret = -EINVAL;
goto free;
}
multicast = is_multicast_ether_addr(hdr.addr1);
/* sta is always NULL for mesh */
if (sta) {
authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
wme_sta = sta->sta.wme;
} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
/* For mesh, the use of the QoS header is mandatory */
wme_sta = true;
}
/* receiver does QoS (which also means we do) use it */
if (wme_sta) {
fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
hdrlen += 2;
}
/*
* Drop unicast frames to unauthorised stations unless they are
* EAPOL frames from the local station.
*/
if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) &&
(sdata->vif.type != NL80211_IFTYPE_OCB) &&
!multicast && !authorized &&
(cpu_to_be16(ethertype) != sdata->control_port_protocol ||
!ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) {
#ifdef CPTCFG_MAC80211_VERBOSE_DEBUG
net_info_ratelimited("%s: dropped frame to %pM (unauthorized port)\n",
sdata->name, hdr.addr1);
#endif
I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
ret = -EPERM;
goto free;
}
if (unlikely(!multicast && skb->sk &&
skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) {
struct sk_buff *ack_skb = skb_clone_sk(skb);
if (ack_skb) {
unsigned long flags;
int id;
spin_lock_irqsave(&local->ack_status_lock, flags);
id = idr_alloc(&local->ack_status_frames, ack_skb,
1, 0x10000, GFP_ATOMIC);
spin_unlock_irqrestore(&local->ack_status_lock, flags);
if (id >= 0) {
info_id = id;
info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
} else {
kfree_skb(ack_skb);
}
}
}
/*
* If the skb is shared we need to obtain our own copy.
*/
if (skb_shared(skb)) {
struct sk_buff *tmp_skb = skb;
/* can't happen -- skb is a clone if info_id != 0 */
WARN_ON(info_id);
skb = skb_clone(skb, GFP_ATOMIC);
kfree_skb(tmp_skb);
if (!skb) {
ret = -ENOMEM;
goto free;
}
}
hdr.frame_control = fc;
hdr.duration_id = 0;
hdr.seq_ctrl = 0;
skip_header_bytes = ETH_HLEN;
if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
encaps_data = bridge_tunnel_header;
encaps_len = sizeof(bridge_tunnel_header);
skip_header_bytes -= 2;
} else if (ethertype >= ETH_P_802_3_MIN) {
encaps_data = rfc1042_header;
encaps_len = sizeof(rfc1042_header);
skip_header_bytes -= 2;
} else {
encaps_data = NULL;
encaps_len = 0;
}
nh_pos = skb_network_header(skb) - skb->data;
h_pos = skb_transport_header(skb) - skb->data;
skb_pull(skb, skip_header_bytes);
nh_pos -= skip_header_bytes;
h_pos -= skip_header_bytes;
head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
/*
* So we need to modify the skb header and hence need a copy of
* that. The head_need variable above doesn't, so far, include
* the needed header space that we don't need right away. If we
* can, then we don't reallocate right now but only after the
* frame arrives at the master device (if it does...)
*
* If we cannot, however, then we will reallocate to include all
* the ever needed space. Also, if we need to reallocate it anyway,
* make it big enough for everything we may ever need.
*/
if (head_need > 0 || skb_cloned(skb)) {
head_need += sdata->encrypt_headroom;
head_need += local->tx_headroom;
head_need = max_t(int, 0, head_need);
if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
ieee80211_free_txskb(&local->hw, skb);
skb = NULL;
return ERR_PTR(-ENOMEM);
}
}
if (encaps_data) {
memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
nh_pos += encaps_len;
h_pos += encaps_len;
}
#ifdef CPTCFG_MAC80211_MESH
if (meshhdrlen > 0) {
memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
nh_pos += meshhdrlen;
h_pos += meshhdrlen;
}
#endif
if (ieee80211_is_data_qos(fc)) {
__le16 *qos_control;
qos_control = (__le16 *) skb_push(skb, 2);
memcpy(skb_push(skb, hdrlen - 2), &hdr, hdrlen - 2);
/*
* Maybe we could actually set some fields here, for now just
* initialise to zero to indicate no special operation.
*/
*qos_control = 0;
} else
memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
nh_pos += hdrlen;
h_pos += hdrlen;
/* Update skb pointers to various headers since this modified frame
* is going to go through Linux networking code that may potentially
* need things like pointer to IP header. */
skb_set_mac_header(skb, 0);
skb_set_network_header(skb, nh_pos);
skb_set_transport_header(skb, h_pos);
info = IEEE80211_SKB_CB(skb);
memset(info, 0, sizeof(*info));
info->flags = info_flags;
info->ack_frame_id = info_id;
info->band = band;
return skb;
free:
kfree_skb(skb);
return ERR_PTR(ret);
}
/*
* fast-xmit overview
*
* The core idea of this fast-xmit is to remove per-packet checks by checking
* them out of band. ieee80211_check_fast_xmit() implements the out-of-band
* checks that are needed to get the sta->fast_tx pointer assigned, after which
* much less work can be done per packet. For example, fragmentation must be
* disabled or the fast_tx pointer will not be set. All the conditions are seen
* in the code here.
*
* Once assigned, the fast_tx data structure also caches the per-packet 802.11
* header and other data to aid packet processing in ieee80211_xmit_fast().
*
* The most difficult part of this is that when any of these assumptions
* change, an external trigger (i.e. a call to ieee80211_clear_fast_xmit(),
* ieee80211_check_fast_xmit() or friends) is required to reset the data,
* since the per-packet code no longer checks the conditions. This is reflected
* by the calls to these functions throughout the rest of the code, and must be
* maintained if any of the TX path checks change.
*/
void ieee80211_check_fast_xmit(struct sta_info *sta)
{
struct ieee80211_fast_tx build = {}, *fast_tx = NULL, *old;
struct ieee80211_local *local = sta->local;
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_hdr *hdr = (void *)build.hdr;
struct ieee80211_chanctx_conf *chanctx_conf;
__le16 fc;
if (!(local->hw.flags & IEEE80211_HW_SUPPORT_FAST_XMIT))
return;
/* Locking here protects both the pointer itself, and against concurrent
* invocations winning data access races to, e.g., the key pointer that
* is used.
* Without it, the invocation of this function right after the key
* pointer changes wouldn't be sufficient, as another CPU could access
* the pointer, then stall, and then do the cache update after the CPU
* that invalidated the key.
* With the locking, such scenarios cannot happen as the check for the
* key and the fast-tx assignment are done atomically, so the CPU that
* modifies the key will either wait or other one will see the key
* cleared/changed already.
*/
spin_lock_bh(&sta->lock);
if (local->hw.flags & IEEE80211_HW_SUPPORTS_PS &&
!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) &&
sdata->vif.type == NL80211_IFTYPE_STATION)
goto out;
if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED))
goto out;
if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
test_sta_flag(sta, WLAN_STA_PS_DELIVER))
goto out;
if (sdata->noack_map)
goto out;
/* fast-xmit doesn't handle fragmentation at all */
if (local->hw.wiphy->frag_threshold != (u32)-1 &&
!local->ops->set_frag_threshold)
goto out;
rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) {
rcu_read_unlock();
goto out;
}
build.band = chanctx_conf->def.chan->band;
rcu_read_unlock();
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
switch (sdata->vif.type) {
case NL80211_IFTYPE_ADHOC:
/* DA SA BSSID */
build.da_offs = offsetof(struct ieee80211_hdr, addr1);
build.sa_offs = offsetof(struct ieee80211_hdr, addr2);
memcpy(hdr->addr3, sdata->u.ibss.bssid, ETH_ALEN);
build.hdr_len = 24;
break;
case NL80211_IFTYPE_STATION:
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
/* DA SA BSSID */
build.da_offs = offsetof(struct ieee80211_hdr, addr1);
build.sa_offs = offsetof(struct ieee80211_hdr, addr2);
memcpy(hdr->addr3, sdata->u.mgd.bssid, ETH_ALEN);
build.hdr_len = 24;
break;
}
if (sdata->u.mgd.use_4addr) {
/* non-regular ethertype cannot use the fastpath */
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
IEEE80211_FCTL_TODS);
/* RA TA DA SA */
memcpy(hdr->addr1, sdata->u.mgd.bssid, ETH_ALEN);
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
build.da_offs = offsetof(struct ieee80211_hdr, addr3);
build.sa_offs = offsetof(struct ieee80211_hdr, addr4);
build.hdr_len = 30;
break;
}
fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
/* BSSID SA DA */
memcpy(hdr->addr1, sdata->u.mgd.bssid, ETH_ALEN);
build.da_offs = offsetof(struct ieee80211_hdr, addr3);
build.sa_offs = offsetof(struct ieee80211_hdr, addr2);
build.hdr_len = 24;
break;
case NL80211_IFTYPE_AP_VLAN:
if (sdata->wdev.use_4addr) {
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
IEEE80211_FCTL_TODS);
/* RA TA DA SA */
memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN);
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
build.da_offs = offsetof(struct ieee80211_hdr, addr3);
build.sa_offs = offsetof(struct ieee80211_hdr, addr4);
build.hdr_len = 30;
break;
}
/* fall through */
case NL80211_IFTYPE_AP:
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
/* DA BSSID SA */
build.da_offs = offsetof(struct ieee80211_hdr, addr1);
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
build.sa_offs = offsetof(struct ieee80211_hdr, addr3);
build.hdr_len = 24;
break;
default:
/* not handled on fast-xmit */
goto out;
}
if (sta->sta.wme) {
build.hdr_len += 2;
fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
}
/* We store the key here so there's no point in using rcu_dereference()
* but that's fine because the code that changes the pointers will call
* this function after doing so. For a single CPU that would be enough,
* for multiple see the comment above.
*/
build.key = rcu_access_pointer(sta->ptk[sta->ptk_idx]);
if (!build.key)
build.key = rcu_access_pointer(sdata->default_unicast_key);
if (build.key) {
bool gen_iv, iv_spc, mmic;
gen_iv = build.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV;
iv_spc = build.key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE;
mmic = build.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC;
/* don't handle software crypto */
if (!(build.key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
goto out;
switch (build.key->conf.cipher) {
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
/* add fixed key ID */
if (gen_iv) {
(build.hdr + build.hdr_len)[3] =
0x20 | (build.key->conf.keyidx << 6);
build.pn_offs = build.hdr_len;
}
if (gen_iv || iv_spc)
build.hdr_len += IEEE80211_CCMP_HDR_LEN;
break;
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
/* add fixed key ID */
if (gen_iv) {
(build.hdr + build.hdr_len)[3] =
0x20 | (build.key->conf.keyidx << 6);
build.pn_offs = build.hdr_len;
}
if (gen_iv || iv_spc)
build.hdr_len += IEEE80211_GCMP_HDR_LEN;
break;
case WLAN_CIPHER_SUITE_TKIP:
/* cannot handle MMIC or IV generation in xmit-fast */
if (mmic || gen_iv)
goto out;
if (iv_spc)
build.hdr_len += IEEE80211_TKIP_IV_LEN;
break;
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
/* cannot handle IV generation in fast-xmit */
if (gen_iv)
goto out;
if (iv_spc)
build.hdr_len += IEEE80211_WEP_IV_LEN;
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
WARN(1,
"management cipher suite 0x%x enabled for data\n",
build.key->conf.cipher);
goto out;
default:
/* we don't know how to generate IVs for this at all */
if (WARN_ON(gen_iv))
goto out;
/* pure hardware keys are OK, of course */
if (!(build.key->flags & KEY_FLAG_CIPHER_SCHEME))
break;
/* cipher scheme might require space allocation */
if (iv_spc &&
build.key->conf.iv_len > IEEE80211_FAST_XMIT_MAX_IV)
goto out;
if (iv_spc)
build.hdr_len += build.key->conf.iv_len;
}
fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
}
hdr->frame_control = fc;
memcpy(build.hdr + build.hdr_len,
rfc1042_header, sizeof(rfc1042_header));
build.hdr_len += sizeof(rfc1042_header);
fast_tx = kmemdup(&build, sizeof(build), GFP_ATOMIC);
/* if the kmemdup fails, continue w/o fast_tx */
if (!fast_tx)
goto out;
out:
/* we might have raced against another call to this function */
old = rcu_dereference_protected(sta->fast_tx,
lockdep_is_held(&sta->lock));
rcu_assign_pointer(sta->fast_tx, fast_tx);
if (old)
kfree_rcu(old, rcu_head);
spin_unlock_bh(&sta->lock);
}
void ieee80211_check_fast_xmit_all(struct ieee80211_local *local)
{
struct sta_info *sta;
rcu_read_lock();
list_for_each_entry_rcu(sta, &local->sta_list, list)
ieee80211_check_fast_xmit(sta);
rcu_read_unlock();
}
void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
rcu_read_lock();
list_for_each_entry_rcu(sta, &local->sta_list, list) {
if (sdata != sta->sdata &&
(!sta->sdata->bss || sta->sdata->bss != sdata->bss))
continue;
ieee80211_check_fast_xmit(sta);
}
rcu_read_unlock();
}
void ieee80211_clear_fast_xmit(struct sta_info *sta)
{
struct ieee80211_fast_tx *fast_tx;
spin_lock_bh(&sta->lock);
fast_tx = rcu_dereference_protected(sta->fast_tx,
lockdep_is_held(&sta->lock));
RCU_INIT_POINTER(sta->fast_tx, NULL);
spin_unlock_bh(&sta->lock);
if (fast_tx)
kfree_rcu(fast_tx, rcu_head);
}
static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
struct net_device *dev, struct sta_info *sta,
struct ieee80211_fast_tx *fast_tx,
struct sk_buff *skb)
{
struct ieee80211_local *local = sdata->local;
u16 ethertype = (skb->data[12] << 8) | skb->data[13];
int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
int hw_headroom = sdata->local->hw.extra_tx_headroom;
struct ethhdr eth;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
struct ieee80211_tx_data tx;
ieee80211_tx_result r;
struct tid_ampdu_tx *tid_tx = NULL;
u8 tid = IEEE80211_NUM_TIDS;
/* control port protocol needs a lot of special handling */
if (cpu_to_be16(ethertype) == sdata->control_port_protocol)
return false;
/* only RFC 1042 SNAP */
if (ethertype < ETH_P_802_3_MIN)
return false;
/* don't handle TX status request here either */
if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
return false;
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
if (tid_tx &&
!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
return false;
}
/* after this point (skb is modified) we cannot return false */
if (skb_shared(skb)) {
struct sk_buff *tmp_skb = skb;
skb = skb_clone(skb, GFP_ATOMIC);
kfree_skb(tmp_skb);
if (!skb)
return true;
}
ieee80211_tx_stats(dev, skb->len + extra_head);
/* will not be crypto-handled beyond what we do here, so use false
* as the may-encrypt argument for the resize to not account for
* more room than we already have in 'extra_head'
*/
if (unlikely(ieee80211_skb_resize(sdata, skb,
max_t(int, extra_head + hw_headroom -
skb_headroom(skb), 0),
false))) {
kfree_skb(skb);
return true;
}
memcpy(ð, skb->data, ETH_HLEN - 2);
hdr = (void *)skb_push(skb, extra_head);
memcpy(skb->data, fast_tx->hdr, fast_tx->hdr_len);
memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN);
memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN);
memset(info, 0, sizeof(*info));
info->band = fast_tx->band;
info->control.vif = &sdata->vif;
info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT |
IEEE80211_TX_CTL_DONTFRAG |
(tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
*ieee80211_get_qos_ctl(hdr) = tid;
hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid);
} else {
info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
hdr->seq_ctrl = cpu_to_le16(sdata->sequence_number);
sdata->sequence_number += 0x10;
}
sta->tx_msdu[tid]++;
info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
__skb_queue_head_init(&tx.skbs);
tx.flags = IEEE80211_TX_UNICAST;
tx.local = local;
tx.sdata = sdata;
tx.sta = sta;
tx.key = fast_tx->key;
if (fast_tx->key)
info->control.hw_key = &fast_tx->key->conf;
if (!(local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) {
tx.skb = skb;
r = ieee80211_tx_h_rate_ctrl(&tx);
skb = tx.skb;
tx.skb = NULL;
if (r != TX_CONTINUE) {
if (r != TX_QUEUED)
kfree_skb(skb);
return true;
}
}
/* statistics normally done by ieee80211_tx_h_stats (but that
* has to consider fragmentation, so is more complex)
*/
sta->tx_bytes[skb_get_queue_mapping(skb)] += skb->len;
sta->tx_packets[skb_get_queue_mapping(skb)]++;
if (fast_tx->pn_offs) {
u64 pn;
u8 *crypto_hdr = skb->data + fast_tx->pn_offs;
switch (fast_tx->key->conf.cipher) {
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
pn = atomic64_inc_return(&fast_tx->key->u.ccmp.tx_pn);
crypto_hdr[0] = pn;
crypto_hdr[1] = pn >> 8;
crypto_hdr[4] = pn >> 16;
crypto_hdr[5] = pn >> 24;
crypto_hdr[6] = pn >> 32;
crypto_hdr[7] = pn >> 40;
break;
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
pn = atomic64_inc_return(&fast_tx->key->u.gcmp.tx_pn);
crypto_hdr[0] = pn;
crypto_hdr[1] = pn >> 8;
crypto_hdr[4] = pn >> 16;
crypto_hdr[5] = pn >> 24;
crypto_hdr[6] = pn >> 32;
crypto_hdr[7] = pn >> 40;
break;
}
}
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
sdata = container_of(sdata->bss,
struct ieee80211_sub_if_data, u.ap);
__skb_queue_tail(&tx.skbs, skb);
ieee80211_tx_frags(local, &sdata->vif, &sta->sta, &tx.skbs, false);
return true;
}
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev,
u32 info_flags)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct sta_info *sta;
struct sk_buff *next;
if (unlikely(skb->len < ETH_HLEN)) {
kfree_skb(skb);
return;
}
rcu_read_lock();
if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
goto out_free;
if (!IS_ERR_OR_NULL(sta)) {
struct ieee80211_fast_tx *fast_tx;
fast_tx = rcu_dereference(sta->fast_tx);
if (fast_tx &&
ieee80211_xmit_fast(sdata, dev, sta, fast_tx, skb))
goto out;
}
if (skb_is_gso(skb)) {
struct sk_buff *segs;
segs = skb_gso_segment(skb, 0);
if (IS_ERR(segs)) {
goto out_free;
} else if (segs) {
consume_skb(skb);
skb = segs;
}
} else {
/* we cannot process non-linear frames on this path */
if (skb_linearize(skb)) {
kfree_skb(skb);
goto out;
}
/* the frame could be fragmented, software-encrypted, and other
* things so we cannot really handle checksum offload with it -
* fix it up in software before we handle anything else.
*/
if (skb->ip_summed == CHECKSUM_PARTIAL) {
if (skb->encapsulation)
skb_set_inner_transport_header(skb,
skb_checksum_start_offset(skb));
else
skb_set_transport_header(skb,
skb_checksum_start_offset(skb));
if (skb_checksum_help(skb))
goto out_free;
}
}
next = skb;
while (next) {
skb = next;
next = skb->next;
skb->prev = NULL;
skb->next = NULL;
skb = ieee80211_build_hdr(sdata, skb, info_flags, sta);
if (IS_ERR(skb))
goto out;
ieee80211_tx_stats(dev, skb->len);
ieee80211_xmit(sdata, sta, skb);
}
goto out;
out_free:
kfree_skb(skb);
out:
rcu_read_unlock();
}
/**
* ieee80211_subif_start_xmit - netif start_xmit function for 802.3 vifs
* @skb: packet to be sent
* @dev: incoming interface
*
* On failure skb will be freed.
*/
netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
__ieee80211_subif_start_xmit(skb, dev, 0);
return NETDEV_TX_OK;
}
struct sk_buff *
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, u32 info_flags)
{
struct ieee80211_hdr *hdr;
struct ieee80211_tx_data tx = {
.local = sdata->local,
.sdata = sdata,
};
struct sta_info *sta;
rcu_read_lock();
if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
kfree_skb(skb);
skb = ERR_PTR(-EINVAL);
goto out;
}
skb = ieee80211_build_hdr(sdata, skb, info_flags, sta);
if (IS_ERR(skb))
goto out;
hdr = (void *)skb->data;
tx.sta = sta_info_get(sdata, hdr->addr1);
tx.skb = skb;
if (ieee80211_tx_h_select_key(&tx) != TX_CONTINUE) {
rcu_read_unlock();
kfree_skb(skb);
return ERR_PTR(-EINVAL);
}
out:
rcu_read_unlock();
return skb;
}
/*
* ieee80211_clear_tx_pending may not be called in a context where
* it is possible that it packets could come in again.
*/
void ieee80211_clear_tx_pending(struct ieee80211_local *local)
{
struct sk_buff *skb;
int i;
for (i = 0; i < local->hw.queues; i++) {
while ((skb = skb_dequeue(&local->pending[i])) != NULL)
ieee80211_free_txskb(&local->hw, skb);
}
}
/*
* Returns false if the frame couldn't be transmitted but was queued instead,
* which in this case means re-queued -- take as an indication to stop sending
* more pending frames.
*/
static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
struct ieee80211_hdr *hdr;
bool result;
struct ieee80211_chanctx_conf *chanctx_conf;
sdata = vif_to_sdata(info->control.vif);
if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) {
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (unlikely(!chanctx_conf)) {
dev_kfree_skb(skb);
return true;
}
info->band = chanctx_conf->def.chan->band;
result = ieee80211_tx(sdata, NULL, skb, true);
} else {
struct sk_buff_head skbs;
__skb_queue_head_init(&skbs);
__skb_queue_tail(&skbs, skb);
hdr = (struct ieee80211_hdr *)skb->data;
sta = sta_info_get(sdata, hdr->addr1);
result = __ieee80211_tx(local, &skbs, skb->len, sta, true);
}
return result;
}
/*
* Transmit all pending packets. Called from tasklet.
*/
void ieee80211_tx_pending(unsigned long data)
{
struct ieee80211_local *local = (struct ieee80211_local *)data;
unsigned long flags;
int i;
bool txok;
rcu_read_lock();
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
for (i = 0; i < local->hw.queues; i++) {
/*
* If queue is stopped by something other than due to pending
* frames, or we have no pending frames, proceed to next queue.
*/
if (local->queue_stop_reasons[i] ||
skb_queue_empty(&local->pending[i]))
continue;
while (!skb_queue_empty(&local->pending[i])) {
struct sk_buff *skb = __skb_dequeue(&local->pending[i]);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
if (WARN_ON(!info->control.vif)) {
ieee80211_free_txskb(&local->hw, skb);
continue;
}
spin_unlock_irqrestore(&local->queue_stop_reason_lock,
flags);
txok = ieee80211_tx_pending_skb(local, skb);
spin_lock_irqsave(&local->queue_stop_reason_lock,
flags);
if (!txok)
break;
}
if (skb_queue_empty(&local->pending[i]))
ieee80211_propagate_queue_wake(local, i);
}
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
rcu_read_unlock();
}
/* functions for drivers to get certain frames */
static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
struct ps_data *ps, struct sk_buff *skb,
bool is_template)
{
u8 *pos, *tim;
int aid0 = 0;
int i, have_bits = 0, n1, n2;
/* Generate bitmap for TIM only if there are any STAs in power save
* mode. */
if (atomic_read(&ps->num_sta_ps) > 0)
/* in the hope that this is faster than
* checking byte-for-byte */
have_bits = !bitmap_empty((unsigned long *)ps->tim,
IEEE80211_MAX_AID+1);
if (!is_template) {
if (ps->dtim_count == 0)
ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1;
else
ps->dtim_count--;
}
tim = pos = (u8 *) skb_put(skb, 6);
*pos++ = WLAN_EID_TIM;
*pos++ = 4;
*pos++ = ps->dtim_count;
*pos++ = sdata->vif.bss_conf.dtim_period;
if (ps->dtim_count == 0 && !skb_queue_empty(&ps->bc_buf))
aid0 = 1;
ps->dtim_bc_mc = aid0 == 1;
if (have_bits) {
/* Find largest even number N1 so that bits numbered 1 through
* (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits
* (N2 + 1) x 8 through 2007 are 0. */
n1 = 0;
for (i = 0; i < IEEE80211_MAX_TIM_LEN; i++) {
if (ps->tim[i]) {
n1 = i & 0xfe;
break;
}
}
n2 = n1;
for (i = IEEE80211_MAX_TIM_LEN - 1; i >= n1; i--) {
if (ps->tim[i]) {
n2 = i;
break;
}
}
/* Bitmap control */
*pos++ = n1 | aid0;
/* Part Virt Bitmap */
skb_put(skb, n2 - n1);
memcpy(pos, ps->tim + n1, n2 - n1 + 1);
tim[1] = n2 - n1 + 4;
} else {
*pos++ = aid0; /* Bitmap control */
*pos++ = 0; /* Part Virt Bitmap */
}
}
static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
struct ps_data *ps, struct sk_buff *skb,
bool is_template)
{
struct ieee80211_local *local = sdata->local;
/*
* Not very nice, but we want to allow the driver to call
* ieee80211_beacon_get() as a response to the set_tim()
* callback. That, however, is already invoked under the
* sta_lock to guarantee consistent and race-free update
* of the tim bitmap in mac80211 and the driver.
*/
if (local->tim_in_locked_section) {
__ieee80211_beacon_add_tim(sdata, ps, skb, is_template);
} else {
spin_lock_bh(&local->tim_lock);
__ieee80211_beacon_add_tim(sdata, ps, skb, is_template);
spin_unlock_bh(&local->tim_lock);
}
return 0;
}
static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata,
struct beacon_data *beacon)
{
struct probe_resp *resp;
u8 *beacon_data;
size_t beacon_data_len;
int i;
u8 count = beacon->csa_current_counter;
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP:
beacon_data = beacon->tail;
beacon_data_len = beacon->tail_len;
break;
case NL80211_IFTYPE_ADHOC:
beacon_data = beacon->head;
beacon_data_len = beacon->head_len;
break;
case NL80211_IFTYPE_MESH_POINT:
beacon_data = beacon->head;
beacon_data_len = beacon->head_len;
break;
default:
return;
}
rcu_read_lock();
for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) {
resp = rcu_dereference(sdata->u.ap.probe_resp);
if (beacon->csa_counter_offsets[i]) {
if (WARN_ON_ONCE(beacon->csa_counter_offsets[i] >=
beacon_data_len)) {
rcu_read_unlock();
return;
}
beacon_data[beacon->csa_counter_offsets[i]] = count;
}
if (sdata->vif.type == NL80211_IFTYPE_AP && resp)
resp->data[resp->csa_counter_offsets[i]] = count;
}
rcu_read_unlock();
}
u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct beacon_data *beacon = NULL;
u8 count = 0;
rcu_read_lock();
if (sdata->vif.type == NL80211_IFTYPE_AP)
beacon = rcu_dereference(sdata->u.ap.beacon);
else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
beacon = rcu_dereference(sdata->u.ibss.presp);
else if (ieee80211_vif_is_mesh(&sdata->vif))
beacon = rcu_dereference(sdata->u.mesh.beacon);
if (!beacon)
goto unlock;
beacon->csa_current_counter--;
/* the counter should never reach 0 */
WARN_ON_ONCE(!beacon->csa_current_counter);
count = beacon->csa_current_counter;
unlock:
rcu_read_unlock();
return count;
}
EXPORT_SYMBOL(ieee80211_csa_update_counter);
bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct beacon_data *beacon = NULL;
u8 *beacon_data;
size_t beacon_data_len;
int ret = false;
if (!ieee80211_sdata_running(sdata))
return false;
rcu_read_lock();
if (vif->type == NL80211_IFTYPE_AP) {
struct ieee80211_if_ap *ap = &sdata->u.ap;
beacon = rcu_dereference(ap->beacon);
if (WARN_ON(!beacon || !beacon->tail))
goto out;
beacon_data = beacon->tail;
beacon_data_len = beacon->tail_len;
} else if (vif->type == NL80211_IFTYPE_ADHOC) {
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
beacon = rcu_dereference(ifibss->presp);
if (!beacon)
goto out;
beacon_data = beacon->head;
beacon_data_len = beacon->head_len;
} else if (vif->type == NL80211_IFTYPE_MESH_POINT) {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
beacon = rcu_dereference(ifmsh->beacon);
if (!beacon)
goto out;
beacon_data = beacon->head;
beacon_data_len = beacon->head_len;
} else {
WARN_ON(1);
goto out;
}
if (!beacon->csa_counter_offsets[0])
goto out;
if (WARN_ON_ONCE(beacon->csa_counter_offsets[0] > beacon_data_len))
goto out;
if (beacon_data[beacon->csa_counter_offsets[0]] == 1)
ret = true;
out:
rcu_read_unlock();
return ret;
}
EXPORT_SYMBOL(ieee80211_csa_is_complete);
static struct sk_buff *
__ieee80211_beacon_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_mutable_offsets *offs,
bool is_template)
{
struct ieee80211_local *local = hw_to_local(hw);
struct beacon_data *beacon = NULL;
struct sk_buff *skb = NULL;
struct ieee80211_tx_info *info;
struct ieee80211_sub_if_data *sdata = NULL;
enum ieee80211_band band;
struct ieee80211_tx_rate_control txrc;
struct ieee80211_chanctx_conf *chanctx_conf;
int csa_off_base = 0;
rcu_read_lock();
sdata = vif_to_sdata(vif);
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!ieee80211_sdata_running(sdata) || !chanctx_conf)
goto out;
if (offs)
memset(offs, 0, sizeof(*offs));
if (sdata->vif.type == NL80211_IFTYPE_AP) {
struct ieee80211_if_ap *ap = &sdata->u.ap;
beacon = rcu_dereference(ap->beacon);
if (beacon) {
if (beacon->csa_counter_offsets[0]) {
if (!is_template)
ieee80211_csa_update_counter(vif);
ieee80211_set_csa(sdata, beacon);
}
/*
* headroom, head length,
* tail length and maximum TIM length
*/
skb = dev_alloc_skb(local->tx_headroom +
beacon->head_len +
beacon->tail_len + 256 +
local->hw.extra_beacon_tailroom);
if (!skb)
goto out;
skb_reserve(skb, local->tx_headroom);
memcpy(skb_put(skb, beacon->head_len), beacon->head,
beacon->head_len);
ieee80211_beacon_add_tim(sdata, &ap->ps, skb,
is_template);
if (offs) {
offs->tim_offset = beacon->head_len;
offs->tim_length = skb->len - beacon->head_len;
/* for AP the csa offsets are from tail */
csa_off_base = skb->len;
}
if (beacon->tail)
memcpy(skb_put(skb, beacon->tail_len),
beacon->tail, beacon->tail_len);
} else
goto out;
} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_hdr *hdr;
beacon = rcu_dereference(ifibss->presp);
if (!beacon)
goto out;
if (beacon->csa_counter_offsets[0]) {
if (!is_template)
ieee80211_csa_update_counter(vif);
ieee80211_set_csa(sdata, beacon);
}
skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
local->hw.extra_beacon_tailroom);
if (!skb)
goto out;
skb_reserve(skb, local->tx_headroom);
memcpy(skb_put(skb, beacon->head_len), beacon->head,
beacon->head_len);
hdr = (struct ieee80211_hdr *) skb->data;
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_BEACON);
} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
beacon = rcu_dereference(ifmsh->beacon);
if (!beacon)
goto out;
if (beacon->csa_counter_offsets[0]) {
if (!is_template)
/* TODO: For mesh csa_counter is in TU, so
* decrementing it by one isn't correct, but
* for now we leave it consistent with overall
* mac80211's behavior.
*/
ieee80211_csa_update_counter(vif);
ieee80211_set_csa(sdata, beacon);
}
if (ifmsh->sync_ops)
ifmsh->sync_ops->adjust_tbtt(sdata, beacon);
skb = dev_alloc_skb(local->tx_headroom +
beacon->head_len +
256 + /* TIM IE */
beacon->tail_len +
local->hw.extra_beacon_tailroom);
if (!skb)
goto out;
skb_reserve(skb, local->tx_headroom);
memcpy(skb_put(skb, beacon->head_len), beacon->head,
beacon->head_len);
ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template);
if (offs) {
offs->tim_offset = beacon->head_len;
offs->tim_length = skb->len - beacon->head_len;
}
memcpy(skb_put(skb, beacon->tail_len), beacon->tail,
beacon->tail_len);
} else {
WARN_ON(1);
goto out;
}
/* CSA offsets */
if (offs && beacon) {
int i;
for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) {
u16 csa_off = beacon->csa_counter_offsets[i];
if (!csa_off)
continue;
offs->csa_counter_offs[i] = csa_off_base + csa_off;
}
}
band = chanctx_conf->def.chan->band;
info = IEEE80211_SKB_CB(skb);
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
info->flags |= IEEE80211_TX_CTL_NO_ACK;
info->band = band;
memset(&txrc, 0, sizeof(txrc));
txrc.hw = hw;
txrc.sband = local->hw.wiphy->bands[band];
txrc.bss_conf = &sdata->vif.bss_conf;
txrc.skb = skb;
txrc.reported_rate.idx = -1;
txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
if (txrc.rate_idx_mask == (1 << txrc.sband->n_bitrates) - 1)
txrc.max_rate_idx = -1;
else
txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
txrc.bss = true;
rate_control_get_rate(sdata, NULL, &txrc);
info->control.vif = vif;
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT |
IEEE80211_TX_CTL_ASSIGN_SEQ |
IEEE80211_TX_CTL_FIRST_FRAGMENT;
out:
rcu_read_unlock();
return skb;
}
struct sk_buff *
ieee80211_beacon_get_template(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_mutable_offsets *offs)
{
return __ieee80211_beacon_get(hw, vif, offs, true);
}
EXPORT_SYMBOL(ieee80211_beacon_get_template);
struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u16 *tim_offset, u16 *tim_length)
{
struct ieee80211_mutable_offsets offs = {};
struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false);
if (tim_offset)
*tim_offset = offs.tim_offset;
if (tim_length)
*tim_length = offs.tim_length;
return bcn;
}
EXPORT_SYMBOL(ieee80211_beacon_get_tim);
struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ieee80211_if_ap *ap = NULL;
struct sk_buff *skb = NULL;
struct probe_resp *presp = NULL;
struct ieee80211_hdr *hdr;
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
if (sdata->vif.type != NL80211_IFTYPE_AP)
return NULL;
rcu_read_lock();
ap = &sdata->u.ap;
presp = rcu_dereference(ap->probe_resp);
if (!presp)
goto out;
skb = dev_alloc_skb(presp->len);
if (!skb)
goto out;
memcpy(skb_put(skb, presp->len), presp->data, presp->len);
hdr = (struct ieee80211_hdr *) skb->data;
memset(hdr->addr1, 0, sizeof(hdr->addr1));
out:
rcu_read_unlock();
return skb;
}
EXPORT_SYMBOL(ieee80211_proberesp_get);
struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ieee80211_sub_if_data *sdata;
struct ieee80211_if_managed *ifmgd;
struct ieee80211_pspoll *pspoll;
struct ieee80211_local *local;
struct sk_buff *skb;
if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
return NULL;
sdata = vif_to_sdata(vif);
ifmgd = &sdata->u.mgd;
local = sdata->local;
skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
if (!skb)
return NULL;
skb_reserve(skb, local->hw.extra_tx_headroom);
pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll));
memset(pspoll, 0, sizeof(*pspoll));
pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
IEEE80211_STYPE_PSPOLL);
pspoll->aid = cpu_to_le16(ifmgd->aid);
/* aid in PS-Poll has its two MSBs each set to 1 */
pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
memcpy(pspoll->ta, vif->addr, ETH_ALEN);
return skb;
}
EXPORT_SYMBOL(ieee80211_pspoll_get);
struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ieee80211_hdr_3addr *nullfunc;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_if_managed *ifmgd;
struct ieee80211_local *local;
struct sk_buff *skb;
if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
return NULL;
sdata = vif_to_sdata(vif);
ifmgd = &sdata->u.mgd;
local = sdata->local;
skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*nullfunc));
if (!skb)
return NULL;
skb_reserve(skb, local->hw.extra_tx_headroom);
nullfunc = (struct ieee80211_hdr_3addr *) skb_put(skb,
sizeof(*nullfunc));
memset(nullfunc, 0, sizeof(*nullfunc));
nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
IEEE80211_STYPE_NULLFUNC |
IEEE80211_FCTL_TODS);
memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN);
memcpy(nullfunc->addr2, vif->addr, ETH_ALEN);
memcpy(nullfunc->addr3, ifmgd->bssid, ETH_ALEN);
return skb;
}
EXPORT_SYMBOL(ieee80211_nullfunc_get);
struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
const u8 *src_addr,
const u8 *ssid, size_t ssid_len,
size_t tailroom)
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_hdr_3addr *hdr;
struct sk_buff *skb;
size_t ie_ssid_len;
u8 *pos;
ie_ssid_len = 2 + ssid_len;
skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) +
ie_ssid_len + tailroom);
if (!skb)
return NULL;
skb_reserve(skb, local->hw.extra_tx_headroom);
hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr));
memset(hdr, 0, sizeof(*hdr));
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_REQ);
eth_broadcast_addr(hdr->addr1);
memcpy(hdr->addr2, src_addr, ETH_ALEN);
eth_broadcast_addr(hdr->addr3);
pos = skb_put(skb, ie_ssid_len);
*pos++ = WLAN_EID_SSID;
*pos++ = ssid_len;
if (ssid_len)
memcpy(pos, ssid, ssid_len);
pos += ssid_len;
return skb;
}
EXPORT_SYMBOL(ieee80211_probereq_get);
void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const void *frame, size_t frame_len,
const struct ieee80211_tx_info *frame_txctl,
struct ieee80211_rts *rts)
{
const struct ieee80211_hdr *hdr = frame;
rts->frame_control =
cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
rts->duration = ieee80211_rts_duration(hw, vif, frame_len,
frame_txctl);
memcpy(rts->ra, hdr->addr1, sizeof(rts->ra));
memcpy(rts->ta, hdr->addr2, sizeof(rts->ta));
}
EXPORT_SYMBOL(ieee80211_rts_get);
void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const void *frame, size_t frame_len,
const struct ieee80211_tx_info *frame_txctl,
struct ieee80211_cts *cts)
{
const struct ieee80211_hdr *hdr = frame;
cts->frame_control =
cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
cts->duration = ieee80211_ctstoself_duration(hw, vif,
frame_len, frame_txctl);
memcpy(cts->ra, hdr->addr1, sizeof(cts->ra));
}
EXPORT_SYMBOL(ieee80211_ctstoself_get);
struct sk_buff *
ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ieee80211_local *local = hw_to_local(hw);
struct sk_buff *skb = NULL;
struct ieee80211_tx_data tx;
struct ieee80211_sub_if_data *sdata;
struct ps_data *ps;
struct ieee80211_tx_info *info;
struct ieee80211_chanctx_conf *chanctx_conf;
sdata = vif_to_sdata(vif);
rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf)
goto out;
if (sdata->vif.type == NL80211_IFTYPE_AP) {
struct beacon_data *beacon =
rcu_dereference(sdata->u.ap.beacon);
if (!beacon || !beacon->head)
goto out;
ps = &sdata->u.ap.ps;
} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
ps = &sdata->u.mesh.ps;
} else {
goto out;
}
if (ps->dtim_count != 0 || !ps->dtim_bc_mc)
goto out; /* send buffered bc/mc only after DTIM beacon */
while (1) {
skb = skb_dequeue(&ps->bc_buf);
if (!skb)
goto out;
local->total_ps_buffered--;
if (!skb_queue_empty(&ps->bc_buf) && skb->len >= 2) {
struct ieee80211_hdr *hdr =
(struct ieee80211_hdr *) skb->data;
/* more buffered multicast/broadcast frames ==> set
* MoreData flag in IEEE 802.11 header to inform PS
* STAs */
hdr->frame_control |=
cpu_to_le16(IEEE80211_FCTL_MOREDATA);
}
if (sdata->vif.type == NL80211_IFTYPE_AP)
sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
if (!ieee80211_tx_prepare(sdata, &tx, NULL, skb))
break;
dev_kfree_skb_any(skb);
}
info = IEEE80211_SKB_CB(skb);
tx.flags |= IEEE80211_TX_PS_BUFFERED;
info->band = chanctx_conf->def.chan->band;
if (invoke_tx_handlers(&tx))
skb = NULL;
out:
rcu_read_unlock();
return skb;
}
EXPORT_SYMBOL(ieee80211_get_buffered_bc);
int ieee80211_reserve_tid(struct ieee80211_sta *pubsta, u8 tid)
{
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_local *local = sdata->local;
int ret;
u32 queues;
lockdep_assert_held(&local->sta_mtx);
/* only some cases are supported right now */
switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_AP_VLAN:
break;
default:
WARN_ON(1);
return -EINVAL;
}
if (WARN_ON(tid >= IEEE80211_NUM_UPS))
return -EINVAL;
if (sta->reserved_tid == tid) {
ret = 0;
goto out;
}
if (sta->reserved_tid != IEEE80211_TID_UNRESERVED) {
sdata_err(sdata, "TID reservation already active\n");
ret = -EALREADY;
goto out;
}
ieee80211_stop_vif_queues(sdata->local, sdata,
IEEE80211_QUEUE_STOP_REASON_RESERVE_TID);
synchronize_net();
/* Tear down BA sessions so we stop aggregating on this TID */
if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) {
set_sta_flag(sta, WLAN_STA_BLOCK_BA);
__ieee80211_stop_tx_ba_session(sta, tid,
AGG_STOP_LOCAL_REQUEST);
}
queues = BIT(sdata->vif.hw_queue[ieee802_1d_to_ac[tid]]);
__ieee80211_flush_queues(local, sdata, queues, false);
sta->reserved_tid = tid;
ieee80211_wake_vif_queues(local, sdata,
IEEE80211_QUEUE_STOP_REASON_RESERVE_TID);
if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)
clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
ret = 0;
out:
return ret;
}
EXPORT_SYMBOL(ieee80211_reserve_tid);
void ieee80211_unreserve_tid(struct ieee80211_sta *pubsta, u8 tid)
{
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
struct ieee80211_sub_if_data *sdata = sta->sdata;
lockdep_assert_held(&sdata->local->sta_mtx);
/* only some cases are supported right now */
switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_AP_VLAN:
break;
default:
WARN_ON(1);
return;
}
if (tid != sta->reserved_tid) {
sdata_err(sdata, "TID to unreserve (%d) isn't reserved\n", tid);
return;
}
sta->reserved_tid = IEEE80211_TID_UNRESERVED;
}
EXPORT_SYMBOL(ieee80211_unreserve_tid);
void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, int tid,
enum ieee80211_band band)
{
int ac = ieee802_1d_to_ac[tid & 7];
skb_set_mac_header(skb, 0);
skb_set_network_header(skb, 0);
skb_set_transport_header(skb, 0);
skb_set_queue_mapping(skb, ac);
skb->priority = tid;
skb->dev = sdata->dev;
/*
* The other path calling ieee80211_xmit is from the tasklet,
* and while we can handle concurrent transmissions locking
* requirements are that we do not come into tx with bhs on.
*/
local_bh_disable();
IEEE80211_SKB_CB(skb)->band = band;
ieee80211_xmit(sdata, NULL, skb);
local_bh_enable();
}
--
To unsubscribe from this list: send the line "unsubscribe backports" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic