nl80211: explicitly check enum nl80211_mesh_power_mode
[cascardo/linux.git] / net / wireless / nl80211.c
index 7d72283..4997857 100644 (file)
@@ -167,6 +167,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
 
        if (attrs[NL80211_ATTR_IFINDEX]) {
                int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
+
                netdev = __dev_get_by_index(netns, ifindex);
                if (netdev) {
                        if (netdev->ieee80211_ptr)
@@ -404,6 +405,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
        [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
        [NL80211_ATTR_STA_SUPPORT_P2P_PS] = { .type = NLA_U8 },
+       [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
+               .len = VHT_MUMIMO_GROUPS_DATA_LEN
+       },
+       [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN },
 };
 
 /* policy for the key attributes */
@@ -731,6 +736,7 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
 
        if (tb[NL80211_KEY_DEFAULT_TYPES]) {
                struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
+
                err = nla_parse_nested(kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1,
                                       tb[NL80211_KEY_DEFAULT_TYPES],
                                       nl80211_key_default_policy);
@@ -1264,7 +1270,7 @@ nl80211_send_mgmt_stypes(struct sk_buff *msg,
 struct nl80211_dump_wiphy_state {
        s64 filter_wiphy;
        long start;
-       long split_start, band_start, chan_start;
+       long split_start, band_start, chan_start, capa_start;
        bool split;
 };
 
@@ -1382,6 +1388,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
                    rdev->ops->get_antenna) {
                        u32 tx_ant = 0, rx_ant = 0;
                        int res;
+
                        res = rdev_get_antenna(rdev, &tx_ant, &rx_ant);
                        if (!res) {
                                if (nla_put_u32(msg,
@@ -1761,6 +1768,47 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
                        nla_nest_end(msg, nested);
                }
 
+               state->split_start++;
+               break;
+       case 13:
+               if (rdev->wiphy.num_iftype_ext_capab &&
+                   rdev->wiphy.iftype_ext_capab) {
+                       struct nlattr *nested_ext_capab, *nested;
+
+                       nested = nla_nest_start(msg,
+                                               NL80211_ATTR_IFTYPE_EXT_CAPA);
+                       if (!nested)
+                               goto nla_put_failure;
+
+                       for (i = state->capa_start;
+                            i < rdev->wiphy.num_iftype_ext_capab; i++) {
+                               const struct wiphy_iftype_ext_capab *capab;
+
+                               capab = &rdev->wiphy.iftype_ext_capab[i];
+
+                               nested_ext_capab = nla_nest_start(msg, i);
+                               if (!nested_ext_capab ||
+                                   nla_put_u32(msg, NL80211_ATTR_IFTYPE,
+                                               capab->iftype) ||
+                                   nla_put(msg, NL80211_ATTR_EXT_CAPA,
+                                           capab->extended_capabilities_len,
+                                           capab->extended_capabilities) ||
+                                   nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
+                                           capab->extended_capabilities_len,
+                                           capab->extended_capabilities_mask))
+                                       goto nla_put_failure;
+
+                               nla_nest_end(msg, nested_ext_capab);
+                               if (state->split)
+                                       break;
+                       }
+                       nla_nest_end(msg, nested);
+                       if (i < rdev->wiphy.num_iftype_ext_capab) {
+                               state->capa_start = i + 1;
+                               break;
+                       }
+               }
+
                /* done */
                state->split_start = 0;
                break;
@@ -2116,7 +2164,6 @@ static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info)
        return rdev_set_wds_peer(rdev, dev, bssid);
 }
 
-
 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev;
@@ -2251,6 +2298,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
            info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
                u32 tx_ant, rx_ant;
+
                if ((!rdev->wiphy.available_antennas_tx &&
                     !rdev->wiphy.available_antennas_rx) ||
                    !rdev->ops->set_antenna)
@@ -2651,6 +2699,38 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
                change = true;
        }
 
+       if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) {
+               const u8 *mumimo_groups;
+               u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
+
+               if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
+                       return -EOPNOTSUPP;
+
+               mumimo_groups =
+                       nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
+
+               /* bits 0 and 63 are reserved and must be zero */
+               if ((mumimo_groups[0] & BIT(7)) ||
+                   (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(0)))
+                       return -EINVAL;
+
+               memcpy(params.vht_mumimo_groups, mumimo_groups,
+                      VHT_MUMIMO_GROUPS_DATA_LEN);
+               change = true;
+       }
+
+       if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) {
+               u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
+
+               if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
+                       return -EOPNOTSUPP;
+
+               nla_memcpy(params.macaddr,
+                          info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR],
+                          ETH_ALEN);
+               change = true;
+       }
+
        if (flags && (*flags & MONITOR_FLAG_ACTIVE) &&
            !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
                return -EOPNOTSUPP;
@@ -2671,7 +2751,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
        struct vif_params params;
        struct wireless_dev *wdev;
-       struct sk_buff *msg, *event;
+       struct sk_buff *msg;
        int err;
        enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
        u32 flags;
@@ -2775,20 +2855,15 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
                return -ENOBUFS;
        }
 
-       event = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (event) {
-               if (nl80211_send_iface(event, 0, 0, 0,
-                                      rdev, wdev, false) < 0) {
-                       nlmsg_free(event);
-                       goto out;
-               }
-
-               genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
-                                       event, 0, NL80211_MCGRP_CONFIG,
-                                       GFP_KERNEL);
-       }
+       /*
+        * For wdevs which have no associated netdev object (e.g. of type
+        * NL80211_IFTYPE_P2P_DEVICE), emit the NEW_INTERFACE event here.
+        * For all other types, the event will be generated from the
+        * netdev notifier
+        */
+       if (!wdev->netdev)
+               nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
 
-out:
        return genlmsg_reply(msg, info);
 }
 
@@ -2796,18 +2871,10 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
        struct wireless_dev *wdev = info->user_ptr[1];
-       struct sk_buff *msg;
-       int status;
 
        if (!rdev->ops->del_virtual_intf)
                return -EOPNOTSUPP;
 
-       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (msg && nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, true) < 0) {
-               nlmsg_free(msg);
-               msg = NULL;
-       }
-
        /*
         * If we remove a wireless device without a netdev then clear
         * user_ptr[1] so that nl80211_post_doit won't dereference it
@@ -2818,15 +2885,7 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
        if (!wdev->netdev)
                info->user_ptr[1] = NULL;
 
-       status = rdev_del_virtual_intf(rdev, wdev);
-       if (status >= 0 && msg)
-               genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
-                                       msg, 0, NL80211_MCGRP_CONFIG,
-                                       GFP_KERNEL);
-       else
-               nlmsg_free(msg);
-
-       return status;
+       return rdev_del_virtual_intf(rdev, wdev);
 }
 
 static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
@@ -2919,6 +2978,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
        pairwise = !!mac_addr;
        if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
                u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
+
                if (kt >= NUM_NL80211_KEYTYPES)
                        return -EINVAL;
                if (kt != NL80211_KEYTYPE_GROUP &&
@@ -3962,7 +4022,6 @@ static int nl80211_dump_station(struct sk_buff *skb,
                sta_idx++;
        }
 
-
  out:
        cb->args[2] = sta_idx;
        err = skb->len;
@@ -4366,6 +4425,12 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
                        nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
                if (params.plink_state >= NUM_NL80211_PLINK_STATES)
                        return -EINVAL;
+               if (info->attrs[NL80211_ATTR_MESH_PEER_AID]) {
+                       params.peer_aid = nla_get_u16(
+                               info->attrs[NL80211_ATTR_MESH_PEER_AID]);
+                       if (params.peer_aid > IEEE80211_MAX_AID)
+                               return -EINVAL;
+               }
                params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
        }
 
@@ -4763,7 +4828,6 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
                path_idx++;
        }
 
-
  out:
        cb->args[2] = path_idx;
        err = skb->len;
@@ -5053,7 +5117,6 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
        enum nl80211_user_reg_hint_type user_reg_hint_type;
        u32 owner_nlportid;
 
-
        /*
         * You should only get this when cfg80211 hasn't yet initialized
         * completely when built-in to the kernel right between the time
@@ -5245,24 +5308,80 @@ static const struct nla_policy
        [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
 };
 
+static int nl80211_check_bool(const struct nlattr *nla, u8 min, u8 max, bool *out)
+{
+       u8 val = nla_get_u8(nla);
+       if (val < min || val > max)
+               return -EINVAL;
+       *out = val;
+       return 0;
+}
+
+static int nl80211_check_u8(const struct nlattr *nla, u8 min, u8 max, u8 *out)
+{
+       u8 val = nla_get_u8(nla);
+       if (val < min || val > max)
+               return -EINVAL;
+       *out = val;
+       return 0;
+}
+
+static int nl80211_check_u16(const struct nlattr *nla, u16 min, u16 max, u16 *out)
+{
+       u16 val = nla_get_u16(nla);
+       if (val < min || val > max)
+               return -EINVAL;
+       *out = val;
+       return 0;
+}
+
+static int nl80211_check_u32(const struct nlattr *nla, u32 min, u32 max, u32 *out)
+{
+       u32 val = nla_get_u32(nla);
+       if (val < min || val > max)
+               return -EINVAL;
+       *out = val;
+       return 0;
+}
+
+static int nl80211_check_s32(const struct nlattr *nla, s32 min, s32 max, s32 *out)
+{
+       s32 val = nla_get_s32(nla);
+       if (val < min || val > max)
+               return -EINVAL;
+       *out = val;
+       return 0;
+}
+
+static int nl80211_check_power_mode(const struct nlattr *nla,
+                                   enum nl80211_mesh_power_mode min,
+                                   enum nl80211_mesh_power_mode max,
+                                   enum nl80211_mesh_power_mode *out)
+{
+       u32 val = nla_get_u32(nla);
+       if (val < min || val > max)
+               return -EINVAL;
+       *out = val;
+       return 0;
+}
+
 static int nl80211_parse_mesh_config(struct genl_info *info,
                                     struct mesh_config *cfg,
                                     u32 *mask_out)
 {
        struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
        u32 mask = 0;
+       u16 ht_opmode;
 
 #define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, min, max, mask, attr, fn) \
 do {                                                                       \
        if (tb[attr]) {                                                     \
-               if (fn(tb[attr]) < min || fn(tb[attr]) > max)               \
+               if (fn(tb[attr], min, max, &cfg->param))                    \
                        return -EINVAL;                                     \
-               cfg->param = fn(tb[attr]);                                  \
                mask |= (1 << (attr - 1));                                  \
        }                                                                   \
 } while (0)
 
-
        if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
                return -EINVAL;
        if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX,
@@ -5277,99 +5396,126 @@ do {                                                                       \
        /* Fill in the params struct */
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, 1, 255,
                                  mask, NL80211_MESHCONF_RETRY_TIMEOUT,
-                                 nla_get_u16);
+                                 nl80211_check_u16);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, 1, 255,
                                  mask, NL80211_MESHCONF_CONFIRM_TIMEOUT,
-                                 nla_get_u16);
+                                 nl80211_check_u16);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, 1, 255,
                                  mask, NL80211_MESHCONF_HOLDING_TIMEOUT,
-                                 nla_get_u16);
+                                 nl80211_check_u16);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, 0, 255,
                                  mask, NL80211_MESHCONF_MAX_PEER_LINKS,
-                                 nla_get_u16);
+                                 nl80211_check_u16);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, 0, 16,
                                  mask, NL80211_MESHCONF_MAX_RETRIES,
-                                 nla_get_u8);
+                                 nl80211_check_u8);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, 1, 255,
-                                 mask, NL80211_MESHCONF_TTL, nla_get_u8);
+                                 mask, NL80211_MESHCONF_TTL, nl80211_check_u8);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, 1, 255,
                                  mask, NL80211_MESHCONF_ELEMENT_TTL,
-                                 nla_get_u8);
+                                 nl80211_check_u8);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, 0, 1,
                                  mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
-                                 nla_get_u8);
+                                 nl80211_check_bool);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
                                  1, 255, mask,
                                  NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
-                                 nla_get_u32);
+                                 nl80211_check_u32);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, 0, 255,
                                  mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
-                                 nla_get_u8);
+                                 nl80211_check_u8);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, 1, 65535,
                                  mask, NL80211_MESHCONF_PATH_REFRESH_TIME,
-                                 nla_get_u32);
+                                 nl80211_check_u32);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, 1, 65535,
                                  mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
-                                 nla_get_u16);
+                                 nl80211_check_u16);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
                                  1, 65535, mask,
                                  NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
-                                 nla_get_u32);
+                                 nl80211_check_u32);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval,
                                  1, 65535, mask,
                                  NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
-                                 nla_get_u16);
+                                 nl80211_check_u16);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval,
                                  1, 65535, mask,
                                  NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
-                                 nla_get_u16);
+                                 nl80211_check_u16);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
                                  dot11MeshHWMPnetDiameterTraversalTime,
                                  1, 65535, mask,
                                  NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
-                                 nla_get_u16);
+                                 nl80211_check_u16);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, 0, 4,
                                  mask, NL80211_MESHCONF_HWMP_ROOTMODE,
-                                 nla_get_u8);
+                                 nl80211_check_u8);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, 1, 65535,
                                  mask, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
-                                 nla_get_u16);
+                                 nl80211_check_u16);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
                                  dot11MeshGateAnnouncementProtocol, 0, 1,
                                  mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
-                                 nla_get_u8);
+                                 nl80211_check_bool);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1,
                                  mask, NL80211_MESHCONF_FORWARDING,
-                                 nla_get_u8);
+                                 nl80211_check_bool);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0,
                                  mask, NL80211_MESHCONF_RSSI_THRESHOLD,
-                                 nla_get_s32);
-       FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16,
-                                 mask, NL80211_MESHCONF_HT_OPMODE,
-                                 nla_get_u16);
+                                 nl80211_check_s32);
+       /*
+        * Check HT operation mode based on
+        * IEEE 802.11 2012 8.4.2.59 HT Operation element.
+        */
+       if (tb[NL80211_MESHCONF_HT_OPMODE]) {
+               ht_opmode = nla_get_u16(tb[NL80211_MESHCONF_HT_OPMODE]);
+
+               if (ht_opmode & ~(IEEE80211_HT_OP_MODE_PROTECTION |
+                                 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
+                                 IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
+                       return -EINVAL;
+
+               if ((ht_opmode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) &&
+                   (ht_opmode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
+                       return -EINVAL;
+
+               switch (ht_opmode & IEEE80211_HT_OP_MODE_PROTECTION) {
+               case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
+               case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
+                       if (ht_opmode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT)
+                               return -EINVAL;
+                       break;
+               case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
+               case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
+                       if (!(ht_opmode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
+                               return -EINVAL;
+                       break;
+               }
+               cfg->ht_opmode = ht_opmode;
+       }
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout,
                                  1, 65535, mask,
                                  NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
-                                 nla_get_u32);
+                                 nl80211_check_u32);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, 1, 65535,
                                  mask, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
-                                 nla_get_u16);
+                                 nl80211_check_u16);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
                                  dot11MeshHWMPconfirmationInterval,
                                  1, 65535, mask,
                                  NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
-                                 nla_get_u16);
+                                 nl80211_check_u16);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode,
                                  NL80211_MESH_POWER_ACTIVE,
                                  NL80211_MESH_POWER_MAX,
                                  mask, NL80211_MESHCONF_POWER_MODE,
-                                 nla_get_u32);
+                                 nl80211_check_power_mode);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration,
                                  0, 65535, mask,
-                                 NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
+                                 NL80211_MESHCONF_AWAKE_WINDOW, nl80211_check_u16);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 0, 0xffffffff,
                                  mask, NL80211_MESHCONF_PLINK_TIMEOUT,
-                                 nla_get_u32);
+                                 nl80211_check_u32);
        if (mask_out)
                *mask_out = mask;
 
@@ -5409,7 +5555,6 @@ static int nl80211_parse_mesh_setup(struct genl_info *info,
                 IEEE80211_PATH_METRIC_VENDOR :
                 IEEE80211_PATH_METRIC_AIRTIME;
 
-
        if (tb[NL80211_MESH_SETUP_IE]) {
                struct nlattr *ieattr =
                        tb[NL80211_MESH_SETUP_IE];
@@ -5796,10 +5941,8 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
                }
        }
 
-       r = set_regdom(rd, REGD_SOURCE_CRDA);
-       /* set_regdom took ownership */
-       rd = NULL;
-
+       /* set_regdom takes ownership of rd */
+       return set_regdom(rd, REGD_SOURCE_CRDA);
  bad_reg:
        kfree(rd);
        return r;
@@ -6033,6 +6176,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                /* all channels */
                for (band = 0; band < NUM_NL80211_BANDS; band++) {
                        int j;
+
                        if (!wiphy->bands[band])
                                continue;
                        for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
@@ -6104,6 +6248,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                }
        }
 
+       if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) {
+               if (!wiphy_ext_feature_isset(wiphy,
+                                       NL80211_EXT_FEATURE_SET_SCAN_DWELL)) {
+                       err = -EOPNOTSUPP;
+                       goto out_free;
+               }
+
+               request->duration =
+                       nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]);
+               request->duration_mandatory =
+                       nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]);
+       }
+
        if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
                request->flags = nla_get_u32(
                        info->attrs[NL80211_ATTR_SCAN_FLAGS]);
@@ -6442,6 +6599,7 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
                /* all channels */
                for (band = 0; band < NUM_NL80211_BANDS; band++) {
                        int j;
+
                        if (!wiphy->bands[band])
                                continue;
                        for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
@@ -6511,7 +6669,7 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
                                       nla_data(ssid), nla_len(ssid));
                                request->match_sets[i].ssid.ssid_len =
                                        nla_len(ssid);
-                               /* special attribute - old implemenation w/a */
+                               /* special attribute - old implementation w/a */
                                request->match_sets[i].rssi_thold =
                                        default_match_rssi;
                                rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
@@ -6936,6 +7094,13 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
                        jiffies_to_msecs(jiffies - intbss->ts)))
                goto nla_put_failure;
 
+       if (intbss->parent_tsf &&
+           (nla_put_u64_64bit(msg, NL80211_BSS_PARENT_TSF,
+                              intbss->parent_tsf, NL80211_BSS_PAD) ||
+            nla_put(msg, NL80211_BSS_PARENT_BSSID, ETH_ALEN,
+                    intbss->parent_bssid)))
+               goto nla_put_failure;
+
        if (intbss->ts_boottime &&
            nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
                              intbss->ts_boottime, NL80211_BSS_PAD))
@@ -7204,6 +7369,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
        if (key.idx >= 0) {
                int i;
                bool ok = false;
+
                for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) {
                        if (key.p.cipher == rdev->wiphy.cipher_suites[i]) {
                                ok = true;
@@ -7282,6 +7448,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
 
        if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
                u16 proto;
+
                proto = nla_get_u16(
                        info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
                settings->control_port_ethertype = cpu_to_be16(proto);
@@ -7597,12 +7764,13 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
 
        ibss.beacon_interval = 100;
 
-       if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
+       if (info->attrs[NL80211_ATTR_BEACON_INTERVAL])
                ibss.beacon_interval =
                        nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
-               if (ibss.beacon_interval < 1 || ibss.beacon_interval > 10000)
-                       return -EINVAL;
-       }
+
+       err = cfg80211_validate_beacon_int(rdev, ibss.beacon_interval);
+       if (err)
+               return err;
 
        if (!rdev->ops->join_ibss)
                return -EOPNOTSUPP;
@@ -8435,6 +8603,7 @@ static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
        for (i = 0; i < rates_len; i++) {
                int rate = (rates[i] & 0x7f) * 5;
                int ridx;
+
                for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
                        struct ieee80211_rate *srate =
                                &sband->bitrates[ridx];
@@ -8743,7 +8912,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
                if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
                    params.wait > rdev->wiphy.max_remain_on_channel_duration)
                        return -EINVAL;
-
        }
 
        params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
@@ -9076,9 +9244,10 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
                setup.beacon_interval =
                        nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
-               if (setup.beacon_interval < 10 ||
-                   setup.beacon_interval > 10000)
-                       return -EINVAL;
+
+               err = cfg80211_validate_beacon_int(rdev, setup.beacon_interval);
+               if (err)
+                       return err;
        }
 
        if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
@@ -10590,7 +10759,6 @@ int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
 
-
 static int nl80211_set_qos_map(struct sk_buff *skb,
                               struct genl_info *info)
 {
@@ -10945,7 +11113,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_WIPHY,
                .doit = nl80211_set_wiphy,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -10961,7 +11129,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_INTERFACE,
                .doit = nl80211_set_interface,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -10969,7 +11137,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_NEW_INTERFACE,
                .doit = nl80211_new_interface,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WIPHY |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -10977,7 +11145,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_DEL_INTERFACE,
                .doit = nl80211_del_interface,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -10985,7 +11153,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_GET_KEY,
                .doit = nl80211_get_key,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -10993,7 +11161,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_KEY,
                .doit = nl80211_set_key,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL |
                                  NL80211_FLAG_CLEAR_SKB,
@@ -11002,7 +11170,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_NEW_KEY,
                .doit = nl80211_new_key,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL |
                                  NL80211_FLAG_CLEAR_SKB,
@@ -11011,14 +11179,14 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_DEL_KEY,
                .doit = nl80211_del_key,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
                .cmd = NL80211_CMD_SET_BEACON,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .doit = nl80211_set_beacon,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
@@ -11026,7 +11194,7 @@ static const struct genl_ops nl80211_ops[] = {
        {
                .cmd = NL80211_CMD_START_AP,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .doit = nl80211_start_ap,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
@@ -11034,7 +11202,7 @@ static const struct genl_ops nl80211_ops[] = {
        {
                .cmd = NL80211_CMD_STOP_AP,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .doit = nl80211_stop_ap,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
@@ -11051,7 +11219,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_STATION,
                .doit = nl80211_set_station,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11059,7 +11227,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_NEW_STATION,
                .doit = nl80211_new_station,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11067,7 +11235,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_DEL_STATION,
                .doit = nl80211_del_station,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11076,7 +11244,7 @@ static const struct genl_ops nl80211_ops[] = {
                .doit = nl80211_get_mpath,
                .dumpit = nl80211_dump_mpath,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11085,7 +11253,7 @@ static const struct genl_ops nl80211_ops[] = {
                .doit = nl80211_get_mpp,
                .dumpit = nl80211_dump_mpp,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11093,7 +11261,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_MPATH,
                .doit = nl80211_set_mpath,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11101,7 +11269,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_NEW_MPATH,
                .doit = nl80211_new_mpath,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11109,7 +11277,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_DEL_MPATH,
                .doit = nl80211_del_mpath,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11117,7 +11285,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_BSS,
                .doit = nl80211_set_bss,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11156,7 +11324,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_MESH_CONFIG,
                .doit = nl80211_update_mesh_config,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11164,7 +11332,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_TRIGGER_SCAN,
                .doit = nl80211_trigger_scan,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11172,7 +11340,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_ABORT_SCAN,
                .doit = nl80211_abort_scan,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11185,7 +11353,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_START_SCHED_SCAN,
                .doit = nl80211_start_sched_scan,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11193,7 +11361,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_STOP_SCHED_SCAN,
                .doit = nl80211_stop_sched_scan,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11201,7 +11369,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_AUTHENTICATE,
                .doit = nl80211_authenticate,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL |
                                  NL80211_FLAG_CLEAR_SKB,
@@ -11210,7 +11378,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_ASSOCIATE,
                .doit = nl80211_associate,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11218,7 +11386,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_DEAUTHENTICATE,
                .doit = nl80211_deauthenticate,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11226,7 +11394,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_DISASSOCIATE,
                .doit = nl80211_disassociate,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11234,7 +11402,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_JOIN_IBSS,
                .doit = nl80211_join_ibss,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11242,7 +11410,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_LEAVE_IBSS,
                .doit = nl80211_leave_ibss,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11252,7 +11420,7 @@ static const struct genl_ops nl80211_ops[] = {
                .doit = nl80211_testmode_do,
                .dumpit = nl80211_testmode_dump,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WIPHY |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11261,7 +11429,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_CONNECT,
                .doit = nl80211_connect,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11269,7 +11437,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_DISCONNECT,
                .doit = nl80211_disconnect,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11277,7 +11445,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_WIPHY_NETNS,
                .doit = nl80211_wiphy_netns,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WIPHY |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11290,7 +11458,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_PMKSA,
                .doit = nl80211_setdel_pmksa,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11298,7 +11466,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_DEL_PMKSA,
                .doit = nl80211_setdel_pmksa,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11306,7 +11474,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_FLUSH_PMKSA,
                .doit = nl80211_flush_pmksa,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11314,7 +11482,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
                .doit = nl80211_remain_on_channel,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11322,7 +11490,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
                .doit = nl80211_cancel_remain_on_channel,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11330,7 +11498,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
                .doit = nl80211_set_tx_bitrate_mask,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11338,7 +11506,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_REGISTER_FRAME,
                .doit = nl80211_register_mgmt,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11346,7 +11514,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_FRAME,
                .doit = nl80211_tx_mgmt,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11354,7 +11522,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
                .doit = nl80211_tx_mgmt_cancel_wait,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11362,7 +11530,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_POWER_SAVE,
                .doit = nl80211_set_power_save,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11378,7 +11546,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_CQM,
                .doit = nl80211_set_cqm,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11386,7 +11554,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_CHANNEL,
                .doit = nl80211_set_channel,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11394,7 +11562,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_WDS_PEER,
                .doit = nl80211_set_wds_peer,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11402,7 +11570,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_JOIN_MESH,
                .doit = nl80211_join_mesh,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11410,7 +11578,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_LEAVE_MESH,
                .doit = nl80211_leave_mesh,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11418,7 +11586,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_JOIN_OCB,
                .doit = nl80211_join_ocb,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11426,7 +11594,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_LEAVE_OCB,
                .doit = nl80211_leave_ocb,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11443,7 +11611,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_WOWLAN,
                .doit = nl80211_set_wowlan,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WIPHY |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11452,7 +11620,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
                .doit = nl80211_set_rekey_data,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL |
                                  NL80211_FLAG_CLEAR_SKB,
@@ -11461,7 +11629,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_TDLS_MGMT,
                .doit = nl80211_tdls_mgmt,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11469,7 +11637,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_TDLS_OPER,
                .doit = nl80211_tdls_oper,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11477,7 +11645,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_UNEXPECTED_FRAME,
                .doit = nl80211_register_unexpected_frame,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11485,7 +11653,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_PROBE_CLIENT,
                .doit = nl80211_probe_client,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11493,7 +11661,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_REGISTER_BEACONS,
                .doit = nl80211_register_beacons,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WIPHY |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11501,7 +11669,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_NOACK_MAP,
                .doit = nl80211_set_noack_map,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11509,7 +11677,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_START_P2P_DEVICE,
                .doit = nl80211_start_p2p_device,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11517,7 +11685,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_STOP_P2P_DEVICE,
                .doit = nl80211_stop_p2p_device,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11525,7 +11693,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_MCAST_RATE,
                .doit = nl80211_set_mcast_rate,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11533,7 +11701,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_MAC_ACL,
                .doit = nl80211_set_mac_acl,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11541,7 +11709,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_RADAR_DETECT,
                .doit = nl80211_start_radar_detection,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11554,7 +11722,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_UPDATE_FT_IES,
                .doit = nl80211_update_ft_ies,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11562,7 +11730,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
                .doit = nl80211_crit_protocol_start,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11570,7 +11738,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
                .doit = nl80211_crit_protocol_stop,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11585,7 +11753,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_COALESCE,
                .doit = nl80211_set_coalesce,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WIPHY |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11593,7 +11761,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_CHANNEL_SWITCH,
                .doit = nl80211_channel_switch,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11602,7 +11770,7 @@ static const struct genl_ops nl80211_ops[] = {
                .doit = nl80211_vendor_cmd,
                .dumpit = nl80211_vendor_cmd_dump,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_WIPHY |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11610,7 +11778,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_SET_QOS_MAP,
                .doit = nl80211_set_qos_map,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11618,7 +11786,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_ADD_TX_TS,
                .doit = nl80211_add_tx_ts,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11626,7 +11794,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_DEL_TX_TS,
                .doit = nl80211_del_tx_ts,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11634,7 +11802,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
                .doit = nl80211_tdls_channel_switch,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11642,7 +11810,7 @@ static const struct genl_ops nl80211_ops[] = {
                .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
                .doit = nl80211_tdls_cancel_channel_switch,
                .policy = nl80211_policy,
-               .flags = GENL_ADMIN_PERM,
+               .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
@@ -11672,6 +11840,29 @@ void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
                                NL80211_MCGRP_CONFIG, GFP_KERNEL);
 }
 
+void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
+                               struct wireless_dev *wdev,
+                               enum nl80211_commands cmd)
+{
+       struct sk_buff *msg;
+
+       WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
+               cmd != NL80211_CMD_DEL_INTERFACE);
+
+       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       if (!msg)
+               return;
+
+       if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev,
+                              cmd == NL80211_CMD_DEL_INTERFACE) < 0) {
+               nlmsg_free(msg);
+               return;
+       }
+
+       genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+                               NL80211_MCGRP_CONFIG, GFP_KERNEL);
+}
+
 static int nl80211_add_scan_req(struct sk_buff *msg,
                                struct cfg80211_registered_device *rdev)
 {
@@ -11708,6 +11899,13 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
            nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
                goto nla_put_failure;
 
+       if (req->info.scan_start_tsf &&
+           (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
+                              req->info.scan_start_tsf, NL80211_BSS_PAD) ||
+            nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
+                    req->info.tsf_bssid)))
+               goto nla_put_failure;
+
        return 0;
  nla_put_failure:
        return -ENOBUFS;
@@ -12092,7 +12290,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
                                 struct net_device *netdev, const u8 *bssid,
                                 const u8 *req_ie, size_t req_ie_len,
                                 const u8 *resp_ie, size_t resp_ie_len,
-                                u16 status, gfp_t gfp)
+                                int status, gfp_t gfp)
 {
        struct sk_buff *msg;
        void *hdr;
@@ -12110,7 +12308,10 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
            nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
            (bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) ||
-           nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status) ||
+           nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
+                       status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
+                       status) ||
+           (status < 0 && nla_put_flag(msg, NL80211_ATTR_TIMED_OUT)) ||
            (req_ie &&
             nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) ||
            (resp_ie &&
@@ -12126,7 +12327,6 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
  nla_put_failure:
        genlmsg_cancel(msg, hdr);
        nlmsg_free(msg);
-
 }
 
 void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
@@ -12165,7 +12365,6 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
  nla_put_failure:
        genlmsg_cancel(msg, hdr);
        nlmsg_free(msg);
-
 }
 
 void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
@@ -12203,7 +12402,6 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
  nla_put_failure:
        genlmsg_cancel(msg, hdr);
        nlmsg_free(msg);
-
 }
 
 void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
@@ -13545,7 +13743,6 @@ void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
        if (hdr)
                genlmsg_cancel(msg, hdr);
        nlmsg_free(msg);
-
 }
 EXPORT_SYMBOL(cfg80211_crit_proto_stopped);