linux/net/wireless/sme.c
<<
>>
Prefs
   1/*
   2 * SME code for cfg80211's connect emulation.
   3 *
   4 * Copyright 2009       Johannes Berg <johannes@sipsolutions.net>
   5 * Copyright (C) 2009   Intel Corporation. All rights reserved.
   6 */
   7
   8#include <linux/etherdevice.h>
   9#include <linux/if_arp.h>
  10#include <linux/slab.h>
  11#include <linux/workqueue.h>
  12#include <linux/wireless.h>
  13#include <linux/export.h>
  14#include <net/iw_handler.h>
  15#include <net/cfg80211.h>
  16#include <net/rtnetlink.h>
  17#include "nl80211.h"
  18#include "reg.h"
  19
  20struct cfg80211_conn {
  21        struct cfg80211_connect_params params;
  22        /* these are sub-states of the _CONNECTING sme_state */
  23        enum {
  24                CFG80211_CONN_IDLE,
  25                CFG80211_CONN_SCANNING,
  26                CFG80211_CONN_SCAN_AGAIN,
  27                CFG80211_CONN_AUTHENTICATE_NEXT,
  28                CFG80211_CONN_AUTHENTICATING,
  29                CFG80211_CONN_ASSOCIATE_NEXT,
  30                CFG80211_CONN_ASSOCIATING,
  31                CFG80211_CONN_DEAUTH_ASSOC_FAIL,
  32        } state;
  33        u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
  34        u8 *ie;
  35        size_t ie_len;
  36        bool auto_auth, prev_bssid_valid;
  37};
  38
  39static bool cfg80211_is_all_idle(void)
  40{
  41        struct cfg80211_registered_device *rdev;
  42        struct wireless_dev *wdev;
  43        bool is_all_idle = true;
  44
  45        mutex_lock(&cfg80211_mutex);
  46
  47        /*
  48         * All devices must be idle as otherwise if you are actively
  49         * scanning some new beacon hints could be learned and would
  50         * count as new regulatory hints.
  51         */
  52        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
  53                cfg80211_lock_rdev(rdev);
  54                list_for_each_entry(wdev, &rdev->wdev_list, list) {
  55                        wdev_lock(wdev);
  56                        if (wdev->sme_state != CFG80211_SME_IDLE)
  57                                is_all_idle = false;
  58                        wdev_unlock(wdev);
  59                }
  60                cfg80211_unlock_rdev(rdev);
  61        }
  62
  63        mutex_unlock(&cfg80211_mutex);
  64
  65        return is_all_idle;
  66}
  67
  68static void disconnect_work(struct work_struct *work)
  69{
  70        if (!cfg80211_is_all_idle())
  71                return;
  72
  73        regulatory_hint_disconnect();
  74}
  75
  76static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
  77
  78static int cfg80211_conn_scan(struct wireless_dev *wdev)
  79{
  80        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
  81        struct cfg80211_scan_request *request;
  82        int n_channels, err;
  83
  84        ASSERT_RTNL();
  85        ASSERT_RDEV_LOCK(rdev);
  86        ASSERT_WDEV_LOCK(wdev);
  87
  88        if (rdev->scan_req)
  89                return -EBUSY;
  90
  91        if (wdev->conn->params.channel) {
  92                n_channels = 1;
  93        } else {
  94                enum ieee80211_band band;
  95                n_channels = 0;
  96
  97                for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
  98                        if (!wdev->wiphy->bands[band])
  99                                continue;
 100                        n_channels += wdev->wiphy->bands[band]->n_channels;
 101                }
 102        }
 103        request = kzalloc(sizeof(*request) + sizeof(request->ssids[0]) +
 104                          sizeof(request->channels[0]) * n_channels,
 105                          GFP_KERNEL);
 106        if (!request)
 107                return -ENOMEM;
 108
 109        if (wdev->conn->params.channel)
 110                request->channels[0] = wdev->conn->params.channel;
 111        else {
 112                int i = 0, j;
 113                enum ieee80211_band band;
 114                struct ieee80211_supported_band *bands;
 115                struct ieee80211_channel *channel;
 116
 117                for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
 118                        bands = wdev->wiphy->bands[band];
 119                        if (!bands)
 120                                continue;
 121                        for (j = 0; j < bands->n_channels; j++) {
 122                                channel = &bands->channels[j];
 123                                if (channel->flags & IEEE80211_CHAN_DISABLED)
 124                                        continue;
 125                                request->channels[i++] = channel;
 126                        }
 127                        request->rates[band] = (1 << bands->n_bitrates) - 1;
 128                }
 129                n_channels = i;
 130        }
 131        request->n_channels = n_channels;
 132        request->ssids = (void *)&request->channels[n_channels];
 133        request->n_ssids = 1;
 134
 135        memcpy(request->ssids[0].ssid, wdev->conn->params.ssid,
 136                wdev->conn->params.ssid_len);
 137        request->ssids[0].ssid_len = wdev->conn->params.ssid_len;
 138
 139        request->wdev = wdev;
 140        request->wiphy = &rdev->wiphy;
 141
 142        rdev->scan_req = request;
 143
 144        err = rdev->ops->scan(wdev->wiphy, request);
 145        if (!err) {
 146                wdev->conn->state = CFG80211_CONN_SCANNING;
 147                nl80211_send_scan_start(rdev, wdev);
 148                dev_hold(wdev->netdev);
 149        } else {
 150                rdev->scan_req = NULL;
 151                kfree(request);
 152        }
 153        return err;
 154}
 155
 156static int cfg80211_conn_do_work(struct wireless_dev *wdev)
 157{
 158        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 159        struct cfg80211_connect_params *params;
 160        const u8 *prev_bssid = NULL;
 161        int err;
 162
 163        ASSERT_WDEV_LOCK(wdev);
 164
 165        if (!wdev->conn)
 166                return 0;
 167
 168        params = &wdev->conn->params;
 169
 170        switch (wdev->conn->state) {
 171        case CFG80211_CONN_SCAN_AGAIN:
 172                return cfg80211_conn_scan(wdev);
 173        case CFG80211_CONN_AUTHENTICATE_NEXT:
 174                BUG_ON(!rdev->ops->auth);
 175                wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
 176                return __cfg80211_mlme_auth(rdev, wdev->netdev,
 177                                            params->channel, params->auth_type,
 178                                            params->bssid,
 179                                            params->ssid, params->ssid_len,
 180                                            NULL, 0,
 181                                            params->key, params->key_len,
 182                                            params->key_idx);
 183        case CFG80211_CONN_ASSOCIATE_NEXT:
 184                BUG_ON(!rdev->ops->assoc);
 185                wdev->conn->state = CFG80211_CONN_ASSOCIATING;
 186                if (wdev->conn->prev_bssid_valid)
 187                        prev_bssid = wdev->conn->prev_bssid;
 188                err = __cfg80211_mlme_assoc(rdev, wdev->netdev,
 189                                            params->channel, params->bssid,
 190                                            prev_bssid,
 191                                            params->ssid, params->ssid_len,
 192                                            params->ie, params->ie_len,
 193                                            false, &params->crypto,
 194                                            params->flags, &params->ht_capa,
 195                                            &params->ht_capa_mask);
 196                if (err)
 197                        __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
 198                                               NULL, 0,
 199                                               WLAN_REASON_DEAUTH_LEAVING,
 200                                               false);
 201                return err;
 202        case CFG80211_CONN_DEAUTH_ASSOC_FAIL:
 203                __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
 204                                       NULL, 0,
 205                                       WLAN_REASON_DEAUTH_LEAVING, false);
 206                /* return an error so that we call __cfg80211_connect_result() */
 207                return -EINVAL;
 208        default:
 209                return 0;
 210        }
 211}
 212
 213void cfg80211_conn_work(struct work_struct *work)
 214{
 215        struct cfg80211_registered_device *rdev =
 216                container_of(work, struct cfg80211_registered_device, conn_work);
 217        struct wireless_dev *wdev;
 218        u8 bssid_buf[ETH_ALEN], *bssid = NULL;
 219
 220        rtnl_lock();
 221        cfg80211_lock_rdev(rdev);
 222        mutex_lock(&rdev->devlist_mtx);
 223
 224        list_for_each_entry(wdev, &rdev->wdev_list, list) {
 225                wdev_lock(wdev);
 226                if (!netif_running(wdev->netdev)) {
 227                        wdev_unlock(wdev);
 228                        continue;
 229                }
 230                if (wdev->sme_state != CFG80211_SME_CONNECTING) {
 231                        wdev_unlock(wdev);
 232                        continue;
 233                }
 234                if (wdev->conn->params.bssid) {
 235                        memcpy(bssid_buf, wdev->conn->params.bssid, ETH_ALEN);
 236                        bssid = bssid_buf;
 237                }
 238                if (cfg80211_conn_do_work(wdev))
 239                        __cfg80211_connect_result(
 240                                        wdev->netdev, bssid,
 241                                        NULL, 0, NULL, 0,
 242                                        WLAN_STATUS_UNSPECIFIED_FAILURE,
 243                                        false, NULL);
 244                wdev_unlock(wdev);
 245        }
 246
 247        mutex_unlock(&rdev->devlist_mtx);
 248        cfg80211_unlock_rdev(rdev);
 249        rtnl_unlock();
 250}
 251
 252static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev)
 253{
 254        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 255        struct cfg80211_bss *bss;
 256        u16 capa = WLAN_CAPABILITY_ESS;
 257
 258        ASSERT_WDEV_LOCK(wdev);
 259
 260        if (wdev->conn->params.privacy)
 261                capa |= WLAN_CAPABILITY_PRIVACY;
 262
 263        bss = cfg80211_get_bss(wdev->wiphy, wdev->conn->params.channel,
 264                               wdev->conn->params.bssid,
 265                               wdev->conn->params.ssid,
 266                               wdev->conn->params.ssid_len,
 267                               WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY,
 268                               capa);
 269        if (!bss)
 270                return NULL;
 271
 272        memcpy(wdev->conn->bssid, bss->bssid, ETH_ALEN);
 273        wdev->conn->params.bssid = wdev->conn->bssid;
 274        wdev->conn->params.channel = bss->channel;
 275        wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
 276        schedule_work(&rdev->conn_work);
 277
 278        return bss;
 279}
 280
 281static void __cfg80211_sme_scan_done(struct net_device *dev)
 282{
 283        struct wireless_dev *wdev = dev->ieee80211_ptr;
 284        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 285        struct cfg80211_bss *bss;
 286
 287        ASSERT_WDEV_LOCK(wdev);
 288
 289        if (wdev->sme_state != CFG80211_SME_CONNECTING)
 290                return;
 291
 292        if (!wdev->conn)
 293                return;
 294
 295        if (wdev->conn->state != CFG80211_CONN_SCANNING &&
 296            wdev->conn->state != CFG80211_CONN_SCAN_AGAIN)
 297                return;
 298
 299        bss = cfg80211_get_conn_bss(wdev);
 300        if (bss) {
 301                cfg80211_put_bss(bss);
 302        } else {
 303                /* not found */
 304                if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)
 305                        schedule_work(&rdev->conn_work);
 306                else
 307                        __cfg80211_connect_result(
 308                                        wdev->netdev,
 309                                        wdev->conn->params.bssid,
 310                                        NULL, 0, NULL, 0,
 311                                        WLAN_STATUS_UNSPECIFIED_FAILURE,
 312                                        false, NULL);
 313        }
 314}
 315
 316void cfg80211_sme_scan_done(struct net_device *dev)
 317{
 318        struct wireless_dev *wdev = dev->ieee80211_ptr;
 319
 320        mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
 321        wdev_lock(wdev);
 322        __cfg80211_sme_scan_done(dev);
 323        wdev_unlock(wdev);
 324        mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
 325}
 326
 327void cfg80211_sme_rx_auth(struct net_device *dev,
 328                          const u8 *buf, size_t len)
 329{
 330        struct wireless_dev *wdev = dev->ieee80211_ptr;
 331        struct wiphy *wiphy = wdev->wiphy;
 332        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 333        struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
 334        u16 status_code = le16_to_cpu(mgmt->u.auth.status_code);
 335
 336        ASSERT_WDEV_LOCK(wdev);
 337
 338        /* should only RX auth frames when connecting */
 339        if (wdev->sme_state != CFG80211_SME_CONNECTING)
 340                return;
 341
 342        if (WARN_ON(!wdev->conn))
 343                return;
 344
 345        if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
 346            wdev->conn->auto_auth &&
 347            wdev->conn->params.auth_type != NL80211_AUTHTYPE_NETWORK_EAP) {
 348                /* select automatically between only open, shared, leap */
 349                switch (wdev->conn->params.auth_type) {
 350                case NL80211_AUTHTYPE_OPEN_SYSTEM:
 351                        if (wdev->connect_keys)
 352                                wdev->conn->params.auth_type =
 353                                        NL80211_AUTHTYPE_SHARED_KEY;
 354                        else
 355                                wdev->conn->params.auth_type =
 356                                        NL80211_AUTHTYPE_NETWORK_EAP;
 357                        break;
 358                case NL80211_AUTHTYPE_SHARED_KEY:
 359                        wdev->conn->params.auth_type =
 360                                NL80211_AUTHTYPE_NETWORK_EAP;
 361                        break;
 362                default:
 363                        /* huh? */
 364                        wdev->conn->params.auth_type =
 365                                NL80211_AUTHTYPE_OPEN_SYSTEM;
 366                        break;
 367                }
 368                wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
 369                schedule_work(&rdev->conn_work);
 370        } else if (status_code != WLAN_STATUS_SUCCESS) {
 371                __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
 372                                          status_code, false, NULL);
 373        } else if (wdev->sme_state == CFG80211_SME_CONNECTING &&
 374                 wdev->conn->state == CFG80211_CONN_AUTHENTICATING) {
 375                wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
 376                schedule_work(&rdev->conn_work);
 377        }
 378}
 379
 380bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev)
 381{
 382        struct wiphy *wiphy = wdev->wiphy;
 383        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 384
 385        if (WARN_ON(!wdev->conn))
 386                return false;
 387
 388        if (!wdev->conn->prev_bssid_valid)
 389                return false;
 390
 391        /*
 392         * Some stupid APs don't accept reassoc, so we
 393         * need to fall back to trying regular assoc.
 394         */
 395        wdev->conn->prev_bssid_valid = false;
 396        wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
 397        schedule_work(&rdev->conn_work);
 398
 399        return true;
 400}
 401
 402void cfg80211_sme_failed_assoc(struct wireless_dev *wdev)
 403{
 404        struct wiphy *wiphy = wdev->wiphy;
 405        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 406
 407        wdev->conn->state = CFG80211_CONN_DEAUTH_ASSOC_FAIL;
 408        schedule_work(&rdev->conn_work);
 409}
 410
 411void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
 412                               const u8 *req_ie, size_t req_ie_len,
 413                               const u8 *resp_ie, size_t resp_ie_len,
 414                               u16 status, bool wextev,
 415                               struct cfg80211_bss *bss)
 416{
 417        struct wireless_dev *wdev = dev->ieee80211_ptr;
 418        u8 *country_ie;
 419#ifdef CONFIG_CFG80211_WEXT
 420        union iwreq_data wrqu;
 421#endif
 422
 423        ASSERT_WDEV_LOCK(wdev);
 424
 425        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
 426                    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
 427                return;
 428
 429        if (wdev->sme_state != CFG80211_SME_CONNECTING)
 430                return;
 431
 432        nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev,
 433                                    bssid, req_ie, req_ie_len,
 434                                    resp_ie, resp_ie_len,
 435                                    status, GFP_KERNEL);
 436
 437#ifdef CONFIG_CFG80211_WEXT
 438        if (wextev) {
 439                if (req_ie && status == WLAN_STATUS_SUCCESS) {
 440                        memset(&wrqu, 0, sizeof(wrqu));
 441                        wrqu.data.length = req_ie_len;
 442                        wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, req_ie);
 443                }
 444
 445                if (resp_ie && status == WLAN_STATUS_SUCCESS) {
 446                        memset(&wrqu, 0, sizeof(wrqu));
 447                        wrqu.data.length = resp_ie_len;
 448                        wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
 449                }
 450
 451                memset(&wrqu, 0, sizeof(wrqu));
 452                wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 453                if (bssid && status == WLAN_STATUS_SUCCESS) {
 454                        memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
 455                        memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN);
 456                        wdev->wext.prev_bssid_valid = true;
 457                }
 458                wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
 459        }
 460#endif
 461
 462        if (wdev->current_bss) {
 463                cfg80211_unhold_bss(wdev->current_bss);
 464                cfg80211_put_bss(&wdev->current_bss->pub);
 465                wdev->current_bss = NULL;
 466        }
 467
 468        if (wdev->conn)
 469                wdev->conn->state = CFG80211_CONN_IDLE;
 470
 471        if (status != WLAN_STATUS_SUCCESS) {
 472                wdev->sme_state = CFG80211_SME_IDLE;
 473                if (wdev->conn)
 474                        kfree(wdev->conn->ie);
 475                kfree(wdev->conn);
 476                wdev->conn = NULL;
 477                kfree(wdev->connect_keys);
 478                wdev->connect_keys = NULL;
 479                wdev->ssid_len = 0;
 480                cfg80211_put_bss(bss);
 481                return;
 482        }
 483
 484        if (!bss)
 485                bss = cfg80211_get_bss(wdev->wiphy,
 486                                       wdev->conn ? wdev->conn->params.channel :
 487                                       NULL,
 488                                       bssid,
 489                                       wdev->ssid, wdev->ssid_len,
 490                                       WLAN_CAPABILITY_ESS,
 491                                       WLAN_CAPABILITY_ESS);
 492
 493        if (WARN_ON(!bss))
 494                return;
 495
 496        cfg80211_hold_bss(bss_from_pub(bss));
 497        wdev->current_bss = bss_from_pub(bss);
 498
 499        wdev->sme_state = CFG80211_SME_CONNECTED;
 500        cfg80211_upload_connect_keys(wdev);
 501
 502        country_ie = (u8 *) ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
 503
 504        if (!country_ie)
 505                return;
 506
 507        /*
 508         * ieee80211_bss_get_ie() ensures we can access:
 509         * - country_ie + 2, the start of the country ie data, and
 510         * - and country_ie[1] which is the IE length
 511         */
 512        regulatory_hint_11d(wdev->wiphy,
 513                            bss->channel->band,
 514                            country_ie + 2,
 515                            country_ie[1]);
 516}
 517
 518void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
 519                             const u8 *req_ie, size_t req_ie_len,
 520                             const u8 *resp_ie, size_t resp_ie_len,
 521                             u16 status, gfp_t gfp)
 522{
 523        struct wireless_dev *wdev = dev->ieee80211_ptr;
 524        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 525        struct cfg80211_event *ev;
 526        unsigned long flags;
 527
 528        CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING);
 529
 530        ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
 531        if (!ev)
 532                return;
 533
 534        ev->type = EVENT_CONNECT_RESULT;
 535        if (bssid)
 536                memcpy(ev->cr.bssid, bssid, ETH_ALEN);
 537        if (req_ie_len) {
 538                ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev);
 539                ev->cr.req_ie_len = req_ie_len;
 540                memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len);
 541        }
 542        if (resp_ie_len) {
 543                ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len;
 544                ev->cr.resp_ie_len = resp_ie_len;
 545                memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len);
 546        }
 547        ev->cr.status = status;
 548
 549        spin_lock_irqsave(&wdev->event_lock, flags);
 550        list_add_tail(&ev->list, &wdev->event_list);
 551        spin_unlock_irqrestore(&wdev->event_lock, flags);
 552        queue_work(cfg80211_wq, &rdev->event_work);
 553}
 554EXPORT_SYMBOL(cfg80211_connect_result);
 555
 556void __cfg80211_roamed(struct wireless_dev *wdev,
 557                       struct cfg80211_bss *bss,
 558                       const u8 *req_ie, size_t req_ie_len,
 559                       const u8 *resp_ie, size_t resp_ie_len)
 560{
 561#ifdef CONFIG_CFG80211_WEXT
 562        union iwreq_data wrqu;
 563#endif
 564        ASSERT_WDEV_LOCK(wdev);
 565
 566        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
 567                    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
 568                goto out;
 569
 570        if (wdev->sme_state != CFG80211_SME_CONNECTED)
 571                goto out;
 572
 573        /* internal error -- how did we get to CONNECTED w/o BSS? */
 574        if (WARN_ON(!wdev->current_bss)) {
 575                goto out;
 576        }
 577
 578        cfg80211_unhold_bss(wdev->current_bss);
 579        cfg80211_put_bss(&wdev->current_bss->pub);
 580        wdev->current_bss = NULL;
 581
 582        cfg80211_hold_bss(bss_from_pub(bss));
 583        wdev->current_bss = bss_from_pub(bss);
 584
 585        nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), wdev->netdev, bss->bssid,
 586                            req_ie, req_ie_len, resp_ie, resp_ie_len,
 587                            GFP_KERNEL);
 588
 589#ifdef CONFIG_CFG80211_WEXT
 590        if (req_ie) {
 591                memset(&wrqu, 0, sizeof(wrqu));
 592                wrqu.data.length = req_ie_len;
 593                wireless_send_event(wdev->netdev, IWEVASSOCREQIE,
 594                                    &wrqu, req_ie);
 595        }
 596
 597        if (resp_ie) {
 598                memset(&wrqu, 0, sizeof(wrqu));
 599                wrqu.data.length = resp_ie_len;
 600                wireless_send_event(wdev->netdev, IWEVASSOCRESPIE,
 601                                    &wrqu, resp_ie);
 602        }
 603
 604        memset(&wrqu, 0, sizeof(wrqu));
 605        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 606        memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN);
 607        memcpy(wdev->wext.prev_bssid, bss->bssid, ETH_ALEN);
 608        wdev->wext.prev_bssid_valid = true;
 609        wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL);
 610#endif
 611
 612        return;
 613out:
 614        cfg80211_put_bss(bss);
 615}
 616
 617void cfg80211_roamed(struct net_device *dev,
 618                     struct ieee80211_channel *channel,
 619                     const u8 *bssid,
 620                     const u8 *req_ie, size_t req_ie_len,
 621                     const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp)
 622{
 623        struct wireless_dev *wdev = dev->ieee80211_ptr;
 624        struct cfg80211_bss *bss;
 625
 626        CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED);
 627
 628        bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, wdev->ssid,
 629                               wdev->ssid_len, WLAN_CAPABILITY_ESS,
 630                               WLAN_CAPABILITY_ESS);
 631        if (WARN_ON(!bss))
 632                return;
 633
 634        cfg80211_roamed_bss(dev, bss, req_ie, req_ie_len, resp_ie,
 635                            resp_ie_len, gfp);
 636}
 637EXPORT_SYMBOL(cfg80211_roamed);
 638
 639void cfg80211_roamed_bss(struct net_device *dev,
 640                         struct cfg80211_bss *bss, const u8 *req_ie,
 641                         size_t req_ie_len, const u8 *resp_ie,
 642                         size_t resp_ie_len, gfp_t gfp)
 643{
 644        struct wireless_dev *wdev = dev->ieee80211_ptr;
 645        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 646        struct cfg80211_event *ev;
 647        unsigned long flags;
 648
 649        CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED);
 650
 651        if (WARN_ON(!bss))
 652                return;
 653
 654        ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
 655        if (!ev) {
 656                cfg80211_put_bss(bss);
 657                return;
 658        }
 659
 660        ev->type = EVENT_ROAMED;
 661        ev->rm.req_ie = ((u8 *)ev) + sizeof(*ev);
 662        ev->rm.req_ie_len = req_ie_len;
 663        memcpy((void *)ev->rm.req_ie, req_ie, req_ie_len);
 664        ev->rm.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len;
 665        ev->rm.resp_ie_len = resp_ie_len;
 666        memcpy((void *)ev->rm.resp_ie, resp_ie, resp_ie_len);
 667        ev->rm.bss = bss;
 668
 669        spin_lock_irqsave(&wdev->event_lock, flags);
 670        list_add_tail(&ev->list, &wdev->event_list);
 671        spin_unlock_irqrestore(&wdev->event_lock, flags);
 672        queue_work(cfg80211_wq, &rdev->event_work);
 673}
 674EXPORT_SYMBOL(cfg80211_roamed_bss);
 675
 676void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
 677                             size_t ie_len, u16 reason, bool from_ap)
 678{
 679        struct wireless_dev *wdev = dev->ieee80211_ptr;
 680        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 681        int i;
 682#ifdef CONFIG_CFG80211_WEXT
 683        union iwreq_data wrqu;
 684#endif
 685
 686        ASSERT_WDEV_LOCK(wdev);
 687
 688        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
 689                    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
 690                return;
 691
 692        if (wdev->sme_state != CFG80211_SME_CONNECTED)
 693                return;
 694
 695        if (wdev->current_bss) {
 696                cfg80211_unhold_bss(wdev->current_bss);
 697                cfg80211_put_bss(&wdev->current_bss->pub);
 698        }
 699
 700        wdev->current_bss = NULL;
 701        wdev->sme_state = CFG80211_SME_IDLE;
 702        wdev->ssid_len = 0;
 703
 704        if (wdev->conn) {
 705                kfree(wdev->conn->ie);
 706                wdev->conn->ie = NULL;
 707                kfree(wdev->conn);
 708                wdev->conn = NULL;
 709        }
 710
 711        nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
 712
 713        /*
 714         * Delete all the keys ... pairwise keys can't really
 715         * exist any more anyway, but default keys might.
 716         */
 717        if (rdev->ops->del_key)
 718                for (i = 0; i < 6; i++)
 719                        rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
 720
 721#ifdef CONFIG_CFG80211_WEXT
 722        memset(&wrqu, 0, sizeof(wrqu));
 723        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 724        wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
 725        wdev->wext.connect.ssid_len = 0;
 726#endif
 727
 728        schedule_work(&cfg80211_disconnect_work);
 729}
 730
 731void cfg80211_disconnected(struct net_device *dev, u16 reason,
 732                           u8 *ie, size_t ie_len, gfp_t gfp)
 733{
 734        struct wireless_dev *wdev = dev->ieee80211_ptr;
 735        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 736        struct cfg80211_event *ev;
 737        unsigned long flags;
 738
 739        CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED);
 740
 741        ev = kzalloc(sizeof(*ev) + ie_len, gfp);
 742        if (!ev)
 743                return;
 744
 745        ev->type = EVENT_DISCONNECTED;
 746        ev->dc.ie = ((u8 *)ev) + sizeof(*ev);
 747        ev->dc.ie_len = ie_len;
 748        memcpy((void *)ev->dc.ie, ie, ie_len);
 749        ev->dc.reason = reason;
 750
 751        spin_lock_irqsave(&wdev->event_lock, flags);
 752        list_add_tail(&ev->list, &wdev->event_list);
 753        spin_unlock_irqrestore(&wdev->event_lock, flags);
 754        queue_work(cfg80211_wq, &rdev->event_work);
 755}
 756EXPORT_SYMBOL(cfg80211_disconnected);
 757
 758int __cfg80211_connect(struct cfg80211_registered_device *rdev,
 759                       struct net_device *dev,
 760                       struct cfg80211_connect_params *connect,
 761                       struct cfg80211_cached_keys *connkeys,
 762                       const u8 *prev_bssid)
 763{
 764        struct wireless_dev *wdev = dev->ieee80211_ptr;
 765        struct cfg80211_bss *bss = NULL;
 766        int err;
 767
 768        ASSERT_WDEV_LOCK(wdev);
 769
 770        if (wdev->sme_state != CFG80211_SME_IDLE)
 771                return -EALREADY;
 772
 773        if (WARN_ON(wdev->connect_keys)) {
 774                kfree(wdev->connect_keys);
 775                wdev->connect_keys = NULL;
 776        }
 777
 778        cfg80211_oper_and_ht_capa(&connect->ht_capa_mask,
 779                                  rdev->wiphy.ht_capa_mod_mask);
 780
 781        if (connkeys && connkeys->def >= 0) {
 782                int idx;
 783                u32 cipher;
 784
 785                idx = connkeys->def;
 786                cipher = connkeys->params[idx].cipher;
 787                /* If given a WEP key we may need it for shared key auth */
 788                if (cipher == WLAN_CIPHER_SUITE_WEP40 ||
 789                    cipher == WLAN_CIPHER_SUITE_WEP104) {
 790                        connect->key_idx = idx;
 791                        connect->key = connkeys->params[idx].key;
 792                        connect->key_len = connkeys->params[idx].key_len;
 793
 794                        /*
 795                         * If ciphers are not set (e.g. when going through
 796                         * iwconfig), we have to set them appropriately here.
 797                         */
 798                        if (connect->crypto.cipher_group == 0)
 799                                connect->crypto.cipher_group = cipher;
 800
 801                        if (connect->crypto.n_ciphers_pairwise == 0) {
 802                                connect->crypto.n_ciphers_pairwise = 1;
 803                                connect->crypto.ciphers_pairwise[0] = cipher;
 804                        }
 805                }
 806        }
 807
 808        if (!rdev->ops->connect) {
 809                if (!rdev->ops->auth || !rdev->ops->assoc)
 810                        return -EOPNOTSUPP;
 811
 812                if (WARN_ON(wdev->conn))
 813                        return -EINPROGRESS;
 814
 815                wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL);
 816                if (!wdev->conn)
 817                        return -ENOMEM;
 818
 819                /*
 820                 * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
 821                 */
 822                memcpy(&wdev->conn->params, connect, sizeof(*connect));
 823                if (connect->bssid) {
 824                        wdev->conn->params.bssid = wdev->conn->bssid;
 825                        memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
 826                }
 827
 828                if (connect->ie) {
 829                        wdev->conn->ie = kmemdup(connect->ie, connect->ie_len,
 830                                                GFP_KERNEL);
 831                        wdev->conn->params.ie = wdev->conn->ie;
 832                        if (!wdev->conn->ie) {
 833                                kfree(wdev->conn);
 834                                wdev->conn = NULL;
 835                                return -ENOMEM;
 836                        }
 837                }
 838
 839                if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
 840                        wdev->conn->auto_auth = true;
 841                        /* start with open system ... should mostly work */
 842                        wdev->conn->params.auth_type =
 843                                NL80211_AUTHTYPE_OPEN_SYSTEM;
 844                } else {
 845                        wdev->conn->auto_auth = false;
 846                }
 847
 848                memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
 849                wdev->ssid_len = connect->ssid_len;
 850                wdev->conn->params.ssid = wdev->ssid;
 851                wdev->conn->params.ssid_len = connect->ssid_len;
 852
 853                /* see if we have the bss already */
 854                bss = cfg80211_get_conn_bss(wdev);
 855
 856                wdev->sme_state = CFG80211_SME_CONNECTING;
 857                wdev->connect_keys = connkeys;
 858
 859                if (prev_bssid) {
 860                        memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN);
 861                        wdev->conn->prev_bssid_valid = true;
 862                }
 863
 864                /* we're good if we have a matching bss struct */
 865                if (bss) {
 866                        wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
 867                        err = cfg80211_conn_do_work(wdev);
 868                        cfg80211_put_bss(bss);
 869                } else {
 870                        /* otherwise we'll need to scan for the AP first */
 871                        err = cfg80211_conn_scan(wdev);
 872                        /*
 873                         * If we can't scan right now, then we need to scan again
 874                         * after the current scan finished, since the parameters
 875                         * changed (unless we find a good AP anyway).
 876                         */
 877                        if (err == -EBUSY) {
 878                                err = 0;
 879                                wdev->conn->state = CFG80211_CONN_SCAN_AGAIN;
 880                        }
 881                }
 882                if (err) {
 883                        kfree(wdev->conn->ie);
 884                        kfree(wdev->conn);
 885                        wdev->conn = NULL;
 886                        wdev->sme_state = CFG80211_SME_IDLE;
 887                        wdev->connect_keys = NULL;
 888                        wdev->ssid_len = 0;
 889                }
 890
 891                return err;
 892        } else {
 893                wdev->sme_state = CFG80211_SME_CONNECTING;
 894                wdev->connect_keys = connkeys;
 895                err = rdev->ops->connect(&rdev->wiphy, dev, connect);
 896                if (err) {
 897                        wdev->connect_keys = NULL;
 898                        wdev->sme_state = CFG80211_SME_IDLE;
 899                        return err;
 900                }
 901
 902                memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
 903                wdev->ssid_len = connect->ssid_len;
 904
 905                return 0;
 906        }
 907}
 908
 909int cfg80211_connect(struct cfg80211_registered_device *rdev,
 910                     struct net_device *dev,
 911                     struct cfg80211_connect_params *connect,
 912                     struct cfg80211_cached_keys *connkeys)
 913{
 914        int err;
 915
 916        mutex_lock(&rdev->devlist_mtx);
 917        wdev_lock(dev->ieee80211_ptr);
 918        err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
 919        wdev_unlock(dev->ieee80211_ptr);
 920        mutex_unlock(&rdev->devlist_mtx);
 921
 922        return err;
 923}
 924
 925int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
 926                          struct net_device *dev, u16 reason, bool wextev)
 927{
 928        struct wireless_dev *wdev = dev->ieee80211_ptr;
 929        int err;
 930
 931        ASSERT_WDEV_LOCK(wdev);
 932
 933        if (wdev->sme_state == CFG80211_SME_IDLE)
 934                return -EINVAL;
 935
 936        kfree(wdev->connect_keys);
 937        wdev->connect_keys = NULL;
 938
 939        if (!rdev->ops->disconnect) {
 940                if (!rdev->ops->deauth)
 941                        return -EOPNOTSUPP;
 942
 943                /* was it connected by userspace SME? */
 944                if (!wdev->conn) {
 945                        cfg80211_mlme_down(rdev, dev);
 946                        return 0;
 947                }
 948
 949                if (wdev->sme_state == CFG80211_SME_CONNECTING &&
 950                    (wdev->conn->state == CFG80211_CONN_SCANNING ||
 951                     wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) {
 952                        wdev->sme_state = CFG80211_SME_IDLE;
 953                        kfree(wdev->conn->ie);
 954                        kfree(wdev->conn);
 955                        wdev->conn = NULL;
 956                        wdev->ssid_len = 0;
 957                        return 0;
 958                }
 959
 960                /* wdev->conn->params.bssid must be set if > SCANNING */
 961                err = __cfg80211_mlme_deauth(rdev, dev,
 962                                             wdev->conn->params.bssid,
 963                                             NULL, 0, reason, false);
 964                if (err)
 965                        return err;
 966        } else {
 967                err = rdev->ops->disconnect(&rdev->wiphy, dev, reason);
 968                if (err)
 969                        return err;
 970        }
 971
 972        if (wdev->sme_state == CFG80211_SME_CONNECTED)
 973                __cfg80211_disconnected(dev, NULL, 0, 0, false);
 974        else if (wdev->sme_state == CFG80211_SME_CONNECTING)
 975                __cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0,
 976                                          WLAN_STATUS_UNSPECIFIED_FAILURE,
 977                                          wextev, NULL);
 978
 979        return 0;
 980}
 981
 982int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
 983                        struct net_device *dev,
 984                        u16 reason, bool wextev)
 985{
 986        int err;
 987
 988        wdev_lock(dev->ieee80211_ptr);
 989        err = __cfg80211_disconnect(rdev, dev, reason, wextev);
 990        wdev_unlock(dev->ieee80211_ptr);
 991
 992        return err;
 993}
 994
 995void cfg80211_sme_disassoc(struct net_device *dev,
 996                           struct cfg80211_internal_bss *bss)
 997{
 998        struct wireless_dev *wdev = dev->ieee80211_ptr;
 999        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1000        u8 bssid[ETH_ALEN];
1001
1002        ASSERT_WDEV_LOCK(wdev);
1003
1004        if (!wdev->conn)
1005                return;
1006
1007        if (wdev->conn->state == CFG80211_CONN_IDLE)
1008                return;
1009
1010        /*
1011         * Ok, so the association was made by this SME -- we don't
1012         * want it any more so deauthenticate too.
1013         */
1014
1015        memcpy(bssid, bss->pub.bssid, ETH_ALEN);
1016
1017        __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0,
1018                               WLAN_REASON_DEAUTH_LEAVING, false);
1019}
1020
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.