^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * cfg80211 scan result handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2008 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 2016 Intel Deutschland GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2018-2020 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/slab.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/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/wireless.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/nl80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/crc32.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/bitfield.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <net/arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <net/cfg80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <net/cfg80211-wext.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <net/iw_handler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "nl80211.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "wext-compat.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "rdev-ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * DOC: BSS tree/list structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * At the top level, the BSS list is kept in both a list in each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * registered device (@bss_list) as well as an RB-tree for faster
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * lookup. In the RB-tree, entries can be looked up using their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * channel, MESHID, MESHCONF (for MBSSes) or channel, BSSID, SSID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * for other BSSes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Due to the possibility of hidden SSIDs, there's a second level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * structure, the "hidden_list" and "hidden_beacon_bss" pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * The hidden_list connects all BSSes belonging to a single AP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * that has a hidden SSID, and connects beacon and probe response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * entries. For a probe response entry for a hidden SSID, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * hidden_beacon_bss pointer points to the BSS struct holding the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * beacon's information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * Reference counting is done for all these references except for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * the hidden_list, so that a beacon BSS struct that is otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * not referenced has one reference for being on the bss_list and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * one for each probe response entry that points to it using the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * hidden_beacon_bss pointer. When a BSS struct that has such a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * pointer is get/put, the refcount update is also propagated to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * the referenced struct, this ensure that it cannot get removed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * while somebody is using the probe response version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * Note that the hidden_beacon_bss pointer never changes, due to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * the reference counting. Therefore, no locking is needed for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * Also note that the hidden_beacon_bss pointer is only relevant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * if the driver uses something other than the IEs, e.g. private
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * data stored in the BSS struct, since the beacon IEs are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * also linked into the probe response struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) */
^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) * Limit the number of BSS entries stored in mac80211. Each one is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * a bit over 4k at most, so this limits to roughly 4-5M of memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * If somebody wants to really attack this though, they'd likely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * use small beacons, and only one type of frame, limiting each of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * the entries to a much smaller size (in order to generate more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * entries in total, so overhead is bigger.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static int bss_entries_limit = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) module_param(bss_entries_limit, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) MODULE_PARM_DESC(bss_entries_limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) "limit to number of scan BSS entries (per wiphy, default 1000)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * struct cfg80211_colocated_ap - colocated AP information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * @list: linked list to all colocated aPS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * @bssid: BSSID of the reported AP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * @ssid: SSID of the reported AP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * @ssid_len: length of the ssid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * @center_freq: frequency the reported AP is on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * @unsolicited_probe: the reported AP is part of an ESS, where all the APs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * that operate in the same channel as the reported AP and that might be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * detected by a STA receiving this frame, are transmitting unsolicited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * Probe Response frames every 20 TUs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * @oct_recommended: OCT is recommended to exchange MMPDUs with the reported AP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * @same_ssid: the reported AP has the same SSID as the reporting AP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * @multi_bss: the reported AP is part of a multiple BSSID set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * @transmitted_bssid: the reported AP is the transmitting BSSID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * @colocated_ess: all the APs that share the same ESS as the reported AP are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * colocated and can be discovered via legacy bands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * @short_ssid_valid: short_ssid is valid and can be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * @short_ssid: the short SSID for this SSID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct cfg80211_colocated_ap {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u8 bssid[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u8 ssid[IEEE80211_MAX_SSID_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) size_t ssid_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u32 short_ssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u32 center_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u8 unsolicited_probe:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) oct_recommended:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) same_ssid:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) multi_bss:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) transmitted_bssid:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) colocated_ess:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) short_ssid_valid:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static void bss_free(struct cfg80211_internal_bss *bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct cfg80211_bss_ies *ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (WARN_ON(atomic_read(&bss->hold)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ies = (void *)rcu_access_pointer(bss->pub.beacon_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (ies && !bss->pub.hidden_beacon_bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) kfree_rcu(ies, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ies = (void *)rcu_access_pointer(bss->pub.proberesp_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (ies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) kfree_rcu(ies, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * This happens when the module is removed, it doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * really matter any more save for completeness
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (!list_empty(&bss->hidden_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) list_del(&bss->hidden_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) kfree(bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static inline void bss_ref_get(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct cfg80211_internal_bss *bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) lockdep_assert_held(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) bss->refcount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (bss->pub.hidden_beacon_bss) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) bss = container_of(bss->pub.hidden_beacon_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct cfg80211_internal_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) bss->refcount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (bss->pub.transmitted_bss) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) bss = container_of(bss->pub.transmitted_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct cfg80211_internal_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) bss->refcount++;
^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) static inline void bss_ref_put(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct cfg80211_internal_bss *bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) lockdep_assert_held(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (bss->pub.hidden_beacon_bss) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct cfg80211_internal_bss *hbss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) hbss = container_of(bss->pub.hidden_beacon_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct cfg80211_internal_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) hbss->refcount--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (hbss->refcount == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) bss_free(hbss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (bss->pub.transmitted_bss) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct cfg80211_internal_bss *tbss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) tbss = container_of(bss->pub.transmitted_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct cfg80211_internal_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) tbss->refcount--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (tbss->refcount == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) bss_free(tbss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) bss->refcount--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (bss->refcount == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) bss_free(bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct cfg80211_internal_bss *bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) lockdep_assert_held(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (!list_empty(&bss->hidden_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * don't remove the beacon entry if it has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * probe responses associated with it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (!bss->pub.hidden_beacon_bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * if it's a probe response entry break its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * link to the other entries in the group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) list_del_init(&bss->hidden_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) list_del_init(&bss->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) list_del_init(&bss->pub.nontrans_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) rb_erase(&bss->rbn, &rdev->bss_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) rdev->bss_entries--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) WARN_ONCE((rdev->bss_entries == 0) ^ list_empty(&rdev->bss_list),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) "rdev bss entries[%d]/list[empty:%d] corruption\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) rdev->bss_entries, list_empty(&rdev->bss_list));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) bss_ref_put(rdev, bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) bool cfg80211_is_element_inherited(const struct element *elem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) const struct element *non_inherit_elem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) u8 id_len, ext_id_len, i, loop_len, id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) const u8 *list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (elem->id == WLAN_EID_MULTIPLE_BSSID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (!non_inherit_elem || non_inherit_elem->datalen < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * non inheritance element format is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * ext ID (56) | IDs list len | list | extension IDs list len | list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * Both lists are optional. Both lengths are mandatory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * This means valid length is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * elem_len = 1 (extension ID) + 2 (list len fields) + list lengths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) id_len = non_inherit_elem->data[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (non_inherit_elem->datalen < 3 + id_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) ext_id_len = non_inherit_elem->data[2 + id_len];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (non_inherit_elem->datalen < 3 + id_len + ext_id_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (elem->id == WLAN_EID_EXTENSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (!ext_id_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) loop_len = ext_id_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) list = &non_inherit_elem->data[3 + id_len];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) id = elem->data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (!id_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) loop_len = id_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) list = &non_inherit_elem->data[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) id = elem->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) for (i = 0; i < loop_len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (list[i] == id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) EXPORT_SYMBOL(cfg80211_is_element_inherited);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) const u8 *subelement, size_t subie_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) u8 *new_ie, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) u8 *pos, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) const u8 *tmp_old, *tmp_new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) const struct element *non_inherit_elem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u8 *sub_copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* copy subelement as we need to change its content to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * mark an ie after it is processed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) sub_copy = kmemdup(subelement, subie_len, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (!sub_copy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) pos = &new_ie[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* set new ssid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) tmp_new = cfg80211_find_ie(WLAN_EID_SSID, sub_copy, subie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (tmp_new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) memcpy(pos, tmp_new, tmp_new[1] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) pos += (tmp_new[1] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /* get non inheritance list if exists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) non_inherit_elem =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) sub_copy, subie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* go through IEs in ie (skip SSID) and subelement,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * merge them into new_ie
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) tmp_old = cfg80211_find_ie(WLAN_EID_SSID, ie, ielen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) tmp_old = (tmp_old) ? tmp_old + tmp_old[1] + 2 : ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) while (tmp_old + tmp_old[1] + 2 - ie <= ielen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (tmp_old[0] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) tmp_old++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (tmp_old[0] == WLAN_EID_EXTENSION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) tmp = (u8 *)cfg80211_find_ext_ie(tmp_old[2], sub_copy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) subie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) tmp = (u8 *)cfg80211_find_ie(tmp_old[0], sub_copy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) subie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (!tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) const struct element *old_elem = (void *)tmp_old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /* ie in old ie but not in subelement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (cfg80211_is_element_inherited(old_elem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) non_inherit_elem)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) memcpy(pos, tmp_old, tmp_old[1] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) pos += tmp_old[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* ie in transmitting ie also in subelement,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * copy from subelement and flag the ie in subelement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * as copied (by setting eid field to WLAN_EID_SSID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * which is skipped anyway).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * For vendor ie, compare OUI + type + subType to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * determine if they are the same ie.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (tmp_old[0] == WLAN_EID_VENDOR_SPECIFIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (!memcmp(tmp_old + 2, tmp + 2, 5)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /* same vendor ie, copy from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * subelement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) memcpy(pos, tmp, tmp[1] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) pos += tmp[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) tmp[0] = WLAN_EID_SSID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) memcpy(pos, tmp_old, tmp_old[1] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) pos += tmp_old[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /* copy ie from subelement into new ie */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) memcpy(pos, tmp, tmp[1] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) pos += tmp[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) tmp[0] = WLAN_EID_SSID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (tmp_old + tmp_old[1] + 2 - ie == ielen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) tmp_old += tmp_old[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* go through subelement again to check if there is any ie not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * copied to new ie, skip ssid, capability, bssid-index ie
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) tmp_new = sub_copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) while (tmp_new + tmp_new[1] + 2 - sub_copy <= subie_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (!(tmp_new[0] == WLAN_EID_NON_TX_BSSID_CAP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) tmp_new[0] == WLAN_EID_SSID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) memcpy(pos, tmp_new, tmp_new[1] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) pos += tmp_new[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (tmp_new + tmp_new[1] + 2 - sub_copy == subie_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) tmp_new += tmp_new[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) kfree(sub_copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return pos - new_ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static bool is_bss(struct cfg80211_bss *a, const u8 *bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) const u8 *ssid, size_t ssid_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) const struct cfg80211_bss_ies *ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) const u8 *ssidie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (bssid && !ether_addr_equal(a->bssid, bssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (!ssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) ies = rcu_access_pointer(a->ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (!ies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) ssidie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (!ssidie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (ssidie[1] != ssid_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return memcmp(ssidie + 2, ssid, ssid_len) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) cfg80211_add_nontrans_list(struct cfg80211_bss *trans_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) struct cfg80211_bss *nontrans_bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) const u8 *ssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) size_t ssid_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct cfg80211_bss *bss = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (!ssid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) ssid_len = ssid[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) ssid = ssid + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /* check if nontrans_bss is in the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) list_for_each_entry(bss, &trans_bss->nontrans_list, nontrans_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (is_bss(bss, nontrans_bss->bssid, ssid, ssid_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /* add to the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) list_add_tail(&nontrans_bss->nontrans_list, &trans_bss->nontrans_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static void __cfg80211_bss_expire(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) unsigned long expire_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct cfg80211_internal_bss *bss, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) bool expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) lockdep_assert_held(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) list_for_each_entry_safe(bss, tmp, &rdev->bss_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (atomic_read(&bss->hold))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!time_after(expire_time, bss->ts))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (__cfg80211_unlink_bss(rdev, bss))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) expired = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (expired)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) rdev->bss_generation++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) static bool cfg80211_bss_expire_oldest(struct cfg80211_registered_device *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) struct cfg80211_internal_bss *bss, *oldest = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) bool ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) lockdep_assert_held(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) list_for_each_entry(bss, &rdev->bss_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (atomic_read(&bss->hold))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (!list_empty(&bss->hidden_list) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) !bss->pub.hidden_beacon_bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (oldest && time_before(oldest->ts, bss->ts))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) oldest = bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (WARN_ON(!oldest))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * The callers make sure to increase rdev->bss_generation if anything
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * gets removed (and a new entry added), so there's no need to also do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * it here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) ret = __cfg80211_unlink_bss(rdev, oldest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) WARN_ON(!ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) static u8 cfg80211_parse_bss_param(u8 data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct cfg80211_colocated_ap *coloc_ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) coloc_ap->oct_recommended =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) u8_get_bits(data, IEEE80211_RNR_TBTT_PARAMS_OCT_RECOMMENDED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) coloc_ap->same_ssid =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) u8_get_bits(data, IEEE80211_RNR_TBTT_PARAMS_SAME_SSID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) coloc_ap->multi_bss =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) u8_get_bits(data, IEEE80211_RNR_TBTT_PARAMS_MULTI_BSSID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) coloc_ap->transmitted_bssid =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) u8_get_bits(data, IEEE80211_RNR_TBTT_PARAMS_TRANSMITTED_BSSID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) coloc_ap->unsolicited_probe =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) u8_get_bits(data, IEEE80211_RNR_TBTT_PARAMS_PROBE_ACTIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) coloc_ap->colocated_ess =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) u8_get_bits(data, IEEE80211_RNR_TBTT_PARAMS_COLOC_ESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return u8_get_bits(data, IEEE80211_RNR_TBTT_PARAMS_COLOC_AP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static int cfg80211_calc_short_ssid(const struct cfg80211_bss_ies *ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) const struct element **elem, u32 *s_ssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) *elem = cfg80211_find_elem(WLAN_EID_SSID, ies->data, ies->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (!*elem || (*elem)->datalen > IEEE80211_MAX_SSID_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) *s_ssid = ~crc32_le(~0, (*elem)->data, (*elem)->datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) static void cfg80211_free_coloc_ap_list(struct list_head *coloc_ap_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) struct cfg80211_colocated_ap *ap, *tmp_ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) list_for_each_entry_safe(ap, tmp_ap, coloc_ap_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) list_del(&ap->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) kfree(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static int cfg80211_parse_ap_info(struct cfg80211_colocated_ap *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) const u8 *pos, u8 length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) const struct element *ssid_elem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) int s_ssid_tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /* skip the TBTT offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) memcpy(entry->bssid, pos, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) pos += ETH_ALEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (length == IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) memcpy(&entry->short_ssid, pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) sizeof(entry->short_ssid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) entry->short_ssid_valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) pos += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) /* skip non colocated APs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (!cfg80211_parse_bss_param(*pos, entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (length == IEEE80211_TBTT_INFO_OFFSET_BSSID_BSS_PARAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * no information about the short ssid. Consider the entry valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * for now. It would later be dropped in case there are explicit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * SSIDs that need to be matched
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (!entry->same_ssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (entry->same_ssid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) entry->short_ssid = s_ssid_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) entry->short_ssid_valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * This is safe because we validate datalen in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * cfg80211_parse_colocated_ap(), before calling this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) memcpy(&entry->ssid, &ssid_elem->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) ssid_elem->datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) entry->ssid_len = ssid_elem->datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static int cfg80211_parse_colocated_ap(const struct cfg80211_bss_ies *ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct list_head *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) struct ieee80211_neighbor_ap_info *ap_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) const struct element *elem, *ssid_elem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) const u8 *pos, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) u32 s_ssid_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) int n_coloc = 0, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) LIST_HEAD(ap_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) elem = cfg80211_find_elem(WLAN_EID_REDUCED_NEIGHBOR_REPORT, ies->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) ies->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (!elem || elem->datalen > IEEE80211_MAX_SSID_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) pos = elem->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) end = pos + elem->datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) ret = cfg80211_calc_short_ssid(ies, &ssid_elem, &s_ssid_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* RNR IE may contain more than one NEIGHBOR_AP_INFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) while (pos + sizeof(*ap_info) <= end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) enum nl80211_band band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) int freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) u8 length, i, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ap_info = (void *)pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) count = u8_get_bits(ap_info->tbtt_info_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) IEEE80211_AP_INFO_TBTT_HDR_COUNT) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) length = ap_info->tbtt_info_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) pos += sizeof(*ap_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (!ieee80211_operating_class_to_band(ap_info->op_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) &band))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) freq = ieee80211_channel_to_frequency(ap_info->channel, band);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (end - pos < count * ap_info->tbtt_info_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * TBTT info must include bss param + BSSID +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * (short SSID or same_ssid bit to be set).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * ignore other options, and move to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * next AP info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (band != NL80211_BAND_6GHZ ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) (length != IEEE80211_TBTT_INFO_OFFSET_BSSID_BSS_PARAM &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) length < IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) pos += count * ap_info->tbtt_info_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) struct cfg80211_colocated_ap *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) entry = kzalloc(sizeof(*entry) + IEEE80211_MAX_SSID_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (!entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) entry->center_freq = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (!cfg80211_parse_ap_info(entry, pos, length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) ssid_elem, s_ssid_tmp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) n_coloc++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) list_add_tail(&entry->list, &ap_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) pos += ap_info->tbtt_info_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (pos != end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) cfg80211_free_coloc_ap_list(&ap_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) list_splice_tail(&ap_list, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return n_coloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static void cfg80211_scan_req_add_chan(struct cfg80211_scan_request *request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) struct ieee80211_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) bool add_to_6ghz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) u32 n_channels = request->n_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) struct cfg80211_scan_6ghz_params *params =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) &request->scan_6ghz_params[request->n_6ghz_params];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) for (i = 0; i < n_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (request->channels[i] == chan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (add_to_6ghz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) params->channel_idx = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) request->channels[n_channels] = chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (add_to_6ghz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) request->scan_6ghz_params[request->n_6ghz_params].channel_idx =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) n_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) request->n_channels++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) static bool cfg80211_find_ssid_match(struct cfg80211_colocated_ap *ap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) struct cfg80211_scan_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) u32 s_ssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) for (i = 0; i < request->n_ssids; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) /* wildcard ssid in the scan request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (!request->ssids[i].ssid_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (ap->ssid_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ap->ssid_len == request->ssids[i].ssid_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (!memcmp(request->ssids[i].ssid, ap->ssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) ap->ssid_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) } else if (ap->short_ssid_valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) s_ssid = ~crc32_le(~0, request->ssids[i].ssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) request->ssids[i].ssid_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (ap->short_ssid == s_ssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) struct cfg80211_colocated_ap *ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) int n_channels, count = 0, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) struct cfg80211_scan_request *request, *rdev_req = rdev->scan_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) LIST_HEAD(coloc_ap_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) bool need_scan_psc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) const struct ieee80211_sband_iftype_data *iftd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) rdev_req->scan_6ghz = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (!rdev->wiphy.bands[NL80211_BAND_6GHZ])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) iftd = ieee80211_get_sband_iftype_data(rdev->wiphy.bands[NL80211_BAND_6GHZ],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) rdev_req->wdev->iftype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (!iftd || !iftd->he_cap.has_he)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) n_channels = rdev->wiphy.bands[NL80211_BAND_6GHZ]->n_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (rdev_req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) struct cfg80211_internal_bss *intbss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) list_for_each_entry(intbss, &rdev->bss_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) struct cfg80211_bss *res = &intbss->pub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) const struct cfg80211_bss_ies *ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) ies = rcu_access_pointer(res->ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) count += cfg80211_parse_colocated_ap(ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) &coloc_ap_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) request = kzalloc(struct_size(request, channels, n_channels) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) sizeof(*request->scan_6ghz_params) * count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (!request) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) cfg80211_free_coloc_ap_list(&coloc_ap_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) *request = *rdev_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) request->n_channels = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) request->scan_6ghz_params =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) (void *)&request->channels[n_channels];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) * PSC channels should not be scanned if all the reported co-located APs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) * are indicating that all APs in the same ESS are co-located
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) need_scan_psc = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) list_for_each_entry(ap, &coloc_ap_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (!ap->colocated_ess) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) need_scan_psc = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) need_scan_psc = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * add to the scan request the channels that need to be scanned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * regardless of the collocated APs (PSC channels or all channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * in case that NL80211_SCAN_FLAG_COLOCATED_6GHZ is not set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) for (i = 0; i < rdev_req->n_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (rdev_req->channels[i]->band == NL80211_BAND_6GHZ &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) ((need_scan_psc &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) cfg80211_channel_is_psc(rdev_req->channels[i])) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) !(rdev_req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) cfg80211_scan_req_add_chan(request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) rdev_req->channels[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (!(rdev_req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) goto skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) list_for_each_entry(ap, &coloc_ap_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) struct cfg80211_scan_6ghz_params *scan_6ghz_params =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) &request->scan_6ghz_params[request->n_6ghz_params];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) struct ieee80211_channel *chan =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) ieee80211_get_channel(&rdev->wiphy, ap->center_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) for (i = 0; i < rdev_req->n_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (rdev_req->channels[i] == chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if (!found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (request->n_ssids > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) !cfg80211_find_ssid_match(ap, request))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) cfg80211_scan_req_add_chan(request, chan, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) memcpy(scan_6ghz_params->bssid, ap->bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) scan_6ghz_params->short_ssid = ap->short_ssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) scan_6ghz_params->short_ssid_valid = ap->short_ssid_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) scan_6ghz_params->unsolicited_probe = ap->unsolicited_probe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) * If a PSC channel is added to the scan and 'need_scan_psc' is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) * set to false, then all the APs that the scan logic is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) * interested with on the channel are collocated and thus there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) * is no need to perform the initial PSC channel listen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) if (cfg80211_channel_is_psc(chan) && !need_scan_psc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) scan_6ghz_params->psc_no_listen = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) request->n_6ghz_params++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) skip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) cfg80211_free_coloc_ap_list(&coloc_ap_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (request->n_channels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) struct cfg80211_scan_request *old = rdev->int_scan_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) rdev->int_scan_req = request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) * If this scan follows a previous scan, save the scan start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) * info from the first part of the scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) rdev->int_scan_req->info = old->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) err = rdev_scan(rdev, request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) rdev->int_scan_req = old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) kfree(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) kfree(old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return err;
^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) kfree(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) int cfg80211_scan(struct cfg80211_registered_device *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct cfg80211_scan_request *request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) struct cfg80211_scan_request *rdev_req = rdev->scan_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) u32 n_channels = 0, idx, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (!(rdev->wiphy.flags & WIPHY_FLAG_SPLIT_SCAN_6GHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return rdev_scan(rdev, rdev_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) for (i = 0; i < rdev_req->n_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (rdev_req->channels[i]->band != NL80211_BAND_6GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) n_channels++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (!n_channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) return cfg80211_scan_6ghz(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) request = kzalloc(struct_size(request, channels, n_channels),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (!request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) *request = *rdev_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) request->n_channels = n_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) for (i = idx = 0; i < rdev_req->n_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (rdev_req->channels[i]->band != NL80211_BAND_6GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) request->channels[idx++] = rdev_req->channels[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) rdev_req->scan_6ghz = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) rdev->int_scan_req = request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return rdev_scan(rdev, request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) bool send_message)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct cfg80211_scan_request *request, *rdev_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) #ifdef CONFIG_CFG80211_WEXT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) union iwreq_data wrqu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (rdev->scan_msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) nl80211_send_scan_msg(rdev, rdev->scan_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) rdev->scan_msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) return;
^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) rdev_req = rdev->scan_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (!rdev_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) wdev = rdev_req->wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) request = rdev->int_scan_req ? rdev->int_scan_req : rdev_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (wdev_running(wdev) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) (rdev->wiphy.flags & WIPHY_FLAG_SPLIT_SCAN_6GHZ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) !rdev_req->scan_6ghz && !request->info.aborted &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) !cfg80211_scan_6ghz(rdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) * This must be before sending the other events!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) * Otherwise, wpa_supplicant gets completely confused with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) * wext events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (wdev->netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) cfg80211_sme_scan_done(wdev->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (!request->info.aborted &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) request->flags & NL80211_SCAN_FLAG_FLUSH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) /* flush entries from previous scans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) __cfg80211_bss_expire(rdev, request->scan_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) msg = nl80211_build_scan_msg(rdev, wdev, request->info.aborted);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) #ifdef CONFIG_CFG80211_WEXT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (wdev->netdev && !request->info.aborted) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) memset(&wrqu, 0, sizeof(wrqu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) wireless_send_event(wdev->netdev, SIOCGIWSCAN, &wrqu, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (wdev->netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) dev_put(wdev->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) kfree(rdev->int_scan_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) rdev->int_scan_req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) kfree(rdev->scan_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) rdev->scan_req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (!send_message)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) rdev->scan_msg = msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) nl80211_send_scan_msg(rdev, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) void __cfg80211_scan_done(struct work_struct *wk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) rdev = container_of(wk, struct cfg80211_registered_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) scan_done_wk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) ___cfg80211_scan_done(rdev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) void cfg80211_scan_done(struct cfg80211_scan_request *request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) struct cfg80211_scan_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) struct cfg80211_scan_info old_info = request->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) trace_cfg80211_scan_done(request, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) WARN_ON(request != wiphy_to_rdev(request->wiphy)->scan_req &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) request != wiphy_to_rdev(request->wiphy)->int_scan_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) request->info = *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * In case the scan is split, the scan_start_tsf and tsf_bssid should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) * be of the first part. In such a case old_info.scan_start_tsf should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) * be non zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (request->scan_6ghz && old_info.scan_start_tsf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) request->info.scan_start_tsf = old_info.scan_start_tsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) memcpy(request->info.tsf_bssid, old_info.tsf_bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) sizeof(request->info.tsf_bssid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) request->notified = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) queue_work(cfg80211_wq, &wiphy_to_rdev(request->wiphy)->scan_done_wk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) EXPORT_SYMBOL(cfg80211_scan_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) void cfg80211_add_sched_scan_req(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) struct cfg80211_sched_scan_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) list_add_rcu(&req->list, &rdev->sched_scan_req_list);
^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) static void cfg80211_del_sched_scan_req(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) struct cfg80211_sched_scan_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) list_del_rcu(&req->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) kfree_rcu(req, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) static struct cfg80211_sched_scan_request *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) cfg80211_find_sched_scan_req(struct cfg80211_registered_device *rdev, u64 reqid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) struct cfg80211_sched_scan_request *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) list_for_each_entry_rcu(pos, &rdev->sched_scan_req_list, list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) lockdep_rtnl_is_held()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (pos->reqid == reqid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * Determines if a scheduled scan request can be handled. When a legacy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * scheduled scan is running no other scheduled scan is allowed regardless
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) * whether the request is for legacy or multi-support scan. When a multi-support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) * scheduled scan is running a request for legacy scan is not allowed. In this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) * case a request for multi-support scan can be handled if resources are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) * available, ie. struct wiphy::max_sched_scan_reqs limit is not yet reached.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) int cfg80211_sched_scan_req_possible(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) bool want_multi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) struct cfg80211_sched_scan_request *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) list_for_each_entry(pos, &rdev->sched_scan_req_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) /* request id zero means legacy in progress */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) if (!i && !pos->reqid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return -EINPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) /* no legacy allowed when multi request(s) are active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (!want_multi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return -EINPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) /* resource limit reached */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (i == rdev->wiphy.max_sched_scan_reqs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) void cfg80211_sched_scan_results_wk(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) struct cfg80211_sched_scan_request *req, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) rdev = container_of(work, struct cfg80211_registered_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) sched_scan_res_wk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) list_for_each_entry_safe(req, tmp, &rdev->sched_scan_req_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (req->report_results) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) req->report_results = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (req->flags & NL80211_SCAN_FLAG_FLUSH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) /* flush entries from previous scans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) __cfg80211_bss_expire(rdev, req->scan_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) req->scan_start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) nl80211_send_sched_scan(req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) NL80211_CMD_SCHED_SCAN_RESULTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) void cfg80211_sched_scan_results(struct wiphy *wiphy, u64 reqid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) struct cfg80211_sched_scan_request *request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) trace_cfg80211_sched_scan_results(wiphy, reqid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) /* ignore if we're not scanning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) request = cfg80211_find_sched_scan_req(rdev, reqid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (request) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) request->report_results = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) queue_work(cfg80211_wq, &rdev->sched_scan_res_wk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) EXPORT_SYMBOL(cfg80211_sched_scan_results);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy, u64 reqid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) trace_cfg80211_sched_scan_stopped(wiphy, reqid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) __cfg80211_stop_sched_scan(rdev, reqid, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) EXPORT_SYMBOL(cfg80211_sched_scan_stopped_rtnl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) void cfg80211_sched_scan_stopped(struct wiphy *wiphy, u64 reqid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) cfg80211_sched_scan_stopped_rtnl(wiphy, reqid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) int cfg80211_stop_sched_scan_req(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) struct cfg80211_sched_scan_request *req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) bool driver_initiated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (!driver_initiated) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) int err = rdev_sched_scan_stop(rdev, req->dev, req->reqid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) nl80211_send_sched_scan(req, NL80211_CMD_SCHED_SCAN_STOPPED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) cfg80211_del_sched_scan_req(rdev, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) u64 reqid, bool driver_initiated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) struct cfg80211_sched_scan_request *sched_scan_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) sched_scan_req = cfg80211_find_sched_scan_req(rdev, reqid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (!sched_scan_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) return cfg80211_stop_sched_scan_req(rdev, sched_scan_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) driver_initiated);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) void cfg80211_bss_age(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) unsigned long age_secs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) struct cfg80211_internal_bss *bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) list_for_each_entry(bss, &rdev->bss_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) bss->ts -= age_jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) void cfg80211_bss_expire(struct cfg80211_registered_device *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) __cfg80211_bss_expire(rdev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) void cfg80211_bss_flush(struct wiphy *wiphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) __cfg80211_bss_expire(rdev, jiffies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) EXPORT_SYMBOL(cfg80211_bss_flush);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) const struct element *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) cfg80211_find_elem_match(u8 eid, const u8 *ies, unsigned int len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) const u8 *match, unsigned int match_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) unsigned int match_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) const struct element *elem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) for_each_element_id(elem, eid, ies, len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) if (elem->datalen >= match_offset + match_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) !memcmp(elem->data + match_offset, match, match_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) return elem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) EXPORT_SYMBOL(cfg80211_find_elem_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) const struct element *cfg80211_find_vendor_elem(unsigned int oui, int oui_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) const u8 *ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) const struct element *elem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) u8 match[] = { oui >> 16, oui >> 8, oui, oui_type };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) int match_len = (oui_type < 0) ? 3 : sizeof(match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (WARN_ON(oui_type > 0xff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) elem = cfg80211_find_elem_match(WLAN_EID_VENDOR_SPECIFIC, ies, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) match, match_len, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) if (!elem || elem->datalen < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) return elem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) EXPORT_SYMBOL(cfg80211_find_vendor_elem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) * enum bss_compare_mode - BSS compare mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * @BSS_CMP_REGULAR: regular compare mode (for insertion and normal find)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * @BSS_CMP_HIDE_ZLEN: find hidden SSID with zero-length mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) * @BSS_CMP_HIDE_NUL: find hidden SSID with NUL-ed out mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) enum bss_compare_mode {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) BSS_CMP_REGULAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) BSS_CMP_HIDE_ZLEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) BSS_CMP_HIDE_NUL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) static int cmp_bss(struct cfg80211_bss *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) struct cfg80211_bss *b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) enum bss_compare_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) const struct cfg80211_bss_ies *a_ies, *b_ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) const u8 *ie1 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) const u8 *ie2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) int i, r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) if (a->channel != b->channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) return b->channel->center_freq - a->channel->center_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) a_ies = rcu_access_pointer(a->ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (!a_ies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) b_ies = rcu_access_pointer(b->ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) if (!b_ies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (WLAN_CAPABILITY_IS_STA_BSS(a->capability))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) ie1 = cfg80211_find_ie(WLAN_EID_MESH_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) a_ies->data, a_ies->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) if (WLAN_CAPABILITY_IS_STA_BSS(b->capability))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) ie2 = cfg80211_find_ie(WLAN_EID_MESH_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) b_ies->data, b_ies->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) if (ie1 && ie2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) int mesh_id_cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) if (ie1[1] == ie2[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) mesh_id_cmp = memcmp(ie1 + 2, ie2 + 2, ie1[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) mesh_id_cmp = ie2[1] - ie1[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) ie1 = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) a_ies->data, a_ies->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) ie2 = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) b_ies->data, b_ies->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (ie1 && ie2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (mesh_id_cmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) return mesh_id_cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (ie1[1] != ie2[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) return ie2[1] - ie1[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) return memcmp(ie1 + 2, ie2 + 2, ie1[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) r = memcmp(a->bssid, b->bssid, sizeof(a->bssid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) ie1 = cfg80211_find_ie(WLAN_EID_SSID, a_ies->data, a_ies->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) ie2 = cfg80211_find_ie(WLAN_EID_SSID, b_ies->data, b_ies->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) if (!ie1 && !ie2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) * Note that with "hide_ssid", the function returns a match if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) * the already-present BSS ("b") is a hidden SSID beacon for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) * the new BSS ("a").
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) /* sort missing IE before (left of) present IE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) if (!ie1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) if (!ie2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) case BSS_CMP_HIDE_ZLEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) * In ZLEN mode we assume the BSS entry we're
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) * looking for has a zero-length SSID. So if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) * the one we're looking at right now has that,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) * return 0. Otherwise, return the difference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) * in length, but since we're looking for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) * 0-length it's really equivalent to returning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) * the length of the one we're looking at.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) * No content comparison is needed as we assume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) * the content length is zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) return ie2[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) case BSS_CMP_REGULAR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) /* sort by length first, then by contents */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (ie1[1] != ie2[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) return ie2[1] - ie1[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) return memcmp(ie1 + 2, ie2 + 2, ie1[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) case BSS_CMP_HIDE_NUL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) if (ie1[1] != ie2[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) return ie2[1] - ie1[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) /* this is equivalent to memcmp(zeroes, ie2 + 2, len) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) for (i = 0; i < ie2[1]; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (ie2[i + 2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) static bool cfg80211_bss_type_match(u16 capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) enum nl80211_band band,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) enum ieee80211_bss_type bss_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) bool ret = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) u16 mask, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) if (bss_type == IEEE80211_BSS_TYPE_ANY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) if (band == NL80211_BAND_60GHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) mask = WLAN_CAPABILITY_DMG_TYPE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) switch (bss_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) case IEEE80211_BSS_TYPE_ESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) val = WLAN_CAPABILITY_DMG_TYPE_AP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) case IEEE80211_BSS_TYPE_PBSS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) val = WLAN_CAPABILITY_DMG_TYPE_PBSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) case IEEE80211_BSS_TYPE_IBSS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) val = WLAN_CAPABILITY_DMG_TYPE_IBSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) mask = WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) switch (bss_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) case IEEE80211_BSS_TYPE_ESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) val = WLAN_CAPABILITY_ESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) case IEEE80211_BSS_TYPE_IBSS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) val = WLAN_CAPABILITY_IBSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) case IEEE80211_BSS_TYPE_MBSS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) ret = ((capability & mask) == val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) /* Returned bss is reference counted and must be cleaned up appropriately. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) struct ieee80211_channel *channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) const u8 *bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) const u8 *ssid, size_t ssid_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) enum ieee80211_bss_type bss_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) enum ieee80211_privacy privacy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) struct cfg80211_internal_bss *bss, *res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) unsigned long now = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) int bss_privacy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) trace_cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, bss_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) privacy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) list_for_each_entry(bss, &rdev->bss_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (!cfg80211_bss_type_match(bss->pub.capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) bss->pub.channel->band, bss_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) bss_privacy = (bss->pub.capability & WLAN_CAPABILITY_PRIVACY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) if ((privacy == IEEE80211_PRIVACY_ON && !bss_privacy) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) (privacy == IEEE80211_PRIVACY_OFF && bss_privacy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) if (channel && bss->pub.channel != channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) if (!is_valid_ether_addr(bss->pub.bssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) /* Don't get expired BSS structs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) !atomic_read(&bss->hold))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) if (is_bss(&bss->pub, bssid, ssid, ssid_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) res = bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) bss_ref_get(rdev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) trace_cfg80211_return_bss(&res->pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) return &res->pub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) EXPORT_SYMBOL(cfg80211_get_bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) static void rb_insert_bss(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) struct cfg80211_internal_bss *bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) struct rb_node **p = &rdev->bss_tree.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) struct rb_node *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) struct cfg80211_internal_bss *tbss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) int cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) while (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) parent = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) tbss = rb_entry(parent, struct cfg80211_internal_bss, rbn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) cmp = cmp_bss(&bss->pub, &tbss->pub, BSS_CMP_REGULAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) if (WARN_ON(!cmp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) /* will sort of leak this BSS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (cmp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) p = &(*p)->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) p = &(*p)->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) rb_link_node(&bss->rbn, parent, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) rb_insert_color(&bss->rbn, &rdev->bss_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) static struct cfg80211_internal_bss *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) rb_find_bss(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) struct cfg80211_internal_bss *res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) enum bss_compare_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) struct rb_node *n = rdev->bss_tree.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) struct cfg80211_internal_bss *bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) while (n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) bss = rb_entry(n, struct cfg80211_internal_bss, rbn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) r = cmp_bss(&res->pub, &bss->pub, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) if (r == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) return bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) else if (r < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) n = n->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) n = n->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) struct cfg80211_internal_bss *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) const struct cfg80211_bss_ies *ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) struct cfg80211_internal_bss *bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) const u8 *ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) int i, ssidlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) u8 fold = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) u32 n_entries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) ies = rcu_access_pointer(new->pub.beacon_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) if (WARN_ON(!ies))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) ie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) if (!ie) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) /* nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) ssidlen = ie[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) for (i = 0; i < ssidlen; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) fold |= ie[2 + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) if (fold) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) /* not a hidden SSID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) /* This is the bad part ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) list_for_each_entry(bss, &rdev->bss_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) * we're iterating all the entries anyway, so take the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) * opportunity to validate the list length accounting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) n_entries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (!ether_addr_equal(bss->pub.bssid, new->pub.bssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) if (bss->pub.channel != new->pub.channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) if (bss->pub.scan_width != new->pub.scan_width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) if (rcu_access_pointer(bss->pub.beacon_ies))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) ies = rcu_access_pointer(bss->pub.ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) if (!ies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) ie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) if (!ie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) if (ssidlen && ie[1] != ssidlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) if (WARN_ON_ONCE(bss->pub.hidden_beacon_bss))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) if (WARN_ON_ONCE(!list_empty(&bss->hidden_list)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) list_del(&bss->hidden_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) /* combine them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) list_add(&bss->hidden_list, &new->hidden_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) bss->pub.hidden_beacon_bss = &new->pub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) new->refcount += bss->refcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) rcu_assign_pointer(bss->pub.beacon_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) new->pub.beacon_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) WARN_ONCE(n_entries != rdev->bss_entries,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) "rdev bss entries[%d]/list[len:%d] corruption\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) rdev->bss_entries, n_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) struct cfg80211_non_tx_bss {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) struct cfg80211_bss *tx_bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) u8 max_bssid_indicator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) u8 bssid_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) cfg80211_update_known_bss(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) struct cfg80211_internal_bss *known,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) struct cfg80211_internal_bss *new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) bool signal_valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) lockdep_assert_held(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) /* Update IEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) if (rcu_access_pointer(new->pub.proberesp_ies)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) const struct cfg80211_bss_ies *old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) old = rcu_access_pointer(known->pub.proberesp_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) rcu_assign_pointer(known->pub.proberesp_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) new->pub.proberesp_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) /* Override possible earlier Beacon frame IEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) rcu_assign_pointer(known->pub.ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) new->pub.proberesp_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) if (old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) } else if (rcu_access_pointer(new->pub.beacon_ies)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) const struct cfg80211_bss_ies *old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) struct cfg80211_internal_bss *bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) if (known->pub.hidden_beacon_bss &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) !list_empty(&known->hidden_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) const struct cfg80211_bss_ies *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) /* The known BSS struct is one of the probe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) * response members of a group, but we're
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) * receiving a beacon (beacon_ies in the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) * bss is used). This can only mean that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) * AP changed its beacon from not having an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) * SSID to showing it, which is confusing so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) * drop this information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) f = rcu_access_pointer(new->pub.beacon_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) kfree_rcu((struct cfg80211_bss_ies *)f, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) old = rcu_access_pointer(known->pub.beacon_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) rcu_assign_pointer(known->pub.beacon_ies, new->pub.beacon_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) /* Override IEs if they were from a beacon before */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) if (old == rcu_access_pointer(known->pub.ies))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) rcu_assign_pointer(known->pub.ies, new->pub.beacon_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) /* Assign beacon IEs to all sub entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) list_for_each_entry(bss, &known->hidden_list, hidden_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) const struct cfg80211_bss_ies *ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) ies = rcu_access_pointer(bss->pub.beacon_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) WARN_ON(ies != old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) rcu_assign_pointer(bss->pub.beacon_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) new->pub.beacon_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) if (old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) known->pub.beacon_interval = new->pub.beacon_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) /* don't update the signal if beacon was heard on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) * adjacent channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) if (signal_valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) known->pub.signal = new->pub.signal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) known->pub.capability = new->pub.capability;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) known->ts = new->ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) known->ts_boottime = new->ts_boottime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) known->parent_tsf = new->parent_tsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) known->pub.chains = new->pub.chains;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) memcpy(known->pub.chain_signal, new->pub.chain_signal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) IEEE80211_MAX_CHAINS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) ether_addr_copy(known->parent_bssid, new->parent_bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) known->pub.max_bssid_indicator = new->pub.max_bssid_indicator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) known->pub.bssid_index = new->pub.bssid_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) /* Returned bss is reference counted and must be cleaned up appropriately. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) struct cfg80211_internal_bss *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) cfg80211_bss_update(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) struct cfg80211_internal_bss *tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) bool signal_valid, unsigned long ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) struct cfg80211_internal_bss *found = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) if (WARN_ON(!tmp->pub.channel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) tmp->ts = ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) if (WARN_ON(!rcu_access_pointer(tmp->pub.ies))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) found = rb_find_bss(rdev, tmp, BSS_CMP_REGULAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) if (found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) if (!cfg80211_update_known_bss(rdev, found, tmp, signal_valid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) struct cfg80211_internal_bss *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) struct cfg80211_internal_bss *hidden;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) struct cfg80211_bss_ies *ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) * create a copy -- the "res" variable that is passed in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) * is allocated on the stack since it's not needed in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) * more common case of an update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) new = kzalloc(sizeof(*new) + rdev->wiphy.bss_priv_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) if (!new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) ies = (void *)rcu_dereference(tmp->pub.beacon_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) if (ies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) kfree_rcu(ies, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) ies = (void *)rcu_dereference(tmp->pub.proberesp_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) if (ies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) kfree_rcu(ies, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) memcpy(new, tmp, sizeof(*new));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) new->refcount = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) INIT_LIST_HEAD(&new->hidden_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) INIT_LIST_HEAD(&new->pub.nontrans_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) hidden = rb_find_bss(rdev, tmp, BSS_CMP_HIDE_ZLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) if (!hidden)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) hidden = rb_find_bss(rdev, tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) BSS_CMP_HIDE_NUL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) if (hidden) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) new->pub.hidden_beacon_bss = &hidden->pub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) list_add(&new->hidden_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) &hidden->hidden_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) hidden->refcount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) rcu_assign_pointer(new->pub.beacon_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) hidden->pub.beacon_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) * Ok so we found a beacon, and don't have an entry. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) * it's a beacon with hidden SSID, we might be in for an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) * expensive search for any probe responses that should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) * be grouped with this beacon for updates ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) if (!cfg80211_combine_bsses(rdev, new)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) bss_ref_put(rdev, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) if (rdev->bss_entries >= bss_entries_limit &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) !cfg80211_bss_expire_oldest(rdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) bss_ref_put(rdev, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) /* This must be before the call to bss_ref_get */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) if (tmp->pub.transmitted_bss) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) struct cfg80211_internal_bss *pbss =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) container_of(tmp->pub.transmitted_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) struct cfg80211_internal_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) new->pub.transmitted_bss = tmp->pub.transmitted_bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) bss_ref_get(rdev, pbss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) list_add_tail(&new->list, &rdev->bss_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) rdev->bss_entries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) rb_insert_bss(rdev, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) found = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) rdev->bss_generation++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) bss_ref_get(rdev, found);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) return found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) * Update RX channel information based on the available frame payload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) * information. This is mainly for the 2.4 GHz band where frames can be received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) * from neighboring channels and the Beacon frames use the DSSS Parameter Set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) * element to indicate the current (transmitting) channel, but this might also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) * be needed on other bands if RX frequency does not match with the actual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) * operating channel of a BSS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) static struct ieee80211_channel *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) struct ieee80211_channel *channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) enum nl80211_bss_scan_width scan_width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) const u8 *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) u32 freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) int channel_number = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) struct ieee80211_channel *alt_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) if (channel->band == NL80211_BAND_S1GHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) tmp = cfg80211_find_ie(WLAN_EID_S1G_OPERATION, ie, ielen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) if (tmp && tmp[1] >= sizeof(struct ieee80211_s1g_oper_ie)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) struct ieee80211_s1g_oper_ie *s1gop = (void *)(tmp + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) channel_number = s1gop->primary_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) if (tmp && tmp[1] == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) channel_number = tmp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) tmp = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie, ielen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) if (tmp && tmp[1] >= sizeof(struct ieee80211_ht_operation)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) struct ieee80211_ht_operation *htop = (void *)(tmp + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) channel_number = htop->primary_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) if (channel_number < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) /* No channel information in frame payload */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) return channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) freq = ieee80211_channel_to_freq_khz(channel_number, channel->band);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) alt_channel = ieee80211_get_channel_khz(wiphy, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) if (!alt_channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) if (channel->band == NL80211_BAND_2GHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) * Better not allow unexpected channels when that could
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) * be going beyond the 1-11 range (e.g., discovering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) * BSS on channel 12 when radio is configured for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) * channel 11.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) /* No match for the payload channel number - ignore it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) return channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) if (scan_width == NL80211_BSS_CHAN_WIDTH_10 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) scan_width == NL80211_BSS_CHAN_WIDTH_5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) * Ignore channel number in 5 and 10 MHz channels where there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) * may not be an n:1 or 1:n mapping between frequencies and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) * channel numbers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) return channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) * Use the channel determined through the payload channel number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) * instead of the RX channel reported by the driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) if (alt_channel->flags & IEEE80211_CHAN_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) return alt_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) /* Returned bss is reference counted and must be cleaned up appropriately. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) static struct cfg80211_bss *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) cfg80211_inform_single_bss_data(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) struct cfg80211_inform_bss *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) enum cfg80211_bss_frame_type ftype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) const u8 *bssid, u64 tsf, u16 capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) u16 beacon_interval, const u8 *ie, size_t ielen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) struct cfg80211_non_tx_bss *non_tx_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) struct cfg80211_bss_ies *ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) struct ieee80211_channel *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) struct cfg80211_internal_bss tmp = {}, *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) int bss_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) bool signal_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) unsigned long ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) if (WARN_ON(!wiphy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) (data->signal < 0 || data->signal > 100)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) channel = cfg80211_get_bss_channel(wiphy, ie, ielen, data->chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) data->scan_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) if (!channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) memcpy(tmp.pub.bssid, bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) tmp.pub.channel = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) tmp.pub.scan_width = data->scan_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) tmp.pub.signal = data->signal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) tmp.pub.beacon_interval = beacon_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) tmp.pub.capability = capability;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) tmp.ts_boottime = data->boottime_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) if (non_tx_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) tmp.pub.transmitted_bss = non_tx_data->tx_bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) ts = bss_from_pub(non_tx_data->tx_bss)->ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) tmp.pub.bssid_index = non_tx_data->bssid_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) tmp.pub.max_bssid_indicator = non_tx_data->max_bssid_indicator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) ts = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) * If we do not know here whether the IEs are from a Beacon or Probe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) * Response frame, we need to pick one of the options and only use it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) * with the driver that does not provide the full Beacon/Probe Response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) * frame. Use Beacon frame pointer to avoid indicating that this should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) * override the IEs pointer should we have received an earlier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) * indication of Probe Response data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) ies = kzalloc(sizeof(*ies) + ielen, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) if (!ies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) ies->len = ielen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) ies->tsf = tsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) ies->from_beacon = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) memcpy(ies->data, ie, ielen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) switch (ftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) case CFG80211_BSS_FTYPE_BEACON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) ies->from_beacon = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) case CFG80211_BSS_FTYPE_UNKNOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) rcu_assign_pointer(tmp.pub.beacon_ies, ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) case CFG80211_BSS_FTYPE_PRESP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) rcu_assign_pointer(tmp.pub.proberesp_ies, ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) rcu_assign_pointer(tmp.pub.ies, ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) signal_valid = data->chan == channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) if (channel->band == NL80211_BAND_60GHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) bss_type = res->pub.capability & WLAN_CAPABILITY_DMG_TYPE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) if (bss_type == WLAN_CAPABILITY_DMG_TYPE_AP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) bss_type == WLAN_CAPABILITY_DMG_TYPE_PBSS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) regulatory_hint_found_beacon(wiphy, channel, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) if (res->pub.capability & WLAN_CAPABILITY_ESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) regulatory_hint_found_beacon(wiphy, channel, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) if (non_tx_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) /* this is a nontransmitting bss, we need to add it to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) * transmitting bss' list if it is not there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) if (cfg80211_add_nontrans_list(non_tx_data->tx_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) &res->pub)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) if (__cfg80211_unlink_bss(rdev, res))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) rdev->bss_generation++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) trace_cfg80211_return_bss(&res->pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) /* cfg80211_bss_update gives us a referenced result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) return &res->pub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) static const struct element
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) *cfg80211_get_profile_continuation(const u8 *ie, size_t ielen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) const struct element *mbssid_elem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) const struct element *sub_elem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) const u8 *mbssid_end = mbssid_elem->data + mbssid_elem->datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) const struct element *next_mbssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) const struct element *next_sub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) next_mbssid = cfg80211_find_elem(WLAN_EID_MULTIPLE_BSSID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) mbssid_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) ielen - (mbssid_end - ie));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) * If it is not the last subelement in current MBSSID IE or there isn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) * a next MBSSID IE - profile is complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) if ((sub_elem->data + sub_elem->datalen < mbssid_end - 1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) !next_mbssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) /* For any length error, just return NULL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) if (next_mbssid->datalen < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) next_sub = (void *)&next_mbssid->data[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) if (next_mbssid->data + next_mbssid->datalen <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) next_sub->data + next_sub->datalen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) if (next_sub->id != 0 || next_sub->datalen < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) * Check if the first element in the next sub element is a start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) * of a new profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) return next_sub->data[0] == WLAN_EID_NON_TX_BSSID_CAP ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) NULL : next_mbssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) size_t cfg80211_merge_profile(const u8 *ie, size_t ielen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) const struct element *mbssid_elem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) const struct element *sub_elem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) u8 *merged_ie, size_t max_copy_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) size_t copied_len = sub_elem->datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) const struct element *next_mbssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) if (sub_elem->datalen > max_copy_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) memcpy(merged_ie, sub_elem->data, sub_elem->datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) while ((next_mbssid = cfg80211_get_profile_continuation(ie, ielen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) mbssid_elem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) sub_elem))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) const struct element *next_sub = (void *)&next_mbssid->data[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) if (copied_len + next_sub->datalen > max_copy_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) memcpy(merged_ie + copied_len, next_sub->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) next_sub->datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) copied_len += next_sub->datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) return copied_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) EXPORT_SYMBOL(cfg80211_merge_profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) struct cfg80211_inform_bss *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) enum cfg80211_bss_frame_type ftype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) const u8 *bssid, u64 tsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) u16 beacon_interval, const u8 *ie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) size_t ielen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) struct cfg80211_non_tx_bss *non_tx_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) const u8 *mbssid_index_ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) const struct element *elem, *sub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) size_t new_ie_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) u8 new_bssid[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) u8 *new_ie, *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) u64 seen_indices = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) u16 capability;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) struct cfg80211_bss *bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) if (!non_tx_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) if (!cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) if (!wiphy->support_mbssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) if (wiphy->support_only_he_mbssid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) !cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, ie, ielen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) new_ie = kmalloc(IEEE80211_MAX_DATA_LEN, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) if (!new_ie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) profile = kmalloc(ielen, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) if (!profile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, ie, ielen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) if (elem->datalen < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) for_each_element(sub, elem->data + 1, elem->datalen - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) u8 profile_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) if (sub->id != 0 || sub->datalen < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) /* not a valid BSS profile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) sub->data[1] != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) /* The first element within the Nontransmitted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) * BSSID Profile is not the Nontransmitted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) * BSSID Capability element.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) memset(profile, 0, ielen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) profile_len = cfg80211_merge_profile(ie, ielen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) elem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) sub,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) ielen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) /* found a Nontransmitted BSSID Profile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) mbssid_index_ie = cfg80211_find_ie
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) (WLAN_EID_MULTI_BSSID_IDX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) profile, profile_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) if (!mbssid_index_ie || mbssid_index_ie[1] < 1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) mbssid_index_ie[2] == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) mbssid_index_ie[2] > 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) /* No valid Multiple BSSID-Index element */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) if (seen_indices & BIT_ULL(mbssid_index_ie[2]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) /* We don't support legacy split of a profile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) net_dbg_ratelimited("Partial info for BSSID index %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) mbssid_index_ie[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) seen_indices |= BIT_ULL(mbssid_index_ie[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) non_tx_data->bssid_index = mbssid_index_ie[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) non_tx_data->max_bssid_indicator = elem->data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) cfg80211_gen_new_bssid(bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) non_tx_data->max_bssid_indicator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) non_tx_data->bssid_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) new_bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) memset(new_ie, 0, IEEE80211_MAX_DATA_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) new_ie_len = cfg80211_gen_new_ie(ie, ielen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) profile_len, new_ie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) if (!new_ie_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) capability = get_unaligned_le16(profile + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) bss = cfg80211_inform_single_bss_data(wiphy, data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) ftype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) new_bssid, tsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) beacon_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) new_ie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) new_ie_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) non_tx_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) if (!bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) cfg80211_put_bss(wiphy, bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) kfree(new_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) kfree(profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) struct cfg80211_bss *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) cfg80211_inform_bss_data(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) struct cfg80211_inform_bss *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) enum cfg80211_bss_frame_type ftype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) const u8 *bssid, u64 tsf, u16 capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) u16 beacon_interval, const u8 *ie, size_t ielen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) struct cfg80211_bss *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) struct cfg80211_non_tx_bss non_tx_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) res = cfg80211_inform_single_bss_data(wiphy, data, ftype, bssid, tsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) capability, beacon_interval, ie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) ielen, NULL, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) non_tx_data.tx_bss = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) cfg80211_parse_mbssid_data(wiphy, data, ftype, bssid, tsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) beacon_interval, ie, ielen, &non_tx_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) EXPORT_SYMBOL(cfg80211_inform_bss_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) cfg80211_parse_mbssid_frame_data(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) struct cfg80211_inform_bss *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) struct ieee80211_mgmt *mgmt, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) struct cfg80211_non_tx_bss *non_tx_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) enum cfg80211_bss_frame_type ftype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) const u8 *ie = mgmt->u.probe_resp.variable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) size_t ielen = len - offsetof(struct ieee80211_mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) u.probe_resp.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) ftype = ieee80211_is_beacon(mgmt->frame_control) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) CFG80211_BSS_FTYPE_BEACON : CFG80211_BSS_FTYPE_PRESP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) cfg80211_parse_mbssid_data(wiphy, data, ftype, mgmt->bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) le64_to_cpu(mgmt->u.probe_resp.timestamp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) le16_to_cpu(mgmt->u.probe_resp.beacon_int),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) ie, ielen, non_tx_data, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) struct cfg80211_bss *nontrans_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) struct ieee80211_mgmt *mgmt, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) u8 *ie, *new_ie, *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) const u8 *nontrans_ssid, *trans_ssid, *mbssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) size_t ielen = len - offsetof(struct ieee80211_mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) u.probe_resp.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) size_t new_ie_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) struct cfg80211_bss_ies *new_ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) const struct cfg80211_bss_ies *old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) u8 cpy_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) lockdep_assert_held(&wiphy_to_rdev(wiphy)->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) ie = mgmt->u.probe_resp.variable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) new_ie_len = ielen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) trans_ssid = cfg80211_find_ie(WLAN_EID_SSID, ie, ielen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) if (!trans_ssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) new_ie_len -= trans_ssid[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) mbssid = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) * It's not valid to have the MBSSID element before SSID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) * ignore if that happens - the code below assumes it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) * after (while copying things inbetween).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) if (!mbssid || mbssid < trans_ssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) new_ie_len -= mbssid[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) nontrans_ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) if (!nontrans_ssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) new_ie_len += nontrans_ssid[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) /* generate new ie for nontrans BSS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) * 1. replace SSID with nontrans BSS' SSID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) * 2. skip MBSSID IE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) new_ie = kzalloc(new_ie_len, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) if (!new_ie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) if (!new_ies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) pos = new_ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) /* copy the nontransmitted SSID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) cpy_len = nontrans_ssid[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) memcpy(pos, nontrans_ssid, cpy_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) pos += cpy_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) /* copy the IEs between SSID and MBSSID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) cpy_len = trans_ssid[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) memcpy(pos, (trans_ssid + cpy_len), (mbssid - (trans_ssid + cpy_len)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) pos += (mbssid - (trans_ssid + cpy_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) /* copy the IEs after MBSSID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) cpy_len = mbssid[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) memcpy(pos, mbssid + cpy_len, ((ie + ielen) - (mbssid + cpy_len)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) /* update ie */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) new_ies->len = new_ie_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) new_ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) new_ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) memcpy(new_ies->data, new_ie, new_ie_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) if (ieee80211_is_probe_resp(mgmt->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) old = rcu_access_pointer(nontrans_bss->proberesp_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) rcu_assign_pointer(nontrans_bss->proberesp_ies, new_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) rcu_assign_pointer(nontrans_bss->ies, new_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) if (old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) old = rcu_access_pointer(nontrans_bss->beacon_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) rcu_assign_pointer(nontrans_bss->beacon_ies, new_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) rcu_assign_pointer(nontrans_bss->ies, new_ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) if (old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) kfree(new_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) /* cfg80211_inform_bss_width_frame helper */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) static struct cfg80211_bss *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) struct cfg80211_inform_bss *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) struct ieee80211_mgmt *mgmt, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) struct cfg80211_internal_bss tmp = {}, *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) struct cfg80211_bss_ies *ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) struct ieee80211_channel *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) bool signal_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) struct ieee80211_ext *ext = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) u8 *bssid, *variable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) u16 capability, beacon_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) size_t ielen, min_hdr_len = offsetof(struct ieee80211_mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) u.probe_resp.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) int bss_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) offsetof(struct ieee80211_mgmt, u.beacon.variable));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) trace_cfg80211_inform_bss_frame(wiphy, data, mgmt, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) if (WARN_ON(!mgmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) if (WARN_ON(!wiphy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) (data->signal < 0 || data->signal > 100)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) ext = (void *) mgmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) min_hdr_len = offsetof(struct ieee80211_ext, u.s1g_beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) if (ieee80211_is_s1g_short_beacon(mgmt->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) min_hdr_len = offsetof(struct ieee80211_ext,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) u.s1g_short_beacon.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) if (WARN_ON(len < min_hdr_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) ielen = len - min_hdr_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) variable = mgmt->u.probe_resp.variable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) if (ext) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) if (ieee80211_is_s1g_short_beacon(mgmt->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) variable = ext->u.s1g_short_beacon.variable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) variable = ext->u.s1g_beacon.variable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) channel = cfg80211_get_bss_channel(wiphy, variable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) ielen, data->chan, data->scan_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) if (!channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) if (ext) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) const struct ieee80211_s1g_bcn_compat_ie *compat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) const struct element *elem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) elem = cfg80211_find_elem(WLAN_EID_S1G_BCN_COMPAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) variable, ielen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) if (!elem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) if (elem->datalen < sizeof(*compat))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) compat = (void *)elem->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) bssid = ext->u.s1g_beacon.sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) capability = le16_to_cpu(compat->compat_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) beacon_int = le16_to_cpu(compat->beacon_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) bssid = mgmt->bssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) beacon_int = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) ies = kzalloc(sizeof(*ies) + ielen, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) if (!ies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) ies->len = ielen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) ieee80211_is_s1g_beacon(mgmt->frame_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) memcpy(ies->data, variable, ielen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) if (ieee80211_is_probe_resp(mgmt->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) rcu_assign_pointer(tmp.pub.proberesp_ies, ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) rcu_assign_pointer(tmp.pub.beacon_ies, ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) rcu_assign_pointer(tmp.pub.ies, ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) memcpy(tmp.pub.bssid, bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) tmp.pub.beacon_interval = beacon_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) tmp.pub.capability = capability;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) tmp.pub.channel = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) tmp.pub.scan_width = data->scan_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) tmp.pub.signal = data->signal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) tmp.ts_boottime = data->boottime_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) tmp.parent_tsf = data->parent_tsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) tmp.pub.chains = data->chains;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) memcpy(tmp.pub.chain_signal, data->chain_signal, IEEE80211_MAX_CHAINS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) ether_addr_copy(tmp.parent_bssid, data->parent_bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) signal_valid = data->chan == channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) jiffies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) if (channel->band == NL80211_BAND_60GHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) bss_type = res->pub.capability & WLAN_CAPABILITY_DMG_TYPE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) if (bss_type == WLAN_CAPABILITY_DMG_TYPE_AP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) bss_type == WLAN_CAPABILITY_DMG_TYPE_PBSS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) regulatory_hint_found_beacon(wiphy, channel, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) if (res->pub.capability & WLAN_CAPABILITY_ESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) regulatory_hint_found_beacon(wiphy, channel, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) trace_cfg80211_return_bss(&res->pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) /* cfg80211_bss_update gives us a referenced result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) return &res->pub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) struct cfg80211_bss *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) struct cfg80211_inform_bss *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) struct ieee80211_mgmt *mgmt, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) struct cfg80211_bss *res, *tmp_bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) const u8 *ie = mgmt->u.probe_resp.variable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) const struct cfg80211_bss_ies *ies1, *ies2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) size_t ielen = len - offsetof(struct ieee80211_mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) u.probe_resp.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) struct cfg80211_non_tx_bss non_tx_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) res = cfg80211_inform_single_bss_frame_data(wiphy, data, mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) len, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) if (!res || !wiphy->support_mbssid ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) !cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) if (wiphy->support_only_he_mbssid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) !cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, ie, ielen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) non_tx_data.tx_bss = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) /* process each non-transmitting bss */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) cfg80211_parse_mbssid_frame_data(wiphy, data, mgmt, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) &non_tx_data, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) spin_lock_bh(&wiphy_to_rdev(wiphy)->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) /* check if the res has other nontransmitting bss which is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) * in MBSSID IE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) ies1 = rcu_access_pointer(res->ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) /* go through nontrans_list, if the timestamp of the BSS is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) * earlier than the timestamp of the transmitting BSS then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) * update it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) list_for_each_entry(tmp_bss, &res->nontrans_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) nontrans_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) ies2 = rcu_access_pointer(tmp_bss->ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) if (ies2->tsf < ies1->tsf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) cfg80211_update_notlisted_nontrans(wiphy, tmp_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) mgmt, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) spin_unlock_bh(&wiphy_to_rdev(wiphy)->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) EXPORT_SYMBOL(cfg80211_inform_bss_frame_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) void cfg80211_ref_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) struct cfg80211_internal_bss *bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) if (!pub)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) bss = container_of(pub, struct cfg80211_internal_bss, pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) bss_ref_get(rdev, bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) EXPORT_SYMBOL(cfg80211_ref_bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) void cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) struct cfg80211_internal_bss *bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) if (!pub)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) bss = container_of(pub, struct cfg80211_internal_bss, pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) bss_ref_put(rdev, bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) EXPORT_SYMBOL(cfg80211_put_bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) struct cfg80211_internal_bss *bss, *tmp1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) struct cfg80211_bss *nontrans_bss, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) if (WARN_ON(!pub))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) bss = container_of(pub, struct cfg80211_internal_bss, pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) if (list_empty(&bss->list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) list_for_each_entry_safe(nontrans_bss, tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) &pub->nontrans_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) nontrans_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) tmp1 = container_of(nontrans_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) struct cfg80211_internal_bss, pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) if (__cfg80211_unlink_bss(rdev, tmp1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) rdev->bss_generation++;
^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 (__cfg80211_unlink_bss(rdev, bss))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) rdev->bss_generation++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) EXPORT_SYMBOL(cfg80211_unlink_bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) void cfg80211_bss_iter(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) struct cfg80211_chan_def *chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) void (*iter)(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) struct cfg80211_bss *bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) void *data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) void *iter_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) struct cfg80211_internal_bss *bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) list_for_each_entry(bss, &rdev->bss_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) if (!chandef || cfg80211_is_sub_chan(chandef, bss->pub.channel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) iter(wiphy, &bss->pub, iter_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) EXPORT_SYMBOL(cfg80211_bss_iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) struct ieee80211_channel *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) struct cfg80211_internal_bss *cbss = wdev->current_bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) struct cfg80211_internal_bss *new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) struct cfg80211_internal_bss *bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) struct cfg80211_bss *nontrans_bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) struct cfg80211_bss *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) * Some APs use CSA also for bandwidth changes, i.e., without actually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) * changing the control channel, so no need to update in such a case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) if (cbss->pub.channel == chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) /* use transmitting bss */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) if (cbss->pub.transmitted_bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) cbss = container_of(cbss->pub.transmitted_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) struct cfg80211_internal_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) cbss->pub.channel = chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) list_for_each_entry(bss, &rdev->bss_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) if (!cfg80211_bss_type_match(bss->pub.capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) bss->pub.channel->band,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) wdev->conn_bss_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) if (bss == cbss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) if (!cmp_bss(&bss->pub, &cbss->pub, BSS_CMP_REGULAR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) new = bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) if (new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) /* to save time, update IEs for transmitting bss only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) if (cfg80211_update_known_bss(rdev, cbss, new, false)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) new->pub.proberesp_ies = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) new->pub.beacon_ies = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) list_for_each_entry_safe(nontrans_bss, tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) &new->pub.nontrans_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) nontrans_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) bss = container_of(nontrans_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) struct cfg80211_internal_bss, pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) if (__cfg80211_unlink_bss(rdev, bss))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) rdev->bss_generation++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) WARN_ON(atomic_read(&new->hold));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) if (!WARN_ON(!__cfg80211_unlink_bss(rdev, new)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) rdev->bss_generation++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) rb_erase(&cbss->rbn, &rdev->bss_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) rb_insert_bss(rdev, cbss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) rdev->bss_generation++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) list_for_each_entry_safe(nontrans_bss, tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) &cbss->pub.nontrans_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) nontrans_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) bss = container_of(nontrans_bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) struct cfg80211_internal_bss, pub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) bss->pub.channel = chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) rb_erase(&bss->rbn, &rdev->bss_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) rb_insert_bss(rdev, bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) rdev->bss_generation++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) #ifdef CONFIG_CFG80211_WEXT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) static struct cfg80211_registered_device *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) dev = dev_get_by_index(net, ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) if (dev->ieee80211_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) rdev = wiphy_to_rdev(dev->ieee80211_ptr->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) rdev = ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) return rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) int cfg80211_wext_siwscan(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) struct wiphy *wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) struct iw_scan_req *wreq = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) struct cfg80211_scan_request *creq = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) int i, err, n_channels = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) enum nl80211_band band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) if (!netif_running(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) return -ENETDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) if (wrqu->data.length == sizeof(struct iw_scan_req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) wreq = (struct iw_scan_req *)extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) if (IS_ERR(rdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) return PTR_ERR(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) if (rdev->scan_req || rdev->scan_msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) wiphy = &rdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) /* Determine number of channels, needed to allocate creq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) if (wreq && wreq->num_channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) n_channels = wreq->num_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) n_channels = ieee80211_get_num_supported_channels(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) n_channels * sizeof(void *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) if (!creq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) creq->wiphy = wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) creq->wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) /* SSIDs come after channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) creq->ssids = (void *)&creq->channels[n_channels];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) creq->n_channels = n_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) creq->n_ssids = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) creq->scan_start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) /* translate "Scan on frequencies" request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) for (band = 0; band < NUM_NL80211_BANDS; band++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) if (!wiphy->bands[band])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) /* ignore disabled channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) if (wiphy->bands[band]->channels[j].flags &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) IEEE80211_CHAN_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) /* If we have a wireless request structure and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) * wireless request specifies frequencies, then search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) * for the matching hardware channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) if (wreq && wreq->num_channels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) int wiphy_freq = wiphy->bands[band]->channels[j].center_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) for (k = 0; k < wreq->num_channels; k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) struct iw_freq *freq =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) &wreq->channel_list[k];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) int wext_freq =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) cfg80211_wext_freq(freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) if (wext_freq == wiphy_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) goto wext_freq_found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) goto wext_freq_not_found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) wext_freq_found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) creq->channels[i] = &wiphy->bands[band]->channels[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) wext_freq_not_found: ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) /* No channels found? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) if (!i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) /* Set real number of channels specified in creq->channels[] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) creq->n_channels = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) /* translate "Scan for SSID" request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) if (wreq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) creq->ssids[0].ssid_len = wreq->essid_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) creq->n_ssids = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) for (i = 0; i < NUM_NL80211_BANDS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) if (wiphy->bands[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) eth_broadcast_addr(creq->bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) rdev->scan_req = creq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) err = rdev_scan(rdev, creq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) rdev->scan_req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) /* creq will be freed below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) nl80211_send_scan_start(rdev, dev->ieee80211_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) /* creq now owned by driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) creq = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) dev_hold(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) kfree(creq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) EXPORT_WEXT_HANDLER(cfg80211_wext_siwscan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) static char *ieee80211_scan_add_ies(struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) const struct cfg80211_bss_ies *ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) char *current_ev, char *end_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) const u8 *pos, *end, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) struct iw_event iwe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) if (!ies)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) return current_ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) * If needed, fragment the IEs buffer (at IE boundaries) into short
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) * enough fragments to fit into IW_GENERIC_IE_MAX octet messages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) pos = ies->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) end = pos + ies->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) while (end - pos > IW_GENERIC_IE_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) next = pos + 2 + pos[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) next = next + 2 + next[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) iwe.cmd = IWEVGENIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) iwe.u.data.length = next - pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) current_ev = iwe_stream_add_point_check(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) end_buf, &iwe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) (void *)pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) return current_ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) pos = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) if (end > pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) iwe.cmd = IWEVGENIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) iwe.u.data.length = end - pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) current_ev = iwe_stream_add_point_check(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) end_buf, &iwe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) (void *)pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) return current_ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) return current_ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) static char *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) struct cfg80211_internal_bss *bss, char *current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) char *end_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) const struct cfg80211_bss_ies *ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) struct iw_event iwe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) const u8 *ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) u8 buf[50];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) u8 *cfg, *p, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) int rem, i, sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) bool ismesh = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) iwe.cmd = SIOCGIWAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) memcpy(iwe.u.ap_addr.sa_data, bss->pub.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) current_ev = iwe_stream_add_event_check(info, current_ev, end_buf, &iwe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) IW_EV_ADDR_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) return current_ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) iwe.cmd = SIOCGIWFREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) iwe.u.freq.m = ieee80211_frequency_to_channel(bss->pub.channel->center_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) iwe.u.freq.e = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) current_ev = iwe_stream_add_event_check(info, current_ev, end_buf, &iwe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) IW_EV_FREQ_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) return current_ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) iwe.cmd = SIOCGIWFREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) iwe.u.freq.m = bss->pub.channel->center_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) iwe.u.freq.e = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) current_ev = iwe_stream_add_event_check(info, current_ev, end_buf, &iwe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) IW_EV_FREQ_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) return current_ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) if (wiphy->signal_type != CFG80211_SIGNAL_TYPE_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) iwe.cmd = IWEVQUAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) IW_QUAL_NOISE_INVALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) IW_QUAL_QUAL_UPDATED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) switch (wiphy->signal_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) case CFG80211_SIGNAL_TYPE_MBM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) sig = bss->pub.signal / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) iwe.u.qual.level = sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) iwe.u.qual.updated |= IW_QUAL_DBM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) if (sig < -110) /* rather bad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) sig = -110;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) else if (sig > -40) /* perfect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) sig = -40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) /* will give a range of 0 .. 70 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) iwe.u.qual.qual = sig + 110;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) case CFG80211_SIGNAL_TYPE_UNSPEC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) iwe.u.qual.level = bss->pub.signal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) /* will give range 0 .. 100 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) iwe.u.qual.qual = bss->pub.signal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) /* not reached */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) current_ev = iwe_stream_add_event_check(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) end_buf, &iwe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) IW_EV_QUAL_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) return current_ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) iwe.cmd = SIOCGIWENCODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) if (bss->pub.capability & WLAN_CAPABILITY_PRIVACY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) iwe.u.data.flags = IW_ENCODE_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) iwe.u.data.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) current_ev = iwe_stream_add_point_check(info, current_ev, end_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) &iwe, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) return current_ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) ies = rcu_dereference(bss->pub.ies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) rem = ies->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) ie = ies->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) while (rem >= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) /* invalid data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) if (ie[1] > rem - 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) switch (ie[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) case WLAN_EID_SSID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) iwe.cmd = SIOCGIWESSID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) iwe.u.data.length = ie[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) iwe.u.data.flags = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) current_ev = iwe_stream_add_point_check(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) end_buf, &iwe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) (u8 *)ie + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) case WLAN_EID_MESH_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) iwe.cmd = SIOCGIWESSID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) iwe.u.data.length = ie[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) iwe.u.data.flags = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) current_ev = iwe_stream_add_point_check(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) end_buf, &iwe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) (u8 *)ie + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) case WLAN_EID_MESH_CONFIG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) ismesh = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) cfg = (u8 *)ie + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) iwe.cmd = IWEVCUSTOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) sprintf(buf, "Mesh Network Path Selection Protocol ID: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) "0x%02X", cfg[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) iwe.u.data.length = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) current_ev = iwe_stream_add_point_check(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) end_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) &iwe, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) sprintf(buf, "Path Selection Metric ID: 0x%02X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) cfg[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) iwe.u.data.length = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) current_ev = iwe_stream_add_point_check(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) end_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) &iwe, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) sprintf(buf, "Congestion Control Mode ID: 0x%02X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) cfg[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) iwe.u.data.length = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) current_ev = iwe_stream_add_point_check(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) end_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) &iwe, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) sprintf(buf, "Synchronization ID: 0x%02X", cfg[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) iwe.u.data.length = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) current_ev = iwe_stream_add_point_check(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) end_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) &iwe, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) sprintf(buf, "Authentication ID: 0x%02X", cfg[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) iwe.u.data.length = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) current_ev = iwe_stream_add_point_check(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) end_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) &iwe, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) sprintf(buf, "Formation Info: 0x%02X", cfg[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) iwe.u.data.length = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) current_ev = iwe_stream_add_point_check(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) end_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) &iwe, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) sprintf(buf, "Capabilities: 0x%02X", cfg[6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) iwe.u.data.length = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) current_ev = iwe_stream_add_point_check(info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) end_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) &iwe, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) case WLAN_EID_SUPP_RATES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) case WLAN_EID_EXT_SUPP_RATES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) /* display all supported rates in readable format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) p = current_ev + iwe_stream_lcp_len(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) iwe.cmd = SIOCGIWRATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) /* Those two flags are ignored... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) for (i = 0; i < ie[1]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) iwe.u.bitrate.value =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) ((ie[i + 2] & 0x7f) * 500000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) tmp = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) p = iwe_stream_add_value(info, current_ev, p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) end_buf, &iwe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) IW_EV_PARAM_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) if (p == tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) current_ev = ERR_PTR(-E2BIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) current_ev = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) rem -= ie[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) ie += ie[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) if (bss->pub.capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) ismesh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) iwe.cmd = SIOCGIWMODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) if (ismesh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) iwe.u.mode = IW_MODE_MESH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) else if (bss->pub.capability & WLAN_CAPABILITY_ESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) iwe.u.mode = IW_MODE_MASTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) iwe.u.mode = IW_MODE_ADHOC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) current_ev = iwe_stream_add_event_check(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) end_buf, &iwe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) IW_EV_UINT_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) iwe.cmd = IWEVCUSTOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) sprintf(buf, "tsf=%016llx", (unsigned long long)(ies->tsf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) iwe.u.data.length = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) current_ev = iwe_stream_add_point_check(info, current_ev, end_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) &iwe, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) memset(&iwe, 0, sizeof(iwe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) iwe.cmd = IWEVCUSTOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) sprintf(buf, " Last beacon: %ums ago",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) elapsed_jiffies_msecs(bss->ts));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) iwe.u.data.length = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) current_ev = iwe_stream_add_point_check(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) end_buf, &iwe, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) if (IS_ERR(current_ev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) current_ev = ieee80211_scan_add_ies(info, ies, current_ev, end_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) return current_ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) static int ieee80211_scan_results(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) char *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) char *current_ev = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) char *end_buf = buf + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) struct cfg80211_internal_bss *bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) spin_lock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) cfg80211_bss_expire(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) list_for_each_entry(bss, &rdev->bss_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) err = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) current_ev = ieee80211_bss(&rdev->wiphy, info, bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) current_ev, end_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) if (IS_ERR(current_ev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) err = PTR_ERR(current_ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) spin_unlock_bh(&rdev->bss_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) return current_ev - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) int cfg80211_wext_giwscan(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) struct iw_point *data, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) if (!netif_running(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) return -ENETDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) if (IS_ERR(rdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) return PTR_ERR(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) if (rdev->scan_req || rdev->scan_msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) res = ieee80211_scan_results(rdev, info, extra, data->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) data->length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) if (res >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) data->length = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) EXPORT_WEXT_HANDLER(cfg80211_wext_giwscan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) #endif