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
  19void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
  20{
  21        struct wireless_dev *wdev = dev->ieee80211_ptr;
  22        struct wiphy *wiphy = wdev->wiphy;
  23        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  24
  25        wdev_lock(wdev);
  26
  27        nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
  28        cfg80211_sme_rx_auth(dev, buf, len);
  29
  30        wdev_unlock(wdev);
  31}
  32EXPORT_SYMBOL(cfg80211_send_rx_auth);
  33
  34void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
  35                            const u8 *buf, size_t len)
  36{
  37        u16 status_code;
  38        struct wireless_dev *wdev = dev->ieee80211_ptr;
  39        struct wiphy *wiphy = wdev->wiphy;
  40        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  41        struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  42        u8 *ie = mgmt->u.assoc_resp.variable;
  43        int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
  44
  45        wdev_lock(wdev);
  46
  47        status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
  48
  49        /*
  50         * This is a bit of a hack, we don't notify userspace of
  51         * a (re-)association reply if we tried to send a reassoc
  52         * and got a reject -- we only try again with an assoc
  53         * frame instead of reassoc.
  54         */
  55        if (status_code != WLAN_STATUS_SUCCESS && wdev->conn &&
  56            cfg80211_sme_failed_reassoc(wdev)) {
  57                cfg80211_put_bss(bss);
  58                goto out;
  59        }
  60
  61        nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
  62
  63        if (status_code != WLAN_STATUS_SUCCESS && wdev->conn) {
  64                cfg80211_sme_failed_assoc(wdev);
  65                /*
  66                 * do not call connect_result() now because the
  67                 * sme will schedule work that does it later.
  68                 */
  69                cfg80211_put_bss(bss);
  70                goto out;
  71        }
  72
  73        if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) {
  74                /*
  75                 * This is for the userspace SME, the CONNECTING
  76                 * state will be changed to CONNECTED by
  77                 * __cfg80211_connect_result() below.
  78                 */
  79                wdev->sme_state = CFG80211_SME_CONNECTING;
  80        }
  81
  82        /* this consumes the bss reference */
  83        __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
  84                                  status_code,
  85                                  status_code == WLAN_STATUS_SUCCESS, bss);
  86 out:
  87        wdev_unlock(wdev);
  88}
  89EXPORT_SYMBOL(cfg80211_send_rx_assoc);
  90
  91void __cfg80211_send_deauth(struct net_device *dev,
  92                                   const u8 *buf, size_t len)
  93{
  94        struct wireless_dev *wdev = dev->ieee80211_ptr;
  95        struct wiphy *wiphy = wdev->wiphy;
  96        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  97        struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
  98        const u8 *bssid = mgmt->bssid;
  99        bool was_current = false;
 100
 101        ASSERT_WDEV_LOCK(wdev);
 102
 103        if (wdev->current_bss &&
 104            ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
 105                cfg80211_unhold_bss(wdev->current_bss);
 106                cfg80211_put_bss(&wdev->current_bss->pub);
 107                wdev->current_bss = NULL;
 108                was_current = true;
 109        }
 110
 111        nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
 112
 113        if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) {
 114                u16 reason_code;
 115                bool from_ap;
 116
 117                reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
 118
 119                from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr);
 120                __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
 121        } else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
 122                __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
 123                                          WLAN_STATUS_UNSPECIFIED_FAILURE,
 124                                          false, NULL);
 125        }
 126}
 127EXPORT_SYMBOL(__cfg80211_send_deauth);
 128
 129void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
 130{
 131        struct wireless_dev *wdev = dev->ieee80211_ptr;
 132
 133        wdev_lock(wdev);
 134        __cfg80211_send_deauth(dev, buf, len);
 135        wdev_unlock(wdev);
 136}
 137EXPORT_SYMBOL(cfg80211_send_deauth);
 138
 139void __cfg80211_send_disassoc(struct net_device *dev,
 140                                     const u8 *buf, size_t len)
 141{
 142        struct wireless_dev *wdev = dev->ieee80211_ptr;
 143        struct wiphy *wiphy = wdev->wiphy;
 144        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 145        struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
 146        const u8 *bssid = mgmt->bssid;
 147        u16 reason_code;
 148        bool from_ap;
 149
 150        ASSERT_WDEV_LOCK(wdev);
 151
 152        nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
 153
 154        if (wdev->sme_state != CFG80211_SME_CONNECTED)
 155                return;
 156
 157        if (wdev->current_bss &&
 158            ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
 159                cfg80211_sme_disassoc(dev, wdev->current_bss);
 160                cfg80211_unhold_bss(wdev->current_bss);
 161                cfg80211_put_bss(&wdev->current_bss->pub);
 162                wdev->current_bss = NULL;
 163        } else
 164                WARN_ON(1);
 165
 166
 167        reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
 168
 169        from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr);
 170        __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
 171}
 172EXPORT_SYMBOL(__cfg80211_send_disassoc);
 173
 174void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
 175{
 176        struct wireless_dev *wdev = dev->ieee80211_ptr;
 177
 178        wdev_lock(wdev);
 179        __cfg80211_send_disassoc(dev, buf, len);
 180        wdev_unlock(wdev);
 181}
 182EXPORT_SYMBOL(cfg80211_send_disassoc);
 183
 184void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf,
 185                                 size_t len)
 186{
 187        struct wireless_dev *wdev = dev->ieee80211_ptr;
 188        struct wiphy *wiphy = wdev->wiphy;
 189        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 190
 191        nl80211_send_unprot_deauth(rdev, dev, buf, len, GFP_ATOMIC);
 192}
 193EXPORT_SYMBOL(cfg80211_send_unprot_deauth);
 194
 195void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf,
 196                                   size_t len)
 197{
 198        struct wireless_dev *wdev = dev->ieee80211_ptr;
 199        struct wiphy *wiphy = wdev->wiphy;
 200        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 201
 202        nl80211_send_unprot_disassoc(rdev, dev, buf, len, GFP_ATOMIC);
 203}
 204EXPORT_SYMBOL(cfg80211_send_unprot_disassoc);
 205
 206void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
 207{
 208        struct wireless_dev *wdev = dev->ieee80211_ptr;
 209        struct wiphy *wiphy = wdev->wiphy;
 210        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 211
 212        wdev_lock(wdev);
 213
 214        nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
 215        if (wdev->sme_state == CFG80211_SME_CONNECTING)
 216                __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
 217                                          WLAN_STATUS_UNSPECIFIED_FAILURE,
 218                                          false, NULL);
 219
 220        wdev_unlock(wdev);
 221}
 222EXPORT_SYMBOL(cfg80211_send_auth_timeout);
 223
 224void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
 225{
 226        struct wireless_dev *wdev = dev->ieee80211_ptr;
 227        struct wiphy *wiphy = wdev->wiphy;
 228        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 229
 230        wdev_lock(wdev);
 231
 232        nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
 233        if (wdev->sme_state == CFG80211_SME_CONNECTING)
 234                __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
 235                                          WLAN_STATUS_UNSPECIFIED_FAILURE,
 236                                          false, NULL);
 237
 238        wdev_unlock(wdev);
 239}
 240EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
 241
 242void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
 243                                  enum nl80211_key_type key_type, int key_id,
 244                                  const u8 *tsc, gfp_t gfp)
 245{
 246        struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
 247        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 248#ifdef CONFIG_CFG80211_WEXT
 249        union iwreq_data wrqu;
 250        char *buf = kmalloc(128, gfp);
 251
 252        if (buf) {
 253                sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
 254                        "keyid=%d %scast addr=%pM)", key_id,
 255                        key_type == NL80211_KEYTYPE_GROUP ? "broad" : "uni",
 256                        addr);
 257                memset(&wrqu, 0, sizeof(wrqu));
 258                wrqu.data.length = strlen(buf);
 259                wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
 260                kfree(buf);
 261        }
 262#endif
 263
 264        nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
 265}
 266EXPORT_SYMBOL(cfg80211_michael_mic_failure);
 267
 268/* some MLME handling for userspace SME */
 269int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
 270                         struct net_device *dev,
 271                         struct ieee80211_channel *chan,
 272                         enum nl80211_auth_type auth_type,
 273                         const u8 *bssid,
 274                         const u8 *ssid, int ssid_len,
 275                         const u8 *ie, int ie_len,
 276                         const u8 *key, int key_len, int key_idx)
 277{
 278        struct wireless_dev *wdev = dev->ieee80211_ptr;
 279        struct cfg80211_auth_request req;
 280        int err;
 281
 282        ASSERT_WDEV_LOCK(wdev);
 283
 284        if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
 285                if (!key || !key_len || key_idx < 0 || key_idx > 4)
 286                        return -EINVAL;
 287
 288        if (wdev->current_bss &&
 289            ether_addr_equal(bssid, wdev->current_bss->pub.bssid))
 290                return -EALREADY;
 291
 292        memset(&req, 0, sizeof(req));
 293
 294        req.ie = ie;
 295        req.ie_len = ie_len;
 296        req.auth_type = auth_type;
 297        req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
 298                                   WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
 299        req.key = key;
 300        req.key_len = key_len;
 301        req.key_idx = key_idx;
 302        if (!req.bss)
 303                return -ENOENT;
 304
 305        err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel,
 306                                    CHAN_MODE_SHARED);
 307        if (err)
 308                goto out;
 309
 310        err = rdev->ops->auth(&rdev->wiphy, dev, &req);
 311
 312out:
 313        cfg80211_put_bss(req.bss);
 314        return err;
 315}
 316
 317int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
 318                       struct net_device *dev, struct ieee80211_channel *chan,
 319                       enum nl80211_auth_type auth_type, const u8 *bssid,
 320                       const u8 *ssid, int ssid_len,
 321                       const u8 *ie, int ie_len,
 322                       const u8 *key, int key_len, int key_idx)
 323{
 324        int err;
 325
 326        mutex_lock(&rdev->devlist_mtx);
 327        wdev_lock(dev->ieee80211_ptr);
 328        err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
 329                                   ssid, ssid_len, ie, ie_len,
 330                                   key, key_len, key_idx);
 331        wdev_unlock(dev->ieee80211_ptr);
 332        mutex_unlock(&rdev->devlist_mtx);
 333
 334        return err;
 335}
 336
 337/*  Do a logical ht_capa &= ht_capa_mask.  */
 338void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
 339                               const struct ieee80211_ht_cap *ht_capa_mask)
 340{
 341        int i;
 342        u8 *p1, *p2;
 343        if (!ht_capa_mask) {
 344                memset(ht_capa, 0, sizeof(*ht_capa));
 345                return;
 346        }
 347
 348        p1 = (u8*)(ht_capa);
 349        p2 = (u8*)(ht_capa_mask);
 350        for (i = 0; i<sizeof(*ht_capa); i++)
 351                p1[i] &= p2[i];
 352}
 353
 354int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
 355                          struct net_device *dev,
 356                          struct ieee80211_channel *chan,
 357                          const u8 *bssid, const u8 *prev_bssid,
 358                          const u8 *ssid, int ssid_len,
 359                          const u8 *ie, int ie_len, bool use_mfp,
 360                          struct cfg80211_crypto_settings *crypt,
 361                          u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
 362                          struct ieee80211_ht_cap *ht_capa_mask)
 363{
 364        struct wireless_dev *wdev = dev->ieee80211_ptr;
 365        struct cfg80211_assoc_request req;
 366        int err;
 367        bool was_connected = false;
 368
 369        ASSERT_WDEV_LOCK(wdev);
 370
 371        memset(&req, 0, sizeof(req));
 372
 373        if (wdev->current_bss && prev_bssid &&
 374            ether_addr_equal(wdev->current_bss->pub.bssid, prev_bssid)) {
 375                /*
 376                 * Trying to reassociate: Allow this to proceed and let the old
 377                 * association to be dropped when the new one is completed.
 378                 */
 379                if (wdev->sme_state == CFG80211_SME_CONNECTED) {
 380                        was_connected = true;
 381                        wdev->sme_state = CFG80211_SME_CONNECTING;
 382                }
 383        } else if (wdev->current_bss)
 384                return -EALREADY;
 385
 386        req.ie = ie;
 387        req.ie_len = ie_len;
 388        memcpy(&req.crypto, crypt, sizeof(req.crypto));
 389        req.use_mfp = use_mfp;
 390        req.prev_bssid = prev_bssid;
 391        req.flags = assoc_flags;
 392        if (ht_capa)
 393                memcpy(&req.ht_capa, ht_capa, sizeof(req.ht_capa));
 394        if (ht_capa_mask)
 395                memcpy(&req.ht_capa_mask, ht_capa_mask,
 396                       sizeof(req.ht_capa_mask));
 397        cfg80211_oper_and_ht_capa(&req.ht_capa_mask,
 398                                  rdev->wiphy.ht_capa_mod_mask);
 399
 400        req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
 401                                   WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
 402        if (!req.bss) {
 403                if (was_connected)
 404                        wdev->sme_state = CFG80211_SME_CONNECTED;
 405                return -ENOENT;
 406        }
 407
 408        err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel,
 409                                    CHAN_MODE_SHARED);
 410        if (err)
 411                goto out;
 412
 413        err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
 414
 415out:
 416        if (err) {
 417                if (was_connected)
 418                        wdev->sme_state = CFG80211_SME_CONNECTED;
 419                cfg80211_put_bss(req.bss);
 420        }
 421
 422        return err;
 423}
 424
 425int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
 426                        struct net_device *dev,
 427                        struct ieee80211_channel *chan,
 428                        const u8 *bssid, const u8 *prev_bssid,
 429                        const u8 *ssid, int ssid_len,
 430                        const u8 *ie, int ie_len, bool use_mfp,
 431                        struct cfg80211_crypto_settings *crypt,
 432                        u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
 433                        struct ieee80211_ht_cap *ht_capa_mask)
 434{
 435        struct wireless_dev *wdev = dev->ieee80211_ptr;
 436        int err;
 437
 438        mutex_lock(&rdev->devlist_mtx);
 439        wdev_lock(wdev);
 440        err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
 441                                    ssid, ssid_len, ie, ie_len, use_mfp, crypt,
 442                                    assoc_flags, ht_capa, ht_capa_mask);
 443        wdev_unlock(wdev);
 444        mutex_unlock(&rdev->devlist_mtx);
 445
 446        return err;
 447}
 448
 449int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
 450                           struct net_device *dev, const u8 *bssid,
 451                           const u8 *ie, int ie_len, u16 reason,
 452                           bool local_state_change)
 453{
 454        struct wireless_dev *wdev = dev->ieee80211_ptr;
 455        struct cfg80211_deauth_request req = {
 456                .bssid = bssid,
 457                .reason_code = reason,
 458                .ie = ie,
 459                .ie_len = ie_len,
 460                .local_state_change = local_state_change,
 461        };
 462
 463        ASSERT_WDEV_LOCK(wdev);
 464
 465        if (local_state_change && (!wdev->current_bss ||
 466            !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
 467                return 0;
 468
 469        return rdev->ops->deauth(&rdev->wiphy, dev, &req);
 470}
 471
 472int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
 473                         struct net_device *dev, const u8 *bssid,
 474                         const u8 *ie, int ie_len, u16 reason,
 475                         bool local_state_change)
 476{
 477        struct wireless_dev *wdev = dev->ieee80211_ptr;
 478        int err;
 479
 480        wdev_lock(wdev);
 481        err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason,
 482                                     local_state_change);
 483        wdev_unlock(wdev);
 484
 485        return err;
 486}
 487
 488static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
 489                                    struct net_device *dev, const u8 *bssid,
 490                                    const u8 *ie, int ie_len, u16 reason,
 491                                    bool local_state_change)
 492{
 493        struct wireless_dev *wdev = dev->ieee80211_ptr;
 494        struct cfg80211_disassoc_request req;
 495
 496        ASSERT_WDEV_LOCK(wdev);
 497
 498        if (wdev->sme_state != CFG80211_SME_CONNECTED)
 499                return -ENOTCONN;
 500
 501        if (WARN_ON(!wdev->current_bss))
 502                return -ENOTCONN;
 503
 504        memset(&req, 0, sizeof(req));
 505        req.reason_code = reason;
 506        req.local_state_change = local_state_change;
 507        req.ie = ie;
 508        req.ie_len = ie_len;
 509        if (ether_addr_equal(wdev->current_bss->pub.bssid, bssid))
 510                req.bss = &wdev->current_bss->pub;
 511        else
 512                return -ENOTCONN;
 513
 514        return rdev->ops->disassoc(&rdev->wiphy, dev, &req);
 515}
 516
 517int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
 518                           struct net_device *dev, const u8 *bssid,
 519                           const u8 *ie, int ie_len, u16 reason,
 520                           bool local_state_change)
 521{
 522        struct wireless_dev *wdev = dev->ieee80211_ptr;
 523        int err;
 524
 525        wdev_lock(wdev);
 526        err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason,
 527                                       local_state_change);
 528        wdev_unlock(wdev);
 529
 530        return err;
 531}
 532
 533void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
 534                        struct net_device *dev)
 535{
 536        struct wireless_dev *wdev = dev->ieee80211_ptr;
 537        struct cfg80211_deauth_request req;
 538        u8 bssid[ETH_ALEN];
 539
 540        ASSERT_WDEV_LOCK(wdev);
 541
 542        if (!rdev->ops->deauth)
 543                return;
 544
 545        memset(&req, 0, sizeof(req));
 546        req.reason_code = WLAN_REASON_DEAUTH_LEAVING;
 547        req.ie = NULL;
 548        req.ie_len = 0;
 549
 550        if (!wdev->current_bss)
 551                return;
 552
 553        memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
 554        req.bssid = bssid;
 555        rdev->ops->deauth(&rdev->wiphy, dev, &req);
 556
 557        if (wdev->current_bss) {
 558                cfg80211_unhold_bss(wdev->current_bss);
 559                cfg80211_put_bss(&wdev->current_bss->pub);
 560                wdev->current_bss = NULL;
 561        }
 562}
 563
 564void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
 565                               struct ieee80211_channel *chan,
 566                               enum nl80211_channel_type channel_type,
 567                               unsigned int duration, gfp_t gfp)
 568{
 569        struct wiphy *wiphy = wdev->wiphy;
 570        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 571
 572        nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, channel_type,
 573                                       duration, gfp);
 574}
 575EXPORT_SYMBOL(cfg80211_ready_on_channel);
 576
 577void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
 578                                        struct ieee80211_channel *chan,
 579                                        enum nl80211_channel_type channel_type,
 580                                        gfp_t gfp)
 581{
 582        struct wiphy *wiphy = wdev->wiphy;
 583        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 584
 585        nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan,
 586                                              channel_type, gfp);
 587}
 588EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
 589
 590void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
 591                      struct station_info *sinfo, gfp_t gfp)
 592{
 593        struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
 594        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 595
 596        nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp);
 597}
 598EXPORT_SYMBOL(cfg80211_new_sta);
 599
 600void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
 601{
 602        struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
 603        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 604
 605        nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp);
 606}
 607EXPORT_SYMBOL(cfg80211_del_sta);
 608
 609struct cfg80211_mgmt_registration {
 610        struct list_head list;
 611
 612        u32 nlpid;
 613
 614        int match_len;
 615
 616        __le16 frame_type;
 617
 618        u8 match[];
 619};
 620
 621int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
 622                                u16 frame_type, const u8 *match_data,
 623                                int match_len)
 624{
 625        struct wiphy *wiphy = wdev->wiphy;
 626        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 627        struct cfg80211_mgmt_registration *reg, *nreg;
 628        int err = 0;
 629        u16 mgmt_type;
 630
 631        if (!wdev->wiphy->mgmt_stypes)
 632                return -EOPNOTSUPP;
 633
 634        if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT)
 635                return -EINVAL;
 636
 637        if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
 638                return -EINVAL;
 639
 640        mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
 641        if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type)))
 642                return -EINVAL;
 643
 644        nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
 645        if (!nreg)
 646                return -ENOMEM;
 647
 648        spin_lock_bh(&wdev->mgmt_registrations_lock);
 649
 650        list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
 651                int mlen = min(match_len, reg->match_len);
 652
 653                if (frame_type != le16_to_cpu(reg->frame_type))
 654                        continue;
 655
 656                if (memcmp(reg->match, match_data, mlen) == 0) {
 657                        err = -EALREADY;
 658                        break;
 659                }
 660        }
 661
 662        if (err) {
 663                kfree(nreg);
 664                goto out;
 665        }
 666
 667        memcpy(nreg->match, match_data, match_len);
 668        nreg->match_len = match_len;
 669        nreg->nlpid = snd_pid;
 670        nreg->frame_type = cpu_to_le16(frame_type);
 671        list_add(&nreg->list, &wdev->mgmt_registrations);
 672
 673        if (rdev->ops->mgmt_frame_register)
 674                rdev->ops->mgmt_frame_register(wiphy, wdev, frame_type, true);
 675
 676 out:
 677        spin_unlock_bh(&wdev->mgmt_registrations_lock);
 678
 679        return err;
 680}
 681
 682void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid)
 683{
 684        struct wiphy *wiphy = wdev->wiphy;
 685        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 686        struct cfg80211_mgmt_registration *reg, *tmp;
 687
 688        spin_lock_bh(&wdev->mgmt_registrations_lock);
 689
 690        list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
 691                if (reg->nlpid != nlpid)
 692                        continue;
 693
 694                if (rdev->ops->mgmt_frame_register) {
 695                        u16 frame_type = le16_to_cpu(reg->frame_type);
 696
 697                        rdev->ops->mgmt_frame_register(wiphy, wdev,
 698                                                       frame_type, false);
 699                }
 700
 701                list_del(&reg->list);
 702                kfree(reg);
 703        }
 704
 705        spin_unlock_bh(&wdev->mgmt_registrations_lock);
 706
 707        if (nlpid == wdev->ap_unexpected_nlpid)
 708                wdev->ap_unexpected_nlpid = 0;
 709}
 710
 711void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
 712{
 713        struct cfg80211_mgmt_registration *reg, *tmp;
 714
 715        spin_lock_bh(&wdev->mgmt_registrations_lock);
 716
 717        list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
 718                list_del(&reg->list);
 719                kfree(reg);
 720        }
 721
 722        spin_unlock_bh(&wdev->mgmt_registrations_lock);
 723}
 724
 725int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
 726                          struct wireless_dev *wdev,
 727                          struct ieee80211_channel *chan, bool offchan,
 728                          enum nl80211_channel_type channel_type,
 729                          bool channel_type_valid, unsigned int wait,
 730                          const u8 *buf, size_t len, bool no_cck,
 731                          bool dont_wait_for_ack, u64 *cookie)
 732{
 733        struct net_device *dev = wdev->netdev;
 734        const struct ieee80211_mgmt *mgmt;
 735        u16 stype;
 736
 737        if (!wdev->wiphy->mgmt_stypes)
 738                return -EOPNOTSUPP;
 739
 740        if (!rdev->ops->mgmt_tx)
 741                return -EOPNOTSUPP;
 742
 743        if (len < 24 + 1)
 744                return -EINVAL;
 745
 746        mgmt = (const struct ieee80211_mgmt *) buf;
 747
 748        if (!ieee80211_is_mgmt(mgmt->frame_control))
 749                return -EINVAL;
 750
 751        stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
 752        if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].tx & BIT(stype >> 4)))
 753                return -EINVAL;
 754
 755        if (ieee80211_is_action(mgmt->frame_control) &&
 756            mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
 757                int err = 0;
 758
 759                wdev_lock(wdev);
 760
 761                switch (wdev->iftype) {
 762                case NL80211_IFTYPE_ADHOC:
 763                case NL80211_IFTYPE_STATION:
 764                case NL80211_IFTYPE_P2P_CLIENT:
 765                        if (!wdev->current_bss) {
 766                                err = -ENOTCONN;
 767                                break;
 768                        }
 769
 770                        if (!ether_addr_equal(wdev->current_bss->pub.bssid,
 771                                              mgmt->bssid)) {
 772                                err = -ENOTCONN;
 773                                break;
 774                        }
 775
 776                        /*
 777                         * check for IBSS DA must be done by driver as
 778                         * cfg80211 doesn't track the stations
 779                         */
 780                        if (wdev->iftype == NL80211_IFTYPE_ADHOC)
 781                                break;
 782
 783                        /* for station, check that DA is the AP */
 784                        if (!ether_addr_equal(wdev->current_bss->pub.bssid,
 785                                              mgmt->da)) {
 786                                err = -ENOTCONN;
 787                                break;
 788                        }
 789                        break;
 790                case NL80211_IFTYPE_AP:
 791                case NL80211_IFTYPE_P2P_GO:
 792                case NL80211_IFTYPE_AP_VLAN:
 793                        if (!ether_addr_equal(mgmt->bssid, dev->dev_addr))
 794                                err = -EINVAL;
 795                        break;
 796                case NL80211_IFTYPE_MESH_POINT:
 797                        if (!ether_addr_equal(mgmt->sa, mgmt->bssid)) {
 798                                err = -EINVAL;
 799                                break;
 800                        }
 801                        /*
 802                         * check for mesh DA must be done by driver as
 803                         * cfg80211 doesn't track the stations
 804                         */
 805                        break;
 806                default:
 807                        err = -EOPNOTSUPP;
 808                        break;
 809                }
 810                wdev_unlock(wdev);
 811
 812                if (err)
 813                        return err;
 814        }
 815
 816        if (!ether_addr_equal(mgmt->sa, dev->dev_addr))
 817                return -EINVAL;
 818
 819        /* Transmit the Action frame as requested by user space */
 820        return rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
 821                                  channel_type, channel_type_valid,
 822                                  wait, buf, len, no_cck, dont_wait_for_ack,
 823                                  cookie);
 824}
 825
 826bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
 827                      const u8 *buf, size_t len, gfp_t gfp)
 828{
 829        struct wiphy *wiphy = wdev->wiphy;
 830        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 831        struct cfg80211_mgmt_registration *reg;
 832        const struct ieee80211_txrx_stypes *stypes =
 833                &wiphy->mgmt_stypes[wdev->iftype];
 834        struct ieee80211_mgmt *mgmt = (void *)buf;
 835        const u8 *data;
 836        int data_len;
 837        bool result = false;
 838        __le16 ftype = mgmt->frame_control &
 839                cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
 840        u16 stype;
 841
 842        stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4;
 843
 844        if (!(stypes->rx & BIT(stype)))
 845                return false;
 846
 847        data = buf + ieee80211_hdrlen(mgmt->frame_control);
 848        data_len = len - ieee80211_hdrlen(mgmt->frame_control);
 849
 850        spin_lock_bh(&wdev->mgmt_registrations_lock);
 851
 852        list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
 853                if (reg->frame_type != ftype)
 854                        continue;
 855
 856                if (reg->match_len > data_len)
 857                        continue;
 858
 859                if (memcmp(reg->match, data, reg->match_len))
 860                        continue;
 861
 862                /* found match! */
 863
 864                /* Indicate the received Action frame to user space */
 865                if (nl80211_send_mgmt(rdev, wdev, reg->nlpid,
 866                                      freq, sig_mbm,
 867                                      buf, len, gfp))
 868                        continue;
 869
 870                result = true;
 871                break;
 872        }
 873
 874        spin_unlock_bh(&wdev->mgmt_registrations_lock);
 875
 876        return result;
 877}
 878EXPORT_SYMBOL(cfg80211_rx_mgmt);
 879
 880void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
 881                             const u8 *buf, size_t len, bool ack, gfp_t gfp)
 882{
 883        struct wiphy *wiphy = wdev->wiphy;
 884        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 885
 886        /* Indicate TX status of the Action frame to user space */
 887        nl80211_send_mgmt_tx_status(rdev, wdev, cookie, buf, len, ack, gfp);
 888}
 889EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
 890
 891void cfg80211_cqm_rssi_notify(struct net_device *dev,
 892                              enum nl80211_cqm_rssi_threshold_event rssi_event,
 893                              gfp_t gfp)
 894{
 895        struct wireless_dev *wdev = dev->ieee80211_ptr;
 896        struct wiphy *wiphy = wdev->wiphy;
 897        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 898
 899        /* Indicate roaming trigger event to user space */
 900        nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp);
 901}
 902EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
 903
 904void cfg80211_cqm_pktloss_notify(struct net_device *dev,
 905                                 const u8 *peer, u32 num_packets, gfp_t gfp)
 906{
 907        struct wireless_dev *wdev = dev->ieee80211_ptr;
 908        struct wiphy *wiphy = wdev->wiphy;
 909        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 910
 911        /* Indicate roaming trigger event to user space */
 912        nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp);
 913}
 914EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
 915
 916void cfg80211_cqm_txe_notify(struct net_device *dev,
 917                             const u8 *peer, u32 num_packets,
 918                             u32 rate, u32 intvl, gfp_t gfp)
 919{
 920        struct wireless_dev *wdev = dev->ieee80211_ptr;
 921        struct wiphy *wiphy = wdev->wiphy;
 922        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 923
 924        nl80211_send_cqm_txe_notify(rdev, dev, peer, num_packets,
 925                                    rate, intvl, gfp);
 926}
 927EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
 928
 929void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
 930                               const u8 *replay_ctr, gfp_t gfp)
 931{
 932        struct wireless_dev *wdev = dev->ieee80211_ptr;
 933        struct wiphy *wiphy = wdev->wiphy;
 934        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 935
 936        nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
 937}
 938EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
 939
 940void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
 941                                     const u8 *bssid, bool preauth, gfp_t gfp)
 942{
 943        struct wireless_dev *wdev = dev->ieee80211_ptr;
 944        struct wiphy *wiphy = wdev->wiphy;
 945        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 946
 947        nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
 948}
 949EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
 950
 951void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
 952                               enum nl80211_channel_type type)
 953{
 954        struct wireless_dev *wdev = dev->ieee80211_ptr;
 955        struct wiphy *wiphy = wdev->wiphy;
 956        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 957        struct ieee80211_channel *chan;
 958
 959        wdev_lock(wdev);
 960
 961        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
 962                    wdev->iftype != NL80211_IFTYPE_P2P_GO))
 963                goto out;
 964
 965        chan = rdev_freq_to_chan(rdev, freq, type);
 966        if (WARN_ON(!chan))
 967                goto out;
 968
 969        wdev->channel = chan;
 970        nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL);
 971out:
 972        wdev_unlock(wdev);
 973        return;
 974}
 975EXPORT_SYMBOL(cfg80211_ch_switch_notify);
 976
 977bool cfg80211_rx_spurious_frame(struct net_device *dev,
 978                                const u8 *addr, gfp_t gfp)
 979{
 980        struct wireless_dev *wdev = dev->ieee80211_ptr;
 981
 982        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
 983                    wdev->iftype != NL80211_IFTYPE_P2P_GO))
 984                return false;
 985
 986        return nl80211_unexpected_frame(dev, addr, gfp);
 987}
 988EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
 989
 990bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
 991                                        const u8 *addr, gfp_t gfp)
 992{
 993        struct wireless_dev *wdev = dev->ieee80211_ptr;
 994
 995        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
 996                    wdev->iftype != NL80211_IFTYPE_P2P_GO &&
 997                    wdev->iftype != NL80211_IFTYPE_AP_VLAN))
 998                return false;
 999
1000        return nl80211_unexpected_4addr_frame(dev, addr, gfp);
1001}
1002EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
1003
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.