nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
/*
|
|
|
|
* cfg80211 MLME SAP interface
|
|
|
|
*
|
|
|
|
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/netdevice.h>
|
|
|
|
#include <linux/nl80211.h>
|
2009-07-27 17:01:53 +07:00
|
|
|
#include <linux/wireless.h>
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
#include <net/cfg80211.h>
|
2009-07-27 17:01:53 +07:00
|
|
|
#include <net/iw_handler.h>
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
#include "core.h"
|
|
|
|
#include "nl80211.h"
|
|
|
|
|
2009-07-07 08:56:07 +07:00
|
|
|
void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
{
|
2009-07-02 22:20:43 +07:00
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
struct wiphy *wiphy = wdev->wiphy;
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
2009-07-02 22:20:43 +07:00
|
|
|
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
|
|
|
|
u8 *bssid = mgmt->bssid;
|
|
|
|
int i;
|
|
|
|
u16 status = le16_to_cpu(mgmt->u.auth.status_code);
|
|
|
|
bool done = false;
|
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
wdev_lock(wdev);
|
2009-07-07 08:56:07 +07:00
|
|
|
|
2009-07-02 22:20:43 +07:00
|
|
|
for (i = 0; i < MAX_AUTH_BSSES; i++) {
|
|
|
|
if (wdev->authtry_bsses[i] &&
|
|
|
|
memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid,
|
|
|
|
ETH_ALEN) == 0) {
|
|
|
|
if (status == WLAN_STATUS_SUCCESS) {
|
|
|
|
wdev->auth_bsses[i] = wdev->authtry_bsses[i];
|
|
|
|
} else {
|
|
|
|
cfg80211_unhold_bss(wdev->authtry_bsses[i]);
|
|
|
|
cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
|
|
|
|
}
|
|
|
|
wdev->authtry_bsses[i] = NULL;
|
|
|
|
done = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
WARN_ON(!done);
|
2009-07-02 14:13:27 +07:00
|
|
|
|
2009-07-07 08:56:07 +07:00
|
|
|
nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
|
2009-07-02 14:13:27 +07:00
|
|
|
cfg80211_sme_rx_auth(dev, buf, len);
|
2009-07-07 08:56:11 +07:00
|
|
|
|
|
|
|
wdev_unlock(wdev);
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(cfg80211_send_rx_auth);
|
|
|
|
|
2009-07-07 08:56:07 +07:00
|
|
|
void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
{
|
2009-07-02 14:13:27 +07:00
|
|
|
u16 status_code;
|
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
struct wiphy *wiphy = wdev->wiphy;
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
2009-07-02 14:13:27 +07:00
|
|
|
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
|
|
|
|
u8 *ie = mgmt->u.assoc_resp.variable;
|
2009-07-02 22:20:43 +07:00
|
|
|
int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
|
2009-07-29 16:23:49 +07:00
|
|
|
struct cfg80211_internal_bss *bss = NULL;
|
2009-07-02 14:13:27 +07:00
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
wdev_lock(wdev);
|
2009-07-07 08:56:07 +07:00
|
|
|
|
2009-07-02 14:13:27 +07:00
|
|
|
status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
|
|
|
|
|
2009-08-07 19:51:05 +07:00
|
|
|
/*
|
|
|
|
* This is a bit of a hack, we don't notify userspace of
|
|
|
|
* a (re-)association reply if we tried to send a reassoc
|
|
|
|
* and got a reject -- we only try again with an assoc
|
|
|
|
* frame instead of reassoc.
|
|
|
|
*/
|
|
|
|
if (status_code != WLAN_STATUS_SUCCESS && wdev->conn &&
|
|
|
|
cfg80211_sme_failed_reassoc(wdev))
|
|
|
|
goto out;
|
|
|
|
|
2009-07-07 08:56:07 +07:00
|
|
|
nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
|
2009-07-02 14:13:27 +07:00
|
|
|
|
2009-07-02 22:20:43 +07:00
|
|
|
if (status_code == WLAN_STATUS_SUCCESS) {
|
2009-07-29 16:23:49 +07:00
|
|
|
for (i = 0; i < MAX_AUTH_BSSES; i++) {
|
|
|
|
if (!wdev->auth_bsses[i])
|
|
|
|
continue;
|
|
|
|
if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid,
|
|
|
|
ETH_ALEN) == 0) {
|
|
|
|
bss = wdev->auth_bsses[i];
|
2009-07-02 22:20:43 +07:00
|
|
|
wdev->auth_bsses[i] = NULL;
|
2009-07-29 16:23:49 +07:00
|
|
|
/* additional reference to drop hold */
|
|
|
|
cfg80211_ref_bss(bss);
|
2009-07-02 22:20:43 +07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-29 16:23:49 +07:00
|
|
|
WARN_ON(!bss);
|
2009-10-20 13:08:53 +07:00
|
|
|
} else if (wdev->conn) {
|
|
|
|
cfg80211_sme_failed_assoc(wdev);
|
|
|
|
/*
|
|
|
|
* do not call connect_result() now because the
|
|
|
|
* sme will schedule work that does it later.
|
|
|
|
*/
|
|
|
|
goto out;
|
2009-07-29 16:23:49 +07:00
|
|
|
}
|
|
|
|
|
2009-08-17 17:22:14 +07:00
|
|
|
if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) {
|
|
|
|
/*
|
|
|
|
* This is for the userspace SME, the CONNECTING
|
|
|
|
* state will be changed to CONNECTED by
|
|
|
|
* __cfg80211_connect_result() below.
|
|
|
|
*/
|
|
|
|
wdev->sme_state = CFG80211_SME_CONNECTING;
|
|
|
|
}
|
|
|
|
|
2009-07-29 16:23:49 +07:00
|
|
|
/* this consumes one bss reference (unless bss is NULL) */
|
|
|
|
__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
|
|
|
|
status_code,
|
|
|
|
status_code == WLAN_STATUS_SUCCESS,
|
|
|
|
bss ? &bss->pub : NULL);
|
|
|
|
/* drop hold now, and also reference acquired above */
|
|
|
|
if (bss) {
|
|
|
|
cfg80211_unhold_bss(bss);
|
|
|
|
cfg80211_put_bss(&bss->pub);
|
2009-07-02 22:20:43 +07:00
|
|
|
}
|
2009-07-07 08:56:11 +07:00
|
|
|
|
2009-08-07 19:51:05 +07:00
|
|
|
out:
|
2009-07-07 08:56:11 +07:00
|
|
|
wdev_unlock(wdev);
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(cfg80211_send_rx_assoc);
|
|
|
|
|
2009-10-13 18:28:13 +07:00
|
|
|
void __cfg80211_send_deauth(struct net_device *dev,
|
2009-07-07 08:56:11 +07:00
|
|
|
const u8 *buf, size_t len)
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
{
|
2009-07-02 14:13:27 +07:00
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
struct wiphy *wiphy = wdev->wiphy;
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
2009-07-02 14:13:27 +07:00
|
|
|
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
|
2009-07-02 22:20:43 +07:00
|
|
|
const u8 *bssid = mgmt->bssid;
|
|
|
|
int i;
|
2009-12-02 18:43:42 +07:00
|
|
|
bool found = false;
|
2009-07-02 14:13:27 +07:00
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
ASSERT_WDEV_LOCK(wdev);
|
2009-07-07 08:56:07 +07:00
|
|
|
|
2009-07-02 22:20:43 +07:00
|
|
|
if (wdev->current_bss &&
|
|
|
|
memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
|
|
|
|
cfg80211_unhold_bss(wdev->current_bss);
|
|
|
|
cfg80211_put_bss(&wdev->current_bss->pub);
|
|
|
|
wdev->current_bss = NULL;
|
2009-12-02 18:43:42 +07:00
|
|
|
found = true;
|
2009-07-02 22:20:43 +07:00
|
|
|
} else for (i = 0; i < MAX_AUTH_BSSES; i++) {
|
|
|
|
if (wdev->auth_bsses[i] &&
|
|
|
|
memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
|
|
|
|
cfg80211_unhold_bss(wdev->auth_bsses[i]);
|
|
|
|
cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
|
|
|
|
wdev->auth_bsses[i] = NULL;
|
2009-12-02 18:43:42 +07:00
|
|
|
found = true;
|
2009-07-02 22:20:43 +07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (wdev->authtry_bsses[i] &&
|
|
|
|
memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
|
|
|
|
cfg80211_unhold_bss(wdev->authtry_bsses[i]);
|
|
|
|
cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
|
|
|
|
wdev->authtry_bsses[i] = NULL;
|
2009-12-02 18:43:42 +07:00
|
|
|
found = true;
|
2009-07-02 22:20:43 +07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-02 18:43:42 +07:00
|
|
|
if (!found)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
|
|
|
|
|
2009-07-02 14:13:27 +07:00
|
|
|
if (wdev->sme_state == CFG80211_SME_CONNECTED) {
|
|
|
|
u16 reason_code;
|
|
|
|
bool from_ap;
|
|
|
|
|
|
|
|
reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
|
|
|
|
|
2009-08-07 01:41:33 +07:00
|
|
|
from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
|
2009-07-07 08:56:11 +07:00
|
|
|
__cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
|
2009-07-02 14:13:27 +07:00
|
|
|
} else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
|
2009-07-07 08:56:11 +07:00
|
|
|
__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
|
|
|
|
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
2009-07-29 16:23:49 +07:00
|
|
|
false, NULL);
|
2009-07-07 08:56:11 +07:00
|
|
|
}
|
|
|
|
}
|
2009-10-13 18:28:13 +07:00
|
|
|
EXPORT_SYMBOL(__cfg80211_send_deauth);
|
2009-07-07 08:56:11 +07:00
|
|
|
|
2009-10-13 18:28:13 +07:00
|
|
|
void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
|
2009-07-07 08:56:11 +07:00
|
|
|
{
|
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
|
2009-10-13 18:28:13 +07:00
|
|
|
wdev_lock(wdev);
|
|
|
|
__cfg80211_send_deauth(dev, buf, len);
|
|
|
|
wdev_unlock(wdev);
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
}
|
2009-03-28 01:53:56 +07:00
|
|
|
EXPORT_SYMBOL(cfg80211_send_deauth);
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
|
2009-10-13 18:28:13 +07:00
|
|
|
void __cfg80211_send_disassoc(struct net_device *dev,
|
2009-07-07 08:56:11 +07:00
|
|
|
const u8 *buf, size_t len)
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
{
|
2009-07-02 14:13:27 +07:00
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
struct wiphy *wiphy = wdev->wiphy;
|
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme")
for informing user space about received and processed Authentication,
(Re)Association Response, Deauthentication, and Disassociation frames in
station and IBSS modes (i.e., MLME SAP interface primitives
MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm,
MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and
MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11
management frame since we already have the frame in that format and it
includes all the needed information.
This is the initial step in providing MLME SAP interface for
authentication and association with nl80211. In other words, kernel code
will act as the MLME and a user space application can control it as the
SME.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-03-19 18:39:21 +07:00
|
|
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
2009-07-02 14:13:27 +07:00
|
|
|
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
|
2009-07-02 22:20:43 +07:00
|
|
|
const u8 *bssid = mgmt->bssid;
|
|
|
|
int i;
|
|
|
|
u16 reason_code;
|
|
|
|
bool from_ap;
|
|
|
|
bool done = false;
|
2009-07-02 14:13:27 +07:00
|
|
|
|
2009-07-11 05:17:32 +07:00
|
|
|
ASSERT_WDEV_LOCK(wdev);
|
2009-07-07 08:56:07 +07:00
|
|
|
|
|
|
|
nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
|
2009-03-28 02:59:49 +07:00
|
|
|
|
2009-07-11 05:17:32 +07:00
|
|
|
if (wdev->sme_state != CFG80211_SME_CONNECTED)
|
|
|
|
return;
|
2009-07-02 14:13:27 +07:00
|
|
|
|
2009-07-02 22:20:43 +07:00
|
|
|
if (wdev->current_bss &&
|
2009-08-06 15:52:42 +07:00
|
|
|
memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
|
2009-07-02 22:20:43 +07:00
|
|
|
for (i = 0; i < MAX_AUTH_BSSES; i++) {
|
|
|
|
if (wdev->authtry_bsses[i] || wdev->auth_bsses[i])
|
|
|
|
continue;
|
|
|
|
wdev->auth_bsses[i] = wdev->current_bss;
|
|
|
|
wdev->current_bss = NULL;
|
|
|
|
done = true;
|
|
|
|
cfg80211_sme_disassoc(dev, i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
WARN_ON(!done);
|
|
|
|
} else
|
|
|
|
WARN_ON(1);
|
2009-07-02 14:13:27 +07:00
|
|
|
|
|
|
|
|
2009-07-02 22:20:43 +07:00
|
|
|
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
|
|
|
|
|
2009-08-07 01:41:33 +07:00
|
|
|
from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
|
2009-07-07 08:56:11 +07:00
|
|
|
__cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
|
|
|
|
}
|
2009-10-13 18:28:13 +07:00
|
|
|
EXPORT_SYMBOL(__cfg80211_send_disassoc);
|
2009-07-07 08:56:11 +07:00
|
|
|
|
2009-10-13 18:28:13 +07:00
|
|
|
void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
|
2009-07-07 08:56:11 +07:00
|
|
|
{
|
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
|
2009-10-13 18:28:13 +07:00
|
|
|
wdev_lock(wdev);
|
|
|
|
__cfg80211_send_disassoc(dev, buf, len);
|
|
|
|
wdev_unlock(wdev);
|
2009-04-23 01:38:25 +07:00
|
|
|
}
|
2009-07-02 14:13:27 +07:00
|
|
|
EXPORT_SYMBOL(cfg80211_send_disassoc);
|
2009-04-23 01:38:25 +07:00
|
|
|
|
2009-11-19 18:45:42 +07:00
|
|
|
static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr)
|
2009-04-23 01:38:25 +07:00
|
|
|
{
|
2009-07-02 22:20:43 +07:00
|
|
|
int i;
|
|
|
|
bool done = false;
|
|
|
|
|
2009-11-19 18:45:42 +07:00
|
|
|
ASSERT_WDEV_LOCK(wdev);
|
2009-07-02 22:20:43 +07:00
|
|
|
|
|
|
|
for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
|
|
|
|
if (wdev->authtry_bsses[i] &&
|
|
|
|
memcmp(wdev->authtry_bsses[i]->pub.bssid,
|
|
|
|
addr, ETH_ALEN) == 0) {
|
|
|
|
cfg80211_unhold_bss(wdev->authtry_bsses[i]);
|
|
|
|
cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
|
|
|
|
wdev->authtry_bsses[i] = NULL;
|
|
|
|
done = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
WARN_ON(!done);
|
2009-11-19 18:45:42 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr)
|
|
|
|
{
|
|
|
|
__cfg80211_auth_remove(dev->ieee80211_ptr, addr);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__cfg80211_auth_canceled);
|
|
|
|
|
|
|
|
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
|
|
|
|
{
|
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
struct wiphy *wiphy = wdev->wiphy;
|
|
|
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
|
|
|
|
|
|
|
wdev_lock(wdev);
|
|
|
|
|
|
|
|
nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
|
|
|
|
if (wdev->sme_state == CFG80211_SME_CONNECTING)
|
|
|
|
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
|
|
|
|
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
|
|
|
false, NULL);
|
|
|
|
|
|
|
|
__cfg80211_auth_remove(wdev, addr);
|
2009-07-07 08:56:11 +07:00
|
|
|
|
|
|
|
wdev_unlock(wdev);
|
2009-04-23 01:38:25 +07:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(cfg80211_send_auth_timeout);
|
|
|
|
|
2009-07-07 08:56:07 +07:00
|
|
|
void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
|
2009-04-23 01:38:25 +07:00
|
|
|
{
|
2009-07-02 14:13:27 +07:00
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
struct wiphy *wiphy = wdev->wiphy;
|
2009-04-23 01:38:25 +07:00
|
|
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
2009-07-02 22:20:43 +07:00
|
|
|
int i;
|
|
|
|
bool done = false;
|
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
wdev_lock(wdev);
|
2009-07-07 08:56:07 +07:00
|
|
|
|
|
|
|
nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
|
2009-07-02 14:13:27 +07:00
|
|
|
if (wdev->sme_state == CFG80211_SME_CONNECTING)
|
2009-07-07 08:56:11 +07:00
|
|
|
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
|
|
|
|
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
2009-07-29 16:23:49 +07:00
|
|
|
false, NULL);
|
2009-07-02 22:20:43 +07:00
|
|
|
|
|
|
|
for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
|
|
|
|
if (wdev->auth_bsses[i] &&
|
|
|
|
memcmp(wdev->auth_bsses[i]->pub.bssid,
|
|
|
|
addr, ETH_ALEN) == 0) {
|
|
|
|
cfg80211_unhold_bss(wdev->auth_bsses[i]);
|
|
|
|
cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
|
|
|
|
wdev->auth_bsses[i] = NULL;
|
|
|
|
done = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
WARN_ON(!done);
|
2009-07-07 08:56:11 +07:00
|
|
|
|
|
|
|
wdev_unlock(wdev);
|
2009-04-23 01:38:25 +07:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
|
|
|
|
|
2009-03-28 02:59:49 +07:00
|
|
|
void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
|
|
|
|
enum nl80211_key_type key_type, int key_id,
|
2009-07-02 02:26:47 +07:00
|
|
|
const u8 *tsc, gfp_t gfp)
|
2009-03-28 02:59:49 +07:00
|
|
|
{
|
|
|
|
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
|
|
|
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
2009-09-30 04:27:28 +07:00
|
|
|
#ifdef CONFIG_CFG80211_WEXT
|
2009-06-19 07:45:21 +07:00
|
|
|
union iwreq_data wrqu;
|
2009-07-02 02:26:47 +07:00
|
|
|
char *buf = kmalloc(128, gfp);
|
2009-06-19 07:45:21 +07:00
|
|
|
|
|
|
|
if (buf) {
|
|
|
|
sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
|
|
|
|
"keyid=%d %scast addr=%pM)", key_id,
|
|
|
|
key_type == NL80211_KEYTYPE_GROUP ? "broad" : "uni",
|
|
|
|
addr);
|
|
|
|
memset(&wrqu, 0, sizeof(wrqu));
|
|
|
|
wrqu.data.length = strlen(buf);
|
|
|
|
wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
|
|
|
|
kfree(buf);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-07-02 02:26:47 +07:00
|
|
|
nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
|
2009-03-28 02:59:49 +07:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(cfg80211_michael_mic_failure);
|
2009-07-02 22:20:43 +07:00
|
|
|
|
|
|
|
/* some MLME handling for userspace SME */
|
2009-07-07 08:56:11 +07:00
|
|
|
int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
|
|
|
struct net_device *dev,
|
|
|
|
struct ieee80211_channel *chan,
|
|
|
|
enum nl80211_auth_type auth_type,
|
|
|
|
const u8 *bssid,
|
|
|
|
const u8 *ssid, int ssid_len,
|
cfg80211: rework key operation
This reworks the key operation in cfg80211, and now only
allows, from userspace, configuring keys (via nl80211)
after the connection has been established (in managed
mode), the IBSS been joined (in IBSS mode), at any time
(in AP[_VLAN] modes) or never for all the other modes.
In order to do shared key authentication correctly, it
is now possible to give a WEP key to the AUTH command.
To configure static WEP keys, these are given to the
CONNECT or IBSS_JOIN command directly, for a userspace
SME it is assumed it will configure it properly after
the connection has been established.
Since mac80211 used to check the default key in IBSS
mode to see whether or not the network is protected,
it needs an update in that area, as well as an update
to make use of the WEP key passed to auth() for shared
key authentication.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-07-08 19:22:54 +07:00
|
|
|
const u8 *ie, int ie_len,
|
|
|
|
const u8 *key, int key_len, int key_idx)
|
2009-07-02 22:20:43 +07:00
|
|
|
{
|
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
struct cfg80211_auth_request req;
|
|
|
|
struct cfg80211_internal_bss *bss;
|
|
|
|
int i, err, slot = -1, nfree = 0;
|
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
ASSERT_WDEV_LOCK(wdev);
|
|
|
|
|
cfg80211: rework key operation
This reworks the key operation in cfg80211, and now only
allows, from userspace, configuring keys (via nl80211)
after the connection has been established (in managed
mode), the IBSS been joined (in IBSS mode), at any time
(in AP[_VLAN] modes) or never for all the other modes.
In order to do shared key authentication correctly, it
is now possible to give a WEP key to the AUTH command.
To configure static WEP keys, these are given to the
CONNECT or IBSS_JOIN command directly, for a userspace
SME it is assumed it will configure it properly after
the connection has been established.
Since mac80211 used to check the default key in IBSS
mode to see whether or not the network is protected,
it needs an update in that area, as well as an update
to make use of the WEP key passed to auth() for shared
key authentication.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-07-08 19:22:54 +07:00
|
|
|
if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
|
|
|
|
if (!key || !key_len || key_idx < 0 || key_idx > 4)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2009-07-02 23:26:18 +07:00
|
|
|
if (wdev->current_bss &&
|
|
|
|
memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0)
|
|
|
|
return -EALREADY;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_AUTH_BSSES; i++) {
|
|
|
|
if (wdev->authtry_bsses[i] &&
|
|
|
|
memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid,
|
|
|
|
ETH_ALEN) == 0)
|
|
|
|
return -EALREADY;
|
|
|
|
if (wdev->auth_bsses[i] &&
|
|
|
|
memcmp(bssid, wdev->auth_bsses[i]->pub.bssid,
|
|
|
|
ETH_ALEN) == 0)
|
|
|
|
return -EALREADY;
|
|
|
|
}
|
|
|
|
|
2009-07-02 22:20:43 +07:00
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
|
|
|
|
req.ie = ie;
|
|
|
|
req.ie_len = ie_len;
|
|
|
|
req.auth_type = auth_type;
|
|
|
|
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
|
|
|
|
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
|
cfg80211: rework key operation
This reworks the key operation in cfg80211, and now only
allows, from userspace, configuring keys (via nl80211)
after the connection has been established (in managed
mode), the IBSS been joined (in IBSS mode), at any time
(in AP[_VLAN] modes) or never for all the other modes.
In order to do shared key authentication correctly, it
is now possible to give a WEP key to the AUTH command.
To configure static WEP keys, these are given to the
CONNECT or IBSS_JOIN command directly, for a userspace
SME it is assumed it will configure it properly after
the connection has been established.
Since mac80211 used to check the default key in IBSS
mode to see whether or not the network is protected,
it needs an update in that area, as well as an update
to make use of the WEP key passed to auth() for shared
key authentication.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-07-08 19:22:54 +07:00
|
|
|
req.key = key;
|
|
|
|
req.key_len = key_len;
|
|
|
|
req.key_idx = key_idx;
|
2009-07-02 22:20:43 +07:00
|
|
|
if (!req.bss)
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
bss = bss_from_pub(req.bss);
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_AUTH_BSSES; i++) {
|
|
|
|
if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) {
|
|
|
|
slot = i;
|
|
|
|
nfree++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we need one free slot for disassoc and one for this auth */
|
|
|
|
if (nfree < 2) {
|
|
|
|
err = -ENOSPC;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
wdev->authtry_bsses[slot] = bss;
|
|
|
|
cfg80211_hold_bss(bss);
|
|
|
|
|
|
|
|
err = rdev->ops->auth(&rdev->wiphy, dev, &req);
|
|
|
|
if (err) {
|
|
|
|
wdev->authtry_bsses[slot] = NULL;
|
|
|
|
cfg80211_unhold_bss(bss);
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (err)
|
|
|
|
cfg80211_put_bss(req.bss);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
|
|
|
struct net_device *dev, struct ieee80211_channel *chan,
|
|
|
|
enum nl80211_auth_type auth_type, const u8 *bssid,
|
|
|
|
const u8 *ssid, int ssid_len,
|
cfg80211: rework key operation
This reworks the key operation in cfg80211, and now only
allows, from userspace, configuring keys (via nl80211)
after the connection has been established (in managed
mode), the IBSS been joined (in IBSS mode), at any time
(in AP[_VLAN] modes) or never for all the other modes.
In order to do shared key authentication correctly, it
is now possible to give a WEP key to the AUTH command.
To configure static WEP keys, these are given to the
CONNECT or IBSS_JOIN command directly, for a userspace
SME it is assumed it will configure it properly after
the connection has been established.
Since mac80211 used to check the default key in IBSS
mode to see whether or not the network is protected,
it needs an update in that area, as well as an update
to make use of the WEP key passed to auth() for shared
key authentication.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-07-08 19:22:54 +07:00
|
|
|
const u8 *ie, int ie_len,
|
|
|
|
const u8 *key, int key_len, int key_idx)
|
2009-07-07 08:56:11 +07:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
wdev_lock(dev->ieee80211_ptr);
|
|
|
|
err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
|
cfg80211: rework key operation
This reworks the key operation in cfg80211, and now only
allows, from userspace, configuring keys (via nl80211)
after the connection has been established (in managed
mode), the IBSS been joined (in IBSS mode), at any time
(in AP[_VLAN] modes) or never for all the other modes.
In order to do shared key authentication correctly, it
is now possible to give a WEP key to the AUTH command.
To configure static WEP keys, these are given to the
CONNECT or IBSS_JOIN command directly, for a userspace
SME it is assumed it will configure it properly after
the connection has been established.
Since mac80211 used to check the default key in IBSS
mode to see whether or not the network is protected,
it needs an update in that area, as well as an update
to make use of the WEP key passed to auth() for shared
key authentication.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-07-08 19:22:54 +07:00
|
|
|
ssid, ssid_len, ie, ie_len,
|
|
|
|
key, key_len, key_idx);
|
2009-07-07 08:56:11 +07:00
|
|
|
wdev_unlock(dev->ieee80211_ptr);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
|
|
|
|
struct net_device *dev,
|
|
|
|
struct ieee80211_channel *chan,
|
|
|
|
const u8 *bssid, const u8 *prev_bssid,
|
|
|
|
const u8 *ssid, int ssid_len,
|
|
|
|
const u8 *ie, int ie_len, bool use_mfp,
|
|
|
|
struct cfg80211_crypto_settings *crypt)
|
2009-07-02 22:20:43 +07:00
|
|
|
{
|
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
struct cfg80211_assoc_request req;
|
|
|
|
struct cfg80211_internal_bss *bss;
|
|
|
|
int i, err, slot = -1;
|
2009-11-18 02:35:38 +07:00
|
|
|
bool was_connected = false;
|
2009-07-02 22:20:43 +07:00
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
ASSERT_WDEV_LOCK(wdev);
|
|
|
|
|
2009-07-02 22:20:43 +07:00
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
|
2009-11-18 02:35:38 +07:00
|
|
|
if (wdev->current_bss && prev_bssid &&
|
|
|
|
memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) {
|
|
|
|
/*
|
|
|
|
* Trying to reassociate: Allow this to proceed and let the old
|
|
|
|
* association to be dropped when the new one is completed.
|
|
|
|
*/
|
|
|
|
if (wdev->sme_state == CFG80211_SME_CONNECTED) {
|
|
|
|
was_connected = true;
|
|
|
|
wdev->sme_state = CFG80211_SME_CONNECTING;
|
|
|
|
}
|
|
|
|
} else if (wdev->current_bss)
|
2009-07-02 22:20:43 +07:00
|
|
|
return -EALREADY;
|
|
|
|
|
|
|
|
req.ie = ie;
|
|
|
|
req.ie_len = ie_len;
|
|
|
|
memcpy(&req.crypto, crypt, sizeof(req.crypto));
|
|
|
|
req.use_mfp = use_mfp;
|
2009-07-07 19:37:26 +07:00
|
|
|
req.prev_bssid = prev_bssid;
|
2009-07-02 22:20:43 +07:00
|
|
|
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
|
|
|
|
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
|
2009-11-18 02:35:38 +07:00
|
|
|
if (!req.bss) {
|
|
|
|
if (was_connected)
|
|
|
|
wdev->sme_state = CFG80211_SME_CONNECTED;
|
2009-07-02 22:20:43 +07:00
|
|
|
return -ENOENT;
|
2009-11-18 02:35:38 +07:00
|
|
|
}
|
2009-07-02 22:20:43 +07:00
|
|
|
|
|
|
|
bss = bss_from_pub(req.bss);
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_AUTH_BSSES; i++) {
|
|
|
|
if (bss == wdev->auth_bsses[i]) {
|
|
|
|
slot = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (slot < 0) {
|
|
|
|
err = -ENOTCONN;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
|
|
|
|
out:
|
2009-11-18 02:35:38 +07:00
|
|
|
if (err && was_connected)
|
|
|
|
wdev->sme_state = CFG80211_SME_CONNECTED;
|
2009-07-02 22:20:43 +07:00
|
|
|
/* still a reference in wdev->auth_bsses[slot] */
|
|
|
|
cfg80211_put_bss(req.bss);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
|
|
|
|
struct net_device *dev,
|
|
|
|
struct ieee80211_channel *chan,
|
|
|
|
const u8 *bssid, const u8 *prev_bssid,
|
|
|
|
const u8 *ssid, int ssid_len,
|
|
|
|
const u8 *ie, int ie_len, bool use_mfp,
|
|
|
|
struct cfg80211_crypto_settings *crypt)
|
|
|
|
{
|
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
wdev_lock(wdev);
|
|
|
|
err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
|
|
|
|
ssid, ssid_len, ie, ie_len, use_mfp, crypt);
|
|
|
|
wdev_unlock(wdev);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
|
|
|
|
struct net_device *dev, const u8 *bssid,
|
|
|
|
const u8 *ie, int ie_len, u16 reason)
|
2009-07-02 22:20:43 +07:00
|
|
|
{
|
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
struct cfg80211_deauth_request req;
|
|
|
|
int i;
|
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
ASSERT_WDEV_LOCK(wdev);
|
|
|
|
|
2009-07-02 22:20:43 +07:00
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.reason_code = reason;
|
|
|
|
req.ie = ie;
|
|
|
|
req.ie_len = ie_len;
|
|
|
|
if (wdev->current_bss &&
|
|
|
|
memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
|
|
|
|
req.bss = &wdev->current_bss->pub;
|
|
|
|
} else for (i = 0; i < MAX_AUTH_BSSES; i++) {
|
|
|
|
if (wdev->auth_bsses[i] &&
|
|
|
|
memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
|
|
|
|
req.bss = &wdev->auth_bsses[i]->pub;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (wdev->authtry_bsses[i] &&
|
|
|
|
memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
|
|
|
|
req.bss = &wdev->authtry_bsses[i]->pub;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!req.bss)
|
|
|
|
return -ENOTCONN;
|
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
|
2009-07-02 22:20:43 +07:00
|
|
|
}
|
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
|
|
|
|
struct net_device *dev, const u8 *bssid,
|
|
|
|
const u8 *ie, int ie_len, u16 reason)
|
|
|
|
{
|
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
wdev_lock(wdev);
|
|
|
|
err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason);
|
|
|
|
wdev_unlock(wdev);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
|
|
|
|
struct net_device *dev, const u8 *bssid,
|
|
|
|
const u8 *ie, int ie_len, u16 reason)
|
2009-07-02 22:20:43 +07:00
|
|
|
{
|
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
struct cfg80211_disassoc_request req;
|
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
ASSERT_WDEV_LOCK(wdev);
|
|
|
|
|
2009-07-27 15:22:28 +07:00
|
|
|
if (wdev->sme_state != CFG80211_SME_CONNECTED)
|
|
|
|
return -ENOTCONN;
|
|
|
|
|
|
|
|
if (WARN_ON(!wdev->current_bss))
|
|
|
|
return -ENOTCONN;
|
|
|
|
|
2009-07-02 22:20:43 +07:00
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.reason_code = reason;
|
|
|
|
req.ie = ie;
|
|
|
|
req.ie_len = ie_len;
|
|
|
|
if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0)
|
|
|
|
req.bss = &wdev->current_bss->pub;
|
|
|
|
else
|
|
|
|
return -ENOTCONN;
|
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
return rdev->ops->disassoc(&rdev->wiphy, dev, &req, wdev);
|
|
|
|
}
|
|
|
|
|
|
|
|
int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
|
|
|
|
struct net_device *dev, const u8 *bssid,
|
|
|
|
const u8 *ie, int ie_len, u16 reason)
|
|
|
|
{
|
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
wdev_lock(wdev);
|
|
|
|
err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason);
|
|
|
|
wdev_unlock(wdev);
|
|
|
|
|
|
|
|
return err;
|
2009-07-02 22:20:43 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
|
|
|
|
struct net_device *dev)
|
|
|
|
{
|
|
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
|
struct cfg80211_deauth_request req;
|
|
|
|
int i;
|
|
|
|
|
2009-07-07 08:56:11 +07:00
|
|
|
ASSERT_WDEV_LOCK(wdev);
|
|
|
|
|
2009-07-02 22:20:43 +07:00
|
|
|
if (!rdev->ops->deauth)
|
|
|
|
return;
|
|
|
|
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.reason_code = WLAN_REASON_DEAUTH_LEAVING;
|
|
|
|
req.ie = NULL;
|
|
|
|
req.ie_len = 0;
|
|
|
|
|
|
|
|
if (wdev->current_bss) {
|
|
|
|
req.bss = &wdev->current_bss->pub;
|
2009-07-07 08:56:11 +07:00
|
|
|
rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
|
2009-07-02 22:20:43 +07:00
|
|
|
if (wdev->current_bss) {
|
|
|
|
cfg80211_unhold_bss(wdev->current_bss);
|
|
|
|
cfg80211_put_bss(&wdev->current_bss->pub);
|
|
|
|
wdev->current_bss = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_AUTH_BSSES; i++) {
|
|
|
|
if (wdev->auth_bsses[i]) {
|
|
|
|
req.bss = &wdev->auth_bsses[i]->pub;
|
2009-07-07 08:56:11 +07:00
|
|
|
rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
|
2009-07-02 22:20:43 +07:00
|
|
|
if (wdev->auth_bsses[i]) {
|
|
|
|
cfg80211_unhold_bss(wdev->auth_bsses[i]);
|
|
|
|
cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
|
|
|
|
wdev->auth_bsses[i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (wdev->authtry_bsses[i]) {
|
|
|
|
req.bss = &wdev->authtry_bsses[i]->pub;
|
2009-07-07 08:56:11 +07:00
|
|
|
rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
|
2009-07-02 22:20:43 +07:00
|
|
|
if (wdev->authtry_bsses[i]) {
|
|
|
|
cfg80211_unhold_bss(wdev->authtry_bsses[i]);
|
|
|
|
cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
|
|
|
|
wdev->authtry_bsses[i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-12-23 19:15:41 +07:00
|
|
|
|
|
|
|
void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,
|
|
|
|
struct ieee80211_channel *chan,
|
|
|
|
enum nl80211_channel_type channel_type,
|
|
|
|
unsigned int duration, gfp_t gfp)
|
|
|
|
{
|
|
|
|
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
|
|
|
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
|
|
|
|
|
|
|
nl80211_send_remain_on_channel(rdev, dev, cookie, chan, channel_type,
|
|
|
|
duration, gfp);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(cfg80211_ready_on_channel);
|
|
|
|
|
|
|
|
void cfg80211_remain_on_channel_expired(struct net_device *dev,
|
|
|
|
u64 cookie,
|
|
|
|
struct ieee80211_channel *chan,
|
|
|
|
enum nl80211_channel_type channel_type,
|
|
|
|
gfp_t gfp)
|
|
|
|
{
|
|
|
|
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
|
|
|
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
|
|
|
|
|
|
|
nl80211_send_remain_on_channel_cancel(rdev, dev, cookie, chan,
|
|
|
|
channel_type, gfp);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
|