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        };
 461
 462        ASSERT_WDEV_LOCK(wdev);
 463
 464        if (local_state_change) {
 465                if (wdev->current_bss &&
 466                    ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
 467                        cfg80211_unhold_bss(wdev->current_bss);
 468                        cfg80211_put_bss(&wdev->current_bss->pub);
 469                        wdev->current_bss = NULL;
 470                }
 471
 472                return 0;
 473        }
 474
 475        return rdev->ops->deauth(&rdev->wiphy, dev, &req);
 476}
 477
 478int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
 479                         struct net_device *dev, const u8 *bssid,
 480                         const u8 *ie, int ie_len, u16 reason,
 481                         bool local_state_change)
 482{
 483        struct wireless_dev *wdev = dev->ieee80211_ptr;
 484        int err;
 485
 486        wdev_lock(wdev);
 487        err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason,
 488                                     local_state_change);
 489        wdev_unlock(wdev);
 490
 491        return err;
 492}
 493
 494static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
 495                                    struct net_device *dev, const u8 *bssid,
 496                                    const u8 *ie, int ie_len, u16 reason,
 497                                    bool local_state_change)
 498{
 499        struct wireless_dev *wdev = dev->ieee80211_ptr;
 500        struct cfg80211_disassoc_request req;
 501
 502        ASSERT_WDEV_LOCK(wdev);
 503
 504        if (wdev->sme_state != CFG80211_SME_CONNECTED)
 505                return -ENOTCONN;
 506
 507        if (WARN_ON(!wdev->current_bss))
 508                return -ENOTCONN;
 509
 510        memset(&req, 0, sizeof(req));
 511        req.reason_code = reason;
 512        req.local_state_change = local_state_change;
 513        req.ie = ie;
 514        req.ie_len = ie_len;
 515        if (ether_addr_equal(wdev->current_bss->pub.bssid, bssid))
 516                req.bss = &wdev->current_bss->pub;
 517        else
 518                return -ENOTCONN;
 519
 520        return rdev->ops->disassoc(&rdev->wiphy, dev, &req);
 521}
 522
 523int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
 524                           struct net_device *dev, const u8 *bssid,
 525                           const u8 *ie, int ie_len, u16 reason,
 526                           bool local_state_change)
 527{
 528        struct wireless_dev *wdev = dev->ieee80211_ptr;
 529        int err;
 530
 531        wdev_lock(wdev);
 532        err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason,
 533                                       local_state_change);
 534        wdev_unlock(wdev);
 535
 536        return err;
 537}
 538
 539void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
 540                        struct net_device *dev)
 541{
 542        struct wireless_dev *wdev = dev->ieee80211_ptr;
 543        struct cfg80211_deauth_request req;
 544        u8 bssid[ETH_ALEN];
 545
 546        ASSERT_WDEV_LOCK(wdev);
 547
 548        if (!rdev->ops->deauth)
 549                return;
 550
 551        memset(&req, 0, sizeof(req));
 552        req.reason_code = WLAN_REASON_DEAUTH_LEAVING;
 553        req.ie = NULL;
 554        req.ie_len = 0;
 555
 556        if (!wdev->current_bss)
 557                return;
 558
 559        memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
 560        req.bssid = bssid;
 561        rdev->ops->deauth(&rdev->wiphy, dev, &req);
 562
 563        if (wdev->current_bss) {
 564                cfg80211_unhold_bss(wdev->current_bss);
 565                cfg80211_put_bss(&wdev->current_bss->pub);
 566                wdev->current_bss = NULL;
 567        }
 568}
 569
 570void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
 571                               struct ieee80211_channel *chan,
 572                               enum nl80211_channel_type channel_type,
 573                               unsigned int duration, gfp_t gfp)
 574{
 575        struct wiphy *wiphy = wdev->wiphy;
 576        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 577
 578        nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, channel_type,
 579                                       duration, gfp);
 580}
 581EXPORT_SYMBOL(cfg80211_ready_on_channel);
 582
 583void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
 584                                        struct ieee80211_channel *chan,
 585                                        enum nl80211_channel_type channel_type,
 586                                        gfp_t gfp)
 587{
 588        struct wiphy *wiphy = wdev->wiphy;
 589        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 590
 591        nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan,
 592                                              channel_type, gfp);
 593}
 594EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
 595
 596void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
 597                      struct station_info *sinfo, gfp_t gfp)
 598{
 599        struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
 600        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 601
 602        nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp);
 603}
 604EXPORT_SYMBOL(cfg80211_new_sta);
 605
 606void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
 607{
 608        struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
 609        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 610
 611        nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp);
 612}
 613EXPORT_SYMBOL(cfg80211_del_sta);
 614
 615struct cfg80211_mgmt_registration {
 616        struct list_head list;
 617
 618        u32 nlpid;
 619
 620        int match_len;
 621
 622        __le16 frame_type;
 623
 624        u8 match[];
 625};
 626
 627int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
 628                                u16 frame_type, const u8 *match_data,
 629                                int match_len)
 630{
 631        struct wiphy *wiphy = wdev->wiphy;
 632        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 633        struct cfg80211_mgmt_registration *reg, *nreg;
 634        int err = 0;
 635        u16 mgmt_type;
 636
 637        if (!wdev->wiphy->mgmt_stypes)
 638                return -EOPNOTSUPP;
 639
 640        if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT)
 641                return -EINVAL;
 642
 643        if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
 644                return -EINVAL;
 645
 646        mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
 647        if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type)))
 648                return -EINVAL;
 649
 650        nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
 651        if (!nreg)
 652                return -ENOMEM;
 653
 654        spin_lock_bh(&wdev->mgmt_registrations_lock);
 655
 656        list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
 657                int mlen = min(match_len, reg->match_len);
 658
 659                if (frame_type != le16_to_cpu(reg->frame_type))
 660                        continue;
 661
 662                if (memcmp(reg->match, match_data, mlen) == 0) {
 663                        err = -EALREADY;
 664                        break;
 665                }
 666        }
 667
 668        if (err) {
 669                kfree(nreg);
 670                goto out;
 671        }
 672
 673        memcpy(nreg->match, match_data, match_len);
 674        nreg->match_len = match_len;
 675        nreg->nlpid = snd_pid;
 676        nreg->frame_type = cpu_to_le16(frame_type);
 677        list_add(&nreg->list, &wdev->mgmt_registrations);
 678
 679        if (rdev->ops->mgmt_frame_register)
 680                rdev->ops->mgmt_frame_register(wiphy, wdev, frame_type, true);
 681
 682 out:
 683        spin_unlock_bh(&wdev->mgmt_registrations_lock);
 684
 685        return err;
 686}
 687
 688void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid)
 689{
 690        struct wiphy *wiphy = wdev->wiphy;
 691        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 692        struct cfg80211_mgmt_registration *reg, *tmp;
 693
 694        spin_lock_bh(&wdev->mgmt_registrations_lock);
 695
 696        list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
 697                if (reg->nlpid != nlpid)
 698                        continue;
 699
 700                if (rdev->ops->mgmt_frame_register) {
 701                        u16 frame_type = le16_to_cpu(reg->frame_type);
 702
 703                        rdev->ops->mgmt_frame_register(wiphy, wdev,
 704                                                       frame_type, false);
 705                }
 706
 707                list_del(&reg->list);
 708                kfree(reg);
 709        }
 710
 711        spin_unlock_bh(&wdev->mgmt_registrations_lock);
 712
 713        if (nlpid == wdev->ap_unexpected_nlpid)
 714                wdev->ap_unexpected_nlpid = 0;
 715}
 716
 717void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
 718{
 719        struct cfg80211_mgmt_registration *reg, *tmp;
 720
 721        spin_lock_bh(&wdev->mgmt_registrations_lock);
 722
 723        list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
 724                list_del(&reg->list);
 725                kfree(reg);
 726        }
 727
 728        spin_unlock_bh(&wdev->mgmt_registrations_lock);
 729}
 730
 731int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
 732                          struct wireless_dev *wdev,
 733                          struct ieee80211_channel *chan, bool offchan,
 734                          enum nl80211_channel_type channel_type,
 735                          bool channel_type_valid, unsigned int wait,
 736                          const u8 *buf, size_t len, bool no_cck,
 737                          bool dont_wait_for_ack, u64 *cookie)
 738{
 739        struct net_device *dev = wdev->netdev;
 740        const struct ieee80211_mgmt *mgmt;
 741        u16 stype;
 742
 743        if (!wdev->wiphy->mgmt_stypes)
 744                return -EOPNOTSUPP;
 745
 746        if (!rdev->ops->mgmt_tx)
 747                return -EOPNOTSUPP;
 748
 749        if (len < 24 + 1)
 750                return -EINVAL;
 751
 752        mgmt = (const struct ieee80211_mgmt *) buf;
 753
 754        if (!ieee80211_is_mgmt(mgmt->frame_control))
 755                return -EINVAL;
 756
 757        stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
 758        if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].tx & BIT(stype >> 4)))
 759                return -EINVAL;
 760
 761        if (ieee80211_is_action(mgmt->frame_control) &&
 762            mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
 763                int err = 0;
 764
 765                wdev_lock(wdev);
 766
 767                switch (wdev->iftype) {
 768                case NL80211_IFTYPE_ADHOC:
 769                case NL80211_IFTYPE_STATION:
 770                case NL80211_IFTYPE_P2P_CLIENT:
 771                        if (!wdev->current_bss) {
 772                                err = -ENOTCONN;
 773                                break;
 774                        }
 775
 776                        if (!ether_addr_equal(wdev->current_bss->pub.bssid,
 777                                              mgmt->bssid)) {
 778                                err = -ENOTCONN;
 779                                break;
 780                        }
 781
 782                        /*
 783                         * check for IBSS DA must be done by driver as
 784                         * cfg80211 doesn't track the stations
 785                         */
 786                        if (wdev->iftype == NL80211_IFTYPE_ADHOC)
 787                                break;
 788
 789                        /* for station, check that DA is the AP */
 790                        if (!ether_addr_equal(wdev->current_bss->pub.bssid,
 791                                              mgmt->da)) {
 792                                err = -ENOTCONN;
 793                                break;
 794                        }
 795                        break;
 796                case NL80211_IFTYPE_AP:
 797                case NL80211_IFTYPE_P2P_GO:
 798                case NL80211_IFTYPE_AP_VLAN:
 799                        if (!ether_addr_equal(mgmt->bssid, dev->dev_addr))
 800                                err = -EINVAL;
 801                        break;
 802                case NL80211_IFTYPE_MESH_POINT:
 803                        if (!ether_addr_equal(mgmt->sa, mgmt->bssid)) {
 804                                err = -EINVAL;
 805                                break;
 806                        }
 807                        /*
 808                         * check for mesh DA must be done by driver as
 809                         * cfg80211 doesn't track the stations
 810                         */
 811                        break;
 812                default:
 813                        err = -EOPNOTSUPP;
 814                        break;
 815                }
 816                wdev_unlock(wdev);
 817
 818                if (err)
 819                        return err;
 820        }
 821
 822        if (!ether_addr_equal(mgmt->sa, dev->dev_addr))
 823                return -EINVAL;
 824
 825        /* Transmit the Action frame as requested by user space */
 826        return rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
 827                                  channel_type, channel_type_valid,
 828                                  wait, buf, len, no_cck, dont_wait_for_ack,
 829                                  cookie);
 830}
 831
 832bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
 833                      const u8 *buf, size_t len, gfp_t gfp)
 834{
 835        struct wiphy *wiphy = wdev->wiphy;
 836        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 837        struct cfg80211_mgmt_registration *reg;
 838        const struct ieee80211_txrx_stypes *stypes =
 839                &wiphy->mgmt_stypes[wdev->iftype];
 840        struct ieee80211_mgmt *mgmt = (void *)buf;
 841        const u8 *data;
 842        int data_len;
 843        bool result = false;
 844        __le16 ftype = mgmt->frame_control &
 845                cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
 846        u16 stype;
 847
 848        stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4;
 849
 850        if (!(stypes->rx & BIT(stype)))
 851                return false;
 852
 853        data = buf + ieee80211_hdrlen(mgmt->frame_control);
 854        data_len = len - ieee80211_hdrlen(mgmt->frame_control);
 855
 856        spin_lock_bh(&wdev->mgmt_registrations_lock);
 857
 858        list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
 859                if (reg->frame_type != ftype)
 860                        continue;
 861
 862                if (reg->match_len > data_len)
 863                        continue;
 864
 865                if (memcmp(reg->match, data, reg->match_len))
 866                        continue;
 867
 868                /* found match! */
 869
 870                /* Indicate the received Action frame to user space */
 871                if (nl80211_send_mgmt(rdev, wdev, reg->nlpid,
 872                                      freq, sig_mbm,
 873                                      buf, len, gfp))
 874                        continue;
 875
 876                result = true;
 877                break;
 878        }
 879
 880        spin_unlock_bh(&wdev->mgmt_registrations_lock);
 881
 882        return result;
 883}
 884EXPORT_SYMBOL(cfg80211_rx_mgmt);
 885
 886void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
 887                             const u8 *buf, size_t len, bool ack, gfp_t gfp)
 888{
 889        struct wiphy *wiphy = wdev->wiphy;
 890        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 891
 892        /* Indicate TX status of the Action frame to user space */
 893        nl80211_send_mgmt_tx_status(rdev, wdev, cookie, buf, len, ack, gfp);
 894}
 895EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
 896
 897void cfg80211_cqm_rssi_notify(struct net_device *dev,
 898                              enum nl80211_cqm_rssi_threshold_event rssi_event,
 899                              gfp_t gfp)
 900{
 901        struct wireless_dev *wdev = dev->ieee80211_ptr;
 902        struct wiphy *wiphy = wdev->wiphy;
 903        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 904
 905        /* Indicate roaming trigger event to user space */
 906        nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp);
 907}
 908EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
 909
 910void cfg80211_cqm_pktloss_notify(struct net_device *dev,
 911                                 const u8 *peer, u32 num_packets, gfp_t gfp)
 912{
 913        struct wireless_dev *wdev = dev->ieee80211_ptr;
 914        struct wiphy *wiphy = wdev->wiphy;
 915        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 916
 917        /* Indicate roaming trigger event to user space */
 918        nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp);
 919}
 920EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
 921
 922void cfg80211_cqm_txe_notify(struct net_device *dev,
 923                             const u8 *peer, u32 num_packets,
 924                             u32 rate, u32 intvl, gfp_t gfp)
 925{
 926        struct wireless_dev *wdev = dev->ieee80211_ptr;
 927        struct wiphy *wiphy = wdev->wiphy;
 928        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 929
 930        nl80211_send_cqm_txe_notify(rdev, dev, peer, num_packets,
 931                                    rate, intvl, gfp);
 932}
 933EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
 934
 935void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
 936                               const u8 *replay_ctr, gfp_t gfp)
 937{
 938        struct wireless_dev *wdev = dev->ieee80211_ptr;
 939        struct wiphy *wiphy = wdev->wiphy;
 940        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 941
 942        nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
 943}
 944EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
 945
 946void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
 947                                     const u8 *bssid, bool preauth, gfp_t gfp)
 948{
 949        struct wireless_dev *wdev = dev->ieee80211_ptr;
 950        struct wiphy *wiphy = wdev->wiphy;
 951        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 952
 953        nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
 954}
 955EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
 956
 957void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
 958                               enum nl80211_channel_type type)
 959{
 960        struct wireless_dev *wdev = dev->ieee80211_ptr;
 961        struct wiphy *wiphy = wdev->wiphy;
 962        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 963        struct ieee80211_channel *chan;
 964
 965        wdev_lock(wdev);
 966
 967        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
 968                    wdev->iftype != NL80211_IFTYPE_P2P_GO))
 969                goto out;
 970
 971        chan = rdev_freq_to_chan(rdev, freq, type);
 972        if (WARN_ON(!chan))
 973                goto out;
 974
 975        wdev->channel = chan;
 976        nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL);
 977out:
 978        wdev_unlock(wdev);
 979        return;
 980}
 981EXPORT_SYMBOL(cfg80211_ch_switch_notify);
 982
 983bool cfg80211_rx_spurious_frame(struct net_device *dev,
 984                                const u8 *addr, gfp_t gfp)
 985{
 986        struct wireless_dev *wdev = dev->ieee80211_ptr;
 987
 988        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
 989                    wdev->iftype != NL80211_IFTYPE_P2P_GO))
 990                return false;
 991
 992        return nl80211_unexpected_frame(dev, addr, gfp);
 993}
 994EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
 995
 996bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
 997                                        const u8 *addr, gfp_t gfp)
 998{
 999        struct wireless_dev *wdev = dev->ieee80211_ptr;
1000
1001        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
1002                    wdev->iftype != NL80211_IFTYPE_P2P_GO &&
1003                    wdev->iftype != NL80211_IFTYPE_AP_VLAN))
1004                return false;
1005
1006        return nl80211_unexpected_4addr_frame(dev, addr, gfp);
1007}
1008EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
1009
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.