Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
[linux-2.6.git] / net / mac80211 / rx.c
index f36d70f..4eafbfd 100644 (file)
@@ -16,6 +16,7 @@
 #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>
 
@@ -77,7 +78,7 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
        /* always present fields */
        len = sizeof(struct ieee80211_radiotap_header) + 9;
 
-       if (status->flag & RX_FLAG_TSFT)
+       if (status->flag & RX_FLAG_MACTIME_MPDU)
                len += 8;
        if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
                len += 1;
@@ -85,6 +86,9 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
        if (len & 1) /* padding for RX_FLAGS if necessary */
                len++;
 
+       if (status->flag & RX_FLAG_HT) /* HT info */
+               len += 3;
+
        return len;
 }
 
@@ -120,7 +124,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        /* the order of the following fields is important */
 
        /* IEEE80211_RADIOTAP_TSFT */
-       if (status->flag & RX_FLAG_TSFT) {
+       if (status->flag & RX_FLAG_MACTIME_MPDU) {
                put_unaligned_le64(status->mactime, pos);
                rthdr->it_present |=
                        cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
@@ -139,11 +143,9 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        /* IEEE80211_RADIOTAP_RATE */
        if (status->flag & RX_FLAG_HT) {
                /*
-                * TODO: add following information into radiotap header once
-                * suitable fields are defined for it:
-                * - MCS index (status->rate_idx)
-                * - HT40 (status->flag & RX_FLAG_40MHZ)
-                * - short-GI (status->flag & RX_FLAG_SHORT_GI)
+                * 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 {
@@ -193,6 +195,20 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
                rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP;
        put_unaligned_le16(rx_flags, pos);
        pos += 2;
+
+       if (status->flag & RX_FLAG_HT) {
+               rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
+               *pos++ = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
+                        IEEE80211_RADIOTAP_MCS_HAVE_GI |
+                        IEEE80211_RADIOTAP_MCS_HAVE_BW;
+               *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;
+               pos++;
+               *pos++ = status->rate_idx;
+       }
 }
 
 /*
@@ -316,15 +332,18 @@ 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;
+       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_CONTROL_A_MSDU_PRESENT)
+               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"):
@@ -337,10 +356,15 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
                 *
                 * We also use that counter for non-QoS STAs.
                 */
-               tid = NUM_RX_DATA_QUEUES - 1;
+               seqno_idx = NUM_RX_DATA_QUEUES;
+               security_idx = 0;
+               if (ieee80211_is_mgmt(hdr->frame_control))
+                       security_idx = NUM_RX_DATA_QUEUES;
+               tid = 0;
        }
 
-       rx->queue = tid;
+       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;
@@ -367,7 +391,7 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
  * 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 inbetween the 802.11 header and
+ * 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.
  */
@@ -389,19 +413,15 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
        struct sk_buff *skb = rx->skb;
 
-       if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN)))
+       if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
+                  !local->sched_scanning))
                return RX_CONTINUE;
 
-       if (test_bit(SCAN_HW_SCANNING, &local->scanning))
+       if (test_bit(SCAN_HW_SCANNING, &local->scanning) ||
+           test_bit(SCAN_SW_SCANNING, &local->scanning) ||
+           local->sched_scanning)
                return ieee80211_scan_rx(rx->sdata, skb);
 
-       if (test_bit(SCAN_SW_SCANNING, &local->scanning)) {
-               /* drop all the other packets during a software scan anyway */
-               if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED)
-                       dev_kfree_skb(skb);
-               return RX_QUEUED;
-       }
-
        /* scanning finished during invoking of handlers */
        I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
        return RX_DROP_UNUSABLE;
@@ -457,7 +477,6 @@ static ieee80211_rx_result
 ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-       unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
        char *dev_addr = rx->sdata->vif.addr;
 
        if (ieee80211_is_data(hdr->frame_control)) {
@@ -479,36 +498,32 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
         * establisment frame, beacon or probe, drop the frame.
         */
 
-       if (!rx->sta || sta_plink_state(rx->sta) != PLINK_ESTAB) {
+       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;
                        mgmt = (struct ieee80211_mgmt *)hdr;
-                       if (mgmt->u.action.category != WLAN_CATEGORY_MESH_PLINK)
+                       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_beacon(hdr->frame_control) ||
+                   ieee80211_is_auth(hdr->frame_control))
                        return RX_CONTINUE;
 
                return RX_DROP_MONITOR;
 
        }
 
-#define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l))
-
-       if (ieee80211_is_data(hdr->frame_control) &&
-           is_multicast_ether_addr(hdr->addr1) &&
-           mesh_rmc_check(hdr->addr3, msh_h_get(hdr, hdrlen), rx->sdata))
-               return RX_DROP_MONITOR;
-#undef msh_h_get
-
        return RX_CONTINUE;
 }
 
@@ -604,7 +619,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
                                skipped++;
                                continue;
                        }
-                       if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
+                       if (skipped &&
+                           !time_after(jiffies, tid_agg_rx->reorder_time[j] +
                                        HT_RX_REORDER_BUF_TIMEOUT))
                                goto set_release_timer;
 
@@ -641,7 +657,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
  set_release_timer:
 
                mod_timer(&tid_agg_rx->reorder_timer,
-                         tid_agg_rx->reorder_time[j] +
+                         tid_agg_rx->reorder_time[j] + 1 +
                          HT_RX_REORDER_BUF_TIMEOUT);
        } else {
                del_timer(&tid_agg_rx->reorder_timer);
@@ -698,6 +714,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
        /*
         * 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) {
@@ -727,10 +745,11 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx)
        struct ieee80211_local *local = rx->local;
        struct ieee80211_hw *hw = &local->hw;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct sta_info *sta = rx->sta;
        struct tid_ampdu_rx *tid_agg_rx;
        u16 sc;
-       int tid;
+       u8 tid, ack_policy;
 
        if (!ieee80211_is_data_qos(hdr->frame_control))
                goto dont_reorder;
@@ -743,6 +762,8 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx)
        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]);
@@ -753,6 +774,15 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx)
        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;
+
+       /* not actually part of this BA session */
+       if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
+               goto dont_reorder;
+
        /* new, potentially un-ordered, ampdu frame - process it */
 
        /* reset session timer */
@@ -792,15 +822,15 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
        /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
        if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
                if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
-                            rx->sta->last_seq_ctrl[rx->queue] ==
+                            rx->sta->last_seq_ctrl[rx->seqno_idx] ==
                             hdr->seq_ctrl)) {
                        if (status->rx_flags & IEEE80211_RX_RA_MATCH) {
                                rx->local->dot11FrameDuplicateCount++;
                                rx->sta->num_duplicates++;
                        }
-                       return RX_DROP_MONITOR;
+                       return RX_DROP_UNUSABLE;
                } else
-                       rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl;
+                       rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl;
        }
 
        if (unlikely(rx->skb->len < 16)) {
@@ -824,16 +854,26 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
                      ieee80211_is_pspoll(hdr->frame_control)) &&
                     rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
                     rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
-                    (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) {
-               if ((!ieee80211_has_fromds(hdr->frame_control) &&
-                    !ieee80211_has_tods(hdr->frame_control) &&
-                    ieee80211_is_data(hdr->frame_control)) ||
-                   !(status->rx_flags & IEEE80211_RX_RA_MATCH)) {
-                       /* Drop IBSS frames and frames for other hosts
-                        * silently. */
-                       return RX_DROP_MONITOR;
+                    (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) {
+               if (rx->sta && rx->sta->dummy &&
+                   ieee80211_is_data_present(hdr->frame_control)) {
+                       u16 ethertype;
+                       u8 *payload;
+
+                       payload = rx->skb->data +
+                               ieee80211_hdrlen(hdr->frame_control);
+                       ethertype = (payload[6] << 8) | payload[7];
+                       if (cpu_to_be16(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;
        }
 
@@ -1003,6 +1043,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
        }
 
        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 {
@@ -1087,8 +1130,9 @@ static void ap_sta_ps_start(struct sta_info *sta)
        struct ieee80211_local *local = sdata->local;
 
        atomic_inc(&sdata->bss->num_sta_ps);
-       set_sta_flags(sta, WLAN_STA_PS_STA);
-       drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
+       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);
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
        printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n",
               sdata->name, sta->sta.addr, sta->sta.aid);
@@ -1106,7 +1150,7 @@ static void ap_sta_ps_end(struct sta_info *sta)
               sdata->name, sta->sta.addr, sta->sta.aid);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 
-       if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) {
+       if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
                printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n",
                       sdata->name, sta->sta.addr, sta->sta.aid);
@@ -1117,6 +1161,102 @@ static void ap_sta_ps_end(struct sta_info *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)
+               ap_sta_ps_start(sta_inf);
+       else
+               ap_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 || !(status->rx_flags & IEEE80211_RX_RA_MATCH))
+               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)
 {
@@ -1136,14 +1276,23 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
        if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
                u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
                                                NL80211_IFTYPE_ADHOC);
-               if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0)
+               if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0) {
                        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;
+                       }
+               }
        } 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;
+               }
        }
 
        if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
@@ -1161,11 +1310,12 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
         * Change STA power saving mode only at the end of a frame
         * exchange sequence.
         */
-       if (!ieee80211_has_morefrags(hdr->frame_control) &&
+       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)) {
-               if (test_sta_flags(sta, WLAN_STA_PS_STA)) {
+               if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
                        /*
                         * Ignore doze->wake transitions that are
                         * indicated by non-data frames, the standard
@@ -1193,15 +1343,20 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 
                /*
                 * If we receive a 4-addr nullfunc frame from a STA
-                * that was not moved to a 4-addr STA vlan yet, drop
-                * the frame to the monitor interface, to make sure
-                * that hostapd sees it
+                * 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)))
+                     !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.
@@ -1334,11 +1489,10 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
        if (frag == 0) {
                /* This is the first fragment of a new frame. */
                entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
-                                                rx->queue, &(rx->skb));
+                                                rx->seqno_idx, &(rx->skb));
                if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP &&
                    ieee80211_has_protected(fc)) {
-                       int queue = ieee80211_is_mgmt(fc) ?
-                               NUM_RX_DATA_QUEUES : rx->queue;
+                       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;
@@ -1352,7 +1506,8 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
        /* 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->queue, hdr);
+       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;
@@ -1372,8 +1527,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
                        if (pn[i])
                                break;
                }
-               queue = ieee80211_is_mgmt(fc) ?
-                       NUM_RX_DATA_QUEUES : rx->queue;
+               queue = rx->security_idx;
                rpn = rx->key->u.ccmp.rx_pn[queue];
                if (memcmp(pn, rpn, CCMP_PN_LEN))
                        return RX_DROP_UNUSABLE;
@@ -1419,33 +1573,6 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 }
 
 static ieee80211_rx_result debug_noinline
-ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
-{
-       struct ieee80211_sub_if_data *sdata = rx->sdata;
-       __le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control;
-       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
-
-       if (likely(!rx->sta || !ieee80211_is_pspoll(fc) ||
-                  !(status->rx_flags & IEEE80211_RX_RA_MATCH)))
-               return RX_CONTINUE;
-
-       if ((sdata->vif.type != NL80211_IFTYPE_AP) &&
-           (sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
-               return RX_DROP_UNUSABLE;
-
-       if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER))
-               ieee80211_sta_ps_deliver_poll_response(rx->sta);
-       else
-               set_sta_flags(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;
-}
-
-static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx)
 {
        u8 *data = rx->skb->data;
@@ -1468,7 +1595,7 @@ static int
 ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
 {
        if (unlikely(!rx->sta ||
-           !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED)))
+           !test_sta_flag(rx->sta, WLAN_STA_AUTHORIZED)))
                return -EACCES;
 
        return 0;
@@ -1511,7 +1638,7 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
        if (status->flag & RX_FLAG_DECRYPTED)
                return 0;
 
-       if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) {
+       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)) {
@@ -1552,7 +1679,7 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
 }
 
 static int
-__ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
+__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;
@@ -1560,6 +1687,7 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
        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;
@@ -1578,11 +1706,13 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
                return -1;
 
        ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
-       if (ret < 0 || !check_port_control)
+       if (ret < 0)
                return ret;
 
        ehdr = (struct ethhdr *) rx->skb->data;
-       if (ehdr->h_proto != rx->sdata->control_port_protocol)
+       if (ehdr->h_proto == rx->sdata->control_port_protocol)
+               *port_control = true;
+       else if (check_port_control)
                return -1;
 
        return 0;
@@ -1740,7 +1870,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
 
        ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
                                 rx->sdata->vif.type,
-                                rx->local->hw.extra_tx_headroom);
+                                rx->local->hw.extra_tx_headroom, true);
 
        while (!skb_queue_empty(&frame_list)) {
                rx->skb = __skb_dequeue(&frame_list);
@@ -1774,6 +1904,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
        mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
 
+       /* frame is in RMC, don't forward */
+       if (ieee80211_is_data(hdr->frame_control) &&
+           is_multicast_ether_addr(hdr->addr1) &&
+           mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))
+               return RX_DROP_MONITOR;
+
        if (!ieee80211_is_data(hdr->frame_control))
                return RX_CONTINUE;
 
@@ -1781,6 +1917,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                /* illegal frame */
                return RX_DROP_MONITOR;
 
+       if (ieee80211_queue_stopped(&local->hw, skb_get_queue_mapping(skb))) {
+               IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
+                                               dropped_frames_congestion);
+               return RX_DROP_MONITOR;
+       }
+
        if (mesh_hdr->flags & MESH_FLAGS_AE) {
                struct mesh_path *mppath;
                char *proxied_addr;
@@ -1812,6 +1954,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
            compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0)
                return RX_CONTINUE;
 
+       skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb));
        mesh_hdr->ttl--;
 
        if (status->rx_flags & IEEE80211_RX_RA_MATCH) {
@@ -1836,13 +1979,11 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                        memset(info, 0, sizeof(*info));
                        info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
                        info->control.vif = &rx->sdata->vif;
-                       skb_set_queue_mapping(skb,
-                               ieee80211_select_queue(rx->sdata, fwd_skb));
-                       ieee80211_set_qos_hdr(local, skb);
-                       if (is_multicast_ether_addr(fwd_hdr->addr1))
+                       info->control.jiffies = jiffies;
+                       if (is_multicast_ether_addr(fwd_hdr->addr1)) {
                                IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
                                                                fwded_mcast);
-                       else {
+                       } else {
                                int err;
                                /*
                                 * Save TA to addr1 to send TA a path error if a
@@ -1883,6 +2024,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
        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)))
@@ -1892,27 +2034,43 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
                return RX_DROP_MONITOR;
 
        /*
-        * Allow the cooked monitor interface of an AP to see 4-addr frames so
-        * that a 4-addr station can be detected and moved into a separate VLAN
+        * 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)
+           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);
+       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;
 
+       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;
 
        dev->stats.rx_packets++;
        dev->stats.rx_bytes += rx->skb->len;
 
        if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 &&
-           !is_multicast_ether_addr(((struct ethhdr *)rx->skb->data)->h_dest)) {
+           !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));
        }
@@ -2041,6 +2199,18 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
        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)) {
+               struct ieee80211_rx_status *status;
+
+               status = IEEE80211_SKB_RXCB(rx->skb);
+               cfg80211_report_obss_beacon(rx->local->hw.wiphy,
+                                           rx->skb->data, rx->skb->len,
+                                           status->freq, GFP_ATOMIC);
+               rx->flags |= IEEE80211_RX_BEACON_REPORTED;
+       }
+
        if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
                return RX_DROP_MONITOR;
 
@@ -2074,13 +2244,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
 
        switch (mgmt->u.action.category) {
        case WLAN_CATEGORY_BACK:
-               /*
-                * The aggregation code is not prepared to handle
-                * anything but STA/AP due to the BSSID handling;
-                * IBSS could work in the code but isn't supported
-                * by drivers or the standard.
-                */
                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)
                        break;
@@ -2155,12 +2320,29 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                        goto handled;
                }
                break;
-       case WLAN_CATEGORY_MESH_PLINK:
+       case WLAN_CATEGORY_SELF_PROTECTED:
+               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.security != IEEE80211_MESH_SEC_NONE)
+                               /* 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 (!ieee80211_vif_is_mesh(&sdata->vif))
                        break;
-               goto queue;
-       case WLAN_CATEGORY_MESH_PATH_SEL:
-               if (!mesh_path_sel_is_hwmp(sdata))
+               if (mesh_action_is_path_sel(mgmt) &&
+                 (!mesh_path_sel_is_hwmp(sdata)))
                        break;
                goto queue;
        }
@@ -2318,47 +2500,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
        return RX_QUEUED;
 }
 
-static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr,
-                                           struct ieee80211_rx_data *rx)
-{
-       int keyidx;
-       unsigned int hdrlen;
-
-       hdrlen = ieee80211_hdrlen(hdr->frame_control);
-       if (rx->skb->len >= hdrlen + 4)
-               keyidx = rx->skb->data[hdrlen + 3] >> 6;
-       else
-               keyidx = -1;
-
-       if (!rx->sta) {
-               /*
-                * Some hardware seem to generate incorrect Michael MIC
-                * reports; ignore them to avoid triggering countermeasures.
-                */
-               return;
-       }
-
-       if (!ieee80211_has_protected(hdr->frame_control))
-               return;
-
-       if (rx->sdata->vif.type == NL80211_IFTYPE_AP && keyidx) {
-               /*
-                * APs with pairwise keys should never receive Michael MIC
-                * errors for non-zero keyidx because these are reserved for
-                * group keys and only the AP is sending real multicast
-                * frames in the BSS.
-                */
-               return;
-       }
-
-       if (!ieee80211_is_data(hdr->frame_control) &&
-           !ieee80211_is_auth(hdr->frame_control))
-               return;
-
-       mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL,
-                                       GFP_ATOMIC);
-}
-
 /* TODO: use IEEE80211_RX_FRAGMENTED */
 static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
                                        struct ieee80211_rate *rate)
@@ -2384,6 +2525,10 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
                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;
+
        if (skb_headroom(skb) < sizeof(*rthdr) &&
            pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC))
                goto out_free_skb;
@@ -2507,21 +2652,20 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx)
                 * same TID from the same station
                 */
                rx->skb = skb;
-               rx->flags = 0;
 
                CALL_RXH(ieee80211_rx_h_decrypt)
                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_defragment)
-               CALL_RXH(ieee80211_rx_h_ps_poll)
                CALL_RXH(ieee80211_rx_h_michael_mic_verify)
                /* must be after MMIC verify so header is counted in MPDU mic */
-               CALL_RXH(ieee80211_rx_h_remove_qos_control)
-               CALL_RXH(ieee80211_rx_h_amsdu)
 #ifdef CONFIG_MAC80211_MESH
                if (ieee80211_vif_is_mesh(&rx->sdata->vif))
                        CALL_RXH(ieee80211_rx_h_mesh_fwding);
 #endif
+               CALL_RXH(ieee80211_rx_h_remove_qos_control)
+               CALL_RXH(ieee80211_rx_h_amsdu)
                CALL_RXH(ieee80211_rx_h_data)
                CALL_RXH(ieee80211_rx_h_ctrl);
                CALL_RXH(ieee80211_rx_h_mgmt_check)
@@ -2577,7 +2721,10 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
                .sta = sta,
                .sdata = sta->sdata,
                .local = sta->local,
-               .queue = tid,
+               /* This is OK -- must be QoS data frame */
+               .security_idx = tid,
+               .seqno_idx = tid,
+               .flags = 0,
        };
        struct tid_ampdu_rx *tid_agg_rx;
 
@@ -2609,7 +2756,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
                        return 0;
                if (!multicast &&
                    compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) {
-                       if (!(sdata->dev->flags & IFF_PROMISC))
+                       if (!(sdata->dev->flags & IFF_PROMISC) ||
+                           sdata->u.mgd.use_4addr)
                                return 0;
                        status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
                }
@@ -2658,7 +2806,10 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
                                return 0;
                } else if (!ieee80211_bssid_match(bssid,
                                        sdata->vif.addr)) {
-                       if (!(status->rx_flags & IEEE80211_RX_IN_SCAN))
+                       if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
+                           !ieee80211_is_beacon(hdr->frame_control) &&
+                           !(ieee80211_is_action(hdr->frame_control) &&
+                             sdata->vif.p2p))
                                return 0;
                        status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
                }
@@ -2700,12 +2851,6 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
        if (!prepares)
                return false;
 
-       if (status->flag & RX_FLAG_MMIC_ERROR) {
-               if (status->rx_flags & IEEE80211_RX_RA_MATCH)
-                       ieee80211_rx_michael_mic_report(hdr, rx);
-               return false;
-       }
-
        if (!consume) {
                skb = skb_copy(skb, GFP_ATOMIC);
                if (!skb) {
@@ -2749,7 +2894,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                local->dot11ReceivedFragmentCount++;
 
        if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
-                    test_bit(SCAN_OFF_CHANNEL, &local->scanning)))
+                    test_bit(SCAN_SW_SCANNING, &local->scanning)))
                status->rx_flags |= IEEE80211_RX_IN_SCAN;
 
        if (ieee80211_is_mgmt(fc))
@@ -2769,7 +2914,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        if (ieee80211_is_data(fc)) {
                prev_sta = NULL;
 
-               for_each_sta_info(local, hdr->addr2, sta, tmp) {
+               for_each_sta_info_rx(local, hdr->addr2, sta, tmp) {
                        if (!prev_sta) {
                                prev_sta = sta;
                                continue;
@@ -2813,7 +2958,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                        continue;
                }
 
-               rx.sta = sta_info_get_bss(prev, hdr->addr2);
+               rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);
                rx.sdata = prev;
                ieee80211_prepare_and_rx_handle(&rx, skb, false);
 
@@ -2821,7 +2966,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        }
 
        if (prev) {
-               rx.sta = sta_info_get_bss(prev, hdr->addr2);
+               rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);
                rx.sdata = prev;
 
                if (ieee80211_prepare_and_rx_handle(&rx, skb, true))