Merge tag 'mac80211-next-for-net-next-2020-02-14' of git://git.kernel.org/pub/scm...
[linux-2.6-microblaze.git] / net / wireless / nl80211.c
index cedf17d..f0112da 100644 (file)
@@ -321,6 +321,13 @@ he_obss_pd_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = {
                NLA_POLICY_RANGE(NLA_U8, 1, 20),
 };
 
+static const struct nla_policy
+he_bss_color_policy[NL80211_HE_BSS_COLOR_ATTR_MAX + 1] = {
+       [NL80211_HE_BSS_COLOR_ATTR_COLOR] = NLA_POLICY_RANGE(NLA_U8, 1, 63),
+       [NL80211_HE_BSS_COLOR_ATTR_DISABLED] = { .type = NLA_FLAG },
+       [NL80211_HE_BSS_COLOR_ATTR_PARTIAL] = { .type = NLA_FLAG },
+};
+
 const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
        [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
@@ -626,6 +633,9 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
        [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
        [NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
+       [NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
+       [NL80211_ATTR_SRC_MAC] = NLA_POLICY_ETH_ADDR,
+       [NL80211_ATTR_DST_MAC] = NLA_POLICY_ETH_ADDR,
 };
 
 /* policy for the key attributes */
@@ -965,6 +975,9 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
                if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
                    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
                        goto nla_put_failure;
+               if ((chan->flags & IEEE80211_CHAN_NO_HE) &&
+                   nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HE))
+                       goto nla_put_failure;
        }
 
        if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
@@ -1886,6 +1899,46 @@ static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
        return 0;
 }
 
+static int
+nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev,
+                             struct sk_buff *msg)
+{
+       int i;
+       struct nlattr *nested, *nested_akms;
+       const struct wiphy_iftype_akm_suites *iftype_akms;
+
+       if (!rdev->wiphy.num_iftype_akm_suites ||
+           !rdev->wiphy.iftype_akm_suites)
+               return 0;
+
+       nested = nla_nest_start(msg, NL80211_ATTR_IFTYPE_AKM_SUITES);
+       if (!nested)
+               return -ENOBUFS;
+
+       for (i = 0; i < rdev->wiphy.num_iftype_akm_suites; i++) {
+               nested_akms = nla_nest_start(msg, i + 1);
+               if (!nested_akms)
+                       return -ENOBUFS;
+
+               iftype_akms = &rdev->wiphy.iftype_akm_suites[i];
+
+               if (nl80211_put_iftypes(msg, NL80211_IFTYPE_AKM_ATTR_IFTYPES,
+                                       iftype_akms->iftypes_mask))
+                       return -ENOBUFS;
+
+               if (nla_put(msg, NL80211_IFTYPE_AKM_ATTR_SUITES,
+                           sizeof(u32) * iftype_akms->n_akm_suites,
+                           iftype_akms->akm_suites)) {
+                       return -ENOBUFS;
+               }
+               nla_nest_end(msg, nested_akms);
+       }
+
+       nla_nest_end(msg, nested);
+
+       return 0;
+}
+
 struct nl80211_dump_wiphy_state {
        s64 filter_wiphy;
        long start;
@@ -2444,6 +2497,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
                            rdev->wiphy.akm_suites))
                        goto nla_put_failure;
 
+               if (nl80211_put_iftype_akm_suites(rdev, msg))
+                       goto nla_put_failure;
+
                /* done */
                state->split_start = 0;
                break;
@@ -4512,6 +4568,30 @@ static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
        return 0;
 }
 
+static int nl80211_parse_he_bss_color(struct nlattr *attrs,
+                                     struct cfg80211_he_bss_color *he_bss_color)
+{
+       struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1];
+       int err;
+
+       err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs,
+                              he_bss_color_policy, NULL);
+       if (err)
+               return err;
+
+       if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR])
+               return -EINVAL;
+
+       he_bss_color->color =
+               nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]);
+       he_bss_color->disabled =
+               nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]);
+       he_bss_color->partial =
+               nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]);
+
+       return 0;
+}
+
 static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
                                            const u8 *rates)
 {
@@ -4804,6 +4884,14 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
                        return err;
        }
 
+       if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) {
+               err = nl80211_parse_he_bss_color(
+                                       info->attrs[NL80211_ATTR_HE_BSS_COLOR],
+                                       &params.he_bss_color);
+               if (err)
+                       return err;
+       }
+
        nl80211_calculate_ap_params(&params);
 
        if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
@@ -10539,8 +10627,9 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
                return -EOPNOTSUPP;
 
        return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
-                       nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
-                       nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]));
+                                          nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
+                                          nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
+                                          info->extack);
 }
 
 static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
@@ -13609,6 +13698,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
        const u8 *buf;
        size_t len;
        u8 *dest;
+       u8 src[ETH_ALEN];
        u16 proto;
        bool noencrypt;
        int err;
@@ -13646,6 +13736,13 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
+       /* copy src address under wdev_lock, as we may copy wdev_address */
+       if (info->attrs[NL80211_ATTR_SRC_MAC])
+               ether_addr_copy(src,
+                               nla_data(info->attrs[NL80211_ATTR_SRC_MAC]));
+       else
+               ether_addr_copy(src, wdev_address(wdev));
+
        wdev_unlock(wdev);
 
        buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
@@ -13656,7 +13753,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
                nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
 
        return rdev_tx_control_port(rdev, dev, buf, len,
-                                   dest, cpu_to_be16(proto), noencrypt);
+                                   dest, src, cpu_to_be16(proto), noencrypt);
 
  out:
        wdev_unlock(wdev);
@@ -15913,7 +16010,8 @@ static int __nl80211_rx_control_port(struct net_device *dev,
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
        struct ethhdr *ehdr = eth_hdr(skb);
-       const u8 *addr = ehdr->h_source;
+       const u8 *daddr = ehdr->h_dest;
+       const u8 *saddr = ehdr->h_source;
        u16 proto = be16_to_cpu(skb->protocol);
        struct sk_buff *msg;
        void *hdr;
@@ -15938,7 +16036,8 @@ static int __nl80211_rx_control_port(struct net_device *dev,
            nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
            nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
                              NL80211_ATTR_PAD) ||
-           nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
+           nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, saddr) ||
+           nla_put(msg, NL80211_ATTR_DST_MAC, ETH_ALEN, daddr) ||
            nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
            (unencrypted && nla_put_flag(msg,
                                         NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))