diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/Kconfig | 2 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 4 | ||||
-rw-r--r-- | net/mac80211/rx.c | 11 | ||||
-rw-r--r-- | net/mac80211/tx.c | 28 | ||||
-rw-r--r-- | net/mac80211/work.c | 5 |
5 files changed, 43 insertions, 7 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 4d6f8653ec88..8e8ea9cb7093 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -92,7 +92,7 @@ config MAC80211_MESH config MAC80211_LEDS bool "Enable LED triggers" depends on MAC80211 - select NEW_LEDS + depends on LEDS_CLASS select LEDS_TRIGGERS ---help--- This option enables a few LED triggers for different diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 239c4836a946..077a93dd1671 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -780,6 +780,9 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, mutex_lock(&sdata->u.ibss.mtx); + if (!sdata->u.ibss.ssid_len) + goto mgmt_out; /* not ready to merge yet */ + switch (fc & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_PROBE_REQ: ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len); @@ -797,6 +800,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, break; } + mgmt_out: mutex_unlock(&sdata->u.ibss.mtx); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 902b03ee8f60..b01e467b76c6 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1788,9 +1788,11 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) fwd_skb = skb_copy(skb, GFP_ATOMIC); - if (!fwd_skb && net_ratelimit()) + if (!fwd_skb && net_ratelimit()) { printk(KERN_DEBUG "%s: failed to clone mesh frame\n", sdata->name); + goto out; + } fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); @@ -1828,6 +1830,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) } } + out: if (is_multicast_ether_addr(hdr->addr1) || sdata->dev->flags & IFF_PROMISC) return RX_CONTINUE; @@ -2247,6 +2250,10 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) break; 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; @@ -2741,6 +2748,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) return; + goto out; } } @@ -2780,6 +2788,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, return; } + out: dev_kfree_skb(skb); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 96c594309506..7a637b80a62e 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1587,7 +1587,12 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, list) { if (!ieee80211_sdata_running(tmp_sdata)) continue; - if (tmp_sdata->vif.type != NL80211_IFTYPE_AP) + 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 (compare_ether_addr(tmp_sdata->vif.addr, hdr->addr2) == 0) { @@ -1732,15 +1737,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, int nh_pos, h_pos; struct sta_info *sta = NULL; u32 sta_flags = 0; + struct sk_buff *tmp_skb; if (unlikely(skb->len < ETH_HLEN)) { ret = NETDEV_TX_OK; goto fail; } - nh_pos = skb_network_header(skb) - skb->data; - h_pos = skb_transport_header(skb) - skb->data; - /* convert Ethernet header to proper 802.11 header (based on * operation mode) */ ethertype = (skb->data[12] << 8) | skb->data[13]; @@ -1913,6 +1916,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, goto fail; } + /* + * If the skb is shared we need to obtain our own copy. + */ + if (skb_shared(skb)) { + tmp_skb = skb; + skb = skb_copy(skb, GFP_ATOMIC); + kfree_skb(tmp_skb); + + if (!skb) { + ret = NETDEV_TX_OK; + goto fail; + } + } + hdr.frame_control = fc; hdr.duration_id = 0; hdr.seq_ctrl = 0; @@ -1931,6 +1948,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, 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; diff --git a/net/mac80211/work.c b/net/mac80211/work.c index ae344d1ba056..146097cb43a7 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -1051,11 +1051,13 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; struct ieee80211_work *wk; + bool cleanup = false; mutex_lock(&local->mtx); list_for_each_entry(wk, &local->work_list, list) { if (wk->sdata != sdata) continue; + cleanup = true; wk->type = IEEE80211_WORK_ABORT; wk->started = true; wk->timeout = jiffies; @@ -1063,7 +1065,8 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) mutex_unlock(&local->mtx); /* run cleanups etc. */ - ieee80211_work_work(&local->work_work); + if (cleanup) + ieee80211_work_work(&local->work_work); mutex_lock(&local->mtx); list_for_each_entry(wk, &local->work_list, list) { |