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
 609void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
 610                          enum nl80211_connect_failed_reason reason,
 611                          gfp_t gfp)
 612{
 613        struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
 614        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 615
 616        nl80211_send_conn_failed_event(rdev, dev, mac_addr, reason, gfp);
 617}
 618EXPORT_SYMBOL(cfg80211_conn_failed);
 619
 620struct cfg80211_mgmt_registration {
 621        struct list_head list;
 622
 623        u32 nlportid;
 624
 625        int match_len;
 626
 627        __le16 frame_type;
 628
 629        u8 match[];
 630};
 631
 632int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
 633                                u16 frame_type, const u8 *match_data,
 634                                int match_len)
 635{
 636        struct wiphy *wiphy = wdev->wiphy;
 637        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 638        struct cfg80211_mgmt_registration *reg, *nreg;
 639        int err = 0;
 640        u16 mgmt_type;
 641
 642        if (!wdev->wiphy->mgmt_stypes)
 643                return -EOPNOTSUPP;
 644
 645        if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT)
 646                return -EINVAL;
 647
 648        if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
 649                return -EINVAL;
 650
 651        mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
 652        if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type)))
 653                return -EINVAL;
 654
 655        nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
 656        if (!nreg)
 657                return -ENOMEM;
 658
 659        spin_lock_bh(&wdev->mgmt_registrations_lock);
 660
 661        list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
 662                int mlen = min(match_len, reg->match_len);
 663
 664                if (frame_type != le16_to_cpu(reg->frame_type))
 665                        continue;
 666
 667                if (memcmp(reg->match, match_data, mlen) == 0) {
 668                        err = -EALREADY;
 669                        break;
 670                }
 671        }
 672
 673        if (err) {
 674                kfree(nreg);
 675                goto out;
 676        }
 677
 678        memcpy(nreg->match, match_data, match_len);
 679        nreg->match_len = match_len;
 680        nreg->nlportid = snd_portid;
 681        nreg->frame_type = cpu_to_le16(frame_type);
 682        list_add(&nreg->list, &wdev->mgmt_registrations);
 683
 684        if (rdev->ops->mgmt_frame_register)
 685                rdev->ops->mgmt_frame_register(wiphy, wdev, frame_type, true);
 686
 687 out:
 688        spin_unlock_bh(&wdev->mgmt_registrations_lock);
 689
 690        return err;
 691}
 692
 693void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
 694{
 695        struct wiphy *wiphy = wdev->wiphy;
 696        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 697        struct cfg80211_mgmt_registration *reg, *tmp;
 698
 699        spin_lock_bh(&wdev->mgmt_registrations_lock);
 700
 701        list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
 702                if (reg->nlportid != nlportid)
 703                        continue;
 704
 705                if (rdev->ops->mgmt_frame_register) {
 706                        u16 frame_type = le16_to_cpu(reg->frame_type);
 707
 708                        rdev->ops->mgmt_frame_register(wiphy, wdev,
 709                                                       frame_type, false);
 710                }
 711
 712                list_del(&reg->list);
 713                kfree(reg);
 714        }
 715
 716        spin_unlock_bh(&wdev->mgmt_registrations_lock);
 717
 718        if (nlportid == wdev->ap_unexpected_nlportid)
 719                wdev->ap_unexpected_nlportid = 0;
 720}
 721
 722void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
 723{
 724        struct cfg80211_mgmt_registration *reg, *tmp;
 725
 726        spin_lock_bh(&wdev->mgmt_registrations_lock);
 727
 728        list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
 729                list_del(&reg->list);
 730                kfree(reg);
 731        }
 732
 733        spin_unlock_bh(&wdev->mgmt_registrations_lock);
 734}
 735
 736int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
 737                          struct wireless_dev *wdev,
 738                          struct ieee80211_channel *chan, bool offchan,
 739                          enum nl80211_channel_type channel_type,
 740                          bool channel_type_valid, unsigned int wait,
 741                          const u8 *buf, size_t len, bool no_cck,
 742                          bool dont_wait_for_ack, u64 *cookie)
 743{
 744        const struct ieee80211_mgmt *mgmt;
 745        u16 stype;
 746
 747        if (!wdev->wiphy->mgmt_stypes)
 748                return -EOPNOTSUPP;
 749
 750        if (!rdev->ops->mgmt_tx)
 751                return -EOPNOTSUPP;
 752
 753        if (len < 24 + 1)
 754                return -EINVAL;
 755
 756        mgmt = (const struct ieee80211_mgmt *) buf;
 757
 758        if (!ieee80211_is_mgmt(mgmt->frame_control))
 759                return -EINVAL;
 760
 761        stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
 762        if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].tx & BIT(stype >> 4)))
 763                return -EINVAL;
 764
 765        if (ieee80211_is_action(mgmt->frame_control) &&
 766            mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
 767                int err = 0;
 768
 769                wdev_lock(wdev);
 770
 771                switch (wdev->iftype) {
 772                case NL80211_IFTYPE_ADHOC:
 773                case NL80211_IFTYPE_STATION:
 774                case NL80211_IFTYPE_P2P_CLIENT:
 775                        if (!wdev->current_bss) {
 776                                err = -ENOTCONN;
 777                                break;
 778                        }
 779
 780                        if (!ether_addr_equal(wdev->current_bss->pub.bssid,
 781                                              mgmt->bssid)) {
 782                                err = -ENOTCONN;
 783                                break;
 784                        }
 785
 786                        /*
 787                         * check for IBSS DA must be done by driver as
 788                         * cfg80211 doesn't track the stations
 789                         */
 790                        if (wdev->iftype == NL80211_IFTYPE_ADHOC)
 791                                break;
 792
 793                        /* for station, check that DA is the AP */
 794                        if (!ether_addr_equal(wdev->current_bss->pub.bssid,
 795                                              mgmt->da)) {
 796                                err = -ENOTCONN;
 797                                break;
 798                        }
 799                        break;
 800                case NL80211_IFTYPE_AP:
 801                case NL80211_IFTYPE_P2P_GO:
 802                case NL80211_IFTYPE_AP_VLAN:
 803                        if (!ether_addr_equal(mgmt->bssid, wdev_address(wdev)))
 804                                err = -EINVAL;
 805                        break;
 806                case NL80211_IFTYPE_MESH_POINT:
 807                        if (!ether_addr_equal(mgmt->sa, mgmt->bssid)) {
 808                                err = -EINVAL;
 809                                break;
 810                        }
 811                        /*
 812                         * check for mesh DA must be done by driver as
 813                         * cfg80211 doesn't track the stations
 814                         */
 815                        break;
 816                case NL80211_IFTYPE_P2P_DEVICE:
 817                        /*
 818                         * fall through, P2P device only supports
 819                         * public action frames
 820                         */
 821                default:
 822                        err = -EOPNOTSUPP;
 823                        break;
 824                }
 825                wdev_unlock(wdev);
 826
 827                if (err)
 828                        return err;
 829        }
 830
 831        if (!ether_addr_equal(mgmt->sa, wdev_address(wdev)))
 832                return -EINVAL;
 833
 834        /* Transmit the Action frame as requested by user space */
 835        return rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
 836                                  channel_type, channel_type_valid,
 837                                  wait, buf, len, no_cck, dont_wait_for_ack,
 838                                  cookie);
 839}
 840
 841bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
 842                      const u8 *buf, size_t len, gfp_t gfp)
 843{
 844        struct wiphy *wiphy = wdev->wiphy;
 845        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 846        struct cfg80211_mgmt_registration *reg;
 847        const struct ieee80211_txrx_stypes *stypes =
 848                &wiphy->mgmt_stypes[wdev->iftype];
 849        struct ieee80211_mgmt *mgmt = (void *)buf;
 850        const u8 *data;
 851        int data_len;
 852        bool result = false;
 853        __le16 ftype = mgmt->frame_control &
 854                cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
 855        u16 stype;
 856
 857        stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4;
 858
 859        if (!(stypes->rx & BIT(stype)))
 860                return false;
 861
 862        data = buf + ieee80211_hdrlen(mgmt->frame_control);
 863        data_len = len - ieee80211_hdrlen(mgmt->frame_control);
 864
 865        spin_lock_bh(&wdev->mgmt_registrations_lock);
 866
 867        list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
 868                if (reg->frame_type != ftype)
 869                        continue;
 870
 871                if (reg->match_len > data_len)
 872                        continue;
 873
 874                if (memcmp(reg->match, data, reg->match_len))
 875                        continue;
 876
 877                /* found match! */
 878
 879                /* Indicate the received Action frame to user space */
 880                if (nl80211_send_mgmt(rdev, wdev, reg->nlportid,
 881                                      freq, sig_mbm,
 882                                      buf, len, gfp))
 883                        continue;
 884
 885                result = true;
 886                break;
 887        }
 888
 889        spin_unlock_bh(&wdev->mgmt_registrations_lock);
 890
 891        return result;
 892}
 893EXPORT_SYMBOL(cfg80211_rx_mgmt);
 894
 895void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
 896                             const u8 *buf, size_t len, bool ack, gfp_t gfp)
 897{
 898        struct wiphy *wiphy = wdev->wiphy;
 899        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 900
 901        /* Indicate TX status of the Action frame to user space */
 902        nl80211_send_mgmt_tx_status(rdev, wdev, cookie, buf, len, ack, gfp);
 903}
 904EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
 905
 906void cfg80211_cqm_rssi_notify(struct net_device *dev,
 907                              enum nl80211_cqm_rssi_threshold_event rssi_event,
 908                              gfp_t gfp)
 909{
 910        struct wireless_dev *wdev = dev->ieee80211_ptr;
 911        struct wiphy *wiphy = wdev->wiphy;
 912        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 913
 914        /* Indicate roaming trigger event to user space */
 915        nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp);
 916}
 917EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
 918
 919void cfg80211_cqm_pktloss_notify(struct net_device *dev,
 920                                 const u8 *peer, u32 num_packets, gfp_t gfp)
 921{
 922        struct wireless_dev *wdev = dev->ieee80211_ptr;
 923        struct wiphy *wiphy = wdev->wiphy;
 924        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 925
 926        /* Indicate roaming trigger event to user space */
 927        nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp);
 928}
 929EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
 930
 931void cfg80211_cqm_txe_notify(struct net_device *dev,
 932                             const u8 *peer, u32 num_packets,
 933                             u32 rate, u32 intvl, gfp_t gfp)
 934{
 935        struct wireless_dev *wdev = dev->ieee80211_ptr;
 936        struct wiphy *wiphy = wdev->wiphy;
 937        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 938
 939        nl80211_send_cqm_txe_notify(rdev, dev, peer, num_packets,
 940                                    rate, intvl, gfp);
 941}
 942EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
 943
 944void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
 945                               const u8 *replay_ctr, gfp_t gfp)
 946{
 947        struct wireless_dev *wdev = dev->ieee80211_ptr;
 948        struct wiphy *wiphy = wdev->wiphy;
 949        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 950
 951        nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
 952}
 953EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
 954
 955void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
 956                                     const u8 *bssid, bool preauth, gfp_t gfp)
 957{
 958        struct wireless_dev *wdev = dev->ieee80211_ptr;
 959        struct wiphy *wiphy = wdev->wiphy;
 960        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 961
 962        nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
 963}
 964EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
 965
 966void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
 967                               enum nl80211_channel_type type)
 968{
 969        struct wireless_dev *wdev = dev->ieee80211_ptr;
 970        struct wiphy *wiphy = wdev->wiphy;
 971        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 972        struct ieee80211_channel *chan;
 973
 974        wdev_lock(wdev);
 975
 976        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
 977                    wdev->iftype != NL80211_IFTYPE_P2P_GO))
 978                goto out;
 979
 980        chan = rdev_freq_to_chan(rdev, freq, type);
 981        if (WARN_ON(!chan))
 982                goto out;
 983
 984        wdev->channel = chan;
 985        nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL);
 986out:
 987        wdev_unlock(wdev);
 988        return;
 989}
 990EXPORT_SYMBOL(cfg80211_ch_switch_notify);
 991
 992bool cfg80211_rx_spurious_frame(struct net_device *dev,
 993                                const u8 *addr, gfp_t gfp)
 994{
 995        struct wireless_dev *wdev = dev->ieee80211_ptr;
 996
 997        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
 998                    wdev->iftype != NL80211_IFTYPE_P2P_GO))
 999                return false;
1000
1001        return nl80211_unexpected_frame(dev, addr, gfp);
1002}
1003EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
1004
1005bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
1006                                        const u8 *addr, gfp_t gfp)
1007{
1008        struct wireless_dev *wdev = dev->ieee80211_ptr;
1009
1010        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
1011                    wdev->iftype != NL80211_IFTYPE_P2P_GO &&
1012                    wdev->iftype != NL80211_IFTYPE_AP_VLAN))
1013                return false;
1014
1015        return nl80211_unexpected_4addr_frame(dev, addr, gfp);
1016}
1017EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
1018
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.