If userspace requested control port frames to go over 80211, then do so. The control packets are intercepted just prior to delivery of the packet to the underlying network device. Pre-authentication type frames (protocol: 0x88c7) are also forwarded over nl80211. Signed-off-by: Denis Kenzior <denkenz@xxxxxxxxx> --- net/mac80211/cfg.c | 2 ++ net/mac80211/ieee80211_i.h | 1 + net/mac80211/mlme.c | 2 ++ net/mac80211/rx.c | 31 ++++++++++++++++++++++++++++--- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 46028e12e216..f53bfb27295f 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -925,6 +925,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, */ sdata->control_port_protocol = params->crypto.control_port_ethertype; sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt; + sdata->control_port_over_nl80211 = false; sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local, ¶ms->crypto, sdata->vif.type); @@ -934,6 +935,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, params->crypto.control_port_ethertype; vlan->control_port_no_encrypt = params->crypto.control_port_no_encrypt; + vlan->control_port_over_nl80211 = false; vlan->encrypt_headroom = ieee80211_cs_headroom(sdata->local, ¶ms->crypto, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 26900025de2f..6f91aea6a4cb 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -899,6 +899,7 @@ struct ieee80211_sub_if_data { u16 sequence_number; __be16 control_port_protocol; bool control_port_no_encrypt; + bool control_port_over_nl80211; int encrypt_headroom; atomic_t num_tx_queued; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 39b660b9a908..fc71a906939b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -4830,6 +4830,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, sdata->control_port_protocol = req->crypto.control_port_ethertype; sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; + sdata->control_port_over_nl80211 = + req->crypto.control_port_over_nl80211; sdata->encrypt_headroom = ieee80211_cs_headroom(local, &req->crypto, sdata->vif.type); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b3cff69bfd66..28b74ae1ee48 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2326,16 +2326,41 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) } #endif - if (skb) { + if (!skb) + goto try_xmit; + + skb->protocol = eth_type_trans(skb, dev); + memset(skb->cb, 0, sizeof(skb->cb)); + + if (unlikely((skb->protocol == sdata->control_port_protocol || + skb->protocol == cpu_to_be16(0x88c7)) && + sdata->control_port_over_nl80211)) { + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + bool noencrypt; + + ehdr = eth_hdr(skb); + + if (status->flag & RX_FLAG_DECRYPTED) + noencrypt = false; + else + noencrypt = true; + + if (!cfg80211_rx_control_port(dev, skb->data, skb->len, + ehdr->h_source, + be16_to_cpu(skb->protocol), + noencrypt)) { + dev_kfree_skb(skb); + skb = NULL; + } + } else { /* 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); } +try_xmit: if (xmit_skb) { /* * Send to wireless media and increase priority by 256 to -- 2.13.5