^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 MLME SAP interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2015 Intel Deutschland GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2019 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^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/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/etherdevice.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/nl80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/wireless.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <net/cfg80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <net/iw_handler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "nl80211.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "rdev-ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) const u8 *buf, size_t len, int uapsd_queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) const u8 *req_ies, size_t req_ies_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct cfg80211_connect_resp_params cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) const u8 *resp_ie = mgmt->u.assoc_resp.variable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) size_t resp_ie_len = len - offsetof(struct ieee80211_mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) u.assoc_resp.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (bss->channel->band == NL80211_BAND_S1GHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) resp_ie = (u8 *)&mgmt->u.s1g_assoc_resp.variable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) resp_ie_len = len - offsetof(struct ieee80211_mgmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) u.s1g_assoc_resp.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) memset(&cr, 0, sizeof(cr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) cr.status = (int)le16_to_cpu(mgmt->u.assoc_resp.status_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) cr.bssid = mgmt->bssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) cr.bss = bss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) cr.req_ie = req_ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) cr.req_ie_len = req_ies_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) cr.resp_ie = resp_ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) cr.resp_ie_len = resp_ie_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) cr.timeout_reason = NL80211_TIMEOUT_UNSPECIFIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) trace_cfg80211_send_rx_assoc(dev, bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * This is a bit of a hack, we don't notify userspace of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * a (re-)association reply if we tried to send a reassoc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * and got a reject -- we only try again with an assoc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * frame instead of reassoc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (cfg80211_sme_rx_assoc_resp(wdev, cr.status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) cfg80211_unhold_bss(bss_from_pub(bss));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) cfg80211_put_bss(wiphy, bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL, uapsd_queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) req_ies, req_ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* update current_bss etc., consumes the bss reference */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) __cfg80211_connect_result(dev, &cr, cr.status == WLAN_STATUS_SUCCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) EXPORT_SYMBOL(cfg80211_rx_assoc_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static void cfg80211_process_auth(struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) const u8 *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) nl80211_send_rx_auth(rdev, wdev->netdev, buf, len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) cfg80211_sme_rx_auth(wdev, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static void cfg80211_process_deauth(struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) const u8 *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) const u8 *bssid = mgmt->bssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) nl80211_send_deauth(rdev, wdev->netdev, buf, len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (!wdev->current_bss ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) __cfg80211_disconnected(wdev->netdev, NULL, 0, reason_code, from_ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) cfg80211_sme_deauth(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static void cfg80211_process_disassoc(struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) const u8 *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) const u8 *bssid = mgmt->bssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u16 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) nl80211_send_disassoc(rdev, wdev->netdev, buf, len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (WARN_ON(!wdev->current_bss ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) __cfg80211_disconnected(wdev->netdev, NULL, 0, reason_code, from_ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) cfg80211_sme_disassoc(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) void cfg80211_rx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct ieee80211_mgmt *mgmt = (void *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ASSERT_WDEV_LOCK(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) trace_cfg80211_rx_mlme_mgmt(dev, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (WARN_ON(len < 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (ieee80211_is_auth(mgmt->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) cfg80211_process_auth(wdev, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) else if (ieee80211_is_deauth(mgmt->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) cfg80211_process_deauth(wdev, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) else if (ieee80211_is_disassoc(mgmt->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) cfg80211_process_disassoc(wdev, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) EXPORT_SYMBOL(cfg80211_rx_mlme_mgmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) trace_cfg80211_send_auth_timeout(dev, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) cfg80211_sme_auth_timeout(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) EXPORT_SYMBOL(cfg80211_auth_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) trace_cfg80211_send_assoc_timeout(dev, bss->bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) nl80211_send_assoc_timeout(rdev, dev, bss->bssid, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) cfg80211_sme_assoc_timeout(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) cfg80211_unhold_bss(bss_from_pub(bss));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) cfg80211_put_bss(wiphy, bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) EXPORT_SYMBOL(cfg80211_assoc_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) cfg80211_sme_abandon_assoc(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) cfg80211_unhold_bss(bss_from_pub(bss));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) cfg80211_put_bss(wiphy, bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) EXPORT_SYMBOL(cfg80211_abandon_assoc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct ieee80211_mgmt *mgmt = (void *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ASSERT_WDEV_LOCK(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) trace_cfg80211_tx_mlme_mgmt(dev, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (WARN_ON(len < 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (ieee80211_is_deauth(mgmt->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) cfg80211_process_deauth(wdev, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) cfg80211_process_disassoc(wdev, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) EXPORT_SYMBOL(cfg80211_tx_mlme_mgmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) enum nl80211_key_type key_type, int key_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) const u8 *tsc, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) #ifdef CONFIG_CFG80211_WEXT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) union iwreq_data wrqu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) char *buf = kmalloc(128, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) "keyid=%d %scast addr=%pM)", key_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) key_type == NL80211_KEYTYPE_GROUP ? "broad" : "uni",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) memset(&wrqu, 0, sizeof(wrqu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) wrqu.data.length = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) trace_cfg80211_michael_mic_failure(dev, addr, key_type, key_id, tsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) EXPORT_SYMBOL(cfg80211_michael_mic_failure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* some MLME handling for userspace SME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct ieee80211_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) enum nl80211_auth_type auth_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) const u8 *bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) const u8 *ssid, int ssid_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) const u8 *ie, int ie_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) const u8 *key, int key_len, int key_idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) const u8 *auth_data, int auth_data_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct cfg80211_auth_request req = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .ie = ie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .ie_len = ie_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .auth_data = auth_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .auth_data_len = auth_data_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .auth_type = auth_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) .key = key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .key_len = key_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) .key_idx = key_idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ASSERT_WDEV_LOCK(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (!key || !key_len || key_idx < 0 || key_idx > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (wdev->current_bss &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) ether_addr_equal(bssid, wdev->current_bss->pub.bssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) IEEE80211_BSS_TYPE_ESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) IEEE80211_PRIVACY_ANY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (!req.bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) err = rdev_auth(rdev, dev, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) cfg80211_put_bss(&rdev->wiphy, req.bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* Do a logical ht_capa &= ht_capa_mask. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) const struct ieee80211_ht_cap *ht_capa_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) u8 *p1, *p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (!ht_capa_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) memset(ht_capa, 0, sizeof(*ht_capa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) p1 = (u8*)(ht_capa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) p2 = (u8*)(ht_capa_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) for (i = 0; i < sizeof(*ht_capa); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) p1[i] &= p2[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /* Do a logical vht_capa &= vht_capa_mask. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) const struct ieee80211_vht_cap *vht_capa_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) u8 *p1, *p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (!vht_capa_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) memset(vht_capa, 0, sizeof(*vht_capa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) p1 = (u8*)(vht_capa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) p2 = (u8*)(vht_capa_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) for (i = 0; i < sizeof(*vht_capa); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) p1[i] &= p2[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct ieee80211_channel *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) const u8 *bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) const u8 *ssid, int ssid_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) struct cfg80211_assoc_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) ASSERT_WDEV_LOCK(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (wdev->current_bss &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) (!req->prev_bssid || !ether_addr_equal(wdev->current_bss->pub.bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) req->prev_bssid)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) cfg80211_oper_and_ht_capa(&req->ht_capa_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) rdev->wiphy.ht_capa_mod_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) cfg80211_oper_and_vht_capa(&req->vht_capa_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) rdev->wiphy.vht_capa_mod_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) req->bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) IEEE80211_BSS_TYPE_ESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) IEEE80211_PRIVACY_ANY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (!req->bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) err = rdev_assoc(rdev, dev, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) cfg80211_hold_bss(bss_from_pub(req->bss));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) cfg80211_put_bss(&rdev->wiphy, req->bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct net_device *dev, const u8 *bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) const u8 *ie, int ie_len, u16 reason,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) bool local_state_change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct cfg80211_deauth_request req = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) .bssid = bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) .reason_code = reason,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) .ie = ie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) .ie_len = ie_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) .local_state_change = local_state_change,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) ASSERT_WDEV_LOCK(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (local_state_change &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) (!wdev->current_bss ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (ether_addr_equal(wdev->disconnect_bssid, bssid) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) (wdev->current_bss &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) wdev->conn_owner_nlportid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return rdev_deauth(rdev, dev, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct net_device *dev, const u8 *bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) const u8 *ie, int ie_len, u16 reason,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) bool local_state_change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct cfg80211_disassoc_request req = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .reason_code = reason,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .local_state_change = local_state_change,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) .ie = ie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) .ie_len = ie_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) ASSERT_WDEV_LOCK(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (!wdev->current_bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (ether_addr_equal(wdev->current_bss->pub.bssid, bssid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) req.bss = &wdev->current_bss->pub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) err = rdev_disassoc(rdev, dev, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /* driver should have reported the disassoc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) WARN_ON(wdev->current_bss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct wireless_dev *wdev = dev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) u8 bssid[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ASSERT_WDEV_LOCK(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (!rdev->ops->deauth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (!wdev->current_bss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) WLAN_REASON_DEAUTH_LEAVING, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct cfg80211_mgmt_registration {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) u32 nlportid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) int match_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) __le16 frame_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) bool multicast_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) u8 match[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static void cfg80211_mgmt_registrations_update(struct wireless_dev *wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct wireless_dev *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) struct cfg80211_mgmt_registration *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct mgmt_frame_regs upd = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) spin_lock_bh(&rdev->mgmt_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (!wdev->mgmt_registrations_need_update) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) spin_unlock_bh(&rdev->mgmt_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) list_for_each_entry_rcu(tmp, &rdev->wiphy.wdev_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) list_for_each_entry(reg, &tmp->mgmt_registrations, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) u32 mask = BIT(le16_to_cpu(reg->frame_type) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) u32 mcast_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (reg->multicast_rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) mcast_mask = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) upd.global_stypes |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) upd.global_mcast_stypes |= mcast_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (tmp == wdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) upd.interface_stypes |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) upd.interface_mcast_stypes |= mcast_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) wdev->mgmt_registrations_need_update = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) spin_unlock_bh(&rdev->mgmt_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) rdev_update_mgmt_frame_registrations(rdev, wdev, &upd);
^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) void cfg80211_mgmt_registrations_update_wk(struct work_struct *wk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) struct wireless_dev *wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) rdev = container_of(wk, struct cfg80211_registered_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) mgmt_registrations_update_wk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) cfg80211_mgmt_registrations_update(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) u16 frame_type, const u8 *match_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) int match_len, bool multicast_rx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) struct cfg80211_mgmt_registration *reg, *nreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) u16 mgmt_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) bool update_multicast = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (!wdev->wiphy->mgmt_stypes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) NL_SET_ERR_MSG(extack, "frame type not management");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return -EINVAL;
^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) if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) NL_SET_ERR_MSG(extack, "Invalid frame type");
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) NL_SET_ERR_MSG(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) "Registration to specific type not supported");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * To support Pre Association Security Negotiation (PASN), registration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * for authentication frames should be supported. However, as some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * versions of the user space daemons wrongly register to all types of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * authentication frames (which might result in unexpected behavior)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * allow such registration if the request is for a specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * authentication algorithm number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (wdev->iftype == NL80211_IFTYPE_STATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) (frame_type & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_AUTH &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) !(match_data && match_len >= 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) NL_SET_ERR_MSG(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) "Authentication algorithm number required");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (!nreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) spin_lock_bh(&rdev->mgmt_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) int mlen = min(match_len, reg->match_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (frame_type != le16_to_cpu(reg->frame_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (memcmp(reg->match, match_data, mlen) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (reg->multicast_rx != multicast_rx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) update_multicast = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) reg->multicast_rx = multicast_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) NL_SET_ERR_MSG(extack, "Match already configured");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) err = -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) break;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (update_multicast) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) kfree(nreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) memcpy(nreg->match, match_data, match_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) nreg->match_len = match_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) nreg->nlportid = snd_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) nreg->frame_type = cpu_to_le16(frame_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) nreg->wdev = wdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) nreg->multicast_rx = multicast_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) list_add(&nreg->list, &wdev->mgmt_registrations);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) wdev->mgmt_registrations_need_update = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) spin_unlock_bh(&rdev->mgmt_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) cfg80211_mgmt_registrations_update(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) kfree(nreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) spin_unlock_bh(&rdev->mgmt_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct cfg80211_mgmt_registration *reg, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) spin_lock_bh(&rdev->mgmt_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (reg->nlportid != nlportid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) list_del(®->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) kfree(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) wdev->mgmt_registrations_need_update = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) schedule_work(&rdev->mgmt_registrations_update_wk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) spin_unlock_bh(&rdev->mgmt_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (nlportid && rdev->crit_proto_nlportid == nlportid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) rdev->crit_proto_nlportid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) rdev_crit_proto_stop(rdev, wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (nlportid == wdev->ap_unexpected_nlportid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) wdev->ap_unexpected_nlportid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct cfg80211_mgmt_registration *reg, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) spin_lock_bh(&rdev->mgmt_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) list_del(®->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) kfree(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) wdev->mgmt_registrations_need_update = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) spin_unlock_bh(&rdev->mgmt_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) cfg80211_mgmt_registrations_update(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct wireless_dev *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) struct cfg80211_mgmt_tx_params *params, u64 *cookie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) const struct ieee80211_mgmt *mgmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) u16 stype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (!wdev->wiphy->mgmt_stypes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (!rdev->ops->mgmt_tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (params->len < 24 + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) mgmt = (const struct ieee80211_mgmt *)params->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (!ieee80211_is_mgmt(mgmt->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].tx & BIT(stype >> 4)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (ieee80211_is_action(mgmt->frame_control) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) wdev_lock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) switch (wdev->iftype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) case NL80211_IFTYPE_ADHOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) case NL80211_IFTYPE_P2P_CLIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (!wdev->current_bss) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) err = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (!ether_addr_equal(wdev->current_bss->pub.bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) mgmt->bssid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) err = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) break;
^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) * check for IBSS DA must be done by driver as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * cfg80211 doesn't track the stations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (wdev->iftype == NL80211_IFTYPE_ADHOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) /* for station, check that DA is the AP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (!ether_addr_equal(wdev->current_bss->pub.bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) mgmt->da)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) err = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) case NL80211_IFTYPE_P2P_GO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) case NL80211_IFTYPE_AP_VLAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (!ether_addr_equal(mgmt->bssid, wdev_address(wdev)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) case NL80211_IFTYPE_MESH_POINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (!ether_addr_equal(mgmt->sa, mgmt->bssid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * check for mesh DA must be done by driver as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * cfg80211 doesn't track the stations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) case NL80211_IFTYPE_P2P_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * fall through, P2P device only supports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * public action frames
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) case NL80211_IFTYPE_NAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) wdev_unlock(wdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (!ether_addr_equal(mgmt->sa, wdev_address(wdev))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) /* Allow random TA to be used with Public Action frames if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) * driver has indicated support for this. Otherwise, only allow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) * the local address to be used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (!ieee80211_is_action(mgmt->frame_control) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) mgmt->u.action.category != WLAN_CATEGORY_PUBLIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (!wdev->current_bss &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) !wiphy_ext_feature_isset(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) &rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (wdev->current_bss &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) !wiphy_ext_feature_isset(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) &rdev->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /* Transmit the Action frame as requested by user space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return rdev_mgmt_tx(rdev, wdev, params, cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) bool cfg80211_rx_mgmt_khz(struct wireless_dev *wdev, int freq, int sig_dbm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) const u8 *buf, size_t len, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct cfg80211_mgmt_registration *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) const struct ieee80211_txrx_stypes *stypes =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) &wiphy->mgmt_stypes[wdev->iftype];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) struct ieee80211_mgmt *mgmt = (void *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) const u8 *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) int data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) bool result = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) __le16 ftype = mgmt->frame_control &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) u16 stype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) trace_cfg80211_rx_mgmt(wdev, freq, sig_dbm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (!(stypes->rx & BIT(stype))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) trace_cfg80211_return_bool(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) data = buf + ieee80211_hdrlen(mgmt->frame_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) data_len = len - ieee80211_hdrlen(mgmt->frame_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) spin_lock_bh(&rdev->mgmt_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) if (reg->frame_type != ftype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (reg->match_len > data_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (memcmp(reg->match, data, reg->match_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) /* found match! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /* Indicate the received Action frame to user space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (nl80211_send_mgmt(rdev, wdev, reg->nlportid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) freq, sig_dbm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) buf, len, flags, GFP_ATOMIC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) result = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) spin_unlock_bh(&rdev->mgmt_registrations_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) trace_cfg80211_return_bool(result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) EXPORT_SYMBOL(cfg80211_rx_mgmt_khz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) cancel_delayed_work(&rdev->dfs_update_channels_wk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) void cfg80211_dfs_channels_update_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct delayed_work *delayed_work = to_delayed_work(work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct cfg80211_registered_device *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) struct cfg80211_chan_def chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct ieee80211_channel *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) struct wiphy *wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) bool check_again = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) unsigned long timeout, next_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) unsigned long time_dfs_update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) enum nl80211_radar_event radar_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) int bandid, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) rdev = container_of(delayed_work, struct cfg80211_registered_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) dfs_update_channels_wk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) wiphy = &rdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) for (bandid = 0; bandid < NUM_NL80211_BANDS; bandid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) sband = wiphy->bands[bandid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) for (i = 0; i < sband->n_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) c = &sband->channels[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (!(c->flags & IEEE80211_CHAN_RADAR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (c->dfs_state != NL80211_DFS_UNAVAILABLE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) c->dfs_state != NL80211_DFS_AVAILABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (c->dfs_state == NL80211_DFS_UNAVAILABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) time_dfs_update = IEEE80211_DFS_MIN_NOP_TIME_MS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) radar_event = NL80211_RADAR_NOP_FINISHED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (regulatory_pre_cac_allowed(wiphy) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) cfg80211_any_wiphy_oper_chan(wiphy, c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) time_dfs_update = REG_PRE_CAC_EXPIRY_GRACE_MS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) radar_event = NL80211_RADAR_PRE_CAC_EXPIRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) timeout = c->dfs_state_entered +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) msecs_to_jiffies(time_dfs_update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (time_after_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) c->dfs_state = NL80211_DFS_USABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) c->dfs_state_entered = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) cfg80211_chandef_create(&chandef, c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) NL80211_CHAN_NO_HT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) nl80211_radar_notify(rdev, &chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) radar_event, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) regulatory_propagate_dfs_state(wiphy, &chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) c->dfs_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) radar_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (!check_again)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) next_time = timeout - jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) next_time = min(next_time, timeout - jiffies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) check_again = true;
^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) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) /* reschedule if there are other channels waiting to be cleared again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (check_again)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) next_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) void cfg80211_radar_event(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct cfg80211_chan_def *chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) trace_cfg80211_radar_event(wiphy, chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) /* only set the chandef supplied channel to unavailable, in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) * case the radar is detected on only one of multiple channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * spanned by the chandef.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) cfg80211_sched_dfs_chan_update(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) memcpy(&rdev->radar_chandef, chandef, sizeof(struct cfg80211_chan_def));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) EXPORT_SYMBOL(cfg80211_radar_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) void cfg80211_cac_event(struct net_device *netdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) const struct cfg80211_chan_def *chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) enum nl80211_radar_event event, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) struct wireless_dev *wdev = netdev->ieee80211_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) struct wiphy *wiphy = wdev->wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) trace_cfg80211_cac_event(netdev, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (WARN_ON(!wdev->cac_started && event != NL80211_RADAR_CAC_STARTED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (WARN_ON(!wdev->chandef.chan))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) case NL80211_RADAR_CAC_FINISHED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) timeout = wdev->cac_start_time +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) msecs_to_jiffies(wdev->cac_time_ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) WARN_ON(!time_after_eq(jiffies, timeout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) memcpy(&rdev->cac_done_chandef, chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) sizeof(struct cfg80211_chan_def));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) cfg80211_sched_dfs_chan_update(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) case NL80211_RADAR_CAC_ABORTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) wdev->cac_started = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) case NL80211_RADAR_CAC_STARTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) wdev->cac_started = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) nl80211_radar_notify(rdev, chandef, event, netdev, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) EXPORT_SYMBOL(cfg80211_cac_event);