|
@@ -2245,6 +2245,32 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,
|
|
|
+ struct ieee80211_rx_data *rx)
|
|
|
+{
|
|
|
+ struct ieee80211_sub_if_data *sdata = rx->sdata;
|
|
|
+ struct net_device *dev = sdata->dev;
|
|
|
+
|
|
|
+ if (unlikely((skb->protocol == sdata->control_port_protocol ||
|
|
|
+ skb->protocol == cpu_to_be16(ETH_P_PREAUTH)) &&
|
|
|
+ sdata->control_port_over_nl80211)) {
|
|
|
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
|
|
+ bool noencrypt = status->flag & RX_FLAG_DECRYPTED;
|
|
|
+ struct ethhdr *ehdr = eth_hdr(skb);
|
|
|
+
|
|
|
+ cfg80211_rx_control_port(dev, skb->data, skb->len,
|
|
|
+ ehdr->h_source,
|
|
|
+ be16_to_cpu(skb->protocol), noencrypt);
|
|
|
+ dev_kfree_skb(skb);
|
|
|
+ } else {
|
|
|
+ /* deliver to local stack */
|
|
|
+ if (rx->napi)
|
|
|
+ napi_gro_receive(rx->napi, skb);
|
|
|
+ else
|
|
|
+ netif_receive_skb(skb);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* requires that rx->skb is a frame with ethernet header
|
|
|
*/
|
|
@@ -2329,13 +2355,10 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
|
|
|
#endif
|
|
|
|
|
|
if (skb) {
|
|
|
- /* deliver to local stack */
|
|
|
skb->protocol = eth_type_trans(skb, dev);
|
|
|
memset(skb->cb, 0, sizeof(skb->cb));
|
|
|
- if (rx->napi)
|
|
|
- napi_gro_receive(rx->napi, skb);
|
|
|
- else
|
|
|
- netif_receive_skb(skb);
|
|
|
+
|
|
|
+ ieee80211_deliver_skb_to_local_stack(skb, rx);
|
|
|
}
|
|
|
|
|
|
if (xmit_skb) {
|