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