net: clear heap allocations for privileged ethtool actions
[firefly-linux-kernel-4.4.55.git] / net / mac80211 / rx.c
index 865fbc09be1adbca316e06c44beb485b4a46cef9..38499c4e7106c514b22efbf679c4bd957f6a61ef 100644 (file)
@@ -1220,7 +1220,8 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
                     (rx->key || rx->sdata->drop_unencrypted)))
                return -EACCES;
        if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) {
-               if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
+               if (unlikely(!ieee80211_has_protected(fc) &&
+                            ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
                             rx->key))
                        return -EACCES;
                /* BIP does not use Protected field, so need to check MMIE */
@@ -1514,7 +1515,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                        mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata);
                } else {
                        spin_lock_bh(&mppath->state_lock);
-                       mppath->exp_time = jiffies;
                        if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0)
                                memcpy(mppath->mpp, hdr->addr4, ETH_ALEN);
                        spin_unlock_bh(&mppath->state_lock);
@@ -1549,7 +1549,9 @@ 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;
-                       ieee80211_select_queue(local, fwd_skb);
+                       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))
                                IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
                                                                fwded_mcast);
@@ -1589,6 +1591,7 @@ static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
 {
        struct net_device *dev = rx->dev;
+       struct ieee80211_local *local = rx->local;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
        __le16 fc = hdr->frame_control;
        int err;
@@ -1611,6 +1614,13 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
        dev->stats.rx_packets++;
        dev->stats.rx_bytes += rx->skb->len;
 
+       if (ieee80211_is_data(hdr->frame_control) &&
+           !is_multicast_ether_addr(hdr->addr1) &&
+           local->hw.conf.dynamic_ps_timeout > 0 && local->ps_sdata) {
+               mod_timer(&local->dynamic_ps_timer, jiffies +
+                         msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
+       }
+
        ieee80211_deliver_skb(rx);
 
        return RX_QUEUED;
@@ -1808,7 +1818,16 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                        return RX_CONTINUE;
                }
                break;
+       case WLAN_CATEGORY_MESH_PLINK:
+       case WLAN_CATEGORY_MESH_PATH_SEL:
+               if (ieee80211_vif_is_mesh(&sdata->vif))
+                       return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
+               break;
        default:
+               /* do not process rejected action frames */
+               if (mgmt->u.action.category & 0x80)
+                       return RX_DROP_MONITOR;
+
                return RX_CONTINUE;
        }
 
@@ -2453,6 +2472,8 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
        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 < 0 ||
                    status->band >= IEEE80211_NUM_BANDS))
                goto drop;