^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * This is the new netlink-based wireless configuration interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2013-2014 Intel Mobile Communications GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright 2015-2017 Intel Deutschland GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2018-2021 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/if.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/if_ether.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/ieee80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/nl80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/nospec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/if_vlan.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <net/net_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <net/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <net/cfg80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <net/inet_connection_sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "nl80211.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "rdev-ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct cfg80211_crypto_settings *settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int cipher_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* the netlink family */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static struct genl_family nl80211_fam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* multicast groups */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) enum nl80211_multicast_groups {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) NL80211_MCGRP_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) NL80211_MCGRP_SCAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) NL80211_MCGRP_REGULATORY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) NL80211_MCGRP_MLME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) NL80211_MCGRP_VENDOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) NL80211_MCGRP_NAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) NL80211_MCGRP_TESTMODE /* keep last - ifdef! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static const struct genl_multicast_group nl80211_mcgrps[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) [NL80211_MCGRP_CONFIG] = { .name = NL80211_MULTICAST_GROUP_CONFIG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) [NL80211_MCGRP_SCAN] = { .name = NL80211_MULTICAST_GROUP_SCAN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) [NL80211_MCGRP_REGULATORY] = { .name = NL80211_MULTICAST_GROUP_REG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) [NL80211_MCGRP_MLME] = { .name = NL80211_MULTICAST_GROUP_MLME },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) [NL80211_MCGRP_VENDOR] = { .name = NL80211_MULTICAST_GROUP_VENDOR },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) [NL80211_MCGRP_NAN] = { .name = NL80211_MULTICAST_GROUP_NAN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #ifdef CONFIG_NL80211_TESTMODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) [NL80211_MCGRP_TESTMODE] = { .name = NL80211_MULTICAST_GROUP_TESTMODE }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* returns ERR_PTR values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static struct wireless_dev *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct wireless_dev *result = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) bool have_ifidx = attrs[NL80211_ATTR_IFINDEX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) bool have_wdev_id = attrs[NL80211_ATTR_WDEV];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) u64 wdev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int wiphy_idx = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int ifidx = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (!have_ifidx && !have_wdev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (have_ifidx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ifidx = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (have_wdev_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) wiphy_idx = wdev_id >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (wiphy_net(&rdev->wiphy) != netns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (have_ifidx && wdev->netdev &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) wdev->netdev->ifindex == ifidx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) result = wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (have_wdev_id && wdev->identifier == (u32)wdev_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) result = wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static struct cfg80211_registered_device *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct cfg80211_registered_device *rdev = NULL, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct net_device *netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (!attrs[NL80211_ATTR_WIPHY] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) !attrs[NL80211_ATTR_IFINDEX] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) !attrs[NL80211_ATTR_WDEV])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (attrs[NL80211_ATTR_WIPHY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) rdev = cfg80211_rdev_by_wiphy_idx(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) nla_get_u32(attrs[NL80211_ATTR_WIPHY]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (attrs[NL80211_ATTR_WDEV]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) u64 wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* make sure wdev exists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) list_for_each_entry(wdev, &tmp->wiphy.wdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (wdev->identifier != (u32)wdev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (!found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (rdev && tmp != rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) rdev = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (attrs[NL80211_ATTR_IFINDEX]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) netdev = __dev_get_by_index(netns, ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (netdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (netdev->ieee80211_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) tmp = wiphy_to_rdev(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) netdev->ieee80211_ptr->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* not wireless device -- return error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (!tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /* mismatch -- return error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (rdev && tmp != rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) rdev = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (!rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (netns != wiphy_net(&rdev->wiphy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * This function returns a pointer to the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * that the genl_info item that is passed refers to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * The result of this can be a PTR_ERR and hence must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * be checked with IS_ERR() for errors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static struct cfg80211_registered_device *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return __cfg80211_rdev_from_attrs(netns, info->attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static int validate_beacon_head(const struct nlattr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) const u8 *data = nla_data(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) unsigned int len = nla_len(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) const struct element *elem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) const struct ieee80211_mgmt *mgmt = (void *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) unsigned int fixedlen, hdrlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) bool s1g_bcn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (len < offsetofend(typeof(*mgmt), frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) s1g_bcn = ieee80211_is_s1g_beacon(mgmt->frame_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (s1g_bcn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) fixedlen = offsetof(struct ieee80211_ext,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) u.s1g_beacon.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) hdrlen = offsetof(struct ieee80211_ext, u.s1g_beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) fixedlen = offsetof(struct ieee80211_mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) u.beacon.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) hdrlen = offsetof(struct ieee80211_mgmt, u.beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (len < fixedlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (ieee80211_hdrlen(mgmt->frame_control) != hdrlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) data += fixedlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) len -= fixedlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) for_each_element(elem, data, len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (for_each_element_completed(elem, data, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) NL_SET_ERR_MSG_ATTR(extack, attr, "malformed beacon head");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static int validate_ie_attr(const struct nlattr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) const u8 *data = nla_data(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) unsigned int len = nla_len(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) const struct element *elem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) for_each_element(elem, data, len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (for_each_element_completed(elem, data, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) NL_SET_ERR_MSG_ATTR(extack, attr, "malformed information elements");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /* policy for the attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) [NL80211_FTM_RESP_ATTR_ENABLED] = { .type = NLA_FLAG, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) [NL80211_FTM_RESP_ATTR_LCI] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) .len = U8_MAX },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) [NL80211_FTM_RESP_ATTR_CIVICLOC] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) .len = U8_MAX },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) NLA_POLICY_MAX(NLA_U8, 15),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) [NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) NLA_POLICY_MAX(NLA_U8, 15),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) [NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) NLA_POLICY_MAX(NLA_U8, 31),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) [NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) [NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) [NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) nl80211_pmsr_req_data_policy[NL80211_PMSR_TYPE_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) [NL80211_PMSR_TYPE_FTM] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) NLA_POLICY_NESTED(nl80211_pmsr_ftm_req_attr_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) nl80211_pmsr_req_attr_policy[NL80211_PMSR_REQ_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) [NL80211_PMSR_REQ_ATTR_DATA] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) NLA_POLICY_NESTED(nl80211_pmsr_req_data_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) [NL80211_PMSR_REQ_ATTR_GET_AP_TSF] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) nl80211_psmr_peer_attr_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) [NL80211_PMSR_PEER_ATTR_ADDR] = NLA_POLICY_ETH_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) [NL80211_PMSR_PEER_ATTR_CHAN] = NLA_POLICY_NESTED(nl80211_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) [NL80211_PMSR_PEER_ATTR_REQ] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) NLA_POLICY_NESTED(nl80211_pmsr_req_attr_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) [NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_REJECT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) nl80211_pmsr_attr_policy[NL80211_PMSR_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) [NL80211_PMSR_ATTR_MAX_PEERS] = { .type = NLA_REJECT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) [NL80211_PMSR_ATTR_REPORT_AP_TSF] = { .type = NLA_REJECT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) [NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR] = { .type = NLA_REJECT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) [NL80211_PMSR_ATTR_TYPE_CAPA] = { .type = NLA_REJECT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) [NL80211_PMSR_ATTR_PEERS] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) NLA_POLICY_NESTED_ARRAY(nl80211_psmr_peer_attr_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) he_obss_pd_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) [NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) NLA_POLICY_RANGE(NLA_U8, 1, 20),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) [NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) NLA_POLICY_RANGE(NLA_U8, 1, 20),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) [NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) NLA_POLICY_RANGE(NLA_U8, 1, 20),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) [NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) NLA_POLICY_EXACT_LEN(8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) [NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) NLA_POLICY_EXACT_LEN(8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) [NL80211_HE_OBSS_PD_ATTR_SR_CTRL] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) he_bss_color_policy[NL80211_HE_BSS_COLOR_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) [NL80211_HE_BSS_COLOR_ATTR_COLOR] = NLA_POLICY_RANGE(NLA_U8, 1, 63),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) [NL80211_HE_BSS_COLOR_ATTR_DISABLED] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) [NL80211_HE_BSS_COLOR_ATTR_PARTIAL] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) .len = NL80211_MAX_SUPP_RATES },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) [NL80211_TXRATE_HT] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) .len = NL80211_MAX_SUPP_HT_RATES },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) [NL80211_TXRATE_VHT] = NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_txrate_vht)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) [NL80211_TXRATE_GI] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) [NL80211_TXRATE_HE] = NLA_POLICY_EXACT_LEN(sizeof(struct nl80211_txrate_he)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) [NL80211_TXRATE_HE_GI] = NLA_POLICY_RANGE(NLA_U8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) NL80211_RATE_INFO_HE_GI_0_8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) NL80211_RATE_INFO_HE_GI_3_2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) [NL80211_TXRATE_HE_LTF] = NLA_POLICY_RANGE(NLA_U8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) NL80211_RATE_INFO_HE_1XLTF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) NL80211_RATE_INFO_HE_4XLTF),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) nl80211_tid_config_attr_policy[NL80211_TID_CONFIG_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) [NL80211_TID_CONFIG_ATTR_VIF_SUPP] = { .type = NLA_U64 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) [NL80211_TID_CONFIG_ATTR_PEER_SUPP] = { .type = NLA_U64 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) [NL80211_TID_CONFIG_ATTR_OVERRIDE] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) [NL80211_TID_CONFIG_ATTR_TIDS] = NLA_POLICY_RANGE(NLA_U16, 1, 0xff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) [NL80211_TID_CONFIG_ATTR_NOACK] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) [NL80211_TID_CONFIG_ATTR_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) [NL80211_TID_CONFIG_ATTR_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) [NL80211_TID_CONFIG_ATTR_AMPDU_CTRL] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) [NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) [NL80211_TID_CONFIG_ATTR_AMSDU_CTRL] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) [NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) NLA_POLICY_MAX(NLA_U8, NL80211_TX_RATE_FIXED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) [NL80211_TID_CONFIG_ATTR_TX_RATE] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) NLA_POLICY_NESTED(nl80211_txattr_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) nl80211_fils_discovery_policy[NL80211_FILS_DISCOVERY_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) [NL80211_FILS_DISCOVERY_ATTR_INT_MIN] = NLA_POLICY_MAX(NLA_U32, 10000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) [NL80211_FILS_DISCOVERY_ATTR_INT_MAX] = NLA_POLICY_MAX(NLA_U32, 10000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) NLA_POLICY_RANGE(NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) NL80211_FILS_DISCOVERY_TMPL_MIN_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) IEEE80211_MAX_DATA_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) nl80211_unsol_bcast_probe_resp_policy[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] = NLA_POLICY_MAX(NLA_U32, 20),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) .len = IEEE80211_MAX_DATA_LEN }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .len = 20-1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) [NL80211_ATTR_WIPHY_EDMG_CHANNELS] = NLA_POLICY_RANGE(NLA_U8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) NL80211_EDMG_CHANNELS_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) NL80211_EDMG_CHANNELS_MAX),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) [NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = NLA_POLICY_RANGE(NLA_U8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) NL80211_EDMG_BW_CONFIG_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) NL80211_EDMG_BW_CONFIG_MAX),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) [NL80211_ATTR_CENTER_FREQ1_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) [NL80211_ATTR_WIPHY_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) [NL80211_ATTR_WIPHY_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) [NL80211_ATTR_IFTYPE] = NLA_POLICY_MAX(NLA_U32, NL80211_IFTYPE_MAX),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) [NL80211_ATTR_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) [NL80211_ATTR_PREV_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) .len = WLAN_MAX_KEY_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) [NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) [NL80211_ATTR_KEY_TYPE] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) [NL80211_ATTR_BEACON_HEAD] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) IEEE80211_MAX_DATA_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) [NL80211_ATTR_BEACON_TAIL] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) IEEE80211_MAX_DATA_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) [NL80211_ATTR_STA_AID] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) .len = NL80211_MAX_SUPP_RATES },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) [NL80211_ATTR_STA_PLINK_ACTION] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_ACTIONS - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) [NL80211_ATTR_STA_TX_POWER_SETTING] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) NLA_POLICY_RANGE(NLA_U8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) NL80211_TX_POWER_AUTOMATIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) NL80211_TX_POWER_FIXED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) [NL80211_ATTR_STA_TX_POWER] = { .type = NLA_S16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) .len = IEEE80211_MAX_MESH_ID_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) [NL80211_ATTR_MPATH_NEXT_HOP] = NLA_POLICY_ETH_ADDR_COMPAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) /* allow 3 for NUL-termination, we used to declare this NLA_STRING */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) [NL80211_ATTR_REG_ALPHA2] = NLA_POLICY_RANGE(NLA_BINARY, 2, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) .len = NL80211_MAX_SUPP_RATES },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) [NL80211_ATTR_HT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_HT_CAPABILITY_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) [NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) validate_ie_attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) IEEE80211_MAX_DATA_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) [NL80211_ATTR_SSID] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) .len = IEEE80211_MAX_SSID_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) [NL80211_ATTR_USE_MFP] = NLA_POLICY_RANGE(NLA_U32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) NL80211_MFP_NO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) NL80211_MFP_OPTIONAL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) [NL80211_ATTR_STA_FLAGS2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) .len = sizeof(struct nl80211_sta_flag_update),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) [NL80211_ATTR_CONTROL_PORT_OVER_NL80211] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) [NL80211_ATTR_STATUS_CODE] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) [NL80211_ATTR_PID] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) [NL80211_ATTR_PMKID] = NLA_POLICY_EXACT_LEN_WARN(WLAN_PMKID_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) [NL80211_ATTR_DURATION] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) [NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) [NL80211_ATTR_FRAME] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) .len = IEEE80211_MAX_DATA_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) [NL80211_ATTR_PS_STATE] = NLA_POLICY_RANGE(NLA_U32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) NL80211_PS_DISABLED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) NL80211_PS_ENABLED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) [NL80211_ATTR_STA_PLINK_STATE] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_STATES - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) [NL80211_ATTR_MEASUREMENT_DURATION] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) [NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) [NL80211_ATTR_MESH_PEER_AID] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) [NL80211_ATTR_HIDDEN_SSID] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) NLA_POLICY_RANGE(NLA_U32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) NL80211_HIDDEN_SSID_NOT_IN_USE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) NL80211_HIDDEN_SSID_ZERO_CONTENTS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) [NL80211_ATTR_IE_PROBE_RESP] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) IEEE80211_MAX_DATA_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) [NL80211_ATTR_IE_ASSOC_RESP] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) IEEE80211_MAX_DATA_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) [NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) [NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) [NL80211_ATTR_TDLS_INITIATOR] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) .len = IEEE80211_MAX_DATA_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) [NL80211_ATTR_HT_CAPABILITY_MASK] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) .len = NL80211_HT_CAPABILITY_LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* need to include at least Auth Transaction and Status Code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) [NL80211_ATTR_AUTH_DATA] = NLA_POLICY_MIN_LEN(4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) [NL80211_ATTR_VHT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_VHT_CAPABILITY_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) [NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) [NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) [NL80211_ATTR_LOCAL_MESH_POWER_MODE] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) NLA_POLICY_RANGE(NLA_U32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) NL80211_MESH_POWER_UNKNOWN + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) NL80211_MESH_POWER_MAX),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) [NL80211_ATTR_VHT_CAPABILITY_MASK] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) .len = NL80211_VHT_CAPABILITY_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) [NL80211_ATTR_MDID] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) .len = IEEE80211_MAX_DATA_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) [NL80211_ATTR_CRIT_PROT_ID] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) [NL80211_ATTR_MAX_CRIT_PROT_DURATION] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) NLA_POLICY_MAX(NLA_U16, NL80211_CRIT_PROTO_MAX_DURATION),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) [NL80211_ATTR_PEER_AID] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) [NL80211_ATTR_CNTDWN_OFFS_BEACON] = { .type = NLA_BINARY },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) [NL80211_ATTR_CNTDWN_OFFS_PRESP] = { .type = NLA_BINARY },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = NLA_POLICY_MIN_LEN(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * The value of the Length field of the Supported Operating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * Classes element is between 2 and 253.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) NLA_POLICY_RANGE(NLA_BINARY, 2, 253),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) [NL80211_ATTR_QOS_MAP] = NLA_POLICY_RANGE(NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) IEEE80211_QOS_MAP_LEN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) IEEE80211_QOS_MAP_LEN_MAX),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) [NL80211_ATTR_MAC_HINT] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) [NL80211_ATTR_TSID] = NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_TIDS - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) [NL80211_ATTR_USER_PRIO] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) [NL80211_ATTR_OPER_CLASS] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) [NL80211_ATTR_MAC_MASK] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) [NL80211_ATTR_STA_SUPPORT_P2P_PS] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) NLA_POLICY_MAX(NLA_U8, NUM_NL80211_P2P_PS_STATUS - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) .len = VHT_MUMIMO_GROUPS_DATA_LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) [NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) [NL80211_ATTR_BANDS] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) .len = FILS_MAX_KEK_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) [NL80211_ATTR_FILS_NONCES] = NLA_POLICY_EXACT_LEN_WARN(2 * FILS_NONCE_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) [NL80211_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) [NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) .len = sizeof(struct nl80211_bss_select_rssi_adjust)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) [NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) [NL80211_ATTR_FILS_ERP_USERNAME] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) .len = FILS_ERP_MAX_USERNAME_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) [NL80211_ATTR_FILS_ERP_REALM] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) .len = FILS_ERP_MAX_REALM_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) [NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) [NL80211_ATTR_FILS_ERP_RRK] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) .len = FILS_ERP_MAX_RRK_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) [NL80211_ATTR_FILS_CACHE_ID] = NLA_POLICY_EXACT_LEN_WARN(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) [NL80211_ATTR_PMKR0_NAME] = NLA_POLICY_EXACT_LEN(WLAN_PMK_NAME_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) [NL80211_ATTR_HE_CAPABILITY] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) NLA_POLICY_RANGE(NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) NL80211_HE_MIN_CAPABILITY_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) NL80211_HE_MAX_CAPABILITY_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) [NL80211_ATTR_FTM_RESPONDER] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) NLA_POLICY_NESTED(nl80211_ftm_responder_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) [NL80211_ATTR_PEER_MEASUREMENTS] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) [NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) [NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) .len = SAE_PASSWORD_MAX_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) [NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) [NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) [NL80211_ATTR_TID_CONFIG] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) NLA_POLICY_NESTED_ARRAY(nl80211_tid_config_attr_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) [NL80211_ATTR_CONTROL_PORT_NO_PREAUTH] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) [NL80211_ATTR_PMK_LIFETIME] = NLA_POLICY_MIN(NLA_U32, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) [NL80211_ATTR_PMK_REAUTH_THRESHOLD] = NLA_POLICY_RANGE(NLA_U8, 1, 100),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) [NL80211_ATTR_RECEIVE_MULTICAST] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) [NL80211_ATTR_WIPHY_FREQ_OFFSET] = NLA_POLICY_RANGE(NLA_U32, 0, 999),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) [NL80211_ATTR_SCAN_FREQ_KHZ] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) [NL80211_ATTR_HE_6GHZ_CAPABILITY] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) NLA_POLICY_EXACT_LEN(sizeof(struct ieee80211_he_6ghz_capa)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) [NL80211_ATTR_FILS_DISCOVERY] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) NLA_POLICY_NESTED(nl80211_fils_discovery_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) [NL80211_ATTR_UNSOL_BCAST_PROBE_RESP] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) NLA_POLICY_NESTED(nl80211_unsol_bcast_probe_resp_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) [NL80211_ATTR_S1G_CAPABILITY] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) [NL80211_ATTR_S1G_CAPABILITY_MASK] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) [NL80211_ATTR_SAE_PWE] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) NL80211_SAE_PWE_BOTH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) /* policy for the key attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) [NL80211_KEY_IDX] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) [NL80211_KEY_CIPHER] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) [NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) [NL80211_KEY_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, NL80211_KEY_SET_TX),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) /* policy for the key default flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) [NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /* policy for WoWLAN attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) [NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) [NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) [NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) [NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) [NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) [NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) [NL80211_WOWLAN_TRIG_NET_DETECT] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) [NL80211_WOWLAN_TCP_SRC_IPV4] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) [NL80211_WOWLAN_TCP_DST_IPV4] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) [NL80211_WOWLAN_TCP_DST_MAC] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) [NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) [NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) [NL80211_WOWLAN_TCP_DATA_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) [NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) .len = sizeof(struct nl80211_wowlan_tcp_data_seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) [NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) .len = sizeof(struct nl80211_wowlan_tcp_data_token)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) [NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = NLA_POLICY_MIN_LEN(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) [NL80211_WOWLAN_TCP_WAKE_MASK] = NLA_POLICY_MIN_LEN(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) #endif /* CONFIG_PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) /* policy for coalesce rule attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) [NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) [NL80211_ATTR_COALESCE_RULE_CONDITION] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) NLA_POLICY_RANGE(NLA_U32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) NL80211_COALESCE_CONDITION_MATCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) NL80211_COALESCE_CONDITION_NO_MATCH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /* policy for GTK rekey offload attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) [NL80211_REKEY_DATA_KEK] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .len = NL80211_KEK_EXT_LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) [NL80211_REKEY_DATA_KCK] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) .len = NL80211_KCK_EXT_LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) [NL80211_REKEY_DATA_REPLAY_CTR] = NLA_POLICY_EXACT_LEN(NL80211_REPLAY_CTR_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) [NL80211_REKEY_DATA_AKM] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) nl80211_match_band_rssi_policy[NUM_NL80211_BANDS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) [NL80211_BAND_2GHZ] = { .type = NLA_S32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) [NL80211_BAND_5GHZ] = { .type = NLA_S32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) [NL80211_BAND_6GHZ] = { .type = NLA_S32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) [NL80211_BAND_60GHZ] = { .type = NLA_S32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) [NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) .len = IEEE80211_MAX_SSID_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) [NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) [NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) NLA_POLICY_NESTED(nl80211_match_band_rssi_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) [NL80211_SCHED_SCAN_PLAN_INTERVAL] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) [NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) [NL80211_BSS_SELECT_ATTR_RSSI] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) [NL80211_BSS_SELECT_ATTR_BAND_PREF] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) [NL80211_BSS_SELECT_ATTR_RSSI_ADJUST] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) .len = sizeof(struct nl80211_bss_select_rssi_adjust)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) /* policy for NAN function attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) [NL80211_NAN_FUNC_TYPE] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) NLA_POLICY_MAX(NLA_U8, NL80211_NAN_FUNC_MAX_TYPE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) [NL80211_NAN_FUNC_SERVICE_ID] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) .len = NL80211_NAN_FUNC_SERVICE_ID_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) [NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) [NL80211_NAN_FUNC_SERVICE_INFO] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) .len = NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) [NL80211_NAN_FUNC_SRF] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) [NL80211_NAN_FUNC_RX_MATCH_FILTER] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) [NL80211_NAN_FUNC_TX_MATCH_FILTER] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) [NL80211_NAN_FUNC_INSTANCE_ID] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) [NL80211_NAN_FUNC_TERM_REASON] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) /* policy for Service Response Filter attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) nl80211_nan_srf_policy[NL80211_NAN_SRF_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) [NL80211_NAN_SRF_INCLUDE] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) [NL80211_NAN_SRF_BF] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .len = NL80211_NAN_FUNC_SRF_MAX_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) [NL80211_NAN_SRF_BF_IDX] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) [NL80211_NAN_SRF_MAC_ADDRS] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) /* policy for packet pattern attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) [NL80211_PKTPAT_MASK] = { .type = NLA_BINARY, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) [NL80211_PKTPAT_PATTERN] = { .type = NLA_BINARY, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) struct cfg80211_registered_device **rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) struct wireless_dev **wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (!cb->args[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) struct nlattr **attrbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (!attrbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) err = nlmsg_parse_deprecated(cb->nlh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) GENL_HDRLEN + nl80211_fam.hdrsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) attrbuf, nl80211_fam.maxattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) nl80211_policy, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) kfree(attrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) *wdev = __cfg80211_wdev_from_attrs(sock_net(cb->skb->sk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) attrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) kfree(attrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (IS_ERR(*wdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return PTR_ERR(*wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) *rdev = wiphy_to_rdev((*wdev)->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) /* 0 is the first index - add 1 to parse only once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) cb->args[0] = (*rdev)->wiphy_idx + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) cb->args[1] = (*wdev)->identifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) /* subtract the 1 again here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct wireless_dev *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (!wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) *wdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) list_for_each_entry(tmp, &(*rdev)->wiphy.wdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (tmp->identifier == cb->args[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) *wdev = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (!*wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) /* message building helper */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) int flags, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) /* since there is no private header just add the generic one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) static int nl80211_msg_put_wmm_rules(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) const struct ieee80211_reg_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) struct nlattr *nl_wmm_rules =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) nla_nest_start_noflag(msg, NL80211_FREQUENCY_ATTR_WMM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (!nl_wmm_rules)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) for (j = 0; j < IEEE80211_NUM_ACS; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) struct nlattr *nl_wmm_rule = nla_nest_start_noflag(msg, j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (!nl_wmm_rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (nla_put_u16(msg, NL80211_WMMR_CW_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) rule->wmm_rule.client[j].cw_min) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) nla_put_u16(msg, NL80211_WMMR_CW_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) rule->wmm_rule.client[j].cw_max) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) nla_put_u8(msg, NL80211_WMMR_AIFSN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) rule->wmm_rule.client[j].aifsn) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) nla_put_u16(msg, NL80211_WMMR_TXOP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) rule->wmm_rule.client[j].cot))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) nla_nest_end(msg, nl_wmm_rule);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) nla_nest_end(msg, nl_wmm_rules);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) struct ieee80211_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) bool large)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) /* Some channels must be completely excluded from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) * list to protect old user-space tools from breaking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) if (!large && chan->flags &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) (IEEE80211_CHAN_NO_10MHZ | IEEE80211_CHAN_NO_20MHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (!large && chan->freq_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) chan->center_freq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_OFFSET, chan->freq_offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) if (chan->flags & IEEE80211_CHAN_NO_IR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (chan->flags & IEEE80211_CHAN_RADAR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (large) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) u32 time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) time = elapsed_jiffies_msecs(chan->dfs_state_entered);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) chan->dfs_state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) time))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) if (nla_put_u32(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) chan->dfs_cac_ms))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (large) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if ((chan->flags & IEEE80211_CHAN_INDOOR_ONLY) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_INDOOR_ONLY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if ((chan->flags & IEEE80211_CHAN_IR_CONCURRENT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_IR_CONCURRENT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if ((chan->flags & IEEE80211_CHAN_NO_20MHZ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_20MHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if ((chan->flags & IEEE80211_CHAN_NO_10MHZ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_10MHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if ((chan->flags & IEEE80211_CHAN_NO_HE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if ((chan->flags & IEEE80211_CHAN_1MHZ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_1MHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if ((chan->flags & IEEE80211_CHAN_2MHZ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_2MHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if ((chan->flags & IEEE80211_CHAN_4MHZ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_4MHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if ((chan->flags & IEEE80211_CHAN_8MHZ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_8MHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if ((chan->flags & IEEE80211_CHAN_16MHZ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_16MHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) DBM_TO_MBM(chan->max_power)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (large) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) const struct ieee80211_reg_rule *rule =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (!IS_ERR_OR_NULL(rule) && rule->has_wmm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (nl80211_msg_put_wmm_rules(msg, rule))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) static bool nl80211_put_txq_stats(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) struct cfg80211_txq_stats *txqstats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) int attrtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) struct nlattr *txqattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) #define PUT_TXQVAL_U32(attr, memb) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (txqstats->filled & BIT(NL80211_TXQ_STATS_ ## attr) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) nla_put_u32(msg, NL80211_TXQ_STATS_ ## attr, txqstats->memb)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return false; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) txqattr = nla_nest_start_noflag(msg, attrtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (!txqattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) PUT_TXQVAL_U32(BACKLOG_BYTES, backlog_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) PUT_TXQVAL_U32(BACKLOG_PACKETS, backlog_packets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) PUT_TXQVAL_U32(FLOWS, flows);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) PUT_TXQVAL_U32(DROPS, drops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) PUT_TXQVAL_U32(ECN_MARKS, ecn_marks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) PUT_TXQVAL_U32(OVERLIMIT, overlimit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) PUT_TXQVAL_U32(OVERMEMORY, overmemory);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) PUT_TXQVAL_U32(COLLISIONS, collisions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) PUT_TXQVAL_U32(TX_BYTES, tx_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) PUT_TXQVAL_U32(TX_PACKETS, tx_packets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) PUT_TXQVAL_U32(MAX_FLOWS, max_flows);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) nla_nest_end(msg, txqattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) #undef PUT_TXQVAL_U32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) /* netlink command implementations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) struct key_parse {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct key_params p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) bool def, defmgmt, defbeacon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) bool def_uni, def_multi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) struct key_parse *k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) struct nlattr *tb[NL80211_KEY_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) int err = nla_parse_nested_deprecated(tb, NL80211_KEY_MAX, key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) nl80211_key_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) k->def = !!tb[NL80211_KEY_DEFAULT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) k->defbeacon = !!tb[NL80211_KEY_DEFAULT_BEACON];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (k->def) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) k->def_uni = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) k->def_multi = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (k->defmgmt || k->defbeacon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) k->def_multi = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (tb[NL80211_KEY_IDX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (tb[NL80211_KEY_DATA]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) k->p.key = nla_data(tb[NL80211_KEY_DATA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) k->p.key_len = nla_len(tb[NL80211_KEY_DATA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) if (tb[NL80211_KEY_SEQ]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) k->p.seq = nla_data(tb[NL80211_KEY_SEQ]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) k->p.seq_len = nla_len(tb[NL80211_KEY_SEQ]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) if (tb[NL80211_KEY_CIPHER])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (tb[NL80211_KEY_TYPE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) if (tb[NL80211_KEY_DEFAULT_TYPES]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) err = nla_parse_nested_deprecated(kdt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) NUM_NL80211_KEY_DEFAULT_TYPES - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) tb[NL80211_KEY_DEFAULT_TYPES],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) nl80211_key_default_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (tb[NL80211_KEY_MODE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) k->p.mode = nla_get_u8(tb[NL80211_KEY_MODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (info->attrs[NL80211_ATTR_KEY_DATA]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) k->p.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) k->p.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) k->p.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) k->p.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if (info->attrs[NL80211_ATTR_KEY_IDX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) k->idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (info->attrs[NL80211_ATTR_KEY_CIPHER])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) k->p.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) if (k->def) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) k->def_uni = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) k->def_multi = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (k->defmgmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) k->def_multi = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) if (info->attrs[NL80211_ATTR_KEY_TYPE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) int err = nla_parse_nested_deprecated(kdt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) NUM_NL80211_KEY_DEFAULT_TYPES - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) nl80211_key_default_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) memset(k, 0, sizeof(*k));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) k->idx = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) k->type = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (info->attrs[NL80211_ATTR_KEY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) err = nl80211_parse_key_new(info, info->attrs[NL80211_ATTR_KEY], k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) err = nl80211_parse_key_old(info, k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) if ((k->def ? 1 : 0) + (k->defmgmt ? 1 : 0) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) (k->defbeacon ? 1 : 0) > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) GENL_SET_ERR_MSG(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) "key with multiple default flags is invalid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (k->defmgmt || k->defbeacon) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) if (k->def_uni || !k->def_multi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) GENL_SET_ERR_MSG(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) "defmgmt/defbeacon key must be mcast");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) if (k->idx != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (k->defmgmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) if (k->idx < 4 || k->idx > 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) GENL_SET_ERR_MSG(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) "defmgmt key idx not 4 or 5");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) } else if (k->defbeacon) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) if (k->idx < 6 || k->idx > 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) GENL_SET_ERR_MSG(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) "defbeacon key idx not 6 or 7");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) } else if (k->def) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) if (k->idx < 0 || k->idx > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) GENL_SET_ERR_MSG(info, "def key idx not 0-3");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (k->idx < 0 || k->idx > 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) GENL_SET_ERR_MSG(info, "key idx not 0-7");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) static struct cfg80211_cached_keys *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) struct genl_info *info, bool *no_ht)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) struct nlattr *keys = info->attrs[NL80211_ATTR_KEYS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) struct key_parse parse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) struct nlattr *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) struct cfg80211_cached_keys *result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) int rem, err, def = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) bool have_key = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) nla_for_each_nested(key, keys, rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) have_key = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) if (!have_key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) result = kzalloc(sizeof(*result), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) if (!result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) result->def = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) nla_for_each_nested(key, keys, rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) memset(&parse, 0, sizeof(parse));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) parse.idx = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) err = nl80211_parse_key_new(info, key, &parse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (!parse.p.key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if (parse.idx < 0 || parse.idx > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) GENL_SET_ERR_MSG(info, "key index out of range [0-3]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (parse.def) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) if (def) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) GENL_SET_ERR_MSG(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) "only one key can be default");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) def = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) result->def = parse.idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (!parse.def_uni || !parse.def_multi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) } else if (parse.defmgmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) err = cfg80211_validate_key_settings(rdev, &parse.p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) parse.idx, false, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) GENL_SET_ERR_MSG(info, "connect key must be WEP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) result->params[parse.idx].cipher = parse.p.cipher;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) result->params[parse.idx].key_len = parse.p.key_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) result->params[parse.idx].key = result->data[parse.idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /* must be WEP key if we got here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) if (no_ht)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) *no_ht = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (result->def < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) GENL_SET_ERR_MSG(info, "need a default/TX key");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) kfree(result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) static int nl80211_key_allowed(struct wireless_dev *wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) ASSERT_WDEV_LOCK(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) switch (wdev->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) case NL80211_IFTYPE_AP_VLAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) case NL80211_IFTYPE_MESH_POINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) case NL80211_IFTYPE_ADHOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) if (!wdev->current_bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) return -ENOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) case NL80211_IFTYPE_UNSPECIFIED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) case NL80211_IFTYPE_OCB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) case NL80211_IFTYPE_MONITOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) case NL80211_IFTYPE_NAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) case NL80211_IFTYPE_P2P_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) case NL80211_IFTYPE_WDS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) case NUM_NL80211_IFTYPES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) u32 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) struct ieee80211_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) chan = ieee80211_get_channel_khz(wiphy, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) return chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) struct nlattr *nl_modes = nla_nest_start_noflag(msg, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) if (!nl_modes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) while (ifmodes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) if ((ifmodes & 1) && nla_put_flag(msg, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) ifmodes >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) nla_nest_end(msg, nl_modes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) static int nl80211_put_iface_combinations(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) bool large)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) struct nlattr *nl_combis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) nl_combis = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) NL80211_ATTR_INTERFACE_COMBINATIONS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (!nl_combis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) for (i = 0; i < wiphy->n_iface_combinations; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) const struct ieee80211_iface_combination *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) struct nlattr *nl_combi, *nl_limits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) c = &wiphy->iface_combinations[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) nl_combi = nla_nest_start_noflag(msg, i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (!nl_combi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) nl_limits = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) NL80211_IFACE_COMB_LIMITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) if (!nl_limits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) for (j = 0; j < c->n_limits; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) struct nlattr *nl_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) nl_limit = nla_nest_start_noflag(msg, j + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) if (!nl_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) c->limits[j].max))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) c->limits[j].types))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) nla_nest_end(msg, nl_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) nla_nest_end(msg, nl_limits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) if (c->beacon_int_infra_match &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) c->num_different_channels) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) c->max_interfaces))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) if (large &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) c->radar_detect_widths) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) c->radar_detect_regions)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) if (c->beacon_int_min_gcd &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) c->beacon_int_min_gcd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) nla_nest_end(msg, nl_combi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) nla_nest_end(msg, nl_combis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) struct sk_buff *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan->tcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) struct nlattr *nl_tcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) if (!tcp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) nl_tcp = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) NL80211_WOWLAN_TRIG_TCP_CONNECTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) if (!nl_tcp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) tcp->data_payload_max))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) tcp->data_payload_max))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) sizeof(*tcp->tok), tcp->tok))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) tcp->data_interval_max))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) tcp->wake_payload_max))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) nla_nest_end(msg, nl_tcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) static int nl80211_send_wowlan(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) bool large)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) struct nlattr *nl_wowlan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) if (!rdev->wiphy.wowlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) nl_wowlan = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) if (!nl_wowlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) if (((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_ANY) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_DISCONNECT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) if (rdev->wiphy.wowlan->n_patterns) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) struct nl80211_pattern_support pat = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) .max_patterns = rdev->wiphy.wowlan->n_patterns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) .min_pattern_len = rdev->wiphy.wowlan->pattern_min_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) .max_pattern_len = rdev->wiphy.wowlan->pattern_max_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) .max_pkt_offset = rdev->wiphy.wowlan->max_pkt_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) sizeof(pat), &pat))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) if ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_NET_DETECT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) nla_put_u32(msg, NL80211_WOWLAN_TRIG_NET_DETECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) rdev->wiphy.wowlan->max_nd_match_sets))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) if (large && nl80211_send_wowlan_tcp_caps(rdev, msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) nla_nest_end(msg, nl_wowlan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) static int nl80211_send_coalesce(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) struct cfg80211_registered_device *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) struct nl80211_coalesce_rule_support rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) if (!rdev->wiphy.coalesce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) rule.max_rules = rdev->wiphy.coalesce->n_rules;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) rule.max_delay = rdev->wiphy.coalesce->max_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) rule.pat.max_patterns = rdev->wiphy.coalesce->n_patterns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) rule.pat.min_pattern_len = rdev->wiphy.coalesce->pattern_min_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) rule.pat.max_pattern_len = rdev->wiphy.coalesce->pattern_max_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) rule.pat.max_pkt_offset = rdev->wiphy.coalesce->max_pkt_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) nl80211_send_iftype_data(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) const struct ieee80211_supported_band *sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) const struct ieee80211_sband_iftype_data *iftdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) iftdata->types_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) if (he_cap->has_he) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) sizeof(he_cap->he_cap_elem.mac_cap_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) he_cap->he_cap_elem.mac_cap_info) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) sizeof(he_cap->he_cap_elem.phy_cap_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) he_cap->he_cap_elem.phy_cap_info) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) sizeof(he_cap->he_mcs_nss_supp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) &he_cap->he_mcs_nss_supp) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) sizeof(he_cap->ppe_thres), he_cap->ppe_thres))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) if (sband->band == NL80211_BAND_6GHZ &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) sizeof(iftdata->he_6ghz_capa),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) &iftdata->he_6ghz_capa))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) static int nl80211_send_band_rateinfo(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) struct ieee80211_supported_band *sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) bool large)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) struct nlattr *nl_rates, *nl_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) struct ieee80211_rate *rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) /* add HT info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) if (sband->ht_cap.ht_supported &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) sizeof(sband->ht_cap.mcs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) &sband->ht_cap.mcs) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) sband->ht_cap.cap) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) sband->ht_cap.ampdu_factor) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) sband->ht_cap.ampdu_density)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) /* add VHT info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) if (sband->vht_cap.vht_supported &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) sizeof(sband->vht_cap.vht_mcs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) &sband->vht_cap.vht_mcs) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) sband->vht_cap.cap)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) if (large && sband->n_iftype_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) struct nlattr *nl_iftype_data =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) NL80211_BAND_ATTR_IFTYPE_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) if (!nl_iftype_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) for (i = 0; i < sband->n_iftype_data; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) struct nlattr *iftdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) iftdata = nla_nest_start_noflag(msg, i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) if (!iftdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) err = nl80211_send_iftype_data(msg, sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) &sband->iftype_data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) nla_nest_end(msg, iftdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) nla_nest_end(msg, nl_iftype_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) /* add EDMG info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) if (large && sband->edmg_cap.channels &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) (nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) sband->edmg_cap.channels) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_BW_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) sband->edmg_cap.bw_config)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) /* add bitrates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) nl_rates = nla_nest_start_noflag(msg, NL80211_BAND_ATTR_RATES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) if (!nl_rates)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) for (i = 0; i < sband->n_bitrates; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) nl_rate = nla_nest_start_noflag(msg, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) if (!nl_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) rate = &sband->bitrates[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) rate->bitrate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) nla_put_flag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) nla_nest_end(msg, nl_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) nla_nest_end(msg, nl_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) nl80211_send_mgmt_stypes(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) const struct ieee80211_txrx_stypes *mgmt_stypes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) u16 stypes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) struct nlattr *nl_ftypes, *nl_ifs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) enum nl80211_iftype ift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) if (!mgmt_stypes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_TX_FRAME_TYPES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) if (!nl_ifs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) nl_ftypes = nla_nest_start_noflag(msg, ift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) if (!nl_ftypes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) stypes = mgmt_stypes[ift].tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) while (stypes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) if ((stypes & 1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) (i << 4) | IEEE80211_FTYPE_MGMT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) stypes >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) nla_nest_end(msg, nl_ftypes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) nla_nest_end(msg, nl_ifs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) nl_ifs = nla_nest_start_noflag(msg, NL80211_ATTR_RX_FRAME_TYPES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) if (!nl_ifs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) nl_ftypes = nla_nest_start_noflag(msg, ift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) if (!nl_ftypes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) stypes = mgmt_stypes[ift].rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) while (stypes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if ((stypes & 1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) (i << 4) | IEEE80211_FTYPE_MGMT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) stypes >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) nla_nest_end(msg, nl_ftypes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) nla_nest_end(msg, nl_ifs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) #define CMD(op, n) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) if (rdev->ops->op) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) i++; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) goto nla_put_failure; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) struct sk_buff *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) * do *NOT* add anything into this function, new things need to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) * advertised only to new versions of userspace that can deal with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) * the split (and they can't possibly care about new features...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) CMD(add_virtual_intf, NEW_INTERFACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) CMD(change_virtual_intf, SET_INTERFACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) CMD(add_key, NEW_KEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) CMD(start_ap, START_AP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) CMD(add_station, NEW_STATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) CMD(add_mpath, NEW_MPATH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) CMD(update_mesh_config, SET_MESH_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) CMD(change_bss, SET_BSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) CMD(auth, AUTHENTICATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) CMD(assoc, ASSOCIATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) CMD(deauth, DEAUTHENTICATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) CMD(disassoc, DISASSOCIATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) CMD(join_ibss, JOIN_IBSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) CMD(join_mesh, JOIN_MESH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) CMD(set_pmksa, SET_PMKSA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) CMD(del_pmksa, DEL_PMKSA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) CMD(flush_pmksa, FLUSH_PMKSA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) if (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) CMD(remain_on_channel, REMAIN_ON_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) CMD(mgmt_tx, FRAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) if (rdev->ops->set_monitor_channel || rdev->ops->start_ap ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) rdev->ops->join_mesh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) CMD(set_wds_peer, SET_WDS_PEER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) CMD(tdls_mgmt, TDLS_MGMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) CMD(tdls_oper, TDLS_OPER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) if (rdev->wiphy.max_sched_scan_reqs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) CMD(sched_scan_start, START_SCHED_SCAN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) CMD(probe_client, PROBE_CLIENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) CMD(set_noack_map, SET_NOACK_MAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) CMD(start_p2p_device, START_P2P_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) CMD(set_mcast_rate, SET_MCAST_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) #ifdef CONFIG_NL80211_TESTMODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) CMD(testmode_cmd, TESTMODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) if (rdev->ops->connect || rdev->ops->auth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) if (rdev->ops->disconnect || rdev->ops->deauth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) struct sk_buff *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) struct nlattr *ftm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) if (!cap->ftm.supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) ftm = nla_nest_start_noflag(msg, NL80211_PMSR_TYPE_FTM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) if (!ftm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) if (cap->ftm.asap && nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_ASAP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) if (cap->ftm.non_asap &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) if (cap->ftm.request_lci &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) if (cap->ftm.request_civicloc &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) cap->ftm.preambles))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) cap->ftm.bandwidths))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) if (cap->ftm.max_bursts_exponent >= 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) cap->ftm.max_bursts_exponent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) if (cap->ftm.max_ftms_per_burst &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) cap->ftm.max_ftms_per_burst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) if (cap->ftm.trigger_based &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) if (cap->ftm.non_trigger_based &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) nla_nest_end(msg, ftm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) struct sk_buff *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) const struct cfg80211_pmsr_capabilities *cap = rdev->wiphy.pmsr_capa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) struct nlattr *pmsr, *caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) if (!cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) * we don't need to clean up anything here since the caller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) * will genlmsg_cancel() if we fail
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) pmsr = nla_nest_start_noflag(msg, NL80211_ATTR_PEER_MEASUREMENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) if (!pmsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) if (nla_put_u32(msg, NL80211_PMSR_ATTR_MAX_PEERS, cap->max_peers))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) if (cap->report_ap_tsf &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) nla_put_flag(msg, NL80211_PMSR_ATTR_REPORT_AP_TSF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) if (cap->randomize_mac_addr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) nla_put_flag(msg, NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) caps = nla_nest_start_noflag(msg, NL80211_PMSR_ATTR_TYPE_CAPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) if (!caps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) if (nl80211_send_pmsr_ftm_capa(cap, msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) nla_nest_end(msg, caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) nla_nest_end(msg, pmsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) struct sk_buff *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) struct nlattr *nested, *nested_akms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) const struct wiphy_iftype_akm_suites *iftype_akms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) if (!rdev->wiphy.num_iftype_akm_suites ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) !rdev->wiphy.iftype_akm_suites)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) nested = nla_nest_start(msg, NL80211_ATTR_IFTYPE_AKM_SUITES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) if (!nested)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) for (i = 0; i < rdev->wiphy.num_iftype_akm_suites; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) nested_akms = nla_nest_start(msg, i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) if (!nested_akms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) iftype_akms = &rdev->wiphy.iftype_akm_suites[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) if (nl80211_put_iftypes(msg, NL80211_IFTYPE_AKM_ATTR_IFTYPES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) iftype_akms->iftypes_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) if (nla_put(msg, NL80211_IFTYPE_AKM_ATTR_SUITES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) sizeof(u32) * iftype_akms->n_akm_suites,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) iftype_akms->akm_suites)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) nla_nest_end(msg, nested_akms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) nla_nest_end(msg, nested);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) nl80211_put_tid_config_support(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) struct sk_buff *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) struct nlattr *supp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) if (!rdev->wiphy.tid_config_support.vif &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) !rdev->wiphy.tid_config_support.peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) supp = nla_nest_start(msg, NL80211_ATTR_TID_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) if (!supp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) if (rdev->wiphy.tid_config_support.vif &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_VIF_SUPP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) rdev->wiphy.tid_config_support.vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) NL80211_TID_CONFIG_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) if (rdev->wiphy.tid_config_support.peer &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_PEER_SUPP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) rdev->wiphy.tid_config_support.peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) NL80211_TID_CONFIG_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) /* for now we just use the same value ... makes more sense */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_SHORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) rdev->wiphy.tid_config_support.max_retry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_LONG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) rdev->wiphy.tid_config_support.max_retry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) nla_nest_end(msg, supp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) nla_nest_cancel(msg, supp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) struct nl80211_dump_wiphy_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) s64 filter_wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) long start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) long split_start, band_start, chan_start, capa_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) bool split;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) enum nl80211_commands cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) struct sk_buff *msg, u32 portid, u32 seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) int flags, struct nl80211_dump_wiphy_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) struct nlattr *nl_bands, *nl_band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) struct nlattr *nl_freqs, *nl_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) struct nlattr *nl_cmds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) enum nl80211_band band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) struct ieee80211_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) const struct ieee80211_txrx_stypes *mgmt_stypes =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) rdev->wiphy.mgmt_stypes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) u32 features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) if (WARN_ON(!state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) nla_put_string(msg, NL80211_ATTR_WIPHY_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) wiphy_name(&rdev->wiphy)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) nla_put_u32(msg, NL80211_ATTR_GENERATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) cfg80211_rdev_list_generation))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) if (cmd != NL80211_CMD_NEW_WIPHY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) goto finish;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) switch (state->split_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) rdev->wiphy.retry_short) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) rdev->wiphy.retry_long) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) rdev->wiphy.frag_threshold) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) rdev->wiphy.rts_threshold) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) rdev->wiphy.coverage_class) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) rdev->wiphy.max_scan_ssids) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) rdev->wiphy.max_sched_scan_ssids) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) rdev->wiphy.max_scan_ie_len) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) rdev->wiphy.max_sched_scan_ie_len) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) rdev->wiphy.max_match_sets))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) if ((rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) if ((rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) if ((rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) if (state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) sizeof(u32) * rdev->wiphy.n_cipher_suites,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) rdev->wiphy.cipher_suites))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) rdev->wiphy.max_num_pmkids))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) if ((rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) rdev->wiphy.available_antennas_tx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) rdev->wiphy.available_antennas_rx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) if ((rdev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) rdev->wiphy.probe_resp_offload))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) if ((rdev->wiphy.available_antennas_tx ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) rdev->wiphy.available_antennas_rx) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) rdev->ops->get_antenna) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) u32 tx_ant = 0, rx_ant = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) res = rdev_get_antenna(rdev, &tx_ant, &rx_ant);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) if (nla_put_u32(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) NL80211_ATTR_WIPHY_ANTENNA_TX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) tx_ant) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) nla_put_u32(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) NL80211_ATTR_WIPHY_ANTENNA_RX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) rx_ant))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) if (state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) rdev->wiphy.interface_modes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) if (state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) nl_bands = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) NL80211_ATTR_WIPHY_BANDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) if (!nl_bands)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) for (band = state->band_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) band < NUM_NL80211_BANDS; band++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) /* omit higher bands for ancient software */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) if (band > NL80211_BAND_5GHZ && !state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) sband = rdev->wiphy.bands[band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) nl_band = nla_nest_start_noflag(msg, band);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) if (!nl_band)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) switch (state->chan_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) if (nl80211_send_band_rateinfo(msg, sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) state->split))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) state->chan_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) if (state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) /* add frequencies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) nl_freqs = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) NL80211_BAND_ATTR_FREQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) if (!nl_freqs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) for (i = state->chan_start - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) i < sband->n_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) nl_freq = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) if (!nl_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) chan = &sband->channels[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) if (nl80211_msg_put_channel(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) msg, &rdev->wiphy, chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) state->split))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) nla_nest_end(msg, nl_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) if (state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) if (i < sband->n_channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) state->chan_start = i + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) state->chan_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) nla_nest_end(msg, nl_freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) nla_nest_end(msg, nl_band);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) if (state->split) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) /* start again here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) if (state->chan_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) band--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) nla_nest_end(msg, nl_bands);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) if (band < NUM_NL80211_BANDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) state->band_start = band + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) state->band_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) /* if bands & channels are done, continue outside */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) if (state->band_start == 0 && state->chan_start == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) if (state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) nl_cmds = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) NL80211_ATTR_SUPPORTED_COMMANDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) if (!nl_cmds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) i = nl80211_add_commands_unsplit(rdev, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) if (i < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) if (state->split) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) CMD(crit_proto_start, CRIT_PROTOCOL_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) CMD(channel_switch, CHANNEL_SWITCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) CMD(set_qos_map, SET_QOS_MAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) if (rdev->wiphy.features &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) CMD(add_tx_ts, ADD_TX_TS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) CMD(update_ft_ies, UPDATE_FT_IES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) #undef CMD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) nla_nest_end(msg, nl_cmds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) if (state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) if (rdev->ops->remain_on_channel &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) nla_put_u32(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) rdev->wiphy.max_remain_on_channel_duration))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) if ((rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) if (state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) if (nl80211_send_wowlan(msg, rdev, state->split))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) if (state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) rdev->wiphy.software_iftypes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) if (nl80211_put_iface_combinations(&rdev->wiphy, msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) state->split))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) if (state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) rdev->wiphy.ap_sme_capa))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) features = rdev->wiphy.features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) * We can only add the per-channel limit information if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) * dump is split, otherwise it makes it too big. Therefore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) * only advertise it in that case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) if (state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) if (rdev->wiphy.ht_capa_mod_mask &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) sizeof(*rdev->wiphy.ht_capa_mod_mask),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) rdev->wiphy.ht_capa_mod_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) if (rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) rdev->wiphy.max_acl_mac_addrs &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) rdev->wiphy.max_acl_mac_addrs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) * Any information below this point is only available to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) * applications that can deal with it being split. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) * helps ensure that newly added capabilities don't break
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) * older tools by overrunning their buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) * We still increment split_start so that in the split
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) * case we'll continue with more data in the next round,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) * but break unconditionally so unsplit data stops here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) if (state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) state->split_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) case 9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) if (nla_put_u32(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) rdev->wiphy.max_sched_scan_plans) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) rdev->wiphy.max_sched_scan_plan_interval) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) rdev->wiphy.max_sched_scan_plan_iterations))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) if (rdev->wiphy.extended_capabilities &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) (nla_put(msg, NL80211_ATTR_EXT_CAPA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) rdev->wiphy.extended_capabilities_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) rdev->wiphy.extended_capabilities) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) rdev->wiphy.extended_capabilities_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) rdev->wiphy.extended_capabilities_mask)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) if (rdev->wiphy.vht_capa_mod_mask &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) sizeof(*rdev->wiphy.vht_capa_mod_mask),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) rdev->wiphy.vht_capa_mod_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) rdev->wiphy.perm_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) if (!is_zero_ether_addr(rdev->wiphy.addr_mask) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) rdev->wiphy.addr_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) if (rdev->wiphy.n_addresses > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) void *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) attr = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) if (!attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) for (i = 0; i < rdev->wiphy.n_addresses; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) if (nla_put(msg, i + 1, ETH_ALEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) rdev->wiphy.addresses[i].addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) nla_nest_end(msg, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) case 10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) if (nl80211_send_coalesce(msg, rdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) if (rdev->wiphy.max_ap_assoc_sta &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) rdev->wiphy.max_ap_assoc_sta))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) case 11:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) if (rdev->wiphy.n_vendor_commands) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) const struct nl80211_vendor_cmd_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) struct nlattr *nested;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) nested = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) NL80211_ATTR_VENDOR_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) if (!nested)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) info = &rdev->wiphy.vendor_commands[i].info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) if (nla_put(msg, i + 1, sizeof(*info), info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) nla_nest_end(msg, nested);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) if (rdev->wiphy.n_vendor_events) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) const struct nl80211_vendor_cmd_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) struct nlattr *nested;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) nested = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) NL80211_ATTR_VENDOR_EVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) if (!nested)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) for (i = 0; i < rdev->wiphy.n_vendor_events; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) info = &rdev->wiphy.vendor_events[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) if (nla_put(msg, i + 1, sizeof(*info), info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) nla_nest_end(msg, nested);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) case 12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) rdev->wiphy.max_num_csa_counters))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) if (rdev->wiphy.max_sched_scan_reqs &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_MAX_REQS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) rdev->wiphy.max_sched_scan_reqs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) if (nla_put(msg, NL80211_ATTR_EXT_FEATURES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) sizeof(rdev->wiphy.ext_features),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) rdev->wiphy.ext_features))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) if (rdev->wiphy.bss_select_support) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) struct nlattr *nested;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) u32 bss_select_support = rdev->wiphy.bss_select_support;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) nested = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) NL80211_ATTR_BSS_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) if (!nested)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) while (bss_select_support) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) if ((bss_select_support & 1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) nla_put_flag(msg, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) bss_select_support >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) nla_nest_end(msg, nested);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) case 13:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) if (rdev->wiphy.num_iftype_ext_capab &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) rdev->wiphy.iftype_ext_capab) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) struct nlattr *nested_ext_capab, *nested;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) nested = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) NL80211_ATTR_IFTYPE_EXT_CAPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) if (!nested)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) for (i = state->capa_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) i < rdev->wiphy.num_iftype_ext_capab; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) const struct wiphy_iftype_ext_capab *capab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) capab = &rdev->wiphy.iftype_ext_capab[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) nested_ext_capab = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) if (!nested_ext_capab ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) nla_put_u32(msg, NL80211_ATTR_IFTYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) capab->iftype) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) nla_put(msg, NL80211_ATTR_EXT_CAPA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) capab->extended_capabilities_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) capab->extended_capabilities) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) capab->extended_capabilities_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) capab->extended_capabilities_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) nla_nest_end(msg, nested_ext_capab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) if (state->split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) nla_nest_end(msg, nested);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) if (i < rdev->wiphy.num_iftype_ext_capab) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) state->capa_start = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) if (nla_put_u32(msg, NL80211_ATTR_BANDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) rdev->wiphy.nan_supported_bands))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) if (wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) NL80211_EXT_FEATURE_TXQS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) struct cfg80211_txq_stats txqstats = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) res = rdev_get_txq_stats(rdev, NULL, &txqstats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) if (!res &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) !nl80211_put_txq_stats(msg, &txqstats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) NL80211_ATTR_TXQ_STATS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) if (nla_put_u32(msg, NL80211_ATTR_TXQ_LIMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) rdev->wiphy.txq_limit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) if (nla_put_u32(msg, NL80211_ATTR_TXQ_MEMORY_LIMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) rdev->wiphy.txq_memory_limit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) if (nla_put_u32(msg, NL80211_ATTR_TXQ_QUANTUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) rdev->wiphy.txq_quantum))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) case 14:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) if (nl80211_send_pmsr_capa(rdev, msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) state->split_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) case 15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) if (rdev->wiphy.akm_suites &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) nla_put(msg, NL80211_ATTR_AKM_SUITES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) sizeof(u32) * rdev->wiphy.n_akm_suites,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) rdev->wiphy.akm_suites))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) if (nl80211_put_iftype_akm_suites(rdev, msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) if (nl80211_put_tid_config_support(rdev, msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) /* done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) state->split_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) finish:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) struct netlink_callback *cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) struct nl80211_dump_wiphy_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) struct nlattr **tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) if (!tb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) ret = nlmsg_parse_deprecated(cb->nlh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) GENL_HDRLEN + nl80211_fam.hdrsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) tb, nl80211_fam.maxattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) nl80211_policy, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) /* ignore parse errors for backward compatibility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) if (tb[NL80211_ATTR_WIPHY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) state->filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) if (tb[NL80211_ATTR_WDEV])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) state->filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) if (tb[NL80211_ATTR_IFINDEX]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) struct net_device *netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) if (!netdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) if (netdev->ieee80211_ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) rdev = wiphy_to_rdev(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) netdev->ieee80211_ptr->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) state->filter_wiphy = rdev->wiphy_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) kfree(tb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) int idx = 0, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) struct nl80211_dump_wiphy_state *state = (void *)cb->args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) if (!state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) state = kzalloc(sizeof(*state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) if (!state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) state->filter_wiphy = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) ret = nl80211_dump_wiphy_parse(skb, cb, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) cb->args[0] = (long)state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) if (++idx <= state->start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) if (state->filter_wiphy != -1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) state->filter_wiphy != rdev->wiphy_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) /* attempt to fit multiple wiphy data chunks into the skb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) ret = nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) cb->nlh->nlmsg_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) NLM_F_MULTI, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) * If sending the wiphy data didn't fit (ENOBUFS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) * or EMSGSIZE returned), this SKB is still
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) * empty (so it's not too big because another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) * wiphy dataset is already in the skb) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) * we've not tried to adjust the dump allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) * yet ... then adjust the alloc size to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) * bigger, and return 1 but with the empty skb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) * This results in an empty message being RX'ed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) * in userspace, but that is ignored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) * We can then retry with the larger buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) !skb->len && !state->split &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) cb->min_dump_alloc < 4096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) cb->min_dump_alloc = 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) state->split_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) idx--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) } while (state->split_start > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) state->start = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) static int nl80211_dump_wiphy_done(struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) kfree((void *)cb->args[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) struct nl80211_dump_wiphy_state state = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) msg = nlmsg_new(4096, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) if (nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY, msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) &state) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) static int parse_txq_params(struct nlattr *tb[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) struct ieee80211_txq_params *txq_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) u8 ac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) !tb[NL80211_TXQ_ATTR_AIFS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) if (ac >= NL80211_NUM_ACS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) txq_params->ac = array_index_nospec(ac, NL80211_NUM_ACS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) * You can only set the channel explicitly for WDS interfaces,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) * all others have their channel managed via their respective
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) * "establish a connection" command (connect, join, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) * For AP/GO and mesh mode, the channel can be set with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) * channel userspace API, but is only stored and passed to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) * low-level driver when the AP starts or the mesh is joined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) * This is for backward compatibility, userspace can also give
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) * the channel in the start-ap or join-mesh commands instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) * Monitors are special as they are normally slaved to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) * whatever else is going on, so they have their own special
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) * operation to set the monitor channel if possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) return !wdev ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) wdev->iftype == NL80211_IFTYPE_AP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) wdev->iftype == NL80211_IFTYPE_MONITOR ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) wdev->iftype == NL80211_IFTYPE_P2P_GO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) struct cfg80211_chan_def *chandef)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) struct netlink_ext_ack *extack = info->extack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) struct nlattr **attrs = info->attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) u32 control_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) if (!attrs[NL80211_ATTR_WIPHY_FREQ])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) control_freq = MHZ_TO_KHZ(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) control_freq +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) memset(chandef, 0, sizeof(*chandef));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) chandef->chan = ieee80211_get_channel_khz(&rdev->wiphy, control_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) chandef->center_freq1 = KHZ_TO_MHZ(control_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) chandef->freq1_offset = control_freq % 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) chandef->center_freq2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) /* Primary channel not allowed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) NL_SET_ERR_MSG_ATTR(extack, attrs[NL80211_ATTR_WIPHY_FREQ],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) "Channel is disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) enum nl80211_channel_type chantype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) chantype = nla_get_u32(attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) switch (chantype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) case NL80211_CHAN_NO_HT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) case NL80211_CHAN_HT20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) case NL80211_CHAN_HT40PLUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) case NL80211_CHAN_HT40MINUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) cfg80211_chandef_create(chandef, chandef->chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) chantype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) /* user input for center_freq is incorrect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) if (attrs[NL80211_ATTR_CENTER_FREQ1] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) chandef->center_freq1 != nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) NL_SET_ERR_MSG_ATTR(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) attrs[NL80211_ATTR_CENTER_FREQ1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) "bad center frequency 1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) /* center_freq2 must be zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) if (attrs[NL80211_ATTR_CENTER_FREQ2] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) NL_SET_ERR_MSG_ATTR(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) attrs[NL80211_ATTR_CENTER_FREQ2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) "center frequency 2 can't be used");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) NL_SET_ERR_MSG_ATTR(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) "invalid channel type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) } else if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) chandef->width =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) if (attrs[NL80211_ATTR_CENTER_FREQ1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) chandef->center_freq1 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) if (attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) chandef->freq1_offset = nla_get_u32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) attrs[NL80211_ATTR_CENTER_FREQ1_OFFSET]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) chandef->freq1_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) if (attrs[NL80211_ATTR_CENTER_FREQ2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) chandef->center_freq2 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) chandef->edmg.channels =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) chandef->edmg.bw_config =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) chandef->edmg.bw_config = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) chandef->edmg.channels = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) if (!cfg80211_chandef_valid(chandef)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) NL_SET_ERR_MSG(extack, "invalid channel definition");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) IEEE80211_CHAN_DISABLED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) NL_SET_ERR_MSG(extack, "(extension) channel is disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) chandef->width == NL80211_CHAN_WIDTH_10) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) NL_SET_ERR_MSG(extack, "5/10 MHz not supported");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) struct cfg80211_chan_def chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) struct wireless_dev *wdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) if (dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) if (!nl80211_can_set_dev_channel(wdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) if (wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) iftype = wdev->iftype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) result = nl80211_parse_chandef(rdev, info, &chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) switch (iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) iftype)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) result = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) if (wdev->beacon_interval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) if (!dev || !rdev->ops->set_ap_chanwidth ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) !(rdev->wiphy.features &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) result = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) /* Only allow dynamic channel width changes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) if (chandef.chan != wdev->preset_chandef.chan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) result = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) result = rdev_set_ap_chanwidth(rdev, dev, &chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) wdev->preset_chandef = chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) case NL80211_IFTYPE_MESH_POINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) result = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) case NL80211_IFTYPE_MONITOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) result = cfg80211_set_monitor_channel(rdev, &chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) result = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) struct net_device *netdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) return __nl80211_set_channel(rdev, netdev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) const u8 *bssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) if (netif_running(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) if (!rdev->ops->set_wds_peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) if (wdev->iftype != NL80211_IFTYPE_WDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) return rdev_set_wds_peer(rdev, dev, bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) struct net_device *netdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) int result = 0, rem_txq_params = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) struct nlattr *nl_txq_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) u32 changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) u8 retry_short = 0, retry_long = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) u32 frag_threshold = 0, rts_threshold = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) u8 coverage_class = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) * Try to find the wiphy and netdev. Normally this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) * function shouldn't need the netdev, but this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) * done for backward compatibility -- previously
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) * setting the channel was done per wiphy, but now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) * it is per netdev. Previous userland like hostapd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) * also passed a netdev to set_wiphy, so that it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) * possible to let that go to the right netdev!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) if (info->attrs[NL80211_ATTR_IFINDEX]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) netdev = __dev_get_by_index(genl_info_net(info), ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) if (netdev && netdev->ieee80211_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) rdev = wiphy_to_rdev(netdev->ieee80211_ptr->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) netdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) if (!netdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) info->attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) if (IS_ERR(rdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) return PTR_ERR(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) wdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) netdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) wdev = netdev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) * end workaround code, by now the rdev is available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) * and locked, and wdev may or may not be NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) if (info->attrs[NL80211_ATTR_WIPHY_NAME])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) result = cfg80211_dev_rename(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) struct ieee80211_txq_params txq_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) if (!rdev->ops->set_txq_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) if (!netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) if (!netif_running(netdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) return -ENETDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) nla_for_each_nested(nl_txq_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) rem_txq_params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) result = nla_parse_nested_deprecated(tb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) NL80211_TXQ_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) nl_txq_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) txq_params_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) result = parse_txq_params(tb, &txq_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) result = rdev_set_txq_params(rdev, netdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) &txq_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) result = __nl80211_set_channel(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) nl80211_can_set_dev_channel(wdev) ? netdev : NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) struct wireless_dev *txp_wdev = wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) enum nl80211_tx_power_setting type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) int idx, mbm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) txp_wdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) if (!rdev->ops->set_tx_power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) type = nla_get_u32(info->attrs[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) (type != NL80211_TX_POWER_AUTOMATIC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) if (type != NL80211_TX_POWER_AUTOMATIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) mbm = nla_get_u32(info->attrs[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) result = rdev_set_tx_power(rdev, txp_wdev, type, mbm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) u32 tx_ant, rx_ant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) if ((!rdev->wiphy.available_antennas_tx &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) !rdev->wiphy.available_antennas_rx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) !rdev->ops->set_antenna)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) /* reject antenna configurations which don't match the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) * available antenna masks, except for the "all" mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) result = rdev_set_antenna(rdev, tx_ant, rx_ant);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) retry_short = nla_get_u8(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) changed |= WIPHY_PARAM_RETRY_SHORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) retry_long = nla_get_u8(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) changed |= WIPHY_PARAM_RETRY_LONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) frag_threshold = nla_get_u32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) if (frag_threshold < 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) if (frag_threshold != (u32) -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) * Fragments (apart from the last one) are required to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) * have even length. Make the fragmentation code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) * simpler by stripping LSB should someone try to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) * odd threshold value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) frag_threshold &= ~0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) changed |= WIPHY_PARAM_FRAG_THRESHOLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) rts_threshold = nla_get_u32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) changed |= WIPHY_PARAM_RTS_THRESHOLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) coverage_class = nla_get_u8(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) changed |= WIPHY_PARAM_COVERAGE_CLASS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) changed |= WIPHY_PARAM_DYN_ACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) NL80211_EXT_FEATURE_TXQS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) txq_limit = nla_get_u32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) info->attrs[NL80211_ATTR_TXQ_LIMIT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) changed |= WIPHY_PARAM_TXQ_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) NL80211_EXT_FEATURE_TXQS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) txq_memory_limit = nla_get_u32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) NL80211_EXT_FEATURE_TXQS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) txq_quantum = nla_get_u32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) changed |= WIPHY_PARAM_TXQ_QUANTUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) if (changed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) u8 old_retry_short, old_retry_long;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) u32 old_frag_threshold, old_rts_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) u8 old_coverage_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348) if (!rdev->ops->set_wiphy_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) old_retry_short = rdev->wiphy.retry_short;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) old_retry_long = rdev->wiphy.retry_long;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) old_frag_threshold = rdev->wiphy.frag_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) old_rts_threshold = rdev->wiphy.rts_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) old_coverage_class = rdev->wiphy.coverage_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) old_txq_limit = rdev->wiphy.txq_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) old_txq_memory_limit = rdev->wiphy.txq_memory_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) old_txq_quantum = rdev->wiphy.txq_quantum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) if (changed & WIPHY_PARAM_RETRY_SHORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) rdev->wiphy.retry_short = retry_short;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) if (changed & WIPHY_PARAM_RETRY_LONG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) rdev->wiphy.retry_long = retry_long;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) rdev->wiphy.frag_threshold = frag_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) if (changed & WIPHY_PARAM_RTS_THRESHOLD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) rdev->wiphy.rts_threshold = rts_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) if (changed & WIPHY_PARAM_COVERAGE_CLASS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) rdev->wiphy.coverage_class = coverage_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) if (changed & WIPHY_PARAM_TXQ_LIMIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) rdev->wiphy.txq_limit = txq_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) if (changed & WIPHY_PARAM_TXQ_MEMORY_LIMIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) rdev->wiphy.txq_memory_limit = txq_memory_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) if (changed & WIPHY_PARAM_TXQ_QUANTUM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) rdev->wiphy.txq_quantum = txq_quantum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) result = rdev_set_wiphy_params(rdev, changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) rdev->wiphy.retry_short = old_retry_short;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) rdev->wiphy.retry_long = old_retry_long;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) rdev->wiphy.frag_threshold = old_frag_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) rdev->wiphy.rts_threshold = old_rts_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) rdev->wiphy.coverage_class = old_coverage_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) rdev->wiphy.txq_limit = old_txq_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) rdev->wiphy.txq_quantum = old_txq_quantum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) static int nl80211_send_chandef(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) const struct cfg80211_chan_def *chandef)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) if (WARN_ON(!cfg80211_chandef_valid(chandef)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) chandef->chan->center_freq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) chandef->chan->freq_offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) switch (chandef->width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) case NL80211_CHAN_WIDTH_20_NOHT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) case NL80211_CHAN_WIDTH_20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) case NL80211_CHAN_WIDTH_40:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) cfg80211_get_chandef_type(chandef)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) if (chandef->center_freq2 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) enum nl80211_commands cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) struct net_device *dev = wdev->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) cmd != NL80211_CMD_DEL_INTERFACE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) cmd != NL80211_CMD_SET_INTERFACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) if (dev &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) NL80211_ATTR_PAD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) nla_put_u32(msg, NL80211_ATTR_GENERATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) rdev->devlist_generation ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) (cfg80211_rdev_list_generation << 2)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) if (rdev->ops->get_channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) struct cfg80211_chan_def chandef = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) ret = rdev_get_channel(rdev, wdev, &chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) if (nl80211_send_chandef(msg, &chandef))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) if (rdev->ops->get_tx_power) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) int dbm, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) ret = rdev_get_tx_power(rdev, wdev, &dbm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) if (ret == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474) nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) DBM_TO_MBM(dbm)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) switch (wdev->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) if (wdev->ssid_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) nla_put(msg, NL80211_ATTR_SSID, wdev->ssid_len, wdev->ssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) goto nla_put_failure_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) case NL80211_IFTYPE_ADHOC: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) const u8 *ssid_ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) if (!wdev->current_bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) ssid_ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) WLAN_EID_SSID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) if (ssid_ie &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) nla_put(msg, NL80211_ATTR_SSID, ssid_ie[1], ssid_ie + 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) goto nla_put_failure_rcu_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) /* nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) if (rdev->ops->get_txq_stats) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) struct cfg80211_txq_stats txqstats = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) int ret = rdev_get_txq_stats(rdev, wdev, &txqstats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) if (ret == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) !nl80211_put_txq_stats(msg, &txqstats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) NL80211_ATTR_TXQ_STATS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) nla_put_failure_rcu_locked:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) nla_put_failure_locked:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) int wp_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) int if_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) int wp_start = cb->args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) int if_start = cb->args[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) int filter_wiphy = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) if (!cb->args[2]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) struct nl80211_dump_wiphy_state state = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) .filter_wiphy = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) ret = nl80211_dump_wiphy_parse(skb, cb, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) filter_wiphy = state.filter_wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) * if filtering, set cb->args[2] to +1 since 0 is the default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) * value needed to determine that parsing is necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556) if (filter_wiphy >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) cb->args[2] = filter_wiphy + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) cb->args[2] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) } else if (cb->args[2] > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) filter_wiphy = cb->args[2] - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565) if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) if (wp_idx < wp_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) wp_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) if (filter_wiphy >= 0 && filter_wiphy != rdev->wiphy_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) if_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) if (if_idx < if_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) if_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) cb->nlh->nlmsg_seq, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) rdev, wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) NL80211_CMD_NEW_INTERFACE) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) if_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) wp_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) cb->args[0] = wp_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) cb->args[1] = if_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597) ret = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625) [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) int flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637) *mntrflags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) if (!nla)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642) if (nla_parse_nested_deprecated(flags, NL80211_MNTR_FLAG_MAX, nla, mntr_flags_policy, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646) if (flags[flag])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) *mntrflags |= (1<<flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649) *mntrflags |= MONITOR_FLAG_CHANGED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654) static int nl80211_parse_mon_options(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655) enum nl80211_iftype type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656) struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657) struct vif_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659) bool change = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662) if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663) if (type != NL80211_IFTYPE_MONITOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) ¶ms->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671) change = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) if (params->flags & MONITOR_FLAG_ACTIVE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675) !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678) if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679) const u8 *mumimo_groups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682) if (type != NL80211_IFTYPE_MONITOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685) if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) mumimo_groups =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689) nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) /* bits 0 and 63 are reserved and must be zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692) if ((mumimo_groups[0] & BIT(0)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(7)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) params->vht_mumimo_groups = mumimo_groups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) change = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703) if (type != NL80211_IFTYPE_MONITOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709) params->vht_mumimo_follow_addr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) nla_data(info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) change = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) return change ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718) struct net_device *netdev, u8 use_4addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719) enum nl80211_iftype iftype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721) if (!use_4addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722) if (netdev && netif_is_bridge_port(netdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727) switch (iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) case NL80211_IFTYPE_AP_VLAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743) static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) struct vif_params params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748) enum nl80211_iftype otype, ntype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750) bool change = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) memset(¶ms, 0, sizeof(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) otype = ntype = dev->ieee80211_ptr->iftype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756) if (info->attrs[NL80211_ATTR_IFTYPE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) if (otype != ntype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759) change = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762) if (info->attrs[NL80211_ATTR_MESH_ID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) if (ntype != NL80211_IFTYPE_MESH_POINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) if (netif_running(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771) BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) IEEE80211_MAX_MESH_ID_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773) wdev->mesh_id_up_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774) nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775) memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) wdev->mesh_id_up_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) if (info->attrs[NL80211_ATTR_4ADDR]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781) params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) change = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783) err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787) params.use_4addr = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790) err = nl80211_parse_mon_options(rdev, ntype, info, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793) if (err > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) change = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) if (change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797) err = cfg80211_change_iface(rdev, dev, ntype, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801) if (!err && params.use_4addr != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802) dev->ieee80211_ptr->use_4addr = params.use_4addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) if (change && !err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807) nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) struct vif_params params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820) enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822) /* to avoid failing a new interface creation due to pending removal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823) cfg80211_destroy_ifaces(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) memset(¶ms, 0, sizeof(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) if (!info->attrs[NL80211_ATTR_IFNAME])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830) if (info->attrs[NL80211_ATTR_IFTYPE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) if (!rdev->ops->add_virtual_intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837) rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) info->attrs[NL80211_ATTR_MAC]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839) nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840) ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) if (!is_valid_ether_addr(params.macaddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) return -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) if (info->attrs[NL80211_ATTR_4ADDR]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852) if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) err = nl80211_parse_mon_options(rdev, type, info, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863) wdev = rdev_add_virtual_intf(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864) nla_data(info->attrs[NL80211_ATTR_IFNAME]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) NET_NAME_USER, type, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) if (WARN_ON(!wdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868) return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869) } else if (IS_ERR(wdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) return PTR_ERR(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874) if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875) wdev->owner_nlportid = info->snd_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878) case NL80211_IFTYPE_MESH_POINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879) if (!info->attrs[NL80211_ATTR_MESH_ID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) IEEE80211_MAX_MESH_ID_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884) wdev->mesh_id_up_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886) memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) wdev->mesh_id_up_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890) case NL80211_IFTYPE_NAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) case NL80211_IFTYPE_P2P_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893) * P2P Device and NAN do not have a netdev, so don't go
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) * through the netdev notifier and must be added here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896) cfg80211_init_wdev(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) cfg80211_register_wdev(rdev, wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903) if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904) rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912) static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917) if (!rdev->ops->del_virtual_intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921) * If we remove a wireless device without a netdev then clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922) * user_ptr[1] so that nl80211_post_doit won't dereference it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923) * to check if it needs to do dev_put(). Otherwise it crashes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924) * since the wdev has been freed, unlike with a netdev where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925) * we need the dev_put() for the netdev to really be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927) if (!wdev->netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928) info->user_ptr[1] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930) return rdev_del_virtual_intf(rdev, wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933) static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937) u16 noack_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939) if (!info->attrs[NL80211_ATTR_NOACK_MAP])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942) if (!rdev->ops->set_noack_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945) noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947) return rdev_set_noack_map(rdev, dev, noack_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950) struct get_key_cookie {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956) static void get_key_callback(void *c, struct key_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958) struct nlattr *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959) struct get_key_cookie *cookie = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961) if ((params->key &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962) nla_put(cookie->msg, NL80211_ATTR_KEY_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963) params->key_len, params->key)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964) (params->seq &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965) nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966) params->seq_len, params->seq)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967) (params->cipher &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968) nla_put_u32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) params->cipher)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972) key = nla_nest_start_noflag(cookie->msg, NL80211_ATTR_KEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973) if (!key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976) if ((params->key &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977) nla_put(cookie->msg, NL80211_KEY_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978) params->key_len, params->key)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) (params->seq &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980) nla_put(cookie->msg, NL80211_KEY_SEQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981) params->seq_len, params->seq)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982) (params->cipher &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983) nla_put_u32(cookie->msg, NL80211_KEY_CIPHER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984) params->cipher)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987) if (nla_put_u8(cookie->msg, NL80211_KEY_IDX, cookie->idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990) nla_nest_end(cookie->msg, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994) cookie->error = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997) static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) u8 key_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003) const u8 *mac_addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) bool pairwise;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005) struct get_key_cookie cookie = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006) .error = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010) bool bigtk_support = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012) if (wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013) NL80211_EXT_FEATURE_BEACON_PROTECTION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014) bigtk_support = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016) if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017) dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018) wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019) NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020) bigtk_support = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022) if (info->attrs[NL80211_ATTR_KEY_IDX]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025) if (key_idx >= 6 && key_idx <= 7 && !bigtk_support) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026) GENL_SET_ERR_MSG(info, "BIGTK not supported");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4031) if (info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4032) mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4034) pairwise = !!mac_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4035) if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4036) u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4038) if (kt != NL80211_KEYTYPE_GROUP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4039) kt != NL80211_KEYTYPE_PAIRWISE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4040) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4041) pairwise = kt == NL80211_KEYTYPE_PAIRWISE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4044) if (!rdev->ops->get_key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4045) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4047) if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4048) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4050) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4051) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4052) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4054) hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4055) NL80211_CMD_NEW_KEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4056) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4057) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4059) cookie.msg = msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4060) cookie.idx = key_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4062) if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4063) nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4064) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4065) if (mac_addr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4066) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4067) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4069) err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4070) get_key_callback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4072) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4073) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4075) if (cookie.error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4076) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4078) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4079) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4081) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4082) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4083) free_msg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4084) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4085) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4088) static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4089) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4090) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4091) struct key_parse key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4092) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4093) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4095) err = nl80211_parse_key(info, &key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4096) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4097) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4099) if (key.idx < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4100) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4102) /* Only support setting default key and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4103) * Extended Key ID action NL80211_KEY_SET_TX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4105) if (!key.def && !key.defmgmt && !key.defbeacon &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4106) !(key.p.mode == NL80211_KEY_SET_TX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4107) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4109) wdev_lock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4111) if (key.def) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4112) if (!rdev->ops->set_default_key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4113) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4114) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4117) err = nl80211_key_allowed(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4118) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4119) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4121) err = rdev_set_default_key(rdev, dev, key.idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4122) key.def_uni, key.def_multi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4124) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4125) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4127) #ifdef CONFIG_CFG80211_WEXT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4128) dev->ieee80211_ptr->wext.default_key = key.idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4129) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4130) } else if (key.defmgmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4131) if (key.def_uni || !key.def_multi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4132) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4133) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4136) if (!rdev->ops->set_default_mgmt_key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4137) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4138) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4141) err = nl80211_key_allowed(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4142) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4143) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4145) err = rdev_set_default_mgmt_key(rdev, dev, key.idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4146) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4147) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4149) #ifdef CONFIG_CFG80211_WEXT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4150) dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4151) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4152) } else if (key.defbeacon) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4153) if (key.def_uni || !key.def_multi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4154) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4155) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4158) if (!rdev->ops->set_default_beacon_key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4159) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4160) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4163) err = nl80211_key_allowed(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4164) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4165) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4167) err = rdev_set_default_beacon_key(rdev, dev, key.idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4168) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4169) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4170) } else if (key.p.mode == NL80211_KEY_SET_TX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4171) wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4172) NL80211_EXT_FEATURE_EXT_KEY_ID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4173) u8 *mac_addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4175) if (info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4176) mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4178) if (!mac_addr || key.idx < 0 || key.idx > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4179) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4180) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4183) err = rdev_add_key(rdev, dev, key.idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4184) NL80211_KEYTYPE_PAIRWISE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4185) mac_addr, &key.p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4186) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4187) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4189) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4190) wdev_unlock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4192) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4195) static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4197) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4198) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4199) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4200) struct key_parse key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4201) const u8 *mac_addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4203) err = nl80211_parse_key(info, &key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4204) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4205) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4207) if (!key.p.key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4208) GENL_SET_ERR_MSG(info, "no key");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4209) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4212) if (info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4213) mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4215) if (key.type == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4216) if (mac_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4217) key.type = NL80211_KEYTYPE_PAIRWISE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4218) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4219) key.type = NL80211_KEYTYPE_GROUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4222) /* for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4223) if (key.type != NL80211_KEYTYPE_PAIRWISE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4224) key.type != NL80211_KEYTYPE_GROUP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4225) GENL_SET_ERR_MSG(info, "key type not pairwise or group");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4226) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4229) if (key.type == NL80211_KEYTYPE_GROUP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4230) info->attrs[NL80211_ATTR_VLAN_ID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4231) key.p.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4233) if (!rdev->ops->add_key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4234) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4236) if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4237) key.type == NL80211_KEYTYPE_PAIRWISE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4238) mac_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4239) GENL_SET_ERR_MSG(info, "key setting validation failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4240) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4243) wdev_lock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4244) err = nl80211_key_allowed(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4245) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4246) GENL_SET_ERR_MSG(info, "key not allowed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4247) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4248) err = rdev_add_key(rdev, dev, key.idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4249) key.type == NL80211_KEYTYPE_PAIRWISE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4250) mac_addr, &key.p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4251) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4252) GENL_SET_ERR_MSG(info, "key addition failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4254) wdev_unlock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4256) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4259) static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4261) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4262) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4263) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4264) u8 *mac_addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4265) struct key_parse key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4267) err = nl80211_parse_key(info, &key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4268) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4269) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4271) if (info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4272) mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4274) if (key.type == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4275) if (mac_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4276) key.type = NL80211_KEYTYPE_PAIRWISE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4277) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4278) key.type = NL80211_KEYTYPE_GROUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4281) /* for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4282) if (key.type != NL80211_KEYTYPE_PAIRWISE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4283) key.type != NL80211_KEYTYPE_GROUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4284) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4286) if (!cfg80211_valid_key_idx(rdev, key.idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4287) key.type == NL80211_KEYTYPE_PAIRWISE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4288) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4290) if (!rdev->ops->del_key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4291) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4293) wdev_lock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4294) err = nl80211_key_allowed(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4296) if (key.type == NL80211_KEYTYPE_GROUP && mac_addr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4297) !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4298) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4300) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4301) err = rdev_del_key(rdev, dev, key.idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4302) key.type == NL80211_KEYTYPE_PAIRWISE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4303) mac_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4305) #ifdef CONFIG_CFG80211_WEXT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4306) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4307) if (key.idx == dev->ieee80211_ptr->wext.default_key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4308) dev->ieee80211_ptr->wext.default_key = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4309) else if (key.idx == dev->ieee80211_ptr->wext.default_mgmt_key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4310) dev->ieee80211_ptr->wext.default_mgmt_key = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4312) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4313) wdev_unlock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4315) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4318) /* This function returns an error or the number of nested attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4319) static int validate_acl_mac_addrs(struct nlattr *nl_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4321) struct nlattr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4322) int n_entries = 0, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4324) nla_for_each_nested(attr, nl_attr, tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4325) if (nla_len(attr) != ETH_ALEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4326) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4328) n_entries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4331) return n_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4334) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4335) * This function parses ACL information and allocates memory for ACL data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4336) * On successful return, the calling function is responsible to free the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4337) * ACL buffer returned by this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4338) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4339) static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4340) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4342) enum nl80211_acl_policy acl_policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4343) struct nlattr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4344) struct cfg80211_acl_data *acl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4345) int i = 0, n_entries, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4347) if (!wiphy->max_acl_mac_addrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4348) return ERR_PTR(-EOPNOTSUPP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4350) if (!info->attrs[NL80211_ATTR_ACL_POLICY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4351) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4353) acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4354) if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4355) acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4356) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4358) if (!info->attrs[NL80211_ATTR_MAC_ADDRS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4359) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4361) n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4362) if (n_entries < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4363) return ERR_PTR(n_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4365) if (n_entries > wiphy->max_acl_mac_addrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4366) return ERR_PTR(-ENOTSUPP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4368) acl = kzalloc(struct_size(acl, mac_addrs, n_entries), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4369) if (!acl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4370) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4372) nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4373) memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4374) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4377) acl->n_acl_entries = n_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4378) acl->acl_policy = acl_policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4380) return acl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4383) static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4385) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4386) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4387) struct cfg80211_acl_data *acl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4388) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4390) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4391) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4392) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4394) if (!dev->ieee80211_ptr->beacon_interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4395) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4397) acl = parse_acl_data(&rdev->wiphy, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4398) if (IS_ERR(acl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4399) return PTR_ERR(acl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4401) err = rdev_set_mac_acl(rdev, dev, acl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4403) kfree(acl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4405) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4408) static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4409) u8 *rates, u8 rates_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4411) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4412) u32 mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4414) for (i = 0; i < rates_len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4415) int rate = (rates[i] & 0x7f) * 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4416) int ridx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4418) for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4419) struct ieee80211_rate *srate =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4420) &sband->bitrates[ridx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4421) if (rate == srate->bitrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4422) mask |= 1 << ridx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4423) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4426) if (ridx == sband->n_bitrates)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4427) return 0; /* rate not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4430) return mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4433) static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4434) u8 *rates, u8 rates_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4435) u8 mcs[IEEE80211_HT_MCS_MASK_LEN])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4437) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4439) memset(mcs, 0, IEEE80211_HT_MCS_MASK_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4441) for (i = 0; i < rates_len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4442) int ridx, rbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4444) ridx = rates[i] / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4445) rbit = BIT(rates[i] % 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4447) /* check validity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4448) if ((ridx < 0) || (ridx >= IEEE80211_HT_MCS_MASK_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4449) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4451) /* check availability */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4452) ridx = array_index_nospec(ridx, IEEE80211_HT_MCS_MASK_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4453) if (sband->ht_cap.mcs.rx_mask[ridx] & rbit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4454) mcs[ridx] |= rbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4455) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4456) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4459) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4462) static u16 vht_mcs_map_to_mcs_mask(u8 vht_mcs_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4464) u16 mcs_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4466) switch (vht_mcs_map) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4467) case IEEE80211_VHT_MCS_NOT_SUPPORTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4468) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4469) case IEEE80211_VHT_MCS_SUPPORT_0_7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4470) mcs_mask = 0x00FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4471) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4472) case IEEE80211_VHT_MCS_SUPPORT_0_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4473) mcs_mask = 0x01FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4474) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4475) case IEEE80211_VHT_MCS_SUPPORT_0_9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4476) mcs_mask = 0x03FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4477) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4478) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4479) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4482) return mcs_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4485) static void vht_build_mcs_mask(u16 vht_mcs_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4486) u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4488) u8 nss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4490) for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4491) vht_mcs_mask[nss] = vht_mcs_map_to_mcs_mask(vht_mcs_map & 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4492) vht_mcs_map >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4496) static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4497) struct nl80211_txrate_vht *txrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4498) u16 mcs[NL80211_VHT_NSS_MAX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4500) u16 tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4501) u16 tx_mcs_mask[NL80211_VHT_NSS_MAX] = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4502) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4504) if (!sband->vht_cap.vht_supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4505) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4507) memset(mcs, 0, sizeof(u16) * NL80211_VHT_NSS_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4509) /* Build vht_mcs_mask from VHT capabilities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4510) vht_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4512) for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4513) if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4514) mcs[i] = txrate->mcs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4515) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4516) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4519) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4522) static u16 he_mcs_map_to_mcs_mask(u8 he_mcs_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4524) switch (he_mcs_map) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4525) case IEEE80211_HE_MCS_NOT_SUPPORTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4526) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4527) case IEEE80211_HE_MCS_SUPPORT_0_7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4528) return 0x00FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4529) case IEEE80211_HE_MCS_SUPPORT_0_9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4530) return 0x03FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4531) case IEEE80211_HE_MCS_SUPPORT_0_11:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4532) return 0xFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4533) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4534) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4536) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4539) static void he_build_mcs_mask(u16 he_mcs_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4540) u16 he_mcs_mask[NL80211_HE_NSS_MAX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4542) u8 nss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4544) for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4545) he_mcs_mask[nss] = he_mcs_map_to_mcs_mask(he_mcs_map & 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4546) he_mcs_map >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4550) static u16 he_get_txmcsmap(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4551) const struct ieee80211_sta_he_cap *he_cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4553) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4554) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4555) __le16 tx_mcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4557) switch (wdev->chandef.width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4558) case NL80211_CHAN_WIDTH_80P80:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4559) tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80p80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4560) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4561) case NL80211_CHAN_WIDTH_160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4562) tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_160;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4563) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4564) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4565) tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4566) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4568) return le16_to_cpu(tx_mcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4571) static bool he_set_mcs_mask(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4572) struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4573) struct ieee80211_supported_band *sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4574) struct nl80211_txrate_he *txrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4575) u16 mcs[NL80211_HE_NSS_MAX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4577) const struct ieee80211_sta_he_cap *he_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4578) u16 tx_mcs_mask[NL80211_HE_NSS_MAX] = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4579) u16 tx_mcs_map = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4580) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4582) he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4583) if (!he_cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4584) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4586) memset(mcs, 0, sizeof(u16) * NL80211_HE_NSS_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4588) tx_mcs_map = he_get_txmcsmap(info, he_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4590) /* Build he_mcs_mask from HE capabilities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4591) he_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4593) for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4594) if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4595) mcs[i] = txrate->mcs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4596) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4597) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4600) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4603) static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4604) struct nlattr *attrs[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4605) enum nl80211_attrs attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4606) struct cfg80211_bitrate_mask *mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4607) struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4609) struct nlattr *tb[NL80211_TXRATE_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4610) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4611) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4612) int rem, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4613) struct nlattr *tx_rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4614) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4615) u16 vht_tx_mcs_map, he_tx_mcs_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4617) memset(mask, 0, sizeof(*mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4618) /* Default to all rates enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4619) for (i = 0; i < NUM_NL80211_BANDS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4620) const struct ieee80211_sta_he_cap *he_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4622) sband = rdev->wiphy.bands[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4624) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4625) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4627) mask->control[i].legacy = (1 << sband->n_bitrates) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4628) memcpy(mask->control[i].ht_mcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4629) sband->ht_cap.mcs.rx_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4630) sizeof(mask->control[i].ht_mcs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4632) if (sband->vht_cap.vht_supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4633) vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4634) vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4637) he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4638) if (!he_cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4639) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4641) he_tx_mcs_map = he_get_txmcsmap(info, he_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4642) he_build_mcs_mask(he_tx_mcs_map, mask->control[i].he_mcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4644) mask->control[i].he_gi = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4645) mask->control[i].he_ltf = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4648) /* if no rates are given set it back to the defaults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4649) if (!attrs[attr])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4650) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4652) /* The nested attribute uses enum nl80211_band as the index. This maps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4653) * directly to the enum nl80211_band values used in cfg80211.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4654) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4655) BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4656) nla_for_each_nested(tx_rates, attrs[attr], rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4657) enum nl80211_band band = nla_type(tx_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4658) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4660) if (band < 0 || band >= NUM_NL80211_BANDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4661) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4662) sband = rdev->wiphy.bands[band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4663) if (sband == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4664) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4665) err = nla_parse_nested_deprecated(tb, NL80211_TXRATE_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4666) tx_rates,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4667) nl80211_txattr_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4668) info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4669) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4670) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4671) if (tb[NL80211_TXRATE_LEGACY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4672) mask->control[band].legacy = rateset_to_mask(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4673) sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4674) nla_data(tb[NL80211_TXRATE_LEGACY]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4675) nla_len(tb[NL80211_TXRATE_LEGACY]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4676) if ((mask->control[band].legacy == 0) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4677) nla_len(tb[NL80211_TXRATE_LEGACY]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4678) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4680) if (tb[NL80211_TXRATE_HT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4681) if (!ht_rateset_to_mask(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4682) sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4683) nla_data(tb[NL80211_TXRATE_HT]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4684) nla_len(tb[NL80211_TXRATE_HT]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4685) mask->control[band].ht_mcs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4686) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4688) if (tb[NL80211_TXRATE_VHT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4689) if (!vht_set_mcs_mask(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4690) sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4691) nla_data(tb[NL80211_TXRATE_VHT]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4692) mask->control[band].vht_mcs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4693) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4695) if (tb[NL80211_TXRATE_GI]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4696) mask->control[band].gi =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4697) nla_get_u8(tb[NL80211_TXRATE_GI]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4698) if (mask->control[band].gi > NL80211_TXRATE_FORCE_LGI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4699) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4701) if (tb[NL80211_TXRATE_HE] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4702) !he_set_mcs_mask(info, wdev, sband,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4703) nla_data(tb[NL80211_TXRATE_HE]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4704) mask->control[band].he_mcs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4705) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4706) if (tb[NL80211_TXRATE_HE_GI])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4707) mask->control[band].he_gi =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4708) nla_get_u8(tb[NL80211_TXRATE_HE_GI]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4709) if (tb[NL80211_TXRATE_HE_LTF])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4710) mask->control[band].he_ltf =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4711) nla_get_u8(tb[NL80211_TXRATE_HE_LTF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4713) if (mask->control[band].legacy == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4714) /* don't allow empty legacy rates if HT, VHT or HE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4715) * are not even supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4716) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4717) if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4718) rdev->wiphy.bands[band]->vht_cap.vht_supported ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4719) ieee80211_get_he_iftype_cap(sband, wdev->iftype)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4720) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4722) for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4723) if (mask->control[band].ht_mcs[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4724) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4726) for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4727) if (mask->control[band].vht_mcs[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4728) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4730) for (i = 0; i < NL80211_HE_NSS_MAX; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4731) if (mask->control[band].he_mcs[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4732) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4734) /* legacy and mcs rates may not be both empty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4735) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4739) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4740) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4743) static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4744) enum nl80211_band band,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4745) struct cfg80211_bitrate_mask *beacon_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4746) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4747) u32 count_ht, count_vht, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4748) u32 rate = beacon_rate->control[band].legacy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4750) /* Allow only one rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4751) if (hweight32(rate) > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4752) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4754) count_ht = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4755) for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4756) if (hweight8(beacon_rate->control[band].ht_mcs[i]) > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4757) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4758) } else if (beacon_rate->control[band].ht_mcs[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4759) count_ht++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4760) if (count_ht > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4761) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4763) if (count_ht && rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4764) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4767) count_vht = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4768) for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4769) if (hweight16(beacon_rate->control[band].vht_mcs[i]) > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4770) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4771) } else if (beacon_rate->control[band].vht_mcs[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4772) count_vht++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4773) if (count_vht > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4774) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4776) if (count_vht && rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4777) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4780) if ((count_ht && count_vht) || (!rate && !count_ht && !count_vht))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4781) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4783) if (rate &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4784) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4785) NL80211_EXT_FEATURE_BEACON_RATE_LEGACY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4786) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4787) if (count_ht &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4788) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4789) NL80211_EXT_FEATURE_BEACON_RATE_HT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4790) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4791) if (count_vht &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4792) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4793) NL80211_EXT_FEATURE_BEACON_RATE_VHT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4794) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4796) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4799) static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4800) struct nlattr *attrs[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4801) struct cfg80211_beacon_data *bcn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4803) bool haveinfo = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4804) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4806) memset(bcn, 0, sizeof(*bcn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4808) if (attrs[NL80211_ATTR_BEACON_HEAD]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4809) bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4810) bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4811) if (!bcn->head_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4812) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4813) haveinfo = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4816) if (attrs[NL80211_ATTR_BEACON_TAIL]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4817) bcn->tail = nla_data(attrs[NL80211_ATTR_BEACON_TAIL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4818) bcn->tail_len = nla_len(attrs[NL80211_ATTR_BEACON_TAIL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4819) haveinfo = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4822) if (!haveinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4823) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4825) if (attrs[NL80211_ATTR_IE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4826) bcn->beacon_ies = nla_data(attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4827) bcn->beacon_ies_len = nla_len(attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4830) if (attrs[NL80211_ATTR_IE_PROBE_RESP]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4831) bcn->proberesp_ies =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4832) nla_data(attrs[NL80211_ATTR_IE_PROBE_RESP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4833) bcn->proberesp_ies_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4834) nla_len(attrs[NL80211_ATTR_IE_PROBE_RESP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4837) if (attrs[NL80211_ATTR_IE_ASSOC_RESP]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4838) bcn->assocresp_ies =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4839) nla_data(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4840) bcn->assocresp_ies_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4841) nla_len(attrs[NL80211_ATTR_IE_ASSOC_RESP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4844) if (attrs[NL80211_ATTR_PROBE_RESP]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4845) bcn->probe_resp = nla_data(attrs[NL80211_ATTR_PROBE_RESP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4846) bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4849) if (attrs[NL80211_ATTR_FTM_RESPONDER]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4850) struct nlattr *tb[NL80211_FTM_RESP_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4852) err = nla_parse_nested_deprecated(tb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4853) NL80211_FTM_RESP_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4854) attrs[NL80211_ATTR_FTM_RESPONDER],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4855) NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4856) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4857) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4859) if (tb[NL80211_FTM_RESP_ATTR_ENABLED] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4860) wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4861) NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4862) bcn->ftm_responder = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4863) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4864) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4866) if (tb[NL80211_FTM_RESP_ATTR_LCI]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4867) bcn->lci = nla_data(tb[NL80211_FTM_RESP_ATTR_LCI]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4868) bcn->lci_len = nla_len(tb[NL80211_FTM_RESP_ATTR_LCI]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4871) if (tb[NL80211_FTM_RESP_ATTR_CIVICLOC]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4872) bcn->civicloc = nla_data(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4873) bcn->civicloc_len = nla_len(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4875) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4876) bcn->ftm_responder = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4879) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4882) static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4883) struct ieee80211_he_obss_pd *he_obss_pd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4885) struct nlattr *tb[NL80211_HE_OBSS_PD_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4886) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4888) err = nla_parse_nested(tb, NL80211_HE_OBSS_PD_ATTR_MAX, attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4889) he_obss_pd_policy, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4890) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4891) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4893) if (!tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4894) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4896) he_obss_pd->sr_ctrl = nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4898) if (tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4899) he_obss_pd->min_offset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4900) nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4901) if (tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4902) he_obss_pd->max_offset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4903) nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4904) if (tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4905) he_obss_pd->non_srg_max_offset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4906) nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4908) if (he_obss_pd->min_offset > he_obss_pd->max_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4909) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4911) if (tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4912) memcpy(he_obss_pd->bss_color_bitmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4913) nla_data(tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4914) sizeof(he_obss_pd->bss_color_bitmap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4916) if (tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4917) memcpy(he_obss_pd->partial_bssid_bitmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4918) nla_data(tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4919) sizeof(he_obss_pd->partial_bssid_bitmap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4921) he_obss_pd->enable = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4923) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4926) static int nl80211_parse_he_bss_color(struct nlattr *attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4927) struct cfg80211_he_bss_color *he_bss_color)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4929) struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4930) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4932) err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4933) he_bss_color_policy, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4934) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4935) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4937) if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4938) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4940) he_bss_color->color =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4941) nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4942) he_bss_color->enabled =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4943) !nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4944) he_bss_color->partial =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4945) nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4947) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4950) static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4951) struct nlattr *attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4952) struct cfg80211_ap_settings *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4954) struct nlattr *tb[NL80211_FILS_DISCOVERY_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4955) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4956) struct cfg80211_fils_discovery *fd = ¶ms->fils_discovery;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4958) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4959) NL80211_EXT_FEATURE_FILS_DISCOVERY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4960) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4962) ret = nla_parse_nested(tb, NL80211_FILS_DISCOVERY_ATTR_MAX, attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4963) NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4964) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4965) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4967) if (!tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4968) !tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4969) !tb[NL80211_FILS_DISCOVERY_ATTR_TMPL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4970) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4972) fd->tmpl_len = nla_len(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4973) fd->tmpl = nla_data(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4974) fd->min_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4975) fd->max_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4977) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4980) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4981) nl80211_parse_unsol_bcast_probe_resp(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4982) struct nlattr *attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4983) struct cfg80211_ap_settings *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4985) struct nlattr *tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4986) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4987) struct cfg80211_unsol_bcast_probe_resp *presp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4988) ¶ms->unsol_bcast_probe_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4990) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4991) NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4992) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4994) ret = nla_parse_nested(tb, NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4995) attrs, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4996) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4997) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4999) if (!tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5000) !tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5001) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5003) presp->tmpl = nla_data(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5004) presp->tmpl_len = nla_len(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5005) presp->interval = nla_get_u32(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5006) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5009) static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5010) const u8 *rates)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5012) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5014) if (!rates)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5015) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5017) for (i = 0; i < rates[1]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5018) if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5019) params->ht_required = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5020) if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5021) params->vht_required = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5022) if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_HE_PHY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5023) params->he_required = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5027) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5028) * Since the nl80211 API didn't include, from the beginning, attributes about
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5029) * HT/VHT requirements/capabilities, we parse them out of the IEs for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5030) * benefit of drivers that rebuild IEs in the firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5031) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5032) static void nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5033) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5034) const struct cfg80211_beacon_data *bcn = ¶ms->beacon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5035) size_t ies_len = bcn->tail_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5036) const u8 *ies = bcn->tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5037) const u8 *rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5038) const u8 *cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5040) rates = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies, ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5041) nl80211_check_ap_rate_selectors(params, rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5043) rates = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, ies, ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5044) nl80211_check_ap_rate_selectors(params, rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5046) cap = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5047) if (cap && cap[1] >= sizeof(*params->ht_cap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5048) params->ht_cap = (void *)(cap + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5049) cap = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, ies, ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5050) if (cap && cap[1] >= sizeof(*params->vht_cap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5051) params->vht_cap = (void *)(cap + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5052) cap = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, ies, ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5053) if (cap && cap[1] >= sizeof(*params->he_cap) + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5054) params->he_cap = (void *)(cap + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5055) cap = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_OPERATION, ies, ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5056) if (cap && cap[1] >= sizeof(*params->he_oper) + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5057) params->he_oper = (void *)(cap + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5060) static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5061) struct cfg80211_ap_settings *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5062) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5063) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5064) bool ret = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5066) list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5067) if (wdev->iftype != NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5068) wdev->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5069) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5071) if (!wdev->preset_chandef.chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5072) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5074) params->chandef = wdev->preset_chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5075) ret = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5076) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5079) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5082) static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5083) enum nl80211_auth_type auth_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5084) enum nl80211_commands cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5085) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5086) if (auth_type > NL80211_AUTHTYPE_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5087) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5089) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5090) case NL80211_CMD_AUTHENTICATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5091) if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5092) auth_type == NL80211_AUTHTYPE_SAE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5093) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5094) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5095) NL80211_EXT_FEATURE_FILS_STA) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5096) (auth_type == NL80211_AUTHTYPE_FILS_SK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5097) auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5098) auth_type == NL80211_AUTHTYPE_FILS_PK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5099) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5100) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5101) case NL80211_CMD_CONNECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5102) if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5103) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5104) NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5105) auth_type == NL80211_AUTHTYPE_SAE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5106) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5108) /* FILS with SK PFS or PK not supported yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5109) if (auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5110) auth_type == NL80211_AUTHTYPE_FILS_PK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5111) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5112) if (!wiphy_ext_feature_isset(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5113) &rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5114) NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5115) auth_type == NL80211_AUTHTYPE_FILS_SK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5116) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5117) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5118) case NL80211_CMD_START_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5119) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5120) NL80211_EXT_FEATURE_SAE_OFFLOAD_AP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5121) auth_type == NL80211_AUTHTYPE_SAE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5122) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5123) /* FILS not supported yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5124) if (auth_type == NL80211_AUTHTYPE_FILS_SK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5125) auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5126) auth_type == NL80211_AUTHTYPE_FILS_PK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5127) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5128) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5129) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5130) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5134) static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5136) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5137) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5138) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5139) struct cfg80211_ap_settings params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5140) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5142) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5143) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5144) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5146) if (!rdev->ops->start_ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5147) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5149) if (wdev->beacon_interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5150) return -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5152) memset(¶ms, 0, sizeof(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5154) /* these are required for START_AP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5155) if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5156) !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5157) !info->attrs[NL80211_ATTR_BEACON_HEAD])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5158) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5160) err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5161) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5162) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5164) params.beacon_interval =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5165) nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5166) params.dtim_period =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5167) nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5169) err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5170) params.beacon_interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5171) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5172) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5174) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5175) * In theory, some of these attributes should be required here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5176) * but since they were not used when the command was originally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5177) * added, keep them optional for old user space programs to let
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5178) * them continue to work with drivers that do not need the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5179) * additional information -- drivers must check!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5180) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5181) if (info->attrs[NL80211_ATTR_SSID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5182) params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5183) params.ssid_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5184) nla_len(info->attrs[NL80211_ATTR_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5185) if (params.ssid_len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5186) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5189) if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5190) params.hidden_ssid = nla_get_u32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5191) info->attrs[NL80211_ATTR_HIDDEN_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5193) params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5195) if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5196) params.auth_type = nla_get_u32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5197) info->attrs[NL80211_ATTR_AUTH_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5198) if (!nl80211_valid_auth_type(rdev, params.auth_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5199) NL80211_CMD_START_AP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5200) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5201) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5202) params.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5204) err = nl80211_crypto_settings(rdev, info, ¶ms.crypto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5205) NL80211_MAX_NR_CIPHER_SUITES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5206) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5207) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5209) if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5210) if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5211) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5212) params.inactivity_timeout = nla_get_u16(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5213) info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5216) if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5217) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5218) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5219) params.p2p_ctwindow =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5220) nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5221) if (params.p2p_ctwindow != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5222) !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5223) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5226) if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5227) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5229) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5230) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5231) tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5232) params.p2p_opp_ps = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5233) if (params.p2p_opp_ps != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5234) !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5235) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5238) if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5239) err = nl80211_parse_chandef(rdev, info, ¶ms.chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5240) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5241) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5242) } else if (wdev->preset_chandef.chan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5243) params.chandef = wdev->preset_chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5244) } else if (!nl80211_get_ap_channel(rdev, ¶ms))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5245) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5247) if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5248) wdev->iftype))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5249) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5251) if (info->attrs[NL80211_ATTR_TX_RATES]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5252) err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5253) NL80211_ATTR_TX_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5254) ¶ms.beacon_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5255) dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5256) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5257) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5259) err = validate_beacon_tx_rate(rdev, params.chandef.chan->band,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5260) ¶ms.beacon_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5261) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5262) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5265) if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5266) params.smps_mode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5267) nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5268) switch (params.smps_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5269) case NL80211_SMPS_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5271) case NL80211_SMPS_STATIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5272) if (!(rdev->wiphy.features &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5273) NL80211_FEATURE_STATIC_SMPS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5274) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5276) case NL80211_SMPS_DYNAMIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5277) if (!(rdev->wiphy.features &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5278) NL80211_FEATURE_DYNAMIC_SMPS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5279) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5280) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5281) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5282) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5284) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5285) params.smps_mode = NL80211_SMPS_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5288) params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5289) if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5290) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5292) if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5293) params.acl = parse_acl_data(&rdev->wiphy, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5294) if (IS_ERR(params.acl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5295) return PTR_ERR(params.acl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5298) params.twt_responder =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5299) nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5301) if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5302) err = nl80211_parse_he_obss_pd(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5303) info->attrs[NL80211_ATTR_HE_OBSS_PD],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5304) ¶ms.he_obss_pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5305) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5306) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5309) if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5310) err = nl80211_parse_he_bss_color(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5311) info->attrs[NL80211_ATTR_HE_BSS_COLOR],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5312) ¶ms.he_bss_color);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5313) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5314) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5317) if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5318) err = nl80211_parse_fils_discovery(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5319) info->attrs[NL80211_ATTR_FILS_DISCOVERY],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5320) ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5321) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5322) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5325) if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5326) err = nl80211_parse_unsol_bcast_probe_resp(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5327) rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5328) ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5329) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5330) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5333) nl80211_calculate_ap_params(¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5335) if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5336) params.flags |= AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5338) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5339) err = rdev_start_ap(rdev, dev, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5340) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5341) wdev->preset_chandef = params.chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5342) wdev->beacon_interval = params.beacon_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5343) wdev->chandef = params.chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5344) wdev->ssid_len = params.ssid_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5345) memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5347) if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5348) wdev->conn_owner_nlportid = info->snd_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5350) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5352) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5353) kfree(params.acl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5355) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5358) static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5360) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5361) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5362) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5363) struct cfg80211_beacon_data params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5364) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5366) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5367) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5368) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5370) if (!rdev->ops->change_beacon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5371) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5373) if (!wdev->beacon_interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5374) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5376) err = nl80211_parse_beacon(rdev, info->attrs, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5377) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5378) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5380) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5381) err = rdev_change_beacon(rdev, dev, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5382) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5384) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5387) static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5389) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5390) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5392) return cfg80211_stop_ap(rdev, dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5395) static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5396) [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5397) [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5398) [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5399) [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5400) [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5401) [NL80211_STA_FLAG_TDLS_PEER] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5402) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5404) static int parse_station_flags(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5405) enum nl80211_iftype iftype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5406) struct station_parameters *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5408) struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5409) struct nlattr *nla;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5410) int flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5412) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5413) * Try parsing the new attribute first so userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5414) * can specify both for older kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5415) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5416) nla = info->attrs[NL80211_ATTR_STA_FLAGS2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5417) if (nla) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5418) struct nl80211_sta_flag_update *sta_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5420) sta_flags = nla_data(nla);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5421) params->sta_flags_mask = sta_flags->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5422) params->sta_flags_set = sta_flags->set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5423) params->sta_flags_set &= params->sta_flags_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5424) if ((params->sta_flags_mask |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5425) params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5426) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5427) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5430) /* if present, parse the old attribute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5432) nla = info->attrs[NL80211_ATTR_STA_FLAGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5433) if (!nla)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5434) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5436) if (nla_parse_nested_deprecated(flags, NL80211_STA_FLAG_MAX, nla, sta_flags_policy, info->extack))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5437) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5439) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5440) * Only allow certain flags for interface types so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5441) * other attributes are silently ignored. Remember that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5442) * this is backward compatibility code with old userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5443) * and shouldn't be hit in other cases anyway.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5444) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5445) switch (iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5446) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5447) case NL80211_IFTYPE_AP_VLAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5448) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5449) params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5450) BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5451) BIT(NL80211_STA_FLAG_WME) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5452) BIT(NL80211_STA_FLAG_MFP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5453) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5454) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5455) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5456) params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5457) BIT(NL80211_STA_FLAG_TDLS_PEER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5458) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5459) case NL80211_IFTYPE_MESH_POINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5460) params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5461) BIT(NL80211_STA_FLAG_MFP) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5462) BIT(NL80211_STA_FLAG_AUTHORIZED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5463) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5464) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5465) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5468) for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5469) if (flags[flag]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5470) params->sta_flags_set |= (1<<flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5472) /* no longer support new API additions in old API */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5473) if (flag > NL80211_STA_FLAG_MAX_OLD_API)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5474) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5478) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5481) bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5483) struct nlattr *rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5484) u32 bitrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5485) u16 bitrate_compat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5486) enum nl80211_rate_info rate_flg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5488) rate = nla_nest_start_noflag(msg, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5489) if (!rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5490) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5492) /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5493) bitrate = cfg80211_calculate_bitrate(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5494) /* report 16-bit bitrate only if we can */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5495) bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5496) if (bitrate > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5497) nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5498) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5499) if (bitrate_compat > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5500) nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5501) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5503) switch (info->bw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5504) case RATE_INFO_BW_5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5505) rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5506) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5507) case RATE_INFO_BW_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5508) rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5509) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5510) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5511) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5512) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5513) case RATE_INFO_BW_20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5514) rate_flg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5515) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5516) case RATE_INFO_BW_40:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5517) rate_flg = NL80211_RATE_INFO_40_MHZ_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5518) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5519) case RATE_INFO_BW_80:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5520) rate_flg = NL80211_RATE_INFO_80_MHZ_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5521) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5522) case RATE_INFO_BW_160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5523) rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5524) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5525) case RATE_INFO_BW_HE_RU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5526) rate_flg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5527) WARN_ON(!(info->flags & RATE_INFO_FLAGS_HE_MCS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5530) if (rate_flg && nla_put_flag(msg, rate_flg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5531) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5533) if (info->flags & RATE_INFO_FLAGS_MCS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5534) if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5535) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5536) if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5537) nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5538) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5539) } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5540) if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5541) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5542) if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5543) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5544) if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5545) nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5546) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5547) } else if (info->flags & RATE_INFO_FLAGS_HE_MCS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5548) if (nla_put_u8(msg, NL80211_RATE_INFO_HE_MCS, info->mcs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5549) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5550) if (nla_put_u8(msg, NL80211_RATE_INFO_HE_NSS, info->nss))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5551) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5552) if (nla_put_u8(msg, NL80211_RATE_INFO_HE_GI, info->he_gi))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5553) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5554) if (nla_put_u8(msg, NL80211_RATE_INFO_HE_DCM, info->he_dcm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5555) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5556) if (info->bw == RATE_INFO_BW_HE_RU &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5557) nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5558) info->he_ru_alloc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5559) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5562) nla_nest_end(msg, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5563) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5566) static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5567) int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5568) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5569) void *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5570) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5572) if (!mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5573) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5575) attr = nla_nest_start_noflag(msg, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5576) if (!attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5577) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5579) for (i = 0; i < IEEE80211_MAX_CHAINS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5580) if (!(mask & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5581) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5583) if (nla_put_u8(msg, i, signal[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5584) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5587) nla_nest_end(msg, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5589) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5592) static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5593) u32 seq, int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5594) struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5595) struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5596) const u8 *mac_addr, struct station_info *sinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5598) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5599) struct nlattr *sinfoattr, *bss_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5601) hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5602) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5603) cfg80211_sinfo_release_content(sinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5604) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5607) if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5608) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5609) nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5610) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5612) sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5613) if (!sinfoattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5614) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5616) #define PUT_SINFO(attr, memb, type) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5617) BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5618) if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5619) nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5620) sinfo->memb)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5621) goto nla_put_failure; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5622) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5623) #define PUT_SINFO_U64(attr, memb) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5624) if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5625) nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5626) sinfo->memb, NL80211_STA_INFO_PAD)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5627) goto nla_put_failure; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5628) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5630) PUT_SINFO(CONNECTED_TIME, connected_time, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5631) PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5632) PUT_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5634) if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5635) BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5636) nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5637) (u32)sinfo->rx_bytes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5638) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5640) if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5641) BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5642) nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5643) (u32)sinfo->tx_bytes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5644) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5646) PUT_SINFO_U64(RX_BYTES64, rx_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5647) PUT_SINFO_U64(TX_BYTES64, tx_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5648) PUT_SINFO(LLID, llid, u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5649) PUT_SINFO(PLID, plid, u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5650) PUT_SINFO(PLINK_STATE, plink_state, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5651) PUT_SINFO_U64(RX_DURATION, rx_duration);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5652) PUT_SINFO_U64(TX_DURATION, tx_duration);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5654) if (wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5655) NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5656) PUT_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5658) switch (rdev->wiphy.signal_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5659) case CFG80211_SIGNAL_TYPE_MBM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5660) PUT_SINFO(SIGNAL, signal, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5661) PUT_SINFO(SIGNAL_AVG, signal_avg, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5662) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5663) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5664) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5666) if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5667) if (!nl80211_put_signal(msg, sinfo->chains,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5668) sinfo->chain_signal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5669) NL80211_STA_INFO_CHAIN_SIGNAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5670) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5672) if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5673) if (!nl80211_put_signal(msg, sinfo->chains,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5674) sinfo->chain_signal_avg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5675) NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5676) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5678) if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5679) if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5680) NL80211_STA_INFO_TX_BITRATE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5681) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5683) if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5684) if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5685) NL80211_STA_INFO_RX_BITRATE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5686) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5689) PUT_SINFO(RX_PACKETS, rx_packets, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5690) PUT_SINFO(TX_PACKETS, tx_packets, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5691) PUT_SINFO(TX_RETRIES, tx_retries, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5692) PUT_SINFO(TX_FAILED, tx_failed, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5693) PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5694) PUT_SINFO(AIRTIME_LINK_METRIC, airtime_link_metric, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5695) PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5696) PUT_SINFO(LOCAL_PM, local_pm, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5697) PUT_SINFO(PEER_PM, peer_pm, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5698) PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5699) PUT_SINFO(CONNECTED_TO_GATE, connected_to_gate, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5700) PUT_SINFO(CONNECTED_TO_AS, connected_to_as, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5702) if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5703) bss_param = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5704) NL80211_STA_INFO_BSS_PARAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5705) if (!bss_param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5706) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5708) if (((sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5709) nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5710) ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5711) nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5712) ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5713) nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5714) nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5715) sinfo->bss_param.dtim_period) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5716) nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5717) sinfo->bss_param.beacon_interval))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5718) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5720) nla_nest_end(msg, bss_param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5722) if ((sinfo->filled & BIT_ULL(NL80211_STA_INFO_STA_FLAGS)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5723) nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5724) sizeof(struct nl80211_sta_flag_update),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5725) &sinfo->sta_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5726) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5728) PUT_SINFO_U64(T_OFFSET, t_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5729) PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5730) PUT_SINFO_U64(BEACON_RX, rx_beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5731) PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5732) PUT_SINFO(RX_MPDUS, rx_mpdu_count, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5733) PUT_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5734) if (wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5735) NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5736) PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5737) PUT_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5740) #undef PUT_SINFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5741) #undef PUT_SINFO_U64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5743) if (sinfo->pertid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5744) struct nlattr *tidsattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5745) int tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5747) tidsattr = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5748) NL80211_STA_INFO_TID_STATS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5749) if (!tidsattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5750) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5752) for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5753) struct cfg80211_tid_stats *tidstats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5754) struct nlattr *tidattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5756) tidstats = &sinfo->pertid[tid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5758) if (!tidstats->filled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5759) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5761) tidattr = nla_nest_start_noflag(msg, tid + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5762) if (!tidattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5763) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5765) #define PUT_TIDVAL_U64(attr, memb) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5766) if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5767) nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5768) tidstats->memb, NL80211_TID_STATS_PAD)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5769) goto nla_put_failure; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5770) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5772) PUT_TIDVAL_U64(RX_MSDU, rx_msdu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5773) PUT_TIDVAL_U64(TX_MSDU, tx_msdu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5774) PUT_TIDVAL_U64(TX_MSDU_RETRIES, tx_msdu_retries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5775) PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5777) #undef PUT_TIDVAL_U64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5778) if ((tidstats->filled &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5779) BIT(NL80211_TID_STATS_TXQ_STATS)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5780) !nl80211_put_txq_stats(msg, &tidstats->txq_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5781) NL80211_TID_STATS_TXQ_STATS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5782) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5784) nla_nest_end(msg, tidattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5787) nla_nest_end(msg, tidsattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5790) nla_nest_end(msg, sinfoattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5792) if (sinfo->assoc_req_ies_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5793) nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5794) sinfo->assoc_req_ies))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5795) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5797) cfg80211_sinfo_release_content(sinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5798) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5799) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5801) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5802) cfg80211_sinfo_release_content(sinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5803) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5804) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5807) static int nl80211_dump_station(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5808) struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5810) struct station_info sinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5811) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5812) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5813) u8 mac_addr[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5814) int sta_idx = cb->args[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5815) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5817) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5818) err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5819) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5820) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5822) if (!wdev->netdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5823) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5824) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5827) if (!rdev->ops->dump_station) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5828) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5829) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5832) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5833) memset(&sinfo, 0, sizeof(sinfo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5834) err = rdev_dump_station(rdev, wdev->netdev, sta_idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5835) mac_addr, &sinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5836) if (err == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5837) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5838) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5839) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5841) if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5842) NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5843) cb->nlh->nlmsg_seq, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5844) rdev, wdev->netdev, mac_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5845) &sinfo) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5846) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5848) sta_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5851) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5852) cb->args[2] = sta_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5853) err = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5854) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5855) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5857) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5860) static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5861) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5862) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5863) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5864) struct station_info sinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5865) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5866) u8 *mac_addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5867) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5869) memset(&sinfo, 0, sizeof(sinfo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5871) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5872) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5874) mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5876) if (!rdev->ops->get_station)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5877) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5879) err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5880) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5881) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5883) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5884) if (!msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5885) cfg80211_sinfo_release_content(&sinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5886) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5889) if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5890) info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5891) rdev, dev, mac_addr, &sinfo) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5892) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5893) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5896) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5899) int cfg80211_check_station_change(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5900) struct station_parameters *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5901) enum cfg80211_station_type statype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5902) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5903) if (params->listen_interval != -1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5904) statype != CFG80211_STA_AP_CLIENT_UNASSOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5905) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5907) if (params->support_p2p_ps != -1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5908) statype != CFG80211_STA_AP_CLIENT_UNASSOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5909) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5911) if (params->aid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5912) !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5913) statype != CFG80211_STA_AP_CLIENT_UNASSOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5914) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5916) /* When you run into this, adjust the code below for the new flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5917) BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5919) switch (statype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5920) case CFG80211_STA_MESH_PEER_KERNEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5921) case CFG80211_STA_MESH_PEER_USER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5922) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5923) * No ignoring the TDLS flag here -- the userspace mesh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5924) * code doesn't have the bug of including TDLS in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5925) * mask everywhere.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5926) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5927) if (params->sta_flags_mask &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5928) ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5929) BIT(NL80211_STA_FLAG_MFP) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5930) BIT(NL80211_STA_FLAG_AUTHORIZED)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5931) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5932) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5933) case CFG80211_STA_TDLS_PEER_SETUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5934) case CFG80211_STA_TDLS_PEER_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5935) if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5936) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5937) /* ignore since it can't change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5938) params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5939) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5940) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5941) /* disallow mesh-specific things */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5942) if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5943) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5944) if (params->local_pm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5945) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5946) if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5947) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5950) if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5951) statype != CFG80211_STA_TDLS_PEER_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5952) /* TDLS can't be set, ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5953) if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5954) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5955) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5956) * ... but don't bother the driver with it. This works around
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5957) * a hostapd/wpa_supplicant issue -- it always includes the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5958) * TLDS_PEER flag in the mask even for AP mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5959) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5960) params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5963) if (statype != CFG80211_STA_TDLS_PEER_SETUP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5964) statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5965) /* reject other things that can't change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5966) if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5967) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5968) if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5969) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5970) if (params->supported_rates)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5971) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5972) if (params->ext_capab || params->ht_capa || params->vht_capa ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5973) params->he_capa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5974) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5977) if (statype != CFG80211_STA_AP_CLIENT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5978) statype != CFG80211_STA_AP_CLIENT_UNASSOC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5979) if (params->vlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5980) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5983) switch (statype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5984) case CFG80211_STA_AP_MLME_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5985) /* Use this only for authorizing/unauthorizing a station */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5986) if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5987) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5988) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5989) case CFG80211_STA_AP_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5990) case CFG80211_STA_AP_CLIENT_UNASSOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5991) /* accept only the listed bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5992) if (params->sta_flags_mask &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5993) ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5994) BIT(NL80211_STA_FLAG_AUTHENTICATED) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5995) BIT(NL80211_STA_FLAG_ASSOCIATED) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5996) BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5997) BIT(NL80211_STA_FLAG_WME) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5998) BIT(NL80211_STA_FLAG_MFP)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5999) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6001) /* but authenticated/associated only if driver handles it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6002) if (!(wiphy->features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6003) params->sta_flags_mask &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6004) (BIT(NL80211_STA_FLAG_AUTHENTICATED) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6005) BIT(NL80211_STA_FLAG_ASSOCIATED)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6006) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6007) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6008) case CFG80211_STA_IBSS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6009) case CFG80211_STA_AP_STA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6010) /* reject any changes other than AUTHORIZED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6011) if (params->sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6012) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6013) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6014) case CFG80211_STA_TDLS_PEER_SETUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6015) /* reject any changes other than AUTHORIZED or WME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6016) if (params->sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6017) BIT(NL80211_STA_FLAG_WME)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6018) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6019) /* force (at least) rates when authorizing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6020) if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6021) !params->supported_rates)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6022) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6023) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6024) case CFG80211_STA_TDLS_PEER_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6025) /* reject any changes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6026) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6027) case CFG80211_STA_MESH_PEER_KERNEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6028) if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6029) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6030) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6031) case CFG80211_STA_MESH_PEER_USER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6032) if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6033) params->plink_action != NL80211_PLINK_ACTION_BLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6034) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6035) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6038) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6039) * Older kernel versions ignored this attribute entirely, so don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6040) * reject attempts to update it but mark it as unused instead so the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6041) * driver won't look at the data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6042) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6043) if (statype != CFG80211_STA_AP_CLIENT_UNASSOC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6044) statype != CFG80211_STA_TDLS_PEER_SETUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6045) params->opmode_notif_used = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6047) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6049) EXPORT_SYMBOL(cfg80211_check_station_change);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6051) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6052) * Get vlan interface making sure it is running and on the right wiphy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6053) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6054) static struct net_device *get_vlan(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6055) struct cfg80211_registered_device *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6056) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6057) struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6058) struct net_device *v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6059) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6061) if (!vlanattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6062) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6064) v = dev_get_by_index(genl_info_net(info), nla_get_u32(vlanattr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6065) if (!v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6066) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6068) if (!v->ieee80211_ptr || v->ieee80211_ptr->wiphy != &rdev->wiphy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6069) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6070) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6073) if (v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6074) v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6075) v->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6076) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6077) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6080) if (!netif_running(v)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6081) ret = -ENETDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6082) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6085) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6086) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6087) dev_put(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6088) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6091) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6092) nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6093) [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6094) [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6095) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6097) static int nl80211_parse_sta_wme(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6098) struct station_parameters *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6099) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6100) struct nlattr *tb[NL80211_STA_WME_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6101) struct nlattr *nla;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6102) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6104) /* parse WME attributes if present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6105) if (!info->attrs[NL80211_ATTR_STA_WME])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6106) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6108) nla = info->attrs[NL80211_ATTR_STA_WME];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6109) err = nla_parse_nested_deprecated(tb, NL80211_STA_WME_MAX, nla,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6110) nl80211_sta_wme_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6111) info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6112) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6113) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6115) if (tb[NL80211_STA_WME_UAPSD_QUEUES])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6116) params->uapsd_queues = nla_get_u8(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6117) tb[NL80211_STA_WME_UAPSD_QUEUES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6118) if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6119) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6121) if (tb[NL80211_STA_WME_MAX_SP])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6122) params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6124) if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6125) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6127) params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6132) static int nl80211_parse_sta_channel_info(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6133) struct station_parameters *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6135) if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6136) params->supported_channels =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6137) nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6138) params->supported_channels_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6139) nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6141) * Need to include at least one (first channel, number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6142) * channels) tuple for each subband (checked in policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6143) * and must have proper tuples for the rest of the data as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6145) if (params->supported_channels_len % 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6146) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6149) if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6150) params->supported_oper_classes =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6151) nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6152) params->supported_oper_classes_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6153) nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6155) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6158) static int nl80211_set_station_tdls(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6159) struct station_parameters *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6161) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6162) /* Dummy STA entry gets updated once the peer capabilities are known */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6163) if (info->attrs[NL80211_ATTR_PEER_AID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6164) params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6165) if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6166) params->ht_capa =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6167) nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6168) if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6169) params->vht_capa =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6170) nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6171) if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6172) params->he_capa =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6173) nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6174) params->he_capa_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6175) nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6178) err = nl80211_parse_sta_channel_info(info, params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6179) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6180) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6182) return nl80211_parse_sta_wme(info, params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6185) static int nl80211_parse_sta_txpower_setting(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6186) struct station_parameters *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6188) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6189) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6191) if (info->attrs[NL80211_ATTR_STA_TX_POWER_SETTING]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6192) if (!rdev->ops->set_tx_power ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6193) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6194) NL80211_EXT_FEATURE_STA_TX_PWR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6195) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6197) idx = NL80211_ATTR_STA_TX_POWER_SETTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6198) params->txpwr.type = nla_get_u8(info->attrs[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6200) if (params->txpwr.type == NL80211_TX_POWER_LIMITED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6201) idx = NL80211_ATTR_STA_TX_POWER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6203) if (info->attrs[idx])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6204) params->txpwr.power =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6205) nla_get_s16(info->attrs[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6206) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6207) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6209) params->sta_modify_mask |= STATION_PARAM_APPLY_STA_TXPOWER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6212) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6215) static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6217) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6218) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6219) struct station_parameters params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6220) u8 *mac_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6221) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6223) memset(¶ms, 0, sizeof(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6225) if (!rdev->ops->change_station)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6226) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6228) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6229) * AID and listen_interval properties can be set only for unassociated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6230) * station. Include these parameters here and will check them in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6231) * cfg80211_check_station_change().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6232) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6233) if (info->attrs[NL80211_ATTR_STA_AID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6234) params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6236) if (info->attrs[NL80211_ATTR_VLAN_ID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6237) params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6239) if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6240) params.listen_interval =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6241) nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6242) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6243) params.listen_interval = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6245) if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6246) params.support_p2p_ps =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6247) nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6248) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6249) params.support_p2p_ps = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6251) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6252) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6254) mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6256) if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6257) params.supported_rates =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6258) nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6259) params.supported_rates_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6260) nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6263) if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6264) params.capability =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6265) nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6266) params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6269) if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6270) params.ext_capab =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6271) nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6272) params.ext_capab_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6273) nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6276) if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6277) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6279) if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6280) params.plink_action =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6281) nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6283) if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6284) params.plink_state =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6285) nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6286) if (info->attrs[NL80211_ATTR_MESH_PEER_AID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6287) params.peer_aid = nla_get_u16(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6288) info->attrs[NL80211_ATTR_MESH_PEER_AID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6289) params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6292) if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6293) params.local_pm = nla_get_u32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6294) info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6296) if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6297) params.opmode_notif_used = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6298) params.opmode_notif =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6299) nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6302) if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6303) params.he_6ghz_capa =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6304) nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6306) if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6307) params.airtime_weight =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6308) nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6310) if (params.airtime_weight &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6311) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6312) NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6313) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6315) err = nl80211_parse_sta_txpower_setting(info, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6316) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6317) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6319) /* Include parameters for TDLS peer (will check later) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6320) err = nl80211_set_station_tdls(info, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6321) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6322) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6324) params.vlan = get_vlan(info, rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6325) if (IS_ERR(params.vlan))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6326) return PTR_ERR(params.vlan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6328) switch (dev->ieee80211_ptr->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6329) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6330) case NL80211_IFTYPE_AP_VLAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6331) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6332) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6333) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6334) case NL80211_IFTYPE_ADHOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6335) case NL80211_IFTYPE_MESH_POINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6336) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6337) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6338) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6339) goto out_put_vlan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6342) /* driver will call cfg80211_check_station_change() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6343) err = rdev_change_station(rdev, dev, mac_addr, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6345) out_put_vlan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6346) if (params.vlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6347) dev_put(params.vlan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6349) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6352) static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6354) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6355) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6356) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6357) struct station_parameters params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6358) u8 *mac_addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6359) u32 auth_assoc = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6360) BIT(NL80211_STA_FLAG_ASSOCIATED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6362) memset(¶ms, 0, sizeof(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6364) if (!rdev->ops->add_station)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6365) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6367) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6368) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6370) if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6371) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6373) if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6374) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6376) if (!info->attrs[NL80211_ATTR_STA_AID] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6377) !info->attrs[NL80211_ATTR_PEER_AID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6378) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6380) mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6381) params.supported_rates =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6382) nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6383) params.supported_rates_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6384) nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6385) params.listen_interval =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6386) nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6388) if (info->attrs[NL80211_ATTR_VLAN_ID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6389) params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6391) if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6392) params.support_p2p_ps =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6393) nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6394) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6395) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6396) * if not specified, assume it's supported for P2P GO interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6397) * and is NOT supported for AP interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6398) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6399) params.support_p2p_ps =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6400) dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6403) if (info->attrs[NL80211_ATTR_PEER_AID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6404) params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6405) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6406) params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6408) if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6409) params.capability =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6410) nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6411) params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6414) if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6415) params.ext_capab =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6416) nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6417) params.ext_capab_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6418) nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6421) if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6422) params.ht_capa =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6423) nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6425) if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6426) params.vht_capa =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6427) nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6429) if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6430) params.he_capa =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6431) nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6432) params.he_capa_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6433) nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6436) if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6437) params.he_6ghz_capa =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6438) nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6440) if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6441) params.opmode_notif_used = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6442) params.opmode_notif =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6443) nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6446) if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6447) params.plink_action =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6448) nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6450) if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6451) params.airtime_weight =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6452) nla_get_u16(info->attrs[NL80211_ATTR_AIRTIME_WEIGHT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6454) if (params.airtime_weight &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6455) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6456) NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6457) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6459) err = nl80211_parse_sta_txpower_setting(info, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6460) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6461) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6463) err = nl80211_parse_sta_channel_info(info, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6464) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6465) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6467) err = nl80211_parse_sta_wme(info, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6468) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6469) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6471) if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6472) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6474) /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6475) * as userspace might just pass through the capabilities from the IEs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6476) * directly, rather than enforcing this restriction and returning an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6477) * error in this case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6478) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6479) if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6480) params.ht_capa = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6481) params.vht_capa = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6483) /* HE requires WME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6484) if (params.he_capa_len || params.he_6ghz_capa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6485) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6488) /* Ensure that HT/VHT capabilities are not set for 6 GHz HE STA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6489) if (params.he_6ghz_capa && (params.ht_capa || params.vht_capa))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6490) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6492) /* When you run into this, adjust the code below for the new flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6493) BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6495) switch (dev->ieee80211_ptr->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6496) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6497) case NL80211_IFTYPE_AP_VLAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6498) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6499) /* ignore WME attributes if iface/sta is not capable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6500) if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6501) !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6502) params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6504) /* TDLS peers cannot be added */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6505) if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6506) info->attrs[NL80211_ATTR_PEER_AID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6507) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6508) /* but don't bother the driver with it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6509) params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6511) /* allow authenticated/associated only if driver handles it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6512) if (!(rdev->wiphy.features &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6513) NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6514) params.sta_flags_mask & auth_assoc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6515) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6517) /* Older userspace, or userspace wanting to be compatible with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6518) * !NL80211_FEATURE_FULL_AP_CLIENT_STATE, will not set the auth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6519) * and assoc flags in the mask, but assumes the station will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6520) * added as associated anyway since this was the required driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6521) * behaviour before NL80211_FEATURE_FULL_AP_CLIENT_STATE was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6522) * introduced.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6523) * In order to not bother drivers with this quirk in the API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6524) * set the flags in both the mask and set for new stations in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6525) * this case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6527) if (!(params.sta_flags_mask & auth_assoc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6528) params.sta_flags_mask |= auth_assoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6529) params.sta_flags_set |= auth_assoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6532) /* must be last in here for error handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6533) params.vlan = get_vlan(info, rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6534) if (IS_ERR(params.vlan))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6535) return PTR_ERR(params.vlan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6536) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6537) case NL80211_IFTYPE_MESH_POINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6538) /* ignore uAPSD data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6539) params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6541) /* associated is disallowed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6542) if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6543) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6544) /* TDLS peers cannot be added */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6545) if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6546) info->attrs[NL80211_ATTR_PEER_AID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6547) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6548) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6549) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6550) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6551) /* ignore uAPSD data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6552) params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6554) /* these are disallowed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6555) if (params.sta_flags_mask &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6556) (BIT(NL80211_STA_FLAG_ASSOCIATED) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6557) BIT(NL80211_STA_FLAG_AUTHENTICATED)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6558) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6559) /* Only TDLS peers can be added */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6560) if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6561) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6562) /* Can only add if TDLS ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6563) if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6564) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6565) /* ... with external setup is supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6566) if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6567) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6568) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6569) * Older wpa_supplicant versions always mark the TDLS peer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6570) * as authorized, but it shouldn't yet be.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6571) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6572) params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6573) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6574) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6575) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6578) /* be aware of params.vlan when changing code here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6580) err = rdev_add_station(rdev, dev, mac_addr, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6582) if (params.vlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6583) dev_put(params.vlan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6584) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6587) static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6588) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6589) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6590) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6591) struct station_del_parameters params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6593) memset(¶ms, 0, sizeof(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6595) if (info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6596) params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6598) switch (dev->ieee80211_ptr->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6599) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6600) case NL80211_IFTYPE_AP_VLAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6601) case NL80211_IFTYPE_MESH_POINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6602) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6603) /* always accept these */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6604) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6605) case NL80211_IFTYPE_ADHOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6606) /* conditionally accept */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6607) if (wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6608) NL80211_EXT_FEATURE_DEL_IBSS_STA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6609) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6610) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6611) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6612) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6615) if (!rdev->ops->del_station)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6616) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6618) if (info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6619) params.subtype =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6620) nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6621) if (params.subtype != IEEE80211_STYPE_DISASSOC >> 4 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6622) params.subtype != IEEE80211_STYPE_DEAUTH >> 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6623) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6624) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6625) /* Default to Deauthentication frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6626) params.subtype = IEEE80211_STYPE_DEAUTH >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6629) if (info->attrs[NL80211_ATTR_REASON_CODE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6630) params.reason_code =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6631) nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6632) if (params.reason_code == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6633) return -EINVAL; /* 0 is reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6634) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6635) /* Default to reason code 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6636) params.reason_code = WLAN_REASON_PREV_AUTH_NOT_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6639) return rdev_del_station(rdev, dev, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6642) static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6643) int flags, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6644) u8 *dst, u8 *next_hop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6645) struct mpath_info *pinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6647) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6648) struct nlattr *pinfoattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6650) hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_MPATH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6651) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6652) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6654) if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6655) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6656) nla_put(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6657) nla_put_u32(msg, NL80211_ATTR_GENERATION, pinfo->generation))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6658) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6660) pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MPATH_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6661) if (!pinfoattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6662) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6663) if ((pinfo->filled & MPATH_INFO_FRAME_QLEN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6664) nla_put_u32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6665) pinfo->frame_qlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6666) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6667) if (((pinfo->filled & MPATH_INFO_SN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6668) nla_put_u32(msg, NL80211_MPATH_INFO_SN, pinfo->sn)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6669) ((pinfo->filled & MPATH_INFO_METRIC) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6670) nla_put_u32(msg, NL80211_MPATH_INFO_METRIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6671) pinfo->metric)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6672) ((pinfo->filled & MPATH_INFO_EXPTIME) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6673) nla_put_u32(msg, NL80211_MPATH_INFO_EXPTIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6674) pinfo->exptime)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6675) ((pinfo->filled & MPATH_INFO_FLAGS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6676) nla_put_u8(msg, NL80211_MPATH_INFO_FLAGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6677) pinfo->flags)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6678) ((pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6679) nla_put_u32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6680) pinfo->discovery_timeout)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6681) ((pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6682) nla_put_u8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6683) pinfo->discovery_retries)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6684) ((pinfo->filled & MPATH_INFO_HOP_COUNT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6685) nla_put_u8(msg, NL80211_MPATH_INFO_HOP_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6686) pinfo->hop_count)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6687) ((pinfo->filled & MPATH_INFO_PATH_CHANGE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6688) nla_put_u32(msg, NL80211_MPATH_INFO_PATH_CHANGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6689) pinfo->path_change_count)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6690) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6692) nla_nest_end(msg, pinfoattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6694) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6695) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6697) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6698) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6699) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6702) static int nl80211_dump_mpath(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6703) struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6705) struct mpath_info pinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6706) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6707) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6708) u8 dst[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6709) u8 next_hop[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6710) int path_idx = cb->args[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6711) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6713) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6714) err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6715) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6716) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6718) if (!rdev->ops->dump_mpath) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6719) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6720) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6723) if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6724) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6725) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6728) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6729) err = rdev_dump_mpath(rdev, wdev->netdev, path_idx, dst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6730) next_hop, &pinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6731) if (err == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6732) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6733) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6734) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6736) if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6737) cb->nlh->nlmsg_seq, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6738) wdev->netdev, dst, next_hop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6739) &pinfo) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6740) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6742) path_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6745) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6746) cb->args[2] = path_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6747) err = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6748) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6749) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6750) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6753) static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6755) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6756) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6757) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6758) struct mpath_info pinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6759) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6760) u8 *dst = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6761) u8 next_hop[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6763) memset(&pinfo, 0, sizeof(pinfo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6765) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6766) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6768) dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6770) if (!rdev->ops->get_mpath)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6771) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6773) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6774) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6776) err = rdev_get_mpath(rdev, dev, dst, next_hop, &pinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6777) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6778) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6780) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6781) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6782) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6784) if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6785) dev, dst, next_hop, &pinfo) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6786) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6787) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6790) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6793) static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6795) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6796) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6797) u8 *dst = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6798) u8 *next_hop = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6800) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6801) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6803) if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6804) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6806) dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6807) next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6809) if (!rdev->ops->change_mpath)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6810) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6812) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6813) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6815) return rdev_change_mpath(rdev, dev, dst, next_hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6818) static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6819) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6820) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6821) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6822) u8 *dst = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6823) u8 *next_hop = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6825) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6826) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6828) if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6829) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6831) dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6832) next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6834) if (!rdev->ops->add_mpath)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6835) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6837) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6838) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6840) return rdev_add_mpath(rdev, dev, dst, next_hop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6843) static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6845) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6846) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6847) u8 *dst = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6849) if (info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6850) dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6852) if (!rdev->ops->del_mpath)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6853) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6855) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6856) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6858) return rdev_del_mpath(rdev, dev, dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6861) static int nl80211_get_mpp(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6863) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6864) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6865) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6866) struct mpath_info pinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6867) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6868) u8 *dst = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6869) u8 mpp[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6871) memset(&pinfo, 0, sizeof(pinfo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6873) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6874) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6876) dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6878) if (!rdev->ops->get_mpp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6879) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6881) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6882) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6884) err = rdev_get_mpp(rdev, dev, dst, mpp, &pinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6885) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6886) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6888) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6889) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6890) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6892) if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6893) dev, dst, mpp, &pinfo) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6894) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6895) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6898) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6901) static int nl80211_dump_mpp(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6902) struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6904) struct mpath_info pinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6905) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6906) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6907) u8 dst[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6908) u8 mpp[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6909) int path_idx = cb->args[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6910) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6912) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6913) err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6914) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6915) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6917) if (!rdev->ops->dump_mpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6918) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6919) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6922) if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6923) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6924) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6927) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6928) err = rdev_dump_mpp(rdev, wdev->netdev, path_idx, dst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6929) mpp, &pinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6930) if (err == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6931) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6932) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6933) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6935) if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6936) cb->nlh->nlmsg_seq, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6937) wdev->netdev, dst, mpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6938) &pinfo) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6939) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6941) path_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6944) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6945) cb->args[2] = path_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6946) err = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6947) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6948) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6949) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6952) static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6954) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6955) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6956) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6957) struct bss_parameters params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6958) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6960) memset(¶ms, 0, sizeof(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6961) /* default to not changing parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6962) params.use_cts_prot = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6963) params.use_short_preamble = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6964) params.use_short_slot_time = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6965) params.ap_isolate = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6966) params.ht_opmode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6967) params.p2p_ctwindow = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6968) params.p2p_opp_ps = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6970) if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6971) params.use_cts_prot =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6972) nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6973) if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6974) params.use_short_preamble =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6975) nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6976) if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6977) params.use_short_slot_time =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6978) nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6979) if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6980) params.basic_rates =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6981) nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6982) params.basic_rates_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6983) nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6985) if (info->attrs[NL80211_ATTR_AP_ISOLATE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6986) params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6987) if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6988) params.ht_opmode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6989) nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6991) if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6992) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6993) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6994) params.p2p_ctwindow =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6995) nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6996) if (params.p2p_ctwindow != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6997) !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6998) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7001) if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7002) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7004) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7005) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7006) tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7007) params.p2p_opp_ps = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7008) if (params.p2p_opp_ps &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7009) !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7010) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7013) if (!rdev->ops->change_bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7014) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7016) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7017) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7018) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7020) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7021) err = rdev_change_bss(rdev, dev, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7022) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7024) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7027) static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7028) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7029) char *data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7030) bool is_indoor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7031) enum nl80211_user_reg_hint_type user_reg_hint_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7032) u32 owner_nlportid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7034) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7035) * You should only get this when cfg80211 hasn't yet initialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7036) * completely when built-in to the kernel right between the time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7037) * window between nl80211_init() and regulatory_init(), if that is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7038) * even possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7039) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7040) if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7041) return -EINPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7043) if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7044) user_reg_hint_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7045) nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7046) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7047) user_reg_hint_type = NL80211_USER_REG_HINT_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7049) switch (user_reg_hint_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7050) case NL80211_USER_REG_HINT_USER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7051) case NL80211_USER_REG_HINT_CELL_BASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7052) if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7053) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7055) data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7056) return regulatory_hint_user(data, user_reg_hint_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7057) case NL80211_USER_REG_HINT_INDOOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7058) if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7059) owner_nlportid = info->snd_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7060) is_indoor = !!info->attrs[NL80211_ATTR_REG_INDOOR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7061) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7062) owner_nlportid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7063) is_indoor = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7066) return regulatory_hint_indoor(is_indoor, owner_nlportid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7067) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7068) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7072) static int nl80211_reload_regdb(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7073) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7074) return reg_reload_regdb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7077) static int nl80211_get_mesh_config(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7078) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7079) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7080) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7081) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7082) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7083) struct mesh_config cur_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7084) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7085) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7086) struct nlattr *pinfoattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7087) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7089) if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7090) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7092) if (!rdev->ops->get_mesh_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7093) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7095) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7096) /* If not connected, get default parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7097) if (!wdev->mesh_id_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7098) memcpy(&cur_params, &default_mesh_config, sizeof(cur_params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7099) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7100) err = rdev_get_mesh_config(rdev, dev, &cur_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7101) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7103) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7104) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7106) /* Draw up a netlink message to send back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7107) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7108) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7109) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7110) hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7111) NL80211_CMD_GET_MESH_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7112) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7113) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7114) pinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_MESH_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7115) if (!pinfoattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7116) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7117) if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7118) nla_put_u16(msg, NL80211_MESHCONF_RETRY_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7119) cur_params.dot11MeshRetryTimeout) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7120) nla_put_u16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7121) cur_params.dot11MeshConfirmTimeout) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7122) nla_put_u16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7123) cur_params.dot11MeshHoldingTimeout) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7124) nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7125) cur_params.dot11MeshMaxPeerLinks) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7126) nla_put_u8(msg, NL80211_MESHCONF_MAX_RETRIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7127) cur_params.dot11MeshMaxRetries) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7128) nla_put_u8(msg, NL80211_MESHCONF_TTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7129) cur_params.dot11MeshTTL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7130) nla_put_u8(msg, NL80211_MESHCONF_ELEMENT_TTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7131) cur_params.element_ttl) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7132) nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7133) cur_params.auto_open_plinks) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7134) nla_put_u32(msg, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7135) cur_params.dot11MeshNbrOffsetMaxNeighbor) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7136) nla_put_u8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7137) cur_params.dot11MeshHWMPmaxPREQretries) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7138) nla_put_u32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7139) cur_params.path_refresh_time) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7140) nla_put_u16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7141) cur_params.min_discovery_timeout) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7142) nla_put_u32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7143) cur_params.dot11MeshHWMPactivePathTimeout) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7144) nla_put_u16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7145) cur_params.dot11MeshHWMPpreqMinInterval) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7146) nla_put_u16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7147) cur_params.dot11MeshHWMPperrMinInterval) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7148) nla_put_u16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7149) cur_params.dot11MeshHWMPnetDiameterTraversalTime) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7150) nla_put_u8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7151) cur_params.dot11MeshHWMPRootMode) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7152) nla_put_u16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7153) cur_params.dot11MeshHWMPRannInterval) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7154) nla_put_u8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7155) cur_params.dot11MeshGateAnnouncementProtocol) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7156) nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7157) cur_params.dot11MeshForwarding) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7158) nla_put_s32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7159) cur_params.rssi_threshold) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7160) nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7161) cur_params.ht_opmode) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7162) nla_put_u32(msg, NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7163) cur_params.dot11MeshHWMPactivePathToRootTimeout) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7164) nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7165) cur_params.dot11MeshHWMProotInterval) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7166) nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7167) cur_params.dot11MeshHWMPconfirmationInterval) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7168) nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7169) cur_params.power_mode) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7170) nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7171) cur_params.dot11MeshAwakeWindowDuration) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7172) nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7173) cur_params.plink_timeout) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7174) nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_GATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7175) cur_params.dot11MeshConnectedToMeshGate) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7176) nla_put_u8(msg, NL80211_MESHCONF_NOLEARN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7177) cur_params.dot11MeshNolearn) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7178) nla_put_u8(msg, NL80211_MESHCONF_CONNECTED_TO_AS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7179) cur_params.dot11MeshConnectedToAuthServer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7180) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7181) nla_nest_end(msg, pinfoattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7182) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7183) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7185) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7186) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7187) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7188) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7191) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7192) nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7193) [NL80211_MESHCONF_RETRY_TIMEOUT] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7194) NLA_POLICY_RANGE(NLA_U16, 1, 255),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7195) [NL80211_MESHCONF_CONFIRM_TIMEOUT] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7196) NLA_POLICY_RANGE(NLA_U16, 1, 255),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7197) [NL80211_MESHCONF_HOLDING_TIMEOUT] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7198) NLA_POLICY_RANGE(NLA_U16, 1, 255),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7199) [NL80211_MESHCONF_MAX_PEER_LINKS] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7200) NLA_POLICY_RANGE(NLA_U16, 0, 255),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7201) [NL80211_MESHCONF_MAX_RETRIES] = NLA_POLICY_MAX(NLA_U8, 16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7202) [NL80211_MESHCONF_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7203) [NL80211_MESHCONF_ELEMENT_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7204) [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = NLA_POLICY_MAX(NLA_U8, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7205) [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7206) NLA_POLICY_RANGE(NLA_U32, 1, 255),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7207) [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7208) [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7209) [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = NLA_POLICY_MIN(NLA_U16, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7210) [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7211) [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7212) NLA_POLICY_MIN(NLA_U16, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7213) [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7214) NLA_POLICY_MIN(NLA_U16, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7215) [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7216) NLA_POLICY_MIN(NLA_U16, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7217) [NL80211_MESHCONF_HWMP_ROOTMODE] = NLA_POLICY_MAX(NLA_U8, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7218) [NL80211_MESHCONF_HWMP_RANN_INTERVAL] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7219) NLA_POLICY_MIN(NLA_U16, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7220) [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = NLA_POLICY_MAX(NLA_U8, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7221) [NL80211_MESHCONF_FORWARDING] = NLA_POLICY_MAX(NLA_U8, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7222) [NL80211_MESHCONF_RSSI_THRESHOLD] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7223) NLA_POLICY_RANGE(NLA_S32, -255, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7224) [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7225) [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7226) [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7227) NLA_POLICY_MIN(NLA_U16, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7228) [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7229) NLA_POLICY_MIN(NLA_U16, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7230) [NL80211_MESHCONF_POWER_MODE] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7231) NLA_POLICY_RANGE(NLA_U32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7232) NL80211_MESH_POWER_ACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7233) NL80211_MESH_POWER_MAX),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7234) [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7235) [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7236) [NL80211_MESHCONF_CONNECTED_TO_GATE] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7237) [NL80211_MESHCONF_NOLEARN] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7238) [NL80211_MESHCONF_CONNECTED_TO_AS] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7239) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7241) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7242) nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7243) [NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7244) [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7245) [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7246) [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7247) [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7248) [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7249) [NL80211_MESH_SETUP_IE] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7250) NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7251) IEEE80211_MAX_DATA_LEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7252) [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7253) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7255) static int nl80211_parse_mesh_config(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7256) struct mesh_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7257) u32 *mask_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7259) struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7260) u32 mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7261) u16 ht_opmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7263) #define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, mask, attr, fn) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7264) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7265) if (tb[attr]) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7266) cfg->param = fn(tb[attr]); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7267) mask |= BIT((attr) - 1); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7268) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7269) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7271) if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7272) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7273) if (nla_parse_nested_deprecated(tb, NL80211_MESHCONF_ATTR_MAX, info->attrs[NL80211_ATTR_MESH_CONFIG], nl80211_meshconf_params_policy, info->extack))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7274) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7276) /* This makes sure that there aren't more than 32 mesh config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7277) * parameters (otherwise our bitfield scheme would not work.) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7278) BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7280) /* Fill in the params struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7281) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7282) NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7283) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7284) NL80211_MESHCONF_CONFIRM_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7285) nla_get_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7286) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7287) NL80211_MESHCONF_HOLDING_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7288) nla_get_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7289) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7290) NL80211_MESHCONF_MAX_PEER_LINKS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7291) nla_get_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7292) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7293) NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7294) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7295) NL80211_MESHCONF_TTL, nla_get_u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7296) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7297) NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7298) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7299) NL80211_MESHCONF_AUTO_OPEN_PLINKS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7300) nla_get_u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7301) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7302) mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7303) NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7304) nla_get_u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7305) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7306) NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7307) nla_get_u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7308) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7309) NL80211_MESHCONF_PATH_REFRESH_TIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7310) nla_get_u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7311) if (mask & BIT(NL80211_MESHCONF_PATH_REFRESH_TIME) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7312) (cfg->path_refresh_time < 1 || cfg->path_refresh_time > 65535))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7313) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7314) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7315) NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7316) nla_get_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7317) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7318) mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7319) NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7320) nla_get_u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7321) if (mask & BIT(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7322) (cfg->dot11MeshHWMPactivePathTimeout < 1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7323) cfg->dot11MeshHWMPactivePathTimeout > 65535))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7324) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7325) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7326) NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7327) nla_get_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7328) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7329) NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7330) nla_get_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7331) FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7332) dot11MeshHWMPnetDiameterTraversalTime, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7333) NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7334) nla_get_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7335) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7336) NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7337) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7338) NL80211_MESHCONF_HWMP_RANN_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7339) nla_get_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7340) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshGateAnnouncementProtocol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7341) mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7342) nla_get_u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7343) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7344) NL80211_MESHCONF_FORWARDING, nla_get_u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7345) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7346) NL80211_MESHCONF_RSSI_THRESHOLD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7347) nla_get_s32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7348) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToMeshGate, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7349) NL80211_MESHCONF_CONNECTED_TO_GATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7350) nla_get_u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7351) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConnectedToAuthServer, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7352) NL80211_MESHCONF_CONNECTED_TO_AS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7353) nla_get_u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7354) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7355) * Check HT operation mode based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7356) * IEEE 802.11-2016 9.4.2.57 HT Operation element.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7358) if (tb[NL80211_MESHCONF_HT_OPMODE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7359) ht_opmode = nla_get_u16(tb[NL80211_MESHCONF_HT_OPMODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7361) if (ht_opmode & ~(IEEE80211_HT_OP_MODE_PROTECTION |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7362) IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7363) IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7364) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7366) /* NON_HT_STA bit is reserved, but some programs set it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7367) ht_opmode &= ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7369) cfg->ht_opmode = ht_opmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7370) mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7372) FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7373) dot11MeshHWMPactivePathToRootTimeout, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7374) NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7375) nla_get_u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7376) if (mask & BIT(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7377) (cfg->dot11MeshHWMPactivePathToRootTimeout < 1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7378) cfg->dot11MeshHWMPactivePathToRootTimeout > 65535))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7379) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7380) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7381) NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7382) nla_get_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7383) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPconfirmationInterval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7384) mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7385) NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7386) nla_get_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7387) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7388) NL80211_MESHCONF_POWER_MODE, nla_get_u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7389) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7390) NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7391) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7392) NL80211_MESHCONF_PLINK_TIMEOUT, nla_get_u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7393) FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNolearn, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7394) NL80211_MESHCONF_NOLEARN, nla_get_u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7395) if (mask_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7396) *mask_out = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7398) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7400) #undef FILL_IN_MESH_PARAM_IF_SET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7403) static int nl80211_parse_mesh_setup(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7404) struct mesh_setup *setup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7406) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7407) struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7409) if (!info->attrs[NL80211_ATTR_MESH_SETUP])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7410) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7411) if (nla_parse_nested_deprecated(tb, NL80211_MESH_SETUP_ATTR_MAX, info->attrs[NL80211_ATTR_MESH_SETUP], nl80211_mesh_setup_params_policy, info->extack))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7412) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7414) if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7415) setup->sync_method =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7416) (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7417) IEEE80211_SYNC_METHOD_VENDOR :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7418) IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7420) if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7421) setup->path_sel_proto =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7422) (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7423) IEEE80211_PATH_PROTOCOL_VENDOR :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7424) IEEE80211_PATH_PROTOCOL_HWMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7426) if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7427) setup->path_metric =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7428) (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7429) IEEE80211_PATH_METRIC_VENDOR :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7430) IEEE80211_PATH_METRIC_AIRTIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7432) if (tb[NL80211_MESH_SETUP_IE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7433) struct nlattr *ieattr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7434) tb[NL80211_MESH_SETUP_IE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7435) setup->ie = nla_data(ieattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7436) setup->ie_len = nla_len(ieattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7438) if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7439) !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7440) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7441) setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7442) setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7443) setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7444) if (setup->is_secure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7445) setup->user_mpm = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7447) if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7448) if (!setup->user_mpm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7449) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7450) setup->auth_id =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7451) nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7454) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7457) static int nl80211_update_mesh_config(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7458) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7460) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7461) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7462) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7463) struct mesh_config cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7464) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7465) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7467) if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7468) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7470) if (!rdev->ops->update_mesh_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7471) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7473) err = nl80211_parse_mesh_config(info, &cfg, &mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7474) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7475) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7477) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7478) if (!wdev->mesh_id_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7479) err = -ENOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7481) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7482) err = rdev_update_mesh_config(rdev, dev, mask, &cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7484) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7486) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7489) static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7490) struct sk_buff *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7492) struct nlattr *nl_reg_rules;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7493) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7495) if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7496) (regdom->dfs_region &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7497) nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7498) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7500) nl_reg_rules = nla_nest_start_noflag(msg, NL80211_ATTR_REG_RULES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7501) if (!nl_reg_rules)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7502) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7504) for (i = 0; i < regdom->n_reg_rules; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7505) struct nlattr *nl_reg_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7506) const struct ieee80211_reg_rule *reg_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7507) const struct ieee80211_freq_range *freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7508) const struct ieee80211_power_rule *power_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7509) unsigned int max_bandwidth_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7511) reg_rule = ®dom->reg_rules[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7512) freq_range = ®_rule->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7513) power_rule = ®_rule->power_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7515) nl_reg_rule = nla_nest_start_noflag(msg, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7516) if (!nl_reg_rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7517) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7519) max_bandwidth_khz = freq_range->max_bandwidth_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7520) if (!max_bandwidth_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7521) max_bandwidth_khz = reg_get_max_bandwidth(regdom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7522) reg_rule);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7524) if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7525) reg_rule->flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7526) nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7527) freq_range->start_freq_khz) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7528) nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7529) freq_range->end_freq_khz) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7530) nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7531) max_bandwidth_khz) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7532) nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7533) power_rule->max_antenna_gain) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7534) nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7535) power_rule->max_eirp) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7536) nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7537) reg_rule->dfs_cac_ms))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7538) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7540) nla_nest_end(msg, nl_reg_rule);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7543) nla_nest_end(msg, nl_reg_rules);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7544) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7546) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7547) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7550) static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7552) const struct ieee80211_regdomain *regdom = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7553) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7554) struct wiphy *wiphy = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7555) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7556) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7558) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7559) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7560) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7562) hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7563) NL80211_CMD_GET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7564) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7565) goto put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7567) if (info->attrs[NL80211_ATTR_WIPHY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7568) bool self_managed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7570) rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7571) if (IS_ERR(rdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7572) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7573) return PTR_ERR(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7576) wiphy = &rdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7577) self_managed = wiphy->regulatory_flags &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7578) REGULATORY_WIPHY_SELF_MANAGED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7579) regdom = get_wiphy_regdom(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7581) /* a self-managed-reg device must have a private regdom */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7582) if (WARN_ON(!regdom && self_managed)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7583) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7584) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7587) if (regdom &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7588) nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7589) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7592) if (!wiphy && reg_last_request_cell_base() &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7593) nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7594) NL80211_USER_REG_HINT_CELL_BASE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7595) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7597) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7599) if (!regdom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7600) regdom = rcu_dereference(cfg80211_regdomain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7602) if (nl80211_put_regdom(regdom, msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7603) goto nla_put_failure_rcu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7605) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7607) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7608) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7610) nla_put_failure_rcu:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7611) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7612) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7613) put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7614) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7615) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7618) static int nl80211_send_regdom(struct sk_buff *msg, struct netlink_callback *cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7619) u32 seq, int flags, struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7620) const struct ieee80211_regdomain *regdom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7621) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7622) void *hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7623) NL80211_CMD_GET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7625) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7626) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7628) genl_dump_check_consistent(cb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7630) if (nl80211_put_regdom(regdom, msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7631) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7633) if (!wiphy && reg_last_request_cell_base() &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7634) nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7635) NL80211_USER_REG_HINT_CELL_BASE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7636) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7638) if (wiphy &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7639) nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7640) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7642) if (wiphy && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7643) nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7644) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7646) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7647) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7649) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7650) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7651) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7654) static int nl80211_get_reg_dump(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7655) struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7657) const struct ieee80211_regdomain *regdom = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7658) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7659) int err, reg_idx, start = cb->args[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7661) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7663) if (cfg80211_regdomain && start == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7664) err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7665) NLM_F_MULTI, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7666) rtnl_dereference(cfg80211_regdomain));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7667) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7668) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7671) /* the global regdom is idx 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7672) reg_idx = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7673) list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7674) regdom = get_wiphy_regdom(&rdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7675) if (!regdom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7676) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7678) if (++reg_idx <= start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7679) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7681) err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7682) NLM_F_MULTI, &rdev->wiphy, regdom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7683) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7684) reg_idx--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7685) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7689) cb->args[2] = reg_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7690) err = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7691) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7692) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7693) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7696) #ifdef CONFIG_CFG80211_CRDA_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7697) static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7698) [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7699) [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7700) [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7701) [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7702) [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7703) [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7704) [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7705) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7707) static int parse_reg_rule(struct nlattr *tb[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7708) struct ieee80211_reg_rule *reg_rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7710) struct ieee80211_freq_range *freq_range = ®_rule->freq_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7711) struct ieee80211_power_rule *power_rule = ®_rule->power_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7713) if (!tb[NL80211_ATTR_REG_RULE_FLAGS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7714) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7715) if (!tb[NL80211_ATTR_FREQ_RANGE_START])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7716) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7717) if (!tb[NL80211_ATTR_FREQ_RANGE_END])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7718) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7719) if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7720) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7721) if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7722) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7724) reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7726) freq_range->start_freq_khz =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7727) nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7728) freq_range->end_freq_khz =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7729) nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7730) freq_range->max_bandwidth_khz =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7731) nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7733) power_rule->max_eirp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7734) nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7736) if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7737) power_rule->max_antenna_gain =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7738) nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7740) if (tb[NL80211_ATTR_DFS_CAC_TIME])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7741) reg_rule->dfs_cac_ms =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7742) nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7744) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7747) static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7749) struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7750) struct nlattr *nl_reg_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7751) char *alpha2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7752) int rem_reg_rules, r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7753) u32 num_rules = 0, rule_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7754) enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7755) struct ieee80211_regdomain *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7757) if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7758) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7760) if (!info->attrs[NL80211_ATTR_REG_RULES])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7761) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7763) alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7765) if (info->attrs[NL80211_ATTR_DFS_REGION])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7766) dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7768) nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7769) rem_reg_rules) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7770) num_rules++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7771) if (num_rules > NL80211_MAX_SUPP_REG_RULES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7772) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7775) if (!reg_is_valid_request(alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7776) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7778) rd = kzalloc(struct_size(rd, reg_rules, num_rules), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7779) if (!rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7780) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7782) rd->n_reg_rules = num_rules;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7783) rd->alpha2[0] = alpha2[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7784) rd->alpha2[1] = alpha2[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7786) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7787) * Disable DFS master mode if the DFS region was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7788) * not supported or known on this kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7789) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7790) if (reg_supported_dfs_region(dfs_region))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7791) rd->dfs_region = dfs_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7793) nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7794) rem_reg_rules) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7795) r = nla_parse_nested_deprecated(tb, NL80211_REG_RULE_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7796) nl_reg_rule, reg_rule_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7797) info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7798) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7799) goto bad_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7800) r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7801) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7802) goto bad_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7804) rule_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7806) if (rule_idx > NL80211_MAX_SUPP_REG_RULES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7807) r = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7808) goto bad_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7812) /* set_regdom takes ownership of rd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7813) return set_regdom(rd, REGD_SOURCE_CRDA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7814) bad_reg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7815) kfree(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7816) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7818) #endif /* CONFIG_CFG80211_CRDA_SUPPORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7820) static int validate_scan_freqs(struct nlattr *freqs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7822) struct nlattr *attr1, *attr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7823) int n_channels = 0, tmp1, tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7825) nla_for_each_nested(attr1, freqs, tmp1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7826) if (nla_len(attr1) != sizeof(u32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7827) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7829) nla_for_each_nested(attr1, freqs, tmp1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7830) n_channels++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7831) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7832) * Some hardware has a limited channel list for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7833) * scanning, and it is pretty much nonsensical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7834) * to scan for a channel twice, so disallow that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7835) * and don't require drivers to check that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7836) * channel list they get isn't longer than what
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7837) * they can scan, as long as they can scan all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7838) * the channels they registered at once.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7839) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7840) nla_for_each_nested(attr2, freqs, tmp2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7841) if (attr1 != attr2 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7842) nla_get_u32(attr1) == nla_get_u32(attr2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7843) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7846) return n_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7849) static bool is_band_valid(struct wiphy *wiphy, enum nl80211_band b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7851) return b < NUM_NL80211_BANDS && wiphy->bands[b];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7854) static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7855) struct cfg80211_bss_selection *bss_select)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7856) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7857) struct nlattr *attr[NL80211_BSS_SELECT_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7858) struct nlattr *nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7859) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7860) bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7861) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7863) /* only process one nested attribute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7864) nest = nla_data(nla);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7865) if (!nla_ok(nest, nla_len(nest)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7866) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7868) err = nla_parse_nested_deprecated(attr, NL80211_BSS_SELECT_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7869) nest, nl80211_bss_select_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7870) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7871) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7872) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7874) /* only one attribute may be given */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7875) for (i = 0; i <= NL80211_BSS_SELECT_ATTR_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7876) if (attr[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7877) if (found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7878) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7879) found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7883) bss_select->behaviour = __NL80211_BSS_SELECT_ATTR_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7885) if (attr[NL80211_BSS_SELECT_ATTR_RSSI])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7886) bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7888) if (attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7889) bss_select->behaviour = NL80211_BSS_SELECT_ATTR_BAND_PREF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7890) bss_select->param.band_pref =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7891) nla_get_u32(attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7892) if (!is_band_valid(wiphy, bss_select->param.band_pref))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7893) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7896) if (attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7897) struct nl80211_bss_select_rssi_adjust *adj_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7899) adj_param = nla_data(attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7900) bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI_ADJUST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7901) bss_select->param.adjust.band = adj_param->band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7902) bss_select->param.adjust.delta = adj_param->delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7903) if (!is_band_valid(wiphy, bss_select->param.adjust.band))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7904) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7907) /* user-space did not provide behaviour attribute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7908) if (bss_select->behaviour == __NL80211_BSS_SELECT_ATTR_INVALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7909) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7911) if (!(wiphy->bss_select_support & BIT(bss_select->behaviour)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7912) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7914) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7917) int nl80211_parse_random_mac(struct nlattr **attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7918) u8 *mac_addr, u8 *mac_addr_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7919) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7920) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7922) if (!attrs[NL80211_ATTR_MAC] && !attrs[NL80211_ATTR_MAC_MASK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7923) eth_zero_addr(mac_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7924) eth_zero_addr(mac_addr_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7925) mac_addr[0] = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7926) mac_addr_mask[0] = 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7928) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7931) /* need both or none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7932) if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_MAC_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7933) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7935) memcpy(mac_addr, nla_data(attrs[NL80211_ATTR_MAC]), ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7936) memcpy(mac_addr_mask, nla_data(attrs[NL80211_ATTR_MAC_MASK]), ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7938) /* don't allow or configure an mcast address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7939) if (!is_multicast_ether_addr(mac_addr_mask) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7940) is_multicast_ether_addr(mac_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7941) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7943) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7944) * allow users to pass a MAC address that has bits set outside
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7945) * of the mask, but don't bother drivers with having to deal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7946) * with such bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7947) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7948) for (i = 0; i < ETH_ALEN; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7949) mac_addr[i] &= mac_addr_mask[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7951) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7954) static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7956) ASSERT_WDEV_LOCK(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7958) if (!cfg80211_beaconing_iface_active(wdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7959) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7961) if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7962) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7964) return regulatory_pre_cac_allowed(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7967) static bool nl80211_check_scan_feat(struct wiphy *wiphy, u32 flags, u32 flag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7968) enum nl80211_ext_feature_index feat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7970) if (!(flags & flag))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7971) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7972) if (wiphy_ext_feature_isset(wiphy, feat))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7973) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7974) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7977) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7978) nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7979) void *request, struct nlattr **attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7980) bool is_sched_scan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7981) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7982) u8 *mac_addr, *mac_addr_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7983) u32 *flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7984) enum nl80211_feature_flags randomness_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7986) if (!attrs[NL80211_ATTR_SCAN_FLAGS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7987) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7989) if (is_sched_scan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7990) struct cfg80211_sched_scan_request *req = request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7992) randomness_flag = wdev ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7993) NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7994) NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7995) flags = &req->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7996) mac_addr = req->mac_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7997) mac_addr_mask = req->mac_addr_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7998) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7999) struct cfg80211_scan_request *req = request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8001) randomness_flag = NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8002) flags = &req->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8003) mac_addr = req->mac_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8004) mac_addr_mask = req->mac_addr_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8007) *flags = nla_get_u32(attrs[NL80211_ATTR_SCAN_FLAGS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8009) if (((*flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8010) !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8011) !nl80211_check_scan_feat(wiphy, *flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8012) NL80211_SCAN_FLAG_LOW_SPAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8013) NL80211_EXT_FEATURE_LOW_SPAN_SCAN) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8014) !nl80211_check_scan_feat(wiphy, *flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8015) NL80211_SCAN_FLAG_LOW_POWER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8016) NL80211_EXT_FEATURE_LOW_POWER_SCAN) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8017) !nl80211_check_scan_feat(wiphy, *flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8018) NL80211_SCAN_FLAG_HIGH_ACCURACY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8019) NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8020) !nl80211_check_scan_feat(wiphy, *flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8021) NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8022) NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8023) !nl80211_check_scan_feat(wiphy, *flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8024) NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8025) NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8026) !nl80211_check_scan_feat(wiphy, *flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8027) NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8028) NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8029) !nl80211_check_scan_feat(wiphy, *flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8030) NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8031) NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8032) !nl80211_check_scan_feat(wiphy, *flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8033) NL80211_SCAN_FLAG_RANDOM_SN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8034) NL80211_EXT_FEATURE_SCAN_RANDOM_SN) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8035) !nl80211_check_scan_feat(wiphy, *flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8036) NL80211_SCAN_FLAG_MIN_PREQ_CONTENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8037) NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8038) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8040) if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8041) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8043) if (!(wiphy->features & randomness_flag) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8044) (wdev && wdev->current_bss))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8045) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8047) err = nl80211_parse_random_mac(attrs, mac_addr, mac_addr_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8048) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8049) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8052) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8055) static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8056) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8057) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8058) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8059) struct cfg80211_scan_request *request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8060) struct nlattr *scan_freqs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8061) bool scan_freqs_khz = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8062) struct nlattr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8063) struct wiphy *wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8064) int err, tmp, n_ssids = 0, n_channels, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8065) size_t ie_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8067) wiphy = &rdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8069) if (wdev->iftype == NL80211_IFTYPE_NAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8070) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8072) if (!rdev->ops->scan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8073) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8075) if (rdev->scan_req || rdev->scan_msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8076) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8078) if (info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8079) if (!wiphy_ext_feature_isset(wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8080) NL80211_EXT_FEATURE_SCAN_FREQ_KHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8081) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8082) scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQ_KHZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8083) scan_freqs_khz = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8084) } else if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8085) scan_freqs = info->attrs[NL80211_ATTR_SCAN_FREQUENCIES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8087) if (scan_freqs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8088) n_channels = validate_scan_freqs(scan_freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8089) if (!n_channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8090) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8091) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8092) n_channels = ieee80211_get_num_supported_channels(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8095) if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8096) nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8097) n_ssids++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8099) if (n_ssids > wiphy->max_scan_ssids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8100) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8102) if (info->attrs[NL80211_ATTR_IE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8103) ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8104) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8105) ie_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8107) if (ie_len > wiphy->max_scan_ie_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8108) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8110) request = kzalloc(sizeof(*request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8111) + sizeof(*request->ssids) * n_ssids
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8112) + sizeof(*request->channels) * n_channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8113) + ie_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8114) if (!request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8115) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8117) if (n_ssids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8118) request->ssids = (void *)&request->channels[n_channels];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8119) request->n_ssids = n_ssids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8120) if (ie_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8121) if (n_ssids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8122) request->ie = (void *)(request->ssids + n_ssids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8123) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8124) request->ie = (void *)(request->channels + n_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8127) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8128) if (scan_freqs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8129) /* user specified, bail out if channel not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8130) nla_for_each_nested(attr, scan_freqs, tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8131) struct ieee80211_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8132) int freq = nla_get_u32(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8134) if (!scan_freqs_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8135) freq = MHZ_TO_KHZ(freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8137) chan = ieee80211_get_channel_khz(wiphy, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8138) if (!chan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8139) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8140) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8143) /* ignore disabled channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8144) if (chan->flags & IEEE80211_CHAN_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8145) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8147) request->channels[i] = chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8148) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8150) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8151) enum nl80211_band band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8153) /* all channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8154) for (band = 0; band < NUM_NL80211_BANDS; band++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8155) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8157) if (!wiphy->bands[band])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8158) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8159) for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8160) struct ieee80211_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8162) chan = &wiphy->bands[band]->channels[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8164) if (chan->flags & IEEE80211_CHAN_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8165) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8167) request->channels[i] = chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8168) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8173) if (!i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8174) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8175) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8178) request->n_channels = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8180) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8181) if (!cfg80211_off_channel_oper_allowed(wdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8182) struct ieee80211_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8184) if (request->n_channels != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8185) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8186) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8187) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8190) chan = request->channels[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8191) if (chan->center_freq != wdev->chandef.chan->center_freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8192) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8193) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8194) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8197) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8199) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8200) if (n_ssids) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8201) nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8202) if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8203) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8204) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8206) request->ssids[i].ssid_len = nla_len(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8207) memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8208) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8212) if (info->attrs[NL80211_ATTR_IE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8213) request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8214) memcpy((void *)request->ie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8215) nla_data(info->attrs[NL80211_ATTR_IE]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8216) request->ie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8219) for (i = 0; i < NUM_NL80211_BANDS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8220) if (wiphy->bands[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8221) request->rates[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8222) (1 << wiphy->bands[i]->n_bitrates) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8224) if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8225) nla_for_each_nested(attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8226) info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8227) tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8228) enum nl80211_band band = nla_type(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8230) if (band < 0 || band >= NUM_NL80211_BANDS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8231) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8232) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8235) if (!wiphy->bands[band])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8236) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8238) err = ieee80211_get_ratemask(wiphy->bands[band],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8239) nla_data(attr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8240) nla_len(attr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8241) &request->rates[band]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8242) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8243) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8247) if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8248) if (!wiphy_ext_feature_isset(wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8249) NL80211_EXT_FEATURE_SET_SCAN_DWELL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8250) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8251) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8254) request->duration =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8255) nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8256) request->duration_mandatory =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8257) nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8260) err = nl80211_check_scan_flags(wiphy, wdev, request, info->attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8261) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8262) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8263) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8265) request->no_cck =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8266) nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8268) /* Initial implementation used NL80211_ATTR_MAC to set the specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8269) * BSSID to scan for. This was problematic because that same attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8270) * was already used for another purpose (local random MAC address). The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8271) * NL80211_ATTR_BSSID attribute was added to fix this. For backwards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8272) * compatibility with older userspace components, also use the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8273) * NL80211_ATTR_MAC value here if it can be determined to be used for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8274) * the specific BSSID use case instead of the random MAC address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8275) * (NL80211_ATTR_SCAN_FLAGS is used to enable random MAC address use).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8277) if (info->attrs[NL80211_ATTR_BSSID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8278) memcpy(request->bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8279) nla_data(info->attrs[NL80211_ATTR_BSSID]), ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8280) else if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8281) info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8282) memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8283) ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8284) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8285) eth_broadcast_addr(request->bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8287) request->wdev = wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8288) request->wiphy = &rdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8289) request->scan_start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8291) rdev->scan_req = request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8292) err = cfg80211_scan(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8294) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8295) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8297) nl80211_send_scan_start(rdev, wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8298) if (wdev->netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8299) dev_hold(wdev->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8301) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8303) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8304) rdev->scan_req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8305) kfree(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8307) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8310) static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8312) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8313) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8315) if (!rdev->ops->abort_scan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8316) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8318) if (rdev->scan_msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8319) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8321) if (!rdev->scan_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8322) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8324) rdev_abort_scan(rdev, wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8325) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8328) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8329) nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8330) struct cfg80211_sched_scan_request *request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8331) struct nlattr **attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8333) int tmp, err, i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8334) struct nlattr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8336) if (!attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8337) u32 interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8339) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8340) * If scan plans are not specified,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8341) * %NL80211_ATTR_SCHED_SCAN_INTERVAL will be specified. In this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8342) * case one scan plan will be set with the specified scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8343) * interval and infinite number of iterations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8344) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8345) interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8346) if (!interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8347) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8349) request->scan_plans[0].interval =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8350) DIV_ROUND_UP(interval, MSEC_PER_SEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8351) if (!request->scan_plans[0].interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8352) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8354) if (request->scan_plans[0].interval >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8355) wiphy->max_sched_scan_plan_interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8356) request->scan_plans[0].interval =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8357) wiphy->max_sched_scan_plan_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8359) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8362) nla_for_each_nested(attr, attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8363) struct nlattr *plan[NL80211_SCHED_SCAN_PLAN_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8365) if (WARN_ON(i >= n_plans))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8366) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8368) err = nla_parse_nested_deprecated(plan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8369) NL80211_SCHED_SCAN_PLAN_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8370) attr, nl80211_plan_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8371) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8372) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8373) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8375) if (!plan[NL80211_SCHED_SCAN_PLAN_INTERVAL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8376) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8378) request->scan_plans[i].interval =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8379) nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_INTERVAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8380) if (!request->scan_plans[i].interval ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8381) request->scan_plans[i].interval >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8382) wiphy->max_sched_scan_plan_interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8383) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8385) if (plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8386) request->scan_plans[i].iterations =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8387) nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8388) if (!request->scan_plans[i].iterations ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8389) (request->scan_plans[i].iterations >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8390) wiphy->max_sched_scan_plan_iterations))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8391) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8392) } else if (i < n_plans - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8393) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8394) * All scan plans but the last one must specify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8395) * a finite number of iterations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8396) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8397) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8400) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8403) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8404) * The last scan plan must not specify the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8405) * iterations, it is supposed to run infinitely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8407) if (request->scan_plans[n_plans - 1].iterations)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8408) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8410) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8413) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8414) nl80211_parse_sched_scan_per_band_rssi(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8415) struct cfg80211_match_set *match_sets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8416) struct nlattr *tb_band_rssi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8417) s32 rssi_thold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8419) struct nlattr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8420) int i, tmp, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8422) if (!wiphy_ext_feature_isset(wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8423) NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8424) if (tb_band_rssi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8425) ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8426) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8427) for (i = 0; i < NUM_NL80211_BANDS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8428) match_sets->per_band_rssi_thold[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8429) NL80211_SCAN_RSSI_THOLD_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8430) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8433) for (i = 0; i < NUM_NL80211_BANDS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8434) match_sets->per_band_rssi_thold[i] = rssi_thold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8436) nla_for_each_nested(attr, tb_band_rssi, tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8437) enum nl80211_band band = nla_type(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8439) if (band < 0 || band >= NUM_NL80211_BANDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8440) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8442) match_sets->per_band_rssi_thold[band] = nla_get_s32(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8445) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8448) static struct cfg80211_sched_scan_request *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8449) nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8450) struct nlattr **attrs, int max_match_sets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8452) struct cfg80211_sched_scan_request *request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8453) struct nlattr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8454) int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i, n_plans = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8455) enum nl80211_band band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8456) size_t ie_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8457) struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8458) s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8460) if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8461) n_channels = validate_scan_freqs(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8462) attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8463) if (!n_channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8464) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8465) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8466) n_channels = ieee80211_get_num_supported_channels(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8469) if (attrs[NL80211_ATTR_SCAN_SSIDS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8470) nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8471) tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8472) n_ssids++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8474) if (n_ssids > wiphy->max_sched_scan_ssids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8475) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8477) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8478) * First, count the number of 'real' matchsets. Due to an issue with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8479) * the old implementation, matchsets containing only the RSSI attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8480) * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8481) * RSSI for all matchsets, rather than their own matchset for reporting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8482) * all APs with a strong RSSI. This is needed to be compatible with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8483) * older userspace that treated a matchset with only the RSSI as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8484) * global RSSI for all other matchsets - if there are other matchsets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8485) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8486) if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8487) nla_for_each_nested(attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8488) attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8489) tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8490) struct nlattr *rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8492) err = nla_parse_nested_deprecated(tb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8493) NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8494) attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8495) nl80211_match_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8496) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8497) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8498) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8500) /* SSID and BSSID are mutually exclusive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8501) if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8502) tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8503) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8505) /* add other standalone attributes here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8506) if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8507) tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8508) n_match_sets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8509) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8511) rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8512) if (rssi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8513) default_match_rssi = nla_get_s32(rssi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8517) /* However, if there's no other matchset, add the RSSI one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8518) if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8519) n_match_sets = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8521) if (n_match_sets > max_match_sets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8522) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8524) if (attrs[NL80211_ATTR_IE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8525) ie_len = nla_len(attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8526) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8527) ie_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8529) if (ie_len > wiphy->max_sched_scan_ie_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8530) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8532) if (attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8533) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8534) * NL80211_ATTR_SCHED_SCAN_INTERVAL must not be specified since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8535) * each scan plan already specifies its own interval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8536) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8537) if (attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8538) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8540) nla_for_each_nested(attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8541) attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8542) n_plans++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8543) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8544) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8545) * The scan interval attribute is kept for backward
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8546) * compatibility. If no scan plans are specified and sched scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8547) * interval is specified, one scan plan will be set with this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8548) * scan interval and infinite number of iterations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8549) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8550) if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8551) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8553) n_plans = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8556) if (!n_plans || n_plans > wiphy->max_sched_scan_plans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8557) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8559) if (!wiphy_ext_feature_isset(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8560) wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8561) (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8562) attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8563) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8565) request = kzalloc(sizeof(*request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8566) + sizeof(*request->ssids) * n_ssids
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8567) + sizeof(*request->match_sets) * n_match_sets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8568) + sizeof(*request->scan_plans) * n_plans
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8569) + sizeof(*request->channels) * n_channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8570) + ie_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8571) if (!request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8572) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8574) if (n_ssids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8575) request->ssids = (void *)&request->channels[n_channels];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8576) request->n_ssids = n_ssids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8577) if (ie_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8578) if (n_ssids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8579) request->ie = (void *)(request->ssids + n_ssids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8580) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8581) request->ie = (void *)(request->channels + n_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8584) if (n_match_sets) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8585) if (request->ie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8586) request->match_sets = (void *)(request->ie + ie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8587) else if (n_ssids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8588) request->match_sets =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8589) (void *)(request->ssids + n_ssids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8590) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8591) request->match_sets =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8592) (void *)(request->channels + n_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8594) request->n_match_sets = n_match_sets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8596) if (n_match_sets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8597) request->scan_plans = (void *)(request->match_sets +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8598) n_match_sets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8599) else if (request->ie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8600) request->scan_plans = (void *)(request->ie + ie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8601) else if (n_ssids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8602) request->scan_plans = (void *)(request->ssids + n_ssids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8603) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8604) request->scan_plans = (void *)(request->channels + n_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8606) request->n_scan_plans = n_plans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8608) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8609) if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8610) /* user specified, bail out if channel not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8611) nla_for_each_nested(attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8612) attrs[NL80211_ATTR_SCAN_FREQUENCIES],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8613) tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8614) struct ieee80211_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8616) chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8618) if (!chan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8619) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8620) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8623) /* ignore disabled channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8624) if (chan->flags & IEEE80211_CHAN_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8625) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8627) request->channels[i] = chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8628) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8630) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8631) /* all channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8632) for (band = 0; band < NUM_NL80211_BANDS; band++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8633) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8635) if (!wiphy->bands[band])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8636) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8637) for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8638) struct ieee80211_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8640) chan = &wiphy->bands[band]->channels[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8642) if (chan->flags & IEEE80211_CHAN_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8643) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8645) request->channels[i] = chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8646) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8651) if (!i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8652) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8653) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8656) request->n_channels = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8658) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8659) if (n_ssids) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8660) nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8661) tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8662) if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8663) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8664) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8666) request->ssids[i].ssid_len = nla_len(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8667) memcpy(request->ssids[i].ssid, nla_data(attr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8668) nla_len(attr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8669) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8673) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8674) if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8675) nla_for_each_nested(attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8676) attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8677) tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8678) struct nlattr *ssid, *bssid, *rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8680) err = nla_parse_nested_deprecated(tb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8681) NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8682) attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8683) nl80211_match_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8684) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8685) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8686) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8687) ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8688) bssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8690) if (!ssid && !bssid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8691) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8692) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8695) if (WARN_ON(i >= n_match_sets)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8696) /* this indicates a programming error,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8697) * the loop above should have verified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8698) * things properly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8699) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8700) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8701) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8704) if (ssid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8705) memcpy(request->match_sets[i].ssid.ssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8706) nla_data(ssid), nla_len(ssid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8707) request->match_sets[i].ssid.ssid_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8708) nla_len(ssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8710) if (bssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8711) memcpy(request->match_sets[i].bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8712) nla_data(bssid), ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8714) /* special attribute - old implementation w/a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8715) request->match_sets[i].rssi_thold = default_match_rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8716) rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8717) if (rssi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8718) request->match_sets[i].rssi_thold =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8719) nla_get_s32(rssi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8721) /* Parse per band RSSI attribute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8722) err = nl80211_parse_sched_scan_per_band_rssi(wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8723) &request->match_sets[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8724) tb[NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8725) request->match_sets[i].rssi_thold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8726) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8727) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8729) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8732) /* there was no other matchset, so the RSSI one is alone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8733) if (i == 0 && n_match_sets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8734) request->match_sets[0].rssi_thold = default_match_rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8736) request->min_rssi_thold = INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8737) for (i = 0; i < n_match_sets; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8738) request->min_rssi_thold =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8739) min(request->match_sets[i].rssi_thold,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8740) request->min_rssi_thold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8741) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8742) request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8745) if (ie_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8746) request->ie_len = ie_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8747) memcpy((void *)request->ie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8748) nla_data(attrs[NL80211_ATTR_IE]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8749) request->ie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8752) err = nl80211_check_scan_flags(wiphy, wdev, request, attrs, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8753) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8754) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8756) if (attrs[NL80211_ATTR_SCHED_SCAN_DELAY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8757) request->delay =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8758) nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8760) if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8761) request->relative_rssi = nla_get_s8(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8762) attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8763) request->relative_rssi_set = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8766) if (request->relative_rssi_set &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8767) attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8768) struct nl80211_bss_select_rssi_adjust *rssi_adjust;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8770) rssi_adjust = nla_data(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8771) attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8772) request->rssi_adjust.band = rssi_adjust->band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8773) request->rssi_adjust.delta = rssi_adjust->delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8774) if (!is_band_valid(wiphy, request->rssi_adjust.band)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8775) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8776) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8780) err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8781) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8782) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8784) request->scan_start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8786) return request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8788) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8789) kfree(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8790) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8793) static int nl80211_start_sched_scan(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8794) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8796) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8797) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8798) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8799) struct cfg80211_sched_scan_request *sched_scan_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8800) bool want_multi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8801) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8803) if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8804) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8806) want_multi = info->attrs[NL80211_ATTR_SCHED_SCAN_MULTI];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8807) err = cfg80211_sched_scan_req_possible(rdev, want_multi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8808) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8809) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8811) sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8812) info->attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8813) rdev->wiphy.max_match_sets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8815) err = PTR_ERR_OR_ZERO(sched_scan_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8816) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8817) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8819) /* leave request id zero for legacy request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8820) * or if driver does not support multi-scheduled scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8821) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8822) if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8823) sched_scan_req->reqid = cfg80211_assign_cookie(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8825) err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8826) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8827) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8829) sched_scan_req->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8830) sched_scan_req->wiphy = &rdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8832) if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8833) sched_scan_req->owner_nlportid = info->snd_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8835) cfg80211_add_sched_scan_req(rdev, sched_scan_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8837) nl80211_send_sched_scan(sched_scan_req, NL80211_CMD_START_SCHED_SCAN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8838) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8840) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8841) kfree(sched_scan_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8842) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8843) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8846) static int nl80211_stop_sched_scan(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8847) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8848) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8849) struct cfg80211_sched_scan_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8850) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8851) u64 cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8853) if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8854) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8856) if (info->attrs[NL80211_ATTR_COOKIE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8857) cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8858) return __cfg80211_stop_sched_scan(rdev, cookie, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8861) req = list_first_or_null_rcu(&rdev->sched_scan_req_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8862) struct cfg80211_sched_scan_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8863) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8864) if (!req || req->reqid ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8865) (req->owner_nlportid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8866) req->owner_nlportid != info->snd_portid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8867) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8869) return cfg80211_stop_sched_scan_req(rdev, req, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8872) static int nl80211_start_radar_detection(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8873) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8874) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8875) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8876) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8877) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8878) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8879) struct cfg80211_chan_def chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8880) enum nl80211_dfs_regions dfs_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8881) unsigned int cac_time_ms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8882) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8884) dfs_region = reg_get_dfs_region(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8885) if (dfs_region == NL80211_DFS_UNSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8886) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8888) err = nl80211_parse_chandef(rdev, info, &chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8889) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8890) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8892) if (netif_carrier_ok(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8893) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8895) if (wdev->cac_started)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8896) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8898) err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8899) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8900) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8902) if (err == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8903) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8905) if (!cfg80211_chandef_dfs_usable(wiphy, &chandef))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8906) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8908) /* CAC start is offloaded to HW and can't be started manually */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8909) if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8910) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8912) if (!rdev->ops->start_radar_detection)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8913) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8915) cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8916) if (WARN_ON(!cac_time_ms))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8917) cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8919) err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8920) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8921) wdev->chandef = chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8922) wdev->cac_started = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8923) wdev->cac_start_time = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8924) wdev->cac_time_ms = cac_time_ms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8926) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8929) static int nl80211_notify_radar_detection(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8930) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8931) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8932) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8933) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8934) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8935) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8936) struct cfg80211_chan_def chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8937) enum nl80211_dfs_regions dfs_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8938) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8940) dfs_region = reg_get_dfs_region(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8941) if (dfs_region == NL80211_DFS_UNSET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8942) GENL_SET_ERR_MSG(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8943) "DFS Region is not set. Unexpected Radar indication");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8944) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8947) err = nl80211_parse_chandef(rdev, info, &chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8948) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8949) GENL_SET_ERR_MSG(info, "Unable to extract chandef info");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8950) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8953) err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8954) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8955) GENL_SET_ERR_MSG(info, "chandef is invalid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8956) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8959) if (err == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8960) GENL_SET_ERR_MSG(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8961) "Unexpected Radar indication for chandef/iftype");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8962) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8965) /* Do not process this notification if radar is already detected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8966) * by kernel on this channel, and return success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8967) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8968) if (chandef.chan->dfs_state == NL80211_DFS_UNAVAILABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8969) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8971) cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_UNAVAILABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8973) cfg80211_sched_dfs_chan_update(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8975) rdev->radar_chandef = chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8977) /* Propagate this notification to other radios as well */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8978) queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8980) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8983) static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8985) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8986) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8987) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8988) struct cfg80211_csa_settings params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8989) /* csa_attrs is defined static to avoid waste of stack size - this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8990) * function is called under RTNL lock, so this should not be a problem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8991) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8992) static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8993) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8994) bool need_new_beacon = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8995) bool need_handle_dfs_flag = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8996) int len, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8997) u32 cs_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8999) if (!rdev->ops->channel_switch ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9000) !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9001) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9003) switch (dev->ieee80211_ptr->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9004) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9005) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9006) need_new_beacon = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9007) /* For all modes except AP the handle_dfs flag needs to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9008) * supplied to tell the kernel that userspace will handle radar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9009) * events when they happen. Otherwise a switch to a channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9010) * requiring DFS will be rejected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9011) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9012) need_handle_dfs_flag = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9014) /* useless if AP is not running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9015) if (!wdev->beacon_interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9016) return -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9017) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9018) case NL80211_IFTYPE_ADHOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9019) if (!wdev->ssid_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9020) return -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9021) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9022) case NL80211_IFTYPE_MESH_POINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9023) if (!wdev->mesh_id_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9024) return -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9025) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9026) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9027) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9030) memset(¶ms, 0, sizeof(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9031) params.beacon_csa.ftm_responder = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9033) if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9034) !info->attrs[NL80211_ATTR_CH_SWITCH_COUNT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9035) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9037) /* only important for AP, IBSS and mesh create IEs internally */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9038) if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9039) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9041) /* Even though the attribute is u32, the specification says
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9042) * u8, so let's make sure we don't overflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9043) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9044) cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9045) if (cs_count > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9046) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9048) params.count = cs_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9050) if (!need_new_beacon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9051) goto skip_beacons;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9053) err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon_after);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9054) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9055) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9057) err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9058) info->attrs[NL80211_ATTR_CSA_IES],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9059) nl80211_policy, info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9060) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9061) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9063) err = nl80211_parse_beacon(rdev, csa_attrs, ¶ms.beacon_csa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9064) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9065) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9067) if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9068) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9070) len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9071) if (!len || (len % sizeof(u16)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9072) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9074) params.n_counter_offsets_beacon = len / sizeof(u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9075) if (rdev->wiphy.max_num_csa_counters &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9076) (params.n_counter_offsets_beacon >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9077) rdev->wiphy.max_num_csa_counters))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9078) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9080) params.counter_offsets_beacon =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9081) nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9083) /* sanity checks - counters should fit and be the same */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9084) for (i = 0; i < params.n_counter_offsets_beacon; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9085) u16 offset = params.counter_offsets_beacon[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9087) if (offset >= params.beacon_csa.tail_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9088) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9090) if (params.beacon_csa.tail[offset] != params.count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9091) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9094) if (csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9095) len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9096) if (!len || (len % sizeof(u16)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9097) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9099) params.n_counter_offsets_presp = len / sizeof(u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9100) if (rdev->wiphy.max_num_csa_counters &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9101) (params.n_counter_offsets_presp >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9102) rdev->wiphy.max_num_csa_counters))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9103) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9105) params.counter_offsets_presp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9106) nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9108) /* sanity checks - counters should fit and be the same */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9109) for (i = 0; i < params.n_counter_offsets_presp; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9110) u16 offset = params.counter_offsets_presp[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9112) if (offset >= params.beacon_csa.probe_resp_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9113) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9115) if (params.beacon_csa.probe_resp[offset] !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9116) params.count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9117) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9121) skip_beacons:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9122) err = nl80211_parse_chandef(rdev, info, ¶ms.chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9123) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9124) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9126) if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9127) wdev->iftype))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9128) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9130) err = cfg80211_chandef_dfs_required(wdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9131) ¶ms.chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9132) wdev->iftype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9133) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9134) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9136) if (err > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9137) params.radar_required = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9138) if (need_handle_dfs_flag &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9139) !nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9140) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9144) if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9145) params.block_tx = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9147) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9148) err = rdev_channel_switch(rdev, dev, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9149) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9151) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9154) static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9155) u32 seq, int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9156) struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9157) struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9158) struct cfg80211_internal_bss *intbss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9160) struct cfg80211_bss *res = &intbss->pub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9161) const struct cfg80211_bss_ies *ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9162) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9163) struct nlattr *bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9165) ASSERT_WDEV_LOCK(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9167) hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9168) NL80211_CMD_NEW_SCAN_RESULTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9169) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9170) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9172) genl_dump_check_consistent(cb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9174) if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9175) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9176) if (wdev->netdev &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9177) nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9178) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9179) if (nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9180) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9181) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9183) bss = nla_nest_start_noflag(msg, NL80211_ATTR_BSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9184) if (!bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9185) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9186) if ((!is_zero_ether_addr(res->bssid) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9187) nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9188) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9190) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9191) /* indicate whether we have probe response data or not */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9192) if (rcu_access_pointer(res->proberesp_ies) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9193) nla_put_flag(msg, NL80211_BSS_PRESP_DATA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9194) goto fail_unlock_rcu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9196) /* this pointer prefers to be pointed to probe response data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9197) * but is always valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9198) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9199) ies = rcu_dereference(res->ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9200) if (ies) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9201) if (nla_put_u64_64bit(msg, NL80211_BSS_TSF, ies->tsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9202) NL80211_BSS_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9203) goto fail_unlock_rcu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9204) if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9205) ies->len, ies->data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9206) goto fail_unlock_rcu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9209) /* and this pointer is always (unless driver didn't know) beacon data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9210) ies = rcu_dereference(res->beacon_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9211) if (ies && ies->from_beacon) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9212) if (nla_put_u64_64bit(msg, NL80211_BSS_BEACON_TSF, ies->tsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9213) NL80211_BSS_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9214) goto fail_unlock_rcu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9215) if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9216) ies->len, ies->data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9217) goto fail_unlock_rcu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9219) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9221) if (res->beacon_interval &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9222) nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9223) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9224) if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9225) nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9226) nla_put_u32(msg, NL80211_BSS_FREQUENCY_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9227) res->channel->freq_offset) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9228) nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9229) nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9230) jiffies_to_msecs(jiffies - intbss->ts)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9231) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9233) if (intbss->parent_tsf &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9234) (nla_put_u64_64bit(msg, NL80211_BSS_PARENT_TSF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9235) intbss->parent_tsf, NL80211_BSS_PAD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9236) nla_put(msg, NL80211_BSS_PARENT_BSSID, ETH_ALEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9237) intbss->parent_bssid)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9238) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9240) if (intbss->ts_boottime &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9241) nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9242) intbss->ts_boottime, NL80211_BSS_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9243) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9245) if (!nl80211_put_signal(msg, intbss->pub.chains,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9246) intbss->pub.chain_signal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9247) NL80211_BSS_CHAIN_SIGNAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9248) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9250) switch (rdev->wiphy.signal_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9251) case CFG80211_SIGNAL_TYPE_MBM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9252) if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9253) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9255) case CFG80211_SIGNAL_TYPE_UNSPEC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9256) if (nla_put_u8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9257) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9258) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9259) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9263) switch (wdev->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9264) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9265) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9266) if (intbss == wdev->current_bss &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9267) nla_put_u32(msg, NL80211_BSS_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9268) NL80211_BSS_STATUS_ASSOCIATED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9269) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9271) case NL80211_IFTYPE_ADHOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9272) if (intbss == wdev->current_bss &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9273) nla_put_u32(msg, NL80211_BSS_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9274) NL80211_BSS_STATUS_IBSS_JOINED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9275) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9276) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9277) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9278) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9281) nla_nest_end(msg, bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9283) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9284) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9286) fail_unlock_rcu:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9287) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9288) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9289) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9290) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9293) static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9295) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9296) struct cfg80211_internal_bss *scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9297) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9298) int start = cb->args[2], idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9299) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9301) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9302) err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9303) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9304) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9305) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9308) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9309) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9311) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9312) * dump_scan will be called multiple times to break up the scan results
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9313) * into multiple messages. It is unlikely that any more bss-es will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9314) * expired after the first call, so only call only call this on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9315) * first dump_scan invocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9316) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9317) if (start == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9318) cfg80211_bss_expire(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9320) cb->seq = rdev->bss_generation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9322) list_for_each_entry(scan, &rdev->bss_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9323) if (++idx <= start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9324) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9325) if (nl80211_send_bss(skb, cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9326) cb->nlh->nlmsg_seq, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9327) rdev, wdev, scan) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9328) idx--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9333) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9334) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9336) cb->args[2] = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9337) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9339) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9342) static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9343) int flags, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9344) bool allow_radio_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9345) struct survey_info *survey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9347) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9348) struct nlattr *infoattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9350) /* skip radio stats if userspace didn't request them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9351) if (!survey->channel && !allow_radio_stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9352) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9354) hdr = nl80211hdr_put(msg, portid, seq, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9355) NL80211_CMD_NEW_SURVEY_RESULTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9356) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9357) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9359) if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9360) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9362) infoattr = nla_nest_start_noflag(msg, NL80211_ATTR_SURVEY_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9363) if (!infoattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9364) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9366) if (survey->channel &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9367) nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9368) survey->channel->center_freq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9369) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9371) if (survey->channel && survey->channel->freq_offset &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9372) nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9373) survey->channel->freq_offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9374) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9376) if ((survey->filled & SURVEY_INFO_NOISE_DBM) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9377) nla_put_u8(msg, NL80211_SURVEY_INFO_NOISE, survey->noise))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9378) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9379) if ((survey->filled & SURVEY_INFO_IN_USE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9380) nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9381) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9382) if ((survey->filled & SURVEY_INFO_TIME) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9383) nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9384) survey->time, NL80211_SURVEY_INFO_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9385) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9386) if ((survey->filled & SURVEY_INFO_TIME_BUSY) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9387) nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BUSY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9388) survey->time_busy, NL80211_SURVEY_INFO_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9389) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9390) if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9391) nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9392) survey->time_ext_busy, NL80211_SURVEY_INFO_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9393) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9394) if ((survey->filled & SURVEY_INFO_TIME_RX) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9395) nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_RX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9396) survey->time_rx, NL80211_SURVEY_INFO_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9397) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9398) if ((survey->filled & SURVEY_INFO_TIME_TX) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9399) nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_TX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9400) survey->time_tx, NL80211_SURVEY_INFO_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9401) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9402) if ((survey->filled & SURVEY_INFO_TIME_SCAN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9403) nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_SCAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9404) survey->time_scan, NL80211_SURVEY_INFO_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9405) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9406) if ((survey->filled & SURVEY_INFO_TIME_BSS_RX) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9407) nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BSS_RX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9408) survey->time_bss_rx, NL80211_SURVEY_INFO_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9409) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9411) nla_nest_end(msg, infoattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9413) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9414) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9416) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9417) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9418) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9421) static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9423) struct nlattr **attrbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9424) struct survey_info survey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9425) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9426) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9427) int survey_idx = cb->args[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9428) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9429) bool radio_stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9431) attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9432) if (!attrbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9433) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9435) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9436) res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9437) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9438) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9440) /* prepare_wdev_dump parsed the attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9441) radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9443) if (!wdev->netdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9444) res = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9445) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9448) if (!rdev->ops->dump_survey) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9449) res = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9450) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9453) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9454) res = rdev_dump_survey(rdev, wdev->netdev, survey_idx, &survey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9455) if (res == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9456) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9457) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9458) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9460) /* don't send disabled channels, but do send non-channel data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9461) if (survey.channel &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9462) survey.channel->flags & IEEE80211_CHAN_DISABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9463) survey_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9464) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9467) if (nl80211_send_survey(skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9468) NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9469) cb->nlh->nlmsg_seq, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9470) wdev->netdev, radio_stats, &survey) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9471) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9472) survey_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9475) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9476) cb->args[2] = survey_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9477) res = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9478) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9479) kfree(attrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9480) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9481) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9484) static bool nl80211_valid_wpa_versions(u32 wpa_versions)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9486) return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9487) NL80211_WPA_VERSION_2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9488) NL80211_WPA_VERSION_3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9491) static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9493) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9494) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9495) struct ieee80211_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9496) const u8 *bssid, *ssid, *ie = NULL, *auth_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9497) int err, ssid_len, ie_len = 0, auth_data_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9498) enum nl80211_auth_type auth_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9499) struct key_parse key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9500) bool local_state_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9501) u32 freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9503) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9504) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9506) if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9507) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9509) if (!info->attrs[NL80211_ATTR_SSID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9510) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9512) if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9513) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9515) err = nl80211_parse_key(info, &key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9516) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9517) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9519) if (key.idx >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9520) if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9521) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9522) if (!key.p.key || !key.p.key_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9523) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9524) if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9525) key.p.key_len != WLAN_KEY_LEN_WEP40) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9526) (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9527) key.p.key_len != WLAN_KEY_LEN_WEP104))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9528) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9529) if (key.idx > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9530) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9531) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9532) key.p.key_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9533) key.p.key = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9536) if (key.idx >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9537) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9538) bool ok = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9540) for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9541) if (key.p.cipher == rdev->wiphy.cipher_suites[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9542) ok = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9543) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9546) if (!ok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9547) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9550) if (!rdev->ops->auth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9551) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9553) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9554) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9555) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9557) bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9558) freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9559) if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9560) freq +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9561) nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9563) chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9564) if (!chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9565) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9567) ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9568) ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9570) if (info->attrs[NL80211_ATTR_IE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9571) ie = nla_data(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9572) ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9575) auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9576) if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9577) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9579) if ((auth_type == NL80211_AUTHTYPE_SAE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9580) auth_type == NL80211_AUTHTYPE_FILS_SK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9581) auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9582) auth_type == NL80211_AUTHTYPE_FILS_PK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9583) !info->attrs[NL80211_ATTR_AUTH_DATA])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9584) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9586) if (info->attrs[NL80211_ATTR_AUTH_DATA]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9587) if (auth_type != NL80211_AUTHTYPE_SAE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9588) auth_type != NL80211_AUTHTYPE_FILS_SK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9589) auth_type != NL80211_AUTHTYPE_FILS_SK_PFS &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9590) auth_type != NL80211_AUTHTYPE_FILS_PK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9591) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9592) auth_data = nla_data(info->attrs[NL80211_ATTR_AUTH_DATA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9593) auth_data_len = nla_len(info->attrs[NL80211_ATTR_AUTH_DATA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9596) local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9598) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9599) * Since we no longer track auth state, ignore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9600) * requests to only change local state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9601) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9602) if (local_state_change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9603) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9605) wdev_lock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9606) err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9607) ssid, ssid_len, ie, ie_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9608) key.p.key, key.p.key_len, key.idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9609) auth_data, auth_data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9610) wdev_unlock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9611) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9614) static int validate_pae_over_nl80211(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9615) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9617) if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9618) GENL_SET_ERR_MSG(info, "SOCKET_OWNER not set");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9619) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9622) if (!rdev->ops->tx_control_port ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9623) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9624) NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9625) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9627) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9630) static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9631) struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9632) struct cfg80211_crypto_settings *settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9633) int cipher_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9634) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9635) memset(settings, 0, sizeof(*settings));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9637) settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9639) if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9640) u16 proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9642) proto = nla_get_u16(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9643) info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9644) settings->control_port_ethertype = cpu_to_be16(proto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9645) if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9646) proto != ETH_P_PAE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9647) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9648) if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9649) settings->control_port_no_encrypt = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9650) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9651) settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9653) if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9654) int r = validate_pae_over_nl80211(rdev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9656) if (r < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9657) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9659) settings->control_port_over_nl80211 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9661) if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9662) settings->control_port_no_preauth = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9665) if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9666) void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9667) int len, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9669) data = nla_data(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9670) len = nla_len(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9671) settings->n_ciphers_pairwise = len / sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9673) if (len % sizeof(u32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9674) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9676) if (settings->n_ciphers_pairwise > cipher_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9677) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9679) memcpy(settings->ciphers_pairwise, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9681) for (i = 0; i < settings->n_ciphers_pairwise; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9682) if (!cfg80211_supported_cipher_suite(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9683) &rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9684) settings->ciphers_pairwise[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9685) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9688) if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9689) settings->cipher_group =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9690) nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9691) if (!cfg80211_supported_cipher_suite(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9692) settings->cipher_group))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9693) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9696) if (info->attrs[NL80211_ATTR_WPA_VERSIONS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9697) settings->wpa_versions =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9698) nla_get_u32(info->attrs[NL80211_ATTR_WPA_VERSIONS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9699) if (!nl80211_valid_wpa_versions(settings->wpa_versions))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9700) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9703) if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9704) void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9705) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9707) data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9708) len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9709) settings->n_akm_suites = len / sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9711) if (len % sizeof(u32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9712) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9714) if (settings->n_akm_suites > NL80211_MAX_NR_AKM_SUITES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9715) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9717) memcpy(settings->akm_suites, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9720) if (info->attrs[NL80211_ATTR_PMK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9721) if (nla_len(info->attrs[NL80211_ATTR_PMK]) != WLAN_PMK_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9722) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9723) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9724) NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9725) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9726) NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9727) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9728) settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9731) if (info->attrs[NL80211_ATTR_SAE_PASSWORD]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9732) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9733) NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9734) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9735) NL80211_EXT_FEATURE_SAE_OFFLOAD_AP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9736) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9737) settings->sae_pwd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9738) nla_data(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9739) settings->sae_pwd_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9740) nla_len(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9743) if (info->attrs[NL80211_ATTR_SAE_PWE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9744) settings->sae_pwe =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9745) nla_get_u8(info->attrs[NL80211_ATTR_SAE_PWE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9746) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9747) settings->sae_pwe = NL80211_SAE_PWE_UNSPECIFIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9749) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9752) static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9753) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9754) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9755) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9756) struct ieee80211_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9757) struct cfg80211_assoc_request req = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9758) const u8 *bssid, *ssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9759) int err, ssid_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9760) u32 freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9762) if (dev->ieee80211_ptr->conn_owner_nlportid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9763) dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9764) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9766) if (!info->attrs[NL80211_ATTR_MAC] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9767) !info->attrs[NL80211_ATTR_SSID] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9768) !info->attrs[NL80211_ATTR_WIPHY_FREQ])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9769) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9771) if (!rdev->ops->assoc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9772) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9774) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9775) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9776) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9778) bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9780) freq = MHZ_TO_KHZ(nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9781) if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9782) freq +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9783) nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9784) chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9785) if (!chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9786) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9788) ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9789) ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9791) if (info->attrs[NL80211_ATTR_IE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9792) req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9793) req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9796) if (info->attrs[NL80211_ATTR_USE_MFP]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9797) enum nl80211_mfp mfp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9798) nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9799) if (mfp == NL80211_MFP_REQUIRED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9800) req.use_mfp = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9801) else if (mfp != NL80211_MFP_NO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9802) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9805) if (info->attrs[NL80211_ATTR_PREV_BSSID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9806) req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9808) if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9809) req.flags |= ASSOC_REQ_DISABLE_HT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9811) if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9812) memcpy(&req.ht_capa_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9813) nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9814) sizeof(req.ht_capa_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9816) if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9817) if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9818) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9819) memcpy(&req.ht_capa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9820) nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9821) sizeof(req.ht_capa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9824) if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9825) req.flags |= ASSOC_REQ_DISABLE_VHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9827) if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9828) memcpy(&req.vht_capa_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9829) nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9830) sizeof(req.vht_capa_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9832) if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9833) if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9834) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9835) memcpy(&req.vht_capa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9836) nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9837) sizeof(req.vht_capa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9840) if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9841) if (!((rdev->wiphy.features &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9842) NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9843) (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9844) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9845) NL80211_EXT_FEATURE_RRM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9846) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9847) req.flags |= ASSOC_REQ_USE_RRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9850) if (info->attrs[NL80211_ATTR_FILS_KEK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9851) req.fils_kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9852) req.fils_kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9853) if (!info->attrs[NL80211_ATTR_FILS_NONCES])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9854) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9855) req.fils_nonces =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9856) nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9859) if (info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9860) if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9861) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9862) memcpy(&req.s1g_capa_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9863) nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9864) sizeof(req.s1g_capa_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9867) if (info->attrs[NL80211_ATTR_S1G_CAPABILITY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9868) if (!info->attrs[NL80211_ATTR_S1G_CAPABILITY_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9869) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9870) memcpy(&req.s1g_capa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9871) nla_data(info->attrs[NL80211_ATTR_S1G_CAPABILITY]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9872) sizeof(req.s1g_capa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9875) err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9876) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9877) wdev_lock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9879) err = cfg80211_mlme_assoc(rdev, dev, chan, bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9880) ssid, ssid_len, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9882) if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9883) dev->ieee80211_ptr->conn_owner_nlportid =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9884) info->snd_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9885) memcpy(dev->ieee80211_ptr->disconnect_bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9886) bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9889) wdev_unlock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9892) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9895) static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9896) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9897) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9898) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9899) const u8 *ie = NULL, *bssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9900) int ie_len = 0, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9901) u16 reason_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9902) bool local_state_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9904) if (dev->ieee80211_ptr->conn_owner_nlportid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9905) dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9906) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9908) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9909) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9911) if (!info->attrs[NL80211_ATTR_REASON_CODE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9912) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9914) if (!rdev->ops->deauth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9915) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9917) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9918) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9919) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9921) bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9923) reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9924) if (reason_code == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9925) /* Reason Code 0 is reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9926) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9929) if (info->attrs[NL80211_ATTR_IE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9930) ie = nla_data(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9931) ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9934) local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9936) wdev_lock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9937) err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9938) local_state_change);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9939) wdev_unlock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9940) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9943) static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9944) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9945) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9946) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9947) const u8 *ie = NULL, *bssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9948) int ie_len = 0, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9949) u16 reason_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9950) bool local_state_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9952) if (dev->ieee80211_ptr->conn_owner_nlportid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9953) dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9954) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9956) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9957) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9959) if (!info->attrs[NL80211_ATTR_REASON_CODE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9960) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9962) if (!rdev->ops->disassoc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9963) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9965) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9966) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9967) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9969) bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9971) reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9972) if (reason_code == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9973) /* Reason Code 0 is reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9974) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9977) if (info->attrs[NL80211_ATTR_IE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9978) ie = nla_data(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9979) ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9982) local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9984) wdev_lock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9985) err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9986) local_state_change);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9987) wdev_unlock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9988) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9991) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9992) nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9993) int mcast_rate[NUM_NL80211_BANDS],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9994) int rateval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9996) struct wiphy *wiphy = &rdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9997) bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9998) int band, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10000) for (band = 0; band < NUM_NL80211_BANDS; band++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10001) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10003) sband = wiphy->bands[band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10004) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10005) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10007) for (i = 0; i < sband->n_bitrates; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10008) if (sband->bitrates[i].bitrate == rateval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10009) mcast_rate[band] = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10010) found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10011) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10016) return found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10019) static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10020) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10021) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10022) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10023) struct cfg80211_ibss_params ibss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10024) struct wiphy *wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10025) struct cfg80211_cached_keys *connkeys = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10026) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10028) memset(&ibss, 0, sizeof(ibss));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10030) if (!info->attrs[NL80211_ATTR_SSID] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10031) !nla_len(info->attrs[NL80211_ATTR_SSID]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10032) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10034) ibss.beacon_interval = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10036) if (info->attrs[NL80211_ATTR_BEACON_INTERVAL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10037) ibss.beacon_interval =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10038) nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10040) err = cfg80211_validate_beacon_int(rdev, NL80211_IFTYPE_ADHOC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10041) ibss.beacon_interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10042) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10043) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10045) if (!rdev->ops->join_ibss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10046) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10048) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10049) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10051) wiphy = &rdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10053) if (info->attrs[NL80211_ATTR_MAC]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10054) ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10056) if (!is_valid_ether_addr(ibss.bssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10057) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10059) ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10060) ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10062) if (info->attrs[NL80211_ATTR_IE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10063) ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10064) ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10067) err = nl80211_parse_chandef(rdev, info, &ibss.chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10068) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10069) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10071) if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10072) NL80211_IFTYPE_ADHOC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10073) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10075) switch (ibss.chandef.width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10076) case NL80211_CHAN_WIDTH_5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10077) case NL80211_CHAN_WIDTH_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10078) case NL80211_CHAN_WIDTH_20_NOHT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10079) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10080) case NL80211_CHAN_WIDTH_20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10081) case NL80211_CHAN_WIDTH_40:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10082) if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10083) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10084) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10085) case NL80211_CHAN_WIDTH_80:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10086) case NL80211_CHAN_WIDTH_80P80:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10087) case NL80211_CHAN_WIDTH_160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10088) if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10089) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10090) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10091) NL80211_EXT_FEATURE_VHT_IBSS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10092) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10093) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10094) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10095) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10098) ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10099) ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10101) if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10102) u8 *rates =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10103) nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10104) int n_rates =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10105) nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10106) struct ieee80211_supported_band *sband =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10107) wiphy->bands[ibss.chandef.chan->band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10109) err = ieee80211_get_ratemask(sband, rates, n_rates,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10110) &ibss.basic_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10111) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10112) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10115) if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10116) memcpy(&ibss.ht_capa_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10117) nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10118) sizeof(ibss.ht_capa_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10120) if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10121) if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10122) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10123) memcpy(&ibss.ht_capa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10124) nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10125) sizeof(ibss.ht_capa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10128) if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10129) !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10130) nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10131) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10133) if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10134) bool no_ht = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10136) connkeys = nl80211_parse_connkeys(rdev, info, &no_ht);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10137) if (IS_ERR(connkeys))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10138) return PTR_ERR(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10140) if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10141) no_ht) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10142) kfree_sensitive(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10143) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10147) ibss.control_port =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10148) nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10150) if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10151) int r = validate_pae_over_nl80211(rdev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10153) if (r < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10154) kfree_sensitive(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10155) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10158) ibss.control_port_over_nl80211 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10161) ibss.userspace_handles_dfs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10162) nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10164) wdev_lock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10165) err = __cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10166) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10167) kfree_sensitive(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10168) else if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10169) dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10170) wdev_unlock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10172) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10175) static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10177) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10178) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10180) if (!rdev->ops->leave_ibss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10181) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10183) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10184) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10186) return cfg80211_leave_ibss(rdev, dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10189) static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10191) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10192) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10193) int mcast_rate[NUM_NL80211_BANDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10194) u32 nla_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10195) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10197) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10198) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10199) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10200) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10202) if (!rdev->ops->set_mcast_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10203) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10205) memset(mcast_rate, 0, sizeof(mcast_rate));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10207) if (!info->attrs[NL80211_ATTR_MCAST_RATE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10208) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10210) nla_rate = nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10211) if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10212) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10214) err = rdev_set_mcast_rate(rdev, dev, mcast_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10216) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10219) static struct sk_buff *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10220) __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10221) struct wireless_dev *wdev, int approxlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10222) u32 portid, u32 seq, enum nl80211_commands cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10223) enum nl80211_attrs attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10224) const struct nl80211_vendor_cmd_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10225) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10227) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10228) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10229) struct nlattr *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10231) skb = nlmsg_new(approxlen + 100, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10232) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10233) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10235) hdr = nl80211hdr_put(skb, portid, seq, 0, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10236) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10237) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10238) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10241) if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10242) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10244) if (info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10245) if (nla_put_u32(skb, NL80211_ATTR_VENDOR_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10246) info->vendor_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10247) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10248) if (nla_put_u32(skb, NL80211_ATTR_VENDOR_SUBCMD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10249) info->subcmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10250) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10253) if (wdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10254) if (nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10255) wdev_id(wdev), NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10256) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10257) if (wdev->netdev &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10258) nla_put_u32(skb, NL80211_ATTR_IFINDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10259) wdev->netdev->ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10260) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10263) data = nla_nest_start_noflag(skb, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10264) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10265) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10267) ((void **)skb->cb)[0] = rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10268) ((void **)skb->cb)[1] = hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10269) ((void **)skb->cb)[2] = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10271) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10273) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10274) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10275) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10278) struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10279) struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10280) enum nl80211_commands cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10281) enum nl80211_attrs attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10282) unsigned int portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10283) int vendor_event_idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10284) int approxlen, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10286) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10287) const struct nl80211_vendor_cmd_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10289) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10290) case NL80211_CMD_TESTMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10291) if (WARN_ON(vendor_event_idx != -1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10292) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10293) info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10294) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10295) case NL80211_CMD_VENDOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10296) if (WARN_ON(vendor_event_idx < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10297) vendor_event_idx >= wiphy->n_vendor_events))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10298) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10299) info = &wiphy->vendor_events[vendor_event_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10300) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10301) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10302) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10303) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10306) return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, portid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10307) cmd, attr, info, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10309) EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10311) void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10313) struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10314) void *hdr = ((void **)skb->cb)[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10315) struct nlmsghdr *nlhdr = nlmsg_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10316) struct nlattr *data = ((void **)skb->cb)[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10317) enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10319) /* clear CB data for netlink core to own from now on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10320) memset(skb->cb, 0, sizeof(skb->cb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10322) nla_nest_end(skb, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10323) genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10325) if (nlhdr->nlmsg_pid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10326) genlmsg_unicast(wiphy_net(&rdev->wiphy), skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10327) nlhdr->nlmsg_pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10328) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10329) if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10330) mcgrp = NL80211_MCGRP_VENDOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10332) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10333) skb, 0, mcgrp, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10336) EXPORT_SYMBOL(__cfg80211_send_event_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10338) #ifdef CONFIG_NL80211_TESTMODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10339) static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10341) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10342) struct wireless_dev *wdev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10343) __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10344) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10346) if (!rdev->ops->testmode_cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10347) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10349) if (IS_ERR(wdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10350) err = PTR_ERR(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10351) if (err != -EINVAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10352) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10353) wdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10354) } else if (wdev->wiphy != &rdev->wiphy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10355) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10358) if (!info->attrs[NL80211_ATTR_TESTDATA])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10359) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10361) rdev->cur_cmd_info = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10362) err = rdev_testmode_cmd(rdev, wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10363) nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10364) nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10365) rdev->cur_cmd_info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10367) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10370) static int nl80211_testmode_dump(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10371) struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10373) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10374) struct nlattr **attrbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10375) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10376) long phy_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10377) void *data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10378) int data_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10380) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10382) if (cb->args[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10383) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10384) * 0 is a valid index, but not valid for args[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10385) * so we need to offset by 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10386) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10387) phy_idx = cb->args[0] - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10389) rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10390) if (!rdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10391) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10392) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10394) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10395) attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10396) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10397) if (!attrbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10398) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10399) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10402) err = nlmsg_parse_deprecated(cb->nlh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10403) GENL_HDRLEN + nl80211_fam.hdrsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10404) attrbuf, nl80211_fam.maxattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10405) nl80211_policy, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10406) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10407) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10409) rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10410) if (IS_ERR(rdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10411) err = PTR_ERR(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10412) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10414) phy_idx = rdev->wiphy_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10416) if (attrbuf[NL80211_ATTR_TESTDATA])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10417) cb->args[1] = (long)attrbuf[NL80211_ATTR_TESTDATA];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10420) if (cb->args[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10421) data = nla_data((void *)cb->args[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10422) data_len = nla_len((void *)cb->args[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10425) if (!rdev->ops->testmode_dump) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10426) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10427) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10430) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10431) void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10432) cb->nlh->nlmsg_seq, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10433) NL80211_CMD_TESTMODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10434) struct nlattr *tmdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10436) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10437) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10439) if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10440) genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10441) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10444) tmdata = nla_nest_start_noflag(skb, NL80211_ATTR_TESTDATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10445) if (!tmdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10446) genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10447) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10449) err = rdev_testmode_dump(rdev, skb, cb, data, data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10450) nla_nest_end(skb, tmdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10452) if (err == -ENOBUFS || err == -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10453) genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10454) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10455) } else if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10456) genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10457) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10460) genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10463) err = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10464) /* see above */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10465) cb->args[0] = phy_idx + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10466) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10467) kfree(attrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10468) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10469) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10471) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10473) static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10475) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10476) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10477) struct cfg80211_connect_params connect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10478) struct wiphy *wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10479) struct cfg80211_cached_keys *connkeys = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10480) u32 freq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10481) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10483) memset(&connect, 0, sizeof(connect));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10485) if (!info->attrs[NL80211_ATTR_SSID] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10486) !nla_len(info->attrs[NL80211_ATTR_SSID]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10487) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10489) if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10490) connect.auth_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10491) nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10492) if (!nl80211_valid_auth_type(rdev, connect.auth_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10493) NL80211_CMD_CONNECT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10494) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10495) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10496) connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10498) connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10500) if (info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10501) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10502) NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10503) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10504) connect.want_1x = info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10506) err = nl80211_crypto_settings(rdev, info, &connect.crypto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10507) NL80211_MAX_NR_CIPHER_SUITES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10508) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10509) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10511) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10512) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10513) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10515) wiphy = &rdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10517) connect.bg_scan_period = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10518) if (info->attrs[NL80211_ATTR_BG_SCAN_PERIOD] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10519) (wiphy->flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10520) connect.bg_scan_period =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10521) nla_get_u16(info->attrs[NL80211_ATTR_BG_SCAN_PERIOD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10524) if (info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10525) connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10526) else if (info->attrs[NL80211_ATTR_MAC_HINT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10527) connect.bssid_hint =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10528) nla_data(info->attrs[NL80211_ATTR_MAC_HINT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10529) connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10530) connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10532) if (info->attrs[NL80211_ATTR_IE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10533) connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10534) connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10537) if (info->attrs[NL80211_ATTR_USE_MFP]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10538) connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10539) if (connect.mfp == NL80211_MFP_OPTIONAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10540) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10541) NL80211_EXT_FEATURE_MFP_OPTIONAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10542) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10543) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10544) connect.mfp = NL80211_MFP_NO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10547) if (info->attrs[NL80211_ATTR_PREV_BSSID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10548) connect.prev_bssid =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10549) nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10551) if (info->attrs[NL80211_ATTR_WIPHY_FREQ])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10552) freq = MHZ_TO_KHZ(nla_get_u32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10553) info->attrs[NL80211_ATTR_WIPHY_FREQ]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10554) if (info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10555) freq +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10556) nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10558) if (freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10559) connect.channel = nl80211_get_valid_chan(wiphy, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10560) if (!connect.channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10561) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10562) } else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10563) freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10564) freq = MHZ_TO_KHZ(freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10565) connect.channel_hint = nl80211_get_valid_chan(wiphy, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10566) if (!connect.channel_hint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10567) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10570) if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10571) connect.edmg.channels =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10572) nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10574) if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10575) connect.edmg.bw_config =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10576) nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10579) if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10580) connkeys = nl80211_parse_connkeys(rdev, info, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10581) if (IS_ERR(connkeys))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10582) return PTR_ERR(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10585) if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10586) connect.flags |= ASSOC_REQ_DISABLE_HT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10588) if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10589) memcpy(&connect.ht_capa_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10590) nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10591) sizeof(connect.ht_capa_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10593) if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10594) if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10595) kfree_sensitive(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10596) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10598) memcpy(&connect.ht_capa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10599) nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10600) sizeof(connect.ht_capa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10603) if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10604) connect.flags |= ASSOC_REQ_DISABLE_VHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10606) if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10607) memcpy(&connect.vht_capa_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10608) nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10609) sizeof(connect.vht_capa_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10611) if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10612) if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10613) kfree_sensitive(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10614) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10616) memcpy(&connect.vht_capa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10617) nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10618) sizeof(connect.vht_capa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10621) if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10622) if (!((rdev->wiphy.features &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10623) NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10624) (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10625) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10626) NL80211_EXT_FEATURE_RRM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10627) kfree_sensitive(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10628) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10630) connect.flags |= ASSOC_REQ_USE_RRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10633) connect.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10634) if (connect.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10635) kfree_sensitive(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10636) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10639) if (info->attrs[NL80211_ATTR_BSS_SELECT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10640) /* bss selection makes no sense if bssid is set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10641) if (connect.bssid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10642) kfree_sensitive(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10643) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10646) err = parse_bss_select(info->attrs[NL80211_ATTR_BSS_SELECT],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10647) wiphy, &connect.bss_select);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10648) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10649) kfree_sensitive(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10650) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10654) if (wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10655) NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10656) info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10657) info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10658) info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10659) info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10660) connect.fils_erp_username =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10661) nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10662) connect.fils_erp_username_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10663) nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10664) connect.fils_erp_realm =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10665) nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10666) connect.fils_erp_realm_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10667) nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10668) connect.fils_erp_next_seq_num =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10669) nla_get_u16(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10670) info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10671) connect.fils_erp_rrk =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10672) nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10673) connect.fils_erp_rrk_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10674) nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10675) } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10676) info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10677) info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10678) info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10679) kfree_sensitive(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10680) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10683) if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10684) if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10685) kfree_sensitive(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10686) GENL_SET_ERR_MSG(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10687) "external auth requires connection ownership");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10688) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10690) connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10693) wdev_lock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10695) err = cfg80211_connect(rdev, dev, &connect, connkeys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10696) connect.prev_bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10697) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10698) kfree_sensitive(connkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10700) if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10701) dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10702) if (connect.bssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10703) memcpy(dev->ieee80211_ptr->disconnect_bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10704) connect.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10705) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10706) eth_zero_addr(dev->ieee80211_ptr->disconnect_bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10709) wdev_unlock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10711) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10714) static int nl80211_update_connect_params(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10715) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10717) struct cfg80211_connect_params connect = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10718) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10719) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10720) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10721) bool fils_sk_offload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10722) u32 auth_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10723) u32 changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10724) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10726) if (!rdev->ops->update_connect_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10727) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10729) if (info->attrs[NL80211_ATTR_IE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10730) connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10731) connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10732) changed |= UPDATE_ASSOC_IES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10735) fils_sk_offload = wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10736) NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10738) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10739) * when driver supports fils-sk offload all attributes must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10740) * provided. So the else covers "fils-sk-not-all" and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10741) * "no-fils-sk-any".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10742) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10743) if (fils_sk_offload &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10744) info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10745) info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10746) info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10747) info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10748) connect.fils_erp_username =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10749) nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10750) connect.fils_erp_username_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10751) nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10752) connect.fils_erp_realm =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10753) nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10754) connect.fils_erp_realm_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10755) nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10756) connect.fils_erp_next_seq_num =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10757) nla_get_u16(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10758) info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10759) connect.fils_erp_rrk =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10760) nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10761) connect.fils_erp_rrk_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10762) nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10763) changed |= UPDATE_FILS_ERP_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10764) } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10765) info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10766) info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10767) info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10768) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10771) if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10772) auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10773) if (!nl80211_valid_auth_type(rdev, auth_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10774) NL80211_CMD_CONNECT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10775) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10777) if (auth_type == NL80211_AUTHTYPE_FILS_SK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10778) fils_sk_offload && !(changed & UPDATE_FILS_ERP_INFO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10779) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10781) connect.auth_type = auth_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10782) changed |= UPDATE_AUTH_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10785) wdev_lock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10786) if (!wdev->current_bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10787) ret = -ENOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10788) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10789) ret = rdev_update_connect_params(rdev, dev, &connect, changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10790) wdev_unlock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10792) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10795) static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10797) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10798) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10799) u16 reason;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10800) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10802) if (dev->ieee80211_ptr->conn_owner_nlportid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10803) dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10804) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10806) if (!info->attrs[NL80211_ATTR_REASON_CODE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10807) reason = WLAN_REASON_DEAUTH_LEAVING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10808) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10809) reason = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10811) if (reason == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10812) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10814) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10815) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10816) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10818) wdev_lock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10819) ret = cfg80211_disconnect(rdev, dev, reason, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10820) wdev_unlock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10821) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10824) static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10825) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10826) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10827) struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10828) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10830) if (info->attrs[NL80211_ATTR_PID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10831) u32 pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10833) net = get_net_ns_by_pid(pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10834) } else if (info->attrs[NL80211_ATTR_NETNS_FD]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10835) u32 fd = nla_get_u32(info->attrs[NL80211_ATTR_NETNS_FD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10837) net = get_net_ns_by_fd(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10838) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10839) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10842) if (IS_ERR(net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10843) return PTR_ERR(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10845) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10847) /* check if anything to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10848) if (!net_eq(wiphy_net(&rdev->wiphy), net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10849) err = cfg80211_switch_netns(rdev, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10851) put_net(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10852) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10855) static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10856) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10857) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10858) int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10859) struct cfg80211_pmksa *pmksa) = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10860) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10861) struct cfg80211_pmksa pmksa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10863) memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10865) if (!info->attrs[NL80211_ATTR_PMKID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10866) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10868) pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10870) if (info->attrs[NL80211_ATTR_MAC]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10871) pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10872) } else if (info->attrs[NL80211_ATTR_SSID] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10873) info->attrs[NL80211_ATTR_FILS_CACHE_ID] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10874) (info->genlhdr->cmd == NL80211_CMD_DEL_PMKSA ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10875) info->attrs[NL80211_ATTR_PMK])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10876) pmksa.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10877) pmksa.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10878) pmksa.cache_id =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10879) nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10880) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10881) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10883) if (info->attrs[NL80211_ATTR_PMK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10884) pmksa.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10885) pmksa.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10888) if (info->attrs[NL80211_ATTR_PMK_LIFETIME])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10889) pmksa.pmk_lifetime =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10890) nla_get_u32(info->attrs[NL80211_ATTR_PMK_LIFETIME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10892) if (info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10893) pmksa.pmk_reauth_threshold =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10894) nla_get_u8(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10895) info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10897) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10898) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10899) !(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10900) wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10901) NL80211_EXT_FEATURE_AP_PMKSA_CACHING)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10902) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10904) switch (info->genlhdr->cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10905) case NL80211_CMD_SET_PMKSA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10906) rdev_ops = rdev->ops->set_pmksa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10907) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10908) case NL80211_CMD_DEL_PMKSA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10909) rdev_ops = rdev->ops->del_pmksa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10910) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10911) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10912) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10913) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10916) if (!rdev_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10917) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10919) return rdev_ops(&rdev->wiphy, dev, &pmksa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10922) static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10923) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10924) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10925) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10927) if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10928) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10929) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10931) if (!rdev->ops->flush_pmksa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10932) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10934) return rdev_flush_pmksa(rdev, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10937) static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10938) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10939) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10940) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10941) u8 action_code, dialog_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10942) u32 peer_capability = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10943) u16 status_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10944) u8 *peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10945) bool initiator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10947) if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10948) !rdev->ops->tdls_mgmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10949) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10951) if (!info->attrs[NL80211_ATTR_TDLS_ACTION] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10952) !info->attrs[NL80211_ATTR_STATUS_CODE] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10953) !info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10954) !info->attrs[NL80211_ATTR_IE] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10955) !info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10956) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10958) peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10959) action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10960) status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10961) dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10962) initiator = nla_get_flag(info->attrs[NL80211_ATTR_TDLS_INITIATOR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10963) if (info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10964) peer_capability =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10965) nla_get_u32(info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10967) return rdev_tdls_mgmt(rdev, dev, peer, action_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10968) dialog_token, status_code, peer_capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10969) initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10970) nla_data(info->attrs[NL80211_ATTR_IE]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10971) nla_len(info->attrs[NL80211_ATTR_IE]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10974) static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10975) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10976) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10977) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10978) enum nl80211_tdls_operation operation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10979) u8 *peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10981) if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10982) !rdev->ops->tdls_oper)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10983) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10985) if (!info->attrs[NL80211_ATTR_TDLS_OPERATION] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10986) !info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10987) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10989) operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10990) peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10992) return rdev_tdls_oper(rdev, dev, peer, operation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10995) static int nl80211_remain_on_channel(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10996) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10997) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10998) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10999) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11000) struct cfg80211_chan_def chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11001) const struct cfg80211_chan_def *compat_chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11002) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11003) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11004) u64 cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11005) u32 duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11006) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11008) if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11009) !info->attrs[NL80211_ATTR_DURATION])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11010) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11012) duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11014) if (!rdev->ops->remain_on_channel ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11015) !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11016) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11018) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11019) * We should be on that channel for at least a minimum amount of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11020) * time (10ms) but no longer than the driver supports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11021) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11022) if (duration < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11023) duration > rdev->wiphy.max_remain_on_channel_duration)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11024) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11026) err = nl80211_parse_chandef(rdev, info, &chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11027) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11028) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11030) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11031) if (!cfg80211_off_channel_oper_allowed(wdev) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11032) !cfg80211_chandef_identical(&wdev->chandef, &chandef)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11033) compat_chandef = cfg80211_chandef_compatible(&wdev->chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11034) &chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11035) if (compat_chandef != &chandef) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11036) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11037) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11040) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11042) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11043) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11044) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11046) hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11047) NL80211_CMD_REMAIN_ON_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11048) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11049) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11050) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11053) err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11054) duration, &cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11056) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11057) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11059) if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11060) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11061) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11063) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11065) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11067) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11068) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11069) free_msg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11070) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11071) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11074) static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11075) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11077) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11078) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11079) u64 cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11081) if (!info->attrs[NL80211_ATTR_COOKIE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11082) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11084) if (!rdev->ops->cancel_remain_on_channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11085) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11087) cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11089) return rdev_cancel_remain_on_channel(rdev, wdev, cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11092) static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11093) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11095) struct cfg80211_bitrate_mask mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11096) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11097) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11098) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11100) if (!rdev->ops->set_bitrate_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11101) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11103) err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11104) NL80211_ATTR_TX_RATES, &mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11105) dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11106) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11107) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11109) return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11112) static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11114) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11115) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11116) u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11118) if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11119) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11121) if (info->attrs[NL80211_ATTR_FRAME_TYPE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11122) frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11124) switch (wdev->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11125) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11126) case NL80211_IFTYPE_ADHOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11127) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11128) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11129) case NL80211_IFTYPE_AP_VLAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11130) case NL80211_IFTYPE_MESH_POINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11131) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11132) case NL80211_IFTYPE_P2P_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11133) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11134) case NL80211_IFTYPE_NAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11135) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11136) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11139) /* not much point in registering if we can't reply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11140) if (!rdev->ops->mgmt_tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11141) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11143) if (info->attrs[NL80211_ATTR_RECEIVE_MULTICAST] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11144) !wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11145) NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11146) GENL_SET_ERR_MSG(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11147) "multicast RX registrations are not supported");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11148) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11151) return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11152) nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11153) nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11154) info->attrs[NL80211_ATTR_RECEIVE_MULTICAST],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11155) info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11158) static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11160) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11161) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11162) struct cfg80211_chan_def chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11163) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11164) void *hdr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11165) u64 cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11166) struct sk_buff *msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11167) struct cfg80211_mgmt_tx_params params = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11168) .dont_wait_for_ack =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11169) info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11170) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11172) if (!info->attrs[NL80211_ATTR_FRAME])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11173) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11175) if (!rdev->ops->mgmt_tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11176) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11178) switch (wdev->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11179) case NL80211_IFTYPE_P2P_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11180) if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11181) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11182) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11183) case NL80211_IFTYPE_ADHOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11184) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11185) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11186) case NL80211_IFTYPE_AP_VLAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11187) case NL80211_IFTYPE_MESH_POINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11188) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11189) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11190) case NL80211_IFTYPE_NAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11191) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11192) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11195) if (info->attrs[NL80211_ATTR_DURATION]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11196) if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11197) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11198) params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11200) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11201) * We should wait on the channel for at least a minimum amount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11202) * of time (10ms) but no longer than the driver supports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11204) if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11205) params.wait > rdev->wiphy.max_remain_on_channel_duration)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11206) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11209) params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11211) if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11212) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11214) params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11216) /* get the channel if any has been specified, otherwise pass NULL to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11217) * the driver. The latter will use the current one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11219) chandef.chan = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11220) if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11221) err = nl80211_parse_chandef(rdev, info, &chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11222) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11223) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11226) if (!chandef.chan && params.offchan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11227) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11229) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11230) if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11231) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11232) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11234) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11236) params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11237) params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11239) if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11240) int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11241) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11243) if (len % sizeof(u16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11244) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11246) params.n_csa_offsets = len / sizeof(u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11247) params.csa_offsets =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11248) nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11250) /* check that all the offsets fit the frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11251) for (i = 0; i < params.n_csa_offsets; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11252) if (params.csa_offsets[i] >= params.len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11253) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11257) if (!params.dont_wait_for_ack) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11258) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11259) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11260) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11262) hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11263) NL80211_CMD_FRAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11264) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11265) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11266) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11270) params.chan = chandef.chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11271) err = cfg80211_mlme_mgmt_tx(rdev, wdev, ¶ms, &cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11272) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11273) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11275) if (msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11276) if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11277) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11278) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11280) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11281) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11284) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11286) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11287) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11288) free_msg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11289) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11290) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11293) static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11295) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11296) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11297) u64 cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11299) if (!info->attrs[NL80211_ATTR_COOKIE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11300) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11302) if (!rdev->ops->mgmt_tx_cancel_wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11303) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11305) switch (wdev->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11306) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11307) case NL80211_IFTYPE_ADHOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11308) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11309) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11310) case NL80211_IFTYPE_AP_VLAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11311) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11312) case NL80211_IFTYPE_P2P_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11313) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11314) case NL80211_IFTYPE_NAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11315) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11316) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11319) cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11321) return rdev_mgmt_tx_cancel_wait(rdev, wdev, cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11324) static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11326) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11327) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11328) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11329) u8 ps_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11330) bool state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11331) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11333) if (!info->attrs[NL80211_ATTR_PS_STATE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11334) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11336) ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11338) wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11340) if (!rdev->ops->set_power_mgmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11341) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11343) state = (ps_state == NL80211_PS_ENABLED) ? true : false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11345) if (state == wdev->ps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11346) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11348) err = rdev_set_power_mgmt(rdev, dev, state, wdev->ps_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11349) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11350) wdev->ps = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11351) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11354) static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11356) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11357) enum nl80211_ps_state ps_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11358) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11359) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11360) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11361) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11362) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11364) wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11366) if (!rdev->ops->set_power_mgmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11367) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11369) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11370) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11371) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11373) hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11374) NL80211_CMD_GET_POWER_SAVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11375) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11376) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11377) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11380) if (wdev->ps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11381) ps_state = NL80211_PS_ENABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11382) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11383) ps_state = NL80211_PS_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11385) if (nla_put_u32(msg, NL80211_ATTR_PS_STATE, ps_state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11386) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11388) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11389) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11391) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11392) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11393) free_msg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11394) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11395) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11398) static const struct nla_policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11399) nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11400) [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_BINARY },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11401) [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11402) [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11403) [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11404) [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11405) [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11406) [NL80211_ATTR_CQM_RSSI_LEVEL] = { .type = NLA_S32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11407) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11409) static int nl80211_set_cqm_txe(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11410) u32 rate, u32 pkts, u32 intvl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11412) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11413) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11414) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11416) if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11417) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11419) if (!rdev->ops->set_cqm_txe_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11420) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11422) if (wdev->iftype != NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11423) wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11424) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11426) return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11429) static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11430) struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11432) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11433) s32 last, low, high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11434) u32 hyst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11435) int i, n, low_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11436) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11438) /* RSSI reporting disabled? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11439) if (!wdev->cqm_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11440) return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11442) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11443) * Obtain current RSSI value if possible, if not and no RSSI threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11444) * event has been received yet, we should receive an event after a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11445) * connection is established and enough beacons received to calculate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11446) * the average.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11447) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11448) if (!wdev->cqm_config->last_rssi_event_value && wdev->current_bss &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11449) rdev->ops->get_station) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11450) struct station_info sinfo = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11451) u8 *mac_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11453) mac_addr = wdev->current_bss->pub.bssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11455) err = rdev_get_station(rdev, dev, mac_addr, &sinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11456) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11457) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11459) cfg80211_sinfo_release_content(&sinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11460) if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11461) wdev->cqm_config->last_rssi_event_value =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11462) (s8) sinfo.rx_beacon_signal_avg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11465) last = wdev->cqm_config->last_rssi_event_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11466) hyst = wdev->cqm_config->rssi_hyst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11467) n = wdev->cqm_config->n_rssi_thresholds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11469) for (i = 0; i < n; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11470) i = array_index_nospec(i, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11471) if (last < wdev->cqm_config->rssi_thresholds[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11472) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11475) low_index = i - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11476) if (low_index >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11477) low_index = array_index_nospec(low_index, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11478) low = wdev->cqm_config->rssi_thresholds[low_index] - hyst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11479) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11480) low = S32_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11482) if (i < n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11483) i = array_index_nospec(i, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11484) high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11485) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11486) high = S32_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11489) return rdev_set_cqm_rssi_range_config(rdev, dev, low, high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11492) static int nl80211_set_cqm_rssi(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11493) const s32 *thresholds, int n_thresholds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11494) u32 hysteresis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11496) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11497) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11498) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11499) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11500) s32 prev = S32_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11502) /* Check all values negative and sorted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11503) for (i = 0; i < n_thresholds; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11504) if (thresholds[i] > 0 || thresholds[i] <= prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11505) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11507) prev = thresholds[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11510) if (wdev->iftype != NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11511) wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11512) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11514) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11515) cfg80211_cqm_config_free(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11516) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11518) if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11519) if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11520) return rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11522) return rdev_set_cqm_rssi_config(rdev, dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11523) thresholds[0], hysteresis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11526) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11527) NL80211_EXT_FEATURE_CQM_RSSI_LIST))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11528) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11530) if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11531) n_thresholds = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11533) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11534) if (n_thresholds) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11535) struct cfg80211_cqm_config *cqm_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11537) cqm_config = kzalloc(sizeof(struct cfg80211_cqm_config) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11538) n_thresholds * sizeof(s32), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11539) if (!cqm_config) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11540) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11541) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11544) cqm_config->rssi_hyst = hysteresis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11545) cqm_config->n_rssi_thresholds = n_thresholds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11546) memcpy(cqm_config->rssi_thresholds, thresholds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11547) n_thresholds * sizeof(s32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11549) wdev->cqm_config = cqm_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11552) err = cfg80211_cqm_rssi_update(rdev, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11554) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11555) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11557) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11560) static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11562) struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11563) struct nlattr *cqm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11564) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11566) cqm = info->attrs[NL80211_ATTR_CQM];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11567) if (!cqm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11568) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11570) err = nla_parse_nested_deprecated(attrs, NL80211_ATTR_CQM_MAX, cqm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11571) nl80211_attr_cqm_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11572) info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11573) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11574) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11576) if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11577) attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11578) const s32 *thresholds =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11579) nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11580) int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11581) u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11583) if (len % 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11584) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11586) return nl80211_set_cqm_rssi(info, thresholds, len / 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11587) hysteresis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11590) if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11591) attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11592) attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11593) u32 rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11594) u32 pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11595) u32 intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11597) return nl80211_set_cqm_txe(info, rate, pkts, intvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11600) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11603) static int nl80211_join_ocb(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11605) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11606) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11607) struct ocb_setup setup = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11608) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11610) err = nl80211_parse_chandef(rdev, info, &setup.chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11611) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11612) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11614) return cfg80211_join_ocb(rdev, dev, &setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11617) static int nl80211_leave_ocb(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11619) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11620) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11622) return cfg80211_leave_ocb(rdev, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11625) static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11627) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11628) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11629) struct mesh_config cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11630) struct mesh_setup setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11631) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11633) /* start with default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11634) memcpy(&cfg, &default_mesh_config, sizeof(cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11635) memcpy(&setup, &default_mesh_setup, sizeof(setup));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11637) if (info->attrs[NL80211_ATTR_MESH_CONFIG]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11638) /* and parse parameters if given */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11639) err = nl80211_parse_mesh_config(info, &cfg, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11640) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11641) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11644) if (!info->attrs[NL80211_ATTR_MESH_ID] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11645) !nla_len(info->attrs[NL80211_ATTR_MESH_ID]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11646) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11648) setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11649) setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11651) if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11652) !nl80211_parse_mcast_rate(rdev, setup.mcast_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11653) nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11654) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11656) if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11657) setup.beacon_interval =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11658) nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11660) err = cfg80211_validate_beacon_int(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11661) NL80211_IFTYPE_MESH_POINT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11662) setup.beacon_interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11663) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11664) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11667) if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11668) setup.dtim_period =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11669) nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11670) if (setup.dtim_period < 1 || setup.dtim_period > 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11671) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11674) if (info->attrs[NL80211_ATTR_MESH_SETUP]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11675) /* parse additional setup parameters if given */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11676) err = nl80211_parse_mesh_setup(info, &setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11677) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11678) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11681) if (setup.user_mpm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11682) cfg.auto_open_plinks = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11684) if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11685) err = nl80211_parse_chandef(rdev, info, &setup.chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11686) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11687) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11688) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11689) /* __cfg80211_join_mesh() will sort it out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11690) setup.chandef.chan = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11693) if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11694) u8 *rates = nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11695) int n_rates =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11696) nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11697) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11699) if (!setup.chandef.chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11700) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11702) sband = rdev->wiphy.bands[setup.chandef.chan->band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11704) err = ieee80211_get_ratemask(sband, rates, n_rates,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11705) &setup.basic_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11706) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11707) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11710) if (info->attrs[NL80211_ATTR_TX_RATES]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11711) err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11712) NL80211_ATTR_TX_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11713) &setup.beacon_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11714) dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11715) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11716) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11718) if (!setup.chandef.chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11719) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11721) err = validate_beacon_tx_rate(rdev, setup.chandef.chan->band,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11722) &setup.beacon_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11723) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11724) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11727) setup.userspace_handles_dfs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11728) nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11730) if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11731) int r = validate_pae_over_nl80211(rdev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11733) if (r < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11734) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11736) setup.control_port_over_nl80211 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11739) wdev_lock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11740) err = __cfg80211_join_mesh(rdev, dev, &setup, &cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11741) if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11742) dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11743) wdev_unlock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11745) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11748) static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11750) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11751) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11753) return cfg80211_leave_mesh(rdev, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11756) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11757) static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11758) struct cfg80211_registered_device *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11759) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11760) struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11761) struct nlattr *nl_pats, *nl_pat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11762) int i, pat_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11764) if (!wowlan->n_patterns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11765) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11767) nl_pats = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11768) if (!nl_pats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11769) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11771) for (i = 0; i < wowlan->n_patterns; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11772) nl_pat = nla_nest_start_noflag(msg, i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11773) if (!nl_pat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11774) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11775) pat_len = wowlan->patterns[i].pattern_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11776) if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11777) wowlan->patterns[i].mask) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11778) nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11779) wowlan->patterns[i].pattern) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11780) nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11781) wowlan->patterns[i].pkt_offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11782) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11783) nla_nest_end(msg, nl_pat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11785) nla_nest_end(msg, nl_pats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11787) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11790) static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11791) struct cfg80211_wowlan_tcp *tcp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11793) struct nlattr *nl_tcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11795) if (!tcp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11796) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11798) nl_tcp = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11799) NL80211_WOWLAN_TRIG_TCP_CONNECTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11800) if (!nl_tcp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11801) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11803) if (nla_put_in_addr(msg, NL80211_WOWLAN_TCP_SRC_IPV4, tcp->src) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11804) nla_put_in_addr(msg, NL80211_WOWLAN_TCP_DST_IPV4, tcp->dst) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11805) nla_put(msg, NL80211_WOWLAN_TCP_DST_MAC, ETH_ALEN, tcp->dst_mac) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11806) nla_put_u16(msg, NL80211_WOWLAN_TCP_SRC_PORT, tcp->src_port) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11807) nla_put_u16(msg, NL80211_WOWLAN_TCP_DST_PORT, tcp->dst_port) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11808) nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11809) tcp->payload_len, tcp->payload) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11810) nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11811) tcp->data_interval) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11812) nla_put(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11813) tcp->wake_len, tcp->wake_data) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11814) nla_put(msg, NL80211_WOWLAN_TCP_WAKE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11815) DIV_ROUND_UP(tcp->wake_len, 8), tcp->wake_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11816) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11818) if (tcp->payload_seq.len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11819) nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11820) sizeof(tcp->payload_seq), &tcp->payload_seq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11821) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11823) if (tcp->payload_tok.len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11824) nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11825) sizeof(tcp->payload_tok) + tcp->tokens_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11826) &tcp->payload_tok))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11827) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11829) nla_nest_end(msg, nl_tcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11831) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11834) static int nl80211_send_wowlan_nd(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11835) struct cfg80211_sched_scan_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11837) struct nlattr *nd, *freqs, *matches, *match, *scan_plans, *scan_plan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11838) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11840) if (!req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11841) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11843) nd = nla_nest_start_noflag(msg, NL80211_WOWLAN_TRIG_NET_DETECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11844) if (!nd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11845) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11847) if (req->n_scan_plans == 1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11848) nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11849) req->scan_plans[0].interval * 1000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11850) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11852) if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11853) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11855) if (req->relative_rssi_set) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11856) struct nl80211_bss_select_rssi_adjust rssi_adjust;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11858) if (nla_put_s8(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11859) req->relative_rssi))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11860) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11862) rssi_adjust.band = req->rssi_adjust.band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11863) rssi_adjust.delta = req->rssi_adjust.delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11864) if (nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11865) sizeof(rssi_adjust), &rssi_adjust))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11866) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11869) freqs = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_FREQUENCIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11870) if (!freqs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11871) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11873) for (i = 0; i < req->n_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11874) if (nla_put_u32(msg, i, req->channels[i]->center_freq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11875) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11878) nla_nest_end(msg, freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11880) if (req->n_match_sets) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11881) matches = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11882) NL80211_ATTR_SCHED_SCAN_MATCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11883) if (!matches)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11884) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11886) for (i = 0; i < req->n_match_sets; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11887) match = nla_nest_start_noflag(msg, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11888) if (!match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11889) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11891) if (nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11892) req->match_sets[i].ssid.ssid_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11893) req->match_sets[i].ssid.ssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11894) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11895) nla_nest_end(msg, match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11897) nla_nest_end(msg, matches);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11900) scan_plans = nla_nest_start_noflag(msg, NL80211_ATTR_SCHED_SCAN_PLANS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11901) if (!scan_plans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11902) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11904) for (i = 0; i < req->n_scan_plans; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11905) scan_plan = nla_nest_start_noflag(msg, i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11906) if (!scan_plan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11907) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11909) if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11910) req->scan_plans[i].interval) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11911) (req->scan_plans[i].iterations &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11912) nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11913) req->scan_plans[i].iterations)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11914) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11915) nla_nest_end(msg, scan_plan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11917) nla_nest_end(msg, scan_plans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11919) nla_nest_end(msg, nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11921) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11924) static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11926) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11927) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11928) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11929) u32 size = NLMSG_DEFAULT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11931) if (!rdev->wiphy.wowlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11932) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11934) if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11935) /* adjust size to have room for all the data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11936) size += rdev->wiphy.wowlan_config->tcp->tokens_size +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11937) rdev->wiphy.wowlan_config->tcp->payload_len +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11938) rdev->wiphy.wowlan_config->tcp->wake_len +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11939) rdev->wiphy.wowlan_config->tcp->wake_len / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11942) msg = nlmsg_new(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11943) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11944) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11946) hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11947) NL80211_CMD_GET_WOWLAN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11948) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11949) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11951) if (rdev->wiphy.wowlan_config) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11952) struct nlattr *nl_wowlan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11954) nl_wowlan = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11955) NL80211_ATTR_WOWLAN_TRIGGERS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11956) if (!nl_wowlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11957) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11959) if ((rdev->wiphy.wowlan_config->any &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11960) nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11961) (rdev->wiphy.wowlan_config->disconnect &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11962) nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11963) (rdev->wiphy.wowlan_config->magic_pkt &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11964) nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11965) (rdev->wiphy.wowlan_config->gtk_rekey_failure &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11966) nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11967) (rdev->wiphy.wowlan_config->eap_identity_req &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11968) nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11969) (rdev->wiphy.wowlan_config->four_way_handshake &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11970) nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11971) (rdev->wiphy.wowlan_config->rfkill_release &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11972) nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11973) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11975) if (nl80211_send_wowlan_patterns(msg, rdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11976) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11978) if (nl80211_send_wowlan_tcp(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11979) rdev->wiphy.wowlan_config->tcp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11980) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11982) if (nl80211_send_wowlan_nd(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11983) msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11984) rdev->wiphy.wowlan_config->nd_config))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11985) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11987) nla_nest_end(msg, nl_wowlan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11990) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11991) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11993) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11994) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11995) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11998) static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11999) struct nlattr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12000) struct cfg80211_wowlan *trig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12002) struct nlattr *tb[NUM_NL80211_WOWLAN_TCP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12003) struct cfg80211_wowlan_tcp *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12004) struct nl80211_wowlan_tcp_data_token *tok = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12005) struct nl80211_wowlan_tcp_data_seq *seq = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12006) u32 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12007) u32 data_size, wake_size, tokens_size = 0, wake_mask_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12008) int err, port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12010) if (!rdev->wiphy.wowlan->tcp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12011) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12013) err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TCP, attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12014) nl80211_wowlan_tcp_policy, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12015) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12016) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12018) if (!tb[NL80211_WOWLAN_TCP_SRC_IPV4] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12019) !tb[NL80211_WOWLAN_TCP_DST_IPV4] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12020) !tb[NL80211_WOWLAN_TCP_DST_MAC] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12021) !tb[NL80211_WOWLAN_TCP_DST_PORT] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12022) !tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12023) !tb[NL80211_WOWLAN_TCP_DATA_INTERVAL] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12024) !tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12025) !tb[NL80211_WOWLAN_TCP_WAKE_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12026) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12028) data_size = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12029) if (data_size > rdev->wiphy.wowlan->tcp->data_payload_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12030) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12032) if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12033) rdev->wiphy.wowlan->tcp->data_interval_max ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12034) nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12035) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12037) wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12038) if (wake_size > rdev->wiphy.wowlan->tcp->wake_payload_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12039) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12041) wake_mask_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_MASK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12042) if (wake_mask_size != DIV_ROUND_UP(wake_size, 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12043) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12045) if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12046) u32 tokln = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12048) tok = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12049) tokens_size = tokln - sizeof(*tok);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12051) if (!tok->len || tokens_size % tok->len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12052) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12053) if (!rdev->wiphy.wowlan->tcp->tok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12054) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12055) if (tok->len > rdev->wiphy.wowlan->tcp->tok->max_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12056) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12057) if (tok->len < rdev->wiphy.wowlan->tcp->tok->min_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12058) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12059) if (tokens_size > rdev->wiphy.wowlan->tcp->tok->bufsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12060) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12061) if (tok->offset + tok->len > data_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12062) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12065) if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12066) seq = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12067) if (!rdev->wiphy.wowlan->tcp->seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12068) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12069) if (seq->len == 0 || seq->len > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12070) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12071) if (seq->len + seq->offset > data_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12072) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12075) size = sizeof(*cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12076) size += data_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12077) size += wake_size + wake_mask_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12078) size += tokens_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12080) cfg = kzalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12081) if (!cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12082) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12083) cfg->src = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_SRC_IPV4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12084) cfg->dst = nla_get_in_addr(tb[NL80211_WOWLAN_TCP_DST_IPV4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12085) memcpy(cfg->dst_mac, nla_data(tb[NL80211_WOWLAN_TCP_DST_MAC]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12086) ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12087) if (tb[NL80211_WOWLAN_TCP_SRC_PORT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12088) port = nla_get_u16(tb[NL80211_WOWLAN_TCP_SRC_PORT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12089) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12090) port = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12091) #ifdef CONFIG_INET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12092) /* allocate a socket and port for it and use it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12093) err = __sock_create(wiphy_net(&rdev->wiphy), PF_INET, SOCK_STREAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12094) IPPROTO_TCP, &cfg->sock, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12095) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12096) kfree(cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12097) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12099) if (inet_csk_get_port(cfg->sock->sk, port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12100) sock_release(cfg->sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12101) kfree(cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12102) return -EADDRINUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12104) cfg->src_port = inet_sk(cfg->sock->sk)->inet_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12105) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12106) if (!port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12107) kfree(cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12108) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12110) cfg->src_port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12111) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12113) cfg->dst_port = nla_get_u16(tb[NL80211_WOWLAN_TCP_DST_PORT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12114) cfg->payload_len = data_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12115) cfg->payload = (u8 *)cfg + sizeof(*cfg) + tokens_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12116) memcpy((void *)cfg->payload,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12117) nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12118) data_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12119) if (seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12120) cfg->payload_seq = *seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12121) cfg->data_interval = nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12122) cfg->wake_len = wake_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12123) cfg->wake_data = (u8 *)cfg + sizeof(*cfg) + tokens_size + data_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12124) memcpy((void *)cfg->wake_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12125) nla_data(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12126) wake_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12127) cfg->wake_mask = (u8 *)cfg + sizeof(*cfg) + tokens_size +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12128) data_size + wake_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12129) memcpy((void *)cfg->wake_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12130) nla_data(tb[NL80211_WOWLAN_TCP_WAKE_MASK]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12131) wake_mask_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12132) if (tok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12133) cfg->tokens_size = tokens_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12134) memcpy(&cfg->payload_tok, tok, sizeof(*tok) + tokens_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12137) trig->tcp = cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12142) static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12143) const struct wiphy_wowlan_support *wowlan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12144) struct nlattr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12145) struct cfg80211_wowlan *trig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12147) struct nlattr **tb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12148) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12150) tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12151) if (!tb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12152) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12154) if (!(wowlan->flags & WIPHY_WOWLAN_NET_DETECT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12155) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12156) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12159) err = nla_parse_nested_deprecated(tb, NL80211_ATTR_MAX, attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12160) nl80211_policy, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12161) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12162) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12164) trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12165) wowlan->max_nd_match_sets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12166) err = PTR_ERR_OR_ZERO(trig->nd_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12167) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12168) trig->nd_config = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12170) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12171) kfree(tb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12172) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12175) static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12177) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12178) struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12179) struct cfg80211_wowlan new_triggers = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12180) struct cfg80211_wowlan *ntrig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12181) const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12182) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12183) bool prev_enabled = rdev->wiphy.wowlan_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12184) bool regular = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12186) if (!wowlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12187) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12189) if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12190) cfg80211_rdev_free_wowlan(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12191) rdev->wiphy.wowlan_config = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12192) goto set_wakeup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12195) err = nla_parse_nested_deprecated(tb, MAX_NL80211_WOWLAN_TRIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12196) info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12197) nl80211_wowlan_policy, info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12198) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12199) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12201) if (tb[NL80211_WOWLAN_TRIG_ANY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12202) if (!(wowlan->flags & WIPHY_WOWLAN_ANY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12203) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12204) new_triggers.any = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12207) if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12208) if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12209) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12210) new_triggers.disconnect = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12211) regular = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12214) if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12215) if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12216) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12217) new_triggers.magic_pkt = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12218) regular = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12221) if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12222) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12224) if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12225) if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12226) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12227) new_triggers.gtk_rekey_failure = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12228) regular = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12231) if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12232) if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12233) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12234) new_triggers.eap_identity_req = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12235) regular = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12238) if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12239) if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12240) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12241) new_triggers.four_way_handshake = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12242) regular = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12245) if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12246) if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12247) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12248) new_triggers.rfkill_release = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12249) regular = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12252) if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12253) struct nlattr *pat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12254) int n_patterns = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12255) int rem, pat_len, mask_len, pkt_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12256) struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12258) regular = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12260) nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12261) rem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12262) n_patterns++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12263) if (n_patterns > wowlan->n_patterns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12264) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12266) new_triggers.patterns = kcalloc(n_patterns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12267) sizeof(new_triggers.patterns[0]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12268) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12269) if (!new_triggers.patterns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12270) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12272) new_triggers.n_patterns = n_patterns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12273) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12275) nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12276) rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12277) u8 *mask_pat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12279) err = nla_parse_nested_deprecated(pat_tb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12280) MAX_NL80211_PKTPAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12281) pat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12282) nl80211_packet_pattern_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12283) info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12284) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12285) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12287) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12288) if (!pat_tb[NL80211_PKTPAT_MASK] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12289) !pat_tb[NL80211_PKTPAT_PATTERN])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12290) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12291) pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12292) mask_len = DIV_ROUND_UP(pat_len, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12293) if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12294) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12295) if (pat_len > wowlan->pattern_max_len ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12296) pat_len < wowlan->pattern_min_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12297) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12299) if (!pat_tb[NL80211_PKTPAT_OFFSET])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12300) pkt_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12301) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12302) pkt_offset = nla_get_u32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12303) pat_tb[NL80211_PKTPAT_OFFSET]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12304) if (pkt_offset > wowlan->max_pkt_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12305) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12306) new_triggers.patterns[i].pkt_offset = pkt_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12308) mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12309) if (!mask_pat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12310) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12311) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12313) new_triggers.patterns[i].mask = mask_pat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12314) memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12315) mask_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12316) mask_pat += mask_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12317) new_triggers.patterns[i].pattern = mask_pat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12318) new_triggers.patterns[i].pattern_len = pat_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12319) memcpy(mask_pat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12320) nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12321) pat_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12322) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12326) if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12327) regular = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12328) err = nl80211_parse_wowlan_tcp(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12329) rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12330) &new_triggers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12331) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12332) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12335) if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12336) regular = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12337) err = nl80211_parse_wowlan_nd(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12338) rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12339) &new_triggers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12340) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12341) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12344) /* The 'any' trigger means the device continues operating more or less
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12345) * as in its normal operation mode and wakes up the host on most of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12346) * normal interrupts (like packet RX, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12347) * It therefore makes little sense to combine with the more constrained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12348) * wakeup trigger modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12349) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12350) if (new_triggers.any && regular) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12351) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12352) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12355) ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12356) if (!ntrig) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12357) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12358) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12360) cfg80211_rdev_free_wowlan(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12361) rdev->wiphy.wowlan_config = ntrig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12363) set_wakeup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12364) if (rdev->ops->set_wakeup &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12365) prev_enabled != !!rdev->wiphy.wowlan_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12366) rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12368) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12369) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12370) for (i = 0; i < new_triggers.n_patterns; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12371) kfree(new_triggers.patterns[i].mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12372) kfree(new_triggers.patterns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12373) if (new_triggers.tcp && new_triggers.tcp->sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12374) sock_release(new_triggers.tcp->sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12375) kfree(new_triggers.tcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12376) kfree(new_triggers.nd_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12377) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12379) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12381) static int nl80211_send_coalesce_rules(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12382) struct cfg80211_registered_device *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12384) struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12385) int i, j, pat_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12386) struct cfg80211_coalesce_rules *rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12388) if (!rdev->coalesce->n_rules)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12389) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12391) nl_rules = nla_nest_start_noflag(msg, NL80211_ATTR_COALESCE_RULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12392) if (!nl_rules)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12393) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12395) for (i = 0; i < rdev->coalesce->n_rules; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12396) nl_rule = nla_nest_start_noflag(msg, i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12397) if (!nl_rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12398) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12400) rule = &rdev->coalesce->rules[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12401) if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12402) rule->delay))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12403) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12405) if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12406) rule->condition))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12407) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12409) nl_pats = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12410) NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12411) if (!nl_pats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12412) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12414) for (j = 0; j < rule->n_patterns; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12415) nl_pat = nla_nest_start_noflag(msg, j + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12416) if (!nl_pat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12417) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12418) pat_len = rule->patterns[j].pattern_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12419) if (nla_put(msg, NL80211_PKTPAT_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12420) DIV_ROUND_UP(pat_len, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12421) rule->patterns[j].mask) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12422) nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12423) rule->patterns[j].pattern) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12424) nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12425) rule->patterns[j].pkt_offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12426) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12427) nla_nest_end(msg, nl_pat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12429) nla_nest_end(msg, nl_pats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12430) nla_nest_end(msg, nl_rule);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12432) nla_nest_end(msg, nl_rules);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12434) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12437) static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12439) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12440) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12441) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12443) if (!rdev->wiphy.coalesce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12444) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12446) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12447) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12448) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12450) hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12451) NL80211_CMD_GET_COALESCE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12452) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12453) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12455) if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12456) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12458) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12459) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12461) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12462) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12463) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12466) void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12468) struct cfg80211_coalesce *coalesce = rdev->coalesce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12469) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12470) struct cfg80211_coalesce_rules *rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12472) if (!coalesce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12473) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12475) for (i = 0; i < coalesce->n_rules; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12476) rule = &coalesce->rules[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12477) for (j = 0; j < rule->n_patterns; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12478) kfree(rule->patterns[j].mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12479) kfree(rule->patterns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12481) kfree(coalesce->rules);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12482) kfree(coalesce);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12483) rdev->coalesce = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12486) static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12487) struct nlattr *rule,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12488) struct cfg80211_coalesce_rules *new_rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12490) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12491) const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12492) struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE], *pat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12493) int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12494) struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12496) err = nla_parse_nested_deprecated(tb, NL80211_ATTR_COALESCE_RULE_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12497) rule, nl80211_coalesce_policy, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12498) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12499) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12501) if (tb[NL80211_ATTR_COALESCE_RULE_DELAY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12502) new_rule->delay =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12503) nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12504) if (new_rule->delay > coalesce->max_delay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12505) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12507) if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12508) new_rule->condition =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12509) nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12511) if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12512) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12514) nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12515) rem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12516) n_patterns++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12517) if (n_patterns > coalesce->n_patterns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12518) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12520) new_rule->patterns = kcalloc(n_patterns, sizeof(new_rule->patterns[0]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12521) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12522) if (!new_rule->patterns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12523) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12525) new_rule->n_patterns = n_patterns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12526) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12528) nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12529) rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12530) u8 *mask_pat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12532) err = nla_parse_nested_deprecated(pat_tb, MAX_NL80211_PKTPAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12533) pat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12534) nl80211_packet_pattern_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12535) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12536) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12537) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12539) if (!pat_tb[NL80211_PKTPAT_MASK] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12540) !pat_tb[NL80211_PKTPAT_PATTERN])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12541) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12542) pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12543) mask_len = DIV_ROUND_UP(pat_len, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12544) if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12545) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12546) if (pat_len > coalesce->pattern_max_len ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12547) pat_len < coalesce->pattern_min_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12548) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12550) if (!pat_tb[NL80211_PKTPAT_OFFSET])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12551) pkt_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12552) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12553) pkt_offset = nla_get_u32(pat_tb[NL80211_PKTPAT_OFFSET]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12554) if (pkt_offset > coalesce->max_pkt_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12555) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12556) new_rule->patterns[i].pkt_offset = pkt_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12558) mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12559) if (!mask_pat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12560) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12562) new_rule->patterns[i].mask = mask_pat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12563) memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12564) mask_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12566) mask_pat += mask_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12567) new_rule->patterns[i].pattern = mask_pat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12568) new_rule->patterns[i].pattern_len = pat_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12569) memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12570) pat_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12571) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12574) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12577) static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12579) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12580) const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12581) struct cfg80211_coalesce new_coalesce = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12582) struct cfg80211_coalesce *n_coalesce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12583) int err, rem_rule, n_rules = 0, i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12584) struct nlattr *rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12585) struct cfg80211_coalesce_rules *tmp_rule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12587) if (!rdev->wiphy.coalesce || !rdev->ops->set_coalesce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12588) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12590) if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12591) cfg80211_rdev_free_coalesce(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12592) rdev_set_coalesce(rdev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12593) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12596) nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12597) rem_rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12598) n_rules++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12599) if (n_rules > coalesce->n_rules)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12600) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12602) new_coalesce.rules = kcalloc(n_rules, sizeof(new_coalesce.rules[0]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12603) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12604) if (!new_coalesce.rules)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12605) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12607) new_coalesce.n_rules = n_rules;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12608) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12610) nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12611) rem_rule) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12612) err = nl80211_parse_coalesce_rule(rdev, rule,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12613) &new_coalesce.rules[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12614) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12615) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12617) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12620) err = rdev_set_coalesce(rdev, &new_coalesce);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12621) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12622) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12624) n_coalesce = kmemdup(&new_coalesce, sizeof(new_coalesce), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12625) if (!n_coalesce) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12626) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12627) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12629) cfg80211_rdev_free_coalesce(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12630) rdev->coalesce = n_coalesce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12632) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12633) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12634) for (i = 0; i < new_coalesce.n_rules; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12635) tmp_rule = &new_coalesce.rules[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12636) for (j = 0; j < tmp_rule->n_patterns; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12637) kfree(tmp_rule->patterns[j].mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12638) kfree(tmp_rule->patterns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12640) kfree(new_coalesce.rules);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12642) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12645) static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12647) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12648) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12649) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12650) struct nlattr *tb[NUM_NL80211_REKEY_DATA];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12651) struct cfg80211_gtk_rekey_data rekey_data = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12652) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12654) if (!info->attrs[NL80211_ATTR_REKEY_DATA])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12655) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12657) err = nla_parse_nested_deprecated(tb, MAX_NL80211_REKEY_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12658) info->attrs[NL80211_ATTR_REKEY_DATA],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12659) nl80211_rekey_policy, info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12660) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12661) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12663) if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12664) !tb[NL80211_REKEY_DATA_KCK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12665) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12666) if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12667) !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12668) nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KEK_EXT_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12669) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12670) if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12671) !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12672) nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KCK_EXT_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12673) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12675) rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12676) rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12677) rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12678) rekey_data.kek_len = nla_len(tb[NL80211_REKEY_DATA_KEK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12679) rekey_data.kck_len = nla_len(tb[NL80211_REKEY_DATA_KCK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12680) if (tb[NL80211_REKEY_DATA_AKM])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12681) rekey_data.akm = nla_get_u32(tb[NL80211_REKEY_DATA_AKM]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12683) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12684) if (!wdev->current_bss) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12685) err = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12686) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12689) if (!rdev->ops->set_rekey_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12690) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12691) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12694) err = rdev_set_rekey_data(rdev, dev, &rekey_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12695) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12696) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12697) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12700) static int nl80211_register_unexpected_frame(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12701) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12703) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12704) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12706) if (wdev->iftype != NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12707) wdev->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12708) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12710) if (wdev->ap_unexpected_nlportid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12711) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12713) wdev->ap_unexpected_nlportid = info->snd_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12714) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12717) static int nl80211_probe_client(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12718) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12719) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12720) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12721) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12722) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12723) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12724) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12725) const u8 *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12726) u64 cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12727) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12729) if (wdev->iftype != NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12730) wdev->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12731) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12733) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12734) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12736) if (!rdev->ops->probe_client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12737) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12739) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12740) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12741) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12743) hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12744) NL80211_CMD_PROBE_CLIENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12745) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12746) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12747) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12750) addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12752) err = rdev_probe_client(rdev, dev, addr, &cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12753) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12754) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12756) if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12757) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12758) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12760) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12762) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12764) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12765) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12766) free_msg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12767) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12768) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12771) static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12773) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12774) struct cfg80211_beacon_registration *reg, *nreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12775) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12777) if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12778) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12780) nreg = kzalloc(sizeof(*nreg), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12781) if (!nreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12782) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12784) /* First, check if already registered. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12785) spin_lock_bh(&rdev->beacon_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12786) list_for_each_entry(reg, &rdev->beacon_registrations, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12787) if (reg->nlportid == info->snd_portid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12788) rv = -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12789) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12792) /* Add it to the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12793) nreg->nlportid = info->snd_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12794) list_add(&nreg->list, &rdev->beacon_registrations);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12796) spin_unlock_bh(&rdev->beacon_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12798) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12799) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12800) spin_unlock_bh(&rdev->beacon_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12801) kfree(nreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12802) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12805) static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12806) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12807) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12808) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12809) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12811) if (!rdev->ops->start_p2p_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12812) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12814) if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12815) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12817) if (wdev_running(wdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12818) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12820) if (rfkill_blocked(rdev->rfkill))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12821) return -ERFKILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12823) err = rdev_start_p2p_device(rdev, wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12824) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12825) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12827) wdev->is_running = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12828) rdev->opencount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12830) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12833) static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12835) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12836) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12838) if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12839) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12841) if (!rdev->ops->stop_p2p_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12842) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12844) cfg80211_stop_p2p_device(rdev, wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12846) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12849) static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12851) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12852) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12853) struct cfg80211_nan_conf conf = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12854) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12856) if (wdev->iftype != NL80211_IFTYPE_NAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12857) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12859) if (wdev_running(wdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12860) return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12862) if (rfkill_blocked(rdev->rfkill))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12863) return -ERFKILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12865) if (!info->attrs[NL80211_ATTR_NAN_MASTER_PREF])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12866) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12868) conf.master_pref =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12869) nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12871) if (info->attrs[NL80211_ATTR_BANDS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12872) u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12874) if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12875) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12877) if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12878) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12880) conf.bands = bands;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12883) err = rdev_start_nan(rdev, wdev, &conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12884) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12885) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12887) wdev->is_running = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12888) rdev->opencount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12890) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12893) static int nl80211_stop_nan(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12895) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12896) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12898) if (wdev->iftype != NL80211_IFTYPE_NAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12899) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12901) cfg80211_stop_nan(rdev, wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12903) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12906) static int validate_nan_filter(struct nlattr *filter_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12908) struct nlattr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12909) int len = 0, n_entries = 0, rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12911) nla_for_each_nested(attr, filter_attr, rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12912) len += nla_len(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12913) n_entries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12916) if (len >= U8_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12917) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12919) return n_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12922) static int handle_nan_filter(struct nlattr *attr_filter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12923) struct cfg80211_nan_func *func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12924) bool tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12926) struct nlattr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12927) int n_entries, rem, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12928) struct cfg80211_nan_func_filter *filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12930) n_entries = validate_nan_filter(attr_filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12931) if (n_entries < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12932) return n_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12934) BUILD_BUG_ON(sizeof(*func->rx_filters) != sizeof(*func->tx_filters));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12936) filter = kcalloc(n_entries, sizeof(*func->rx_filters), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12937) if (!filter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12938) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12940) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12941) nla_for_each_nested(attr, attr_filter, rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12942) filter[i].filter = nla_memdup(attr, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12943) if (!filter[i].filter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12944) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12946) filter[i].len = nla_len(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12947) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12949) if (tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12950) func->num_tx_filters = n_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12951) func->tx_filters = filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12952) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12953) func->num_rx_filters = n_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12954) func->rx_filters = filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12957) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12959) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12960) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12961) nla_for_each_nested(attr, attr_filter, rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12962) kfree(filter[i].filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12963) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12965) kfree(filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12966) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12969) static int nl80211_nan_add_func(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12970) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12971) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12972) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12973) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12974) struct nlattr *tb[NUM_NL80211_NAN_FUNC_ATTR], *func_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12975) struct cfg80211_nan_func *func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12976) struct sk_buff *msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12977) void *hdr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12978) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12980) if (wdev->iftype != NL80211_IFTYPE_NAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12981) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12983) if (!wdev_running(wdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12984) return -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12986) if (!info->attrs[NL80211_ATTR_NAN_FUNC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12987) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12989) err = nla_parse_nested_deprecated(tb, NL80211_NAN_FUNC_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12990) info->attrs[NL80211_ATTR_NAN_FUNC],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12991) nl80211_nan_func_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12992) info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12993) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12994) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12996) func = kzalloc(sizeof(*func), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12997) if (!func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12998) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13000) func->cookie = cfg80211_assign_cookie(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13002) if (!tb[NL80211_NAN_FUNC_TYPE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13003) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13004) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13008) func->type = nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13010) if (!tb[NL80211_NAN_FUNC_SERVICE_ID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13011) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13012) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13015) memcpy(func->service_id, nla_data(tb[NL80211_NAN_FUNC_SERVICE_ID]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13016) sizeof(func->service_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13018) func->close_range =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13019) nla_get_flag(tb[NL80211_NAN_FUNC_CLOSE_RANGE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13021) if (tb[NL80211_NAN_FUNC_SERVICE_INFO]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13022) func->serv_spec_info_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13023) nla_len(tb[NL80211_NAN_FUNC_SERVICE_INFO]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13024) func->serv_spec_info =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13025) kmemdup(nla_data(tb[NL80211_NAN_FUNC_SERVICE_INFO]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13026) func->serv_spec_info_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13027) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13028) if (!func->serv_spec_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13029) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13030) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13034) if (tb[NL80211_NAN_FUNC_TTL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13035) func->ttl = nla_get_u32(tb[NL80211_NAN_FUNC_TTL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13037) switch (func->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13038) case NL80211_NAN_FUNC_PUBLISH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13039) if (!tb[NL80211_NAN_FUNC_PUBLISH_TYPE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13040) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13041) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13044) func->publish_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13045) nla_get_u8(tb[NL80211_NAN_FUNC_PUBLISH_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13046) func->publish_bcast =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13047) nla_get_flag(tb[NL80211_NAN_FUNC_PUBLISH_BCAST]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13049) if ((!(func->publish_type & NL80211_NAN_SOLICITED_PUBLISH)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13050) func->publish_bcast) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13051) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13052) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13054) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13055) case NL80211_NAN_FUNC_SUBSCRIBE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13056) func->subscribe_active =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13057) nla_get_flag(tb[NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13058) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13059) case NL80211_NAN_FUNC_FOLLOW_UP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13060) if (!tb[NL80211_NAN_FUNC_FOLLOW_UP_ID] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13061) !tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13062) !tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13063) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13064) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13067) func->followup_id =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13068) nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13069) func->followup_reqid =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13070) nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13071) memcpy(func->followup_dest.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13072) nla_data(tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13073) sizeof(func->followup_dest.addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13074) if (func->ttl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13075) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13076) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13078) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13079) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13080) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13081) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13084) if (tb[NL80211_NAN_FUNC_SRF]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13085) struct nlattr *srf_tb[NUM_NL80211_NAN_SRF_ATTR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13087) err = nla_parse_nested_deprecated(srf_tb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13088) NL80211_NAN_SRF_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13089) tb[NL80211_NAN_FUNC_SRF],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13090) nl80211_nan_srf_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13091) info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13092) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13093) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13095) func->srf_include =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13096) nla_get_flag(srf_tb[NL80211_NAN_SRF_INCLUDE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13098) if (srf_tb[NL80211_NAN_SRF_BF]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13099) if (srf_tb[NL80211_NAN_SRF_MAC_ADDRS] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13100) !srf_tb[NL80211_NAN_SRF_BF_IDX]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13101) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13102) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13105) func->srf_bf_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13106) nla_len(srf_tb[NL80211_NAN_SRF_BF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13107) func->srf_bf =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13108) kmemdup(nla_data(srf_tb[NL80211_NAN_SRF_BF]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13109) func->srf_bf_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13110) if (!func->srf_bf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13111) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13112) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13115) func->srf_bf_idx =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13116) nla_get_u8(srf_tb[NL80211_NAN_SRF_BF_IDX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13117) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13118) struct nlattr *attr, *mac_attr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13119) srf_tb[NL80211_NAN_SRF_MAC_ADDRS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13120) int n_entries, rem, i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13122) if (!mac_attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13123) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13124) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13127) n_entries = validate_acl_mac_addrs(mac_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13128) if (n_entries <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13129) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13130) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13133) func->srf_num_macs = n_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13134) func->srf_macs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13135) kcalloc(n_entries, sizeof(*func->srf_macs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13136) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13137) if (!func->srf_macs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13138) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13139) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13142) nla_for_each_nested(attr, mac_attr, rem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13143) memcpy(func->srf_macs[i++].addr, nla_data(attr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13144) sizeof(*func->srf_macs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13148) if (tb[NL80211_NAN_FUNC_TX_MATCH_FILTER]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13149) err = handle_nan_filter(tb[NL80211_NAN_FUNC_TX_MATCH_FILTER],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13150) func, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13151) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13152) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13155) if (tb[NL80211_NAN_FUNC_RX_MATCH_FILTER]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13156) err = handle_nan_filter(tb[NL80211_NAN_FUNC_RX_MATCH_FILTER],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13157) func, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13158) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13159) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13162) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13163) if (!msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13164) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13165) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13168) hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13169) NL80211_CMD_ADD_NAN_FUNCTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13170) /* This can't really happen - we just allocated 4KB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13171) if (WARN_ON(!hdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13172) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13173) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13176) err = rdev_add_nan_func(rdev, wdev, func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13177) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13178) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13179) cfg80211_free_nan_func(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13180) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13181) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13184) /* propagate the instance id and cookie to userspace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13185) if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, func->cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13186) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13187) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13189) func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13190) if (!func_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13191) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13193) if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13194) func->instance_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13195) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13197) nla_nest_end(msg, func_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13199) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13200) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13202) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13203) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13204) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13207) static int nl80211_nan_del_func(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13208) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13210) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13211) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13212) u64 cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13214) if (wdev->iftype != NL80211_IFTYPE_NAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13215) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13217) if (!wdev_running(wdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13218) return -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13220) if (!info->attrs[NL80211_ATTR_COOKIE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13221) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13223) cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13225) rdev_del_nan_func(rdev, wdev, cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13227) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13230) static int nl80211_nan_change_config(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13231) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13233) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13234) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13235) struct cfg80211_nan_conf conf = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13236) u32 changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13238) if (wdev->iftype != NL80211_IFTYPE_NAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13239) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13241) if (!wdev_running(wdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13242) return -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13244) if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13245) conf.master_pref =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13246) nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13247) if (conf.master_pref <= 1 || conf.master_pref == 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13248) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13250) changed |= CFG80211_NAN_CONF_CHANGED_PREF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13253) if (info->attrs[NL80211_ATTR_BANDS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13254) u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13256) if (bands & ~(u32)wdev->wiphy->nan_supported_bands)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13257) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13259) if (bands && !(bands & BIT(NL80211_BAND_2GHZ)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13260) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13262) conf.bands = bands;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13263) changed |= CFG80211_NAN_CONF_CHANGED_BANDS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13266) if (!changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13267) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13269) return rdev_nan_change_conf(rdev, wdev, &conf, changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13272) void cfg80211_nan_match(struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13273) struct cfg80211_nan_match_params *match, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13275) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13276) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13277) struct nlattr *match_attr, *local_func_attr, *peer_func_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13278) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13279) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13281) if (WARN_ON(!match->inst_id || !match->peer_inst_id || !match->addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13282) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13284) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13285) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13286) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13288) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_MATCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13289) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13290) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13291) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13294) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13295) (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13296) wdev->netdev->ifindex)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13297) nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13298) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13299) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13301) if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, match->cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13302) NL80211_ATTR_PAD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13303) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, match->addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13304) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13306) match_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_MATCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13307) if (!match_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13308) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13310) local_func_attr = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13311) NL80211_NAN_MATCH_FUNC_LOCAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13312) if (!local_func_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13313) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13315) if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->inst_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13316) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13318) nla_nest_end(msg, local_func_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13320) peer_func_attr = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13321) NL80211_NAN_MATCH_FUNC_PEER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13322) if (!peer_func_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13323) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13325) if (nla_put_u8(msg, NL80211_NAN_FUNC_TYPE, match->type) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13326) nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->peer_inst_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13327) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13329) if (match->info && match->info_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13330) nla_put(msg, NL80211_NAN_FUNC_SERVICE_INFO, match->info_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13331) match->info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13332) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13334) nla_nest_end(msg, peer_func_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13335) nla_nest_end(msg, match_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13336) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13338) if (!wdev->owner_nlportid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13339) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13340) msg, 0, NL80211_MCGRP_NAN, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13341) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13342) genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13343) wdev->owner_nlportid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13345) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13347) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13348) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13350) EXPORT_SYMBOL(cfg80211_nan_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13352) void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13353) u8 inst_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13354) enum nl80211_nan_func_term_reason reason,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13355) u64 cookie, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13357) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13358) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13359) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13360) struct nlattr *func_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13361) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13363) if (WARN_ON(!inst_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13364) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13366) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13367) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13368) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13370) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_NAN_FUNCTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13371) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13372) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13373) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13376) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13377) (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13378) wdev->netdev->ifindex)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13379) nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13380) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13381) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13383) if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13384) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13385) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13387) func_attr = nla_nest_start_noflag(msg, NL80211_ATTR_NAN_FUNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13388) if (!func_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13389) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13391) if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, inst_id) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13392) nla_put_u8(msg, NL80211_NAN_FUNC_TERM_REASON, reason))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13393) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13395) nla_nest_end(msg, func_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13396) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13398) if (!wdev->owner_nlportid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13399) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13400) msg, 0, NL80211_MCGRP_NAN, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13401) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13402) genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13403) wdev->owner_nlportid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13405) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13407) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13408) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13410) EXPORT_SYMBOL(cfg80211_nan_func_terminated);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13412) static int nl80211_get_protocol_features(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13413) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13415) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13416) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13418) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13419) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13420) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13422) hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13423) NL80211_CMD_GET_PROTOCOL_FEATURES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13424) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13425) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13427) if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13428) NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13429) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13431) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13432) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13434) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13435) kfree_skb(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13436) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13439) static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13441) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13442) struct cfg80211_update_ft_ies_params ft_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13443) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13445) if (!rdev->ops->update_ft_ies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13446) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13448) if (!info->attrs[NL80211_ATTR_MDID] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13449) !info->attrs[NL80211_ATTR_IE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13450) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13452) memset(&ft_params, 0, sizeof(ft_params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13453) ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13454) ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13455) ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13457) return rdev_update_ft_ies(rdev, dev, &ft_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13460) static int nl80211_crit_protocol_start(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13461) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13463) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13464) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13465) enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13466) u16 duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13467) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13469) if (!rdev->ops->crit_proto_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13470) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13472) if (WARN_ON(!rdev->ops->crit_proto_stop))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13473) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13475) if (rdev->crit_proto_nlportid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13476) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13478) /* determine protocol if provided */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13479) if (info->attrs[NL80211_ATTR_CRIT_PROT_ID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13480) proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13482) if (proto >= NUM_NL80211_CRIT_PROTO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13483) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13485) /* timeout must be provided */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13486) if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13487) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13489) duration =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13490) nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13492) ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13493) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13494) rdev->crit_proto_nlportid = info->snd_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13496) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13499) static int nl80211_crit_protocol_stop(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13500) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13502) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13503) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13505) if (!rdev->ops->crit_proto_stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13506) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13508) if (rdev->crit_proto_nlportid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13509) rdev->crit_proto_nlportid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13510) rdev_crit_proto_stop(rdev, wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13512) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13515) static int nl80211_vendor_check_policy(const struct wiphy_vendor_command *vcmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13516) struct nlattr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13517) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13519) if (vcmd->policy == VENDOR_CMD_RAW_DATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13520) if (attr->nla_type & NLA_F_NESTED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13521) NL_SET_ERR_MSG_ATTR(extack, attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13522) "unexpected nested data");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13523) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13526) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13529) if (!(attr->nla_type & NLA_F_NESTED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13530) NL_SET_ERR_MSG_ATTR(extack, attr, "expected nested data");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13531) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13534) return nla_validate_nested(attr, vcmd->maxattr, vcmd->policy, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13537) static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13539) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13540) struct wireless_dev *wdev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13541) __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13542) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13543) u32 vid, subcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13545) if (!rdev->wiphy.vendor_commands)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13546) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13548) if (IS_ERR(wdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13549) err = PTR_ERR(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13550) if (err != -EINVAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13551) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13552) wdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13553) } else if (wdev->wiphy != &rdev->wiphy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13554) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13557) if (!info->attrs[NL80211_ATTR_VENDOR_ID] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13558) !info->attrs[NL80211_ATTR_VENDOR_SUBCMD])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13559) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13561) vid = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13562) subcmd = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_SUBCMD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13563) for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13564) const struct wiphy_vendor_command *vcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13565) void *data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13566) int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13568) vcmd = &rdev->wiphy.vendor_commands[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13570) if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13571) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13573) if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13574) WIPHY_VENDOR_CMD_NEED_NETDEV)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13575) if (!wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13576) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13577) if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13578) !wdev->netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13579) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13581) if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13582) if (!wdev_running(wdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13583) return -ENETDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13585) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13586) wdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13589) if (!vcmd->doit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13590) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13592) if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13593) data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13594) len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13596) err = nl80211_vendor_check_policy(vcmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13597) info->attrs[NL80211_ATTR_VENDOR_DATA],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13598) info->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13599) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13600) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13603) rdev->cur_cmd_info = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13604) err = vcmd->doit(&rdev->wiphy, wdev, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13605) rdev->cur_cmd_info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13606) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13609) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13612) static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13613) struct netlink_callback *cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13614) struct cfg80211_registered_device **rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13615) struct wireless_dev **wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13617) struct nlattr **attrbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13618) u32 vid, subcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13619) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13620) int vcmd_idx = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13621) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13622) void *data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13623) unsigned int data_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13625) if (cb->args[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13626) /* subtract the 1 again here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13627) struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13628) struct wireless_dev *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13630) if (!wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13631) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13632) *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13633) *wdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13635) if (cb->args[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13636) list_for_each_entry(tmp, &wiphy->wdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13637) if (tmp->identifier == cb->args[1] - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13638) *wdev = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13639) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13644) /* keep rtnl locked in successful case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13645) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13648) attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13649) if (!attrbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13650) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13652) err = nlmsg_parse_deprecated(cb->nlh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13653) GENL_HDRLEN + nl80211_fam.hdrsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13654) attrbuf, nl80211_fam.maxattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13655) nl80211_policy, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13656) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13657) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13659) if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13660) !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13661) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13662) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13665) *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13666) if (IS_ERR(*wdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13667) *wdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13669) *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13670) if (IS_ERR(*rdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13671) err = PTR_ERR(*rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13672) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13675) vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13676) subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13678) for (i = 0; i < (*rdev)->wiphy.n_vendor_commands; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13679) const struct wiphy_vendor_command *vcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13681) vcmd = &(*rdev)->wiphy.vendor_commands[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13683) if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13684) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13686) if (!vcmd->dumpit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13687) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13688) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13691) vcmd_idx = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13692) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13695) if (vcmd_idx < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13696) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13697) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13700) if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13701) data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13702) data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13704) err = nl80211_vendor_check_policy(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13705) &(*rdev)->wiphy.vendor_commands[vcmd_idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13706) attrbuf[NL80211_ATTR_VENDOR_DATA],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13707) cb->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13708) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13709) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13712) /* 0 is the first index - add 1 to parse only once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13713) cb->args[0] = (*rdev)->wiphy_idx + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13714) /* add 1 to know if it was NULL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13715) cb->args[1] = *wdev ? (*wdev)->identifier + 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13716) cb->args[2] = vcmd_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13717) cb->args[3] = (unsigned long)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13718) cb->args[4] = data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13720) /* keep rtnl locked in successful case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13721) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13722) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13723) kfree(attrbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13724) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13727) static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13728) struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13730) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13731) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13732) unsigned int vcmd_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13733) const struct wiphy_vendor_command *vcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13734) void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13735) int data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13736) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13737) struct nlattr *vendor_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13739) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13740) err = nl80211_prepare_vendor_dump(skb, cb, &rdev, &wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13741) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13742) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13744) vcmd_idx = cb->args[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13745) data = (void *)cb->args[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13746) data_len = cb->args[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13747) vcmd = &rdev->wiphy.vendor_commands[vcmd_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13749) if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13750) WIPHY_VENDOR_CMD_NEED_NETDEV)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13751) if (!wdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13752) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13753) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13755) if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13756) !wdev->netdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13757) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13758) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13761) if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13762) if (!wdev_running(wdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13763) err = -ENETDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13764) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13769) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13770) void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13771) cb->nlh->nlmsg_seq, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13772) NL80211_CMD_VENDOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13773) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13774) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13776) if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13777) (wdev && nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13778) wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13779) NL80211_ATTR_PAD))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13780) genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13781) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13784) vendor_data = nla_nest_start_noflag(skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13785) NL80211_ATTR_VENDOR_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13786) if (!vendor_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13787) genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13788) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13791) err = vcmd->dumpit(&rdev->wiphy, wdev, skb, data, data_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13792) (unsigned long *)&cb->args[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13793) nla_nest_end(skb, vendor_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13795) if (err == -ENOBUFS || err == -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13796) genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13797) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13798) } else if (err <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13799) genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13800) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13803) genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13806) err = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13807) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13808) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13809) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13812) struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13813) enum nl80211_commands cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13814) enum nl80211_attrs attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13815) int approxlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13816) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13817) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13819) if (WARN_ON(!rdev->cur_cmd_info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13820) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13822) return __cfg80211_alloc_vendor_skb(rdev, NULL, approxlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13823) rdev->cur_cmd_info->snd_portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13824) rdev->cur_cmd_info->snd_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13825) cmd, attr, NULL, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13827) EXPORT_SYMBOL(__cfg80211_alloc_reply_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13829) int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13831) struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13832) void *hdr = ((void **)skb->cb)[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13833) struct nlattr *data = ((void **)skb->cb)[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13835) /* clear CB data for netlink core to own from now on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13836) memset(skb->cb, 0, sizeof(skb->cb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13838) if (WARN_ON(!rdev->cur_cmd_info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13839) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13840) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13843) nla_nest_end(skb, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13844) genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13845) return genlmsg_reply(skb, rdev->cur_cmd_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13847) EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13849) unsigned int cfg80211_vendor_cmd_get_sender(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13851) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13853) if (WARN_ON(!rdev->cur_cmd_info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13854) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13856) return rdev->cur_cmd_info->snd_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13858) EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_get_sender);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13860) static int nl80211_set_qos_map(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13861) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13863) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13864) struct cfg80211_qos_map *qos_map = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13865) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13866) u8 *pos, len, num_des, des_len, des;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13867) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13869) if (!rdev->ops->set_qos_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13870) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13872) if (info->attrs[NL80211_ATTR_QOS_MAP]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13873) pos = nla_data(info->attrs[NL80211_ATTR_QOS_MAP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13874) len = nla_len(info->attrs[NL80211_ATTR_QOS_MAP]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13876) if (len % 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13877) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13879) qos_map = kzalloc(sizeof(struct cfg80211_qos_map), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13880) if (!qos_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13881) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13883) num_des = (len - IEEE80211_QOS_MAP_LEN_MIN) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13884) if (num_des) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13885) des_len = num_des *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13886) sizeof(struct cfg80211_dscp_exception);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13887) memcpy(qos_map->dscp_exception, pos, des_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13888) qos_map->num_des = num_des;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13889) for (des = 0; des < num_des; des++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13890) if (qos_map->dscp_exception[des].up > 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13891) kfree(qos_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13892) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13895) pos += des_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13897) memcpy(qos_map->up, pos, IEEE80211_QOS_MAP_LEN_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13900) wdev_lock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13901) ret = nl80211_key_allowed(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13902) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13903) ret = rdev_set_qos_map(rdev, dev, qos_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13904) wdev_unlock(dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13906) kfree(qos_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13907) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13910) static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13912) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13913) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13914) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13915) const u8 *peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13916) u8 tsid, up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13917) u16 admitted_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13918) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13920) if (!(rdev->wiphy.features & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13921) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13923) if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13924) !info->attrs[NL80211_ATTR_USER_PRIO])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13925) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13927) tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13928) up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13930) /* WMM uses TIDs 0-7 even for TSPEC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13931) if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13932) /* TODO: handle 802.11 TSPEC/admission control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13933) * need more attributes for that (e.g. BA session requirement);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13934) * change the WMM adminssion test above to allow both then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13935) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13936) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13939) peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13941) if (info->attrs[NL80211_ATTR_ADMITTED_TIME]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13942) admitted_time =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13943) nla_get_u16(info->attrs[NL80211_ATTR_ADMITTED_TIME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13944) if (!admitted_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13945) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13948) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13949) switch (wdev->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13950) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13951) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13952) if (wdev->current_bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13953) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13954) err = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13955) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13956) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13957) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13958) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13961) err = rdev_add_tx_ts(rdev, dev, tsid, peer, up, admitted_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13963) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13964) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13965) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13968) static int nl80211_del_tx_ts(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13970) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13971) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13972) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13973) const u8 *peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13974) u8 tsid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13975) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13977) if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13978) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13980) tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13981) peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13983) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13984) err = rdev_del_tx_ts(rdev, dev, tsid, peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13985) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13987) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13990) static int nl80211_tdls_channel_switch(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13991) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13992) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13993) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13994) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13995) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13996) struct cfg80211_chan_def chandef = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13997) const u8 *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13998) u8 oper_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13999) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14001) if (!rdev->ops->tdls_channel_switch ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14002) !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14003) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14005) switch (dev->ieee80211_ptr->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14006) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14007) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14008) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14009) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14010) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14013) if (!info->attrs[NL80211_ATTR_MAC] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14014) !info->attrs[NL80211_ATTR_OPER_CLASS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14015) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14017) err = nl80211_parse_chandef(rdev, info, &chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14018) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14019) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14021) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14022) * Don't allow wide channels on the 2.4Ghz band, as per IEEE802.11-2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14023) * section 10.22.6.2.1. Disallow 5/10Mhz channels as well for now, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14024) * specification is not defined for them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14025) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14026) if (chandef.chan->band == NL80211_BAND_2GHZ &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14027) chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14028) chandef.width != NL80211_CHAN_WIDTH_20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14029) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14031) /* we will be active on the TDLS link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14032) if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14033) wdev->iftype))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14034) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14036) /* don't allow switching to DFS channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14037) if (cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, wdev->iftype))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14038) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14040) addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14041) oper_class = nla_get_u8(info->attrs[NL80211_ATTR_OPER_CLASS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14043) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14044) err = rdev_tdls_channel_switch(rdev, dev, addr, oper_class, &chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14045) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14047) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14050) static int nl80211_tdls_cancel_channel_switch(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14051) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14052) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14053) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14054) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14055) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14056) const u8 *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14058) if (!rdev->ops->tdls_channel_switch ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14059) !rdev->ops->tdls_cancel_channel_switch ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14060) !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14061) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14063) switch (dev->ieee80211_ptr->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14064) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14065) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14066) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14067) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14068) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14071) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14072) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14074) addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14076) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14077) rdev_tdls_cancel_channel_switch(rdev, dev, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14078) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14080) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14083) static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14084) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14085) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14086) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14087) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14088) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14089) const struct nlattr *nla;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14090) bool enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14092) if (!rdev->ops->set_multicast_to_unicast)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14093) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14095) if (wdev->iftype != NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14096) wdev->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14097) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14099) nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14100) enabled = nla_get_flag(nla);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14102) return rdev_set_multicast_to_unicast(rdev, dev, enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14105) static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14107) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14108) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14109) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14110) struct cfg80211_pmk_conf pmk_conf = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14111) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14113) if (wdev->iftype != NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14114) wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14115) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14117) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14118) NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14119) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14121) if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_PMK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14122) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14124) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14125) if (!wdev->current_bss) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14126) ret = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14127) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14130) pmk_conf.aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14131) if (memcmp(pmk_conf.aa, wdev->current_bss->pub.bssid, ETH_ALEN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14132) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14133) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14136) pmk_conf.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14137) pmk_conf.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14138) if (pmk_conf.pmk_len != WLAN_PMK_LEN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14139) pmk_conf.pmk_len != WLAN_PMK_LEN_SUITE_B_192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14140) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14141) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14144) if (info->attrs[NL80211_ATTR_PMKR0_NAME])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14145) pmk_conf.pmk_r0_name =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14146) nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14148) ret = rdev_set_pmk(rdev, dev, &pmk_conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14149) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14150) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14151) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14154) static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14156) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14157) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14158) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14159) const u8 *aa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14160) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14162) if (wdev->iftype != NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14163) wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14164) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14166) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14167) NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14168) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14170) if (!info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14171) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14173) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14174) aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14175) ret = rdev_del_pmk(rdev, dev, aa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14176) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14178) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14181) static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14183) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14184) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14185) struct cfg80211_external_auth_params params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14187) if (!rdev->ops->external_auth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14188) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14190) if (!info->attrs[NL80211_ATTR_SSID] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14191) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14192) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14193) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14195) if (!info->attrs[NL80211_ATTR_BSSID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14196) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14198) if (!info->attrs[NL80211_ATTR_STATUS_CODE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14199) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14201) memset(¶ms, 0, sizeof(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14203) if (info->attrs[NL80211_ATTR_SSID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14204) params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14205) if (params.ssid.ssid_len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14206) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14207) memcpy(params.ssid.ssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14208) nla_data(info->attrs[NL80211_ATTR_SSID]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14209) params.ssid.ssid_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14212) memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14213) ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14215) params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14217) if (info->attrs[NL80211_ATTR_PMKID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14218) params.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14220) return rdev_external_auth(rdev, dev, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14223) static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14225) bool dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14226) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14227) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14228) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14229) const u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14230) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14231) u8 *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14232) u16 proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14233) bool noencrypt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14234) u64 cookie = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14235) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14237) if (!wiphy_ext_feature_isset(&rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14238) NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14239) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14241) if (!rdev->ops->tx_control_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14242) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14244) if (!info->attrs[NL80211_ATTR_FRAME] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14245) !info->attrs[NL80211_ATTR_MAC] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14246) !info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14247) GENL_SET_ERR_MSG(info, "Frame, MAC or ethertype missing");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14248) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14251) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14253) switch (wdev->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14254) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14255) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14256) case NL80211_IFTYPE_MESH_POINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14257) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14258) case NL80211_IFTYPE_ADHOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14259) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14260) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14261) if (wdev->current_bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14262) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14263) err = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14264) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14265) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14266) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14267) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14270) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14272) buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14273) len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14274) dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14275) proto = nla_get_u16(info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14276) noencrypt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14277) nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14279) err = rdev_tx_control_port(rdev, dev, buf, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14280) dest, cpu_to_be16(proto), noencrypt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14281) dont_wait_for_ack ? NULL : &cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14282) if (!err && !dont_wait_for_ack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14283) nl_set_extack_cookie_u64(info->extack, cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14284) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14285) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14286) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14287) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14290) static int nl80211_get_ftm_responder_stats(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14291) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14293) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14294) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14295) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14296) struct cfg80211_ftm_responder_stats ftm_stats = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14297) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14298) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14299) struct nlattr *ftm_stats_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14300) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14302) if (wdev->iftype != NL80211_IFTYPE_AP || !wdev->beacon_interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14303) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14305) err = rdev_get_ftm_responder_stats(rdev, dev, &ftm_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14306) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14307) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14309) if (!ftm_stats.filled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14310) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14312) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14313) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14314) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14316) hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14317) NL80211_CMD_GET_FTM_RESPONDER_STATS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14318) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14319) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14321) if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14322) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14324) ftm_stats_attr = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14325) NL80211_ATTR_FTM_RESPONDER_STATS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14326) if (!ftm_stats_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14327) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14329) #define SET_FTM(field, name, type) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14330) do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14331) nla_put_ ## type(msg, NL80211_FTM_STATS_ ## name, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14332) ftm_stats.field)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14333) goto nla_put_failure; } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14334) #define SET_FTM_U64(field, name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14335) do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14336) nla_put_u64_64bit(msg, NL80211_FTM_STATS_ ## name, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14337) ftm_stats.field, NL80211_FTM_STATS_PAD)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14338) goto nla_put_failure; } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14340) SET_FTM(success_num, SUCCESS_NUM, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14341) SET_FTM(partial_num, PARTIAL_NUM, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14342) SET_FTM(failed_num, FAILED_NUM, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14343) SET_FTM(asap_num, ASAP_NUM, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14344) SET_FTM(non_asap_num, NON_ASAP_NUM, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14345) SET_FTM_U64(total_duration_ms, TOTAL_DURATION_MSEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14346) SET_FTM(unknown_triggers_num, UNKNOWN_TRIGGERS_NUM, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14347) SET_FTM(reschedule_requests_num, RESCHEDULE_REQUESTS_NUM, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14348) SET_FTM(out_of_window_triggers_num, OUT_OF_WINDOW_TRIGGERS_NUM, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14349) #undef SET_FTM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14351) nla_nest_end(msg, ftm_stats_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14353) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14354) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14356) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14357) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14358) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14361) static int nl80211_update_owe_info(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14363) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14364) struct cfg80211_update_owe_info owe_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14365) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14367) if (!rdev->ops->update_owe_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14368) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14370) if (!info->attrs[NL80211_ATTR_STATUS_CODE] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14371) !info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14372) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14374) memset(&owe_info, 0, sizeof(owe_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14375) owe_info.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14376) nla_memcpy(owe_info.peer, info->attrs[NL80211_ATTR_MAC], ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14378) if (info->attrs[NL80211_ATTR_IE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14379) owe_info.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14380) owe_info.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14383) return rdev_update_owe_info(rdev, dev, &owe_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14386) static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14388) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14389) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14390) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14391) struct station_info sinfo = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14392) const u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14393) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14394) u8 *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14395) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14397) if (!rdev->ops->probe_mesh_link || !rdev->ops->get_station)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14398) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14400) if (!info->attrs[NL80211_ATTR_MAC] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14401) !info->attrs[NL80211_ATTR_FRAME]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14402) GENL_SET_ERR_MSG(info, "Frame or MAC missing");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14403) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14406) if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14407) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14409) dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14410) buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14411) len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14413) if (len < sizeof(struct ethhdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14414) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14416) if (!ether_addr_equal(buf, dest) || is_multicast_ether_addr(buf) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14417) !ether_addr_equal(buf + ETH_ALEN, dev->dev_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14418) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14420) err = rdev_get_station(rdev, dev, dest, &sinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14421) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14422) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14424) cfg80211_sinfo_release_content(&sinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14426) return rdev_probe_mesh_link(rdev, dev, dest, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14429) static int parse_tid_conf(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14430) struct nlattr *attrs[], struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14431) struct cfg80211_tid_cfg *tid_conf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14432) struct genl_info *info, const u8 *peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14434) struct netlink_ext_ack *extack = info->extack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14435) u64 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14436) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14438) if (!attrs[NL80211_TID_CONFIG_ATTR_TIDS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14439) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14441) tid_conf->config_override =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14442) nla_get_flag(attrs[NL80211_TID_CONFIG_ATTR_OVERRIDE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14443) tid_conf->tids = nla_get_u16(attrs[NL80211_TID_CONFIG_ATTR_TIDS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14445) if (tid_conf->config_override) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14446) if (rdev->ops->reset_tid_config) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14447) err = rdev_reset_tid_config(rdev, dev, peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14448) tid_conf->tids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14449) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14450) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14451) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14452) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14456) if (attrs[NL80211_TID_CONFIG_ATTR_NOACK]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14457) tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_NOACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14458) tid_conf->noack =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14459) nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_NOACK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14462) if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14463) tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_SHORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14464) tid_conf->retry_short =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14465) nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14467) if (tid_conf->retry_short > rdev->wiphy.max_data_retry_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14468) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14471) if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14472) tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14473) tid_conf->retry_long =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14474) nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14476) if (tid_conf->retry_long > rdev->wiphy.max_data_retry_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14477) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14480) if (attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14481) tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14482) tid_conf->ampdu =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14483) nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14486) if (attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14487) tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14488) tid_conf->rtscts =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14489) nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14492) if (attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14493) tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14494) tid_conf->amsdu =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14495) nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14498) if (attrs[NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14499) u32 idx = NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14501) tid_conf->txrate_type = nla_get_u8(attrs[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14503) if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14504) attr = NL80211_TID_CONFIG_ATTR_TX_RATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14505) err = nl80211_parse_tx_bitrate_mask(info, attrs, attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14506) &tid_conf->txrate_mask, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14507) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14508) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14510) tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14512) tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14515) if (peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14516) mask = rdev->wiphy.tid_config_support.peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14517) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14518) mask = rdev->wiphy.tid_config_support.vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14520) if (tid_conf->mask & ~mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14521) NL_SET_ERR_MSG(extack, "unsupported TID configuration");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14522) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14525) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14528) static int nl80211_set_tid_config(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14529) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14531) struct cfg80211_registered_device *rdev = info->user_ptr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14532) struct nlattr *attrs[NL80211_TID_CONFIG_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14533) struct net_device *dev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14534) struct cfg80211_tid_config *tid_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14535) struct nlattr *tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14536) int conf_idx = 0, rem_conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14537) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14538) u32 num_conf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14540) if (!info->attrs[NL80211_ATTR_TID_CONFIG])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14541) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14543) if (!rdev->ops->set_tid_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14544) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14546) nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14547) rem_conf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14548) num_conf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14550) tid_config = kzalloc(struct_size(tid_config, tid_conf, num_conf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14551) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14552) if (!tid_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14553) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14555) tid_config->n_tid_conf = num_conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14557) if (info->attrs[NL80211_ATTR_MAC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14558) tid_config->peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14560) nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14561) rem_conf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14562) ret = nla_parse_nested(attrs, NL80211_TID_CONFIG_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14563) tid, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14565) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14566) goto bad_tid_conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14568) ret = parse_tid_conf(rdev, attrs, dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14569) &tid_config->tid_conf[conf_idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14570) info, tid_config->peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14571) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14572) goto bad_tid_conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14574) conf_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14577) ret = rdev_set_tid_config(rdev, dev, tid_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14579) bad_tid_conf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14580) kfree(tid_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14581) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14584) #define NL80211_FLAG_NEED_WIPHY 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14585) #define NL80211_FLAG_NEED_NETDEV 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14586) #define NL80211_FLAG_NEED_RTNL 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14587) #define NL80211_FLAG_CHECK_NETDEV_UP 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14588) #define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14589) NL80211_FLAG_CHECK_NETDEV_UP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14590) #define NL80211_FLAG_NEED_WDEV 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14591) /* If a netdev is associated, it must be UP, P2P must be started */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14592) #define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14593) NL80211_FLAG_CHECK_NETDEV_UP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14594) #define NL80211_FLAG_CLEAR_SKB 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14596) static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14597) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14599) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14600) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14601) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14602) bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14604) if (rtnl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14605) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14607) if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14608) rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14609) if (IS_ERR(rdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14610) if (rtnl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14611) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14612) return PTR_ERR(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14614) info->user_ptr[0] = rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14615) } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14616) ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14617) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14619) wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14620) info->attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14621) if (IS_ERR(wdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14622) if (rtnl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14623) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14624) return PTR_ERR(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14627) dev = wdev->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14628) rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14630) if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14631) if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14632) if (rtnl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14633) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14634) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14637) info->user_ptr[1] = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14638) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14639) info->user_ptr[1] = wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14642) if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14643) !wdev_running(wdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14644) if (rtnl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14645) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14646) return -ENETDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14649) if (dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14650) dev_hold(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14652) info->user_ptr[0] = rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14655) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14658) static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14659) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14661) if (info->user_ptr[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14662) if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14663) struct wireless_dev *wdev = info->user_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14665) if (wdev->netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14666) dev_put(wdev->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14667) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14668) dev_put(info->user_ptr[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14672) if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14673) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14675) /* If needed, clear the netlink message payload from the SKB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14676) * as it might contain key data that shouldn't stick around on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14677) * the heap after the SKB is freed. The netlink message header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14678) * is still needed for further processing, so leave it intact.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14679) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14680) if (ops->internal_flags & NL80211_FLAG_CLEAR_SKB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14681) struct nlmsghdr *nlh = nlmsg_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14683) memset(nlmsg_data(nlh), 0, nlmsg_len(nlh));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14687) static const struct genl_ops nl80211_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14689) .cmd = NL80211_CMD_GET_WIPHY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14690) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14691) .doit = nl80211_get_wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14692) .dumpit = nl80211_dump_wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14693) .done = nl80211_dump_wiphy_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14694) /* can be retrieved by unprivileged users */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14695) .internal_flags = NL80211_FLAG_NEED_WIPHY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14696) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14697) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14698) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14700) static const struct genl_small_ops nl80211_small_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14702) .cmd = NL80211_CMD_SET_WIPHY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14703) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14704) .doit = nl80211_set_wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14705) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14706) .internal_flags = NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14707) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14708) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14709) .cmd = NL80211_CMD_GET_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14710) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14711) .doit = nl80211_get_interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14712) .dumpit = nl80211_dump_interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14713) /* can be retrieved by unprivileged users */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14714) .internal_flags = NL80211_FLAG_NEED_WDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14715) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14716) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14718) .cmd = NL80211_CMD_SET_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14719) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14720) .doit = nl80211_set_interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14721) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14722) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14723) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14724) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14726) .cmd = NL80211_CMD_NEW_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14727) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14728) .doit = nl80211_new_interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14729) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14730) .internal_flags = NL80211_FLAG_NEED_WIPHY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14731) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14732) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14734) .cmd = NL80211_CMD_DEL_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14735) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14736) .doit = nl80211_del_interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14737) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14738) .internal_flags = NL80211_FLAG_NEED_WDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14739) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14740) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14742) .cmd = NL80211_CMD_GET_KEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14743) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14744) .doit = nl80211_get_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14745) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14746) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14747) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14748) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14750) .cmd = NL80211_CMD_SET_KEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14751) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14752) .doit = nl80211_set_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14753) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14754) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14755) NL80211_FLAG_NEED_RTNL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14756) NL80211_FLAG_CLEAR_SKB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14757) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14759) .cmd = NL80211_CMD_NEW_KEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14760) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14761) .doit = nl80211_new_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14762) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14763) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14764) NL80211_FLAG_NEED_RTNL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14765) NL80211_FLAG_CLEAR_SKB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14766) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14768) .cmd = NL80211_CMD_DEL_KEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14769) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14770) .doit = nl80211_del_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14771) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14772) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14773) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14774) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14776) .cmd = NL80211_CMD_SET_BEACON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14777) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14778) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14779) .doit = nl80211_set_beacon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14780) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14781) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14782) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14783) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14784) .cmd = NL80211_CMD_START_AP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14785) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14786) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14787) .doit = nl80211_start_ap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14788) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14789) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14790) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14791) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14792) .cmd = NL80211_CMD_STOP_AP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14793) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14794) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14795) .doit = nl80211_stop_ap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14796) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14797) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14798) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14800) .cmd = NL80211_CMD_GET_STATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14801) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14802) .doit = nl80211_get_station,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14803) .dumpit = nl80211_dump_station,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14804) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14805) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14806) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14808) .cmd = NL80211_CMD_SET_STATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14809) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14810) .doit = nl80211_set_station,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14811) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14812) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14813) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14814) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14816) .cmd = NL80211_CMD_NEW_STATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14817) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14818) .doit = nl80211_new_station,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14819) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14820) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14821) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14822) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14824) .cmd = NL80211_CMD_DEL_STATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14825) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14826) .doit = nl80211_del_station,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14827) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14828) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14829) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14830) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14832) .cmd = NL80211_CMD_GET_MPATH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14833) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14834) .doit = nl80211_get_mpath,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14835) .dumpit = nl80211_dump_mpath,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14836) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14837) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14838) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14839) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14840) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14841) .cmd = NL80211_CMD_GET_MPP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14842) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14843) .doit = nl80211_get_mpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14844) .dumpit = nl80211_dump_mpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14845) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14846) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14847) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14848) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14850) .cmd = NL80211_CMD_SET_MPATH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14851) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14852) .doit = nl80211_set_mpath,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14853) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14854) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14855) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14856) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14858) .cmd = NL80211_CMD_NEW_MPATH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14859) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14860) .doit = nl80211_new_mpath,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14861) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14862) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14863) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14864) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14866) .cmd = NL80211_CMD_DEL_MPATH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14867) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14868) .doit = nl80211_del_mpath,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14869) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14870) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14871) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14872) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14874) .cmd = NL80211_CMD_SET_BSS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14875) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14876) .doit = nl80211_set_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14877) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14878) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14879) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14880) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14882) .cmd = NL80211_CMD_GET_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14883) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14884) .doit = nl80211_get_reg_do,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14885) .dumpit = nl80211_get_reg_dump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14886) .internal_flags = NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14887) /* can be retrieved by unprivileged users */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14888) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14889) #ifdef CONFIG_CFG80211_CRDA_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14890) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14891) .cmd = NL80211_CMD_SET_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14892) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14893) .doit = nl80211_set_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14894) .flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14895) .internal_flags = NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14896) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14897) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14898) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14899) .cmd = NL80211_CMD_REQ_SET_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14900) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14901) .doit = nl80211_req_set_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14902) .flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14903) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14905) .cmd = NL80211_CMD_RELOAD_REGDB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14906) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14907) .doit = nl80211_reload_regdb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14908) .flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14909) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14910) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14911) .cmd = NL80211_CMD_GET_MESH_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14912) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14913) .doit = nl80211_get_mesh_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14914) /* can be retrieved by unprivileged users */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14915) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14916) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14917) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14919) .cmd = NL80211_CMD_SET_MESH_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14920) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14921) .doit = nl80211_update_mesh_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14922) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14923) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14924) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14925) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14926) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14927) .cmd = NL80211_CMD_TRIGGER_SCAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14928) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14929) .doit = nl80211_trigger_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14930) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14931) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14932) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14933) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14935) .cmd = NL80211_CMD_ABORT_SCAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14936) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14937) .doit = nl80211_abort_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14938) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14939) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14940) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14941) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14943) .cmd = NL80211_CMD_GET_SCAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14944) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14945) .dumpit = nl80211_dump_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14946) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14947) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14948) .cmd = NL80211_CMD_START_SCHED_SCAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14949) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14950) .doit = nl80211_start_sched_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14951) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14952) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14953) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14954) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14956) .cmd = NL80211_CMD_STOP_SCHED_SCAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14957) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14958) .doit = nl80211_stop_sched_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14959) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14960) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14961) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14962) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14963) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14964) .cmd = NL80211_CMD_AUTHENTICATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14965) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14966) .doit = nl80211_authenticate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14967) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14968) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14969) NL80211_FLAG_NEED_RTNL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14970) NL80211_FLAG_CLEAR_SKB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14971) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14972) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14973) .cmd = NL80211_CMD_ASSOCIATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14974) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14975) .doit = nl80211_associate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14976) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14977) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14978) NL80211_FLAG_NEED_RTNL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14979) NL80211_FLAG_CLEAR_SKB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14980) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14981) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14982) .cmd = NL80211_CMD_DEAUTHENTICATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14983) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14984) .doit = nl80211_deauthenticate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14985) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14986) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14987) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14988) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14990) .cmd = NL80211_CMD_DISASSOCIATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14991) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14992) .doit = nl80211_disassociate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14993) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14994) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14995) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14996) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14997) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14998) .cmd = NL80211_CMD_JOIN_IBSS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14999) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15000) .doit = nl80211_join_ibss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15001) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15002) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15003) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15004) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15005) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15006) .cmd = NL80211_CMD_LEAVE_IBSS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15007) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15008) .doit = nl80211_leave_ibss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15009) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15010) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15011) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15012) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15013) #ifdef CONFIG_NL80211_TESTMODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15014) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15015) .cmd = NL80211_CMD_TESTMODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15016) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15017) .doit = nl80211_testmode_do,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15018) .dumpit = nl80211_testmode_dump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15019) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15020) .internal_flags = NL80211_FLAG_NEED_WIPHY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15021) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15022) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15023) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15025) .cmd = NL80211_CMD_CONNECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15026) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15027) .doit = nl80211_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15028) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15029) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15030) NL80211_FLAG_NEED_RTNL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15031) NL80211_FLAG_CLEAR_SKB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15032) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15033) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15034) .cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15035) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15036) .doit = nl80211_update_connect_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15037) .flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15038) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15039) NL80211_FLAG_NEED_RTNL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15040) NL80211_FLAG_CLEAR_SKB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15041) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15042) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15043) .cmd = NL80211_CMD_DISCONNECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15044) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15045) .doit = nl80211_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15046) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15047) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15048) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15049) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15050) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15051) .cmd = NL80211_CMD_SET_WIPHY_NETNS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15052) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15053) .doit = nl80211_wiphy_netns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15054) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15055) .internal_flags = NL80211_FLAG_NEED_WIPHY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15056) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15057) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15059) .cmd = NL80211_CMD_GET_SURVEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15060) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15061) .dumpit = nl80211_dump_survey,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15062) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15063) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15064) .cmd = NL80211_CMD_SET_PMKSA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15065) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15066) .doit = nl80211_setdel_pmksa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15067) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15068) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15069) NL80211_FLAG_NEED_RTNL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15070) NL80211_FLAG_CLEAR_SKB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15071) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15072) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15073) .cmd = NL80211_CMD_DEL_PMKSA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15074) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15075) .doit = nl80211_setdel_pmksa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15076) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15077) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15078) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15079) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15080) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15081) .cmd = NL80211_CMD_FLUSH_PMKSA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15082) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15083) .doit = nl80211_flush_pmksa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15084) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15085) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15086) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15087) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15088) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15089) .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15090) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15091) .doit = nl80211_remain_on_channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15092) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15093) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15094) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15095) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15097) .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15098) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15099) .doit = nl80211_cancel_remain_on_channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15100) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15101) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15102) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15103) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15105) .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15106) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15107) .doit = nl80211_set_tx_bitrate_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15108) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15109) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15110) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15111) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15113) .cmd = NL80211_CMD_REGISTER_FRAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15114) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15115) .doit = nl80211_register_mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15116) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15117) .internal_flags = NL80211_FLAG_NEED_WDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15118) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15119) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15121) .cmd = NL80211_CMD_FRAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15122) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15123) .doit = nl80211_tx_mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15124) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15125) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15126) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15127) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15129) .cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15130) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15131) .doit = nl80211_tx_mgmt_cancel_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15132) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15133) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15134) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15135) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15137) .cmd = NL80211_CMD_SET_POWER_SAVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15138) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15139) .doit = nl80211_set_power_save,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15140) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15141) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15142) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15143) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15145) .cmd = NL80211_CMD_GET_POWER_SAVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15146) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15147) .doit = nl80211_get_power_save,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15148) /* can be retrieved by unprivileged users */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15149) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15150) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15151) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15153) .cmd = NL80211_CMD_SET_CQM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15154) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15155) .doit = nl80211_set_cqm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15156) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15157) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15158) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15159) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15161) .cmd = NL80211_CMD_SET_CHANNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15162) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15163) .doit = nl80211_set_channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15164) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15165) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15166) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15167) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15169) .cmd = NL80211_CMD_SET_WDS_PEER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15170) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15171) .doit = nl80211_set_wds_peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15172) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15173) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15174) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15175) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15177) .cmd = NL80211_CMD_JOIN_MESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15178) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15179) .doit = nl80211_join_mesh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15180) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15181) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15182) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15183) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15185) .cmd = NL80211_CMD_LEAVE_MESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15186) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15187) .doit = nl80211_leave_mesh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15188) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15189) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15190) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15191) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15193) .cmd = NL80211_CMD_JOIN_OCB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15194) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15195) .doit = nl80211_join_ocb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15196) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15197) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15198) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15199) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15201) .cmd = NL80211_CMD_LEAVE_OCB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15202) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15203) .doit = nl80211_leave_ocb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15204) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15205) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15206) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15207) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15208) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15210) .cmd = NL80211_CMD_GET_WOWLAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15211) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15212) .doit = nl80211_get_wowlan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15213) /* can be retrieved by unprivileged users */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15214) .internal_flags = NL80211_FLAG_NEED_WIPHY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15215) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15216) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15218) .cmd = NL80211_CMD_SET_WOWLAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15219) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15220) .doit = nl80211_set_wowlan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15221) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15222) .internal_flags = NL80211_FLAG_NEED_WIPHY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15223) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15224) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15225) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15227) .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15228) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15229) .doit = nl80211_set_rekey_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15230) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15231) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15232) NL80211_FLAG_NEED_RTNL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15233) NL80211_FLAG_CLEAR_SKB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15234) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15236) .cmd = NL80211_CMD_TDLS_MGMT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15237) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15238) .doit = nl80211_tdls_mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15239) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15240) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15241) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15242) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15244) .cmd = NL80211_CMD_TDLS_OPER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15245) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15246) .doit = nl80211_tdls_oper,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15247) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15248) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15249) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15250) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15252) .cmd = NL80211_CMD_UNEXPECTED_FRAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15253) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15254) .doit = nl80211_register_unexpected_frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15255) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15256) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15257) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15258) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15260) .cmd = NL80211_CMD_PROBE_CLIENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15261) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15262) .doit = nl80211_probe_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15263) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15264) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15265) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15266) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15268) .cmd = NL80211_CMD_REGISTER_BEACONS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15269) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15270) .doit = nl80211_register_beacons,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15271) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15272) .internal_flags = NL80211_FLAG_NEED_WIPHY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15273) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15274) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15276) .cmd = NL80211_CMD_SET_NOACK_MAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15277) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15278) .doit = nl80211_set_noack_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15279) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15280) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15281) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15282) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15284) .cmd = NL80211_CMD_START_P2P_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15285) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15286) .doit = nl80211_start_p2p_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15287) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15288) .internal_flags = NL80211_FLAG_NEED_WDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15289) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15290) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15292) .cmd = NL80211_CMD_STOP_P2P_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15293) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15294) .doit = nl80211_stop_p2p_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15295) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15296) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15297) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15298) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15300) .cmd = NL80211_CMD_START_NAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15301) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15302) .doit = nl80211_start_nan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15303) .flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15304) .internal_flags = NL80211_FLAG_NEED_WDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15305) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15306) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15308) .cmd = NL80211_CMD_STOP_NAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15309) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15310) .doit = nl80211_stop_nan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15311) .flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15312) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15313) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15314) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15316) .cmd = NL80211_CMD_ADD_NAN_FUNCTION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15317) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15318) .doit = nl80211_nan_add_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15319) .flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15320) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15321) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15322) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15324) .cmd = NL80211_CMD_DEL_NAN_FUNCTION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15325) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15326) .doit = nl80211_nan_del_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15327) .flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15328) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15329) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15330) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15332) .cmd = NL80211_CMD_CHANGE_NAN_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15333) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15334) .doit = nl80211_nan_change_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15335) .flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15336) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15337) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15338) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15340) .cmd = NL80211_CMD_SET_MCAST_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15341) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15342) .doit = nl80211_set_mcast_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15343) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15344) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15345) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15346) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15348) .cmd = NL80211_CMD_SET_MAC_ACL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15349) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15350) .doit = nl80211_set_mac_acl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15351) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15352) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15353) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15354) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15356) .cmd = NL80211_CMD_RADAR_DETECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15357) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15358) .doit = nl80211_start_radar_detection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15359) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15360) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15361) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15362) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15364) .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15365) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15366) .doit = nl80211_get_protocol_features,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15367) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15369) .cmd = NL80211_CMD_UPDATE_FT_IES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15370) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15371) .doit = nl80211_update_ft_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15372) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15373) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15374) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15375) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15377) .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15378) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15379) .doit = nl80211_crit_protocol_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15380) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15381) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15382) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15383) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15385) .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15386) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15387) .doit = nl80211_crit_protocol_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15388) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15389) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15390) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15391) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15393) .cmd = NL80211_CMD_GET_COALESCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15394) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15395) .doit = nl80211_get_coalesce,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15396) .internal_flags = NL80211_FLAG_NEED_WIPHY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15397) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15398) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15400) .cmd = NL80211_CMD_SET_COALESCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15401) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15402) .doit = nl80211_set_coalesce,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15403) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15404) .internal_flags = NL80211_FLAG_NEED_WIPHY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15405) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15406) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15408) .cmd = NL80211_CMD_CHANNEL_SWITCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15409) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15410) .doit = nl80211_channel_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15411) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15412) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15413) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15414) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15416) .cmd = NL80211_CMD_VENDOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15417) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15418) .doit = nl80211_vendor_cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15419) .dumpit = nl80211_vendor_cmd_dump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15420) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15421) .internal_flags = NL80211_FLAG_NEED_WIPHY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15422) NL80211_FLAG_NEED_RTNL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15423) NL80211_FLAG_CLEAR_SKB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15424) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15426) .cmd = NL80211_CMD_SET_QOS_MAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15427) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15428) .doit = nl80211_set_qos_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15429) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15430) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15431) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15432) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15434) .cmd = NL80211_CMD_ADD_TX_TS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15435) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15436) .doit = nl80211_add_tx_ts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15437) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15438) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15439) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15440) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15442) .cmd = NL80211_CMD_DEL_TX_TS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15443) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15444) .doit = nl80211_del_tx_ts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15445) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15446) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15447) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15448) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15450) .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15451) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15452) .doit = nl80211_tdls_channel_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15453) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15454) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15455) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15456) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15458) .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15459) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15460) .doit = nl80211_tdls_cancel_channel_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15461) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15462) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15463) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15464) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15466) .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15467) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15468) .doit = nl80211_set_multicast_to_unicast,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15469) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15470) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15471) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15472) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15474) .cmd = NL80211_CMD_SET_PMK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15475) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15476) .doit = nl80211_set_pmk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15477) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15478) NL80211_FLAG_NEED_RTNL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15479) NL80211_FLAG_CLEAR_SKB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15480) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15482) .cmd = NL80211_CMD_DEL_PMK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15483) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15484) .doit = nl80211_del_pmk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15485) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15486) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15487) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15489) .cmd = NL80211_CMD_EXTERNAL_AUTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15490) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15491) .doit = nl80211_external_auth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15492) .flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15493) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15494) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15495) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15497) .cmd = NL80211_CMD_CONTROL_PORT_FRAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15498) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15499) .doit = nl80211_tx_control_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15500) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15501) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15502) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15503) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15505) .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15506) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15507) .doit = nl80211_get_ftm_responder_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15508) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15509) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15510) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15512) .cmd = NL80211_CMD_PEER_MEASUREMENT_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15513) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15514) .doit = nl80211_pmsr_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15515) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15516) .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15517) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15518) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15520) .cmd = NL80211_CMD_NOTIFY_RADAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15521) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15522) .doit = nl80211_notify_radar_detection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15523) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15524) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15525) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15526) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15528) .cmd = NL80211_CMD_UPDATE_OWE_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15529) .doit = nl80211_update_owe_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15530) .flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15531) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15532) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15533) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15535) .cmd = NL80211_CMD_PROBE_MESH_LINK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15536) .doit = nl80211_probe_mesh_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15537) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15538) .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15539) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15540) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15542) .cmd = NL80211_CMD_SET_TID_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15543) .doit = nl80211_set_tid_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15544) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15545) .internal_flags = NL80211_FLAG_NEED_NETDEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15546) NL80211_FLAG_NEED_RTNL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15547) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15548) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15550) static struct genl_family nl80211_fam __ro_after_init = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15551) .name = NL80211_GENL_NAME, /* have users key off the name instead */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15552) .hdrsize = 0, /* no private header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15553) .version = 1, /* no particular meaning now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15554) .maxattr = NL80211_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15555) .policy = nl80211_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15556) .netnsok = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15557) .pre_doit = nl80211_pre_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15558) .post_doit = nl80211_post_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15559) .module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15560) .ops = nl80211_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15561) .n_ops = ARRAY_SIZE(nl80211_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15562) .small_ops = nl80211_small_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15563) .n_small_ops = ARRAY_SIZE(nl80211_small_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15564) .mcgrps = nl80211_mcgrps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15565) .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15566) .parallel_ops = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15567) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15569) /* notification functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15571) void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15572) enum nl80211_commands cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15574) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15575) struct nl80211_dump_wiphy_state state = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15577) WARN_ON(cmd != NL80211_CMD_NEW_WIPHY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15578) cmd != NL80211_CMD_DEL_WIPHY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15580) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15581) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15582) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15584) if (nl80211_send_wiphy(rdev, cmd, msg, 0, 0, 0, &state) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15585) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15586) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15589) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15590) NL80211_MCGRP_CONFIG, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15593) void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15594) struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15595) enum nl80211_commands cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15596) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15597) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15599) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15600) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15601) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15603) if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, cmd) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15604) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15605) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15608) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15609) NL80211_MCGRP_CONFIG, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15612) static int nl80211_add_scan_req(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15613) struct cfg80211_registered_device *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15615) struct cfg80211_scan_request *req = rdev->scan_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15616) struct nlattr *nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15617) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15618) struct cfg80211_scan_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15620) if (WARN_ON(!req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15621) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15623) nest = nla_nest_start_noflag(msg, NL80211_ATTR_SCAN_SSIDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15624) if (!nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15625) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15626) for (i = 0; i < req->n_ssids; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15627) if (nla_put(msg, i, req->ssids[i].ssid_len, req->ssids[i].ssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15628) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15630) nla_nest_end(msg, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15632) if (req->flags & NL80211_SCAN_FLAG_FREQ_KHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15633) nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQ_KHZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15634) if (!nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15635) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15636) for (i = 0; i < req->n_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15637) if (nla_put_u32(msg, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15638) ieee80211_channel_to_khz(req->channels[i])))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15639) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15641) nla_nest_end(msg, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15642) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15643) nest = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15644) NL80211_ATTR_SCAN_FREQUENCIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15645) if (!nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15646) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15647) for (i = 0; i < req->n_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15648) if (nla_put_u32(msg, i, req->channels[i]->center_freq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15649) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15651) nla_nest_end(msg, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15654) if (req->ie &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15655) nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15656) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15658) if (req->flags &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15659) nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15660) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15662) info = rdev->int_scan_req ? &rdev->int_scan_req->info :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15663) &rdev->scan_req->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15664) if (info->scan_start_tsf &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15665) (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15666) info->scan_start_tsf, NL80211_BSS_PAD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15667) nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15668) info->tsf_bssid)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15669) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15671) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15672) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15673) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15676) static int nl80211_prep_scan_msg(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15677) struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15678) struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15679) u32 portid, u32 seq, int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15680) u32 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15682) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15684) hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15685) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15686) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15688) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15689) (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15690) wdev->netdev->ifindex)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15691) nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15692) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15693) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15695) /* ignore errors and send incomplete event anyway */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15696) nl80211_add_scan_req(msg, rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15698) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15699) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15701) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15702) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15703) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15706) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15707) nl80211_prep_sched_scan_msg(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15708) struct cfg80211_sched_scan_request *req, u32 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15710) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15712) hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15713) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15714) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15716) if (nla_put_u32(msg, NL80211_ATTR_WIPHY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15717) wiphy_to_rdev(req->wiphy)->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15718) nla_put_u32(msg, NL80211_ATTR_IFINDEX, req->dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15719) nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, req->reqid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15720) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15721) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15723) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15724) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15726) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15727) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15728) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15731) void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15732) struct wireless_dev *wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15734) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15736) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15737) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15738) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15740) if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15741) NL80211_CMD_TRIGGER_SCAN) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15742) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15743) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15746) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15747) NL80211_MCGRP_SCAN, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15750) struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15751) struct wireless_dev *wdev, bool aborted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15752) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15753) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15755) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15756) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15757) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15759) if (nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15760) aborted ? NL80211_CMD_SCAN_ABORTED :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15761) NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15762) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15763) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15766) return msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15769) /* send message created by nl80211_build_scan_msg() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15770) void nl80211_send_scan_msg(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15771) struct sk_buff *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15773) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15774) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15776) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15777) NL80211_MCGRP_SCAN, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15780) void nl80211_send_sched_scan(struct cfg80211_sched_scan_request *req, u32 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15782) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15784) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15785) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15786) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15788) if (nl80211_prep_sched_scan_msg(msg, req, cmd) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15789) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15790) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15793) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(req->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15794) NL80211_MCGRP_SCAN, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15797) static bool nl80211_reg_change_event_fill(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15798) struct regulatory_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15800) /* Userspace can always count this one always being set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15801) if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15802) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15804) if (request->alpha2[0] == '0' && request->alpha2[1] == '0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15805) if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15806) NL80211_REGDOM_TYPE_WORLD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15807) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15808) } else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15809) if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15810) NL80211_REGDOM_TYPE_CUSTOM_WORLD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15811) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15812) } else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15813) request->intersect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15814) if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15815) NL80211_REGDOM_TYPE_INTERSECTION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15816) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15817) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15818) if (nla_put_u8(msg, NL80211_ATTR_REG_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15819) NL80211_REGDOM_TYPE_COUNTRY) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15820) nla_put_string(msg, NL80211_ATTR_REG_ALPHA2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15821) request->alpha2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15822) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15825) if (request->wiphy_idx != WIPHY_IDX_INVALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15826) struct wiphy *wiphy = wiphy_idx_to_wiphy(request->wiphy_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15828) if (wiphy &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15829) nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15830) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15832) if (wiphy &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15833) wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15834) nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15835) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15838) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15840) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15841) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15844) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15845) * This can happen on global regulatory changes or device specific settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15846) * based on custom regulatory domains.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15847) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15848) void nl80211_common_reg_change_event(enum nl80211_commands cmd_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15849) struct regulatory_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15851) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15852) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15854) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15855) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15856) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15858) hdr = nl80211hdr_put(msg, 0, 0, 0, cmd_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15859) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15860) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15862) if (!nl80211_reg_change_event_fill(msg, request))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15863) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15865) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15867) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15868) genlmsg_multicast_allns(&nl80211_fam, msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15869) NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15870) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15872) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15874) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15875) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15878) static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15879) struct net_device *netdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15880) const u8 *buf, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15881) enum nl80211_commands cmd, gfp_t gfp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15882) int uapsd_queues, const u8 *req_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15883) size_t req_ies_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15885) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15886) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15888) msg = nlmsg_new(100 + len + req_ies_len, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15889) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15890) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15892) hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15893) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15894) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15895) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15898) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15899) nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15900) nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15901) (req_ies &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15902) nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15903) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15905) if (uapsd_queues >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15906) struct nlattr *nla_wmm =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15907) nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15908) if (!nla_wmm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15909) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15911) if (nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15912) uapsd_queues))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15913) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15915) nla_nest_end(msg, nla_wmm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15918) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15920) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15921) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15922) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15924) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15925) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15928) void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15929) struct net_device *netdev, const u8 *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15930) size_t len, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15931) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15932) nl80211_send_mlme_event(rdev, netdev, buf, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15933) NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15936) void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15937) struct net_device *netdev, const u8 *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15938) size_t len, gfp_t gfp, int uapsd_queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15939) const u8 *req_ies, size_t req_ies_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15941) nl80211_send_mlme_event(rdev, netdev, buf, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15942) NL80211_CMD_ASSOCIATE, gfp, uapsd_queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15943) req_ies, req_ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15946) void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15947) struct net_device *netdev, const u8 *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15948) size_t len, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15950) nl80211_send_mlme_event(rdev, netdev, buf, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15951) NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15954) void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15955) struct net_device *netdev, const u8 *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15956) size_t len, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15958) nl80211_send_mlme_event(rdev, netdev, buf, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15959) NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15962) void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15963) size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15964) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15965) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15966) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15967) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15968) const struct ieee80211_mgmt *mgmt = (void *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15969) u32 cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15971) if (WARN_ON(len < 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15972) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15974) if (ieee80211_is_deauth(mgmt->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15975) cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15976) } else if (ieee80211_is_disassoc(mgmt->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15977) cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15978) } else if (ieee80211_is_beacon(mgmt->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15979) if (wdev->unprot_beacon_reported &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15980) elapsed_jiffies_msecs(wdev->unprot_beacon_reported) < 10000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15981) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15982) cmd = NL80211_CMD_UNPROT_BEACON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15983) wdev->unprot_beacon_reported = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15984) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15985) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15988) trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15989) nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15990) NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15992) EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15994) static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15995) struct net_device *netdev, int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15996) const u8 *addr, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15997) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15998) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15999) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16001) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16002) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16003) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16005) hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16006) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16007) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16008) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16011) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16012) nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16013) nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16014) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16015) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16017) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16019) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16020) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16021) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16023) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16024) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16027) void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16028) struct net_device *netdev, const u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16029) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16030) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16031) nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16032) addr, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16035) void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16036) struct net_device *netdev, const u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16037) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16038) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16039) nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16040) addr, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16043) void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16044) struct net_device *netdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16045) struct cfg80211_connect_resp_params *cr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16046) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16048) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16049) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16051) msg = nlmsg_new(100 + cr->req_ie_len + cr->resp_ie_len +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16052) cr->fils.kek_len + cr->fils.pmk_len +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16053) (cr->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16054) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16055) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16057) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONNECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16058) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16059) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16060) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16063) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16064) nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16065) (cr->bssid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16066) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, cr->bssid)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16067) nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16068) cr->status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16069) cr->status) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16070) (cr->status < 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16071) (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16072) nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16073) cr->timeout_reason))) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16074) (cr->req_ie &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16075) nla_put(msg, NL80211_ATTR_REQ_IE, cr->req_ie_len, cr->req_ie)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16076) (cr->resp_ie &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16077) nla_put(msg, NL80211_ATTR_RESP_IE, cr->resp_ie_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16078) cr->resp_ie)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16079) (cr->fils.update_erp_next_seq_num &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16080) nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16081) cr->fils.erp_next_seq_num)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16082) (cr->status == WLAN_STATUS_SUCCESS &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16083) ((cr->fils.kek &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16084) nla_put(msg, NL80211_ATTR_FILS_KEK, cr->fils.kek_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16085) cr->fils.kek)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16086) (cr->fils.pmk &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16087) nla_put(msg, NL80211_ATTR_PMK, cr->fils.pmk_len, cr->fils.pmk)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16088) (cr->fils.pmkid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16089) nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, cr->fils.pmkid)))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16090) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16092) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16094) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16095) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16096) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16098) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16099) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16102) void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16103) struct net_device *netdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16104) struct cfg80211_roam_info *info, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16106) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16107) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16108) const u8 *bssid = info->bss ? info->bss->bssid : info->bssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16110) msg = nlmsg_new(100 + info->req_ie_len + info->resp_ie_len +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16111) info->fils.kek_len + info->fils.pmk_len +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16112) (info->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16113) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16114) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16116) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ROAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16117) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16118) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16119) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16122) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16123) nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16124) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16125) (info->req_ie &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16126) nla_put(msg, NL80211_ATTR_REQ_IE, info->req_ie_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16127) info->req_ie)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16128) (info->resp_ie &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16129) nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16130) info->resp_ie)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16131) (info->fils.update_erp_next_seq_num &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16132) nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16133) info->fils.erp_next_seq_num)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16134) (info->fils.kek &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16135) nla_put(msg, NL80211_ATTR_FILS_KEK, info->fils.kek_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16136) info->fils.kek)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16137) (info->fils.pmk &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16138) nla_put(msg, NL80211_ATTR_PMK, info->fils.pmk_len, info->fils.pmk)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16139) (info->fils.pmkid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16140) nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, info->fils.pmkid)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16141) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16143) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16145) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16146) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16147) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16149) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16150) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16153) void nl80211_send_port_authorized(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16154) struct net_device *netdev, const u8 *bssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16156) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16157) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16159) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16160) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16161) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16163) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PORT_AUTHORIZED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16164) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16165) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16166) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16169) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16170) nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16171) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16172) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16174) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16176) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16177) NL80211_MCGRP_MLME, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16178) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16180) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16181) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16184) void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16185) struct net_device *netdev, u16 reason,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16186) const u8 *ie, size_t ie_len, bool from_ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16188) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16189) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16191) msg = nlmsg_new(100 + ie_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16192) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16193) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16195) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DISCONNECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16196) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16197) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16198) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16201) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16202) nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16203) (reason &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16204) nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16205) (from_ap &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16206) nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16207) (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16208) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16210) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16212) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16213) NL80211_MCGRP_MLME, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16214) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16216) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16217) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16220) void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16221) struct net_device *netdev, const u8 *bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16222) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16224) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16225) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16227) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16228) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16229) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16231) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16232) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16233) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16234) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16237) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16238) nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16239) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16240) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16242) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16244) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16245) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16246) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16248) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16249) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16252) void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16253) const u8 *ie, u8 ie_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16254) int sig_dbm, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16256) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16257) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16258) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16259) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16261) if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16262) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16264) trace_cfg80211_notify_new_peer_candidate(dev, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16266) msg = nlmsg_new(100 + ie_len, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16267) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16268) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16270) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16271) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16272) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16273) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16276) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16277) nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16278) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16279) (ie_len && ie &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16280) nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16281) (sig_dbm &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16282) nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16283) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16285) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16287) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16288) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16289) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16291) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16292) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16294) EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16296) void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16297) struct net_device *netdev, const u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16298) enum nl80211_key_type key_type, int key_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16299) const u8 *tsc, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16301) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16302) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16304) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16305) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16306) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16308) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16309) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16310) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16311) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16314) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16315) nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16316) (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16317) nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, key_type) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16318) (key_id != -1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16319) nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_id)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16320) (tsc && nla_put(msg, NL80211_ATTR_KEY_SEQ, 6, tsc)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16321) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16323) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16325) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16326) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16327) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16329) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16330) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16333) void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16334) struct ieee80211_channel *channel_before,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16335) struct ieee80211_channel *channel_after)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16337) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16338) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16339) struct nlattr *nl_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16341) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16342) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16343) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16345) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16346) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16347) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16348) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16351) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16352) * Since we are applying the beacon hint to a wiphy we know its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16353) * wiphy_idx is valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16354) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16355) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16356) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16358) /* Before */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16359) nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_BEFORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16360) if (!nl_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16361) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16363) if (nl80211_msg_put_channel(msg, wiphy, channel_before, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16364) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16365) nla_nest_end(msg, nl_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16367) /* After */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16368) nl_freq = nla_nest_start_noflag(msg, NL80211_ATTR_FREQ_AFTER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16369) if (!nl_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16370) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16372) if (nl80211_msg_put_channel(msg, wiphy, channel_after, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16373) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16374) nla_nest_end(msg, nl_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16376) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16378) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16379) genlmsg_multicast_allns(&nl80211_fam, msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16380) NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16381) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16383) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16385) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16386) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16389) static void nl80211_send_remain_on_chan_event(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16390) int cmd, struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16391) struct wireless_dev *wdev, u64 cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16392) struct ieee80211_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16393) unsigned int duration, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16395) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16396) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16398) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16399) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16400) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16402) hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16403) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16404) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16405) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16408) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16409) (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16410) wdev->netdev->ifindex)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16411) nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16412) NL80211_ATTR_PAD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16413) nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16414) nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16415) NL80211_CHAN_NO_HT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16416) nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16417) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16418) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16420) if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16421) nla_put_u32(msg, NL80211_ATTR_DURATION, duration))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16422) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16424) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16426) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16427) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16428) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16430) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16431) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16434) void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16435) struct ieee80211_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16436) unsigned int duration, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16438) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16439) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16441) trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16442) nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16443) rdev, wdev, cookie, chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16444) duration, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16446) EXPORT_SYMBOL(cfg80211_ready_on_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16448) void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16449) struct ieee80211_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16450) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16452) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16453) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16455) trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16456) nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16457) rdev, wdev, cookie, chan, 0, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16459) EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16461) void cfg80211_tx_mgmt_expired(struct wireless_dev *wdev, u64 cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16462) struct ieee80211_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16463) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16465) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16466) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16468) trace_cfg80211_tx_mgmt_expired(wdev, cookie, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16469) nl80211_send_remain_on_chan_event(NL80211_CMD_FRAME_WAIT_CANCEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16470) rdev, wdev, cookie, chan, 0, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16472) EXPORT_SYMBOL(cfg80211_tx_mgmt_expired);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16474) void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16475) struct station_info *sinfo, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16477) struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16478) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16479) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16481) trace_cfg80211_new_sta(dev, mac_addr, sinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16483) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16484) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16485) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16487) if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16488) rdev, dev, mac_addr, sinfo) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16489) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16490) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16493) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16494) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16496) EXPORT_SYMBOL(cfg80211_new_sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16498) void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16499) struct station_info *sinfo, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16501) struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16502) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16503) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16504) struct station_info empty_sinfo = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16506) if (!sinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16507) sinfo = &empty_sinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16509) trace_cfg80211_del_sta(dev, mac_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16511) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16512) if (!msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16513) cfg80211_sinfo_release_content(sinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16514) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16517) if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16518) rdev, dev, mac_addr, sinfo) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16519) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16520) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16523) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16524) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16526) EXPORT_SYMBOL(cfg80211_del_sta_sinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16528) void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16529) enum nl80211_connect_failed_reason reason,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16530) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16532) struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16533) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16534) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16535) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16537) msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16538) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16539) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16541) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONN_FAILED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16542) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16543) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16544) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16547) if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16548) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16549) nla_put_u32(msg, NL80211_ATTR_CONN_FAILED_REASON, reason))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16550) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16552) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16554) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16555) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16556) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16558) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16559) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16561) EXPORT_SYMBOL(cfg80211_conn_failed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16563) static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16564) const u8 *addr, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16566) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16567) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16568) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16569) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16570) u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16572) if (!nlportid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16573) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16575) msg = nlmsg_new(100, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16576) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16577) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16579) hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16580) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16581) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16582) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16585) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16586) nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16587) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16588) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16590) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16591) genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16592) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16594) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16595) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16596) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16599) bool cfg80211_rx_spurious_frame(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16600) const u8 *addr, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16602) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16603) bool ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16605) trace_cfg80211_rx_spurious_frame(dev, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16607) if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16608) wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16609) trace_cfg80211_return_bool(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16610) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16612) ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16613) addr, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16614) trace_cfg80211_return_bool(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16615) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16617) EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16619) bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16620) const u8 *addr, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16621) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16622) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16623) bool ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16625) trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16627) if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16628) wdev->iftype != NL80211_IFTYPE_P2P_GO &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16629) wdev->iftype != NL80211_IFTYPE_AP_VLAN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16630) trace_cfg80211_return_bool(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16631) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16633) ret = __nl80211_unexpected_frame(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16634) NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16635) addr, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16636) trace_cfg80211_return_bool(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16637) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16639) EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16641) int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16642) struct wireless_dev *wdev, u32 nlportid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16643) int freq, int sig_dbm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16644) const u8 *buf, size_t len, u32 flags, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16646) struct net_device *netdev = wdev->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16647) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16648) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16650) msg = nlmsg_new(100 + len, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16651) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16652) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16654) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16655) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16656) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16657) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16660) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16661) (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16662) netdev->ifindex)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16663) nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16664) NL80211_ATTR_PAD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16665) nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, KHZ_TO_MHZ(freq)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16666) nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET, freq % 1000) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16667) (sig_dbm &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16668) nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16669) nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16670) (flags &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16671) nla_put_u32(msg, NL80211_ATTR_RXMGMT_FLAGS, flags)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16672) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16674) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16676) return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16678) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16679) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16680) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16683) static void nl80211_frame_tx_status(struct wireless_dev *wdev, u64 cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16684) const u8 *buf, size_t len, bool ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16685) gfp_t gfp, enum nl80211_commands command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16687) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16688) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16689) struct net_device *netdev = wdev->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16690) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16691) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16693) if (command == NL80211_CMD_FRAME_TX_STATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16694) trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16695) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16696) trace_cfg80211_control_port_tx_status(wdev, cookie, ack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16698) msg = nlmsg_new(100 + len, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16699) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16700) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16702) hdr = nl80211hdr_put(msg, 0, 0, 0, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16703) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16704) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16705) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16708) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16709) (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16710) netdev->ifindex)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16711) nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16712) NL80211_ATTR_PAD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16713) nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16714) nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16715) NL80211_ATTR_PAD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16716) (ack && nla_put_flag(msg, NL80211_ATTR_ACK)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16717) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16719) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16721) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16722) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16723) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16725) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16726) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16729) void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16730) const u8 *buf, size_t len, bool ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16731) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16733) nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16734) NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16736) EXPORT_SYMBOL(cfg80211_control_port_tx_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16738) void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16739) const u8 *buf, size_t len, bool ack, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16741) nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16742) NL80211_CMD_FRAME_TX_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16744) EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16746) static int __nl80211_rx_control_port(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16747) struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16748) bool unencrypted, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16750) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16751) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16752) struct ethhdr *ehdr = eth_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16753) const u8 *addr = ehdr->h_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16754) u16 proto = be16_to_cpu(skb->protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16755) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16756) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16757) struct nlattr *frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16759) u32 nlportid = READ_ONCE(wdev->conn_owner_nlportid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16761) if (!nlportid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16762) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16764) msg = nlmsg_new(100 + skb->len, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16765) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16766) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16768) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONTROL_PORT_FRAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16769) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16770) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16771) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16774) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16775) nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16776) nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16777) NL80211_ATTR_PAD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16778) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16779) nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16780) (unencrypted && nla_put_flag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16781) NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16782) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16784) frame = nla_reserve(msg, NL80211_ATTR_FRAME, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16785) if (!frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16786) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16788) skb_copy_bits(skb, 0, nla_data(frame), skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16789) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16791) return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16793) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16794) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16795) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16798) bool cfg80211_rx_control_port(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16799) struct sk_buff *skb, bool unencrypted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16801) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16803) trace_cfg80211_rx_control_port(dev, skb, unencrypted);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16804) ret = __nl80211_rx_control_port(dev, skb, unencrypted, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16805) trace_cfg80211_return_bool(ret == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16806) return ret == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16808) EXPORT_SYMBOL(cfg80211_rx_control_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16810) static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16811) const char *mac, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16813) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16814) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16815) struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16816) void **cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16818) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16819) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16821) cb = (void **)msg->cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16823) cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16824) if (!cb[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16825) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16826) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16829) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16830) nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16831) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16833) if (mac && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16834) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16836) cb[1] = nla_nest_start_noflag(msg, NL80211_ATTR_CQM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16837) if (!cb[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16838) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16840) cb[2] = rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16842) return msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16843) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16844) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16845) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16848) static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16850) void **cb = (void **)msg->cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16851) struct cfg80211_registered_device *rdev = cb[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16853) nla_nest_end(msg, cb[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16854) genlmsg_end(msg, cb[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16856) memset(msg->cb, 0, sizeof(msg->cb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16858) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16859) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16862) void cfg80211_cqm_rssi_notify(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16863) enum nl80211_cqm_rssi_threshold_event rssi_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16864) s32 rssi_level, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16866) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16867) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16868) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16870) trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16872) if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16873) rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16874) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16876) if (wdev->cqm_config) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16877) wdev->cqm_config->last_rssi_event_value = rssi_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16879) cfg80211_cqm_rssi_update(rdev, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16881) if (rssi_level == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16882) rssi_level = wdev->cqm_config->last_rssi_event_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16885) msg = cfg80211_prepare_cqm(dev, NULL, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16886) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16887) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16889) if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16890) rssi_event))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16891) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16893) if (rssi_level && nla_put_s32(msg, NL80211_ATTR_CQM_RSSI_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16894) rssi_level))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16895) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16897) cfg80211_send_cqm(msg, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16899) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16901) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16902) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16904) EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16906) void cfg80211_cqm_txe_notify(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16907) const u8 *peer, u32 num_packets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16908) u32 rate, u32 intvl, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16910) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16912) msg = cfg80211_prepare_cqm(dev, peer, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16913) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16914) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16916) if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16917) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16919) if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16920) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16922) if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16923) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16925) cfg80211_send_cqm(msg, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16926) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16928) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16929) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16931) EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16933) void cfg80211_cqm_pktloss_notify(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16934) const u8 *peer, u32 num_packets, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16936) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16938) trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16940) msg = cfg80211_prepare_cqm(dev, peer, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16941) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16942) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16944) if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16945) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16947) cfg80211_send_cqm(msg, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16948) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16950) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16951) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16953) EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16955) void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16956) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16957) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16959) msg = cfg80211_prepare_cqm(dev, NULL, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16960) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16961) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16963) if (nla_put_flag(msg, NL80211_ATTR_CQM_BEACON_LOSS_EVENT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16964) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16966) cfg80211_send_cqm(msg, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16967) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16969) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16970) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16972) EXPORT_SYMBOL(cfg80211_cqm_beacon_loss_notify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16974) static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16975) struct net_device *netdev, const u8 *bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16976) const u8 *replay_ctr, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16977) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16978) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16979) struct nlattr *rekey_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16980) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16982) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16983) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16984) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16986) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16987) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16988) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16989) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16992) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16993) nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16994) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16995) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16997) rekey_attr = nla_nest_start_noflag(msg, NL80211_ATTR_REKEY_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16998) if (!rekey_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16999) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17001) if (nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17002) NL80211_REPLAY_CTR_LEN, replay_ctr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17003) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17005) nla_nest_end(msg, rekey_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17007) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17009) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17010) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17011) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17013) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17014) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17017) void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17018) const u8 *replay_ctr, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17019) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17020) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17021) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17022) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17024) trace_cfg80211_gtk_rekey_notify(dev, bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17025) nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17027) EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17029) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17030) nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17031) struct net_device *netdev, int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17032) const u8 *bssid, bool preauth, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17033) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17034) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17035) struct nlattr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17036) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17038) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17039) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17040) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17042) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PMKSA_CANDIDATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17043) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17044) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17045) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17048) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17049) nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17050) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17052) attr = nla_nest_start_noflag(msg, NL80211_ATTR_PMKSA_CANDIDATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17053) if (!attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17054) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17056) if (nla_put_u32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17057) nla_put(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17058) (preauth &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17059) nla_put_flag(msg, NL80211_PMKSA_CANDIDATE_PREAUTH)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17060) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17062) nla_nest_end(msg, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17064) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17066) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17067) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17068) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17070) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17071) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17074) void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17075) const u8 *bssid, bool preauth, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17077) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17078) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17079) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17081) trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17082) nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17084) EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17086) static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17087) struct net_device *netdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17088) struct cfg80211_chan_def *chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17089) gfp_t gfp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17090) enum nl80211_commands notif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17091) u8 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17092) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17093) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17094) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17096) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17097) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17098) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17100) hdr = nl80211hdr_put(msg, 0, 0, 0, notif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17101) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17102) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17103) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17106) if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17107) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17109) if (nl80211_send_chandef(msg, chandef))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17110) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17112) if ((notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17113) (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17114) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17116) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17118) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17119) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17120) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17122) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17123) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17126) void cfg80211_ch_switch_notify(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17127) struct cfg80211_chan_def *chandef)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17129) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17130) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17131) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17133) ASSERT_WDEV_LOCK(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17135) trace_cfg80211_ch_switch_notify(dev, chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17137) wdev->chandef = *chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17138) wdev->preset_chandef = *chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17140) if ((wdev->iftype == NL80211_IFTYPE_STATION ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17141) wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17142) !WARN_ON(!wdev->current_bss))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17143) cfg80211_update_assoc_bss_entry(wdev, chandef->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17145) cfg80211_sched_dfs_chan_update(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17147) nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17148) NL80211_CMD_CH_SWITCH_NOTIFY, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17150) EXPORT_SYMBOL(cfg80211_ch_switch_notify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17152) void cfg80211_ch_switch_started_notify(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17153) struct cfg80211_chan_def *chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17154) u8 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17156) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17157) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17158) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17160) trace_cfg80211_ch_switch_started_notify(dev, chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17162) nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17163) NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17165) EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17167) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17168) nl80211_radar_notify(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17169) const struct cfg80211_chan_def *chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17170) enum nl80211_radar_event event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17171) struct net_device *netdev, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17173) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17174) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17176) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17177) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17178) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17180) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RADAR_DETECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17181) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17182) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17183) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17186) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17187) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17189) /* NOP and radar events don't need a netdev parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17190) if (netdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17191) struct wireless_dev *wdev = netdev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17193) if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17194) nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17195) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17196) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17199) if (nla_put_u32(msg, NL80211_ATTR_RADAR_EVENT, event))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17200) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17202) if (nl80211_send_chandef(msg, chandef))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17203) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17205) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17207) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17208) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17209) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17211) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17212) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17215) void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17216) struct sta_opmode_info *sta_opmode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17217) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17219) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17220) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17221) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17222) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17224) if (WARN_ON(!mac))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17225) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17227) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17228) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17229) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17231) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STA_OPMODE_CHANGED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17232) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17233) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17234) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17237) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17238) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17240) if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17241) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17243) if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17244) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17246) if ((sta_opmode->changed & STA_OPMODE_SMPS_MODE_CHANGED) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17247) nla_put_u8(msg, NL80211_ATTR_SMPS_MODE, sta_opmode->smps_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17248) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17250) if ((sta_opmode->changed & STA_OPMODE_MAX_BW_CHANGED) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17251) nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, sta_opmode->bw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17252) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17254) if ((sta_opmode->changed & STA_OPMODE_N_SS_CHANGED) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17255) nla_put_u8(msg, NL80211_ATTR_NSS, sta_opmode->rx_nss))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17256) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17258) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17260) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17261) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17263) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17265) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17266) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17268) EXPORT_SYMBOL(cfg80211_sta_opmode_change_notify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17270) void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17271) u64 cookie, bool acked, s32 ack_signal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17272) bool is_valid_ack_signal, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17274) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17275) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17276) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17277) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17279) trace_cfg80211_probe_status(dev, addr, cookie, acked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17281) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17283) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17284) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17286) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_CLIENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17287) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17288) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17289) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17292) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17293) nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17294) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17295) nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17296) NL80211_ATTR_PAD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17297) (acked && nla_put_flag(msg, NL80211_ATTR_ACK)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17298) (is_valid_ack_signal && nla_put_s32(msg, NL80211_ATTR_ACK_SIGNAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17299) ack_signal)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17300) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17302) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17304) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17305) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17306) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17308) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17309) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17311) EXPORT_SYMBOL(cfg80211_probe_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17313) void cfg80211_report_obss_beacon_khz(struct wiphy *wiphy, const u8 *frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17314) size_t len, int freq, int sig_dbm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17316) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17317) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17318) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17319) struct cfg80211_beacon_registration *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17321) trace_cfg80211_report_obss_beacon(wiphy, frame, len, freq, sig_dbm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17323) spin_lock_bh(&rdev->beacon_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17324) list_for_each_entry(reg, &rdev->beacon_registrations, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17325) msg = nlmsg_new(len + 100, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17326) if (!msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17327) spin_unlock_bh(&rdev->beacon_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17328) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17331) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17332) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17333) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17335) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17336) (freq &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17337) (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17338) KHZ_TO_MHZ(freq)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17339) nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17340) freq % 1000))) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17341) (sig_dbm &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17342) nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17343) nla_put(msg, NL80211_ATTR_FRAME, len, frame))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17344) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17346) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17348) genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17350) spin_unlock_bh(&rdev->beacon_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17351) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17353) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17354) spin_unlock_bh(&rdev->beacon_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17355) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17357) EXPORT_SYMBOL(cfg80211_report_obss_beacon_khz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17359) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17360) static int cfg80211_net_detect_results(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17361) struct cfg80211_wowlan_wakeup *wakeup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17363) struct cfg80211_wowlan_nd_info *nd = wakeup->net_detect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17364) struct nlattr *nl_results, *nl_match, *nl_freqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17365) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17367) nl_results = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17368) NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17369) if (!nl_results)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17370) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17372) for (i = 0; i < nd->n_matches; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17373) struct cfg80211_wowlan_nd_match *match = nd->matches[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17375) nl_match = nla_nest_start_noflag(msg, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17376) if (!nl_match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17377) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17379) /* The SSID attribute is optional in nl80211, but for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17380) * simplicity reasons it's always present in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17381) * cfg80211 structure. If a driver can't pass the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17382) * SSID, that needs to be changed. A zero length SSID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17383) * is still a valid SSID (wildcard), so it cannot be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17384) * used for this purpose.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17386) if (nla_put(msg, NL80211_ATTR_SSID, match->ssid.ssid_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17387) match->ssid.ssid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17388) nla_nest_cancel(msg, nl_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17389) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17392) if (match->n_channels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17393) nl_freqs = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17394) NL80211_ATTR_SCAN_FREQUENCIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17395) if (!nl_freqs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17396) nla_nest_cancel(msg, nl_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17397) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17400) for (j = 0; j < match->n_channels; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17401) if (nla_put_u32(msg, j, match->channels[j])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17402) nla_nest_cancel(msg, nl_freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17403) nla_nest_cancel(msg, nl_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17404) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17408) nla_nest_end(msg, nl_freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17411) nla_nest_end(msg, nl_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17414) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17415) nla_nest_end(msg, nl_results);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17416) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17419) void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17420) struct cfg80211_wowlan_wakeup *wakeup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17421) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17423) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17424) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17425) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17426) int size = 200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17428) trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17430) if (wakeup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17431) size += wakeup->packet_present_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17433) msg = nlmsg_new(size, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17434) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17435) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17437) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_WOWLAN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17438) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17439) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17441) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17442) nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17443) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17444) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17446) if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17447) wdev->netdev->ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17448) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17450) if (wakeup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17451) struct nlattr *reasons;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17453) reasons = nla_nest_start_noflag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17454) NL80211_ATTR_WOWLAN_TRIGGERS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17455) if (!reasons)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17456) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17458) if (wakeup->disconnect &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17459) nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17460) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17461) if (wakeup->magic_pkt &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17462) nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17463) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17464) if (wakeup->gtk_rekey_failure &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17465) nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17466) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17467) if (wakeup->eap_identity_req &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17468) nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17469) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17470) if (wakeup->four_way_handshake &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17471) nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17472) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17473) if (wakeup->rfkill_release &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17474) nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17475) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17477) if (wakeup->pattern_idx >= 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17478) nla_put_u32(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17479) wakeup->pattern_idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17480) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17482) if (wakeup->tcp_match &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17483) nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17484) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17486) if (wakeup->tcp_connlost &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17487) nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17488) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17490) if (wakeup->tcp_nomoretokens &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17491) nla_put_flag(msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17492) NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17493) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17495) if (wakeup->packet) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17496) u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17497) u32 len_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17499) if (!wakeup->packet_80211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17500) pkt_attr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17501) NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17502) len_attr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17503) NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17506) if (wakeup->packet_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17507) nla_put_u32(msg, len_attr, wakeup->packet_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17508) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17510) if (nla_put(msg, pkt_attr, wakeup->packet_present_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17511) wakeup->packet))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17512) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17515) if (wakeup->net_detect &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17516) cfg80211_net_detect_results(msg, wakeup))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17517) goto free_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17519) nla_nest_end(msg, reasons);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17522) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17524) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17525) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17526) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17528) free_msg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17529) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17531) EXPORT_SYMBOL(cfg80211_report_wowlan_wakeup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17532) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17534) void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17535) enum nl80211_tdls_operation oper,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17536) u16 reason_code, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17538) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17539) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17540) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17541) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17543) trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17544) reason_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17546) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17547) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17548) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17550) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17551) if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17552) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17553) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17556) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17557) nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17558) nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17559) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17560) (reason_code > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17561) nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17562) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17564) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17566) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17567) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17568) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17570) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17571) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17573) EXPORT_SYMBOL(cfg80211_tdls_oper_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17575) static int nl80211_netlink_notify(struct notifier_block * nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17576) unsigned long state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17577) void *_notify)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17579) struct netlink_notify *notify = _notify;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17580) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17581) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17582) struct cfg80211_beacon_registration *reg, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17584) if (state != NETLINK_URELEASE || notify->protocol != NETLINK_GENERIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17585) return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17587) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17589) list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17590) struct cfg80211_sched_scan_request *sched_scan_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17592) list_for_each_entry_rcu(sched_scan_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17593) &rdev->sched_scan_req_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17594) list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17595) if (sched_scan_req->owner_nlportid == notify->portid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17596) sched_scan_req->nl_owner_dead = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17597) schedule_work(&rdev->sched_scan_stop_wk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17601) list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17602) cfg80211_mlme_unregister_socket(wdev, notify->portid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17604) if (wdev->owner_nlportid == notify->portid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17605) wdev->nl_owner_dead = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17606) schedule_work(&rdev->destroy_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17607) } else if (wdev->conn_owner_nlportid == notify->portid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17608) schedule_work(&wdev->disconnect_wk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17611) cfg80211_release_pmsr(wdev, notify->portid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17614) spin_lock_bh(&rdev->beacon_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17615) list_for_each_entry_safe(reg, tmp, &rdev->beacon_registrations,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17616) list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17617) if (reg->nlportid == notify->portid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17618) list_del(®->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17619) kfree(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17620) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17623) spin_unlock_bh(&rdev->beacon_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17626) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17628) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17629) * It is possible that the user space process that is controlling the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17630) * indoor setting disappeared, so notify the regulatory core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17631) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17632) regulatory_netlink_notify(notify->portid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17633) return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17636) static struct notifier_block nl80211_netlink_notifier = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17637) .notifier_call = nl80211_netlink_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17638) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17640) void cfg80211_ft_event(struct net_device *netdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17641) struct cfg80211_ft_event_params *ft_event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17643) struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17644) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17645) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17646) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17648) trace_cfg80211_ft_event(wiphy, netdev, ft_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17650) if (!ft_event->target_ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17651) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17653) msg = nlmsg_new(100 + ft_event->ies_len + ft_event->ric_ies_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17654) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17655) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17656) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17658) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17659) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17660) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17662) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17663) nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17664) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17665) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17667) if (ft_event->ies &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17668) nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17669) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17670) if (ft_event->ric_ies &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17671) nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17672) ft_event->ric_ies))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17673) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17675) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17677) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17678) NL80211_MCGRP_MLME, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17679) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17680) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17681) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17683) EXPORT_SYMBOL(cfg80211_ft_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17685) void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17687) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17688) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17689) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17690) u32 nlportid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17692) rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17693) if (!rdev->crit_proto_nlportid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17694) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17696) nlportid = rdev->crit_proto_nlportid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17697) rdev->crit_proto_nlportid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17699) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17700) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17701) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17703) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17704) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17705) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17707) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17708) nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17709) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17710) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17712) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17714) genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17715) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17717) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17718) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17720) EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17722) void nl80211_send_ap_stopped(struct wireless_dev *wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17724) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17725) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17726) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17727) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17729) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17730) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17731) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17733) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17734) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17735) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17737) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17738) nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17739) nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17740) NL80211_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17741) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17743) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17745) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17746) NL80211_MCGRP_MLME, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17747) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17748) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17749) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17752) int cfg80211_external_auth_request(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17753) struct cfg80211_external_auth_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17754) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17756) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17757) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17758) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17759) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17761) if (!wdev->conn_owner_nlportid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17762) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17764) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17765) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17766) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17768) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17769) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17770) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17772) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17773) nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17774) nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17775) nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17776) params->action) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17777) nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17778) nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17779) params->ssid.ssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17780) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17782) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17783) genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17784) wdev->conn_owner_nlportid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17785) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17787) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17788) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17789) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17791) EXPORT_SYMBOL(cfg80211_external_auth_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17793) void cfg80211_update_owe_info_event(struct net_device *netdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17794) struct cfg80211_update_owe_info *owe_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17795) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17797) struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17798) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17799) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17800) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17802) trace_cfg80211_update_owe_info_event(wiphy, netdev, owe_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17804) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17805) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17806) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17808) hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UPDATE_OWE_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17809) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17810) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17812) if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17813) nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17814) nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, owe_info->peer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17815) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17817) if (!owe_info->ie_len ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17818) nla_put(msg, NL80211_ATTR_IE, owe_info->ie_len, owe_info->ie))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17819) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17821) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17823) genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17824) NL80211_MCGRP_MLME, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17825) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17827) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17828) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17829) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17831) EXPORT_SYMBOL(cfg80211_update_owe_info_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17833) /* initialisation/exit functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17835) int __init nl80211_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17837) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17839) err = genl_register_family(&nl80211_fam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17840) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17841) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17843) err = netlink_register_notifier(&nl80211_netlink_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17844) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17845) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17847) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17848) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17849) genl_unregister_family(&nl80211_fam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17850) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17853) void nl80211_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17854) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17855) netlink_unregister_notifier(&nl80211_netlink_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17856) genl_unregister_family(&nl80211_fam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17857) }