wifi: cfg80211/mac80211: Support control port TX from specific link
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>
Thu, 30 Jun 2022 12:27:59 +0000 (15:27 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 15 Jul 2022 09:43:19 +0000 (11:43 +0200)
In case of authentication with a legacy station, link addressed EAPOL
frames should be sent. Support it.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
net/mac80211/ieee80211_i.h
net/mac80211/tx.c
net/wireless/nl80211.c
net/wireless/rdev-ops.h
net/wireless/trace.h

index bc96064..8dbc642 100644 (file)
@@ -4580,7 +4580,7 @@ struct cfg80211_ops {
                                   struct net_device *dev,
                                   const u8 *buf, size_t len,
                                   const u8 *dest, const __be16 proto,
-                                  const bool noencrypt,
+                                  const bool noencrypt, int link_id,
                                   u64 *cookie);
 
        int     (*get_ftm_responder_stats)(struct wiphy *wiphy,
index d17d73e..58b0831 100644 (file)
@@ -1946,7 +1946,7 @@ void ieee80211_clear_fast_xmit(struct sta_info *sta);
 int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
                              const u8 *buf, size_t len,
                              const u8 *dest, __be16 proto, bool unencrypted,
-                             u64 *cookie);
+                             int link_id, u64 *cookie);
 int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
                              const u8 *buf, size_t len);
 
index 4a7a714..8f25cfe 100644 (file)
@@ -5674,7 +5674,7 @@ void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
 int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
                              const u8 *buf, size_t len,
                              const u8 *dest, __be16 proto, bool unencrypted,
-                             u64 *cookie)
+                             int link_id, u64 *cookie)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
@@ -5714,7 +5714,23 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
 
        ehdr = skb_push(skb, sizeof(struct ethhdr));
        memcpy(ehdr->h_dest, dest, ETH_ALEN);
-       memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
+
+       if (link_id < 0) {
+               memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
+       } else {
+               struct ieee80211_bss_conf *link_conf;
+
+               rcu_read_lock();
+               link_conf = rcu_dereference(sdata->vif.link_conf[link_id]);
+               if (!link_conf) {
+                       dev_kfree_skb(skb);
+                       rcu_read_unlock();
+                       return -ENOLINK;
+               }
+               memcpy(ehdr->h_source, link_conf->addr, ETH_ALEN);
+               rcu_read_unlock();
+       }
+
        ehdr->h_proto = proto;
 
        skb->dev = dev;
index 35fcf36..53d63ef 100644 (file)
@@ -15223,6 +15223,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
        u16 proto;
        bool noencrypt;
        u64 cookie = 0;
+       int link_id;
        int err;
 
        if (!wiphy_ext_feature_isset(&rdev->wiphy,
@@ -15271,8 +15272,10 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
        noencrypt =
                nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
 
+       link_id = nl80211_link_id_or_invalid(info->attrs);
+
        err = rdev_tx_control_port(rdev, dev, buf, len,
-                                  dest, cpu_to_be16(proto), noencrypt,
+                                  dest, cpu_to_be16(proto), noencrypt, link_id,
                                   dont_wait_for_ack ? NULL : &cookie);
        if (!err && !dont_wait_for_ack)
                nl_set_extack_cookie_u64(info->extack, cookie);
index 53f5a01..40915a8 100644 (file)
@@ -746,13 +746,14 @@ static inline int rdev_tx_control_port(struct cfg80211_registered_device *rdev,
                                       struct net_device *dev,
                                       const void *buf, size_t len,
                                       const u8 *dest, __be16 proto,
-                                      const bool noencrypt, u64 *cookie)
+                                      const bool noencrypt, int link,
+                                      u64 *cookie)
 {
        int ret;
        trace_rdev_tx_control_port(&rdev->wiphy, dev, buf, len,
-                                  dest, proto, noencrypt);
+                                  dest, proto, noencrypt, link);
        ret = rdev->ops->tx_control_port(&rdev->wiphy, dev, buf, len,
-                                        dest, proto, noencrypt, cookie);
+                                        dest, proto, noencrypt, link, cookie);
        if (cookie)
                trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
        else
index dac66ad..592b9e9 100644 (file)
@@ -2015,14 +2015,15 @@ TRACE_EVENT(rdev_mgmt_tx,
 TRACE_EVENT(rdev_tx_control_port,
        TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
                 const u8 *buf, size_t len, const u8 *dest, __be16 proto,
-                bool unencrypted),
-       TP_ARGS(wiphy, netdev, buf, len, dest, proto, unencrypted),
+                bool unencrypted, int link_id),
+       TP_ARGS(wiphy, netdev, buf, len, dest, proto, unencrypted, link_id),
        TP_STRUCT__entry(
                WIPHY_ENTRY
                NETDEV_ENTRY
                MAC_ENTRY(dest)
                __field(__be16, proto)
                __field(bool, unencrypted)
+               __field(int, link_id)
        ),
        TP_fast_assign(
                WIPHY_ASSIGN;
@@ -2030,12 +2031,14 @@ TRACE_EVENT(rdev_tx_control_port,
                MAC_ASSIGN(dest, dest);
                __entry->proto = proto;
                __entry->unencrypted = unencrypted;
+               __entry->link_id = link_id;
        ),
        TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ","
-                 " proto: 0x%x, unencrypted: %s",
+                 " proto: 0x%x, unencrypted: %s, link: %d",
                  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dest),
                  be16_to_cpu(__entry->proto),
-                 BOOL_TO_STR(__entry->unencrypted))
+                 BOOL_TO_STR(__entry->unencrypted),
+                 __entry->link_id)
 );
 
 TRACE_EVENT(rdev_set_noack_map,