root/net/wireless/mlme.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cfg80211_rx_assoc_resp
  2. cfg80211_process_auth
  3. cfg80211_process_deauth
  4. cfg80211_process_disassoc
  5. cfg80211_rx_mlme_mgmt
  6. cfg80211_auth_timeout
  7. cfg80211_assoc_timeout
  8. cfg80211_abandon_assoc
  9. cfg80211_tx_mlme_mgmt
  10. cfg80211_michael_mic_failure
  11. cfg80211_mlme_auth
  12. cfg80211_oper_and_ht_capa
  13. cfg80211_oper_and_vht_capa
  14. cfg80211_mlme_assoc
  15. cfg80211_mlme_deauth
  16. cfg80211_mlme_disassoc
  17. cfg80211_mlme_down
  18. cfg80211_process_mlme_unregistrations
  19. cfg80211_mlme_unreg_wk
  20. cfg80211_mlme_register_mgmt
  21. cfg80211_mlme_unregister_socket
  22. cfg80211_mlme_purge_registrations
  23. cfg80211_mlme_mgmt_tx
  24. cfg80211_rx_mgmt
  25. cfg80211_sched_dfs_chan_update
  26. cfg80211_dfs_channels_update_work
  27. cfg80211_radar_event
  28. cfg80211_cac_event

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

/* [<][>][^][v][top][bottom][index][help] */