wifi: mac80211: Allow EAPOL frames from link addresses
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>
Thu, 30 Jun 2022 12:37:37 +0000 (15:37 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 15 Jul 2022 09:43:20 +0000 (11:43 +0200)
Allow transmitting EAPOL frames not only from the interface
address (which is the MLD address) but also any link addresses,
in order to support non-MLO stations on AP interfaces.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/rx.c

index c70156e49d0db4b282603c4359380758e2a3a21c..1c798c11648e7e636fed960a1f2d4f4cba50631d 100644 (file)
@@ -2532,6 +2532,35 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control)
        return 0;
 }
 
+static bool ieee80211_is_our_addr(struct ieee80211_sub_if_data *sdata,
+                                 const u8 *addr, int *out_link_id)
+{
+       unsigned int link_id;
+
+       /* non-MLO, or MLD address replaced by hardware */
+       if (ether_addr_equal(sdata->vif.addr, addr))
+               return true;
+
+       if (!sdata->vif.valid_links)
+               return false;
+
+       for (link_id = 0; link_id < ARRAY_SIZE(sdata->vif.link_conf); link_id++) {
+               struct ieee80211_bss_conf *conf;
+
+               conf = rcu_dereference(sdata->vif.link_conf[link_id]);
+
+               if (!conf)
+                       continue;
+               if (ether_addr_equal(conf->addr, addr)) {
+                       if (out_link_id)
+                               *out_link_id = link_id;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 /*
  * requires that rx->skb is a frame with ethernet header
  */
@@ -2547,7 +2576,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc)
         * all other destination addresses for them.
         */
        if (unlikely(ehdr->h_proto == rx->sdata->control_port_protocol))
-               return ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) ||
+               return ieee80211_is_our_addr(rx->sdata, ehdr->h_dest, NULL) ||
                       ether_addr_equal(ehdr->h_dest, pae_group_addr);
 
        if (ieee80211_802_1x_port_control(rx) ||
@@ -4143,35 +4172,6 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
               is_broadcast_ether_addr(raddr);
 }
 
-static bool ieee80211_is_our_addr(struct ieee80211_sub_if_data *sdata,
-                                 const u8 *addr, int *out_link_id)
-{
-       unsigned int link_id;
-
-       /* non-MLO, or MLD address replaced by hardware */
-       if (ether_addr_equal(sdata->vif.addr, addr))
-               return true;
-
-       if (!sdata->vif.valid_links)
-               return false;
-
-       for (link_id = 0; link_id < ARRAY_SIZE(sdata->vif.link_conf); link_id++) {
-               struct ieee80211_bss_conf *conf;
-
-               conf = rcu_dereference(sdata->vif.link_conf[link_id]);
-
-               if (!conf)
-                       continue;
-               if (ether_addr_equal(conf->addr, addr)) {
-                       if (out_link_id)
-                               *out_link_id = link_id;
-                       return true;
-               }
-       }
-
-       return false;
-}
-
 static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_sub_if_data *sdata = rx->sdata;