* [PATCH 01/20 v4] wext: allow returning NULL stats
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 02/20 v4] mac80211: fix todo lock Johannes Berg
` (21 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
Currently, wext drivers cannot return NULL for stats even though
that would make the ioctl return -EOPNOTSUPP because that would
mean they are no longer listed in /proc/net/wireless. This patch
changes the wext core's behaviour to list them if they have any
wireless_handlers, but only show their stats when available, so
that drivers can start returning NULL if stats are currently not
available, reducing confusion for e.g. IBSS.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/wireless/wext.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
--- wireless-testing.orig/net/wireless/wext.c 2009-07-01 08:55:08.000000000 +0200
+++ wireless-testing/net/wireless/wext.c 2009-07-01 08:59:43.000000000 +0200
@@ -610,6 +610,11 @@ static void wireless_seq_printf_stats(st
{
/* Get stats from the driver */
struct iw_statistics *stats = get_wireless_stats(dev);
+ static struct iw_statistics nullstats = {};
+
+ /* show device if it's wireless regardless of current stats */
+ if (!stats && dev->wireless_handlers)
+ stats = &nullstats;
if (stats) {
seq_printf(seq, "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d "
@@ -628,7 +633,9 @@ static void wireless_seq_printf_stats(st
stats->discard.nwid, stats->discard.code,
stats->discard.fragment, stats->discard.retries,
stats->discard.misc, stats->miss.beacon);
- stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
+
+ if (stats != &nullstats)
+ stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
}
}
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 02/20 v4] mac80211: fix todo lock
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
2009-07-01 19:26 ` [PATCH 01/20 v4] wext: allow returning NULL stats Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 03/20 v4] wext: default to y Johannes Berg
` (20 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Bob Copeland, Gabor Juhos
The key todo lock can be taken from different locks
that require it to be _bh to avoid lock inversion
due to (soft)irqs.
This should fix the two problems reported by Bob and
Gabor:
http://mid.gmane.org/20090619113049.GB18956@hash.localnet
http://mid.gmane.org/4A3FA376.8020307@openwrt.org
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Bob Copeland <me@bobcopeland.com>
Cc: Gabor Juhos <juhosg@openwrt.org>
---
net/mac80211/key.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
--- wireless-testing.orig/net/mac80211/key.c 2009-07-01 08:55:08.000000000 +0200
+++ wireless-testing/net/mac80211/key.c 2009-07-01 08:59:43.000000000 +0200
@@ -67,6 +67,8 @@ static DECLARE_WORK(todo_work, key_todo)
*
* @key: key to add to do item for
* @flag: todo flag(s)
+ *
+ * Must be called with IRQs or softirqs disabled.
*/
static void add_todo(struct ieee80211_key *key, u32 flag)
{
@@ -140,9 +142,9 @@ static void ieee80211_key_enable_hw_acce
ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf);
if (!ret) {
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
}
if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
@@ -164,12 +166,12 @@ static void ieee80211_key_disable_hw_acc
if (!key || !key->local->ops->set_key)
return;
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
return;
}
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
sta = get_sta_for_key(key);
sdata = key->sdata;
@@ -188,9 +190,9 @@ static void ieee80211_key_disable_hw_acc
wiphy_name(key->local->hw.wiphy),
key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
}
static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
@@ -437,14 +439,14 @@ void ieee80211_key_link(struct ieee80211
__ieee80211_key_replace(sdata, sta, old_key, key);
- spin_unlock_irqrestore(&sdata->local->key_lock, flags);
-
/* free old key later */
add_todo(old_key, KEY_FLAG_TODO_DELETE);
add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
if (netif_running(sdata->dev))
add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
+
+ spin_unlock_irqrestore(&sdata->local->key_lock, flags);
}
static void __ieee80211_key_free(struct ieee80211_key *key)
@@ -547,7 +549,7 @@ static void __ieee80211_key_todo(void)
*/
synchronize_rcu();
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
while (!list_empty(&todo_list)) {
key = list_first_entry(&todo_list, struct ieee80211_key, todo);
list_del_init(&key->todo);
@@ -558,7 +560,7 @@ static void __ieee80211_key_todo(void)
KEY_FLAG_TODO_HWACCEL_REMOVE |
KEY_FLAG_TODO_DELETE);
key->flags &= ~todoflags;
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
work_done = false;
@@ -591,9 +593,9 @@ static void __ieee80211_key_todo(void)
WARN_ON(!work_done);
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
}
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
}
void ieee80211_key_todo(void)
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 03/20 v4] wext: default to y
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
2009-07-01 19:26 ` [PATCH 01/20 v4] wext: allow returning NULL stats Johannes Berg
2009-07-01 19:26 ` [PATCH 02/20 v4] mac80211: fix todo lock Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 04/20 v4] cfg80211: move break statement to correct place Johannes Berg
` (19 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
The way I initially thought we could do wireless extensions
is by making all the compat code in cfg80211 be independent
of CONFIG_WIRELESS_EXT, but this is turning out to not be
feasible. Therefore, fix the Kconfig help text and make the
option default to yes, so people won't get a nasty surprise
when mac80211 will get rid of its 'select WIRELESS_EXT' any
time now.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/wireless/Kconfig | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
--- wireless-testing.orig/net/wireless/Kconfig 2009-07-01 08:55:08.000000000 +0200
+++ wireless-testing/net/wireless/Kconfig 2009-07-01 08:59:43.000000000 +0200
@@ -35,19 +35,13 @@ config WIRELESS_OLD_REGULATORY
config WIRELESS_EXT
bool "Wireless extensions"
- default n
+ default y
---help---
This option enables the legacy wireless extensions
(wireless network interface configuration via ioctls.)
- Wireless extensions will be replaced by cfg80211 and
- will be required only by legacy drivers that implement
- wireless extension handlers. This option does not
- affect the wireless-extension backward compatibility
- code in cfg80211.
-
- Say N (if you can) unless you know you need wireless
- extensions for external modules.
+ Say Y unless you've upgraded all your userspace to use
+ nl80211 instead of wireless extensions.
config WIRELESS_EXT_SYSFS
bool "Wireless extensions sysfs files"
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 04/20 v4] cfg80211: move break statement to correct place
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (2 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 03/20 v4] wext: default to y Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 05/20 v4] nl80211: clean up function definitions Johannes Berg
` (18 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
Move a break statement to the correct place _after_ the
#endif, otherwise w/o WIRELESS_EXT things break badly.
Also, while touching this code, do a cleanup and assign
dev->ieee80211_ptr to a new variable.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/wireless/core.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
--- wireless-testing.orig/net/wireless/core.c 2009-07-01 08:55:08.000000000 +0200
+++ wireless-testing/net/wireless/core.c 2009-07-01 08:59:44.000000000 +0200
@@ -526,52 +526,53 @@ static int cfg80211_netdev_notifier_call
void *ndev)
{
struct net_device *dev = ndev;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev;
- if (!dev->ieee80211_ptr)
+ if (!wdev)
return NOTIFY_DONE;
- rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
+ rdev = wiphy_to_dev(wdev->wiphy);
- WARN_ON(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_UNSPECIFIED);
+ WARN_ON(wdev->iftype == NL80211_IFTYPE_UNSPECIFIED);
switch (state) {
case NETDEV_REGISTER:
mutex_lock(&rdev->devlist_mtx);
- list_add(&dev->ieee80211_ptr->list, &rdev->netdev_list);
+ list_add(&wdev->list, &rdev->netdev_list);
if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
"phy80211")) {
printk(KERN_ERR "wireless: failed to add phy80211 "
"symlink to netdev!\n");
}
- dev->ieee80211_ptr->netdev = dev;
+ wdev->netdev = dev;
#ifdef CONFIG_WIRELESS_EXT
- dev->ieee80211_ptr->wext.default_key = -1;
- dev->ieee80211_ptr->wext.default_mgmt_key = -1;
+ wdev->wext.default_key = -1;
+ wdev->wext.default_mgmt_key = -1;
#endif
mutex_unlock(&rdev->devlist_mtx);
break;
case NETDEV_GOING_DOWN:
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
+ if (wdev->iftype != NL80211_IFTYPE_ADHOC)
break;
- if (!dev->ieee80211_ptr->ssid_len)
+ if (!wdev->ssid_len)
break;
cfg80211_leave_ibss(rdev, dev, true);
break;
case NETDEV_UP:
#ifdef CONFIG_WIRELESS_EXT
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
+ if (wdev->iftype != NL80211_IFTYPE_ADHOC)
break;
- if (!dev->ieee80211_ptr->wext.ibss.ssid_len)
+ if (!wdev->wext.ibss.ssid_len)
break;
- cfg80211_join_ibss(rdev, dev, &dev->ieee80211_ptr->wext.ibss);
- break;
+ cfg80211_join_ibss(rdev, dev, &wdev->wext.ibss);
#endif
+ break;
case NETDEV_UNREGISTER:
mutex_lock(&rdev->devlist_mtx);
- if (!list_empty(&dev->ieee80211_ptr->list)) {
+ if (!list_empty(&wdev->list)) {
sysfs_remove_link(&dev->dev.kobj, "phy80211");
- list_del_init(&dev->ieee80211_ptr->list);
+ list_del_init(&wdev->list);
}
mutex_unlock(&rdev->devlist_mtx);
break;
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 05/20 v4] nl80211: clean up function definitions
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (3 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 04/20 v4] cfg80211: move break statement to correct place Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 06/20 v4] cfg80211: use proper allocation flags Johannes Berg
` (17 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
I don't like the 'extern' keyword much when it's not
necessary, it makes lines rather long.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/wireless/nl80211.h | 58 ++++++++++++++++++++++++-------------------------
1 file changed, 29 insertions(+), 29 deletions(-)
--- wireless-testing.orig/net/wireless/nl80211.h 2009-07-01 08:55:07.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.h 2009-07-01 08:59:44.000000000 +0200
@@ -3,41 +3,41 @@
#include "core.h"
-extern int nl80211_init(void);
-extern void nl80211_exit(void);
-extern void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
-extern void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
- struct net_device *netdev);
-extern void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
- struct net_device *netdev);
-extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
- struct net_device *netdev);
-extern void nl80211_send_reg_change_event(struct regulatory_request *request);
-extern void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
- const u8 *buf, size_t len);
-extern void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
- const u8 *buf, size_t len);
-extern void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
+int nl80211_init(void);
+void nl80211_exit(void);
+void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
+void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev);
+void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev);
+void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev);
+void nl80211_send_reg_change_event(struct regulatory_request *request);
+void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ const u8 *buf, size_t len);
+void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ const u8 *buf, size_t len);
+void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ const u8 *buf, size_t len);
+void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ const u8 *buf, size_t len);
+void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ const u8 *addr);
+void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
- const u8 *buf, size_t len);
-extern void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
- const u8 *buf, size_t len);
-extern void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
- const u8 *addr);
-extern void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
- const u8 *addr);
-extern void
+ const u8 *addr);
+void
nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *addr,
enum nl80211_key_type key_type,
int key_id, const u8 *tsc);
-extern void
+void
nl80211_send_beacon_hint_event(struct wiphy *wiphy,
struct ieee80211_channel *channel_before,
struct ieee80211_channel *channel_after);
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 06/20 v4] cfg80211: use proper allocation flags
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (4 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 05/20 v4] nl80211: clean up function definitions Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 07/20 v4] cfg80211: remove wireless_dev->bssid Johannes Berg
` (16 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
Instead of hardcoding GFP_ATOMIC everywhere, add a
new function parameter that gets the flags from the
caller. Obviously then I need to update all callers
(all of them in mac80211), and it turns out that now
it's ok to use GFP_KERNEL in almost all places.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/net/cfg80211.h | 21 +++++++++++++------
net/mac80211/event.c | 5 ++--
net/mac80211/ieee80211_i.h | 3 +-
net/mac80211/mlme.c | 30 +++++++++++++++++-----------
net/mac80211/rx.c | 3 +-
net/mac80211/wpa.c | 3 +-
net/wireless/mlme.c | 30 ++++++++++++++--------------
net/wireless/nl80211.c | 48 +++++++++++++++++++++++++--------------------
net/wireless/nl80211.h | 14 ++++++-------
9 files changed, 91 insertions(+), 66 deletions(-)
--- wireless-testing.orig/include/net/cfg80211.h 2009-07-01 08:55:07.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h 2009-07-01 09:01:15.000000000 +0200
@@ -1572,64 +1572,70 @@ void cfg80211_unlink_bss(struct wiphy *w
* @dev: network device
* @buf: authentication frame (header + body)
* @len: length of the frame data
+ * @gfp: allocation flags
*
* This function is called whenever an authentication has been processed in
* station mode. The driver is required to call either this function or
* cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth()
* call.
*/
-void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
+void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp);
/**
* cfg80211_send_auth_timeout - notification of timed out authentication
* @dev: network device
* @addr: The MAC address of the device with which the authentication timed out
+ * @gfp: allocation flags
*/
-void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
+void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr, gfp_t gfp);
/**
* cfg80211_send_rx_assoc - notification of processed association
* @dev: network device
* @buf: (re)association response frame (header + body)
* @len: length of the frame data
+ * @gfp: allocation flags
*
* This function is called whenever a (re)association response has been
* processed in station mode. The driver is required to call either this
* function or cfg80211_send_assoc_timeout() to indicate the result of
* cfg80211_ops::assoc() call.
*/
-void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len);
+void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp);
/**
* cfg80211_send_assoc_timeout - notification of timed out association
* @dev: network device
* @addr: The MAC address of the device with which the association timed out
+ * @gfp: allocation flags
*/
-void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
+void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr, gfp_t gfp);
/**
* cfg80211_send_deauth - notification of processed deauthentication
* @dev: network device
* @buf: deauthentication frame (header + body)
* @len: length of the frame data
+ * @gfp: allocation flags
*
* This function is called whenever deauthentication has been processed in
* station mode. This includes both received deauthentication frames and
* locally generated ones.
*/
-void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
+void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp);
/**
* cfg80211_send_disassoc - notification of processed disassociation
* @dev: network device
* @buf: disassociation response frame (header + body)
* @len: length of the frame data
+ * @gfp: allocation flags
*
* This function is called whenever disassociation has been processed in
* station mode. This includes both received disassociation frames and locally
* generated ones.
*/
-void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len);
+void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp);
/**
* cfg80211_hold_bss - exclude bss from expiration
@@ -1655,6 +1661,7 @@ void cfg80211_unhold_bss(struct cfg80211
* @key_type: The key type that the received frame used
* @key_id: Key identifier (0..3)
* @tsc: The TSC value of the frame that generated the MIC failure (6 octets)
+ * @gfp: allocation flags
*
* This function is called whenever the local MAC detects a MIC failure in a
* received frame. This matches with MLME-MICHAELMICFAILURE.indication()
@@ -1662,7 +1669,7 @@ void cfg80211_unhold_bss(struct cfg80211
*/
void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
enum nl80211_key_type key_type, int key_id,
- const u8 *tsc);
+ const u8 *tsc, gfp_t gfp);
/**
* cfg80211_ibss_joined - notify cfg80211 that device joined an IBSS
--- wireless-testing.orig/net/wireless/mlme.c 2009-07-01 08:55:07.000000000 +0200
+++ wireless-testing/net/wireless/mlme.c 2009-07-01 09:01:15.000000000 +0200
@@ -12,35 +12,35 @@
#include "core.h"
#include "nl80211.h"
-void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
+void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
{
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_rx_auth(rdev, dev, buf, len);
+ nl80211_send_rx_auth(rdev, dev, buf, len, gfp);
}
EXPORT_SYMBOL(cfg80211_send_rx_auth);
-void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
+void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
{
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_rx_assoc(rdev, dev, buf, len);
+ nl80211_send_rx_assoc(rdev, dev, buf, len, gfp);
}
EXPORT_SYMBOL(cfg80211_send_rx_assoc);
-void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
+void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
{
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_deauth(rdev, dev, buf, len);
+ nl80211_send_deauth(rdev, dev, buf, len, gfp);
}
EXPORT_SYMBOL(cfg80211_send_deauth);
-void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
+void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
{
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_disassoc(rdev, dev, buf, len);
+ nl80211_send_disassoc(rdev, dev, buf, len, gfp);
}
EXPORT_SYMBOL(cfg80211_send_disassoc);
@@ -53,33 +53,33 @@ static void cfg80211_wext_disconnected(s
#endif
}
-void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
+void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr, gfp_t gfp)
{
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_auth_timeout(rdev, dev, addr);
+ nl80211_send_auth_timeout(rdev, dev, addr, gfp);
cfg80211_wext_disconnected(dev);
}
EXPORT_SYMBOL(cfg80211_send_auth_timeout);
-void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
+void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr, gfp_t gfp)
{
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_assoc_timeout(rdev, dev, addr);
+ nl80211_send_assoc_timeout(rdev, dev, addr, gfp);
cfg80211_wext_disconnected(dev);
}
EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
enum nl80211_key_type key_type, int key_id,
- const u8 *tsc)
+ const u8 *tsc, gfp_t gfp)
{
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
#ifdef CONFIG_WIRELESS_EXT
union iwreq_data wrqu;
- char *buf = kmalloc(128, GFP_ATOMIC);
+ char *buf = kmalloc(128, gfp);
if (buf) {
sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
@@ -93,6 +93,6 @@ void cfg80211_michael_mic_failure(struct
}
#endif
- nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc);
+ nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
}
EXPORT_SYMBOL(cfg80211_michael_mic_failure);
--- wireless-testing.orig/net/wireless/nl80211.c 2009-07-01 08:56:30.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.c 2009-07-01 09:01:15.000000000 +0200
@@ -3831,12 +3831,12 @@ nla_put_failure:
static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
const u8 *buf, size_t len,
- enum nl80211_commands cmd)
+ enum nl80211_commands cmd, gfp_t gfp)
{
struct sk_buff *msg;
void *hdr;
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
if (!msg)
return;
@@ -3855,7 +3855,7 @@ static void nl80211_send_mlme_event(stru
return;
}
- genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
return;
nla_put_failure:
@@ -3864,42 +3864,45 @@ static void nl80211_send_mlme_event(stru
}
void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, const u8 *buf, size_t len)
+ struct net_device *netdev, const u8 *buf,
+ size_t len, gfp_t gfp)
{
nl80211_send_mlme_event(rdev, netdev, buf, len,
- NL80211_CMD_AUTHENTICATE);
+ NL80211_CMD_AUTHENTICATE, gfp);
}
void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *buf,
- size_t len)
+ size_t len, gfp_t gfp)
{
- nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_ASSOCIATE);
+ nl80211_send_mlme_event(rdev, netdev, buf, len,
+ NL80211_CMD_ASSOCIATE, gfp);
}
void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, const u8 *buf, size_t len)
+ struct net_device *netdev, const u8 *buf,
+ size_t len, gfp_t gfp)
{
nl80211_send_mlme_event(rdev, netdev, buf, len,
- NL80211_CMD_DEAUTHENTICATE);
+ NL80211_CMD_DEAUTHENTICATE, gfp);
}
void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *buf,
- size_t len)
+ size_t len, gfp_t gfp)
{
nl80211_send_mlme_event(rdev, netdev, buf, len,
- NL80211_CMD_DISASSOCIATE);
+ NL80211_CMD_DISASSOCIATE, gfp);
}
static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
struct net_device *netdev, int cmd,
- const u8 *addr)
+ const u8 *addr, gfp_t gfp)
{
struct sk_buff *msg;
void *hdr;
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
if (!msg)
return;
@@ -3919,7 +3922,7 @@ static void nl80211_send_mlme_timeout(st
return;
}
- genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
return;
nla_put_failure:
@@ -3928,16 +3931,19 @@ static void nl80211_send_mlme_timeout(st
}
void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, const u8 *addr)
+ struct net_device *netdev, const u8 *addr,
+ gfp_t gfp)
{
nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
- addr);
+ addr, gfp);
}
void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, const u8 *addr)
+ struct net_device *netdev, const u8 *addr,
+ gfp_t gfp)
{
- nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE, addr);
+ nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE,
+ addr, gfp);
}
void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
@@ -3977,12 +3983,12 @@ void nl80211_send_ibss_bssid(struct cfg8
void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *addr,
enum nl80211_key_type key_type, int key_id,
- const u8 *tsc)
+ const u8 *tsc, gfp_t gfp)
{
struct sk_buff *msg;
void *hdr;
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
if (!msg)
return;
@@ -4006,7 +4012,7 @@ void nl80211_michael_mic_failure(struct
return;
}
- genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
return;
nla_put_failure:
--- wireless-testing.orig/net/wireless/nl80211.h 2009-07-01 08:59:44.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.h 2009-07-01 09:01:15.000000000 +0200
@@ -15,27 +15,27 @@ void nl80211_send_scan_aborted(struct cf
void nl80211_send_reg_change_event(struct regulatory_request *request);
void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
- const u8 *buf, size_t len);
+ const u8 *buf, size_t len, gfp_t gfp);
void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
- const u8 *buf, size_t len);
+ const u8 *buf, size_t len, gfp_t gfp);
void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
- const u8 *buf, size_t len);
+ const u8 *buf, size_t len, gfp_t gfp);
void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
- const u8 *buf, size_t len);
+ const u8 *buf, size_t len, gfp_t gfp);
void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
- const u8 *addr);
+ const u8 *addr, gfp_t gfp);
void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
- const u8 *addr);
+ const u8 *addr, gfp_t gfp);
void
nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *addr,
enum nl80211_key_type key_type,
- int key_id, const u8 *tsc);
+ int key_id, const u8 *tsc, gfp_t gfp);
void
nl80211_send_beacon_hint_event(struct wiphy *wiphy,
--- wireless-testing.orig/net/mac80211/mlme.c 2009-07-01 08:55:07.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c 2009-07-01 09:01:15.000000000 +0200
@@ -419,9 +419,11 @@ static void ieee80211_send_deauth_disass
mgmt->u.deauth.reason_code = cpu_to_le16(reason);
if (stype == IEEE80211_STYPE_DEAUTH)
- cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, skb->len);
+ cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, skb->len,
+ GFP_KERNEL);
else
- cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, skb->len);
+ cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, skb->len,
+ GFP_KERNEL);
ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED);
}
@@ -1006,7 +1008,8 @@ static void ieee80211_direct_probe(struc
sdata->dev->name, ifmgd->bssid);
ifmgd->state = IEEE80211_STA_MLME_DISABLED;
ieee80211_recalc_idle(local);
- cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid);
+ cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid,
+ GFP_KERNEL);
/*
* Most likely AP is not in the range so remove the
@@ -1055,7 +1058,8 @@ static void ieee80211_authenticate(struc
sdata->dev->name, ifmgd->bssid);
ifmgd->state = IEEE80211_STA_MLME_DISABLED;
ieee80211_recalc_idle(local);
- cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid);
+ cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid,
+ GFP_KERNEL);
ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
sdata->local->hw.conf.channel->center_freq,
ifmgd->ssid, ifmgd->ssid_len);
@@ -1243,7 +1247,8 @@ static void ieee80211_associate(struct i
sdata->dev->name, ifmgd->bssid);
ifmgd->state = IEEE80211_STA_MLME_DISABLED;
ieee80211_recalc_idle(local);
- cfg80211_send_assoc_timeout(sdata->dev, ifmgd->bssid);
+ cfg80211_send_assoc_timeout(sdata->dev, ifmgd->bssid,
+ GFP_KERNEL);
ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
sdata->local->hw.conf.channel->center_freq,
ifmgd->ssid, ifmgd->ssid_len);
@@ -1517,12 +1522,14 @@ static void ieee80211_rx_mgmt_auth(struc
case WLAN_AUTH_LEAP:
case WLAN_AUTH_FT:
ieee80211_auth_completed(sdata);
- cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len);
+ cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len,
+ GFP_KERNEL);
break;
case WLAN_AUTH_SHARED_KEY:
if (ifmgd->auth_transaction == 4) {
ieee80211_auth_completed(sdata);
- cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len);
+ cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len,
+ GFP_KERNEL);
} else
ieee80211_auth_challenge(sdata, mgmt, len);
break;
@@ -1560,7 +1567,7 @@ static void ieee80211_rx_mgmt_deauth(str
ieee80211_set_disassoc(sdata, true, false, 0);
ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED;
- cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, len);
+ cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, len, GFP_KERNEL);
}
@@ -1591,7 +1598,7 @@ static void ieee80211_rx_mgmt_disassoc(s
}
ieee80211_set_disassoc(sdata, false, false, reason_code);
- cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, len);
+ cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, len, GFP_KERNEL);
}
@@ -1660,7 +1667,8 @@ static void ieee80211_rx_mgmt_assoc_resp
* association next time. This works around some broken APs
* which do not correctly reject reassociation requests. */
ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
- cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len);
+ cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len,
+ GFP_KERNEL);
if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
/* Wait for SME to decide what to do next */
ifmgd->state = IEEE80211_STA_MLME_DISABLED;
@@ -1823,7 +1831,7 @@ static void ieee80211_rx_mgmt_assoc_resp
ifmgd->last_beacon = jiffies;
ieee80211_associated(sdata);
- cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len);
+ cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len, GFP_KERNEL);
}
--- wireless-testing.orig/net/mac80211/event.c 2009-07-01 08:55:07.000000000 +0200
+++ wireless-testing/net/mac80211/event.c 2009-07-01 09:01:15.000000000 +0200
@@ -16,11 +16,12 @@
* driver or is still in the frame), it should provide that information.
*/
void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
- struct ieee80211_hdr *hdr, const u8 *tsc)
+ struct ieee80211_hdr *hdr, const u8 *tsc,
+ gfp_t gfp)
{
cfg80211_michael_mic_failure(sdata->dev, hdr->addr2,
(hdr->addr1[0] & 0x01) ?
NL80211_KEYTYPE_GROUP :
NL80211_KEYTYPE_PAIRWISE,
- keyidx, tsc);
+ keyidx, tsc, gfp);
}
--- wireless-testing.orig/net/mac80211/ieee80211_i.h 2009-07-01 08:55:07.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h 2009-07-01 09:01:15.000000000 +0200
@@ -1085,7 +1085,8 @@ u8 *ieee80211_get_bssid(struct ieee80211
int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
int rate, int erp, int short_preamble);
void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
- struct ieee80211_hdr *hdr, const u8 *tsc);
+ struct ieee80211_hdr *hdr, const u8 *tsc,
+ gfp_t gfp);
void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata);
void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
int encrypt);
--- wireless-testing.orig/net/mac80211/rx.c 2009-07-01 08:55:07.000000000 +0200
+++ wireless-testing/net/mac80211/rx.c 2009-07-01 09:01:15.000000000 +0200
@@ -1868,7 +1868,8 @@ static void ieee80211_rx_michael_mic_rep
!ieee80211_is_auth(hdr->frame_control))
goto ignore;
- mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL);
+ mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL,
+ GFP_ATOMIC);
ignore:
dev_kfree_skb(rx->skb);
rx->skb = NULL;
--- wireless-testing.orig/net/mac80211/wpa.c 2009-07-01 08:55:07.000000000 +0200
+++ wireless-testing/net/mac80211/wpa.c 2009-07-01 09:01:15.000000000 +0200
@@ -122,7 +122,8 @@ ieee80211_rx_h_michael_mic_verify(struct
return RX_DROP_UNUSABLE;
mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx,
- (void *) skb->data, NULL);
+ (void *) skb->data, NULL,
+ GFP_ATOMIC);
return RX_DROP_UNUSABLE;
}
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 07/20 v4] cfg80211: remove wireless_dev->bssid
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (5 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 06/20 v4] cfg80211: use proper allocation flags Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 08/20 v4] mac80211: tell SME about real auth state Johannes Berg
` (15 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
This variable isn't necessary -- the wext code keeps
track of the BSSID itself, and otherwise we have
current_bss.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/net/cfg80211.h | 1 -
net/wireless/ibss.c | 13 +++----------
2 files changed, 3 insertions(+), 11 deletions(-)
--- wireless-testing.orig/net/wireless/ibss.c 2009-07-01 08:55:06.000000000 +0200
+++ wireless-testing/net/wireless/ibss.c 2009-07-01 09:01:19.000000000 +0200
@@ -24,9 +24,6 @@ void cfg80211_ibss_joined(struct net_dev
if (WARN_ON(!wdev->ssid_len))
return;
- if (memcmp(bssid, wdev->bssid, ETH_ALEN) == 0)
- return;
-
bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
wdev->ssid, wdev->ssid_len,
WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
@@ -41,7 +38,6 @@ void cfg80211_ibss_joined(struct net_dev
cfg80211_hold_bss(bss);
wdev->current_bss = bss;
- memcpy(wdev->bssid, bssid, ETH_ALEN);
nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, gfp);
#ifdef CONFIG_WIRELESS_EXT
@@ -87,7 +83,6 @@ void cfg80211_clear_ibss(struct net_devi
wdev->current_bss = NULL;
wdev->ssid_len = 0;
- memset(wdev->bssid, 0, ETH_ALEN);
#ifdef CONFIG_WIRELESS_EXT
if (!nowext)
wdev->wext.ibss.ssid_len = 0;
@@ -356,12 +351,10 @@ int cfg80211_ibss_wext_giwap(struct net_
ap_addr->sa_family = ARPHRD_ETHER;
- if (wdev->wext.ibss.bssid) {
+ if (wdev->current_bss)
+ memcpy(ap_addr->sa_data, wdev->current_bss->bssid, ETH_ALEN);
+ else
memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN);
- return 0;
- }
-
- memcpy(ap_addr->sa_data, wdev->bssid, ETH_ALEN);
return 0;
}
/* temporary symbol - mark GPL - in the future the handler won't be */
--- wireless-testing.orig/include/net/cfg80211.h 2009-07-01 09:01:15.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h 2009-07-01 09:01:19.000000000 +0200
@@ -1170,7 +1170,6 @@ struct wireless_dev {
/* currently used for IBSS - might be rearranged in the future */
struct cfg80211_bss *current_bss;
- u8 bssid[ETH_ALEN];
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ssid_len;
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 08/20 v4] mac80211: tell SME about real auth state
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (6 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 07/20 v4] cfg80211: remove wireless_dev->bssid Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 09/20 v4] wext: constify extra argument to wireless_send_event Johannes Berg
` (14 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
When the auth algorithm is rejected, but we don't have
another one to try, we will eventually retry but that
isn't useful -- we'll then do it again and again until
we eventually give up. Instead, we should let the SME
know and go into disabled state. The same applies for
situations where the AP rejects with any other status
code.
Additionally, when trying the next auth algorithm, we
should reset the auth_tries so that just a single lost
frame doesn't lead to us giving up on the third auth
algorithm.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/mlme.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- wireless-testing.orig/net/mac80211/mlme.c 2009-07-01 09:01:15.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c 2009-07-01 09:01:19.000000000 +0200
@@ -1511,9 +1511,15 @@ static void ieee80211_rx_mgmt_auth(struc
!ieee80211_sta_wep_configured(sdata))
continue;
ifmgd->auth_alg = algs[pos];
- break;
+ ifmgd->auth_tries = 0;
+ return;
}
}
+ /* nothing else to try -- give up */
+ cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len,
+ GFP_KERNEL);
+ ifmgd->state = IEEE80211_STA_MLME_DISABLED;
+ ieee80211_recalc_idle(sdata->local);
return;
}
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 09/20 v4] wext: constify extra argument to wireless_send_event
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (7 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 08/20 v4] mac80211: tell SME about real auth state Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 10/20 v4] cfg80211: introduce nl80211 testmode command Johannes Berg
` (13 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
This is never changed by the function, so can be marked const.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/net/iw_handler.h | 2 +-
net/wireless/wext.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
--- wireless-testing.orig/include/net/iw_handler.h 2009-07-01 08:55:06.000000000 +0200
+++ wireless-testing/include/net/iw_handler.h 2009-07-01 09:01:20.000000000 +0200
@@ -443,7 +443,7 @@ extern int dev_get_wireless_info(char *
extern void wireless_send_event(struct net_device * dev,
unsigned int cmd,
union iwreq_data * wrqu,
- char * extra);
+ const char * extra);
/* We may need a function to send a stream of events to user space.
* More on that later... */
--- wireless-testing.orig/net/wireless/wext.c 2009-07-01 08:59:43.000000000 +0200
+++ wireless-testing/net/wireless/wext.c 2009-07-01 09:01:20.000000000 +0200
@@ -1376,7 +1376,7 @@ static void rtmsg_iwinfo(struct net_devi
void wireless_send_event(struct net_device * dev,
unsigned int cmd,
union iwreq_data * wrqu,
- char * extra)
+ const char * extra)
{
const struct iw_ioctl_description * descr = NULL;
int extra_len = 0;
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 10/20 v4] cfg80211: introduce nl80211 testmode command
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (8 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 09/20 v4] wext: constify extra argument to wireless_send_event Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 11/20 v4] mac80211: remove an unused function declaration Johannes Berg
` (12 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
This introduces a new NL80211_CMD_TESTMODE for testing
and calibration use with nl80211. There's no multiplexing
like like iwpriv had, and the command is not available by
default, it needs to be explicitly enabled in Kconfig and
shouldn't be enabled in most kernels.
The command requires a wiphy index or interface index to
identify the device to operate on, and the new TESTDATA
attribute. There also is API for sending replies to the
command, and testmode multicast messages (on a testmode
multicast group).
I've also updated mac80211 to be able to pass through the
command to the driver, since it itself doesn't implement
the testmode command.
Additionally, to give people an idea of how to use the
command, I've added a little code to hwsim that makes use
of the new command to set the powersave mode, this is
currently done via debugfs and should remain there, and
the testmode command only serves as an example of how to
use this best -- with nested netlink attributes in the
TESTDATA attribute. A hwsim testmode tool can be found at
http://git.sipsolutions.net/hwsim.git/. This tool is BSD
licensed so people can easily use it as a basis for their
own internal fabrication and validation tools.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
I haven't implemented dumping because right now I'm not sure
how to, nor whether people will use it when they can allocate
larger skbs for more data which in test environments should
be acceptable.
drivers/net/wireless/mac80211_hwsim.c | 68 +++++++++++++++++
include/linux/nl80211.h | 11 ++
include/net/cfg80211.h | 83 ++++++++++++++++++++
include/net/mac80211.h | 5 +
net/mac80211/cfg.c | 13 +++
net/wireless/Kconfig | 15 +++
net/wireless/core.h | 4 +
net/wireless/nl80211.c | 136 ++++++++++++++++++++++++++++++++++
8 files changed, 335 insertions(+)
--- wireless-testing.orig/include/linux/nl80211.h 2009-07-01 08:55:06.000000000 +0200
+++ wireless-testing/include/linux/nl80211.h 2009-07-01 09:01:20.000000000 +0200
@@ -242,6 +242,10 @@
* @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is
* determined by the network interface.
*
+ * @NL80211_CMD_TESTMODE: testmode command, takes a wiphy (or ifindex) attribute
+ * to identify the device, and the TESTDATA blob attribute to pass through
+ * to the driver.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -310,6 +314,8 @@ enum nl80211_commands {
NL80211_CMD_JOIN_IBSS,
NL80211_CMD_LEAVE_IBSS,
+ NL80211_CMD_TESTMODE,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -511,6 +517,9 @@ enum nl80211_commands {
* authorized by user space. Otherwise, port is marked authorized by
* default in station mode.
*
+ * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver.
+ * We recommend using nested, driver-specific attributes within this.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -619,6 +628,8 @@ enum nl80211_attrs {
NL80211_ATTR_CONTROL_PORT,
+ NL80211_ATTR_TESTDATA,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
--- wireless-testing.orig/include/net/cfg80211.h 2009-07-01 09:01:19.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h 2009-07-01 09:01:20.000000000 +0200
@@ -857,6 +857,8 @@ enum tx_power_setting {
*
* @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting
* functions to adjust rfkill hw state
+ *
+ * @testmode_cmd: run a test mode command
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy);
@@ -955,6 +957,10 @@ struct cfg80211_ops {
int (*get_tx_power)(struct wiphy *wiphy, int *dbm);
void (*rfkill_poll)(struct wiphy *wiphy);
+
+#ifdef CONFIG_NL80211_TESTMODE
+ int (*testmode_cmd)(struct wiphy *wiphy, void *data, int len);
+#endif
};
/*
@@ -1705,4 +1711,81 @@ void wiphy_rfkill_start_polling(struct w
*/
void wiphy_rfkill_stop_polling(struct wiphy *wiphy);
+#ifdef CONFIG_NL80211_TESTMODE
+/**
+ * cfg80211_testmode_alloc_reply_skb - allocate testmode reply
+ * @wiphy: the wiphy
+ * @approxlen: an upper bound of the length of the data that will
+ * be put into the skb
+ *
+ * This function allocates and pre-fills an skb for a reply to
+ * the testmode command. Since it is intended for a reply, calling
+ * it outside of the @testmode_cmd operation is invalid.
+ *
+ * The returned skb (or %NULL if any errors happen) is pre-filled
+ * with the wiphy index and set up in a way that any data that is
+ * put into the skb (with skb_put(), nla_put() or similar) will end
+ * up being within the %NL80211_ATTR_TESTDATA attribute, so all that
+ * needs to be done with the skb is adding data for the corresponding
+ * userspace tool which can then read that data out of the testdata
+ * attribute. You must not modify the skb in any other way.
+ *
+ * When done, call cfg80211_testmode_reply() with the skb and return
+ * its error code as the result of the @testmode_cmd operation.
+ */
+struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
+ int approxlen);
+
+/**
+ * cfg80211_testmode_reply - send the reply skb
+ * @skb: The skb, must have been allocated with
+ * cfg80211_testmode_alloc_reply_skb()
+ *
+ * Returns an error code or 0 on success, since calling this
+ * function will usually be the last thing before returning
+ * from the @testmode_cmd you should return the error code.
+ * Note that this function consumes the skb regardless of the
+ * return value.
+ */
+int cfg80211_testmode_reply(struct sk_buff *skb);
+
+/**
+ * cfg80211_testmode_alloc_event_skb - allocate testmode event
+ * @wiphy: the wiphy
+ * @approxlen: an upper bound of the length of the data that will
+ * be put into the skb
+ * @gfp: allocation flags
+ *
+ * This function allocates and pre-fills an skb for an event on the
+ * testmode multicast group.
+ *
+ * The returned skb (or %NULL if any errors happen) is set up in the
+ * same way as with cfg80211_testmode_alloc_reply_skb() but prepared
+ * for an event. As there, you should simply add data to it that will
+ * then end up in the %NL80211_ATTR_TESTDATA attribute. Again, you must
+ * not modify the skb in any other way.
+ *
+ * When done filling the skb, call cfg80211_testmode_event() with the
+ * skb to send the event.
+ */
+struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
+ int approxlen, gfp_t gfp);
+
+/**
+ * cfg80211_testmode_event - send the event
+ * @skb: The skb, must have been allocated with
+ * cfg80211_testmode_alloc_event_skb()
+ * @gfp: allocation flags
+ *
+ * This function sends the given @skb, which must have been allocated
+ * by cfg80211_testmode_alloc_event_skb(), as an event. It always
+ * consumes it.
+ */
+void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp);
+
+#define CFG80211_TESTMODE_CMD(cmd) .testmode_cmd = (cmd),
+#else
+#define CFG80211_TESTMODE_CMD(cmd)
+#endif
+
#endif /* __NET_CFG80211_H */
--- wireless-testing.orig/net/wireless/Kconfig 2009-07-01 08:59:43.000000000 +0200
+++ wireless-testing/net/wireless/Kconfig 2009-07-01 09:01:20.000000000 +0200
@@ -2,6 +2,21 @@ config CFG80211
tristate "Improved wireless configuration API"
depends on RFKILL || !RFKILL
+config NL80211_TESTMODE
+ bool "nl80211 testmode command"
+ depends on CFG80211
+ help
+ The nl80211 testmode command helps implementing things like
+ factory calibration or validation tools for wireless chips.
+
+ Select this option ONLY for kernels that are specifically
+ built for such purposes.
+
+ Debugging tools that are supposed to end up in the hands of
+ users should better be implemented with debugfs.
+
+ Say N.
+
config CFG80211_REG_DEBUG
bool "cfg80211 regulatory debugging"
depends on CFG80211
--- wireless-testing.orig/net/wireless/core.h 2009-07-01 08:55:05.000000000 +0200
+++ wireless-testing/net/wireless/core.h 2009-07-01 09:01:20.000000000 +0200
@@ -58,6 +58,10 @@ struct cfg80211_registered_device {
struct cfg80211_scan_request *scan_req; /* protected by RTNL */
unsigned long suspend_at;
+#ifdef CONFIG_NL80211_TESTMODE
+ struct genl_info *testmode_info;
+#endif
+
#ifdef CONFIG_CFG80211_DEBUGFS
/* Debugfs entries */
struct wiphy_debugfsdentries {
--- wireless-testing.orig/net/wireless/nl80211.c 2009-07-01 09:01:15.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.c 2009-07-01 09:01:20.000000000 +0200
@@ -3415,6 +3415,128 @@ unlock_rtnl:
return err;
}
+#ifdef CONFIG_NL80211_TESTMODE
+static struct genl_multicast_group nl80211_testmode_mcgrp = {
+ .name = "testmode",
+};
+
+static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev;
+ int err;
+
+ if (!info->attrs[NL80211_ATTR_TESTDATA])
+ return -EINVAL;
+
+ rtnl_lock();
+
+ rdev = cfg80211_get_dev_from_info(info);
+ if (IS_ERR(rdev)) {
+ err = PTR_ERR(rdev);
+ goto unlock_rtnl;
+ }
+
+ err = -EOPNOTSUPP;
+ if (rdev->ops->testmode_cmd) {
+ rdev->testmode_info = info;
+ err = rdev->ops->testmode_cmd(&rdev->wiphy,
+ nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
+ nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
+ rdev->testmode_info = NULL;
+ }
+
+ cfg80211_put_dev(rdev);
+
+ unlock_rtnl:
+ rtnl_unlock();
+ return err;
+}
+
+static struct sk_buff *
+__cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev,
+ int approxlen, u32 pid, u32 seq, gfp_t gfp)
+{
+ struct sk_buff *skb;
+ void *hdr;
+ struct nlattr *data;
+
+ skb = nlmsg_new(approxlen + 100, gfp);
+ if (!skb)
+ return NULL;
+
+ hdr = nl80211hdr_put(skb, pid, seq, 0, NL80211_CMD_TESTMODE);
+ if (!hdr) {
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ NLA_PUT_U32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+ data = nla_nest_start(skb, NL80211_ATTR_TESTDATA);
+
+ ((void **)skb->cb)[0] = rdev;
+ ((void **)skb->cb)[1] = hdr;
+ ((void **)skb->cb)[2] = data;
+
+ return skb;
+
+ nla_put_failure:
+ kfree_skb(skb);
+ return NULL;
+}
+
+struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
+ int approxlen)
+{
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+ if (WARN_ON(!rdev->testmode_info))
+ return NULL;
+
+ return __cfg80211_testmode_alloc_skb(rdev, approxlen,
+ rdev->testmode_info->snd_pid,
+ rdev->testmode_info->snd_seq,
+ GFP_KERNEL);
+}
+EXPORT_SYMBOL(cfg80211_testmode_alloc_reply_skb);
+
+int cfg80211_testmode_reply(struct sk_buff *skb)
+{
+ struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
+ void *hdr = ((void **)skb->cb)[1];
+ struct nlattr *data = ((void **)skb->cb)[2];
+
+ if (WARN_ON(!rdev->testmode_info)) {
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ nla_nest_end(skb, data);
+ genlmsg_end(skb, hdr);
+ return genlmsg_reply(skb, rdev->testmode_info);
+}
+EXPORT_SYMBOL(cfg80211_testmode_reply);
+
+struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
+ int approxlen, gfp_t gfp)
+{
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+ return __cfg80211_testmode_alloc_skb(rdev, approxlen, 0, 0, gfp);
+}
+EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb);
+
+void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
+{
+ void *hdr = ((void **)skb->cb)[1];
+ struct nlattr *data = ((void **)skb->cb)[2];
+
+ nla_nest_end(skb, data);
+ genlmsg_end(skb, hdr);
+ genlmsg_multicast(skb, 0, nl80211_testmode_mcgrp.id, gfp);
+}
+EXPORT_SYMBOL(cfg80211_testmode_event);
+#endif
+
static struct genl_ops nl80211_ops[] = {
{
.cmd = NL80211_CMD_GET_WIPHY,
@@ -3628,6 +3750,14 @@ static struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
},
+#ifdef CONFIG_NL80211_TESTMODE
+ {
+ .cmd = NL80211_CMD_TESTMODE,
+ .doit = nl80211_testmode_do,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+#endif
};
static struct genl_multicast_group nl80211_mlme_mcgrp = {
.name = "mlme",
@@ -4101,6 +4231,12 @@ int nl80211_init(void)
if (err)
goto err_out;
+#ifdef CONFIG_NL80211_TESTMODE
+ err = genl_register_mc_group(&nl80211_fam, &nl80211_testmode_mcgrp);
+ if (err)
+ goto err_out;
+#endif
+
return 0;
err_out:
genl_unregister_family(&nl80211_fam);
--- wireless-testing.orig/include/net/mac80211.h 2009-07-01 08:55:06.000000000 +0200
+++ wireless-testing/include/net/mac80211.h 2009-07-01 09:01:20.000000000 +0200
@@ -1419,6 +1419,8 @@ enum ieee80211_ampdu_mlme_action {
* @rfkill_poll: Poll rfkill hardware state. If you need this, you also
* need to set wiphy->rfkill_poll to %true before registration,
* and need to call wiphy_rfkill_set_hw_state() in the callback.
+ *
+ * @testmode_cmd: Implement a cfg80211 test mode command.
*/
struct ieee80211_ops {
int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1469,6 +1471,9 @@ struct ieee80211_ops {
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
void (*rfkill_poll)(struct ieee80211_hw *hw);
+#ifdef CONFIG_NL80211_TESTMODE
+ int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
+#endif
};
/**
--- wireless-testing.orig/net/mac80211/cfg.c 2009-07-01 08:55:05.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c 2009-07-01 09:01:20.000000000 +0200
@@ -1376,6 +1376,18 @@ static void ieee80211_rfkill_poll(struct
drv_rfkill_poll(local);
}
+#ifdef CONFIG_NL80211_TESTMODE
+int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
+{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+
+ if (!local->ops->testmode_cmd)
+ return -EOPNOTSUPP;
+
+ return local->ops->testmode_cmd(&local->hw, data, len);
+}
+#endif
+
struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -1418,4 +1430,5 @@ struct cfg80211_ops mac80211_config_ops
.set_tx_power = ieee80211_set_tx_power,
.get_tx_power = ieee80211_get_tx_power,
.rfkill_poll = ieee80211_rfkill_poll,
+ CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
};
--- wireless-testing.orig/drivers/net/wireless/mac80211_hwsim.c 2009-07-01 08:56:08.000000000 +0200
+++ wireless-testing/drivers/net/wireless/mac80211_hwsim.c 2009-07-01 09:01:20.000000000 +0200
@@ -699,6 +699,73 @@ static int mac80211_hwsim_conf_tx(
return 0;
}
+#ifdef CONFIG_NL80211_TESTMODE
+/*
+ * This section contains example code for using netlink
+ * attributes with the testmode command in nl80211.
+ */
+
+/* These enums need to be kept in sync with userspace */
+enum hwsim_testmode_attr {
+ __HWSIM_TM_ATTR_INVALID = 0,
+ HWSIM_TM_ATTR_CMD = 1,
+ HWSIM_TM_ATTR_PS = 2,
+
+ /* keep last */
+ __HWSIM_TM_ATTR_AFTER_LAST,
+ HWSIM_TM_ATTR_MAX = __HWSIM_TM_ATTR_AFTER_LAST - 1
+};
+
+enum hwsim_testmode_cmd {
+ HWSIM_TM_CMD_SET_PS = 0,
+ HWSIM_TM_CMD_GET_PS = 1,
+};
+
+static const struct nla_policy hwsim_testmode_policy[HWSIM_TM_ATTR_MAX + 1] = {
+ [HWSIM_TM_ATTR_CMD] = { .type = NLA_U32 },
+ [HWSIM_TM_ATTR_PS] = { .type = NLA_U32 },
+};
+
+static int hwsim_fops_ps_write(void *dat, u64 val);
+
+int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
+{
+ struct mac80211_hwsim_data *hwsim = hw->priv;
+ struct nlattr *tb[HWSIM_TM_ATTR_MAX + 1];
+ struct sk_buff *skb;
+ int err, ps;
+
+ err = nla_parse(tb, HWSIM_TM_ATTR_MAX, data, len,
+ hwsim_testmode_policy);
+ if (err)
+ return err;
+
+ if (!tb[HWSIM_TM_ATTR_CMD])
+ return -EINVAL;
+
+ switch (nla_get_u32(tb[HWSIM_TM_ATTR_CMD])) {
+ case HWSIM_TM_CMD_SET_PS:
+ if (!tb[HWSIM_TM_ATTR_PS])
+ return -EINVAL;
+ ps = nla_get_u32(tb[HWSIM_TM_ATTR_PS]);
+ return hwsim_fops_ps_write(hwsim, ps);
+ case HWSIM_TM_CMD_GET_PS:
+ skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
+ nla_total_size(sizeof(u32)));
+ if (!skb)
+ return -ENOMEM;
+ NLA_PUT_U32(skb, HWSIM_TM_ATTR_PS, hwsim->ps);
+ return cfg80211_testmode_reply(skb);
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ nla_put_failure:
+ kfree_skb(skb);
+ return -ENOBUFS;
+}
+#endif
+
static const struct ieee80211_ops mac80211_hwsim_ops =
{
.tx = mac80211_hwsim_tx,
@@ -712,6 +779,7 @@ static const struct ieee80211_ops mac802
.sta_notify = mac80211_hwsim_sta_notify,
.set_tim = mac80211_hwsim_set_tim,
.conf_tx = mac80211_hwsim_conf_tx,
+ CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
};
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 11/20 v4] mac80211: remove an unused function declaration
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (9 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 10/20 v4] cfg80211: introduce nl80211 testmode command Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 12/20 v4] wireless: define AKM suites Johannes Berg
` (11 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
The ieee80211_scan_results function hasn't existed for a
long time now, so its declaration should be removed as
well.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/ieee80211_i.h | 3 ---
1 file changed, 3 deletions(-)
--- wireless-testing.orig/net/mac80211/ieee80211_i.h 2009-07-01 09:01:15.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h 2009-07-01 09:01:21.000000000 +0200
@@ -979,9 +979,6 @@ int ieee80211_request_internal_scan(stru
const u8 *ssid, u8 ssid_len);
int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
struct cfg80211_scan_request *req);
-int ieee80211_scan_results(struct ieee80211_local *local,
- struct iw_request_info *info,
- char *buf, size_t len);
void ieee80211_scan_cancel(struct ieee80211_local *local);
ieee80211_rx_result
ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 12/20 v4] wireless: define AKM suites
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (10 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 11/20 v4] mac80211: remove an unused function declaration Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 13/20 v4] cfg80211: connect/disconnect API Johannes Berg
` (10 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
We'll need these values for some drivers using connect API
and for wext compat code, so let's define them.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/linux/ieee80211.h | 4 ++++
1 file changed, 4 insertions(+)
--- wireless-testing.orig/include/linux/ieee80211.h 2009-07-01 08:55:05.000000000 +0200
+++ wireless-testing/include/linux/ieee80211.h 2009-07-01 09:01:21.000000000 +0200
@@ -1196,6 +1196,10 @@ enum ieee80211_sa_query_action {
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
+/* AKM suite selectors */
+#define WLAN_AKM_SUITE_8021X 0x000FAC01
+#define WLAN_AKM_SUITE_PSK 0x000FAC02
+
#define WLAN_MAX_KEY_LEN 32
/**
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 13/20 v4] cfg80211: connect/disconnect API
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (11 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 12/20 v4] wireless: define AKM suites Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 14/20 v4] cfg80211: emulate connect with auth/assoc Johannes Berg
` (9 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Samuel Ortiz
From: Samuel Ortiz <sameo@linux.intel.com>
This patch introduces the cfg80211 connect/disconnect API.
The goal here is to run the AUTH and ASSOC steps in one call.
This is needed for some fullmac cards that run both steps
directly from the target, after the host driver sends a
connect command.
Additionally, all the new crypto parameters for connect()
are now also valid for associate() -- although associate
requires the IEs to be used, the information can be useful
for drivers and should be given.
Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/linux/nl80211.h | 80 ++++++++++
include/net/cfg80211.h | 135 ++++++++++++++++-
net/mac80211/cfg.c | 2
net/wireless/Makefile | 2
net/wireless/core.c | 16 +-
net/wireless/core.h | 7
net/wireless/nl80211.c | 368 +++++++++++++++++++++++++++++++++++++++++++++++-
net/wireless/nl80211.h | 13 +
net/wireless/sme.c | 224 +++++++++++++++++++++++++++++
9 files changed, 829 insertions(+), 18 deletions(-)
--- wireless-testing.orig/include/linux/nl80211.h 2009-07-01 09:01:20.000000000 +0200
+++ wireless-testing/include/linux/nl80211.h 2009-07-01 09:01:22.000000000 +0200
@@ -246,6 +246,22 @@
* to identify the device, and the TESTDATA blob attribute to pass through
* to the driver.
*
+ * @NL80211_CMD_CONNECT: connection request and notification; this command
+ * requests to connect to a specified network but without separating
+ * auth and assoc steps. For this, you need to specify the SSID in a
+ * %NL80211_ATTR_SSID attribute, and can optionally specify the association
+ * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC,
+ * %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_CONTROL_PORT.
+ * It is also sent as an event, with the BSSID and response IEs when the
+ * connection is established or failed to be established. This can be
+ * determined by the STATUS_CODE attribute.
+ * @NL80211_CMD_ROAM: request that the card roam (currently not implemented),
+ * sent as an event when the card/driver roamed by itself.
+ * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
+ * userspace that a connection was dropped by the AP or due to other
+ * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and
+ * %NL80211_ATTR_REASON_CODE attributes are used.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -316,6 +332,10 @@ enum nl80211_commands {
NL80211_CMD_TESTMODE,
+ NL80211_CMD_CONNECT,
+ NL80211_CMD_ROAM,
+ NL80211_CMD_DISCONNECT,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -520,6 +540,30 @@ enum nl80211_commands {
* @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver.
* We recommend using nested, driver-specific attributes within this.
*
+ * @NL80211_ATTR_DISCONNECTED_BY_AP: A flag indicating that the DISCONNECT
+ * event was due to the AP disconnecting the station, and not due to
+ * a local disconnect request.
+ * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT
+ * event (u16)
+ * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating
+ * that protected APs should be used.
+ *
+ * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT and ASSOCIATE to
+ * indicate which unicast key ciphers will be used with the connection
+ * (an array of u32).
+ * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT and ASSOCIATE to indicate
+ * which group key cipher will be used with the connection (a u32).
+ * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT and ASSOCIATE to indicate
+ * which WPA version(s) the AP we want to associate with is using
+ * (a u32 with flags from &enum nl80211_wpa_versions).
+ * @NL80211_ATTR_AKM_SUITES: Used with CONNECT and ASSOCIATE to indicate
+ * which key management algorithm(s) to use (an array of u32).
+ *
+ * @NL80211_ATTR_REQ_IE: (Re)association request information elements as
+ * sent out by the card, for ROAM and successful CONNECT events.
+ * @NL80211_ATTR_RESP_IE: (Re)association response information elements as
+ * sent by peer, for ROAM and successful CONNECT events.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -630,6 +674,19 @@ enum nl80211_attrs {
NL80211_ATTR_TESTDATA,
+ NL80211_ATTR_PRIVACY,
+
+ NL80211_ATTR_DISCONNECTED_BY_AP,
+ NL80211_ATTR_STATUS_CODE,
+
+ NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
+ NL80211_ATTR_CIPHER_SUITE_GROUP,
+ NL80211_ATTR_WPA_VERSIONS,
+ NL80211_ATTR_AKM_SUITES,
+
+ NL80211_ATTR_REQ_IE,
+ NL80211_ATTR_RESP_IE,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -640,6 +697,7 @@ enum nl80211_attrs {
* Allow user space programs to use #ifdef on new attributes by defining them
* here
*/
+#define NL80211_CMD_CONNECT NL80211_CMD_CONNECT
#define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY
#define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES
#define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS
@@ -653,6 +711,10 @@ enum nl80211_attrs {
#define NL80211_ATTR_SSID NL80211_ATTR_SSID
#define NL80211_ATTR_AUTH_TYPE NL80211_ATTR_AUTH_TYPE
#define NL80211_ATTR_REASON_CODE NL80211_ATTR_REASON_CODE
+#define NL80211_ATTR_CIPHER_SUITES_PAIRWISE NL80211_ATTR_CIPHER_SUITES_PAIRWISE
+#define NL80211_ATTR_CIPHER_SUITE_GROUP NL80211_ATTR_CIPHER_SUITE_GROUP
+#define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS
+#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES
#define NL80211_MAX_SUPP_RATES 32
#define NL80211_MAX_SUPP_REG_RULES 32
@@ -661,6 +723,9 @@ enum nl80211_attrs {
#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
#define NL80211_HT_CAPABILITY_LEN 26
+#define NL80211_MAX_NR_CIPHER_SUITES 5
+#define NL80211_MAX_NR_AKM_SUITES 2
+
/**
* enum nl80211_iftype - (virtual) interface types
*
@@ -1205,12 +1270,22 @@ enum nl80211_bss {
* @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only)
* @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
* @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
+ * @__NL80211_AUTHTYPE_NUM: internal
+ * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
+ * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
+ * trying multiple times); this is invalid in netlink -- leave out
+ * the attribute for this on CONNECT commands.
*/
enum nl80211_auth_type {
NL80211_AUTHTYPE_OPEN_SYSTEM,
NL80211_AUTHTYPE_SHARED_KEY,
NL80211_AUTHTYPE_FT,
NL80211_AUTHTYPE_NETWORK_EAP,
+
+ /* keep last */
+ __NL80211_AUTHTYPE_NUM,
+ NL80211_AUTHTYPE_MAX = __NL80211_AUTHTYPE_NUM - 1,
+ NL80211_AUTHTYPE_AUTOMATIC
};
/**
@@ -1235,4 +1310,9 @@ enum nl80211_mfp {
NL80211_MFP_REQUIRED,
};
+enum nl80211_wpa_versions {
+ NL80211_WPA_VERSION_1 = 1 << 0,
+ NL80211_WPA_VERSION_2 = 1 << 1,
+};
+
#endif /* __LINUX_NL80211_H */
--- wireless-testing.orig/include/net/cfg80211.h 2009-07-01 09:01:20.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h 2009-07-01 09:01:22.000000000 +0200
@@ -605,6 +605,30 @@ struct cfg80211_bss {
};
/**
+ * struct cfg80211_crypto_settings - Crypto settings
+ * @wpa_versions: indicates which, if any, WPA versions are enabled
+ * (from enum nl80211_wpa_versions)
+ * @cipher_group: group key cipher suite (or 0 if unset)
+ * @n_ciphers_pairwise: number of AP supported unicast ciphers
+ * @ciphers_pairwise: unicast key cipher suites
+ * @n_akm_suites: number of AKM suites
+ * @akm_suites: AKM suites
+ * @control_port: Whether user space controls IEEE 802.1X port, i.e.,
+ * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is
+ * required to assume that the port is unauthorized until authorized by
+ * user space. Otherwise, port is marked authorized by default.
+ */
+struct cfg80211_crypto_settings {
+ u32 wpa_versions;
+ u32 cipher_group;
+ int n_ciphers_pairwise;
+ u32 ciphers_pairwise[NL80211_MAX_NR_CIPHER_SUITES];
+ int n_akm_suites;
+ u32 akm_suites[NL80211_MAX_NR_AKM_SUITES];
+ bool control_port;
+};
+
+/**
* struct cfg80211_auth_request - Authentication request data
*
* This structure provides information needed to complete IEEE 802.11
@@ -658,10 +682,7 @@ struct cfg80211_auth_request {
* @ie: Extra IEs to add to (Re)Association Request frame or %NULL
* @ie_len: Length of ie buffer in octets
* @use_mfp: Use management frame protection (IEEE 802.11w) in this association
- * @control_port: Whether user space controls IEEE 802.1X port, i.e.,
- * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is
- * required to assume that the port is unauthorized until authorized by
- * user space. Otherwise, port is marked authorized by default.
+ * @crypto: crypto settings
*/
struct cfg80211_assoc_request {
struct ieee80211_channel *chan;
@@ -671,7 +692,7 @@ struct cfg80211_assoc_request {
const u8 *ie;
size_t ie_len;
bool use_mfp;
- bool control_port;
+ struct cfg80211_crypto_settings crypto;
};
/**
@@ -738,6 +759,36 @@ struct cfg80211_ibss_params {
};
/**
+ * struct cfg80211_connect_params - Connection parameters
+ *
+ * This structure provides information needed to complete IEEE 802.11
+ * authentication and association.
+ *
+ * @channel: The channel to use or %NULL if not specified (auto-select based
+ * on scan results)
+ * @bssid: The AP BSSID or %NULL if not specified (auto-select based on scan
+ * results)
+ * @ssid: SSID
+ * @ssid_len: Length of ssid in octets
+ * @auth_type: Authentication type (algorithm)
+ * @assoc_ie: IEs for association request
+ * @assoc_ie_len: Length of assoc_ie in octets
+ * @privacy: indicates whether privacy-enabled APs should be used
+ * @crypto: crypto settings
+ */
+struct cfg80211_connect_params {
+ struct ieee80211_channel *channel;
+ u8 *bssid;
+ u8 *ssid;
+ size_t ssid_len;
+ enum nl80211_auth_type auth_type;
+ u8 *ie;
+ size_t ie_len;
+ bool privacy;
+ struct cfg80211_crypto_settings crypto;
+};
+
+/**
* enum wiphy_params_flags - set_wiphy_params bitfield values
* WIPHY_PARAM_RETRY_SHORT: wiphy->retry_short has changed
* WIPHY_PARAM_RETRY_LONG: wiphy->retry_long has changed
@@ -841,6 +892,12 @@ enum tx_power_setting {
* @deauth: Request to deauthenticate from the specified peer
* @disassoc: Request to disassociate from the specified peer
*
+ * @connect: Connect to the ESS with the specified parameters. When connected,
+ * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.
+ * If the connection fails for some reason, call cfg80211_connect_result()
+ * with the status from the AP.
+ * @disconnect: Disconnect from the BSS/ESS.
+ *
* @join_ibss: Join the specified IBSS (or create if necessary). Once done, call
* cfg80211_ibss_joined(), also call that function when changing BSSID due
* to a merge.
@@ -946,6 +1003,11 @@ struct cfg80211_ops {
int (*disassoc)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_disassoc_request *req);
+ int (*connect)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme);
+ int (*disconnect)(struct wiphy *wiphy, struct net_device *dev,
+ u16 reason_code);
+
int (*join_ibss)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ibss_params *params);
int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev);
@@ -1174,10 +1236,15 @@ struct wireless_dev {
struct list_head list;
struct net_device *netdev;
- /* currently used for IBSS - might be rearranged in the future */
+ /* currently used for IBSS and SME - might be rearranged later */
struct cfg80211_bss *current_bss;
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ssid_len;
+ enum {
+ CFG80211_SME_IDLE,
+ CFG80211_SME_CONNECTING, /* ->connect called */
+ CFG80211_SME_CONNECTED,
+ } sme_state;
#ifdef CONFIG_WIRELESS_EXT
/* wext data */
@@ -1788,4 +1855,60 @@ void cfg80211_testmode_event(struct sk_b
#define CFG80211_TESTMODE_CMD(cmd)
#endif
+/**
+ * cfg80211_connect_result - notify cfg80211 of connection result
+ *
+ * @dev: network device
+ * @bssid: the BSSID of the AP
+ * @req_ie: association request IEs (maybe be %NULL)
+ * @req_ie_len: association request IEs length
+ * @resp_ie: association response IEs (may be %NULL)
+ * @resp_ie_len: assoc response IEs length
+ * @status: status code, 0 for successful connection, use
+ * %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you
+ * the real status code for failures.
+ * @gfp: allocation flags
+ *
+ * It should be called by the underlying driver whenever connect() has
+ * succeeded.
+ */
+void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, gfp_t gfp);
+
+/**
+ * cfg80211_roamed - notify cfg80211 of roaming
+ *
+ * @dev: network device
+ * @bssid: the BSSID of the new AP
+ * @req_ie: association request IEs (maybe be %NULL)
+ * @req_ie_len: association request IEs length
+ * @resp_ie: association response IEs (may be %NULL)
+ * @resp_ie_len: assoc response IEs length
+ * @gfp: allocation flags
+ *
+ * It should be called by the underlying driver whenever it roamed
+ * from one AP to another while connected.
+ */
+void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp);
+
+/**
+ * cfg80211_disconnected - notify cfg80211 that connection was dropped
+ *
+ * @dev: network device
+ * @ie: information elements of the deauth/disassoc frame (may be %NULL)
+ * @ie_len: length of IEs
+ * @reason: reason code for the disconnection, set it to 0 if unknown
+ * @gfp: allocation flags
+ *
+ * After it calls this function, the driver should enter an idle state
+ * and not try to connect to any AP any more.
+ */
+void cfg80211_disconnected(struct net_device *dev, u16 reason,
+ u8 *ie, size_t ie_len, gfp_t gfp);
+
+
#endif /* __NET_CFG80211_H */
--- wireless-testing.orig/net/wireless/Makefile 2009-07-01 08:55:04.000000000 +0200
+++ wireless-testing/net/wireless/Makefile 2009-07-01 09:01:22.000000000 +0200
@@ -5,7 +5,7 @@ obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib8
obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
-cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o
+cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o sme.o
cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o
--- wireless-testing.orig/net/wireless/core.h 2009-07-01 09:01:20.000000000 +0200
+++ wireless-testing/net/wireless/core.h 2009-07-01 09:01:22.000000000 +0200
@@ -174,6 +174,13 @@ void cfg80211_clear_ibss(struct net_devi
int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
struct net_device *dev, bool nowext);
+/* SME */
+int cfg80211_connect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_connect_params *connect);
+int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u16 reason);
+
/* internal helpers */
int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
const u8 *mac_addr);
--- wireless-testing.orig/net/wireless/nl80211.c 2009-07-01 09:01:20.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.c 2009-07-01 09:01:22.000000000 +0200
@@ -128,6 +128,9 @@ static struct nla_policy nl80211_policy[
.len = sizeof(struct nl80211_sta_flag_update),
},
[NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
+ [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
+ [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
+ [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
};
/* IE validation */
@@ -347,6 +350,17 @@ static int nl80211_send_wiphy(struct sk_
CMD(join_ibss, JOIN_IBSS);
#undef CMD
+
+ if (dev->ops->connect) {
+ i++;
+ NLA_PUT_U32(msg, i, NL80211_CMD_CONNECT);
+ }
+
+ if (dev->ops->disconnect) {
+ i++;
+ NLA_PUT_U32(msg, i, NL80211_CMD_DISCONNECT);
+ }
+
nla_nest_end(msg, nl_cmds);
return genlmsg_end(msg, hdr);
@@ -3000,12 +3014,31 @@ static int nl80211_dump_scan(struct sk_b
static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type)
{
- return auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM ||
- auth_type == NL80211_AUTHTYPE_SHARED_KEY ||
- auth_type == NL80211_AUTHTYPE_FT ||
- auth_type == NL80211_AUTHTYPE_NETWORK_EAP;
+ return auth_type <= NL80211_AUTHTYPE_MAX;
+}
+
+static bool nl80211_valid_wpa_versions(u32 wpa_versions)
+{
+ return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
+ NL80211_WPA_VERSION_2));
+}
+
+static bool nl80211_valid_akm_suite(u32 akm)
+{
+ return akm == WLAN_AKM_SUITE_8021X ||
+ akm == WLAN_AKM_SUITE_PSK;
+}
+
+static bool nl80211_valid_cipher_suite(u32 cipher)
+{
+ return cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ cipher == WLAN_CIPHER_SUITE_WEP104 ||
+ cipher == WLAN_CIPHER_SUITE_TKIP ||
+ cipher == WLAN_CIPHER_SUITE_CCMP ||
+ cipher == WLAN_CIPHER_SUITE_AES_CMAC;
}
+
static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *drv;
@@ -3085,6 +3118,68 @@ unlock_rtnl:
return err;
}
+static int nl80211_crypto_settings(struct genl_info *info,
+ struct cfg80211_crypto_settings *settings)
+{
+ settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
+
+ if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
+ void *data;
+ int len, i;
+
+ data = nla_data(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
+ len = nla_len(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
+ settings->n_ciphers_pairwise = len / sizeof(u32);
+
+ if (len % sizeof(u32))
+ return -EINVAL;
+
+ if (settings->n_ciphers_pairwise > NL80211_MAX_NR_CIPHER_SUITES)
+ return -EINVAL;
+
+ memcpy(settings->ciphers_pairwise, data, len);
+
+ for (i = 0; i < settings->n_ciphers_pairwise; i++)
+ if (!nl80211_valid_cipher_suite(
+ settings->ciphers_pairwise[i]))
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) {
+ settings->cipher_group =
+ nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]);
+ if (!nl80211_valid_cipher_suite(settings->cipher_group))
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_WPA_VERSIONS]) {
+ settings->wpa_versions =
+ nla_get_u32(info->attrs[NL80211_ATTR_WPA_VERSIONS]);
+ if (!nl80211_valid_wpa_versions(settings->wpa_versions))
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
+ void *data;
+ int len, i;
+
+ data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
+ len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
+ settings->n_akm_suites = len / sizeof(u32);
+
+ if (len % sizeof(u32))
+ return -EINVAL;
+
+ memcpy(settings->akm_suites, data, len);
+
+ for (i = 0; i < settings->n_ciphers_pairwise; i++)
+ if (!nl80211_valid_akm_suite(settings->akm_suites[i]))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *drv;
@@ -3155,9 +3250,9 @@ static int nl80211_associate(struct sk_b
}
}
- req.control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
-
- err = drv->ops->assoc(&drv->wiphy, dev, &req);
+ err = nl80211_crypto_settings(info, &req.crypto);
+ if (!err)
+ err = drv->ops->assoc(&drv->wiphy, dev, &req);
out:
cfg80211_put_dev(drv);
@@ -3537,6 +3632,130 @@ void cfg80211_testmode_event(struct sk_b
EXPORT_SYMBOL(cfg80211_testmode_event);
#endif
+static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *drv;
+ struct net_device *dev;
+ struct cfg80211_connect_params connect;
+ struct wiphy *wiphy;
+ int err;
+
+ memset(&connect, 0, sizeof(connect));
+
+ if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
+ return -EINVAL;
+
+ if (!info->attrs[NL80211_ATTR_SSID] ||
+ !nla_len(info->attrs[NL80211_ATTR_SSID]))
+ return -EINVAL;
+
+ if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
+ connect.auth_type =
+ nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
+ if (!nl80211_valid_auth_type(connect.auth_type))
+ return -EINVAL;
+ } else
+ connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
+
+ connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
+
+ err = nl80211_crypto_settings(info, &connect.crypto);
+ if (err)
+ return err;
+ rtnl_lock();
+
+ err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ if (err)
+ goto unlock_rtnl;
+
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (!netif_running(dev)) {
+ err = -ENETDOWN;
+ goto out;
+ }
+
+ wiphy = &drv->wiphy;
+
+ connect.bssid = NULL;
+ connect.channel = NULL;
+ connect.auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
+
+ if (info->attrs[NL80211_ATTR_MAC])
+ connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
+ connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
+ connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
+
+ if (info->attrs[NL80211_ATTR_IE]) {
+ connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+ connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+ }
+
+ if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
+ connect.channel =
+ ieee80211_get_channel(wiphy,
+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
+ if (!connect.channel ||
+ connect.channel->flags & IEEE80211_CHAN_DISABLED) {
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
+ err = cfg80211_connect(drv, dev, &connect);
+
+out:
+ cfg80211_put_dev(drv);
+ dev_put(dev);
+unlock_rtnl:
+ rtnl_unlock();
+ return err;
+}
+
+static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *drv;
+ struct net_device *dev;
+ int err;
+ u16 reason;
+
+ if (!info->attrs[NL80211_ATTR_REASON_CODE])
+ reason = WLAN_REASON_DEAUTH_LEAVING;
+ else
+ reason = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
+
+ if (reason == 0)
+ return -EINVAL;
+
+ rtnl_lock();
+
+ err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ if (err)
+ goto unlock_rtnl;
+
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (!netif_running(dev)) {
+ err = -ENETDOWN;
+ goto out;
+ }
+
+ err = cfg80211_disconnect(drv, dev, reason);
+
+out:
+ cfg80211_put_dev(drv);
+ dev_put(dev);
+unlock_rtnl:
+ rtnl_unlock();
+ return err;
+}
+
static struct genl_ops nl80211_ops[] = {
{
.cmd = NL80211_CMD_GET_WIPHY,
@@ -3758,6 +3977,18 @@ static struct genl_ops nl80211_ops[] = {
.flags = GENL_ADMIN_PERM,
},
#endif
+ {
+ .cmd = NL80211_CMD_CONNECT,
+ .doit = nl80211_connect,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = NL80211_CMD_DISCONNECT,
+ .doit = nl80211_disconnect,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
};
static struct genl_multicast_group nl80211_mlme_mcgrp = {
.name = "mlme",
@@ -4076,6 +4307,129 @@ void nl80211_send_assoc_timeout(struct c
addr, gfp);
}
+void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, gfp_t gfp)
+{
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONNECT);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
+ if (bssid)
+ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
+ NLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status);
+ if (req_ie)
+ NLA_PUT(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie);
+ if (resp_ie)
+ NLA_PUT(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie);
+
+ if (genlmsg_end(msg, hdr) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
+ return;
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+
+}
+
+void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp)
+{
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ROAM);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
+ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
+ if (req_ie)
+ NLA_PUT(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie);
+ if (resp_ie)
+ NLA_PUT(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie);
+
+ if (genlmsg_end(msg, hdr) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
+ return;
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+
+}
+
+void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, u16 reason,
+ u8 *ie, size_t ie_len, bool from_ap, gfp_t gfp)
+{
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DISCONNECT);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
+ if (from_ap && reason)
+ NLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason);
+ if (from_ap)
+ NLA_PUT_FLAG(msg, NL80211_ATTR_DISCONNECTED_BY_AP);
+ if (ie)
+ NLA_PUT(msg, NL80211_ATTR_IE, ie_len, ie);
+
+ if (genlmsg_end(msg, hdr) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
+ return;
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+
+}
+
void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *bssid,
gfp_t gfp)
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ wireless-testing/net/wireless/sme.c 2009-07-01 09:01:22.000000000 +0200
@@ -0,0 +1,224 @@
+/*
+ * SME code for cfg80211's connect emulation.
+ *
+ * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <linux/workqueue.h>
+#include <net/cfg80211.h>
+#include <net/rtnetlink.h>
+#include "nl80211.h"
+
+
+void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, gfp_t gfp)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_bss *bss;
+#ifdef CONFIG_WIRELESS_EXT
+ union iwreq_data wrqu;
+#endif
+
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return;
+
+ if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING))
+ return;
+
+ if (wdev->current_bss) {
+ cfg80211_unhold_bss(wdev->current_bss);
+ cfg80211_put_bss(wdev->current_bss);
+ wdev->current_bss = NULL;
+ }
+
+ if (status == WLAN_STATUS_SUCCESS) {
+ bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
+ wdev->ssid, wdev->ssid_len,
+ WLAN_CAPABILITY_ESS,
+ WLAN_CAPABILITY_ESS);
+
+ if (WARN_ON(!bss))
+ return;
+
+ cfg80211_hold_bss(bss);
+ wdev->current_bss = bss;
+
+ wdev->sme_state = CFG80211_SME_CONNECTED;
+ } else {
+ wdev->sme_state = CFG80211_SME_IDLE;
+ }
+
+ nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, bssid,
+ req_ie, req_ie_len, resp_ie, resp_ie_len,
+ status, gfp);
+
+#ifdef CONFIG_WIRELESS_EXT
+ if (req_ie && status == WLAN_STATUS_SUCCESS) {
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = req_ie_len;
+ wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie);
+ }
+
+ if (resp_ie && status == WLAN_STATUS_SUCCESS) {
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = resp_ie_len;
+ wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
+ }
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ if (bssid)
+ memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
+ wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+#endif
+}
+EXPORT_SYMBOL(cfg80211_connect_result);
+
+void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_bss *bss;
+#ifdef CONFIG_WIRELESS_EXT
+ union iwreq_data wrqu;
+#endif
+
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return;
+
+ if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED))
+ return;
+
+ /* internal error -- how did we get to CONNECTED w/o BSS? */
+ if (WARN_ON(!wdev->current_bss)) {
+ return;
+ }
+
+ cfg80211_unhold_bss(wdev->current_bss);
+ cfg80211_put_bss(wdev->current_bss);
+ wdev->current_bss = NULL;
+
+ bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
+ wdev->ssid, wdev->ssid_len,
+ WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+
+ if (WARN_ON(!bss))
+ return;
+
+ cfg80211_hold_bss(bss);
+ wdev->current_bss = bss;
+
+ nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), dev, bssid,
+ req_ie, req_ie_len, resp_ie, resp_ie_len, gfp);
+
+#ifdef CONFIG_WIRELESS_EXT
+ if (req_ie) {
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = req_ie_len;
+ wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie);
+ }
+
+ if (resp_ie) {
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = resp_ie_len;
+ wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
+ }
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
+ wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+#endif
+}
+EXPORT_SYMBOL(cfg80211_roamed);
+
+static void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp,
+ u8 *ie, size_t ie_len, u16 reason,
+ bool from_ap)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+#ifdef CONFIG_WIRELESS_EXT
+ union iwreq_data wrqu;
+#endif
+
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return;
+
+ if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED))
+ return;
+
+ if (wdev->current_bss) {
+ cfg80211_unhold_bss(wdev->current_bss);
+ cfg80211_put_bss(wdev->current_bss);
+ }
+
+ wdev->current_bss = NULL;
+ wdev->sme_state = CFG80211_SME_IDLE;
+
+ nl80211_send_disconnected(wiphy_to_dev(wdev->wiphy), dev,
+ reason, ie, ie_len, from_ap, gfp);
+
+#ifdef CONFIG_WIRELESS_EXT
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+#endif
+}
+
+void cfg80211_disconnected(struct net_device *dev, u16 reason,
+ u8 *ie, size_t ie_len, gfp_t gfp)
+{
+ __cfg80211_disconnected(dev, reason, ie, ie_len, true, gfp);
+}
+EXPORT_SYMBOL(cfg80211_disconnected);
+
+int cfg80211_connect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_connect_params *connect)
+{
+ int err;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ if (wdev->sme_state != CFG80211_SME_IDLE)
+ return -EALREADY;
+
+ if (!rdev->ops->connect) {
+ return -EOPNOTSUPP;
+ } else {
+ wdev->sme_state = CFG80211_SME_CONNECTING;
+ err = rdev->ops->connect(&rdev->wiphy, dev, connect);
+ if (err) {
+ wdev->sme_state = CFG80211_SME_IDLE;
+ return err;
+ }
+ }
+
+ memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
+ wdev->ssid_len = connect->ssid_len;
+
+ return 0;
+}
+
+int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u16 reason)
+{
+ int err;
+
+ if (!rdev->ops->disconnect) {
+ return -EOPNOTSUPP;
+ } else {
+ err = rdev->ops->disconnect(&rdev->wiphy, dev, reason);
+ if (err)
+ return err;
+ }
+
+ __cfg80211_disconnected(dev, 0, NULL, 0, false, GFP_KERNEL);
+
+ return 0;
+}
--- wireless-testing.orig/net/wireless/core.c 2009-07-01 08:59:44.000000000 +0200
+++ wireless-testing/net/wireless/core.c 2009-07-01 09:01:22.000000000 +0200
@@ -546,6 +546,7 @@ static int cfg80211_netdev_notifier_call
"symlink to netdev!\n");
}
wdev->netdev = dev;
+ wdev->sme_state = CFG80211_SME_IDLE;
#ifdef CONFIG_WIRELESS_EXT
wdev->wext.default_key = -1;
wdev->wext.default_mgmt_key = -1;
@@ -553,11 +554,20 @@ static int cfg80211_netdev_notifier_call
mutex_unlock(&rdev->devlist_mtx);
break;
case NETDEV_GOING_DOWN:
- if (wdev->iftype != NL80211_IFTYPE_ADHOC)
- break;
if (!wdev->ssid_len)
break;
- cfg80211_leave_ibss(rdev, dev, true);
+
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ cfg80211_leave_ibss(rdev, dev, true);
+ break;
+ case NL80211_IFTYPE_STATION:
+ cfg80211_disconnect(rdev, dev,
+ WLAN_REASON_DEAUTH_LEAVING);
+ break;
+ default:
+ break;
+ }
break;
case NETDEV_UP:
#ifdef CONFIG_WIRELESS_EXT
--- wireless-testing.orig/net/wireless/nl80211.h 2009-07-01 09:01:15.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.h 2009-07-01 09:01:22.000000000 +0200
@@ -31,6 +31,19 @@ void nl80211_send_auth_timeout(struct cf
void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
const u8 *addr, gfp_t gfp);
+void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, gfp_t gfp);
+void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp);
+void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, u16 reason,
+ u8 *ie, size_t ie_len, bool from_ap, gfp_t gfp);
+
void
nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *addr,
--- wireless-testing.orig/net/mac80211/cfg.c 2009-07-01 09:01:20.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c 2009-07-01 09:01:22.000000000 +0200
@@ -1262,7 +1262,7 @@ static int ieee80211_assoc(struct wiphy
sdata->u.mgd.flags &= ~IEEE80211_STA_MFP_ENABLED;
}
- if (req->control_port)
+ if (req->crypto.control_port)
sdata->u.mgd.flags |= IEEE80211_STA_CONTROL_PORT;
else
sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 14/20 v4] cfg80211: emulate connect with auth/assoc
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (12 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 13/20 v4] cfg80211: connect/disconnect API Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-02 7:13 ` [PATCH 14/20 v4.1] " Johannes Berg
2009-07-01 19:26 ` [PATCH 15/20 v4] cfg80211: managed mode wext compatibility Johannes Berg
` (8 subsequent siblings)
22 siblings, 1 reply; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Samuel Ortiz
This adds code to cfg80211 so that drivers (mac80211 right
now) that don't implement connect but rather auth/assoc can
still be used with the nl80211 connect command. This will
also be necessary for the wext compat code.
Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
v4: dynamically allocate conn data
include/net/cfg80211.h | 6
net/wireless/core.c | 7
net/wireless/core.h | 8 +
net/wireless/mlme.c | 81 ++++++++--
net/wireless/nl80211.c | 4
net/wireless/scan.c | 7
net/wireless/sme.c | 390 +++++++++++++++++++++++++++++++++++++++++++++++--
7 files changed, 471 insertions(+), 32 deletions(-)
--- wireless-testing.orig/net/wireless/core.h 2009-07-01 09:37:28.000000000 +0200
+++ wireless-testing/net/wireless/core.h 2009-07-01 19:44:19.000000000 +0200
@@ -62,6 +62,8 @@ struct cfg80211_registered_device {
struct genl_info *testmode_info;
#endif
+ struct work_struct conn_work;
+
#ifdef CONFIG_CFG80211_DEBUGFS
/* Debugfs entries */
struct wiphy_debugfsdentries {
@@ -181,8 +183,14 @@ int cfg80211_connect(struct cfg80211_reg
int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
struct net_device *dev, u16 reason);
+void cfg80211_conn_work(struct work_struct *work);
+
/* internal helpers */
int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
const u8 *mac_addr);
+void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp, u8 *ie,
+ size_t ie_len, u16 reason, bool from_ap);
+void cfg80211_sme_scan_done(struct net_device *dev);
+void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
#endif /* __NET_WIRELESS_CORE_H */
--- wireless-testing.orig/net/wireless/nl80211.c 2009-07-01 09:37:28.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.c 2009-07-01 19:33:12.000000000 +0200
@@ -351,12 +351,12 @@ static int nl80211_send_wiphy(struct sk_
#undef CMD
- if (dev->ops->connect) {
+ if (dev->ops->connect || dev->ops->auth) {
i++;
NLA_PUT_U32(msg, i, NL80211_CMD_CONNECT);
}
- if (dev->ops->disconnect) {
+ if (dev->ops->disconnect || dev->ops->deauth) {
i++;
NLA_PUT_U32(msg, i, NL80211_CMD_DISCONNECT);
}
--- wireless-testing.orig/net/wireless/sme.c 2009-07-01 09:37:28.000000000 +0200
+++ wireless-testing/net/wireless/sme.c 2009-07-01 19:57:04.000000000 +0200
@@ -12,6 +12,263 @@
#include <net/rtnetlink.h>
#include "nl80211.h"
+struct cfg80211_conn {
+ struct cfg80211_connect_params params;
+ /* these are sub-states of the _CONNECTING sme_state */
+ enum {
+ CFG80211_CONN_IDLE,
+ CFG80211_CONN_SCANNING,
+ CFG80211_CONN_SCAN_AGAIN,
+ CFG80211_CONN_AUTHENTICATE_NEXT,
+ CFG80211_CONN_AUTHENTICATING,
+ CFG80211_CONN_ASSOCIATE_NEXT,
+ CFG80211_CONN_ASSOCIATING,
+ } state;
+ u8 bssid[ETH_ALEN];
+ u8 *ie;
+ size_t ie_len;
+ bool auto_auth;
+};
+
+
+static int cfg80211_conn_scan(struct wireless_dev *wdev)
+{
+ struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_scan_request *request;
+ int n_channels, err;
+
+ ASSERT_RTNL();
+
+ if (drv->scan_req)
+ return -EBUSY;
+
+ if (wdev->conn->params.channel) {
+ n_channels = 1;
+ } else {
+ enum ieee80211_band band;
+ n_channels = 0;
+
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ if (!wdev->wiphy->bands[band])
+ continue;
+ n_channels += wdev->wiphy->bands[band]->n_channels;
+ }
+ }
+ request = kzalloc(sizeof(*request) + sizeof(request->ssids[0]) +
+ sizeof(request->channels[0]) * n_channels,
+ GFP_KERNEL);
+ if (!request)
+ return -ENOMEM;
+
+ request->channels = (void *)((char *)request + sizeof(*request));
+ if (wdev->conn->params.channel)
+ request->channels[0] = wdev->conn->params.channel;
+ else {
+ int i = 0, j;
+ enum ieee80211_band band;
+
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ if (!wdev->wiphy->bands[band])
+ continue;
+ for (j = 0; j < wdev->wiphy->bands[band]->n_channels;
+ i++, j++)
+ request->channels[i] =
+ &wdev->wiphy->bands[band]->channels[j];
+ }
+ }
+ request->n_channels = n_channels;
+ request->ssids = (void *)(request->channels + n_channels);
+ request->n_ssids = 1;
+
+ memcpy(request->ssids[0].ssid, wdev->conn->params.ssid,
+ wdev->conn->params.ssid_len);
+ request->ssids[0].ssid_len = wdev->conn->params.ssid_len;
+
+ request->ifidx = wdev->netdev->ifindex;
+ request->wiphy = &drv->wiphy;
+
+ drv->scan_req = request;
+
+ err = drv->ops->scan(wdev->wiphy, wdev->netdev, request);
+ if (!err) {
+ wdev->conn->state = CFG80211_CONN_SCANNING;
+ nl80211_send_scan_start(drv, wdev->netdev);
+ } else {
+ drv->scan_req = NULL;
+ kfree(request);
+ }
+ return err;
+}
+
+static int cfg80211_conn_do_work(struct wireless_dev *wdev)
+{
+ struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy);
+ union {
+ struct cfg80211_auth_request auth_req;
+ struct cfg80211_assoc_request assoc_req;
+ } u;
+
+ memset(&u, 0, sizeof(u));
+
+ if (!wdev->conn)
+ return 0;
+
+ switch (wdev->conn->state) {
+ case CFG80211_CONN_SCAN_AGAIN:
+ return cfg80211_conn_scan(wdev);
+ case CFG80211_CONN_AUTHENTICATE_NEXT:
+ u.auth_req.chan = wdev->conn->params.channel;
+ u.auth_req.peer_addr = wdev->conn->params.bssid;
+ u.auth_req.ssid = wdev->conn->params.ssid;
+ u.auth_req.ssid_len = wdev->conn->params.ssid_len;
+ u.auth_req.auth_type = wdev->conn->params.auth_type;
+ u.auth_req.ie = NULL;
+ u.auth_req.ie_len = 0;
+ wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
+ BUG_ON(!drv->ops->auth);
+ return drv->ops->auth(wdev->wiphy, wdev->netdev, &u.auth_req);
+ case CFG80211_CONN_ASSOCIATE_NEXT:
+ u.assoc_req.chan = wdev->conn->params.channel;
+ u.assoc_req.peer_addr = wdev->conn->params.bssid;
+ u.assoc_req.ssid = wdev->conn->params.ssid;
+ u.assoc_req.ssid_len = wdev->conn->params.ssid_len;
+ u.assoc_req.ie = wdev->conn->params.ie;
+ u.assoc_req.ie_len = wdev->conn->params.ie_len;
+ u.assoc_req.use_mfp = false;
+ memcpy(&u.assoc_req.crypto, &wdev->conn->params.crypto,
+ sizeof(u.assoc_req.crypto));
+ wdev->conn->state = CFG80211_CONN_ASSOCIATING;
+ BUG_ON(!drv->ops->assoc);
+ return drv->ops->assoc(wdev->wiphy, wdev->netdev,
+ &u.assoc_req);
+ default:
+ return 0;
+ }
+}
+
+void cfg80211_conn_work(struct work_struct *work)
+{
+ struct cfg80211_registered_device *drv =
+ container_of(work, struct cfg80211_registered_device, conn_work);
+ struct wireless_dev *wdev;
+
+ rtnl_lock();
+ mutex_lock(&drv->devlist_mtx);
+
+ list_for_each_entry(wdev, &drv->netdev_list, list) {
+ if (!netif_running(wdev->netdev))
+ continue;
+ if (wdev->sme_state != CFG80211_SME_CONNECTING)
+ continue;
+ if (cfg80211_conn_do_work(wdev))
+ cfg80211_connect_result(wdev->netdev,
+ wdev->conn->params.bssid,
+ NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_ATOMIC);
+ }
+
+ mutex_unlock(&drv->devlist_mtx);
+ rtnl_unlock();
+}
+
+static bool cfg80211_get_conn_bss(struct wireless_dev *wdev)
+{
+ struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_bss *bss;
+ u16 capa = WLAN_CAPABILITY_ESS;
+
+ if (wdev->conn->params.privacy)
+ capa |= WLAN_CAPABILITY_PRIVACY;
+
+ bss = cfg80211_get_bss(wdev->wiphy, NULL, wdev->conn->params.bssid,
+ wdev->conn->params.ssid,
+ wdev->conn->params.ssid_len,
+ WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY,
+ capa);
+
+ if (!bss)
+ return false;
+
+ memcpy(wdev->conn->bssid, bss->bssid, ETH_ALEN);
+ wdev->conn->params.bssid = wdev->conn->bssid;
+ wdev->conn->params.channel = bss->channel;
+ wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
+ schedule_work(&drv->conn_work);
+
+ cfg80211_put_bss(bss);
+ return true;
+}
+
+void cfg80211_sme_scan_done(struct net_device *dev)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy);
+
+ if (wdev->sme_state != CFG80211_SME_CONNECTING)
+ return;
+
+ if (WARN_ON(!wdev->conn))
+ return;
+
+ if (wdev->conn->state != CFG80211_CONN_SCANNING &&
+ wdev->conn->state != CFG80211_CONN_SCAN_AGAIN)
+ return;
+
+ if (!cfg80211_get_conn_bss(wdev)) {
+ /* not found */
+ if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)
+ schedule_work(&drv->conn_work);
+ else
+ cfg80211_connect_result(dev, wdev->conn->params.bssid,
+ NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_ATOMIC);
+ return;
+ }
+}
+
+void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
+ u16 status_code = le16_to_cpu(mgmt->u.auth.status_code);
+
+ /* should only RX auth frames when connecting */
+ if (WARN_ON(!wdev->conn))
+ return;
+
+ if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
+ wdev->conn->auto_auth &&
+ wdev->conn->params.auth_type != NL80211_AUTHTYPE_NETWORK_EAP) {
+ /* select automatically between only open, shared, leap */
+ switch (wdev->conn->params.auth_type) {
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_SHARED_KEY;
+ break;
+ case NL80211_AUTHTYPE_SHARED_KEY:
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_NETWORK_EAP;
+ break;
+ default:
+ /* huh? */
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_OPEN_SYSTEM;
+ break;
+ }
+ wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
+ schedule_work(&rdev->conn_work);
+ } else if (status_code != WLAN_STATUS_SUCCESS)
+ wdev->sme_state = CFG80211_SME_IDLE;
+ else if (wdev->sme_state == CFG80211_SME_CONNECTING &&
+ wdev->conn->state == CFG80211_CONN_AUTHENTICATING) {
+ wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
+ schedule_work(&rdev->conn_work);
+ }
+}
void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
const u8 *req_ie, size_t req_ie_len,
@@ -53,6 +310,9 @@ void cfg80211_connect_result(struct net_
wdev->sme_state = CFG80211_SME_IDLE;
}
+ if (wdev->conn)
+ wdev->conn->state = CFG80211_CONN_IDLE;
+
nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, bssid,
req_ie, req_ie_len, resp_ie, resp_ie_len,
status, gfp);
@@ -72,7 +332,7 @@ void cfg80211_connect_result(struct net_
memset(&wrqu, 0, sizeof(wrqu));
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- if (bssid)
+ if (bssid && status == WLAN_STATUS_SUCCESS)
memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
#endif
@@ -138,9 +398,8 @@ void cfg80211_roamed(struct net_device *
}
EXPORT_SYMBOL(cfg80211_roamed);
-static void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp,
- u8 *ie, size_t ie_len, u16 reason,
- bool from_ap)
+void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp, u8 *ie,
+ size_t ie_len, u16 reason, bool from_ap)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
#ifdef CONFIG_WIRELESS_EXT
@@ -161,6 +420,11 @@ static void __cfg80211_disconnected(stru
wdev->current_bss = NULL;
wdev->sme_state = CFG80211_SME_IDLE;
+ if (wdev->conn) {
+ kfree(wdev->conn->ie);
+ wdev->conn->ie = NULL;
+ }
+
nl80211_send_disconnected(wiphy_to_dev(wdev->wiphy), dev,
reason, ie, ie_len, from_ap, gfp);
@@ -174,7 +438,7 @@ static void __cfg80211_disconnected(stru
void cfg80211_disconnected(struct net_device *dev, u16 reason,
u8 *ie, size_t ie_len, gfp_t gfp)
{
- __cfg80211_disconnected(dev, reason, ie, ie_len, true, gfp);
+ __cfg80211_disconnected(dev, gfp, ie, ie_len, reason, true);
}
EXPORT_SYMBOL(cfg80211_disconnected);
@@ -189,7 +453,74 @@ int cfg80211_connect(struct cfg80211_reg
return -EALREADY;
if (!rdev->ops->connect) {
- return -EOPNOTSUPP;
+ if (!rdev->ops->auth || !rdev->ops->assoc)
+ return -EOPNOTSUPP;
+
+ if (!wdev->conn) {
+ wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL);
+ if (!wdev->conn)
+ return -ENOMEM;
+ } else
+ memset(wdev->conn, 0, sizeof(*wdev->conn));
+
+ /*
+ * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
+ */
+ memcpy(&wdev->conn->params, connect, sizeof(*connect));
+ if (connect->bssid) {
+ wdev->conn->params.bssid = wdev->conn->bssid;
+ memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
+ }
+
+ if (connect->ie) {
+ wdev->conn->ie = kmemdup(connect->ie, connect->ie_len,
+ GFP_KERNEL);
+ wdev->conn->params.ie = wdev->conn->ie;
+ if (!wdev->conn->ie)
+ return -ENOMEM;
+ }
+
+ if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
+ wdev->conn->auto_auth = true;
+ /* start with open system ... should mostly work */
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_OPEN_SYSTEM;
+ } else {
+ wdev->conn->auto_auth = false;
+ }
+
+ memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
+ wdev->ssid_len = connect->ssid_len;
+ wdev->conn->params.ssid = wdev->ssid;
+ wdev->conn->params.ssid_len = connect->ssid_len;
+
+ /* don't care about result -- but fill bssid & channel */
+ if (!wdev->conn->params.bssid || !wdev->conn->params.channel)
+ cfg80211_get_conn_bss(wdev);
+
+ wdev->sme_state = CFG80211_SME_CONNECTING;
+
+ /* we're good if we have both BSSID and channel */
+ if (wdev->conn->params.bssid && wdev->conn->params.channel) {
+ wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
+ err = cfg80211_conn_do_work(wdev);
+ } else {
+ /* otherwise we'll need to scan for the AP first */
+ err = cfg80211_conn_scan(wdev);
+ /*
+ * If we can't scan right now, then we need to scan again
+ * after the current scan finished, since the parameters
+ * changed (unless we find a good AP anyway).
+ */
+ if (err == -EBUSY) {
+ err = 0;
+ wdev->conn->state = CFG80211_CONN_SCAN_AGAIN;
+ }
+ }
+ if (err)
+ wdev->sme_state = CFG80211_SME_IDLE;
+
+ return err;
} else {
wdev->sme_state = CFG80211_SME_CONNECTING;
err = rdev->ops->connect(&rdev->wiphy, dev, connect);
@@ -197,28 +528,63 @@ int cfg80211_connect(struct cfg80211_reg
wdev->sme_state = CFG80211_SME_IDLE;
return err;
}
- }
- memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
- wdev->ssid_len = connect->ssid_len;
+ memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
+ wdev->ssid_len = connect->ssid_len;
- return 0;
+ return 0;
+ }
}
int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
struct net_device *dev, u16 reason)
{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
+ if (wdev->sme_state == CFG80211_SME_IDLE)
+ return -EINVAL;
+
if (!rdev->ops->disconnect) {
- return -EOPNOTSUPP;
+ struct cfg80211_deauth_request deauth;
+ u8 bssid[ETH_ALEN];
+
+ /* internal bug. */
+ if (WARN_ON(!wdev->conn))
+ return -EINVAL;
+
+ if (wdev->sme_state == CFG80211_SME_CONNECTING &&
+ (wdev->conn->state == CFG80211_CONN_SCANNING ||
+ wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) {
+ wdev->sme_state = CFG80211_SME_IDLE;
+ return 0;
+ }
+
+ if (!rdev->ops->deauth)
+ return -EOPNOTSUPP;
+
+ memset(&deauth, 0, sizeof(deauth));
+
+ /* wdev->conn->params.bssid must be set if > SCANNING */
+ memcpy(bssid, wdev->conn->params.bssid, ETH_ALEN);
+ deauth.peer_addr = bssid;
+ deauth.reason_code = reason;
+
+ err = rdev->ops->deauth(&rdev->wiphy, dev, &deauth);
+ if (err)
+ return err;
} else {
err = rdev->ops->disconnect(&rdev->wiphy, dev, reason);
if (err)
return err;
}
- __cfg80211_disconnected(dev, 0, NULL, 0, false, GFP_KERNEL);
+ if (wdev->sme_state == CFG80211_SME_CONNECTED)
+ __cfg80211_disconnected(dev, GFP_KERNEL, NULL, 0, 0, false);
+ else if (wdev->sme_state == CFG80211_SME_CONNECTING)
+ cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_KERNEL);
return 0;
}
--- wireless-testing.orig/net/wireless/mlme.c 2009-07-01 09:37:28.000000000 +0200
+++ wireless-testing/net/wireless/mlme.c 2009-07-01 19:44:40.000000000 +0200
@@ -16,58 +16,105 @@ void cfg80211_send_rx_auth(struct net_de
{
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
nl80211_send_rx_auth(rdev, dev, buf, len, gfp);
+ cfg80211_sme_rx_auth(dev, buf, len);
}
EXPORT_SYMBOL(cfg80211_send_rx_auth);
void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
- struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ u16 status_code;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
+ u8 *ie = mgmt->u.assoc_resp.variable;
+ int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
+
+ status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
+
nl80211_send_rx_assoc(rdev, dev, buf, len, gfp);
+
+ cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
+ status_code, gfp);
}
EXPORT_SYMBOL(cfg80211_send_rx_assoc);
void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
+
nl80211_send_deauth(rdev, dev, buf, len, gfp);
+
+ if (wdev->sme_state == CFG80211_SME_CONNECTED) {
+ u16 reason_code;
+ bool from_ap;
+
+ reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
+
+ from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0;
+ __cfg80211_disconnected(dev, gfp, NULL, 0,
+ reason_code, from_ap);
+
+ wdev->sme_state = CFG80211_SME_IDLE;
+ } else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
+ cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE, gfp);
+ }
}
EXPORT_SYMBOL(cfg80211_send_deauth);
void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
+
nl80211_send_disassoc(rdev, dev, buf, len, gfp);
-}
-EXPORT_SYMBOL(cfg80211_send_disassoc);
-static void cfg80211_wext_disconnected(struct net_device *dev)
-{
-#ifdef CONFIG_WIRELESS_EXT
- union iwreq_data wrqu;
- memset(&wrqu, 0, sizeof(wrqu));
- wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
-#endif
+ if (wdev->sme_state == CFG80211_SME_CONNECTED) {
+ u16 reason_code;
+ bool from_ap;
+
+ reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
+
+ from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0;
+ __cfg80211_disconnected(dev, gfp, NULL, 0,
+ reason_code, from_ap);
+
+ wdev->sme_state = CFG80211_SME_IDLE;
+ }
}
+EXPORT_SYMBOL(cfg80211_send_disassoc);
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr, gfp_t gfp)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
nl80211_send_auth_timeout(rdev, dev, addr, gfp);
- cfg80211_wext_disconnected(dev);
+ if (wdev->sme_state == CFG80211_SME_CONNECTING)
+ cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE, gfp);
+ wdev->sme_state = CFG80211_SME_IDLE;
}
EXPORT_SYMBOL(cfg80211_send_auth_timeout);
void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr, gfp_t gfp)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
nl80211_send_assoc_timeout(rdev, dev, addr, gfp);
- cfg80211_wext_disconnected(dev);
+ if (wdev->sme_state == CFG80211_SME_CONNECTING)
+ cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE, gfp);
+ wdev->sme_state = CFG80211_SME_IDLE;
}
EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
--- wireless-testing.orig/net/wireless/core.c 2009-07-01 09:37:28.000000000 +0200
+++ wireless-testing/net/wireless/core.c 2009-07-01 19:52:04.000000000 +0200
@@ -321,6 +321,7 @@ struct wiphy *wiphy_new(const struct cfg
}
INIT_WORK(&drv->rfkill_sync, cfg80211_rfkill_sync_work);
+ INIT_WORK(&drv->conn_work, cfg80211_conn_work);
/*
* Initialize wiphy parameters to IEEE 802.11 MIB default values.
@@ -481,6 +482,8 @@ void wiphy_unregister(struct wiphy *wiph
/* unlock again before freeing */
mutex_unlock(&drv->mtx);
+ cancel_work_sync(&drv->conn_work);
+
cfg80211_debugfs_drv_del(drv);
/* If this device got a regulatory hint tell core its
@@ -569,6 +572,10 @@ static int cfg80211_netdev_notifier_call
break;
}
break;
+ case NETDEV_DOWN:
+ kfree(wdev->conn);
+ wdev->conn = NULL;
+ break;
case NETDEV_UP:
#ifdef CONFIG_WIRELESS_EXT
if (wdev->iftype != NL80211_IFTYPE_ADHOC)
--- wireless-testing.orig/include/net/cfg80211.h 2009-07-01 09:37:28.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h 2009-07-01 19:47:27.000000000 +0200
@@ -1209,6 +1209,9 @@ extern void wiphy_unregister(struct wiph
*/
extern void wiphy_free(struct wiphy *wiphy);
+/* internal struct */
+struct cfg80211_conn;
+
/**
* struct wireless_dev - wireless per-netdev state
*
@@ -1242,9 +1245,10 @@ struct wireless_dev {
u8 ssid_len;
enum {
CFG80211_SME_IDLE,
- CFG80211_SME_CONNECTING, /* ->connect called */
+ CFG80211_SME_CONNECTING,
CFG80211_SME_CONNECTED,
} sme_state;
+ struct cfg80211_conn *conn;
#ifdef CONFIG_WIRELESS_EXT
/* wext data */
--- wireless-testing.orig/net/wireless/scan.c 2009-07-01 09:37:18.000000000 +0200
+++ wireless-testing/net/wireless/scan.c 2009-07-01 13:27:45.000000000 +0200
@@ -30,6 +30,13 @@ void cfg80211_scan_done(struct cfg80211_
WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
+ /*
+ * This must be before sending the other events!
+ * Otherwise, wpa_supplicant gets completely confused with
+ * wext events.
+ */
+ cfg80211_sme_scan_done(dev);
+
if (aborted)
nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev);
else
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 14/20 v4.1] cfg80211: emulate connect with auth/assoc
2009-07-01 19:26 ` [PATCH 14/20 v4] cfg80211: emulate connect with auth/assoc Johannes Berg
@ 2009-07-02 7:13 ` Johannes Berg
0 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-02 7:13 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Samuel Ortiz
This adds code to cfg80211 so that drivers (mac80211 right
now) that don't implement connect but rather auth/assoc can
still be used with the nl80211 connect command. This will
also be necessary for the wext compat code.
Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
v4: dynamically allocate conn data
v4.1: fix warnings with userspace SME
include/net/cfg80211.h | 6
net/wireless/core.c | 7
net/wireless/core.h | 8
net/wireless/mlme.c | 81 +++++++---
net/wireless/nl80211.c | 4
net/wireless/scan.c | 7
net/wireless/sme.c | 395 +++++++++++++++++++++++++++++++++++++++++++++++--
7 files changed, 475 insertions(+), 33 deletions(-)
--- wireless-testing.orig/net/wireless/core.h 2009-07-01 21:28:15.000000000 +0200
+++ wireless-testing/net/wireless/core.h 2009-07-02 08:46:10.000000000 +0200
@@ -62,6 +62,8 @@ struct cfg80211_registered_device {
struct genl_info *testmode_info;
#endif
+ struct work_struct conn_work;
+
#ifdef CONFIG_CFG80211_DEBUGFS
/* Debugfs entries */
struct wiphy_debugfsdentries {
@@ -181,8 +183,14 @@ int cfg80211_connect(struct cfg80211_reg
int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
struct net_device *dev, u16 reason);
+void cfg80211_conn_work(struct work_struct *work);
+
/* internal helpers */
int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
const u8 *mac_addr);
+void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp, u8 *ie,
+ size_t ie_len, u16 reason, bool from_ap);
+void cfg80211_sme_scan_done(struct net_device *dev);
+void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
#endif /* __NET_WIRELESS_CORE_H */
--- wireless-testing.orig/net/wireless/nl80211.c 2009-07-01 21:28:15.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.c 2009-07-02 08:46:10.000000000 +0200
@@ -351,12 +351,12 @@ static int nl80211_send_wiphy(struct sk_
#undef CMD
- if (dev->ops->connect) {
+ if (dev->ops->connect || dev->ops->auth) {
i++;
NLA_PUT_U32(msg, i, NL80211_CMD_CONNECT);
}
- if (dev->ops->disconnect) {
+ if (dev->ops->disconnect || dev->ops->deauth) {
i++;
NLA_PUT_U32(msg, i, NL80211_CMD_DISCONNECT);
}
--- wireless-testing.orig/net/wireless/sme.c 2009-07-01 21:28:15.000000000 +0200
+++ wireless-testing/net/wireless/sme.c 2009-07-02 08:47:45.000000000 +0200
@@ -12,6 +12,266 @@
#include <net/rtnetlink.h>
#include "nl80211.h"
+struct cfg80211_conn {
+ struct cfg80211_connect_params params;
+ /* these are sub-states of the _CONNECTING sme_state */
+ enum {
+ CFG80211_CONN_IDLE,
+ CFG80211_CONN_SCANNING,
+ CFG80211_CONN_SCAN_AGAIN,
+ CFG80211_CONN_AUTHENTICATE_NEXT,
+ CFG80211_CONN_AUTHENTICATING,
+ CFG80211_CONN_ASSOCIATE_NEXT,
+ CFG80211_CONN_ASSOCIATING,
+ } state;
+ u8 bssid[ETH_ALEN];
+ u8 *ie;
+ size_t ie_len;
+ bool auto_auth;
+};
+
+
+static int cfg80211_conn_scan(struct wireless_dev *wdev)
+{
+ struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_scan_request *request;
+ int n_channels, err;
+
+ ASSERT_RTNL();
+
+ if (drv->scan_req)
+ return -EBUSY;
+
+ if (wdev->conn->params.channel) {
+ n_channels = 1;
+ } else {
+ enum ieee80211_band band;
+ n_channels = 0;
+
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ if (!wdev->wiphy->bands[band])
+ continue;
+ n_channels += wdev->wiphy->bands[band]->n_channels;
+ }
+ }
+ request = kzalloc(sizeof(*request) + sizeof(request->ssids[0]) +
+ sizeof(request->channels[0]) * n_channels,
+ GFP_KERNEL);
+ if (!request)
+ return -ENOMEM;
+
+ request->channels = (void *)((char *)request + sizeof(*request));
+ if (wdev->conn->params.channel)
+ request->channels[0] = wdev->conn->params.channel;
+ else {
+ int i = 0, j;
+ enum ieee80211_band band;
+
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ if (!wdev->wiphy->bands[band])
+ continue;
+ for (j = 0; j < wdev->wiphy->bands[band]->n_channels;
+ i++, j++)
+ request->channels[i] =
+ &wdev->wiphy->bands[band]->channels[j];
+ }
+ }
+ request->n_channels = n_channels;
+ request->ssids = (void *)(request->channels + n_channels);
+ request->n_ssids = 1;
+
+ memcpy(request->ssids[0].ssid, wdev->conn->params.ssid,
+ wdev->conn->params.ssid_len);
+ request->ssids[0].ssid_len = wdev->conn->params.ssid_len;
+
+ request->ifidx = wdev->netdev->ifindex;
+ request->wiphy = &drv->wiphy;
+
+ drv->scan_req = request;
+
+ err = drv->ops->scan(wdev->wiphy, wdev->netdev, request);
+ if (!err) {
+ wdev->conn->state = CFG80211_CONN_SCANNING;
+ nl80211_send_scan_start(drv, wdev->netdev);
+ } else {
+ drv->scan_req = NULL;
+ kfree(request);
+ }
+ return err;
+}
+
+static int cfg80211_conn_do_work(struct wireless_dev *wdev)
+{
+ struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy);
+ union {
+ struct cfg80211_auth_request auth_req;
+ struct cfg80211_assoc_request assoc_req;
+ } u;
+
+ memset(&u, 0, sizeof(u));
+
+ if (!wdev->conn)
+ return 0;
+
+ switch (wdev->conn->state) {
+ case CFG80211_CONN_SCAN_AGAIN:
+ return cfg80211_conn_scan(wdev);
+ case CFG80211_CONN_AUTHENTICATE_NEXT:
+ u.auth_req.chan = wdev->conn->params.channel;
+ u.auth_req.peer_addr = wdev->conn->params.bssid;
+ u.auth_req.ssid = wdev->conn->params.ssid;
+ u.auth_req.ssid_len = wdev->conn->params.ssid_len;
+ u.auth_req.auth_type = wdev->conn->params.auth_type;
+ u.auth_req.ie = NULL;
+ u.auth_req.ie_len = 0;
+ wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
+ BUG_ON(!drv->ops->auth);
+ return drv->ops->auth(wdev->wiphy, wdev->netdev, &u.auth_req);
+ case CFG80211_CONN_ASSOCIATE_NEXT:
+ u.assoc_req.chan = wdev->conn->params.channel;
+ u.assoc_req.peer_addr = wdev->conn->params.bssid;
+ u.assoc_req.ssid = wdev->conn->params.ssid;
+ u.assoc_req.ssid_len = wdev->conn->params.ssid_len;
+ u.assoc_req.ie = wdev->conn->params.ie;
+ u.assoc_req.ie_len = wdev->conn->params.ie_len;
+ u.assoc_req.use_mfp = false;
+ memcpy(&u.assoc_req.crypto, &wdev->conn->params.crypto,
+ sizeof(u.assoc_req.crypto));
+ wdev->conn->state = CFG80211_CONN_ASSOCIATING;
+ BUG_ON(!drv->ops->assoc);
+ return drv->ops->assoc(wdev->wiphy, wdev->netdev,
+ &u.assoc_req);
+ default:
+ return 0;
+ }
+}
+
+void cfg80211_conn_work(struct work_struct *work)
+{
+ struct cfg80211_registered_device *drv =
+ container_of(work, struct cfg80211_registered_device, conn_work);
+ struct wireless_dev *wdev;
+
+ rtnl_lock();
+ mutex_lock(&drv->devlist_mtx);
+
+ list_for_each_entry(wdev, &drv->netdev_list, list) {
+ if (!netif_running(wdev->netdev))
+ continue;
+ if (wdev->sme_state != CFG80211_SME_CONNECTING)
+ continue;
+ if (cfg80211_conn_do_work(wdev))
+ cfg80211_connect_result(wdev->netdev,
+ wdev->conn->params.bssid,
+ NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_ATOMIC);
+ }
+
+ mutex_unlock(&drv->devlist_mtx);
+ rtnl_unlock();
+}
+
+static bool cfg80211_get_conn_bss(struct wireless_dev *wdev)
+{
+ struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_bss *bss;
+ u16 capa = WLAN_CAPABILITY_ESS;
+
+ if (wdev->conn->params.privacy)
+ capa |= WLAN_CAPABILITY_PRIVACY;
+
+ bss = cfg80211_get_bss(wdev->wiphy, NULL, wdev->conn->params.bssid,
+ wdev->conn->params.ssid,
+ wdev->conn->params.ssid_len,
+ WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY,
+ capa);
+
+ if (!bss)
+ return false;
+
+ memcpy(wdev->conn->bssid, bss->bssid, ETH_ALEN);
+ wdev->conn->params.bssid = wdev->conn->bssid;
+ wdev->conn->params.channel = bss->channel;
+ wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
+ schedule_work(&drv->conn_work);
+
+ cfg80211_put_bss(bss);
+ return true;
+}
+
+void cfg80211_sme_scan_done(struct net_device *dev)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy);
+
+ if (wdev->sme_state != CFG80211_SME_CONNECTING)
+ return;
+
+ if (WARN_ON(!wdev->conn))
+ return;
+
+ if (wdev->conn->state != CFG80211_CONN_SCANNING &&
+ wdev->conn->state != CFG80211_CONN_SCAN_AGAIN)
+ return;
+
+ if (!cfg80211_get_conn_bss(wdev)) {
+ /* not found */
+ if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)
+ schedule_work(&drv->conn_work);
+ else
+ cfg80211_connect_result(dev, wdev->conn->params.bssid,
+ NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_ATOMIC);
+ return;
+ }
+}
+
+void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
+ u16 status_code = le16_to_cpu(mgmt->u.auth.status_code);
+
+ /* should only RX auth frames when connecting */
+ if (wdev->sme_state != CFG80211_SME_CONNECTING)
+ return;
+
+ if (WARN_ON(!wdev->conn))
+ return;
+
+ if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
+ wdev->conn->auto_auth &&
+ wdev->conn->params.auth_type != NL80211_AUTHTYPE_NETWORK_EAP) {
+ /* select automatically between only open, shared, leap */
+ switch (wdev->conn->params.auth_type) {
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_SHARED_KEY;
+ break;
+ case NL80211_AUTHTYPE_SHARED_KEY:
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_NETWORK_EAP;
+ break;
+ default:
+ /* huh? */
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_OPEN_SYSTEM;
+ break;
+ }
+ wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
+ schedule_work(&rdev->conn_work);
+ } else if (status_code != WLAN_STATUS_SUCCESS)
+ wdev->sme_state = CFG80211_SME_IDLE;
+ else if (wdev->sme_state == CFG80211_SME_CONNECTING &&
+ wdev->conn->state == CFG80211_CONN_AUTHENTICATING) {
+ wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
+ schedule_work(&rdev->conn_work);
+ }
+}
void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
const u8 *req_ie, size_t req_ie_len,
@@ -27,7 +287,7 @@ void cfg80211_connect_result(struct net_
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
return;
- if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING))
+ if (wdev->sme_state != CFG80211_SME_CONNECTING)
return;
if (wdev->current_bss) {
@@ -53,6 +313,9 @@ void cfg80211_connect_result(struct net_
wdev->sme_state = CFG80211_SME_IDLE;
}
+ if (wdev->conn)
+ wdev->conn->state = CFG80211_CONN_IDLE;
+
nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, bssid,
req_ie, req_ie_len, resp_ie, resp_ie_len,
status, gfp);
@@ -72,7 +335,7 @@ void cfg80211_connect_result(struct net_
memset(&wrqu, 0, sizeof(wrqu));
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- if (bssid)
+ if (bssid && status == WLAN_STATUS_SUCCESS)
memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
#endif
@@ -138,9 +401,8 @@ void cfg80211_roamed(struct net_device *
}
EXPORT_SYMBOL(cfg80211_roamed);
-static void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp,
- u8 *ie, size_t ie_len, u16 reason,
- bool from_ap)
+void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp, u8 *ie,
+ size_t ie_len, u16 reason, bool from_ap)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
#ifdef CONFIG_WIRELESS_EXT
@@ -161,6 +423,11 @@ static void __cfg80211_disconnected(stru
wdev->current_bss = NULL;
wdev->sme_state = CFG80211_SME_IDLE;
+ if (wdev->conn) {
+ kfree(wdev->conn->ie);
+ wdev->conn->ie = NULL;
+ }
+
nl80211_send_disconnected(wiphy_to_dev(wdev->wiphy), dev,
reason, ie, ie_len, from_ap, gfp);
@@ -174,7 +441,7 @@ static void __cfg80211_disconnected(stru
void cfg80211_disconnected(struct net_device *dev, u16 reason,
u8 *ie, size_t ie_len, gfp_t gfp)
{
- __cfg80211_disconnected(dev, reason, ie, ie_len, true, gfp);
+ __cfg80211_disconnected(dev, gfp, ie, ie_len, reason, true);
}
EXPORT_SYMBOL(cfg80211_disconnected);
@@ -189,7 +456,74 @@ int cfg80211_connect(struct cfg80211_reg
return -EALREADY;
if (!rdev->ops->connect) {
- return -EOPNOTSUPP;
+ if (!rdev->ops->auth || !rdev->ops->assoc)
+ return -EOPNOTSUPP;
+
+ if (!wdev->conn) {
+ wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL);
+ if (!wdev->conn)
+ return -ENOMEM;
+ } else
+ memset(wdev->conn, 0, sizeof(*wdev->conn));
+
+ /*
+ * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
+ */
+ memcpy(&wdev->conn->params, connect, sizeof(*connect));
+ if (connect->bssid) {
+ wdev->conn->params.bssid = wdev->conn->bssid;
+ memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
+ }
+
+ if (connect->ie) {
+ wdev->conn->ie = kmemdup(connect->ie, connect->ie_len,
+ GFP_KERNEL);
+ wdev->conn->params.ie = wdev->conn->ie;
+ if (!wdev->conn->ie)
+ return -ENOMEM;
+ }
+
+ if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
+ wdev->conn->auto_auth = true;
+ /* start with open system ... should mostly work */
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_OPEN_SYSTEM;
+ } else {
+ wdev->conn->auto_auth = false;
+ }
+
+ memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
+ wdev->ssid_len = connect->ssid_len;
+ wdev->conn->params.ssid = wdev->ssid;
+ wdev->conn->params.ssid_len = connect->ssid_len;
+
+ /* don't care about result -- but fill bssid & channel */
+ if (!wdev->conn->params.bssid || !wdev->conn->params.channel)
+ cfg80211_get_conn_bss(wdev);
+
+ wdev->sme_state = CFG80211_SME_CONNECTING;
+
+ /* we're good if we have both BSSID and channel */
+ if (wdev->conn->params.bssid && wdev->conn->params.channel) {
+ wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
+ err = cfg80211_conn_do_work(wdev);
+ } else {
+ /* otherwise we'll need to scan for the AP first */
+ err = cfg80211_conn_scan(wdev);
+ /*
+ * If we can't scan right now, then we need to scan again
+ * after the current scan finished, since the parameters
+ * changed (unless we find a good AP anyway).
+ */
+ if (err == -EBUSY) {
+ err = 0;
+ wdev->conn->state = CFG80211_CONN_SCAN_AGAIN;
+ }
+ }
+ if (err)
+ wdev->sme_state = CFG80211_SME_IDLE;
+
+ return err;
} else {
wdev->sme_state = CFG80211_SME_CONNECTING;
err = rdev->ops->connect(&rdev->wiphy, dev, connect);
@@ -197,28 +531,63 @@ int cfg80211_connect(struct cfg80211_reg
wdev->sme_state = CFG80211_SME_IDLE;
return err;
}
- }
- memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
- wdev->ssid_len = connect->ssid_len;
+ memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
+ wdev->ssid_len = connect->ssid_len;
- return 0;
+ return 0;
+ }
}
int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
struct net_device *dev, u16 reason)
{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
+ if (wdev->sme_state == CFG80211_SME_IDLE)
+ return -EINVAL;
+
if (!rdev->ops->disconnect) {
- return -EOPNOTSUPP;
+ struct cfg80211_deauth_request deauth;
+ u8 bssid[ETH_ALEN];
+
+ /* internal bug. */
+ if (WARN_ON(!wdev->conn))
+ return -EINVAL;
+
+ if (wdev->sme_state == CFG80211_SME_CONNECTING &&
+ (wdev->conn->state == CFG80211_CONN_SCANNING ||
+ wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) {
+ wdev->sme_state = CFG80211_SME_IDLE;
+ return 0;
+ }
+
+ if (!rdev->ops->deauth)
+ return -EOPNOTSUPP;
+
+ memset(&deauth, 0, sizeof(deauth));
+
+ /* wdev->conn->params.bssid must be set if > SCANNING */
+ memcpy(bssid, wdev->conn->params.bssid, ETH_ALEN);
+ deauth.peer_addr = bssid;
+ deauth.reason_code = reason;
+
+ err = rdev->ops->deauth(&rdev->wiphy, dev, &deauth);
+ if (err)
+ return err;
} else {
err = rdev->ops->disconnect(&rdev->wiphy, dev, reason);
if (err)
return err;
}
- __cfg80211_disconnected(dev, 0, NULL, 0, false, GFP_KERNEL);
+ if (wdev->sme_state == CFG80211_SME_CONNECTED)
+ __cfg80211_disconnected(dev, GFP_KERNEL, NULL, 0, 0, false);
+ else if (wdev->sme_state == CFG80211_SME_CONNECTING)
+ cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_KERNEL);
return 0;
}
--- wireless-testing.orig/net/wireless/mlme.c 2009-07-01 21:28:14.000000000 +0200
+++ wireless-testing/net/wireless/mlme.c 2009-07-01 21:28:15.000000000 +0200
@@ -16,58 +16,105 @@ void cfg80211_send_rx_auth(struct net_de
{
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
nl80211_send_rx_auth(rdev, dev, buf, len, gfp);
+ cfg80211_sme_rx_auth(dev, buf, len);
}
EXPORT_SYMBOL(cfg80211_send_rx_auth);
void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
- struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ u16 status_code;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
+ u8 *ie = mgmt->u.assoc_resp.variable;
+ int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
+
+ status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
+
nl80211_send_rx_assoc(rdev, dev, buf, len, gfp);
+
+ cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
+ status_code, gfp);
}
EXPORT_SYMBOL(cfg80211_send_rx_assoc);
void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
+
nl80211_send_deauth(rdev, dev, buf, len, gfp);
+
+ if (wdev->sme_state == CFG80211_SME_CONNECTED) {
+ u16 reason_code;
+ bool from_ap;
+
+ reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
+
+ from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0;
+ __cfg80211_disconnected(dev, gfp, NULL, 0,
+ reason_code, from_ap);
+
+ wdev->sme_state = CFG80211_SME_IDLE;
+ } else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
+ cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE, gfp);
+ }
}
EXPORT_SYMBOL(cfg80211_send_deauth);
void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len, gfp_t gfp)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
+
nl80211_send_disassoc(rdev, dev, buf, len, gfp);
-}
-EXPORT_SYMBOL(cfg80211_send_disassoc);
-static void cfg80211_wext_disconnected(struct net_device *dev)
-{
-#ifdef CONFIG_WIRELESS_EXT
- union iwreq_data wrqu;
- memset(&wrqu, 0, sizeof(wrqu));
- wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
-#endif
+ if (wdev->sme_state == CFG80211_SME_CONNECTED) {
+ u16 reason_code;
+ bool from_ap;
+
+ reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
+
+ from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0;
+ __cfg80211_disconnected(dev, gfp, NULL, 0,
+ reason_code, from_ap);
+
+ wdev->sme_state = CFG80211_SME_IDLE;
+ }
}
+EXPORT_SYMBOL(cfg80211_send_disassoc);
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr, gfp_t gfp)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
nl80211_send_auth_timeout(rdev, dev, addr, gfp);
- cfg80211_wext_disconnected(dev);
+ if (wdev->sme_state == CFG80211_SME_CONNECTING)
+ cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE, gfp);
+ wdev->sme_state = CFG80211_SME_IDLE;
}
EXPORT_SYMBOL(cfg80211_send_auth_timeout);
void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr, gfp_t gfp)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
nl80211_send_assoc_timeout(rdev, dev, addr, gfp);
- cfg80211_wext_disconnected(dev);
+ if (wdev->sme_state == CFG80211_SME_CONNECTING)
+ cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE, gfp);
+ wdev->sme_state = CFG80211_SME_IDLE;
}
EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
--- wireless-testing.orig/net/wireless/core.c 2009-07-01 21:28:15.000000000 +0200
+++ wireless-testing/net/wireless/core.c 2009-07-02 08:46:10.000000000 +0200
@@ -321,6 +321,7 @@ struct wiphy *wiphy_new(const struct cfg
}
INIT_WORK(&drv->rfkill_sync, cfg80211_rfkill_sync_work);
+ INIT_WORK(&drv->conn_work, cfg80211_conn_work);
/*
* Initialize wiphy parameters to IEEE 802.11 MIB default values.
@@ -481,6 +482,8 @@ void wiphy_unregister(struct wiphy *wiph
/* unlock again before freeing */
mutex_unlock(&drv->mtx);
+ cancel_work_sync(&drv->conn_work);
+
cfg80211_debugfs_drv_del(drv);
/* If this device got a regulatory hint tell core its
@@ -569,6 +572,10 @@ static int cfg80211_netdev_notifier_call
break;
}
break;
+ case NETDEV_DOWN:
+ kfree(wdev->conn);
+ wdev->conn = NULL;
+ break;
case NETDEV_UP:
#ifdef CONFIG_WIRELESS_EXT
if (wdev->iftype != NL80211_IFTYPE_ADHOC)
--- wireless-testing.orig/include/net/cfg80211.h 2009-07-01 21:28:15.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h 2009-07-02 08:46:10.000000000 +0200
@@ -1209,6 +1209,9 @@ extern void wiphy_unregister(struct wiph
*/
extern void wiphy_free(struct wiphy *wiphy);
+/* internal struct */
+struct cfg80211_conn;
+
/**
* struct wireless_dev - wireless per-netdev state
*
@@ -1242,9 +1245,10 @@ struct wireless_dev {
u8 ssid_len;
enum {
CFG80211_SME_IDLE,
- CFG80211_SME_CONNECTING, /* ->connect called */
+ CFG80211_SME_CONNECTING,
CFG80211_SME_CONNECTED,
} sme_state;
+ struct cfg80211_conn *conn;
#ifdef CONFIG_WIRELESS_EXT
/* wext data */
--- wireless-testing.orig/net/wireless/scan.c 2009-07-01 21:24:42.000000000 +0200
+++ wireless-testing/net/wireless/scan.c 2009-07-01 21:28:15.000000000 +0200
@@ -30,6 +30,13 @@ void cfg80211_scan_done(struct cfg80211_
WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
+ /*
+ * This must be before sending the other events!
+ * Otherwise, wpa_supplicant gets completely confused with
+ * wext events.
+ */
+ cfg80211_sme_scan_done(dev);
+
if (aborted)
nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev);
else
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 15/20 v4] cfg80211: managed mode wext compatibility
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (13 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 14/20 v4] cfg80211: emulate connect with auth/assoc Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-02 23:55 ` [PATCH] iwmc3200wifi: cfg80211 managed mode port Samuel Ortiz
2009-07-03 0:00 ` [PATCH] cfg80211: check for current_bss from giwrate Samuel Ortiz
2009-07-01 19:26 ` [PATCH 16/20 v4] cfg80211: implement iwpower Johannes Berg
` (7 subsequent siblings)
22 siblings, 2 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Samuel Ortiz
This adds code to make it possible to use the cfg80211
connect() API with wireless extensions, and because the
previous patch added emulation of that API with auth()
and assoc(), by extension also supports wext on that.
At the same time, removes code from mac80211 for wext,
but doesn't yet clean up mac80211's mlme code more.
Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/net/cfg80211.h | 36 ++++
net/mac80211/mlme.c | 69 ---------
net/mac80211/wext.c | 215 ++---------------------------
net/wireless/Makefile | 2
net/wireless/core.c | 23 ++-
net/wireless/core.h | 3
net/wireless/nl80211.c | 2
net/wireless/sme.c | 55 ++++---
net/wireless/wext-compat.c | 229 +++++++++++++++++++++++++------
net/wireless/wext-sme.c | 329 +++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 625 insertions(+), 338 deletions(-)
--- wireless-testing.orig/include/net/cfg80211.h 2009-07-01 20:58:27.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h 2009-07-01 21:15:12.000000000 +0200
@@ -1253,8 +1253,14 @@ struct wireless_dev {
#ifdef CONFIG_WIRELESS_EXT
/* wext data */
struct {
- struct cfg80211_ibss_params ibss;
+ union {
+ struct cfg80211_ibss_params ibss;
+ struct cfg80211_connect_params connect;
+ };
+ u8 *ie;
+ size_t ie_len;
u8 bssid[ETH_ALEN];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
s8 default_key, default_mgmt_key;
} wext;
#endif
@@ -1535,6 +1541,34 @@ int cfg80211_ibss_wext_giwap(struct net_
struct iw_request_info *info,
struct sockaddr *ap_addr, char *extra);
+int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra);
+int cfg80211_mgd_wext_giwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra);
+int cfg80211_mgd_wext_siwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid);
+int cfg80211_mgd_wext_giwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid);
+int cfg80211_mgd_wext_siwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra);
+int cfg80211_mgd_wext_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra);
+int cfg80211_wext_siwgenie(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra);
+int cfg80211_wext_siwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra);
+int cfg80211_wext_giwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra);
+
struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
struct iw_freq *freq);
--- wireless-testing.orig/net/wireless/Makefile 2009-07-01 20:58:26.000000000 +0200
+++ wireless-testing/net/wireless/Makefile 2009-07-01 21:15:12.000000000 +0200
@@ -7,6 +7,6 @@ obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o sme.o
cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
-cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o
+cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o wext-sme.o
ccflags-y += -D__CHECK_ENDIAN__
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ wireless-testing/net/wireless/wext-sme.c 2009-07-01 21:15:12.000000000 +0200
@@ -0,0 +1,329 @@
+/*
+ * cfg80211 wext compat for managed mode.
+ *
+ * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <net/cfg80211.h>
+#include "nl80211.h"
+
+static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
+{
+ int err;
+
+ if (!netif_running(wdev->netdev))
+ return 0;
+
+ wdev->wext.connect.ie = wdev->wext.ie;
+ wdev->wext.connect.ie_len = wdev->wext.ie_len;
+ wdev->wext.connect.privacy = wdev->wext.default_key != -1;
+
+ err = 0;
+ if (wdev->wext.connect.ssid_len != 0)
+ err = cfg80211_connect(rdev, wdev->netdev,
+ &wdev->wext.connect);
+
+ return err;
+}
+
+int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct ieee80211_channel *chan;
+ int err;
+
+ /* call only for station! */
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return -EINVAL;
+
+ chan = cfg80211_wext_freq(wdev->wiphy, freq);
+ if (chan && IS_ERR(chan))
+ return PTR_ERR(chan);
+
+ if (chan && (chan->flags & IEEE80211_CHAN_DISABLED))
+ return -EINVAL;
+
+ if (wdev->wext.connect.channel == chan)
+ return 0;
+
+ if (wdev->sme_state != CFG80211_SME_IDLE) {
+ bool event = true;
+ /* if SSID set, we'll try right again, avoid event */
+ if (wdev->wext.connect.ssid_len)
+ event = false;
+ err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
+ dev, WLAN_REASON_DEAUTH_LEAVING,
+ event);
+ if (err)
+ return err;
+ }
+
+ wdev->wext.connect.channel = chan;
+
+ /* SSID is not set, we just want to switch channel */
+ if (wdev->wext.connect.ssid_len && chan) {
+ if (!rdev->ops->set_channel)
+ return -EOPNOTSUPP;
+
+ return rdev->ops->set_channel(wdev->wiphy, chan,
+ NL80211_CHAN_NO_HT);
+ }
+
+ return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
+}
+/* temporary symbol - mark GPL - in the future the handler won't be */
+EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwfreq);
+
+int cfg80211_mgd_wext_giwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct ieee80211_channel *chan = NULL;
+
+ /* call only for station! */
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return -EINVAL;
+
+ if (wdev->current_bss)
+ chan = wdev->current_bss->channel;
+ else if (wdev->wext.connect.channel)
+ chan = wdev->wext.connect.channel;
+
+ if (chan) {
+ freq->m = chan->center_freq;
+ freq->e = 6;
+ return 0;
+ }
+
+ /* no channel if not joining */
+ return -EINVAL;
+}
+/* temporary symbol - mark GPL - in the future the handler won't be */
+EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwfreq);
+
+int cfg80211_mgd_wext_siwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ size_t len = data->length;
+ int err;
+
+ /* call only for station! */
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return -EINVAL;
+
+ if (!data->flags)
+ len = 0;
+
+ /* iwconfig uses nul termination in SSID.. */
+ if (len > 0 && ssid[len - 1] == '\0')
+ len--;
+
+ if (wdev->wext.connect.ssid && len &&
+ len == wdev->wext.connect.ssid_len &&
+ memcmp(wdev->wext.connect.ssid, ssid, len))
+ return 0;
+
+ if (wdev->sme_state != CFG80211_SME_IDLE) {
+ bool event = true;
+ /* if SSID set now, we'll try to connect, avoid event */
+ if (len)
+ event = false;
+ err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
+ dev, WLAN_REASON_DEAUTH_LEAVING,
+ event);
+ if (err)
+ return err;
+ }
+
+ wdev->wext.connect.ssid = wdev->wext.ssid;
+ memcpy(wdev->wext.ssid, ssid, len);
+ wdev->wext.connect.ssid_len = len;
+
+ wdev->wext.connect.crypto.control_port = false;
+
+ return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
+}
+/* temporary symbol - mark GPL - in the future the handler won't be */
+EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwessid);
+
+int cfg80211_mgd_wext_giwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ /* call only for station! */
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return -EINVAL;
+
+ data->flags = 0;
+
+ if (wdev->ssid_len) {
+ data->flags = 1;
+ data->length = wdev->ssid_len;
+ memcpy(ssid, wdev->ssid, data->length);
+ } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) {
+ data->flags = 1;
+ data->length = wdev->wext.connect.ssid_len;
+ memcpy(ssid, wdev->wext.connect.ssid, data->length);
+ } else
+ data->flags = 0;
+
+ return 0;
+}
+/* temporary symbol - mark GPL - in the future the handler won't be */
+EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwessid);
+
+int cfg80211_mgd_wext_siwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ u8 *bssid = ap_addr->sa_data;
+ int err;
+
+ /* call only for station! */
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return -EINVAL;
+
+ if (ap_addr->sa_family != ARPHRD_ETHER)
+ return -EINVAL;
+
+ /* automatic mode */
+ if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
+ bssid = NULL;
+
+ /* both automatic */
+ if (!bssid && !wdev->wext.connect.bssid)
+ return 0;
+
+ /* fixed already - and no change */
+ if (wdev->wext.connect.bssid && bssid &&
+ compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0)
+ return 0;
+
+ if (wdev->sme_state != CFG80211_SME_IDLE) {
+ err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
+ dev, WLAN_REASON_DEAUTH_LEAVING,
+ false);
+ if (err)
+ return err;
+ }
+
+ if (bssid) {
+ memcpy(wdev->wext.bssid, bssid, ETH_ALEN);
+ wdev->wext.connect.bssid = wdev->wext.bssid;
+ } else
+ wdev->wext.connect.bssid = NULL;
+
+ return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
+}
+/* temporary symbol - mark GPL - in the future the handler won't be */
+EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwap);
+
+int cfg80211_mgd_wext_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ /* call only for station! */
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return -EINVAL;
+
+ ap_addr->sa_family = ARPHRD_ETHER;
+
+ if (wdev->current_bss)
+ memcpy(ap_addr->sa_data, wdev->current_bss->bssid, ETH_ALEN);
+ else if (wdev->wext.connect.bssid)
+ memcpy(ap_addr->sa_data, wdev->wext.connect.bssid, ETH_ALEN);
+ else
+ memset(ap_addr->sa_data, 0, ETH_ALEN);
+
+ return 0;
+}
+/* temporary symbol - mark GPL - in the future the handler won't be */
+EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwap);
+
+int cfg80211_wext_siwgenie(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ u8 *ie = extra;
+ int ie_len = data->length, err;
+
+ if (wdev->iftype != NL80211_IFTYPE_STATION)
+ return -EOPNOTSUPP;
+
+ if (!ie_len)
+ ie = NULL;
+
+ /* no change */
+ if (wdev->wext.ie_len == ie_len &&
+ memcmp(wdev->wext.ie, ie, ie_len) == 0)
+ return 0;
+
+ if (ie_len) {
+ ie = kmemdup(extra, ie_len, GFP_KERNEL);
+ if (!ie)
+ return -ENOMEM;
+ } else
+ ie = NULL;
+
+ kfree(wdev->wext.ie);
+ wdev->wext.ie = ie;
+ wdev->wext.ie_len = ie_len;
+
+ if (wdev->sme_state != CFG80211_SME_IDLE) {
+ err = cfg80211_disconnect(rdev, dev,
+ WLAN_REASON_DEAUTH_LEAVING, false);
+ if (err)
+ return err;
+ }
+
+ /* userspace better not think we'll reconnect */
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwgenie);
+
+int cfg80211_wext_siwmlme(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct iw_mlme *mlme = (struct iw_mlme *)extra;
+ struct cfg80211_registered_device *rdev;
+
+ if (!wdev)
+ return -EOPNOTSUPP;
+
+ rdev = wiphy_to_dev(wdev->wiphy);
+
+ if (wdev->iftype != NL80211_IFTYPE_STATION)
+ return -EINVAL;
+
+ if (mlme->addr.sa_family != ARPHRD_ETHER)
+ return -EINVAL;
+
+ switch (mlme->cmd) {
+ case IW_MLME_DEAUTH:
+ case IW_MLME_DISASSOC:
+ return cfg80211_disconnect(rdev, dev, mlme->reason_code,
+ true);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme);
--- wireless-testing.orig/net/wireless/core.c 2009-07-01 20:58:27.000000000 +0200
+++ wireless-testing/net/wireless/core.c 2009-07-01 21:15:12.000000000 +0200
@@ -553,6 +553,7 @@ static int cfg80211_netdev_notifier_call
#ifdef CONFIG_WIRELESS_EXT
wdev->wext.default_key = -1;
wdev->wext.default_mgmt_key = -1;
+ wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
#endif
mutex_unlock(&rdev->devlist_mtx);
break;
@@ -565,8 +566,13 @@ static int cfg80211_netdev_notifier_call
cfg80211_leave_ibss(rdev, dev, true);
break;
case NL80211_IFTYPE_STATION:
+#ifdef CONFIG_WIRELESS_EXT
+ kfree(wdev->wext.ie);
+ wdev->wext.ie = NULL;
+ wdev->wext.ie_len = 0;
+#endif
cfg80211_disconnect(rdev, dev,
- WLAN_REASON_DEAUTH_LEAVING);
+ WLAN_REASON_DEAUTH_LEAVING, true);
break;
default:
break;
@@ -578,11 +584,20 @@ static int cfg80211_netdev_notifier_call
break;
case NETDEV_UP:
#ifdef CONFIG_WIRELESS_EXT
- if (wdev->iftype != NL80211_IFTYPE_ADHOC)
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ if (wdev->wext.ibss.ssid_len)
+ cfg80211_join_ibss(rdev, dev,
+ &wdev->wext.ibss);
break;
- if (!wdev->wext.ibss.ssid_len)
+ case NL80211_IFTYPE_STATION:
+ if (wdev->wext.connect.ssid_len)
+ cfg80211_connect(rdev, dev,
+ &wdev->wext.connect);
+ break;
+ default:
break;
- cfg80211_join_ibss(rdev, dev, &wdev->wext.ibss);
+ }
#endif
break;
case NETDEV_UNREGISTER:
--- wireless-testing.orig/net/mac80211/wext.c 2009-07-01 20:50:38.000000000 +0200
+++ wireless-testing/net/mac80211/wext.c 2009-07-01 21:15:12.000000000 +0200
@@ -27,29 +27,6 @@
#include "aes_ccm.h"
-static int ieee80211_ioctl_siwgenie(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- struct ieee80211_sub_if_data *sdata;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length);
- if (ret && ret != -EALREADY)
- return ret;
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
- sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
- sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
- if (ret != -EALREADY)
- ieee80211_sta_req_auth(sdata);
- return 0;
- }
-
- return -EOPNOTSUPP;
-}
-
static int ieee80211_ioctl_siwfreq(struct net_device *dev,
struct iw_request_info *info,
struct iw_freq *freq, char *extra)
@@ -61,16 +38,13 @@ static int ieee80211_ioctl_siwfreq(struc
if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
+ return cfg80211_mgd_wext_siwfreq(dev, info, freq, extra);
/* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
if (freq->e == 0) {
- if (freq->m < 0) {
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- sdata->u.mgd.flags |=
- IEEE80211_STA_AUTO_CHANNEL_SEL;
- return 0;
- } else
+ if (freq->m < 0)
+ return -EINVAL;
+ else
chan = ieee80211_get_channel(local->hw.wiphy,
ieee80211_channel_to_frequency(freq->m));
} else {
@@ -95,9 +69,6 @@ static int ieee80211_ioctl_siwfreq(struc
if (local->oper_channel == chan)
return 0;
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- ieee80211_sta_req_auth(sdata);
-
local->oper_channel = chan;
local->oper_channel_type = NL80211_CHAN_NO_HT;
ieee80211_hw_config(local, 0);
@@ -115,6 +86,8 @@ static int ieee80211_ioctl_giwfreq(struc
if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
+ else if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
freq->m = local->oper_channel->center_freq;
freq->e = 6;
@@ -128,31 +101,11 @@ static int ieee80211_ioctl_siwessid(stru
struct iw_point *data, char *ssid)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- size_t len = data->length;
- int ret;
if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
-
- /* iwconfig uses nul termination in SSID.. */
- if (len > 0 && ssid[len - 1] == '\0')
- len--;
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- if (data->flags)
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
- else
- sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL;
-
- ret = ieee80211_sta_set_ssid(sdata, ssid, len);
- if (ret)
- return ret;
-
- sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
- sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
- ieee80211_sta_req_auth(sdata);
- return 0;
- }
+ else if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
return -EOPNOTSUPP;
}
@@ -162,23 +115,14 @@ static int ieee80211_ioctl_giwessid(stru
struct iw_request_info *info,
struct iw_point *data, char *ssid)
{
- size_t len;
struct ieee80211_sub_if_data *sdata;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- int res = ieee80211_sta_get_ssid(sdata, ssid, &len);
- if (res == 0) {
- data->length = len;
- data->flags = 1;
- } else
- data->flags = 0;
- return res;
- }
+ else if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
return -EOPNOTSUPP;
}
@@ -193,24 +137,10 @@ static int ieee80211_ioctl_siwap(struct
if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- int ret;
+ if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
- if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
- sdata->u.mgd.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
- IEEE80211_STA_AUTO_CHANNEL_SEL;
- else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
- sdata->u.mgd.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
- else
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
- ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data);
- if (ret)
- return ret;
- sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
- sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
- ieee80211_sta_req_auth(sdata);
- return 0;
- } else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
+ if (sdata->vif.type == NL80211_IFTYPE_WDS) {
/*
* If it is necessary to update the WDS peer address
* while the interface is running, then we need to do
@@ -240,14 +170,10 @@ static int ieee80211_ioctl_giwap(struct
if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATED) {
- ap_addr->sa_family = ARPHRD_ETHER;
- memcpy(&ap_addr->sa_data, sdata->u.mgd.bssid, ETH_ALEN);
- } else
- memset(&ap_addr->sa_data, 0, ETH_ALEN);
- return 0;
- } else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
+ if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
+
+ if (sdata->vif.type == NL80211_IFTYPE_WDS) {
ap_addr->sa_family = ARPHRD_ETHER;
memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
return 0;
@@ -395,85 +321,6 @@ static int ieee80211_ioctl_giwpower(stru
return 0;
}
-static int ieee80211_ioctl_siwauth(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *data, char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- int ret = 0;
-
- switch (data->flags & IW_AUTH_INDEX) {
- case IW_AUTH_WPA_VERSION:
- case IW_AUTH_CIPHER_GROUP:
- case IW_AUTH_WPA_ENABLED:
- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- case IW_AUTH_KEY_MGMT:
- case IW_AUTH_CIPHER_GROUP_MGMT:
- break;
- case IW_AUTH_CIPHER_PAIRWISE:
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- if (data->value & (IW_AUTH_CIPHER_WEP40 |
- IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_TKIP))
- sdata->u.mgd.flags |=
- IEEE80211_STA_TKIP_WEP_USED;
- else
- sdata->u.mgd.flags &=
- ~IEEE80211_STA_TKIP_WEP_USED;
- }
- break;
- case IW_AUTH_DROP_UNENCRYPTED:
- sdata->drop_unencrypted = !!data->value;
- break;
- case IW_AUTH_PRIVACY_INVOKED:
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- ret = -EINVAL;
- else {
- sdata->u.mgd.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
- /*
- * Privacy invoked by wpa_supplicant, store the
- * value and allow associating to a protected
- * network without having a key up front.
- */
- if (data->value)
- sdata->u.mgd.flags |=
- IEEE80211_STA_PRIVACY_INVOKED;
- }
- break;
- case IW_AUTH_80211_AUTH_ALG:
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- sdata->u.mgd.auth_algs = data->value;
- else
- ret = -EOPNOTSUPP;
- break;
- case IW_AUTH_MFP:
- if (!(sdata->local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) {
- ret = -EOPNOTSUPP;
- break;
- }
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- switch (data->value) {
- case IW_AUTH_MFP_DISABLED:
- sdata->u.mgd.mfp = IEEE80211_MFP_DISABLED;
- break;
- case IW_AUTH_MFP_OPTIONAL:
- sdata->u.mgd.mfp = IEEE80211_MFP_OPTIONAL;
- break;
- case IW_AUTH_MFP_REQUIRED:
- sdata->u.mgd.mfp = IEEE80211_MFP_REQUIRED;
- break;
- default:
- ret = -EINVAL;
- }
- } else
- ret = -EOPNOTSUPP;
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
- return ret;
-}
-
/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
{
@@ -541,28 +388,6 @@ static struct iw_statistics *ieee80211_g
return wstats;
}
-static int ieee80211_ioctl_giwauth(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *data, char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- int ret = 0;
-
- switch (data->flags & IW_AUTH_INDEX) {
- case IW_AUTH_80211_AUTH_ALG:
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- data->value = sdata->u.mgd.auth_algs;
- else
- ret = -EOPNOTSUPP;
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
- return ret;
-}
-
-
/* Structures to export the Wireless Handlers */
static const iw_handler ieee80211_handler[] =
@@ -615,10 +440,10 @@ static const iw_handler ieee80211_handle
(iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
- (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */
+ (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */
(iw_handler) NULL, /* SIOCGIWGENIE */
- (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */
- (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */
+ (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */
+ (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */
(iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */
(iw_handler) NULL, /* SIOCGIWENCODEEXT */
(iw_handler) NULL, /* SIOCSIWPMKSA */
--- wireless-testing.orig/net/mac80211/mlme.c 2009-07-01 20:50:38.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c 2009-07-01 21:15:12.000000000 +0200
@@ -870,70 +870,6 @@ static u32 ieee80211_handle_bss_capabili
return changed;
}
-static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata)
-{
- union iwreq_data wrqu;
-
- memset(&wrqu, 0, sizeof(wrqu));
- if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED)
- memcpy(wrqu.ap_addr.sa_data, sdata->u.mgd.bssid, ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL);
-}
-
-static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- char *buf;
- size_t len;
- int i;
- union iwreq_data wrqu;
-
- if (!ifmgd->assocreq_ies && !ifmgd->assocresp_ies)
- return;
-
- buf = kmalloc(50 + 2 * (ifmgd->assocreq_ies_len +
- ifmgd->assocresp_ies_len), GFP_KERNEL);
- if (!buf)
- return;
-
- len = sprintf(buf, "ASSOCINFO(");
- if (ifmgd->assocreq_ies) {
- len += sprintf(buf + len, "ReqIEs=");
- for (i = 0; i < ifmgd->assocreq_ies_len; i++) {
- len += sprintf(buf + len, "%02x",
- ifmgd->assocreq_ies[i]);
- }
- }
- if (ifmgd->assocresp_ies) {
- if (ifmgd->assocreq_ies)
- len += sprintf(buf + len, " ");
- len += sprintf(buf + len, "RespIEs=");
- for (i = 0; i < ifmgd->assocresp_ies_len; i++) {
- len += sprintf(buf + len, "%02x",
- ifmgd->assocresp_ies[i]);
- }
- }
- len += sprintf(buf + len, ")");
-
- if (len > IW_CUSTOM_MAX) {
- len = sprintf(buf, "ASSOCRESPIE=");
- for (i = 0; i < ifmgd->assocresp_ies_len; i++) {
- len += sprintf(buf + len, "%02x",
- ifmgd->assocresp_ies[i]);
- }
- }
-
- if (len <= IW_CUSTOM_MAX) {
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = len;
- wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf);
- }
-
- kfree(buf);
-}
-
-
static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
u32 bss_info_changed)
{
@@ -966,7 +902,6 @@ static void ieee80211_set_associated(str
ifmgd->flags |= IEEE80211_STA_PREV_BSSID_SET;
memcpy(ifmgd->prev_bssid, sdata->u.mgd.bssid, ETH_ALEN);
- ieee80211_sta_send_associnfo(sdata);
ifmgd->last_probe = jiffies;
ieee80211_led_assoc(local, 1);
@@ -993,8 +928,6 @@ static void ieee80211_set_associated(str
netif_tx_start_all_queues(sdata->dev);
netif_carrier_on(sdata->dev);
-
- ieee80211_sta_send_apinfo(sdata);
}
static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata)
@@ -1147,8 +1080,6 @@ static void ieee80211_set_disassoc(struc
changed |= BSS_CHANGED_ASSOC;
sdata->vif.bss_conf.assoc = false;
- ieee80211_sta_send_apinfo(sdata);
-
if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) {
ifmgd->state = IEEE80211_STA_MLME_DISABLED;
ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
--- wireless-testing.orig/net/wireless/wext-compat.c 2009-07-01 20:50:38.000000000 +0200
+++ wireless-testing/net/wireless/wext-compat.c 2009-07-01 21:15:45.000000000 +0200
@@ -261,50 +261,6 @@ int cfg80211_wext_giwrange(struct net_de
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange);
-int cfg80211_wext_siwmlme(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct iw_mlme *mlme = (struct iw_mlme *)extra;
- struct cfg80211_registered_device *rdev;
- union {
- struct cfg80211_disassoc_request disassoc;
- struct cfg80211_deauth_request deauth;
- } cmd;
-
- if (!wdev)
- return -EOPNOTSUPP;
-
- rdev = wiphy_to_dev(wdev->wiphy);
-
- if (wdev->iftype != NL80211_IFTYPE_STATION)
- return -EINVAL;
-
- if (mlme->addr.sa_family != ARPHRD_ETHER)
- return -EINVAL;
-
- memset(&cmd, 0, sizeof(cmd));
-
- switch (mlme->cmd) {
- case IW_MLME_DEAUTH:
- if (!rdev->ops->deauth)
- return -EOPNOTSUPP;
- cmd.deauth.peer_addr = mlme->addr.sa_data;
- cmd.deauth.reason_code = mlme->reason_code;
- return rdev->ops->deauth(wdev->wiphy, dev, &cmd.deauth);
- case IW_MLME_DISASSOC:
- if (!rdev->ops->disassoc)
- return -EOPNOTSUPP;
- cmd.disassoc.peer_addr = mlme->addr.sa_data;
- cmd.disassoc.reason_code = mlme->reason_code;
- return rdev->ops->disassoc(wdev->wiphy, dev, &cmd.disassoc);
- default:
- return -EOPNOTSUPP;
- }
-}
-EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme);
-
/**
* cfg80211_wext_freq - get wext frequency for non-"auto"
@@ -846,3 +802,188 @@ int cfg80211_wext_giwtxpower(struct net_
return 0;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower);
+
+static int cfg80211_set_auth_alg(struct wireless_dev *wdev,
+ s32 auth_alg)
+{
+ int nr_alg = 0;
+
+ if (!auth_alg)
+ return -EINVAL;
+
+ if (auth_alg & ~(IW_AUTH_ALG_OPEN_SYSTEM |
+ IW_AUTH_ALG_SHARED_KEY |
+ IW_AUTH_ALG_LEAP))
+ return -EINVAL;
+
+ if (auth_alg & IW_AUTH_ALG_OPEN_SYSTEM) {
+ nr_alg++;
+ wdev->wext.connect.auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
+ }
+
+ if (auth_alg & IW_AUTH_ALG_SHARED_KEY) {
+ nr_alg++;
+ wdev->wext.connect.auth_type = NL80211_AUTHTYPE_SHARED_KEY;
+ }
+
+ if (auth_alg & IW_AUTH_ALG_LEAP) {
+ nr_alg++;
+ wdev->wext.connect.auth_type = NL80211_AUTHTYPE_NETWORK_EAP;
+ }
+
+ if (nr_alg > 1)
+ wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
+
+ return 0;
+}
+
+static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions)
+{
+ wdev->wext.connect.crypto.wpa_versions = 0;
+
+ if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA |
+ IW_AUTH_WPA_VERSION_WPA2))
+ return -EINVAL;
+
+ if (wpa_versions & IW_AUTH_WPA_VERSION_WPA)
+ wdev->wext.connect.crypto.wpa_versions |=
+ NL80211_WPA_VERSION_1;
+
+ if (wpa_versions & IW_AUTH_WPA_VERSION_WPA2)
+ wdev->wext.connect.crypto.wpa_versions |=
+ NL80211_WPA_VERSION_2;
+
+ return 0;
+}
+
+int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher)
+{
+ wdev->wext.connect.crypto.cipher_group = 0;
+
+ if (cipher & IW_AUTH_CIPHER_WEP40)
+ wdev->wext.connect.crypto.cipher_group =
+ WLAN_CIPHER_SUITE_WEP40;
+ else if (cipher & IW_AUTH_CIPHER_WEP104)
+ wdev->wext.connect.crypto.cipher_group =
+ WLAN_CIPHER_SUITE_WEP104;
+ else if (cipher & IW_AUTH_CIPHER_TKIP)
+ wdev->wext.connect.crypto.cipher_group =
+ WLAN_CIPHER_SUITE_TKIP;
+ else if (cipher & IW_AUTH_CIPHER_CCMP)
+ wdev->wext.connect.crypto.cipher_group =
+ WLAN_CIPHER_SUITE_CCMP;
+ else if (cipher & IW_AUTH_CIPHER_AES_CMAC)
+ wdev->wext.connect.crypto.cipher_group =
+ WLAN_CIPHER_SUITE_AES_CMAC;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+int cfg80211_set_cipher_pairwise(struct wireless_dev *wdev, u32 cipher)
+{
+ int nr_ciphers = 0;
+ u32 *ciphers_pairwise = wdev->wext.connect.crypto.ciphers_pairwise;
+
+ if (cipher & IW_AUTH_CIPHER_WEP40) {
+ ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP40;
+ nr_ciphers++;
+ }
+
+ if (cipher & IW_AUTH_CIPHER_WEP104) {
+ ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP104;
+ nr_ciphers++;
+ }
+
+ if (cipher & IW_AUTH_CIPHER_TKIP) {
+ ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_TKIP;
+ nr_ciphers++;
+ }
+
+ if (cipher & IW_AUTH_CIPHER_CCMP) {
+ ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_CCMP;
+ nr_ciphers++;
+ }
+
+ if (cipher & IW_AUTH_CIPHER_AES_CMAC) {
+ ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_AES_CMAC;
+ nr_ciphers++;
+ }
+
+ BUILD_BUG_ON(NL80211_MAX_NR_CIPHER_SUITES < 5);
+
+ wdev->wext.connect.crypto.n_ciphers_pairwise = nr_ciphers;
+
+ return 0;
+}
+
+
+int cfg80211_set_key_mgt(struct wireless_dev *wdev, u32 key_mgt)
+{
+ int nr_akm_suites = 0;
+
+ if (key_mgt & ~(IW_AUTH_KEY_MGMT_802_1X |
+ IW_AUTH_KEY_MGMT_PSK))
+ return -EINVAL;
+
+ if (key_mgt & IW_AUTH_KEY_MGMT_802_1X) {
+ wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
+ WLAN_AKM_SUITE_8021X;
+ nr_akm_suites++;
+ }
+
+ if (key_mgt & IW_AUTH_KEY_MGMT_PSK) {
+ wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
+ WLAN_AKM_SUITE_PSK;
+ nr_akm_suites++;
+ }
+
+ wdev->wext.connect.crypto.n_akm_suites = nr_akm_suites;
+
+ return 0;
+}
+
+int cfg80211_wext_siwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ if (wdev->iftype != NL80211_IFTYPE_STATION)
+ return -EOPNOTSUPP;
+
+ switch (data->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_PRIVACY_INVOKED:
+ wdev->wext.connect.privacy = data->value;
+ return 0;
+ case IW_AUTH_WPA_VERSION:
+ return cfg80211_set_wpa_version(wdev, data->value);
+ case IW_AUTH_CIPHER_GROUP:
+ return cfg80211_set_cipher_group(wdev, data->value);
+ case IW_AUTH_KEY_MGMT:
+ return cfg80211_set_key_mgt(wdev, data->value);
+ case IW_AUTH_CIPHER_PAIRWISE:
+ return cfg80211_set_cipher_pairwise(wdev, data->value);
+ case IW_AUTH_80211_AUTH_ALG:
+ return cfg80211_set_auth_alg(wdev, data->value);
+ case IW_AUTH_WPA_ENABLED:
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ case IW_AUTH_DROP_UNENCRYPTED:
+ case IW_AUTH_MFP:
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwauth);
+
+int cfg80211_wext_giwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra)
+{
+ /* XXX: what do we need? */
+
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth);
--- wireless-testing.orig/net/wireless/core.h 2009-07-01 20:58:27.000000000 +0200
+++ wireless-testing/net/wireless/core.h 2009-07-01 21:15:12.000000000 +0200
@@ -181,7 +181,8 @@ int cfg80211_connect(struct cfg80211_reg
struct net_device *dev,
struct cfg80211_connect_params *connect);
int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
- struct net_device *dev, u16 reason);
+ struct net_device *dev, u16 reason,
+ bool wextev);
void cfg80211_conn_work(struct work_struct *work);
--- wireless-testing.orig/net/wireless/nl80211.c 2009-07-01 20:58:27.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.c 2009-07-01 21:15:12.000000000 +0200
@@ -3746,7 +3746,7 @@ static int nl80211_disconnect(struct sk_
goto out;
}
- err = cfg80211_disconnect(drv, dev, reason);
+ err = cfg80211_disconnect(drv, dev, reason, true);
out:
cfg80211_put_dev(drv);
--- wireless-testing.orig/net/wireless/sme.c 2009-07-01 20:58:27.000000000 +0200
+++ wireless-testing/net/wireless/sme.c 2009-07-01 21:15:12.000000000 +0200
@@ -270,10 +270,10 @@ void cfg80211_sme_rx_auth(struct net_dev
}
}
-void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
- const u8 *req_ie, size_t req_ie_len,
- const u8 *resp_ie, size_t resp_ie_len,
- u16 status, gfp_t gfp)
+static void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, bool wextev, gfp_t gfp)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_bss *bss;
@@ -318,25 +318,36 @@ void cfg80211_connect_result(struct net_
status, gfp);
#ifdef CONFIG_WIRELESS_EXT
- if (req_ie && status == WLAN_STATUS_SUCCESS) {
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = req_ie_len;
- wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie);
- }
+ if (wextev) {
+ if (req_ie && status == WLAN_STATUS_SUCCESS) {
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = req_ie_len;
+ wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie);
+ }
+
+ if (resp_ie && status == WLAN_STATUS_SUCCESS) {
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = resp_ie_len;
+ wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
+ }
- if (resp_ie && status == WLAN_STATUS_SUCCESS) {
memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = resp_ie_len;
- wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ if (bssid && status == WLAN_STATUS_SUCCESS)
+ memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
+ wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
}
-
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- if (bssid && status == WLAN_STATUS_SUCCESS)
- memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
- wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
#endif
}
+
+void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, gfp_t gfp)
+{
+ bool wextev = status == WLAN_STATUS_SUCCESS;
+ __cfg80211_connect_result(dev, bssid, req_ie, req_ie_len, resp_ie, resp_ie_len, status, wextev, gfp);
+}
EXPORT_SYMBOL(cfg80211_connect_result);
void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
@@ -537,7 +548,7 @@ int cfg80211_connect(struct cfg80211_reg
}
int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
- struct net_device *dev, u16 reason)
+ struct net_device *dev, u16 reason, bool wextev)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
@@ -582,9 +593,9 @@ int cfg80211_disconnect(struct cfg80211_
if (wdev->sme_state == CFG80211_SME_CONNECTED)
__cfg80211_disconnected(dev, GFP_KERNEL, NULL, 0, 0, false);
else if (wdev->sme_state == CFG80211_SME_CONNECTING)
- cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0,
- WLAN_STATUS_UNSPECIFIED_FAILURE,
- GFP_KERNEL);
+ __cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ wextev, GFP_KERNEL);
return 0;
}
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH] iwmc3200wifi: cfg80211 managed mode port
2009-07-01 19:26 ` [PATCH 15/20 v4] cfg80211: managed mode wext compatibility Johannes Berg
@ 2009-07-02 23:55 ` Samuel Ortiz
2009-07-03 8:02 ` Johannes Berg
2009-07-05 1:37 ` Johannes Berg
2009-07-03 0:00 ` [PATCH] cfg80211: check for current_bss from giwrate Samuel Ortiz
1 sibling, 2 replies; 31+ messages in thread
From: Samuel Ortiz @ 2009-07-02 23:55 UTC (permalink / raw)
To: Johannes Berg, Zhu, Yi; +Cc: John Linville, linux-wireless@vger.kernel.org
This patch ports iwm to the new cfg80211 managed mode API.
Whenever those managed mode routines get combined with the ibss one, we will
just have to entirely get rid of the wext implementation (We may have to only
keep the iw_handler until cfg80211 does the wext registration for us).
Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com>
---
drivers/net/wireless/iwmc3200wifi/cfg80211.c | 195 ++++++++++++++++
drivers/net/wireless/iwmc3200wifi/rx.c | 13 -
drivers/net/wireless/iwmc3200wifi/wext.c | 320 ++-------------------------
3 files changed, 239 insertions(+), 289 deletions(-)
Index: iwm-2.6/drivers/net/wireless/iwmc3200wifi/cfg80211.c
===================================================================
--- iwm-2.6.orig/drivers/net/wireless/iwmc3200wifi/cfg80211.c 2009-07-02 21:20:34.000000000 +0200
+++ iwm-2.6/drivers/net/wireless/iwmc3200wifi/cfg80211.c 2009-07-03 01:43:09.000000000 +0200
@@ -305,6 +305,25 @@ static int iwm_cfg80211_set_default_key(
return iwm_reset_profile(iwm);
}
+int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
+ u8 *mac, struct station_info *sinfo)
+{
+ struct iwm_priv *iwm = ndev_to_iwm(ndev);
+
+ if (memcmp(mac, iwm->bssid, ETH_ALEN))
+ return -ENOENT;
+
+ sinfo->filled |= STATION_INFO_TX_BITRATE;
+ sinfo->txrate.legacy = iwm->rate * 10;
+
+ if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
+ sinfo->filled |= STATION_INFO_SIGNAL;
+ sinfo->signal = iwm->wstats.qual.level;
+ }
+
+ return 0;
+}
+
int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
{
@@ -500,6 +519,179 @@ static int iwm_cfg80211_leave_ibss(struc
return 0;
}
+static int iwm_set_auth_type(struct iwm_priv *iwm,
+ enum nl80211_auth_type sme_auth_type)
+{
+ u8 *auth_type = &iwm->umac_profile->sec.auth_type;
+
+ switch (sme_auth_type) {
+ case NL80211_AUTHTYPE_AUTOMATIC:
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+ IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
+ *auth_type = UMAC_AUTH_TYPE_OPEN;
+ break;
+ case NL80211_AUTHTYPE_SHARED_KEY:
+ if (iwm->umac_profile->sec.flags &
+ (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
+ IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
+ *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
+ } else {
+ IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
+ *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
+ }
+
+ break;
+ default:
+ IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
+{
+ if (!wpa_version) {
+ iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
+ return 0;
+ }
+
+ if (wpa_version & NL80211_WPA_VERSION_2)
+ iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
+
+ if (wpa_version & NL80211_WPA_VERSION_1)
+ iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK;
+
+ return 0;
+}
+
+static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
+{
+ u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
+ &iwm->umac_profile->sec.mcast_cipher;
+
+ if (!cipher) {
+ *profile_cipher = UMAC_CIPHER_TYPE_NONE;
+ return 0;
+ }
+
+ switch (cipher) {
+ case IW_AUTH_CIPHER_NONE:
+ *profile_cipher = UMAC_CIPHER_TYPE_NONE;
+ break;
+ case WLAN_CIPHER_SUITE_WEP40:
+ *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
+ break;
+ default:
+ IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
+{
+ u8 *auth_type = &iwm->umac_profile->sec.auth_type;
+
+ IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
+
+ if (key_mgt == WLAN_AKM_SUITE_8021X)
+ *auth_type = UMAC_AUTH_TYPE_8021X;
+ else if (key_mgt == WLAN_AKM_SUITE_PSK) {
+ if (iwm->umac_profile->sec.flags &
+ (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
+ *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
+ else
+ *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
+ } else {
+ IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme)
+{
+ struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+ struct ieee80211_channel *chan = sme->channel;
+ int ret;
+
+ if (!test_bit(IWM_STATUS_READY, &iwm->status))
+ return -EIO;
+
+ if (!sme->ssid)
+ return -EINVAL;
+
+ if (chan)
+ iwm->channel =
+ ieee80211_frequency_to_channel(chan->center_freq);
+
+ iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
+ memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
+
+ if (sme->bssid) {
+ IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
+ memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
+ iwm->umac_profile->bss_num = 1;
+ } else {
+ memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
+ iwm->umac_profile->bss_num = 0;
+ }
+
+ ret = iwm_set_auth_type(iwm, sme->auth_type);
+ if (ret < 0)
+ return ret;
+
+ ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
+ if (ret < 0)
+ return ret;
+
+ if (sme->crypto.n_ciphers_pairwise) {
+ ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
+ true);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
+ if (ret < 0)
+ return ret;
+
+ if (sme->crypto.n_akm_suites) {
+ ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
+ if (ret < 0)
+ return ret;
+ }
+
+ return iwm_send_mlme_profile(iwm);
+}
+
+static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+ u16 reason_code)
+{
+ struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+
+ IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
+
+ if (iwm->umac_profile_active)
+ return iwm_invalidate_mlme_profile(iwm);
+
+ return 0;
+}
+
static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
enum tx_power_setting type, int dbm)
{
@@ -549,8 +741,11 @@ static struct cfg80211_ops iwm_cfg80211_
.get_key = iwm_cfg80211_get_key,
.del_key = iwm_cfg80211_del_key,
.set_default_key = iwm_cfg80211_set_default_key,
+ .get_station = iwm_cfg80211_get_station,
.scan = iwm_cfg80211_scan,
.set_wiphy_params = iwm_cfg80211_set_wiphy_params,
+ .connect = iwm_cfg80211_connect,
+ .disconnect = iwm_cfg80211_disconnect,
.join_ibss = iwm_cfg80211_join_ibss,
.leave_ibss = iwm_cfg80211_leave_ibss,
.set_tx_power = iwm_cfg80211_set_txpower,
Index: iwm-2.6/drivers/net/wireless/iwmc3200wifi/wext.c
===================================================================
--- iwm-2.6.orig/drivers/net/wireless/iwmc3200wifi/wext.c 2009-07-02 21:20:34.000000000 +0200
+++ iwm-2.6/drivers/net/wireless/iwmc3200wifi/wext.c 2009-07-03 01:18:56.000000000 +0200
@@ -21,31 +21,11 @@
*
*/
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
#include <linux/wireless.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
#include <net/cfg80211.h>
-#include <net/iw_handler.h>
#include "iwm.h"
-#include "umac.h"
#include "commands.h"
-#include "debug.h"
-
-static struct iw_statistics *iwm_get_wireless_stats(struct net_device *dev)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
- struct iw_statistics *wstats = &iwm->wstats;
-
- if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
- memset(wstats, 0, sizeof(struct iw_statistics));
- wstats->qual.updated = IW_QUAL_ALL_INVALID;
- }
-
- return wstats;
-}
static int iwm_wext_siwfreq(struct net_device *dev,
struct iw_request_info *info,
@@ -53,14 +33,12 @@ static int iwm_wext_siwfreq(struct net_d
{
struct iwm_priv *iwm = ndev_to_iwm(dev);
- if (freq->flags == IW_FREQ_AUTO)
- return 0;
-
- /* frequency/channel can only be set in IBSS mode */
- if (iwm->conf.mode != UMAC_MODE_IBSS)
+ switch (iwm->conf.mode) {
+ case UMAC_MODE_IBSS:
+ return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
+ default:
return -EOPNOTSUPP;
-
- return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
+ }
}
static int iwm_wext_giwfreq(struct net_device *dev,
@@ -69,69 +47,29 @@ static int iwm_wext_giwfreq(struct net_d
{
struct iwm_priv *iwm = ndev_to_iwm(dev);
- if (iwm->conf.mode == UMAC_MODE_IBSS)
+ switch (iwm->conf.mode) {
+ case UMAC_MODE_IBSS:
return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
-
- freq->e = 0;
- freq->m = iwm->channel;
-
- return 0;
+ case UMAC_MODE_BSS:
+ return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
+ default:
+ return -EOPNOTSUPP;
+ }
}
static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info,
struct sockaddr *ap_addr, char *extra)
{
struct iwm_priv *iwm = ndev_to_iwm(dev);
- int ret;
-
- IWM_DBG_WEXT(iwm, DBG, "Set BSSID: %pM\n", ap_addr->sa_data);
- if (iwm->conf.mode == UMAC_MODE_IBSS)
+ switch (iwm->conf.mode) {
+ case UMAC_MODE_IBSS:
return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
-
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
- return -EIO;
-
- if (is_zero_ether_addr(ap_addr->sa_data) ||
- is_broadcast_ether_addr(ap_addr->sa_data)) {
- IWM_DBG_WEXT(iwm, DBG, "clear mandatory bssid %pM\n",
- iwm->umac_profile->bssid[0]);
- memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
- iwm->umac_profile->bss_num = 0;
- } else {
- IWM_DBG_WEXT(iwm, DBG, "add mandatory bssid %pM\n",
- ap_addr->sa_data);
- memcpy(&iwm->umac_profile->bssid[0], ap_addr->sa_data,
- ETH_ALEN);
- iwm->umac_profile->bss_num = 1;
- }
-
- if (iwm->umac_profile_active) {
- int i;
-
- if (!memcmp(&iwm->umac_profile->bssid[0], iwm->bssid, ETH_ALEN))
- return 0;
-
- /*
- * If we're clearing the BSSID, and we're associated,
- * we have to clear the keys as they're no longer valid.
- */
- if (is_zero_ether_addr(ap_addr->sa_data)) {
- for (i = 0; i < IWM_NUM_KEYS; i++)
- iwm->keys[i].key_len = 0;
- }
-
- ret = iwm_invalidate_mlme_profile(iwm);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't invalidate profile\n");
- return ret;
- }
+ case UMAC_MODE_BSS:
+ return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
+ default:
+ return -EOPNOTSUPP;
}
-
- if (iwm->umac_profile->ssid.ssid_len)
- return iwm_send_mlme_profile(iwm);
-
- return 0;
}
static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info,
@@ -143,17 +81,10 @@ static int iwm_wext_giwap(struct net_dev
case UMAC_MODE_IBSS:
return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
case UMAC_MODE_BSS:
- if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
- ap_addr->sa_family = ARPHRD_ETHER;
- memcpy(&ap_addr->sa_data, iwm->bssid, ETH_ALEN);
- } else
- memset(&ap_addr->sa_data, 0, ETH_ALEN);
- break;
+ return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
default:
return -EOPNOTSUPP;
}
-
- return 0;
}
static int iwm_wext_siwessid(struct net_device *dev,
@@ -161,36 +92,15 @@ static int iwm_wext_siwessid(struct net_
struct iw_point *data, char *ssid)
{
struct iwm_priv *iwm = ndev_to_iwm(dev);
- size_t len = data->length;
- int ret;
-
- IWM_DBG_WEXT(iwm, DBG, "Set ESSID: >%s<\n", ssid);
- if (iwm->conf.mode == UMAC_MODE_IBSS)
+ switch (iwm->conf.mode) {
+ case UMAC_MODE_IBSS:
return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
-
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
- return -EIO;
-
- if (len > 0 && ssid[len - 1] == '\0')
- len--;
-
- if (iwm->umac_profile_active) {
- if (iwm->umac_profile->ssid.ssid_len == len &&
- !memcmp(iwm->umac_profile->ssid.ssid, ssid, len))
- return 0;
-
- ret = iwm_invalidate_mlme_profile(iwm);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't invalidate profile\n");
- return ret;
- }
+ case UMAC_MODE_BSS:
+ return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
+ default:
+ return -EOPNOTSUPP;
}
-
- iwm->umac_profile->ssid.ssid_len = len;
- memcpy(iwm->umac_profile->ssid.ssid, ssid, len);
-
- return iwm_send_mlme_profile(iwm);
}
static int iwm_wext_giwessid(struct net_device *dev,
@@ -199,174 +109,14 @@ static int iwm_wext_giwessid(struct net_
{
struct iwm_priv *iwm = ndev_to_iwm(dev);
- if (iwm->conf.mode == UMAC_MODE_IBSS)
+ switch (iwm->conf.mode) {
+ case UMAC_MODE_IBSS:
return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
-
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
- return -EIO;
-
- data->length = iwm->umac_profile->ssid.ssid_len;
- if (data->length) {
- memcpy(ssid, iwm->umac_profile->ssid.ssid, data->length);
- data->flags = 1;
- } else
- data->flags = 0;
-
- return 0;
-}
-
-static int iwm_wext_giwrate(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rate, char *extra)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
-
- rate->value = iwm->rate * 1000000;
-
- return 0;
-}
-
-static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version)
-{
- if (wpa_version & IW_AUTH_WPA_VERSION_WPA2)
- iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
- else if (wpa_version & IW_AUTH_WPA_VERSION_WPA)
- iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
- else
- iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
-
- return 0;
-}
-
-static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt)
-{
- u8 *auth_type = &iwm->umac_profile->sec.auth_type;
-
- IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
-
- if (key_mgt == IW_AUTH_KEY_MGMT_802_1X)
- *auth_type = UMAC_AUTH_TYPE_8021X;
- else if (key_mgt == IW_AUTH_KEY_MGMT_PSK) {
- if (iwm->umac_profile->sec.flags &
- (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
- *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
- else
- *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
- } else {
- IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int iwm_set_cipher(struct iwm_priv *iwm, u8 cipher, u8 ucast)
-{
- u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
- &iwm->umac_profile->sec.mcast_cipher;
-
- switch (cipher) {
- case IW_AUTH_CIPHER_NONE:
- *profile_cipher = UMAC_CIPHER_TYPE_NONE;
- break;
- case IW_AUTH_CIPHER_WEP40:
- *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
- break;
- case IW_AUTH_CIPHER_TKIP:
- *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
- break;
- case IW_AUTH_CIPHER_CCMP:
- *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
- break;
- case IW_AUTH_CIPHER_WEP104:
- *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
- break;
- default:
- IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
- return -ENOTSUPP;
- }
-
- return 0;
-}
-
-static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg)
-{
- u8 *auth_type = &iwm->umac_profile->sec.auth_type;
-
- IWM_DBG_WEXT(iwm, DBG, "auth_alg: 0x%x\n", auth_alg);
-
- switch (auth_alg) {
- case IW_AUTH_ALG_OPEN_SYSTEM:
- *auth_type = UMAC_AUTH_TYPE_OPEN;
- break;
- case IW_AUTH_ALG_SHARED_KEY:
- if (iwm->umac_profile->sec.flags &
- (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
- if (*auth_type == UMAC_AUTH_TYPE_8021X)
- return -EINVAL;
- *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
- } else {
- IWM_DBG_WEXT(iwm, DBG, "WEP shared key\n");
- *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
- }
- break;
- case IW_AUTH_ALG_LEAP:
- default:
- IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", auth_alg);
- return -ENOTSUPP;
- }
-
- return 0;
-}
-
-static int iwm_wext_siwauth(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *data, char *extra)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
- int ret;
-
- if ((data->flags) &
- (IW_AUTH_WPA_VERSION | IW_AUTH_KEY_MGMT |
- IW_AUTH_WPA_ENABLED | IW_AUTH_80211_AUTH_ALG)) {
- /* We need to invalidate the current profile */
- if (iwm->umac_profile_active) {
- ret = iwm_invalidate_mlme_profile(iwm);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't invalidate profile\n");
- return ret;
- }
- }
- }
-
- switch (data->flags & IW_AUTH_INDEX) {
- case IW_AUTH_WPA_VERSION:
- return iwm_set_wpa_version(iwm, data->value);
- break;
- case IW_AUTH_CIPHER_PAIRWISE:
- return iwm_set_cipher(iwm, data->value, 1);
- break;
- case IW_AUTH_CIPHER_GROUP:
- return iwm_set_cipher(iwm, data->value, 0);
- break;
- case IW_AUTH_KEY_MGMT:
- return iwm_set_key_mgt(iwm, data->value);
- break;
- case IW_AUTH_80211_AUTH_ALG:
- return iwm_set_auth_alg(iwm, data->value);
- break;
+ case UMAC_MODE_BSS:
+ return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
default:
- return -ENOTSUPP;
+ return -EOPNOTSUPP;
}
-
- return 0;
-}
-
-static int iwm_wext_giwauth(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *data, char *extra)
-{
- return 0;
}
static const iw_handler iwm_handlers[] =
@@ -404,7 +154,7 @@ static const iw_handler iwm_handlers[] =
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* SIOCSIWRATE */
- (iw_handler) iwm_wext_giwrate, /* SIOCGIWRATE */
+ (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */
(iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */
(iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
(iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
@@ -419,10 +169,10 @@ static const iw_handler iwm_handlers[] =
(iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* SIOCSIWGENIE */
+ (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */
(iw_handler) NULL, /* SIOCGIWGENIE */
- (iw_handler) iwm_wext_siwauth, /* SIOCSIWAUTH */
- (iw_handler) iwm_wext_giwauth, /* SIOCGIWAUTH */
+ (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */
+ (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */
(iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */
(iw_handler) NULL, /* SIOCGIWENCODEEXT */
(iw_handler) NULL, /* SIOCSIWPMKSA */
@@ -432,6 +182,6 @@ static const iw_handler iwm_handlers[] =
const struct iw_handler_def iwm_iw_handler_def = {
.num_standard = ARRAY_SIZE(iwm_handlers),
.standard = (iw_handler *) iwm_handlers,
- .get_wireless_stats = iwm_get_wireless_stats,
+ .get_wireless_stats = cfg80211_wireless_stats,
};
Index: iwm-2.6/drivers/net/wireless/iwmc3200wifi/rx.c
===================================================================
--- iwm-2.6.orig/drivers/net/wireless/iwmc3200wifi/rx.c 2009-07-02 21:19:58.000000000 +0200
+++ iwm-2.6/drivers/net/wireless/iwmc3200wifi/rx.c 2009-07-03 00:24:46.000000000 +0200
@@ -521,7 +521,10 @@ static int iwm_mlme_assoc_complete(struc
iwm_link_on(iwm);
- memcpy(wrqu.ap_addr.sa_data, complete->bssid, ETH_ALEN);
+ cfg80211_connect_result(iwm_to_ndev(iwm),
+ complete->bssid,
+ NULL, 0, NULL, 0,
+ WLAN_STATUS_SUCCESS, GFP_KERNEL);
break;
case UMAC_ASSOC_COMPLETE_FAILURE:
clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
@@ -529,6 +532,11 @@ static int iwm_mlme_assoc_complete(struc
iwm->channel = 0;
iwm_link_off(iwm);
+
+ cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid,
+ NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_KERNEL);
default:
break;
}
@@ -538,9 +546,6 @@ static int iwm_mlme_assoc_complete(struc
return 0;
}
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(iwm_to_ndev(iwm), SIOCGIWAP, &wrqu, NULL);
-
return 0;
}
--
Intel Open Source Technology Centre
http://oss.intel.com/
---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris,
92196 Meudon Cedex, France
Registration Number: 302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH] iwmc3200wifi: cfg80211 managed mode port
2009-07-02 23:55 ` [PATCH] iwmc3200wifi: cfg80211 managed mode port Samuel Ortiz
@ 2009-07-03 8:02 ` Johannes Berg
2009-07-03 13:10 ` Samuel Ortiz
2009-07-05 1:37 ` Johannes Berg
1 sibling, 1 reply; 31+ messages in thread
From: Johannes Berg @ 2009-07-03 8:02 UTC (permalink / raw)
To: Samuel Ortiz; +Cc: Zhu, Yi, John Linville, linux-wireless@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 21676 bytes --]
On Fri, 2009-07-03 at 01:55 +0200, Samuel Ortiz wrote:
> This patch ports iwm to the new cfg80211 managed mode API.
> Whenever those managed mode routines get combined with the ibss one, we will
> just have to entirely get rid of the wext implementation (We may have to only
> keep the iw_handler until cfg80211 does the wext registration for us).
Looks good. I'll take care of the combine part later.
johannes
> Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com>
> ---
> drivers/net/wireless/iwmc3200wifi/cfg80211.c | 195 ++++++++++++++++
> drivers/net/wireless/iwmc3200wifi/rx.c | 13 -
> drivers/net/wireless/iwmc3200wifi/wext.c | 320 ++-------------------------
> 3 files changed, 239 insertions(+), 289 deletions(-)
>
> Index: iwm-2.6/drivers/net/wireless/iwmc3200wifi/cfg80211.c
> ===================================================================
> --- iwm-2.6.orig/drivers/net/wireless/iwmc3200wifi/cfg80211.c 2009-07-02 21:20:34.000000000 +0200
> +++ iwm-2.6/drivers/net/wireless/iwmc3200wifi/cfg80211.c 2009-07-03 01:43:09.000000000 +0200
> @@ -305,6 +305,25 @@ static int iwm_cfg80211_set_default_key(
> return iwm_reset_profile(iwm);
> }
>
> +int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
> + u8 *mac, struct station_info *sinfo)
> +{
> + struct iwm_priv *iwm = ndev_to_iwm(ndev);
> +
> + if (memcmp(mac, iwm->bssid, ETH_ALEN))
> + return -ENOENT;
> +
> + sinfo->filled |= STATION_INFO_TX_BITRATE;
> + sinfo->txrate.legacy = iwm->rate * 10;
> +
> + if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
> + sinfo->filled |= STATION_INFO_SIGNAL;
> + sinfo->signal = iwm->wstats.qual.level;
> + }
> +
> + return 0;
> +}
> +
>
> int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
> {
> @@ -500,6 +519,179 @@ static int iwm_cfg80211_leave_ibss(struc
> return 0;
> }
>
> +static int iwm_set_auth_type(struct iwm_priv *iwm,
> + enum nl80211_auth_type sme_auth_type)
> +{
> + u8 *auth_type = &iwm->umac_profile->sec.auth_type;
> +
> + switch (sme_auth_type) {
> + case NL80211_AUTHTYPE_AUTOMATIC:
> + case NL80211_AUTHTYPE_OPEN_SYSTEM:
> + IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
> + *auth_type = UMAC_AUTH_TYPE_OPEN;
> + break;
> + case NL80211_AUTHTYPE_SHARED_KEY:
> + if (iwm->umac_profile->sec.flags &
> + (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
> + IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
> + *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
> + } else {
> + IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
> + *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
> + }
> +
> + break;
> + default:
> + IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
> + return -ENOTSUPP;
> + }
> +
> + return 0;
> +}
> +
> +static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
> +{
> + if (!wpa_version) {
> + iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
> + return 0;
> + }
> +
> + if (wpa_version & NL80211_WPA_VERSION_2)
> + iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
> +
> + if (wpa_version & NL80211_WPA_VERSION_1)
> + iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK;
> +
> + return 0;
> +}
> +
> +static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
> +{
> + u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
> + &iwm->umac_profile->sec.mcast_cipher;
> +
> + if (!cipher) {
> + *profile_cipher = UMAC_CIPHER_TYPE_NONE;
> + return 0;
> + }
> +
> + switch (cipher) {
> + case IW_AUTH_CIPHER_NONE:
> + *profile_cipher = UMAC_CIPHER_TYPE_NONE;
> + break;
> + case WLAN_CIPHER_SUITE_WEP40:
> + *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
> + break;
> + case WLAN_CIPHER_SUITE_WEP104:
> + *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
> + break;
> + case WLAN_CIPHER_SUITE_TKIP:
> + *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
> + break;
> + case WLAN_CIPHER_SUITE_CCMP:
> + *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
> + break;
> + default:
> + IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
> + return -ENOTSUPP;
> + }
> +
> + return 0;
> +}
> +
> +static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
> +{
> + u8 *auth_type = &iwm->umac_profile->sec.auth_type;
> +
> + IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
> +
> + if (key_mgt == WLAN_AKM_SUITE_8021X)
> + *auth_type = UMAC_AUTH_TYPE_8021X;
> + else if (key_mgt == WLAN_AKM_SUITE_PSK) {
> + if (iwm->umac_profile->sec.flags &
> + (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
> + *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
> + else
> + *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
> + } else {
> + IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +
> +static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
> + struct cfg80211_connect_params *sme)
> +{
> + struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
> + struct ieee80211_channel *chan = sme->channel;
> + int ret;
> +
> + if (!test_bit(IWM_STATUS_READY, &iwm->status))
> + return -EIO;
> +
> + if (!sme->ssid)
> + return -EINVAL;
> +
> + if (chan)
> + iwm->channel =
> + ieee80211_frequency_to_channel(chan->center_freq);
> +
> + iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
> + memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
> +
> + if (sme->bssid) {
> + IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
> + memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
> + iwm->umac_profile->bss_num = 1;
> + } else {
> + memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
> + iwm->umac_profile->bss_num = 0;
> + }
> +
> + ret = iwm_set_auth_type(iwm, sme->auth_type);
> + if (ret < 0)
> + return ret;
> +
> + ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
> + if (ret < 0)
> + return ret;
> +
> + if (sme->crypto.n_ciphers_pairwise) {
> + ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
> + true);
> + if (ret < 0)
> + return ret;
> + }
> +
> + ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
> + if (ret < 0)
> + return ret;
> +
> + if (sme->crypto.n_akm_suites) {
> + ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
> + if (ret < 0)
> + return ret;
> + }
> +
> + return iwm_send_mlme_profile(iwm);
> +}
> +
> +static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
> + u16 reason_code)
> +{
> + struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
> +
> + IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
> +
> + if (iwm->umac_profile_active)
> + return iwm_invalidate_mlme_profile(iwm);
> +
> + return 0;
> +}
> +
> static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
> enum tx_power_setting type, int dbm)
> {
> @@ -549,8 +741,11 @@ static struct cfg80211_ops iwm_cfg80211_
> .get_key = iwm_cfg80211_get_key,
> .del_key = iwm_cfg80211_del_key,
> .set_default_key = iwm_cfg80211_set_default_key,
> + .get_station = iwm_cfg80211_get_station,
> .scan = iwm_cfg80211_scan,
> .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
> + .connect = iwm_cfg80211_connect,
> + .disconnect = iwm_cfg80211_disconnect,
> .join_ibss = iwm_cfg80211_join_ibss,
> .leave_ibss = iwm_cfg80211_leave_ibss,
> .set_tx_power = iwm_cfg80211_set_txpower,
> Index: iwm-2.6/drivers/net/wireless/iwmc3200wifi/wext.c
> ===================================================================
> --- iwm-2.6.orig/drivers/net/wireless/iwmc3200wifi/wext.c 2009-07-02 21:20:34.000000000 +0200
> +++ iwm-2.6/drivers/net/wireless/iwmc3200wifi/wext.c 2009-07-03 01:18:56.000000000 +0200
> @@ -21,31 +21,11 @@
> *
> */
>
> -#include <linux/kernel.h>
> -#include <linux/netdevice.h>
> #include <linux/wireless.h>
> -#include <linux/if_arp.h>
> -#include <linux/etherdevice.h>
> #include <net/cfg80211.h>
> -#include <net/iw_handler.h>
>
> #include "iwm.h"
> -#include "umac.h"
> #include "commands.h"
> -#include "debug.h"
> -
> -static struct iw_statistics *iwm_get_wireless_stats(struct net_device *dev)
> -{
> - struct iwm_priv *iwm = ndev_to_iwm(dev);
> - struct iw_statistics *wstats = &iwm->wstats;
> -
> - if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
> - memset(wstats, 0, sizeof(struct iw_statistics));
> - wstats->qual.updated = IW_QUAL_ALL_INVALID;
> - }
> -
> - return wstats;
> -}
>
> static int iwm_wext_siwfreq(struct net_device *dev,
> struct iw_request_info *info,
> @@ -53,14 +33,12 @@ static int iwm_wext_siwfreq(struct net_d
> {
> struct iwm_priv *iwm = ndev_to_iwm(dev);
>
> - if (freq->flags == IW_FREQ_AUTO)
> - return 0;
> -
> - /* frequency/channel can only be set in IBSS mode */
> - if (iwm->conf.mode != UMAC_MODE_IBSS)
> + switch (iwm->conf.mode) {
> + case UMAC_MODE_IBSS:
> + return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
> + default:
> return -EOPNOTSUPP;
> -
> - return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
> + }
> }
>
> static int iwm_wext_giwfreq(struct net_device *dev,
> @@ -69,69 +47,29 @@ static int iwm_wext_giwfreq(struct net_d
> {
> struct iwm_priv *iwm = ndev_to_iwm(dev);
>
> - if (iwm->conf.mode == UMAC_MODE_IBSS)
> + switch (iwm->conf.mode) {
> + case UMAC_MODE_IBSS:
> return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
> -
> - freq->e = 0;
> - freq->m = iwm->channel;
> -
> - return 0;
> + case UMAC_MODE_BSS:
> + return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
> + default:
> + return -EOPNOTSUPP;
> + }
> }
>
> static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info,
> struct sockaddr *ap_addr, char *extra)
> {
> struct iwm_priv *iwm = ndev_to_iwm(dev);
> - int ret;
> -
> - IWM_DBG_WEXT(iwm, DBG, "Set BSSID: %pM\n", ap_addr->sa_data);
>
> - if (iwm->conf.mode == UMAC_MODE_IBSS)
> + switch (iwm->conf.mode) {
> + case UMAC_MODE_IBSS:
> return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
> -
> - if (!test_bit(IWM_STATUS_READY, &iwm->status))
> - return -EIO;
> -
> - if (is_zero_ether_addr(ap_addr->sa_data) ||
> - is_broadcast_ether_addr(ap_addr->sa_data)) {
> - IWM_DBG_WEXT(iwm, DBG, "clear mandatory bssid %pM\n",
> - iwm->umac_profile->bssid[0]);
> - memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
> - iwm->umac_profile->bss_num = 0;
> - } else {
> - IWM_DBG_WEXT(iwm, DBG, "add mandatory bssid %pM\n",
> - ap_addr->sa_data);
> - memcpy(&iwm->umac_profile->bssid[0], ap_addr->sa_data,
> - ETH_ALEN);
> - iwm->umac_profile->bss_num = 1;
> - }
> -
> - if (iwm->umac_profile_active) {
> - int i;
> -
> - if (!memcmp(&iwm->umac_profile->bssid[0], iwm->bssid, ETH_ALEN))
> - return 0;
> -
> - /*
> - * If we're clearing the BSSID, and we're associated,
> - * we have to clear the keys as they're no longer valid.
> - */
> - if (is_zero_ether_addr(ap_addr->sa_data)) {
> - for (i = 0; i < IWM_NUM_KEYS; i++)
> - iwm->keys[i].key_len = 0;
> - }
> -
> - ret = iwm_invalidate_mlme_profile(iwm);
> - if (ret < 0) {
> - IWM_ERR(iwm, "Couldn't invalidate profile\n");
> - return ret;
> - }
> + case UMAC_MODE_BSS:
> + return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
> + default:
> + return -EOPNOTSUPP;
> }
> -
> - if (iwm->umac_profile->ssid.ssid_len)
> - return iwm_send_mlme_profile(iwm);
> -
> - return 0;
> }
>
> static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info,
> @@ -143,17 +81,10 @@ static int iwm_wext_giwap(struct net_dev
> case UMAC_MODE_IBSS:
> return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
> case UMAC_MODE_BSS:
> - if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
> - ap_addr->sa_family = ARPHRD_ETHER;
> - memcpy(&ap_addr->sa_data, iwm->bssid, ETH_ALEN);
> - } else
> - memset(&ap_addr->sa_data, 0, ETH_ALEN);
> - break;
> + return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
> default:
> return -EOPNOTSUPP;
> }
> -
> - return 0;
> }
>
> static int iwm_wext_siwessid(struct net_device *dev,
> @@ -161,36 +92,15 @@ static int iwm_wext_siwessid(struct net_
> struct iw_point *data, char *ssid)
> {
> struct iwm_priv *iwm = ndev_to_iwm(dev);
> - size_t len = data->length;
> - int ret;
> -
> - IWM_DBG_WEXT(iwm, DBG, "Set ESSID: >%s<\n", ssid);
>
> - if (iwm->conf.mode == UMAC_MODE_IBSS)
> + switch (iwm->conf.mode) {
> + case UMAC_MODE_IBSS:
> return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
> -
> - if (!test_bit(IWM_STATUS_READY, &iwm->status))
> - return -EIO;
> -
> - if (len > 0 && ssid[len - 1] == '\0')
> - len--;
> -
> - if (iwm->umac_profile_active) {
> - if (iwm->umac_profile->ssid.ssid_len == len &&
> - !memcmp(iwm->umac_profile->ssid.ssid, ssid, len))
> - return 0;
> -
> - ret = iwm_invalidate_mlme_profile(iwm);
> - if (ret < 0) {
> - IWM_ERR(iwm, "Couldn't invalidate profile\n");
> - return ret;
> - }
> + case UMAC_MODE_BSS:
> + return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
> + default:
> + return -EOPNOTSUPP;
> }
> -
> - iwm->umac_profile->ssid.ssid_len = len;
> - memcpy(iwm->umac_profile->ssid.ssid, ssid, len);
> -
> - return iwm_send_mlme_profile(iwm);
> }
>
> static int iwm_wext_giwessid(struct net_device *dev,
> @@ -199,174 +109,14 @@ static int iwm_wext_giwessid(struct net_
> {
> struct iwm_priv *iwm = ndev_to_iwm(dev);
>
> - if (iwm->conf.mode == UMAC_MODE_IBSS)
> + switch (iwm->conf.mode) {
> + case UMAC_MODE_IBSS:
> return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
> -
> - if (!test_bit(IWM_STATUS_READY, &iwm->status))
> - return -EIO;
> -
> - data->length = iwm->umac_profile->ssid.ssid_len;
> - if (data->length) {
> - memcpy(ssid, iwm->umac_profile->ssid.ssid, data->length);
> - data->flags = 1;
> - } else
> - data->flags = 0;
> -
> - return 0;
> -}
> -
> -static int iwm_wext_giwrate(struct net_device *dev,
> - struct iw_request_info *info,
> - struct iw_param *rate, char *extra)
> -{
> - struct iwm_priv *iwm = ndev_to_iwm(dev);
> -
> - rate->value = iwm->rate * 1000000;
> -
> - return 0;
> -}
> -
> -static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version)
> -{
> - if (wpa_version & IW_AUTH_WPA_VERSION_WPA2)
> - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
> - else if (wpa_version & IW_AUTH_WPA_VERSION_WPA)
> - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
> - else
> - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
> -
> - return 0;
> -}
> -
> -static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt)
> -{
> - u8 *auth_type = &iwm->umac_profile->sec.auth_type;
> -
> - IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
> -
> - if (key_mgt == IW_AUTH_KEY_MGMT_802_1X)
> - *auth_type = UMAC_AUTH_TYPE_8021X;
> - else if (key_mgt == IW_AUTH_KEY_MGMT_PSK) {
> - if (iwm->umac_profile->sec.flags &
> - (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
> - *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
> - else
> - *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
> - } else {
> - IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
> - return -EINVAL;
> - }
> -
> - return 0;
> -}
> -
> -static int iwm_set_cipher(struct iwm_priv *iwm, u8 cipher, u8 ucast)
> -{
> - u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
> - &iwm->umac_profile->sec.mcast_cipher;
> -
> - switch (cipher) {
> - case IW_AUTH_CIPHER_NONE:
> - *profile_cipher = UMAC_CIPHER_TYPE_NONE;
> - break;
> - case IW_AUTH_CIPHER_WEP40:
> - *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
> - break;
> - case IW_AUTH_CIPHER_TKIP:
> - *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
> - break;
> - case IW_AUTH_CIPHER_CCMP:
> - *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
> - break;
> - case IW_AUTH_CIPHER_WEP104:
> - *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
> - break;
> - default:
> - IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
> - return -ENOTSUPP;
> - }
> -
> - return 0;
> -}
> -
> -static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg)
> -{
> - u8 *auth_type = &iwm->umac_profile->sec.auth_type;
> -
> - IWM_DBG_WEXT(iwm, DBG, "auth_alg: 0x%x\n", auth_alg);
> -
> - switch (auth_alg) {
> - case IW_AUTH_ALG_OPEN_SYSTEM:
> - *auth_type = UMAC_AUTH_TYPE_OPEN;
> - break;
> - case IW_AUTH_ALG_SHARED_KEY:
> - if (iwm->umac_profile->sec.flags &
> - (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
> - if (*auth_type == UMAC_AUTH_TYPE_8021X)
> - return -EINVAL;
> - *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
> - } else {
> - IWM_DBG_WEXT(iwm, DBG, "WEP shared key\n");
> - *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
> - }
> - break;
> - case IW_AUTH_ALG_LEAP:
> - default:
> - IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", auth_alg);
> - return -ENOTSUPP;
> - }
> -
> - return 0;
> -}
> -
> -static int iwm_wext_siwauth(struct net_device *dev,
> - struct iw_request_info *info,
> - struct iw_param *data, char *extra)
> -{
> - struct iwm_priv *iwm = ndev_to_iwm(dev);
> - int ret;
> -
> - if ((data->flags) &
> - (IW_AUTH_WPA_VERSION | IW_AUTH_KEY_MGMT |
> - IW_AUTH_WPA_ENABLED | IW_AUTH_80211_AUTH_ALG)) {
> - /* We need to invalidate the current profile */
> - if (iwm->umac_profile_active) {
> - ret = iwm_invalidate_mlme_profile(iwm);
> - if (ret < 0) {
> - IWM_ERR(iwm, "Couldn't invalidate profile\n");
> - return ret;
> - }
> - }
> - }
> -
> - switch (data->flags & IW_AUTH_INDEX) {
> - case IW_AUTH_WPA_VERSION:
> - return iwm_set_wpa_version(iwm, data->value);
> - break;
> - case IW_AUTH_CIPHER_PAIRWISE:
> - return iwm_set_cipher(iwm, data->value, 1);
> - break;
> - case IW_AUTH_CIPHER_GROUP:
> - return iwm_set_cipher(iwm, data->value, 0);
> - break;
> - case IW_AUTH_KEY_MGMT:
> - return iwm_set_key_mgt(iwm, data->value);
> - break;
> - case IW_AUTH_80211_AUTH_ALG:
> - return iwm_set_auth_alg(iwm, data->value);
> - break;
> + case UMAC_MODE_BSS:
> + return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
> default:
> - return -ENOTSUPP;
> + return -EOPNOTSUPP;
> }
> -
> - return 0;
> -}
> -
> -static int iwm_wext_giwauth(struct net_device *dev,
> - struct iw_request_info *info,
> - struct iw_param *data, char *extra)
> -{
> - return 0;
> }
>
> static const iw_handler iwm_handlers[] =
> @@ -404,7 +154,7 @@ static const iw_handler iwm_handlers[] =
> (iw_handler) NULL, /* -- hole -- */
> (iw_handler) NULL, /* -- hole -- */
> (iw_handler) NULL, /* SIOCSIWRATE */
> - (iw_handler) iwm_wext_giwrate, /* SIOCGIWRATE */
> + (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */
> (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */
> (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
> (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
> @@ -419,10 +169,10 @@ static const iw_handler iwm_handlers[] =
> (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */
> (iw_handler) NULL, /* -- hole -- */
> (iw_handler) NULL, /* -- hole -- */
> - (iw_handler) NULL, /* SIOCSIWGENIE */
> + (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */
> (iw_handler) NULL, /* SIOCGIWGENIE */
> - (iw_handler) iwm_wext_siwauth, /* SIOCSIWAUTH */
> - (iw_handler) iwm_wext_giwauth, /* SIOCGIWAUTH */
> + (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */
> + (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */
> (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */
> (iw_handler) NULL, /* SIOCGIWENCODEEXT */
> (iw_handler) NULL, /* SIOCSIWPMKSA */
> @@ -432,6 +182,6 @@ static const iw_handler iwm_handlers[] =
> const struct iw_handler_def iwm_iw_handler_def = {
> .num_standard = ARRAY_SIZE(iwm_handlers),
> .standard = (iw_handler *) iwm_handlers,
> - .get_wireless_stats = iwm_get_wireless_stats,
> + .get_wireless_stats = cfg80211_wireless_stats,
> };
>
> Index: iwm-2.6/drivers/net/wireless/iwmc3200wifi/rx.c
> ===================================================================
> --- iwm-2.6.orig/drivers/net/wireless/iwmc3200wifi/rx.c 2009-07-02 21:19:58.000000000 +0200
> +++ iwm-2.6/drivers/net/wireless/iwmc3200wifi/rx.c 2009-07-03 00:24:46.000000000 +0200
> @@ -521,7 +521,10 @@ static int iwm_mlme_assoc_complete(struc
>
> iwm_link_on(iwm);
>
> - memcpy(wrqu.ap_addr.sa_data, complete->bssid, ETH_ALEN);
> + cfg80211_connect_result(iwm_to_ndev(iwm),
> + complete->bssid,
> + NULL, 0, NULL, 0,
> + WLAN_STATUS_SUCCESS, GFP_KERNEL);
> break;
> case UMAC_ASSOC_COMPLETE_FAILURE:
> clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
> @@ -529,6 +532,11 @@ static int iwm_mlme_assoc_complete(struc
> iwm->channel = 0;
>
> iwm_link_off(iwm);
> +
> + cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid,
> + NULL, 0, NULL, 0,
> + WLAN_STATUS_UNSPECIFIED_FAILURE,
> + GFP_KERNEL);
> default:
> break;
> }
> @@ -538,9 +546,6 @@ static int iwm_mlme_assoc_complete(struc
> return 0;
> }
>
> - wrqu.ap_addr.sa_family = ARPHRD_ETHER;
> - wireless_send_event(iwm_to_ndev(iwm), SIOCGIWAP, &wrqu, NULL);
> -
> return 0;
> }
>
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH] iwmc3200wifi: cfg80211 managed mode port
2009-07-03 8:02 ` Johannes Berg
@ 2009-07-03 13:10 ` Samuel Ortiz
0 siblings, 0 replies; 31+ messages in thread
From: Samuel Ortiz @ 2009-07-03 13:10 UTC (permalink / raw)
To: Johannes Berg; +Cc: Zhu, Yi, John Linville, linux-wireless@vger.kernel.org
On Fri, Jul 03, 2009 at 01:02:39AM -0700, Johannes Berg wrote:
> On Fri, 2009-07-03 at 01:55 +0200, Samuel Ortiz wrote:
> > This patch ports iwm to the new cfg80211 managed mode API.
> > Whenever those managed mode routines get combined with the ibss one, we will
> > just have to entirely get rid of the wext implementation (We may have to only
> > keep the iw_handler until cfg80211 does the wext registration for us).
>
> Looks good. I'll take care of the combine part later.
Thanks in advance.
Cheers,
Samuel.
> johannes
>
> > Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com>
> > ---
> > drivers/net/wireless/iwmc3200wifi/cfg80211.c | 195 ++++++++++++++++
> > drivers/net/wireless/iwmc3200wifi/rx.c | 13 -
> > drivers/net/wireless/iwmc3200wifi/wext.c | 320 ++-------------------------
> > 3 files changed, 239 insertions(+), 289 deletions(-)
> >
> > Index: iwm-2.6/drivers/net/wireless/iwmc3200wifi/cfg80211.c
> > ===================================================================
> > --- iwm-2.6.orig/drivers/net/wireless/iwmc3200wifi/cfg80211.c 2009-07-02 21:20:34.000000000 +0200
> > +++ iwm-2.6/drivers/net/wireless/iwmc3200wifi/cfg80211.c 2009-07-03 01:43:09.000000000 +0200
> > @@ -305,6 +305,25 @@ static int iwm_cfg80211_set_default_key(
> > return iwm_reset_profile(iwm);
> > }
> >
> > +int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
> > + u8 *mac, struct station_info *sinfo)
> > +{
> > + struct iwm_priv *iwm = ndev_to_iwm(ndev);
> > +
> > + if (memcmp(mac, iwm->bssid, ETH_ALEN))
> > + return -ENOENT;
> > +
> > + sinfo->filled |= STATION_INFO_TX_BITRATE;
> > + sinfo->txrate.legacy = iwm->rate * 10;
> > +
> > + if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
> > + sinfo->filled |= STATION_INFO_SIGNAL;
> > + sinfo->signal = iwm->wstats.qual.level;
> > + }
> > +
> > + return 0;
> > +}
> > +
> >
> > int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
> > {
> > @@ -500,6 +519,179 @@ static int iwm_cfg80211_leave_ibss(struc
> > return 0;
> > }
> >
> > +static int iwm_set_auth_type(struct iwm_priv *iwm,
> > + enum nl80211_auth_type sme_auth_type)
> > +{
> > + u8 *auth_type = &iwm->umac_profile->sec.auth_type;
> > +
> > + switch (sme_auth_type) {
> > + case NL80211_AUTHTYPE_AUTOMATIC:
> > + case NL80211_AUTHTYPE_OPEN_SYSTEM:
> > + IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
> > + *auth_type = UMAC_AUTH_TYPE_OPEN;
> > + break;
> > + case NL80211_AUTHTYPE_SHARED_KEY:
> > + if (iwm->umac_profile->sec.flags &
> > + (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
> > + IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
> > + *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
> > + } else {
> > + IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
> > + *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
> > + }
> > +
> > + break;
> > + default:
> > + IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
> > + return -ENOTSUPP;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
> > +{
> > + if (!wpa_version) {
> > + iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
> > + return 0;
> > + }
> > +
> > + if (wpa_version & NL80211_WPA_VERSION_2)
> > + iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
> > +
> > + if (wpa_version & NL80211_WPA_VERSION_1)
> > + iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK;
> > +
> > + return 0;
> > +}
> > +
> > +static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
> > +{
> > + u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
> > + &iwm->umac_profile->sec.mcast_cipher;
> > +
> > + if (!cipher) {
> > + *profile_cipher = UMAC_CIPHER_TYPE_NONE;
> > + return 0;
> > + }
> > +
> > + switch (cipher) {
> > + case IW_AUTH_CIPHER_NONE:
> > + *profile_cipher = UMAC_CIPHER_TYPE_NONE;
> > + break;
> > + case WLAN_CIPHER_SUITE_WEP40:
> > + *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
> > + break;
> > + case WLAN_CIPHER_SUITE_WEP104:
> > + *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
> > + break;
> > + case WLAN_CIPHER_SUITE_TKIP:
> > + *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
> > + break;
> > + case WLAN_CIPHER_SUITE_CCMP:
> > + *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
> > + break;
> > + default:
> > + IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
> > + return -ENOTSUPP;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
> > +{
> > + u8 *auth_type = &iwm->umac_profile->sec.auth_type;
> > +
> > + IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
> > +
> > + if (key_mgt == WLAN_AKM_SUITE_8021X)
> > + *auth_type = UMAC_AUTH_TYPE_8021X;
> > + else if (key_mgt == WLAN_AKM_SUITE_PSK) {
> > + if (iwm->umac_profile->sec.flags &
> > + (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
> > + *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
> > + else
> > + *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
> > + } else {
> > + IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
> > + return -EINVAL;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +
> > +static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
> > + struct cfg80211_connect_params *sme)
> > +{
> > + struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
> > + struct ieee80211_channel *chan = sme->channel;
> > + int ret;
> > +
> > + if (!test_bit(IWM_STATUS_READY, &iwm->status))
> > + return -EIO;
> > +
> > + if (!sme->ssid)
> > + return -EINVAL;
> > +
> > + if (chan)
> > + iwm->channel =
> > + ieee80211_frequency_to_channel(chan->center_freq);
> > +
> > + iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
> > + memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
> > +
> > + if (sme->bssid) {
> > + IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
> > + memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
> > + iwm->umac_profile->bss_num = 1;
> > + } else {
> > + memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
> > + iwm->umac_profile->bss_num = 0;
> > + }
> > +
> > + ret = iwm_set_auth_type(iwm, sme->auth_type);
> > + if (ret < 0)
> > + return ret;
> > +
> > + ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
> > + if (ret < 0)
> > + return ret;
> > +
> > + if (sme->crypto.n_ciphers_pairwise) {
> > + ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
> > + true);
> > + if (ret < 0)
> > + return ret;
> > + }
> > +
> > + ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
> > + if (ret < 0)
> > + return ret;
> > +
> > + if (sme->crypto.n_akm_suites) {
> > + ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
> > + if (ret < 0)
> > + return ret;
> > + }
> > +
> > + return iwm_send_mlme_profile(iwm);
> > +}
> > +
> > +static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
> > + u16 reason_code)
> > +{
> > + struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
> > +
> > + IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
> > +
> > + if (iwm->umac_profile_active)
> > + return iwm_invalidate_mlme_profile(iwm);
> > +
> > + return 0;
> > +}
> > +
> > static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
> > enum tx_power_setting type, int dbm)
> > {
> > @@ -549,8 +741,11 @@ static struct cfg80211_ops iwm_cfg80211_
> > .get_key = iwm_cfg80211_get_key,
> > .del_key = iwm_cfg80211_del_key,
> > .set_default_key = iwm_cfg80211_set_default_key,
> > + .get_station = iwm_cfg80211_get_station,
> > .scan = iwm_cfg80211_scan,
> > .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
> > + .connect = iwm_cfg80211_connect,
> > + .disconnect = iwm_cfg80211_disconnect,
> > .join_ibss = iwm_cfg80211_join_ibss,
> > .leave_ibss = iwm_cfg80211_leave_ibss,
> > .set_tx_power = iwm_cfg80211_set_txpower,
> > Index: iwm-2.6/drivers/net/wireless/iwmc3200wifi/wext.c
> > ===================================================================
> > --- iwm-2.6.orig/drivers/net/wireless/iwmc3200wifi/wext.c 2009-07-02 21:20:34.000000000 +0200
> > +++ iwm-2.6/drivers/net/wireless/iwmc3200wifi/wext.c 2009-07-03 01:18:56.000000000 +0200
> > @@ -21,31 +21,11 @@
> > *
> > */
> >
> > -#include <linux/kernel.h>
> > -#include <linux/netdevice.h>
> > #include <linux/wireless.h>
> > -#include <linux/if_arp.h>
> > -#include <linux/etherdevice.h>
> > #include <net/cfg80211.h>
> > -#include <net/iw_handler.h>
> >
> > #include "iwm.h"
> > -#include "umac.h"
> > #include "commands.h"
> > -#include "debug.h"
> > -
> > -static struct iw_statistics *iwm_get_wireless_stats(struct net_device *dev)
> > -{
> > - struct iwm_priv *iwm = ndev_to_iwm(dev);
> > - struct iw_statistics *wstats = &iwm->wstats;
> > -
> > - if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
> > - memset(wstats, 0, sizeof(struct iw_statistics));
> > - wstats->qual.updated = IW_QUAL_ALL_INVALID;
> > - }
> > -
> > - return wstats;
> > -}
> >
> > static int iwm_wext_siwfreq(struct net_device *dev,
> > struct iw_request_info *info,
> > @@ -53,14 +33,12 @@ static int iwm_wext_siwfreq(struct net_d
> > {
> > struct iwm_priv *iwm = ndev_to_iwm(dev);
> >
> > - if (freq->flags == IW_FREQ_AUTO)
> > - return 0;
> > -
> > - /* frequency/channel can only be set in IBSS mode */
> > - if (iwm->conf.mode != UMAC_MODE_IBSS)
> > + switch (iwm->conf.mode) {
> > + case UMAC_MODE_IBSS:
> > + return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
> > + default:
> > return -EOPNOTSUPP;
> > -
> > - return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
> > + }
> > }
> >
> > static int iwm_wext_giwfreq(struct net_device *dev,
> > @@ -69,69 +47,29 @@ static int iwm_wext_giwfreq(struct net_d
> > {
> > struct iwm_priv *iwm = ndev_to_iwm(dev);
> >
> > - if (iwm->conf.mode == UMAC_MODE_IBSS)
> > + switch (iwm->conf.mode) {
> > + case UMAC_MODE_IBSS:
> > return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
> > -
> > - freq->e = 0;
> > - freq->m = iwm->channel;
> > -
> > - return 0;
> > + case UMAC_MODE_BSS:
> > + return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
> > + default:
> > + return -EOPNOTSUPP;
> > + }
> > }
> >
> > static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info,
> > struct sockaddr *ap_addr, char *extra)
> > {
> > struct iwm_priv *iwm = ndev_to_iwm(dev);
> > - int ret;
> > -
> > - IWM_DBG_WEXT(iwm, DBG, "Set BSSID: %pM\n", ap_addr->sa_data);
> >
> > - if (iwm->conf.mode == UMAC_MODE_IBSS)
> > + switch (iwm->conf.mode) {
> > + case UMAC_MODE_IBSS:
> > return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
> > -
> > - if (!test_bit(IWM_STATUS_READY, &iwm->status))
> > - return -EIO;
> > -
> > - if (is_zero_ether_addr(ap_addr->sa_data) ||
> > - is_broadcast_ether_addr(ap_addr->sa_data)) {
> > - IWM_DBG_WEXT(iwm, DBG, "clear mandatory bssid %pM\n",
> > - iwm->umac_profile->bssid[0]);
> > - memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
> > - iwm->umac_profile->bss_num = 0;
> > - } else {
> > - IWM_DBG_WEXT(iwm, DBG, "add mandatory bssid %pM\n",
> > - ap_addr->sa_data);
> > - memcpy(&iwm->umac_profile->bssid[0], ap_addr->sa_data,
> > - ETH_ALEN);
> > - iwm->umac_profile->bss_num = 1;
> > - }
> > -
> > - if (iwm->umac_profile_active) {
> > - int i;
> > -
> > - if (!memcmp(&iwm->umac_profile->bssid[0], iwm->bssid, ETH_ALEN))
> > - return 0;
> > -
> > - /*
> > - * If we're clearing the BSSID, and we're associated,
> > - * we have to clear the keys as they're no longer valid.
> > - */
> > - if (is_zero_ether_addr(ap_addr->sa_data)) {
> > - for (i = 0; i < IWM_NUM_KEYS; i++)
> > - iwm->keys[i].key_len = 0;
> > - }
> > -
> > - ret = iwm_invalidate_mlme_profile(iwm);
> > - if (ret < 0) {
> > - IWM_ERR(iwm, "Couldn't invalidate profile\n");
> > - return ret;
> > - }
> > + case UMAC_MODE_BSS:
> > + return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
> > + default:
> > + return -EOPNOTSUPP;
> > }
> > -
> > - if (iwm->umac_profile->ssid.ssid_len)
> > - return iwm_send_mlme_profile(iwm);
> > -
> > - return 0;
> > }
> >
> > static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info,
> > @@ -143,17 +81,10 @@ static int iwm_wext_giwap(struct net_dev
> > case UMAC_MODE_IBSS:
> > return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
> > case UMAC_MODE_BSS:
> > - if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
> > - ap_addr->sa_family = ARPHRD_ETHER;
> > - memcpy(&ap_addr->sa_data, iwm->bssid, ETH_ALEN);
> > - } else
> > - memset(&ap_addr->sa_data, 0, ETH_ALEN);
> > - break;
> > + return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
> > default:
> > return -EOPNOTSUPP;
> > }
> > -
> > - return 0;
> > }
> >
> > static int iwm_wext_siwessid(struct net_device *dev,
> > @@ -161,36 +92,15 @@ static int iwm_wext_siwessid(struct net_
> > struct iw_point *data, char *ssid)
> > {
> > struct iwm_priv *iwm = ndev_to_iwm(dev);
> > - size_t len = data->length;
> > - int ret;
> > -
> > - IWM_DBG_WEXT(iwm, DBG, "Set ESSID: >%s<\n", ssid);
> >
> > - if (iwm->conf.mode == UMAC_MODE_IBSS)
> > + switch (iwm->conf.mode) {
> > + case UMAC_MODE_IBSS:
> > return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
> > -
> > - if (!test_bit(IWM_STATUS_READY, &iwm->status))
> > - return -EIO;
> > -
> > - if (len > 0 && ssid[len - 1] == '\0')
> > - len--;
> > -
> > - if (iwm->umac_profile_active) {
> > - if (iwm->umac_profile->ssid.ssid_len == len &&
> > - !memcmp(iwm->umac_profile->ssid.ssid, ssid, len))
> > - return 0;
> > -
> > - ret = iwm_invalidate_mlme_profile(iwm);
> > - if (ret < 0) {
> > - IWM_ERR(iwm, "Couldn't invalidate profile\n");
> > - return ret;
> > - }
> > + case UMAC_MODE_BSS:
> > + return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
> > + default:
> > + return -EOPNOTSUPP;
> > }
> > -
> > - iwm->umac_profile->ssid.ssid_len = len;
> > - memcpy(iwm->umac_profile->ssid.ssid, ssid, len);
> > -
> > - return iwm_send_mlme_profile(iwm);
> > }
> >
> > static int iwm_wext_giwessid(struct net_device *dev,
> > @@ -199,174 +109,14 @@ static int iwm_wext_giwessid(struct net_
> > {
> > struct iwm_priv *iwm = ndev_to_iwm(dev);
> >
> > - if (iwm->conf.mode == UMAC_MODE_IBSS)
> > + switch (iwm->conf.mode) {
> > + case UMAC_MODE_IBSS:
> > return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
> > -
> > - if (!test_bit(IWM_STATUS_READY, &iwm->status))
> > - return -EIO;
> > -
> > - data->length = iwm->umac_profile->ssid.ssid_len;
> > - if (data->length) {
> > - memcpy(ssid, iwm->umac_profile->ssid.ssid, data->length);
> > - data->flags = 1;
> > - } else
> > - data->flags = 0;
> > -
> > - return 0;
> > -}
> > -
> > -static int iwm_wext_giwrate(struct net_device *dev,
> > - struct iw_request_info *info,
> > - struct iw_param *rate, char *extra)
> > -{
> > - struct iwm_priv *iwm = ndev_to_iwm(dev);
> > -
> > - rate->value = iwm->rate * 1000000;
> > -
> > - return 0;
> > -}
> > -
> > -static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version)
> > -{
> > - if (wpa_version & IW_AUTH_WPA_VERSION_WPA2)
> > - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
> > - else if (wpa_version & IW_AUTH_WPA_VERSION_WPA)
> > - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
> > - else
> > - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
> > -
> > - return 0;
> > -}
> > -
> > -static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt)
> > -{
> > - u8 *auth_type = &iwm->umac_profile->sec.auth_type;
> > -
> > - IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
> > -
> > - if (key_mgt == IW_AUTH_KEY_MGMT_802_1X)
> > - *auth_type = UMAC_AUTH_TYPE_8021X;
> > - else if (key_mgt == IW_AUTH_KEY_MGMT_PSK) {
> > - if (iwm->umac_profile->sec.flags &
> > - (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
> > - *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
> > - else
> > - *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
> > - } else {
> > - IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
> > - return -EINVAL;
> > - }
> > -
> > - return 0;
> > -}
> > -
> > -static int iwm_set_cipher(struct iwm_priv *iwm, u8 cipher, u8 ucast)
> > -{
> > - u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
> > - &iwm->umac_profile->sec.mcast_cipher;
> > -
> > - switch (cipher) {
> > - case IW_AUTH_CIPHER_NONE:
> > - *profile_cipher = UMAC_CIPHER_TYPE_NONE;
> > - break;
> > - case IW_AUTH_CIPHER_WEP40:
> > - *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
> > - break;
> > - case IW_AUTH_CIPHER_TKIP:
> > - *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
> > - break;
> > - case IW_AUTH_CIPHER_CCMP:
> > - *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
> > - break;
> > - case IW_AUTH_CIPHER_WEP104:
> > - *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
> > - break;
> > - default:
> > - IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
> > - return -ENOTSUPP;
> > - }
> > -
> > - return 0;
> > -}
> > -
> > -static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg)
> > -{
> > - u8 *auth_type = &iwm->umac_profile->sec.auth_type;
> > -
> > - IWM_DBG_WEXT(iwm, DBG, "auth_alg: 0x%x\n", auth_alg);
> > -
> > - switch (auth_alg) {
> > - case IW_AUTH_ALG_OPEN_SYSTEM:
> > - *auth_type = UMAC_AUTH_TYPE_OPEN;
> > - break;
> > - case IW_AUTH_ALG_SHARED_KEY:
> > - if (iwm->umac_profile->sec.flags &
> > - (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
> > - if (*auth_type == UMAC_AUTH_TYPE_8021X)
> > - return -EINVAL;
> > - *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
> > - } else {
> > - IWM_DBG_WEXT(iwm, DBG, "WEP shared key\n");
> > - *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
> > - }
> > - break;
> > - case IW_AUTH_ALG_LEAP:
> > - default:
> > - IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", auth_alg);
> > - return -ENOTSUPP;
> > - }
> > -
> > - return 0;
> > -}
> > -
> > -static int iwm_wext_siwauth(struct net_device *dev,
> > - struct iw_request_info *info,
> > - struct iw_param *data, char *extra)
> > -{
> > - struct iwm_priv *iwm = ndev_to_iwm(dev);
> > - int ret;
> > -
> > - if ((data->flags) &
> > - (IW_AUTH_WPA_VERSION | IW_AUTH_KEY_MGMT |
> > - IW_AUTH_WPA_ENABLED | IW_AUTH_80211_AUTH_ALG)) {
> > - /* We need to invalidate the current profile */
> > - if (iwm->umac_profile_active) {
> > - ret = iwm_invalidate_mlme_profile(iwm);
> > - if (ret < 0) {
> > - IWM_ERR(iwm, "Couldn't invalidate profile\n");
> > - return ret;
> > - }
> > - }
> > - }
> > -
> > - switch (data->flags & IW_AUTH_INDEX) {
> > - case IW_AUTH_WPA_VERSION:
> > - return iwm_set_wpa_version(iwm, data->value);
> > - break;
> > - case IW_AUTH_CIPHER_PAIRWISE:
> > - return iwm_set_cipher(iwm, data->value, 1);
> > - break;
> > - case IW_AUTH_CIPHER_GROUP:
> > - return iwm_set_cipher(iwm, data->value, 0);
> > - break;
> > - case IW_AUTH_KEY_MGMT:
> > - return iwm_set_key_mgt(iwm, data->value);
> > - break;
> > - case IW_AUTH_80211_AUTH_ALG:
> > - return iwm_set_auth_alg(iwm, data->value);
> > - break;
> > + case UMAC_MODE_BSS:
> > + return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
> > default:
> > - return -ENOTSUPP;
> > + return -EOPNOTSUPP;
> > }
> > -
> > - return 0;
> > -}
> > -
> > -static int iwm_wext_giwauth(struct net_device *dev,
> > - struct iw_request_info *info,
> > - struct iw_param *data, char *extra)
> > -{
> > - return 0;
> > }
> >
> > static const iw_handler iwm_handlers[] =
> > @@ -404,7 +154,7 @@ static const iw_handler iwm_handlers[] =
> > (iw_handler) NULL, /* -- hole -- */
> > (iw_handler) NULL, /* -- hole -- */
> > (iw_handler) NULL, /* SIOCSIWRATE */
> > - (iw_handler) iwm_wext_giwrate, /* SIOCGIWRATE */
> > + (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */
> > (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */
> > (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
> > (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
> > @@ -419,10 +169,10 @@ static const iw_handler iwm_handlers[] =
> > (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */
> > (iw_handler) NULL, /* -- hole -- */
> > (iw_handler) NULL, /* -- hole -- */
> > - (iw_handler) NULL, /* SIOCSIWGENIE */
> > + (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */
> > (iw_handler) NULL, /* SIOCGIWGENIE */
> > - (iw_handler) iwm_wext_siwauth, /* SIOCSIWAUTH */
> > - (iw_handler) iwm_wext_giwauth, /* SIOCGIWAUTH */
> > + (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */
> > + (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */
> > (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */
> > (iw_handler) NULL, /* SIOCGIWENCODEEXT */
> > (iw_handler) NULL, /* SIOCSIWPMKSA */
> > @@ -432,6 +182,6 @@ static const iw_handler iwm_handlers[] =
> > const struct iw_handler_def iwm_iw_handler_def = {
> > .num_standard = ARRAY_SIZE(iwm_handlers),
> > .standard = (iw_handler *) iwm_handlers,
> > - .get_wireless_stats = iwm_get_wireless_stats,
> > + .get_wireless_stats = cfg80211_wireless_stats,
> > };
> >
> > Index: iwm-2.6/drivers/net/wireless/iwmc3200wifi/rx.c
> > ===================================================================
> > --- iwm-2.6.orig/drivers/net/wireless/iwmc3200wifi/rx.c 2009-07-02 21:19:58.000000000 +0200
> > +++ iwm-2.6/drivers/net/wireless/iwmc3200wifi/rx.c 2009-07-03 00:24:46.000000000 +0200
> > @@ -521,7 +521,10 @@ static int iwm_mlme_assoc_complete(struc
> >
> > iwm_link_on(iwm);
> >
> > - memcpy(wrqu.ap_addr.sa_data, complete->bssid, ETH_ALEN);
> > + cfg80211_connect_result(iwm_to_ndev(iwm),
> > + complete->bssid,
> > + NULL, 0, NULL, 0,
> > + WLAN_STATUS_SUCCESS, GFP_KERNEL);
> > break;
> > case UMAC_ASSOC_COMPLETE_FAILURE:
> > clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
> > @@ -529,6 +532,11 @@ static int iwm_mlme_assoc_complete(struc
> > iwm->channel = 0;
> >
> > iwm_link_off(iwm);
> > +
> > + cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid,
> > + NULL, 0, NULL, 0,
> > + WLAN_STATUS_UNSPECIFIED_FAILURE,
> > + GFP_KERNEL);
> > default:
> > break;
> > }
> > @@ -538,9 +546,6 @@ static int iwm_mlme_assoc_complete(struc
> > return 0;
> > }
> >
> > - wrqu.ap_addr.sa_family = ARPHRD_ETHER;
> > - wireless_send_event(iwm_to_ndev(iwm), SIOCGIWAP, &wrqu, NULL);
> > -
> > return 0;
> > }
> >
--
Intel Open Source Technology Centre
http://oss.intel.com/
---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris,
92196 Meudon Cedex, France
Registration Number: 302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] iwmc3200wifi: cfg80211 managed mode port
2009-07-02 23:55 ` [PATCH] iwmc3200wifi: cfg80211 managed mode port Samuel Ortiz
2009-07-03 8:02 ` Johannes Berg
@ 2009-07-05 1:37 ` Johannes Berg
1 sibling, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-05 1:37 UTC (permalink / raw)
To: Samuel Ortiz; +Cc: Zhu, Yi, John Linville, linux-wireless@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 198 bytes --]
On Fri, 2009-07-03 at 01:55 +0200, Samuel Ortiz wrote:
> @@ -521,7 +521,10 @@ static int iwm_mlme_assoc_complete(struc
- union iwreq_data wrqu;
- memset(&wrqu, 0, sizeof(wrqu));
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH] cfg80211: check for current_bss from giwrate
2009-07-01 19:26 ` [PATCH 15/20 v4] cfg80211: managed mode wext compatibility Johannes Berg
2009-07-02 23:55 ` [PATCH] iwmc3200wifi: cfg80211 managed mode port Samuel Ortiz
@ 2009-07-03 0:00 ` Samuel Ortiz
2009-07-03 8:01 ` Johannes Berg
1 sibling, 1 reply; 31+ messages in thread
From: Samuel Ortiz @ 2009-07-03 0:00 UTC (permalink / raw)
To: Johannes Berg; +Cc: John Linville, linux-wireless@vger.kernel.org
When connecting to an ESSID manually, we may not set the BSSID, and thus
wdev->wext.connect.bssid will be NULL.
wdev->current_bss is always updated when a connection is established so we
should check it first.
Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com>
---
net/wireless/wext-compat.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
Index: iwm-2.6/net/wireless/wext-compat.c
===================================================================
--- iwm-2.6.orig/net/wireless/wext-compat.c 2009-07-03 01:40:09.000000000 +0200
+++ iwm-2.6/net/wireless/wext-compat.c 2009-07-03 01:40:18.000000000 +0200
@@ -1137,8 +1137,11 @@ int cfg80211_wext_giwrate(struct net_dev
if (!rdev->ops->get_station)
return -EOPNOTSUPP;
- addr = wdev->wext.connect.bssid;
- if (!addr)
+ if (wdev->current_bss)
+ addr = wdev->current_bss->bssid;
+ else if (wdev->wext.connect.bssid)
+ addr = wdev->wext.connect.bssid;
+ else
return -ENOTSUPP;
err = rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo);
--
Intel Open Source Technology Centre
http://oss.intel.com/
---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris,
92196 Meudon Cedex, France
Registration Number: 302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] cfg80211: check for current_bss from giwrate
2009-07-03 0:00 ` [PATCH] cfg80211: check for current_bss from giwrate Samuel Ortiz
@ 2009-07-03 8:01 ` Johannes Berg
0 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-03 8:01 UTC (permalink / raw)
To: Samuel Ortiz; +Cc: John Linville, linux-wireless@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 1238 bytes --]
On Fri, 2009-07-03 at 02:00 +0200, Samuel Ortiz wrote:
> When connecting to an ESSID manually, we may not set the BSSID, and thus
> wdev->wext.connect.bssid will be NULL.
> wdev->current_bss is always updated when a connection is established so we
> should check it first.
Indeed, good catch
Acked-by: Johannes Berg <johannes@sipsolutions.net>
> Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com>
> ---
> net/wireless/wext-compat.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> Index: iwm-2.6/net/wireless/wext-compat.c
> ===================================================================
> --- iwm-2.6.orig/net/wireless/wext-compat.c 2009-07-03 01:40:09.000000000 +0200
> +++ iwm-2.6/net/wireless/wext-compat.c 2009-07-03 01:40:18.000000000 +0200
> @@ -1137,8 +1137,11 @@ int cfg80211_wext_giwrate(struct net_dev
> if (!rdev->ops->get_station)
> return -EOPNOTSUPP;
>
> - addr = wdev->wext.connect.bssid;
> - if (!addr)
> + if (wdev->current_bss)
> + addr = wdev->current_bss->bssid;
> + else if (wdev->wext.connect.bssid)
> + addr = wdev->wext.connect.bssid;
> + else
> return -ENOTSUPP;
>
> err = rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo);
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 16/20 v4] cfg80211: implement iwpower
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (14 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 15/20 v4] cfg80211: managed mode wext compatibility Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 17/20 v4] cfg80211: implement IWAP for WDS Johannes Berg
` (6 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
Just on/off and timeout, and with a hacky cfg80211 method
until we figure out what we want, though this is probably
sufficient as we want to use pm_qos for wifi everywhere.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
drivers/net/wireless/iwmc3200wifi/cfg80211.c | 22 ++++++++
drivers/net/wireless/iwmc3200wifi/wext.c | 47 ------------------
include/net/cfg80211.h | 13 +++++
net/mac80211/Kconfig | 16 ------
net/mac80211/cfg.c | 26 ++++++++++
net/mac80211/mlme.c | 5 -
net/mac80211/wext.c | 70 ---------------------------
net/wireless/Kconfig | 16 ++++++
net/wireless/core.c | 11 +++-
net/wireless/wext-compat.c | 60 +++++++++++++++++++++++
10 files changed, 151 insertions(+), 135 deletions(-)
--- wireless-testing.orig/include/net/cfg80211.h 2009-07-01 19:57:56.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h 2009-07-01 20:29:35.000000000 +0200
@@ -1023,6 +1023,10 @@ struct cfg80211_ops {
#ifdef CONFIG_NL80211_TESTMODE
int (*testmode_cmd)(struct wiphy *wiphy, void *data, int len);
#endif
+
+ /* some temporary stuff to finish wext */
+ int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
+ bool enabled, int timeout);
};
/*
@@ -1262,6 +1266,8 @@ struct wireless_dev {
u8 bssid[ETH_ALEN];
u8 ssid[IEEE80211_MAX_SSID_LEN];
s8 default_key, default_mgmt_key;
+ bool ps;
+ int ps_timeout;
} wext;
#endif
};
@@ -1606,6 +1612,13 @@ int cfg80211_wext_giwtxpower(struct net_
struct iw_request_info *info,
union iwreq_data *data, char *keybuf);
+int cfg80211_wext_siwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *wrq, char *extra);
+int cfg80211_wext_giwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *wrq, char *extra);
+
/*
* callbacks for asynchronous cfg80211 methods, notification
* functions and BSS handling helpers
--- wireless-testing.orig/net/mac80211/Kconfig 2009-07-01 19:31:59.000000000 +0200
+++ wireless-testing/net/mac80211/Kconfig 2009-07-01 20:29:35.000000000 +0200
@@ -14,22 +14,6 @@ config MAC80211
comment "CFG80211 needs to be enabled for MAC80211"
depends on CFG80211=n
-config MAC80211_DEFAULT_PS
- bool "enable powersave by default"
- depends on MAC80211
- default y
- help
- This option enables powersave mode by default.
-
- If this causes your applications to misbehave you should fix your
- applications instead -- they need to register their network
- latency requirement, see Documentation/power/pm_qos_interface.txt.
-
-config MAC80211_DEFAULT_PS_VALUE
- int
- default 1 if MAC80211_DEFAULT_PS
- default 0
-
menu "Rate control algorithm selection"
depends on MAC80211 != n
--- wireless-testing.orig/net/mac80211/wext.c 2009-07-01 19:57:56.000000000 +0200
+++ wireless-testing/net/mac80211/wext.c 2009-07-01 20:29:35.000000000 +0200
@@ -255,72 +255,6 @@ static int ieee80211_ioctl_giwrate(struc
return 0;
}
-static int ieee80211_ioctl_siwpower(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *wrq,
- char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_conf *conf = &local->hw.conf;
- int timeout = 0;
- bool ps;
-
- if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
- return -EOPNOTSUPP;
-
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- return -EINVAL;
-
- if (wrq->disabled) {
- ps = false;
- timeout = 0;
- goto set;
- }
-
- switch (wrq->flags & IW_POWER_MODE) {
- case IW_POWER_ON: /* If not specified */
- case IW_POWER_MODE: /* If set all mask */
- case IW_POWER_ALL_R: /* If explicitely state all */
- ps = true;
- break;
- default: /* Otherwise we ignore */
- return -EINVAL;
- }
-
- if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
- return -EINVAL;
-
- if (wrq->flags & IW_POWER_TIMEOUT)
- timeout = wrq->value / 1000;
-
- set:
- if (ps == sdata->u.mgd.powersave && timeout == conf->dynamic_ps_timeout)
- return 0;
-
- sdata->u.mgd.powersave = ps;
- conf->dynamic_ps_timeout = timeout;
-
- if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
-
- ieee80211_recalc_ps(local, -1);
-
- return 0;
-}
-
-static int ieee80211_ioctl_giwpower(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu,
- char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- wrqu->power.disabled = !sdata->u.mgd.powersave;
-
- return 0;
-}
-
/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
{
@@ -436,8 +370,8 @@ static const iw_handler ieee80211_handle
(iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */
(iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */
(iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */
- (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */
- (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */
+ (iw_handler) cfg80211_wext_siwpower, /* SIOCSIWPOWER */
+ (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */
--- wireless-testing.orig/net/wireless/Kconfig 2009-07-01 19:31:59.000000000 +0200
+++ wireless-testing/net/wireless/Kconfig 2009-07-01 20:29:35.000000000 +0200
@@ -26,6 +26,22 @@ config CFG80211_REG_DEBUG
If unsure, say N.
+config CFG80211_DEFAULT_PS
+ bool "enable powersave by default"
+ depends on CFG80211
+ default y
+ help
+ This option enables powersave mode by default.
+
+ If this causes your applications to misbehave you should fix your
+ applications instead -- they need to register their network
+ latency requirement, see Documentation/power/pm_qos_interface.txt.
+
+config CFG80211_DEFAULT_PS_VALUE
+ int
+ default 1 if CFG80211_DEFAULT_PS
+ default 0
+
config CFG80211_DEBUGFS
bool "cfg80211 DebugFS entries"
depends on CFG80211 && DEBUG_FS
--- wireless-testing.orig/net/wireless/core.c 2009-07-01 19:57:56.000000000 +0200
+++ wireless-testing/net/wireless/core.c 2009-07-01 20:29:35.000000000 +0200
@@ -550,12 +550,21 @@ static int cfg80211_netdev_notifier_call
}
wdev->netdev = dev;
wdev->sme_state = CFG80211_SME_IDLE;
+ mutex_unlock(&rdev->devlist_mtx);
#ifdef CONFIG_WIRELESS_EXT
wdev->wext.default_key = -1;
wdev->wext.default_mgmt_key = -1;
wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
+ wdev->wext.ps = CONFIG_CFG80211_DEFAULT_PS_VALUE;
+ wdev->wext.ps_timeout = 500;
+ if (rdev->ops->set_power_mgmt)
+ if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
+ wdev->wext.ps,
+ wdev->wext.ps_timeout)) {
+ /* assume this means it's off */
+ wdev->wext.ps = false;
+ }
#endif
- mutex_unlock(&rdev->devlist_mtx);
break;
case NETDEV_GOING_DOWN:
if (!wdev->ssid_len)
--- wireless-testing.orig/net/wireless/wext-compat.c 2009-07-01 19:57:56.000000000 +0200
+++ wireless-testing/net/wireless/wext-compat.c 2009-07-01 20:29:35.000000000 +0200
@@ -988,3 +988,63 @@ int cfg80211_wext_giwauth(struct net_dev
return -EOPNOTSUPP;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth);
+
+int cfg80211_wext_siwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *wrq, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ bool ps = wdev->wext.ps;
+ int timeout = wdev->wext.ps_timeout;
+ int err;
+
+ if (wdev->iftype != NL80211_IFTYPE_STATION)
+ return -EINVAL;
+
+ if (!rdev->ops->set_power_mgmt)
+ return -EOPNOTSUPP;
+
+ if (wrq->disabled) {
+ ps = false;
+ } else {
+ switch (wrq->flags & IW_POWER_MODE) {
+ case IW_POWER_ON: /* If not specified */
+ case IW_POWER_MODE: /* If set all mask */
+ case IW_POWER_ALL_R: /* If explicitely state all */
+ ps = true;
+ break;
+ default: /* Otherwise we ignore */
+ return -EINVAL;
+ }
+
+ if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
+ return -EINVAL;
+
+ if (wrq->flags & IW_POWER_TIMEOUT)
+ timeout = wrq->value / 1000;
+ }
+
+ err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, ps, timeout);
+ if (err)
+ return err;
+
+ wdev->wext.ps = ps;
+ wdev->wext.ps_timeout = timeout;
+
+ return 0;
+
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwpower);
+
+int cfg80211_wext_giwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *wrq, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ wrq->disabled = !wdev->wext.ps;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower);
--- wireless-testing.orig/net/mac80211/cfg.c 2009-07-01 19:31:59.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c 2009-07-01 20:29:35.000000000 +0200
@@ -1388,6 +1388,31 @@ int ieee80211_testmode_cmd(struct wiphy
}
#endif
+static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+ bool enabled, int timeout)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_conf *conf = &local->hw.conf;
+
+ if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
+ return -EOPNOTSUPP;
+
+ if (enabled == sdata->u.mgd.powersave &&
+ timeout == conf->dynamic_ps_timeout)
+ return 0;
+
+ sdata->u.mgd.powersave = enabled;
+ conf->dynamic_ps_timeout = timeout;
+
+ if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+
+ ieee80211_recalc_ps(local, -1);
+
+ return 0;
+}
+
struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -1431,4 +1456,5 @@ struct cfg80211_ops mac80211_config_ops
.get_tx_power = ieee80211_get_tx_power,
.rfkill_poll = ieee80211_rfkill_poll,
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
+ .set_power_mgmt = ieee80211_set_power_mgmt,
};
--- wireless-testing.orig/net/mac80211/mlme.c 2009-07-01 19:57:56.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c 2009-07-01 20:29:35.000000000 +0200
@@ -2360,11 +2360,6 @@ void ieee80211_sta_setup_sdata(struct ie
ifmgd->flags |= IEEE80211_STA_WMM_ENABLED;
hw_flags = sdata->local->hw.flags;
-
- if (hw_flags & IEEE80211_HW_SUPPORTS_PS) {
- ifmgd->powersave = CONFIG_MAC80211_DEFAULT_PS_VALUE;
- sdata->local->hw.conf.dynamic_ps_timeout = 500;
- }
}
/* configuration hooks */
--- wireless-testing.orig/drivers/net/wireless/iwmc3200wifi/cfg80211.c 2009-07-01 19:31:59.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwmc3200wifi/cfg80211.c 2009-07-01 20:29:35.000000000 +0200
@@ -522,6 +522,27 @@ static int iwm_cfg80211_get_txpower(stru
return 0;
}
+static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+ struct net_device *dev,
+ bool enabled, int timeout)
+{
+ struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+ u32 power_index;
+
+ if (enabled)
+ power_index = IWM_POWER_INDEX_DEFAULT;
+ else
+ power_index = IWM_POWER_INDEX_MIN;
+
+ if (power_index == iwm->conf.power_index)
+ return 0;
+
+ iwm->conf.power_index = power_index;
+
+ return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+ CFG_POWER_INDEX, iwm->conf.power_index);
+}
+
static struct cfg80211_ops iwm_cfg80211_ops = {
.change_virtual_intf = iwm_cfg80211_change_iface,
.add_key = iwm_cfg80211_add_key,
@@ -534,6 +555,7 @@ static struct cfg80211_ops iwm_cfg80211_
.leave_ibss = iwm_cfg80211_leave_ibss,
.set_tx_power = iwm_cfg80211_set_txpower,
.get_tx_power = iwm_cfg80211_get_txpower,
+ .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
};
struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
--- wireless-testing.orig/drivers/net/wireless/iwmc3200wifi/wext.c 2009-07-01 19:31:59.000000000 +0200
+++ wireless-testing/drivers/net/wireless/iwmc3200wifi/wext.c 2009-07-01 20:29:35.000000000 +0200
@@ -238,49 +238,6 @@ static int iwm_set_wpa_version(struct iw
return 0;
}
-static int iwm_wext_siwpower(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *wrq, char *extra)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
- u32 power_index;
-
- if (wrq->disabled) {
- power_index = IWM_POWER_INDEX_MIN;
- goto set;
- } else
- power_index = IWM_POWER_INDEX_DEFAULT;
-
- switch (wrq->flags & IW_POWER_MODE) {
- case IW_POWER_ON:
- case IW_POWER_MODE:
- case IW_POWER_ALL_R:
- break;
- default:
- return -EINVAL;
- }
-
- set:
- if (power_index == iwm->conf.power_index)
- return 0;
-
- iwm->conf.power_index = power_index;
-
- return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_POWER_INDEX, iwm->conf.power_index);
-}
-
-static int iwm_wext_giwpower(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
-
- wrqu->power.disabled = (iwm->conf.power_index == IWM_POWER_INDEX_MIN);
-
- return 0;
-}
-
static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt)
{
u8 *auth_type = &iwm->umac_profile->sec.auth_type;
@@ -458,8 +415,8 @@ static const iw_handler iwm_handlers[] =
(iw_handler) NULL, /* SIOCGIWRETRY */
(iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */
(iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */
- (iw_handler) iwm_wext_siwpower, /* SIOCSIWPOWER */
- (iw_handler) iwm_wext_giwpower, /* SIOCGIWPOWER */
+ (iw_handler) cfg80211_wext_siwpower, /* SIOCSIWPOWER */
+ (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* SIOCSIWGENIE */
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 17/20 v4] cfg80211: implement IWAP for WDS
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (15 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 16/20 v4] cfg80211: implement iwpower Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:26 ` [PATCH 18/20 v4] cfg80211: implement IWRATE Johannes Berg
` (5 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
This implements siocsiwap/giwap for WDS mode.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/net/cfg80211.h | 10 +++++++++
net/mac80211/cfg.c | 11 ++++++++++
net/mac80211/wext.c | 26 +++----------------------
net/wireless/wext-compat.c | 46 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 71 insertions(+), 22 deletions(-)
--- wireless-testing.orig/include/net/cfg80211.h 2009-07-01 20:29:35.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h 2009-07-01 20:29:40.000000000 +0200
@@ -1018,6 +1018,9 @@ struct cfg80211_ops {
enum tx_power_setting type, int dbm);
int (*get_tx_power)(struct wiphy *wiphy, int *dbm);
+ int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *addr);
+
void (*rfkill_poll)(struct wiphy *wiphy);
#ifdef CONFIG_NL80211_TESTMODE
@@ -1619,6 +1622,13 @@ int cfg80211_wext_giwpower(struct net_de
struct iw_request_info *info,
struct iw_param *wrq, char *extra);
+int cfg80211_wds_wext_siwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *addr, char *extra);
+int cfg80211_wds_wext_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *addr, char *extra);
+
/*
* callbacks for asynchronous cfg80211 methods, notification
* functions and BSS handling helpers
--- wireless-testing.orig/net/mac80211/wext.c 2009-07-01 20:29:35.000000000 +0200
+++ wireless-testing/net/mac80211/wext.c 2009-07-01 20:29:40.000000000 +0200
@@ -140,23 +140,8 @@ static int ieee80211_ioctl_siwap(struct
if (sdata->vif.type == NL80211_IFTYPE_STATION)
return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
- if (sdata->vif.type == NL80211_IFTYPE_WDS) {
- /*
- * If it is necessary to update the WDS peer address
- * while the interface is running, then we need to do
- * more work here, namely if it is running we need to
- * add a new and remove the old STA entry, this is
- * normally handled by _open() and _stop().
- */
- if (netif_running(dev))
- return -EBUSY;
-
- memcpy(&sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
- ETH_ALEN);
-
- return 0;
- }
-
+ if (sdata->vif.type == NL80211_IFTYPE_WDS)
+ return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra);
return -EOPNOTSUPP;
}
@@ -173,11 +158,8 @@ static int ieee80211_ioctl_giwap(struct
if (sdata->vif.type == NL80211_IFTYPE_STATION)
return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
- if (sdata->vif.type == NL80211_IFTYPE_WDS) {
- ap_addr->sa_family = ARPHRD_ETHER;
- memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
- return 0;
- }
+ if (sdata->vif.type == NL80211_IFTYPE_WDS)
+ return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra);
return -EOPNOTSUPP;
}
--- wireless-testing.orig/net/wireless/wext-compat.c 2009-07-01 20:29:35.000000000 +0200
+++ wireless-testing/net/wireless/wext-compat.c 2009-07-01 20:29:40.000000000 +0200
@@ -1048,3 +1048,49 @@ int cfg80211_wext_giwpower(struct net_de
return 0;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower);
+
+int cfg80211_wds_wext_siwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *addr, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ int err;
+
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
+ return -EINVAL;
+
+ if (addr->sa_family != ARPHRD_ETHER)
+ return -EINVAL;
+
+ if (netif_running(dev))
+ return -EBUSY;
+
+ if (!rdev->ops->set_wds_peer)
+ return -EOPNOTSUPP;
+
+ err = rdev->ops->set_wds_peer(wdev->wiphy, dev, (u8 *) &addr->sa_data);
+ if (err)
+ return err;
+
+ memcpy(&wdev->wext.bssid, (u8 *) &addr->sa_data, ETH_ALEN);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wds_wext_siwap);
+
+int cfg80211_wds_wext_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *addr, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
+ return -EINVAL;
+
+ addr->sa_family = ARPHRD_ETHER;
+ memcpy(&addr->sa_data, wdev->wext.bssid, ETH_ALEN);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wds_wext_giwap);
--- wireless-testing.orig/net/mac80211/cfg.c 2009-07-01 20:29:35.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c 2009-07-01 20:29:40.000000000 +0200
@@ -1369,6 +1369,16 @@ static int ieee80211_get_tx_power(struct
return 0;
}
+static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
+ u8 *addr)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ memcpy(&sdata->u.wds.remote_addr, addr, ETH_ALEN);
+
+ return 0;
+}
+
static void ieee80211_rfkill_poll(struct wiphy *wiphy)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
@@ -1454,6 +1464,7 @@ struct cfg80211_ops mac80211_config_ops
.set_wiphy_params = ieee80211_set_wiphy_params,
.set_tx_power = ieee80211_set_tx_power,
.get_tx_power = ieee80211_get_tx_power,
+ .set_wds_peer = ieee80211_set_wds_peer,
.rfkill_poll = ieee80211_rfkill_poll,
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
.set_power_mgmt = ieee80211_set_power_mgmt,
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 18/20 v4] cfg80211: implement IWRATE
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (16 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 17/20 v4] cfg80211: implement IWAP for WDS Johannes Berg
@ 2009-07-01 19:26 ` Johannes Berg
2009-07-01 19:27 ` [PATCH 19/20 v4] cfg80211: implement get_wireless_stats Johannes Berg
` (4 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:26 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
For now, let's implement that using a very hackish way:
simply mirror the wext API in the cfg80211 API. This
will have to be changed later when we implement proper
bitrate API.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/net/cfg80211.h | 32 ++++++++++++++++++
net/mac80211/cfg.c | 43 +++++++++++++++++++++++++
net/mac80211/wext.c | 76 +--------------------------------------------
net/wireless/wext-compat.c | 63 +++++++++++++++++++++++++++++++++++++
4 files changed, 140 insertions(+), 74 deletions(-)
--- wireless-testing.orig/include/net/cfg80211.h 2009-07-01 20:29:40.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h 2009-07-01 20:29:45.000000000 +0200
@@ -815,6 +815,26 @@ enum tx_power_setting {
TX_POWER_FIXED,
};
+/*
+ * cfg80211_bitrate_mask - masks for bitrate control
+ */
+struct cfg80211_bitrate_mask {
+/*
+ * As discussed in Berlin, this struct really
+ * should look like this:
+
+ struct {
+ u32 legacy;
+ u8 mcs[IEEE80211_HT_MCS_MASK_LEN];
+ } control[IEEE80211_NUM_BANDS];
+
+ * Since we can always fix in-kernel users, let's keep
+ * it simpler for now:
+ */
+ u32 fixed; /* fixed bitrate, 0 == not fixed */
+ u32 maxrate; /* in kbps, 0 == no limit */
+};
+
/**
* struct cfg80211_ops - backend description for wireless configuration
*
@@ -1027,6 +1047,11 @@ struct cfg80211_ops {
int (*testmode_cmd)(struct wiphy *wiphy, void *data, int len);
#endif
+ int (*set_bitrate_mask)(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *peer,
+ const struct cfg80211_bitrate_mask *mask);
+
/* some temporary stuff to finish wext */
int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
bool enabled, int timeout);
@@ -1581,6 +1606,13 @@ int cfg80211_wext_giwauth(struct net_dev
struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
struct iw_freq *freq);
+int cfg80211_wext_siwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rate, char *extra);
+int cfg80211_wext_giwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rate, char *extra);
+
int cfg80211_wext_siwrts(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rts, char *extra);
--- wireless-testing.orig/net/mac80211/cfg.c 2009-07-01 20:29:40.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c 2009-07-01 20:29:45.000000000 +0200
@@ -1423,6 +1423,48 @@ static int ieee80211_set_power_mgmt(stru
return 0;
}
+static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *addr,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ int i, err = -EINVAL;
+ u32 target_rate;
+ struct ieee80211_supported_band *sband;
+
+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+
+ /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
+ * target_rate = X, rate->fixed = 1 means only rate X
+ * target_rate = X, rate->fixed = 0 means all rates <= X */
+ sdata->max_ratectrl_rateidx = -1;
+ sdata->force_unicast_rateidx = -1;
+
+ if (mask->fixed)
+ target_rate = mask->fixed / 100;
+ else if (mask->maxrate)
+ target_rate = mask->maxrate / 100;
+ else
+ return 0;
+
+ for (i=0; i< sband->n_bitrates; i++) {
+ struct ieee80211_rate *brate = &sband->bitrates[i];
+ int this_rate = brate->bitrate;
+
+ if (target_rate == this_rate) {
+ sdata->max_ratectrl_rateidx = i;
+ if (mask->fixed)
+ sdata->force_unicast_rateidx = i;
+ err = 0;
+ break;
+ }
+ }
+
+ return err;
+}
+
struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -1468,4 +1510,5 @@ struct cfg80211_ops mac80211_config_ops
.rfkill_poll = ieee80211_rfkill_poll,
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
.set_power_mgmt = ieee80211_set_power_mgmt,
+ .set_bitrate_mask = ieee80211_set_bitrate_mask,
};
--- wireless-testing.orig/net/mac80211/wext.c 2009-07-01 20:29:40.000000000 +0200
+++ wireless-testing/net/mac80211/wext.c 2009-07-01 20:29:45.000000000 +0200
@@ -165,78 +165,6 @@ static int ieee80211_ioctl_giwap(struct
}
-static int ieee80211_ioctl_siwrate(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rate, char *extra)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- int i, err = -EINVAL;
- u32 target_rate = rate->value / 100000;
- struct ieee80211_sub_if_data *sdata;
- struct ieee80211_supported_band *sband;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
- /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
- * target_rate = X, rate->fixed = 1 means only rate X
- * target_rate = X, rate->fixed = 0 means all rates <= X */
- sdata->max_ratectrl_rateidx = -1;
- sdata->force_unicast_rateidx = -1;
- if (rate->value < 0)
- return 0;
-
- for (i=0; i< sband->n_bitrates; i++) {
- struct ieee80211_rate *brate = &sband->bitrates[i];
- int this_rate = brate->bitrate;
-
- if (target_rate == this_rate) {
- sdata->max_ratectrl_rateidx = i;
- if (rate->fixed)
- sdata->force_unicast_rateidx = i;
- err = 0;
- break;
- }
- }
- return err;
-}
-
-static int ieee80211_ioctl_giwrate(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rate, char *extra)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct sta_info *sta;
- struct ieee80211_sub_if_data *sdata;
- struct ieee80211_supported_band *sband;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- return -EOPNOTSUPP;
-
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
- rcu_read_lock();
-
- sta = sta_info_get(local, sdata->u.mgd.bssid);
-
- if (sta && !(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
- rate->value = sband->bitrates[sta->last_tx_rate.idx].bitrate;
- else
- rate->value = 0;
-
- rcu_read_unlock();
-
- if (!sta)
- return -ENODEV;
-
- rate->value *= 100000;
-
- return 0;
-}
-
/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
{
@@ -340,8 +268,8 @@ static const iw_handler ieee80211_handle
(iw_handler) NULL, /* SIOCGIWNICKN */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
- (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */
- (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */
+ (iw_handler) cfg80211_wext_siwrate, /* SIOCSIWRATE */
+ (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */
(iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */
(iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
(iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
--- wireless-testing.orig/net/wireless/wext-compat.c 2009-07-01 20:29:40.000000000 +0200
+++ wireless-testing/net/wireless/wext-compat.c 2009-07-01 20:29:45.000000000 +0200
@@ -1094,3 +1094,66 @@ int cfg80211_wds_wext_giwap(struct net_d
return 0;
}
EXPORT_SYMBOL_GPL(cfg80211_wds_wext_giwap);
+
+int cfg80211_wext_siwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rate, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_bitrate_mask mask;
+
+ if (!rdev->ops->set_bitrate_mask)
+ return -EOPNOTSUPP;
+
+ mask.fixed = 0;
+ mask.maxrate = 0;
+
+ if (rate->value < 0) {
+ /* nothing */
+ } else if (rate->fixed) {
+ mask.fixed = rate->value / 1000; /* kbps */
+ } else {
+ mask.maxrate = rate->value / 1000; /* kbps */
+ }
+
+ return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask);
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate);
+
+int cfg80211_wext_giwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rate, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ /* we are under RTNL - globally locked - so can use a static struct */
+ static struct station_info sinfo;
+ u8 *addr;
+ int err;
+
+ if (wdev->iftype != NL80211_IFTYPE_STATION)
+ return -EOPNOTSUPP;
+
+ if (!rdev->ops->get_station)
+ return -EOPNOTSUPP;
+
+ addr = wdev->wext.connect.bssid;
+ if (!addr)
+ return -EOPNOTSUPP;
+
+ err = rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo);
+ if (err)
+ return err;
+
+ if (!(sinfo.filled & STATION_INFO_TX_BITRATE))
+ return -EOPNOTSUPP;
+
+ rate->value = 0;
+
+ if (!(sinfo.txrate.flags & RATE_INFO_FLAGS_MCS))
+ rate->value = 100000 * sinfo.txrate.legacy;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_giwrate);
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 19/20 v4] cfg80211: implement get_wireless_stats
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (17 preceding siblings ...)
2009-07-01 19:26 ` [PATCH 18/20 v4] cfg80211: implement IWRATE Johannes Berg
@ 2009-07-01 19:27 ` Johannes Berg
2009-07-01 19:27 ` [PATCH 20/20 v4] mac80211: re-add HT disabling Johannes Berg
` (3 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:27 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
By dropping the noise reporting, we can implement
wireless stats in cfg80211. We also make the
handler return NULL if we have no information,
which is possible thanks to the recent wext change.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/net/cfg80211.h | 1
net/mac80211/wext.c | 69 ---------------------------------------------
net/wireless/wext-compat.c | 59 ++++++++++++++++++++++++++++++++++++++
3 files changed, 61 insertions(+), 68 deletions(-)
--- wireless-testing.orig/net/mac80211/wext.c 2009-07-01 20:29:45.000000000 +0200
+++ wireless-testing/net/mac80211/wext.c 2009-07-01 20:29:46.000000000 +0200
@@ -165,73 +165,6 @@ static int ieee80211_ioctl_giwap(struct
}
-/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
-static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct iw_statistics *wstats = &local->wstats;
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct sta_info *sta = NULL;
-
- rcu_read_lock();
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- sta = sta_info_get(local, sdata->u.mgd.bssid);
-
- if (!sta) {
- wstats->discard.fragment = 0;
- wstats->discard.misc = 0;
- wstats->qual.qual = 0;
- wstats->qual.level = 0;
- wstats->qual.noise = 0;
- wstats->qual.updated = IW_QUAL_ALL_INVALID;
- } else {
- wstats->qual.updated = 0;
- /*
- * mirror what cfg80211 does for iwrange/scan results,
- * otherwise userspace gets confused.
- */
- if (local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC |
- IEEE80211_HW_SIGNAL_DBM)) {
- wstats->qual.updated |= IW_QUAL_LEVEL_UPDATED;
- wstats->qual.updated |= IW_QUAL_QUAL_UPDATED;
- } else {
- wstats->qual.updated |= IW_QUAL_LEVEL_INVALID;
- wstats->qual.updated |= IW_QUAL_QUAL_INVALID;
- }
-
- if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) {
- wstats->qual.level = sta->last_signal;
- wstats->qual.qual = sta->last_signal;
- } else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
- int sig = sta->last_signal;
-
- wstats->qual.updated |= IW_QUAL_DBM;
- wstats->qual.level = sig;
- if (sig < -110)
- sig = -110;
- else if (sig > -40)
- sig = -40;
- wstats->qual.qual = sig + 110;
- }
-
- if (local->hw.flags & IEEE80211_HW_NOISE_DBM) {
- /*
- * This assumes that if driver reports noise, it also
- * reports signal in dBm.
- */
- wstats->qual.noise = sta->last_noise;
- wstats->qual.updated |= IW_QUAL_NOISE_UPDATED;
- } else {
- wstats->qual.updated |= IW_QUAL_NOISE_INVALID;
- }
- }
-
- rcu_read_unlock();
-
- return wstats;
-}
-
/* Structures to export the Wireless Handlers */
static const iw_handler ieee80211_handler[] =
@@ -298,5 +231,5 @@ const struct iw_handler_def ieee80211_iw
{
.num_standard = ARRAY_SIZE(ieee80211_handler),
.standard = (iw_handler *) ieee80211_handler,
- .get_wireless_stats = ieee80211_get_wireless_stats,
+ .get_wireless_stats = cfg80211_wireless_stats,
};
--- wireless-testing.orig/net/wireless/wext-compat.c 2009-07-01 20:29:45.000000000 +0200
+++ wireless-testing/net/wireless/wext-compat.c 2009-07-01 20:29:46.000000000 +0200
@@ -1157,3 +1157,62 @@ int cfg80211_wext_giwrate(struct net_dev
return 0;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwrate);
+
+/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
+struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ /* we are under RTNL - globally locked - so can use static structs */
+ static struct iw_statistics wstats;
+ static struct station_info sinfo;
+ u8 *addr;
+
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
+ return NULL;
+
+ if (!rdev->ops->get_station)
+ return NULL;
+
+ addr = wdev->wext.connect.bssid;
+ if (!addr)
+ return NULL;
+
+ if (rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo))
+ return NULL;
+
+ memset(&wstats, 0, sizeof(wstats));
+
+ switch (rdev->wiphy.signal_type) {
+ case CFG80211_SIGNAL_TYPE_MBM:
+ if (sinfo.filled & STATION_INFO_SIGNAL) {
+ int sig = sinfo.signal;
+ wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
+ wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
+ wstats.qual.updated |= IW_QUAL_DBM;
+ wstats.qual.level = sig;
+ if (sig < -110)
+ sig = -110;
+ else if (sig > -40)
+ sig = -40;
+ wstats.qual.qual = sig + 110;
+ break;
+ }
+ case CFG80211_SIGNAL_TYPE_UNSPEC:
+ if (sinfo.filled & STATION_INFO_SIGNAL) {
+ wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
+ wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
+ wstats.qual.level = sinfo.signal;
+ wstats.qual.qual = sinfo.signal;
+ break;
+ }
+ default:
+ wstats.qual.updated |= IW_QUAL_LEVEL_INVALID;
+ wstats.qual.updated |= IW_QUAL_QUAL_INVALID;
+ }
+
+ wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
+
+ return &wstats;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wireless_stats);
--- wireless-testing.orig/include/net/cfg80211.h 2009-07-01 20:29:45.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h 2009-07-01 20:29:46.000000000 +0200
@@ -1646,6 +1646,7 @@ int cfg80211_wext_siwtxpower(struct net_
int cfg80211_wext_giwtxpower(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *data, char *keybuf);
+struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev);
int cfg80211_wext_siwpower(struct net_device *dev,
struct iw_request_info *info,
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 20/20 v4] mac80211: re-add HT disabling
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (18 preceding siblings ...)
2009-07-01 19:27 ` [PATCH 19/20 v4] cfg80211: implement get_wireless_stats Johannes Berg
@ 2009-07-01 19:27 ` Johannes Berg
2009-07-01 19:40 ` [PATCH 21/20 v4] mac80211: remove auth algorithm retry Johannes Berg
` (2 subsequent siblings)
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:27 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
The IEEE80211_STA_TKIP_WEP_USED flag is used internally to
disable HT when WEP or TKIP are used. Now that cfg80211 is
giving us the required information, we can set the flag
appropriately again.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/cfg.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
--- wireless-testing.orig/net/mac80211/cfg.c 2009-07-01 20:29:45.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c 2009-07-01 20:29:47.000000000 +0200
@@ -1228,7 +1228,7 @@ static int ieee80211_assoc(struct wiphy
struct cfg80211_assoc_request *req)
{
struct ieee80211_sub_if_data *sdata;
- int ret;
+ int ret, i;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -1236,6 +1236,14 @@ static int ieee80211_assoc(struct wiphy
!(sdata->u.mgd.flags & IEEE80211_STA_AUTHENTICATED))
return -ENOLINK; /* not authenticated */
+ sdata->u.mgd.flags &= ~IEEE80211_STA_TKIP_WEP_USED;
+
+ for (i = 0; i < req->crypto.n_ciphers_pairwise; i++)
+ if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
+ req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
+ req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104)
+ sdata->u.mgd.flags |= IEEE80211_STA_TKIP_WEP_USED;
+
sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET;
--
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 21/20 v4] mac80211: remove auth algorithm retry
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (19 preceding siblings ...)
2009-07-01 19:27 ` [PATCH 20/20 v4] mac80211: re-add HT disabling Johannes Berg
@ 2009-07-01 19:40 ` Johannes Berg
2009-07-01 19:41 ` [PATCH 22/20 v4] mac80211: remove dead code, clean up Johannes Berg
2009-07-02 7:58 ` [PATCH] cfg80211: send events for userspace SME Johannes Berg
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:40 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
The automatic auth algorithm issue is now solved in
cfg80211, so mac80211 no longer needs code to try
different algorithms -- just using whatever cfg80211
asked for is good.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/cfg.c | 8 +++----
net/mac80211/debugfs_netdev.c | 3 --
net/mac80211/ieee80211_i.h | 8 -------
net/mac80211/mlme.c | 47 ------------------------------------------
4 files changed, 4 insertions(+), 62 deletions(-)
--- wireless-testing.orig/net/mac80211/ieee80211_i.h 2009-07-01 13:27:46.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h 2009-07-01 20:29:51.000000000 +0200
@@ -251,12 +251,6 @@ struct mesh_preq_queue {
#define IEEE80211_STA_REQ_AUTH 1
#define IEEE80211_STA_REQ_RUN 2
-/* bitfield of allowed auth algs */
-#define IEEE80211_AUTH_ALG_OPEN BIT(0)
-#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1)
-#define IEEE80211_AUTH_ALG_LEAP BIT(2)
-#define IEEE80211_AUTH_ALG_FT BIT(3)
-
struct ieee80211_if_managed {
struct timer_list timer;
struct timer_list chswitch_timer;
@@ -303,7 +297,6 @@ struct ieee80211_if_managed {
unsigned int flags;
- unsigned int auth_algs; /* bitfield of allowed auth algs */
int auth_alg; /* currently used IEEE 802.11 authentication algorithm */
int auth_transaction;
@@ -488,7 +481,6 @@ struct ieee80211_sub_if_data {
struct dentry *extra_ie_len;
struct dentry *auth_tries;
struct dentry *assoc_tries;
- struct dentry *auth_algs;
struct dentry *auth_alg;
struct dentry *auth_transaction;
struct dentry *flags;
--- wireless-testing.orig/net/mac80211/mlme.c 2009-07-01 20:29:35.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c 2009-07-01 20:29:51.000000000 +0200
@@ -1414,39 +1414,6 @@ static void ieee80211_rx_mgmt_auth(struc
return;
if (status_code != WLAN_STATUS_SUCCESS) {
- if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
- u8 algs[3];
- const int num_algs = ARRAY_SIZE(algs);
- int i, pos;
- algs[0] = algs[1] = algs[2] = 0xff;
- if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_OPEN)
- algs[0] = WLAN_AUTH_OPEN;
- if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
- algs[1] = WLAN_AUTH_SHARED_KEY;
- if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP)
- algs[2] = WLAN_AUTH_LEAP;
- if (ifmgd->auth_alg == WLAN_AUTH_OPEN)
- pos = 0;
- else if (ifmgd->auth_alg == WLAN_AUTH_SHARED_KEY)
- pos = 1;
- else
- pos = 2;
- for (i = 0; i < num_algs; i++) {
- pos++;
- if (pos >= num_algs)
- pos = 0;
- if (algs[pos] == ifmgd->auth_alg ||
- algs[pos] == 0xff)
- continue;
- if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
- !ieee80211_sta_wep_configured(sdata))
- continue;
- ifmgd->auth_alg = algs[pos];
- ifmgd->auth_tries = 0;
- return;
- }
- }
- /* nothing else to try -- give up */
cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len,
GFP_KERNEL);
ifmgd->state = IEEE80211_STA_MLME_DISABLED;
@@ -2102,18 +2069,6 @@ static void ieee80211_sta_reset_auth(str
drv_reset_tsf(local);
ifmgd->wmm_last_param_set = -1; /* allow any WMM update */
-
-
- if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_OPEN)
- ifmgd->auth_alg = WLAN_AUTH_OPEN;
- else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
- ifmgd->auth_alg = WLAN_AUTH_SHARED_KEY;
- else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP)
- ifmgd->auth_alg = WLAN_AUTH_LEAP;
- else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_FT)
- ifmgd->auth_alg = WLAN_AUTH_FT;
- else
- ifmgd->auth_alg = WLAN_AUTH_OPEN;
ifmgd->auth_transaction = -1;
ifmgd->flags &= ~IEEE80211_STA_ASSOCIATED;
ifmgd->assoc_scan_tries = 0;
@@ -2351,8 +2306,6 @@ void ieee80211_sta_setup_sdata(struct ie
skb_queue_head_init(&ifmgd->skb_queue);
ifmgd->capab = WLAN_CAPABILITY_ESS;
- ifmgd->auth_algs = IEEE80211_AUTH_ALG_OPEN |
- IEEE80211_AUTH_ALG_SHARED_KEY;
ifmgd->flags |= IEEE80211_STA_CREATE_IBSS |
IEEE80211_STA_AUTO_BSSID_SEL |
IEEE80211_STA_AUTO_CHANNEL_SEL;
--- wireless-testing.orig/net/mac80211/cfg.c 2009-07-01 20:29:47.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c 2009-07-01 20:29:51.000000000 +0200
@@ -1178,16 +1178,16 @@ static int ieee80211_auth(struct wiphy *
switch (req->auth_type) {
case NL80211_AUTHTYPE_OPEN_SYSTEM:
- sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_OPEN;
+ sdata->u.mgd.auth_alg = WLAN_AUTH_OPEN;
break;
case NL80211_AUTHTYPE_SHARED_KEY:
- sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_SHARED_KEY;
+ sdata->u.mgd.auth_alg = WLAN_AUTH_SHARED_KEY;
break;
case NL80211_AUTHTYPE_FT:
- sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_FT;
+ sdata->u.mgd.auth_alg = WLAN_AUTH_FT;
break;
case NL80211_AUTHTYPE_NETWORK_EAP:
- sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_LEAP;
+ sdata->u.mgd.auth_alg = WLAN_AUTH_LEAP;
break;
default:
return -EOPNOTSUPP;
--- wireless-testing.orig/net/mac80211/debugfs_netdev.c 2009-07-01 13:27:46.000000000 +0200
+++ wireless-testing/net/mac80211/debugfs_netdev.c 2009-07-01 20:29:52.000000000 +0200
@@ -105,7 +105,6 @@ IEEE80211_IF_FILE(capab, u.mgd.capab, HE
IEEE80211_IF_FILE(extra_ie_len, u.mgd.extra_ie_len, SIZE);
IEEE80211_IF_FILE(auth_tries, u.mgd.auth_tries, DEC);
IEEE80211_IF_FILE(assoc_tries, u.mgd.assoc_tries, DEC);
-IEEE80211_IF_FILE(auth_algs, u.mgd.auth_algs, HEX);
IEEE80211_IF_FILE(auth_alg, u.mgd.auth_alg, DEC);
IEEE80211_IF_FILE(auth_transaction, u.mgd.auth_transaction, DEC);
@@ -194,7 +193,6 @@ static void add_sta_files(struct ieee802
DEBUGFS_ADD(extra_ie_len, sta);
DEBUGFS_ADD(auth_tries, sta);
DEBUGFS_ADD(assoc_tries, sta);
- DEBUGFS_ADD(auth_algs, sta);
DEBUGFS_ADD(auth_alg, sta);
DEBUGFS_ADD(auth_transaction, sta);
DEBUGFS_ADD(flags, sta);
@@ -327,7 +325,6 @@ static void del_sta_files(struct ieee802
DEBUGFS_DEL(extra_ie_len, sta);
DEBUGFS_DEL(auth_tries, sta);
DEBUGFS_DEL(assoc_tries, sta);
- DEBUGFS_DEL(auth_algs, sta);
DEBUGFS_DEL(auth_alg, sta);
DEBUGFS_DEL(auth_transaction, sta);
DEBUGFS_DEL(flags, sta);
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 22/20 v4] mac80211: remove dead code, clean up
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (20 preceding siblings ...)
2009-07-01 19:40 ` [PATCH 21/20 v4] mac80211: remove auth algorithm retry Johannes Berg
@ 2009-07-01 19:41 ` Johannes Berg
2009-07-02 7:58 ` [PATCH] cfg80211: send events for userspace SME Johannes Berg
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-01 19:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
With mac80211 now always controlled by an external SME,
a lot of code is dead -- SSID, BSSID, channel selection
is always done externally, etc. Additionally, rename
IEEE80211_STA_TKIP_WEP_USED to IEEE80211_STA_DISABLE_11N
and clean up the code a bit.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/cfg.c | 39 ++-----
net/mac80211/debugfs_netdev.c | 4
net/mac80211/ieee80211_i.h | 42 +++----
net/mac80211/iface.c | 2
net/mac80211/mlme.c | 231 ++++--------------------------------------
5 files changed, 54 insertions(+), 264 deletions(-)
--- wireless-testing.orig/net/mac80211/cfg.c 2009-07-01 20:29:51.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c 2009-07-01 20:29:52.000000000 +0200
@@ -1194,18 +1194,14 @@ static int ieee80211_auth(struct wiphy *
}
memcpy(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN);
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
- sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET;
- /* TODO: req->chan */
- sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL;
+ sdata->local->oper_channel = req->chan;
+ ieee80211_hw_config(sdata->local, 0);
- if (req->ssid) {
- sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET;
- memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len);
- sdata->u.mgd.ssid_len = req->ssid_len;
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
- }
+ if (!req->ssid)
+ return -EINVAL;
+ memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len);
+ sdata->u.mgd.ssid_len = req->ssid_len;
kfree(sdata->u.mgd.sme_auth_ie);
sdata->u.mgd.sme_auth_ie = NULL;
@@ -1218,7 +1214,6 @@ static int ieee80211_auth(struct wiphy *
sdata->u.mgd.sme_auth_ie_len = req->ie_len;
}
- sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME;
sdata->u.mgd.state = IEEE80211_STA_MLME_DIRECT_PROBE;
ieee80211_sta_req_auth(sdata);
return 0;
@@ -1236,27 +1231,22 @@ static int ieee80211_assoc(struct wiphy
!(sdata->u.mgd.flags & IEEE80211_STA_AUTHENTICATED))
return -ENOLINK; /* not authenticated */
- sdata->u.mgd.flags &= ~IEEE80211_STA_TKIP_WEP_USED;
+ sdata->u.mgd.flags &= ~IEEE80211_STA_DISABLE_11N;
for (i = 0; i < req->crypto.n_ciphers_pairwise; i++)
if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104)
- sdata->u.mgd.flags |= IEEE80211_STA_TKIP_WEP_USED;
+ sdata->u.mgd.flags |= IEEE80211_STA_DISABLE_11N;
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
- sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET;
+ sdata->local->oper_channel = req->chan;
+ ieee80211_hw_config(sdata->local, 0);
- /* TODO: req->chan */
- sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL;
+ if (!req->ssid)
+ return -EINVAL;
- if (req->ssid) {
- sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET;
- memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len);
- sdata->u.mgd.ssid_len = req->ssid_len;
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
- } else
- sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL;
+ memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len);
+ sdata->u.mgd.ssid_len = req->ssid_len;
ret = ieee80211_sta_set_extra_ie(sdata, req->ie, req->ie_len);
if (ret && ret != -EALREADY)
@@ -1275,7 +1265,6 @@ static int ieee80211_assoc(struct wiphy
else
sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
- sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME;
sdata->u.mgd.state = IEEE80211_STA_MLME_ASSOCIATE;
ieee80211_sta_req_auth(sdata);
return 0;
--- wireless-testing.orig/net/mac80211/ieee80211_i.h 2009-07-01 20:29:51.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h 2009-07-01 20:29:52.000000000 +0200
@@ -228,28 +228,24 @@ struct mesh_preq_queue {
};
/* flags used in struct ieee80211_if_managed.flags */
-#define IEEE80211_STA_SSID_SET BIT(0)
-#define IEEE80211_STA_BSSID_SET BIT(1)
-#define IEEE80211_STA_PREV_BSSID_SET BIT(2)
-#define IEEE80211_STA_AUTHENTICATED BIT(3)
-#define IEEE80211_STA_ASSOCIATED BIT(4)
-#define IEEE80211_STA_PROBEREQ_POLL BIT(5)
-#define IEEE80211_STA_CREATE_IBSS BIT(6)
-#define IEEE80211_STA_CONTROL_PORT BIT(7)
-#define IEEE80211_STA_WMM_ENABLED BIT(8)
-/* hole at 9, please re-use */
-#define IEEE80211_STA_AUTO_SSID_SEL BIT(10)
-#define IEEE80211_STA_AUTO_BSSID_SEL BIT(11)
-#define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12)
-#define IEEE80211_STA_PRIVACY_INVOKED BIT(13)
-#define IEEE80211_STA_TKIP_WEP_USED BIT(14)
-#define IEEE80211_STA_CSA_RECEIVED BIT(15)
-#define IEEE80211_STA_MFP_ENABLED BIT(16)
-#define IEEE80211_STA_EXT_SME BIT(17)
+enum ieee80211_sta_flags {
+ IEEE80211_STA_PREV_BSSID_SET = BIT(0),
+ IEEE80211_STA_AUTHENTICATED = BIT(1),
+ IEEE80211_STA_ASSOCIATED = BIT(2),
+ IEEE80211_STA_PROBEREQ_POLL = BIT(3),
+ IEEE80211_STA_CONTROL_PORT = BIT(4),
+ IEEE80211_STA_WMM_ENABLED = BIT(5),
+ IEEE80211_STA_DISABLE_11N = BIT(6),
+ IEEE80211_STA_CSA_RECEIVED = BIT(7),
+ IEEE80211_STA_MFP_ENABLED = BIT(8),
+};
+
/* flags for MLME request */
-#define IEEE80211_STA_REQ_SCAN 0
-#define IEEE80211_STA_REQ_AUTH 1
-#define IEEE80211_STA_REQ_RUN 2
+enum ieee80211_sta_request {
+ IEEE80211_STA_REQ_SCAN,
+ IEEE80211_STA_REQ_AUTH,
+ IEEE80211_STA_REQ_RUN,
+};
struct ieee80211_if_managed {
struct timer_list timer;
@@ -934,10 +930,6 @@ extern const struct iw_handler_def ieee8
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata);
ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
-int ieee80211_sta_commit(struct ieee80211_sub_if_data *sdata);
-int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len);
-int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len);
-int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid);
void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata);
int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason);
int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason);
--- wireless-testing.orig/net/mac80211/mlme.c 2009-07-01 20:29:51.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c 2009-07-01 20:29:52.000000000 +0200
@@ -347,7 +347,7 @@ static void ieee80211_send_assoc(struct
sband->ht_cap.ht_supported &&
(ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) &&
ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
- (!(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED))) {
+ (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) {
struct ieee80211_ht_info *ht_info =
(struct ieee80211_ht_info *)(ht_ie + 2);
u16 cap = sband->ht_cap.cap;
@@ -981,8 +981,6 @@ static void ieee80211_authenticate(struc
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
- u8 *ies;
- size_t ies_len;
ifmgd->auth_tries++;
if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
@@ -1010,15 +1008,8 @@ static void ieee80211_authenticate(struc
printk(KERN_DEBUG "%s: authenticate with AP %pM\n",
sdata->dev->name, ifmgd->bssid);
- if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
- ies = ifmgd->sme_auth_ie;
- ies_len = ifmgd->sme_auth_ie_len;
- } else {
- ies = NULL;
- ies_len = 0;
- }
- ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, ies, ies_len,
- ifmgd->bssid, 0);
+ ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, ifmgd->sme_auth_ie,
+ ifmgd->sme_auth_ie_len, ifmgd->bssid, 0);
ifmgd->auth_transaction = 2;
mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
@@ -1128,44 +1119,6 @@ static void ieee80211_set_disassoc(struc
sta_info_destroy(sta);
}
-static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata)
-{
- if (!sdata || !sdata->default_key ||
- sdata->default_key->conf.alg != ALG_WEP)
- return 0;
- return 1;
-}
-
-static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_bss *bss;
- int bss_privacy;
- int wep_privacy;
- int privacy_invoked;
-
- if (!ifmgd || (ifmgd->flags & IEEE80211_STA_EXT_SME))
- return 0;
-
- bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
- local->hw.conf.channel->center_freq,
- ifmgd->ssid, ifmgd->ssid_len);
- if (!bss)
- return 0;
-
- bss_privacy = !!(bss->cbss.capability & WLAN_CAPABILITY_PRIVACY);
- wep_privacy = !!ieee80211_sta_wep_configured(sdata);
- privacy_invoked = !!(ifmgd->flags & IEEE80211_STA_PRIVACY_INVOKED);
-
- ieee80211_rx_bss_put(local, bss);
-
- if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
- return 0;
-
- return 1;
-}
-
static void ieee80211_associate(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -1195,14 +1148,6 @@ static void ieee80211_associate(struct i
ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE;
printk(KERN_DEBUG "%s: associate with AP %pM\n",
sdata->dev->name, ifmgd->bssid);
- if (ieee80211_privacy_mismatch(sdata)) {
- printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
- "mixed-cell disabled - abort association\n", sdata->dev->name);
- ifmgd->state = IEEE80211_STA_MLME_DISABLED;
- ieee80211_recalc_idle(local);
- return;
- }
-
ieee80211_send_assoc(sdata);
mod_timer(&ifmgd->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
@@ -1360,12 +1305,9 @@ static void ieee80211_auth_completed(str
printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name);
ifmgd->flags |= IEEE80211_STA_AUTHENTICATED;
- if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
- /* Wait for SME to request association */
- ifmgd->state = IEEE80211_STA_MLME_DISABLED;
- ieee80211_recalc_idle(sdata->local);
- } else
- ieee80211_associate(sdata);
+ /* Wait for SME to request association */
+ ifmgd->state = IEEE80211_STA_MLME_DISABLED;
+ ieee80211_recalc_idle(sdata->local);
}
@@ -1460,15 +1402,6 @@ static void ieee80211_rx_mgmt_deauth(str
printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n",
sdata->dev->name, reason_code);
- if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
- (ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE ||
- ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE ||
- ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)) {
- ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
- mod_timer(&ifmgd->timer, jiffies +
- IEEE80211_RETRY_AUTH_INTERVAL);
- }
-
ieee80211_set_disassoc(sdata, true, false, 0);
ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED;
cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, len, GFP_KERNEL);
@@ -1494,13 +1427,6 @@ static void ieee80211_rx_mgmt_disassoc(s
printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
sdata->dev->name, reason_code);
- if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
- ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) {
- ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE;
- mod_timer(&ifmgd->timer, jiffies +
- IEEE80211_RETRY_AUTH_INTERVAL);
- }
-
ieee80211_set_disassoc(sdata, false, false, reason_code);
cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, len, GFP_KERNEL);
}
@@ -1573,11 +1499,9 @@ static void ieee80211_rx_mgmt_assoc_resp
ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len,
GFP_KERNEL);
- if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
- /* Wait for SME to decide what to do next */
- ifmgd->state = IEEE80211_STA_MLME_DISABLED;
- ieee80211_recalc_idle(local);
- }
+ /* Wait for SME to decide what to do next */
+ ifmgd->state = IEEE80211_STA_MLME_DISABLED;
+ ieee80211_recalc_idle(local);
return;
}
@@ -1683,8 +1607,7 @@ static void ieee80211_rx_mgmt_assoc_resp
else
sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
- /* If TKIP/WEP is used, no need to parse AP's HT capabilities */
- if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED))
+ if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
elems.ht_cap_elem, &sta->sta.ht_cap);
@@ -1718,7 +1641,7 @@ static void ieee80211_rx_mgmt_assoc_resp
if (elems.ht_info_elem && elems.wmm_param &&
(ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
- !(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED))
+ !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
ap_ht_cap_flags);
@@ -1931,7 +1854,7 @@ static void ieee80211_rx_mgmt_beacon(str
if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param &&
- !(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED)) {
+ !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) {
struct sta_info *sta;
struct ieee80211_supported_band *sband;
u16 ap_ht_cap_flags;
@@ -2090,26 +2013,6 @@ static int ieee80211_sta_config_auth(str
u16 capa_val = WLAN_CAPABILITY_ESS;
struct ieee80211_channel *chan = local->oper_channel;
- if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
- ifmgd->flags & (IEEE80211_STA_AUTO_SSID_SEL |
- IEEE80211_STA_AUTO_BSSID_SEL |
- IEEE80211_STA_AUTO_CHANNEL_SEL)) {
- capa_mask |= WLAN_CAPABILITY_PRIVACY;
- if (sdata->default_key)
- capa_val |= WLAN_CAPABILITY_PRIVACY;
- }
-
- if (ifmgd->flags & IEEE80211_STA_AUTO_CHANNEL_SEL)
- chan = NULL;
-
- if (ifmgd->flags & IEEE80211_STA_AUTO_BSSID_SEL)
- bssid = NULL;
-
- if (ifmgd->flags & IEEE80211_STA_AUTO_SSID_SEL) {
- ssid = NULL;
- ssid_len = 0;
- }
-
bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan,
bssid, ssid, ssid_len,
capa_mask, capa_val);
@@ -2119,10 +2022,6 @@ static int ieee80211_sta_config_auth(str
local->oper_channel_type = NL80211_CHAN_NO_HT;
ieee80211_hw_config(local, 0);
- if (!(ifmgd->flags & IEEE80211_STA_SSID_SET))
- ieee80211_sta_set_ssid(sdata, bss->ssid,
- bss->ssid_len);
- ieee80211_sta_set_bssid(sdata, bss->cbss.bssid);
ieee80211_sta_def_wmm_params(sdata, bss->supp_rates_len,
bss->supp_rates);
if (sdata->u.mgd.mfp == IEEE80211_MFP_REQUIRED)
@@ -2232,14 +2131,6 @@ static void ieee80211_sta_work(struct wo
WARN_ON(1);
break;
}
-
- if (ieee80211_privacy_mismatch(sdata)) {
- printk(KERN_DEBUG "%s: privacy configuration mismatch and "
- "mixed-cell disabled - disassociate\n", sdata->dev->name);
-
- ieee80211_set_disassoc(sdata, false, true,
- WLAN_REASON_UNSPECIFIED);
- }
}
static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
@@ -2306,9 +2197,7 @@ void ieee80211_sta_setup_sdata(struct ie
skb_queue_head_init(&ifmgd->skb_queue);
ifmgd->capab = WLAN_CAPABILITY_ESS;
- ifmgd->flags |= IEEE80211_STA_CREATE_IBSS |
- IEEE80211_STA_AUTO_BSSID_SEL |
- IEEE80211_STA_AUTO_CHANNEL_SEL;
+ ifmgd->flags = 0;
if (sdata->local->hw.queues >= 4)
ifmgd->flags |= IEEE80211_STA_WMM_ENABLED;
@@ -2324,96 +2213,20 @@ void ieee80211_sta_req_auth(struct ieee8
if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
return;
- if ((ifmgd->flags & (IEEE80211_STA_BSSID_SET |
- IEEE80211_STA_AUTO_BSSID_SEL)) &&
- (ifmgd->flags & (IEEE80211_STA_SSID_SET |
- IEEE80211_STA_AUTO_SSID_SEL))) {
-
- if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)
- ieee80211_set_disassoc(sdata, true, true,
- WLAN_REASON_DEAUTH_LEAVING);
-
- if (ifmgd->ssid_len == 0) {
- /*
- * Only allow association to be started if a valid SSID
- * is configured.
- */
- return;
- }
-
- if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) ||
- ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE)
- set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
- else if (ifmgd->flags & IEEE80211_STA_EXT_SME)
- set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
- queue_work(local->hw.workqueue, &ifmgd->work);
- }
-}
-
-int ieee80211_sta_commit(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-
- if (ifmgd->ssid_len)
- ifmgd->flags |= IEEE80211_STA_SSID_SET;
- else
- ifmgd->flags &= ~IEEE80211_STA_SSID_SET;
-
- return 0;
-}
-
-int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len)
-{
- struct ieee80211_if_managed *ifmgd;
-
- if (len > IEEE80211_MAX_SSID_LEN)
- return -EINVAL;
-
- ifmgd = &sdata->u.mgd;
-
- if (ifmgd->ssid_len != len || memcmp(ifmgd->ssid, ssid, len) != 0) {
- if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)
- ieee80211_set_disassoc(sdata, true, true,
- WLAN_REASON_DEAUTH_LEAVING);
-
- /*
- * Do not use reassociation if SSID is changed (different ESS).
- */
- ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
- memset(ifmgd->ssid, 0, sizeof(ifmgd->ssid));
- memcpy(ifmgd->ssid, ssid, len);
- ifmgd->ssid_len = len;
- }
-
- return ieee80211_sta_commit(sdata);
-}
-
-int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len)
-{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- memcpy(ssid, ifmgd->ssid, ifmgd->ssid_len);
- *len = ifmgd->ssid_len;
- return 0;
-}
-
-int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
-{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-
- if (compare_ether_addr(bssid, ifmgd->bssid) != 0 &&
- ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)
+ if (WARN_ON(ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED))
ieee80211_set_disassoc(sdata, true, true,
WLAN_REASON_DEAUTH_LEAVING);
- if (is_valid_ether_addr(bssid)) {
- memcpy(ifmgd->bssid, bssid, ETH_ALEN);
- ifmgd->flags |= IEEE80211_STA_BSSID_SET;
- } else {
- memset(ifmgd->bssid, 0, ETH_ALEN);
- ifmgd->flags &= ~IEEE80211_STA_BSSID_SET;
+ if (WARN_ON(ifmgd->ssid_len == 0)) {
+ /*
+ * Only allow association to be started if a valid SSID
+ * is configured.
+ */
+ return;
}
- return ieee80211_sta_commit(sdata);
+ set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
+ queue_work(local->hw.workqueue, &ifmgd->work);
}
int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata,
--- wireless-testing.orig/net/mac80211/debugfs_netdev.c 2009-07-01 20:29:52.000000000 +0200
+++ wireless-testing/net/mac80211/debugfs_netdev.c 2009-07-01 20:29:52.000000000 +0200
@@ -111,9 +111,7 @@ IEEE80211_IF_FILE(auth_transaction, u.mg
static ssize_t ieee80211_if_fmt_flags(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
{
- return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n",
- sdata->u.mgd.flags & IEEE80211_STA_SSID_SET ? "SSID\n" : "",
- sdata->u.mgd.flags & IEEE80211_STA_BSSID_SET ? "BSSID\n" : "",
+ return scnprintf(buf, buflen, "%s%s%s%s%s\n",
sdata->u.mgd.flags & IEEE80211_STA_PREV_BSSID_SET ? "prev BSSID\n" : "",
sdata->u.mgd.flags & IEEE80211_STA_AUTHENTICATED ? "AUTH\n" : "",
sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED ? "ASSOC\n" : "",
--- wireless-testing.orig/net/mac80211/iface.c 2009-07-01 13:27:46.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c 2009-07-01 20:29:52.000000000 +0200
@@ -485,8 +485,6 @@ static int ieee80211_stop(struct net_dev
synchronize_rcu();
skb_queue_purge(&sdata->u.mgd.skb_queue);
- sdata->u.mgd.flags &= ~(IEEE80211_STA_PRIVACY_INVOKED |
- IEEE80211_STA_TKIP_WEP_USED);
kfree(sdata->u.mgd.extra_ie);
sdata->u.mgd.extra_ie = NULL;
sdata->u.mgd.extra_ie_len = 0;
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH] cfg80211: send events for userspace SME
2009-07-01 19:26 [PATCH 00/20 v4] wireless patch dump Johannes Berg
` (21 preceding siblings ...)
2009-07-01 19:41 ` [PATCH 22/20 v4] mac80211: remove dead code, clean up Johannes Berg
@ 2009-07-02 7:58 ` Johannes Berg
22 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2009-07-02 7:58 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
When the userspace SME is in control, we are currently not sending
events, but this means that any userspace applications using wext
or nl80211 to receive events will not know what's going on unless
they can also interpret the nl80211 assoc event. Since we have all
the required code, let the SME follow events from the userspace
SME, this even means that you will be refused to connect() while
the userspace SME is in control and connected.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/wireless/sme.c | 64 +++++++++++++++++++++++++++++++----------------------
1 file changed, 38 insertions(+), 26 deletions(-)
--- wireless-testing.orig/net/wireless/sme.c 2009-07-02 09:56:39.000000000 +0200
+++ wireless-testing/net/wireless/sme.c 2009-07-02 09:56:43.000000000 +0200
@@ -287,6 +287,44 @@ static void __cfg80211_connect_result(st
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
return;
+ if (wdev->sme_state == CFG80211_SME_CONNECTED)
+ nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), dev,
+ bssid, req_ie, req_ie_len,
+ resp_ie, resp_ie_len, gfp);
+ else
+ nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev,
+ bssid, req_ie, req_ie_len,
+ resp_ie, resp_ie_len,
+ status, gfp);
+
+#ifdef CONFIG_WIRELESS_EXT
+ if (wextev) {
+ if (req_ie && status == WLAN_STATUS_SUCCESS) {
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = req_ie_len;
+ wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie);
+ }
+
+ if (resp_ie && status == WLAN_STATUS_SUCCESS) {
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = resp_ie_len;
+ wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
+ }
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ if (bssid && status == WLAN_STATUS_SUCCESS)
+ memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
+ wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+ }
+#endif
+
+ if (status == WLAN_STATUS_SUCCESS &&
+ wdev->sme_state == CFG80211_SME_IDLE) {
+ wdev->sme_state = CFG80211_SME_CONNECTED;
+ return;
+ }
+
if (wdev->sme_state != CFG80211_SME_CONNECTING)
return;
@@ -315,32 +353,6 @@ static void __cfg80211_connect_result(st
if (wdev->conn)
wdev->conn->state = CFG80211_CONN_IDLE;
-
- nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, bssid,
- req_ie, req_ie_len, resp_ie, resp_ie_len,
- status, gfp);
-
-#ifdef CONFIG_WIRELESS_EXT
- if (wextev) {
- if (req_ie && status == WLAN_STATUS_SUCCESS) {
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = req_ie_len;
- wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie);
- }
-
- if (resp_ie && status == WLAN_STATUS_SUCCESS) {
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = resp_ie_len;
- wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
- }
-
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- if (bssid && status == WLAN_STATUS_SUCCESS)
- memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
- wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
- }
-#endif
}
void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
^ permalink raw reply [flat|nested] 31+ messages in thread