Commit fffd0934 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

cfg80211: rework key operation

This reworks the key operation in cfg80211, and now only
allows, from userspace, configuring keys (via nl80211)
after the connection has been established (in managed
mode), the IBSS been joined (in IBSS mode), at any time
(in AP[_VLAN] modes) or never for all the other modes.

In order to do shared key authentication correctly, it
is now possible to give a WEP key to the AUTH command.
To configure static WEP keys, these are given to the
CONNECT or IBSS_JOIN command directly, for a userspace
SME it is assumed it will configure it properly after
the connection has been established.

Since mac80211 used to check the default key in IBSS
mode to see whether or not the network is protected,
it needs an update in that area, as well as an update
to make use of the WEP key passed to auth() for shared
key authentication.
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent b9454e83
...@@ -569,6 +569,9 @@ enum nl80211_commands { ...@@ -569,6 +569,9 @@ enum nl80211_commands {
* *
* @NL80211_ATTR_KEY: key information in a nested attribute with * @NL80211_ATTR_KEY: key information in a nested attribute with
* %NL80211_KEY_* sub-attributes * %NL80211_KEY_* sub-attributes
* @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect()
* and join_ibss(), key information is in a nested attribute each
* with %NL80211_KEY_* sub-attributes
* *
* @NL80211_ATTR_MAX: highest attribute number currently defined * @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use * @__NL80211_ATTR_AFTER_LAST: internal use
...@@ -696,6 +699,7 @@ enum nl80211_attrs { ...@@ -696,6 +699,7 @@ enum nl80211_attrs {
NL80211_ATTR_PREV_BSSID, NL80211_ATTR_PREV_BSSID,
NL80211_ATTR_KEY, NL80211_ATTR_KEY,
NL80211_ATTR_KEYS,
/* add attributes here, update the policy in nl80211.c */ /* add attributes here, update the policy in nl80211.c */
...@@ -726,6 +730,7 @@ enum nl80211_attrs { ...@@ -726,6 +730,7 @@ enum nl80211_attrs {
#define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS #define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS
#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES #define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES
#define NL80211_ATTR_KEY NL80211_ATTR_KEY #define NL80211_ATTR_KEY NL80211_ATTR_KEY
#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS
#define NL80211_MAX_SUPP_RATES 32 #define NL80211_MAX_SUPP_RATES 32
#define NL80211_MAX_SUPP_REG_RULES 32 #define NL80211_MAX_SUPP_REG_RULES 32
......
...@@ -647,12 +647,17 @@ struct cfg80211_crypto_settings { ...@@ -647,12 +647,17 @@ struct cfg80211_crypto_settings {
* @auth_type: Authentication type (algorithm) * @auth_type: Authentication type (algorithm)
* @ie: Extra IEs to add to Authentication frame or %NULL * @ie: Extra IEs to add to Authentication frame or %NULL
* @ie_len: Length of ie buffer in octets * @ie_len: Length of ie buffer in octets
* @key_len: length of WEP key for shared key authentication
* @key_idx: index of WEP key for shared key authentication
* @key: WEP key for shared key authentication
*/ */
struct cfg80211_auth_request { struct cfg80211_auth_request {
struct cfg80211_bss *bss; struct cfg80211_bss *bss;
const u8 *ie; const u8 *ie;
size_t ie_len; size_t ie_len;
enum nl80211_auth_type auth_type; enum nl80211_auth_type auth_type;
const u8 *key;
u8 key_len, key_idx;
}; };
/** /**
...@@ -727,6 +732,8 @@ struct cfg80211_disassoc_request { ...@@ -727,6 +732,8 @@ struct cfg80211_disassoc_request {
* @ie: information element(s) to include in the beacon * @ie: information element(s) to include in the beacon
* @ie_len: length of that * @ie_len: length of that
* @beacon_interval: beacon interval to use * @beacon_interval: beacon interval to use
* @privacy: this is a protected network, keys will be configured
* after joining
*/ */
struct cfg80211_ibss_params { struct cfg80211_ibss_params {
u8 *ssid; u8 *ssid;
...@@ -736,6 +743,7 @@ struct cfg80211_ibss_params { ...@@ -736,6 +743,7 @@ struct cfg80211_ibss_params {
u8 ssid_len, ie_len; u8 ssid_len, ie_len;
u16 beacon_interval; u16 beacon_interval;
bool channel_fixed; bool channel_fixed;
bool privacy;
}; };
/** /**
...@@ -755,6 +763,9 @@ struct cfg80211_ibss_params { ...@@ -755,6 +763,9 @@ struct cfg80211_ibss_params {
* @assoc_ie_len: Length of assoc_ie in octets * @assoc_ie_len: Length of assoc_ie in octets
* @privacy: indicates whether privacy-enabled APs should be used * @privacy: indicates whether privacy-enabled APs should be used
* @crypto: crypto settings * @crypto: crypto settings
* @key_len: length of WEP key for shared key authentication
* @key_idx: index of WEP key for shared key authentication
* @key: WEP key for shared key authentication
*/ */
struct cfg80211_connect_params { struct cfg80211_connect_params {
struct ieee80211_channel *channel; struct ieee80211_channel *channel;
...@@ -766,6 +777,8 @@ struct cfg80211_connect_params { ...@@ -766,6 +777,8 @@ struct cfg80211_connect_params {
size_t ie_len; size_t ie_len;
bool privacy; bool privacy;
struct cfg80211_crypto_settings crypto; struct cfg80211_crypto_settings crypto;
const u8 *key;
u8 key_len, key_idx;
}; };
/** /**
...@@ -1223,9 +1236,10 @@ extern void wiphy_unregister(struct wiphy *wiphy); ...@@ -1223,9 +1236,10 @@ extern void wiphy_unregister(struct wiphy *wiphy);
*/ */
extern void wiphy_free(struct wiphy *wiphy); extern void wiphy_free(struct wiphy *wiphy);
/* internal struct */ /* internal structs */
struct cfg80211_conn; struct cfg80211_conn;
struct cfg80211_internal_bss; struct cfg80211_internal_bss;
struct cfg80211_cached_keys;
#define MAX_AUTH_BSSES 4 #define MAX_AUTH_BSSES 4
...@@ -1267,6 +1281,7 @@ struct wireless_dev { ...@@ -1267,6 +1281,7 @@ struct wireless_dev {
CFG80211_SME_CONNECTED, CFG80211_SME_CONNECTED,
} sme_state; } sme_state;
struct cfg80211_conn *conn; struct cfg80211_conn *conn;
struct cfg80211_cached_keys *connect_keys;
struct list_head event_list; struct list_head event_list;
spinlock_t event_lock; spinlock_t event_lock;
...@@ -1280,6 +1295,7 @@ struct wireless_dev { ...@@ -1280,6 +1295,7 @@ struct wireless_dev {
struct { struct {
struct cfg80211_ibss_params ibss; struct cfg80211_ibss_params ibss;
struct cfg80211_connect_params connect; struct cfg80211_connect_params connect;
struct cfg80211_cached_keys *keys;
u8 *ie; u8 *ie;
size_t ie_len; size_t ie_len;
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
......
...@@ -57,7 +57,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, ...@@ -57,7 +57,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
*/ */
if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1) if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1)
ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0, ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0,
sdata->u.ibss.bssid, 0); sdata->u.ibss.bssid, NULL, 0, 0);
} }
static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
...@@ -494,7 +494,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) ...@@ -494,7 +494,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
capability = WLAN_CAPABILITY_IBSS; capability = WLAN_CAPABILITY_IBSS;
if (sdata->default_key) if (ifibss->privacy)
capability |= WLAN_CAPABILITY_PRIVACY; capability |= WLAN_CAPABILITY_PRIVACY;
else else
sdata->drop_unencrypted = 0; sdata->drop_unencrypted = 0;
...@@ -524,9 +524,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) ...@@ -524,9 +524,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
return; return;
capability = WLAN_CAPABILITY_IBSS; capability = WLAN_CAPABILITY_IBSS;
if (sdata->default_key) if (ifibss->privacy)
capability |= WLAN_CAPABILITY_PRIVACY; capability |= WLAN_CAPABILITY_PRIVACY;
if (ifibss->fixed_bssid) if (ifibss->fixed_bssid)
bssid = ifibss->bssid; bssid = ifibss->bssid;
if (ifibss->fixed_channel) if (ifibss->fixed_channel)
...@@ -872,6 +871,8 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, ...@@ -872,6 +871,8 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
} else } else
sdata->u.ibss.fixed_bssid = false; sdata->u.ibss.fixed_bssid = false;
sdata->u.ibss.privacy = params->privacy;
sdata->vif.bss_conf.beacon_int = params->beacon_interval; sdata->vif.bss_conf.beacon_int = params->beacon_interval;
sdata->u.ibss.channel = params->channel; sdata->u.ibss.channel = params->channel;
......
...@@ -247,6 +247,9 @@ struct ieee80211_mgd_work { ...@@ -247,6 +247,9 @@ struct ieee80211_mgd_work {
int tries; int tries;
u8 key[WLAN_KEY_LEN_WEP104];
u8 key_len, key_idx;
/* must be last */ /* must be last */
u8 ie[0]; /* for auth or assoc frame, not probe */ u8 ie[0]; /* for auth or assoc frame, not probe */
}; };
...@@ -321,6 +324,7 @@ struct ieee80211_if_ibss { ...@@ -321,6 +324,7 @@ struct ieee80211_if_ibss {
bool fixed_bssid; bool fixed_bssid;
bool fixed_channel; bool fixed_channel;
bool privacy;
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid[IEEE80211_MAX_SSID_LEN];
...@@ -1093,8 +1097,8 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local, ...@@ -1093,8 +1097,8 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local,
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
u16 transaction, u16 auth_alg, u16 transaction, u16 auth_alg,
u8 *extra, size_t extra_len, u8 *extra, size_t extra_len, const u8 *bssid,
const u8 *bssid, int encrypt); const u8 *key, u8 key_len, u8 key_idx);
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
const u8 *ie, size_t ie_len); const u8 *ie, size_t ie_len);
void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
......
...@@ -954,7 +954,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, ...@@ -954,7 +954,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
sdata->dev->name, wk->bss->cbss.bssid, wk->tries); sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len,
wk->bss->cbss.bssid, 0); wk->bss->cbss.bssid, NULL, 0, 0);
wk->auth_transaction = 2; wk->auth_transaction = 2;
wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
...@@ -1176,7 +1176,8 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, ...@@ -1176,7 +1176,8 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
return; return;
ieee80211_send_auth(sdata, 3, wk->auth_alg, ieee80211_send_auth(sdata, 3, wk->auth_alg,
elems.challenge - 2, elems.challenge_len + 2, elems.challenge - 2, elems.challenge_len + 2,
wk->bss->cbss.bssid, 1); wk->bss->cbss.bssid,
wk->key, wk->key_len, wk->key_idx);
wk->auth_transaction = 4; wk->auth_transaction = 4;
} }
...@@ -2175,6 +2176,12 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, ...@@ -2175,6 +2176,12 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
wk->ie_len = req->ie_len; wk->ie_len = req->ie_len;
} }
if (req->key && req->key_len) {
wk->key_len = req->key_len;
wk->key_idx = req->key_idx;
memcpy(wk->key, req->key, req->key_len);
}
ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
memcpy(wk->ssid, ssid + 2, ssid[1]); memcpy(wk->ssid, ssid + 2, ssid[1]);
wk->ssid_len = ssid[1]; wk->ssid_len = ssid[1];
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "mesh.h" #include "mesh.h"
#include "wme.h" #include "wme.h"
#include "led.h" #include "led.h"
#include "wep.h"
/* privid for wiphys to determine whether they belong to us or not */ /* privid for wiphys to determine whether they belong to us or not */
void *mac80211_wiphy_privid = &mac80211_wiphy_privid; void *mac80211_wiphy_privid = &mac80211_wiphy_privid;
...@@ -804,12 +805,13 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local, ...@@ -804,12 +805,13 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
u16 transaction, u16 auth_alg, u16 transaction, u16 auth_alg,
u8 *extra, size_t extra_len, u8 *extra, size_t extra_len, const u8 *bssid,
const u8 *bssid, int encrypt) const u8 *key, u8 key_len, u8 key_idx)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct sk_buff *skb; struct sk_buff *skb;
struct ieee80211_mgmt *mgmt; struct ieee80211_mgmt *mgmt;
int err;
skb = dev_alloc_skb(local->hw.extra_tx_headroom + skb = dev_alloc_skb(local->hw.extra_tx_headroom +
sizeof(*mgmt) + 6 + extra_len); sizeof(*mgmt) + 6 + extra_len);
...@@ -824,8 +826,6 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, ...@@ -824,8 +826,6 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
memset(mgmt, 0, 24 + 6); memset(mgmt, 0, 24 + 6);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_AUTH); IEEE80211_STYPE_AUTH);
if (encrypt)
mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
memcpy(mgmt->da, bssid, ETH_ALEN); memcpy(mgmt->da, bssid, ETH_ALEN);
memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
memcpy(mgmt->bssid, bssid, ETH_ALEN); memcpy(mgmt->bssid, bssid, ETH_ALEN);
...@@ -835,7 +835,13 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, ...@@ -835,7 +835,13 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
if (extra) if (extra)
memcpy(skb_put(skb, extra_len), extra, extra_len); memcpy(skb_put(skb, extra_len), extra, extra_len);
ieee80211_tx_skb(sdata, skb, encrypt); if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
err = ieee80211_wep_encrypt(local, skb, key, key_len, key_idx);
WARN_ON(err);
}
ieee80211_tx_skb(sdata, skb, 0);
} }
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
......
...@@ -144,9 +144,9 @@ void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, ...@@ -144,9 +144,9 @@ void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
* *
* WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
*/ */
static int ieee80211_wep_encrypt(struct ieee80211_local *local, int ieee80211_wep_encrypt(struct ieee80211_local *local,
struct sk_buff *skb, struct sk_buff *skb,
const u8 *key, int keylen, int keyidx) const u8 *key, int keylen, int keyidx)
{ {
u8 *iv; u8 *iv;
size_t len; size_t len;
......
...@@ -20,6 +20,9 @@ int ieee80211_wep_init(struct ieee80211_local *local); ...@@ -20,6 +20,9 @@ int ieee80211_wep_init(struct ieee80211_local *local);
void ieee80211_wep_free(struct ieee80211_local *local); void ieee80211_wep_free(struct ieee80211_local *local);
void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
size_t klen, u8 *data, size_t data_len); size_t klen, u8 *data, size_t data_len);
int ieee80211_wep_encrypt(struct ieee80211_local *local,
struct sk_buff *skb,
const u8 *key, int keylen, int keyidx);
int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
size_t klen, u8 *data, size_t data_len); size_t klen, u8 *data, size_t data_len);
bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
......
...@@ -666,14 +666,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, ...@@ -666,14 +666,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
wdev_lock(wdev); wdev_lock(wdev);
switch (wdev->iftype) { switch (wdev->iftype) {
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
if (wdev->wext.ibss.ssid_len) cfg80211_ibss_wext_join(rdev, wdev);
__cfg80211_join_ibss(rdev, dev,
&wdev->wext.ibss);
break; break;
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
if (wdev->wext.connect.ssid_len) cfg80211_mgd_wext_connect(rdev, wdev);
__cfg80211_connect(rdev, dev,
&wdev->wext.connect);
break; break;
default: default:
break; break;
...@@ -690,6 +686,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, ...@@ -690,6 +686,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
} }
mutex_unlock(&rdev->devlist_mtx); mutex_unlock(&rdev->devlist_mtx);
mutex_destroy(&wdev->mtx); mutex_destroy(&wdev->mtx);
#ifdef CONFIG_WIRELESS_EXT
kfree(wdev->wext.keys);
#endif
break; break;
case NETDEV_PRE_UP: case NETDEV_PRE_UP:
if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
......
...@@ -238,6 +238,12 @@ struct cfg80211_event { ...@@ -238,6 +238,12 @@ struct cfg80211_event {
}; };
}; };
struct cfg80211_cached_keys {
struct key_params params[6];
u8 data[6][WLAN_MAX_KEY_LEN];
int def, defmgmt;
};
/* free object */ /* free object */
extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev); extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
...@@ -256,14 +262,18 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev, ...@@ -256,14 +262,18 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
/* IBSS */ /* IBSS */
int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct net_device *dev,
struct cfg80211_ibss_params *params); struct cfg80211_ibss_params *params,
struct cfg80211_cached_keys *connkeys);
int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct net_device *dev,
struct cfg80211_ibss_params *params); struct cfg80211_ibss_params *params,
struct cfg80211_cached_keys *connkeys);
void cfg80211_clear_ibss(struct net_device *dev, bool nowext); void cfg80211_clear_ibss(struct net_device *dev, bool nowext);
int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
struct net_device *dev, bool nowext); struct net_device *dev, bool nowext);
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev);
/* MLME */ /* MLME */
int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
...@@ -272,12 +282,14 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, ...@@ -272,12 +282,14 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
enum nl80211_auth_type auth_type, enum nl80211_auth_type auth_type,
const u8 *bssid, const u8 *bssid,
const u8 *ssid, int ssid_len, const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len); const u8 *ie, int ie_len,
const u8 *key, int key_len, int key_idx);
int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct ieee80211_channel *chan, struct net_device *dev, struct ieee80211_channel *chan,
enum nl80211_auth_type auth_type, const u8 *bssid, enum nl80211_auth_type auth_type, const u8 *bssid,
const u8 *ssid, int ssid_len, const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len); const u8 *ie, int ie_len,
const u8 *key, int key_len, int key_idx);
int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct net_device *dev,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
...@@ -310,10 +322,12 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, ...@@ -310,10 +322,12 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
/* SME */ /* SME */
int __cfg80211_connect(struct cfg80211_registered_device *rdev, int __cfg80211_connect(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct net_device *dev,
struct cfg80211_connect_params *connect); struct cfg80211_connect_params *connect,
struct cfg80211_cached_keys *connkeys);
int cfg80211_connect(struct cfg80211_registered_device *rdev, int cfg80211_connect(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct net_device *dev,
struct cfg80211_connect_params *connect); struct cfg80211_connect_params *connect,
struct cfg80211_cached_keys *connkeys);
int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
struct net_device *dev, u16 reason, struct net_device *dev, u16 reason,
bool wextev); bool wextev);
...@@ -323,11 +337,14 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev, ...@@ -323,11 +337,14 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
const u8 *req_ie, size_t req_ie_len, const u8 *req_ie, size_t req_ie_len,
const u8 *resp_ie, size_t resp_ie_len); const u8 *resp_ie, size_t resp_ie_len);
int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev);
void cfg80211_conn_work(struct work_struct *work); void cfg80211_conn_work(struct work_struct *work);
/* internal helpers */ /* internal helpers */
int cfg80211_validate_key_settings(struct key_params *params, int key_idx, int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
struct key_params *params, int key_idx,
const u8 *mac_addr); const u8 *mac_addr);
void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
size_t ie_len, u16 reason, bool from_ap); size_t ie_len, u16 reason, bool from_ap);
...@@ -335,5 +352,6 @@ void cfg80211_sme_scan_done(struct net_device *dev); ...@@ -335,5 +352,6 @@ void cfg80211_sme_scan_done(struct net_device *dev);
void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
void cfg80211_sme_disassoc(struct net_device *dev, int idx); void cfg80211_sme_disassoc(struct net_device *dev, int idx);
void __cfg80211_scan_done(struct work_struct *wk); void __cfg80211_scan_done(struct work_struct *wk);
void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
#endif /* __NET_WIRELESS_CORE_H */ #endif /* __NET_WIRELESS_CORE_H */
...@@ -39,6 +39,8 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) ...@@ -39,6 +39,8 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
cfg80211_hold_bss(bss_from_pub(bss)); cfg80211_hold_bss(bss_from_pub(bss));
wdev->current_bss = bss_from_pub(bss); wdev->current_bss = bss_from_pub(bss);
cfg80211_upload_connect_keys(wdev);
nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid,
GFP_KERNEL); GFP_KERNEL);
#ifdef CONFIG_WIRELESS_EXT #ifdef CONFIG_WIRELESS_EXT
...@@ -71,7 +73,8 @@ EXPORT_SYMBOL(cfg80211_ibss_joined); ...@@ -71,7 +73,8 @@ EXPORT_SYMBOL(cfg80211_ibss_joined);
int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct net_device *dev,
struct cfg80211_ibss_params *params) struct cfg80211_ibss_params *params,
struct cfg80211_cached_keys *connkeys)
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
int err; int err;
...@@ -81,13 +84,18 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, ...@@ -81,13 +84,18 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
if (wdev->ssid_len) if (wdev->ssid_len)
return -EALREADY; return -EALREADY;
if (WARN_ON(wdev->connect_keys))
kfree(wdev->connect_keys);
wdev->connect_keys = connkeys;
#ifdef CONFIG_WIRELESS_EXT #ifdef CONFIG_WIRELESS_EXT
wdev->wext.ibss.channel = params->channel; wdev->wext.ibss.channel = params->channel;
#endif #endif
err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
if (err) {
if (err) wdev->connect_keys = NULL;
return err; return err;
}
memcpy(wdev->ssid, params->ssid, params->ssid_len); memcpy(wdev->ssid, params->ssid, params->ssid_len);
wdev->ssid_len = params->ssid_len; wdev->ssid_len = params->ssid_len;
...@@ -97,13 +105,14 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, ...@@ -97,13 +105,14 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,