#include <net/cfg80211.h>
#include "ieee80211_i.h"
#include "cfg.h"
-#include "ieee80211_rate.h"
+#include "rate.h"
#include "mesh.h"
static enum ieee80211_if_types
case NL80211_IFTYPE_MESH_POINT:
return IEEE80211_IF_TYPE_MESH_POINT;
#endif
+ case NL80211_IFTYPE_WDS:
+ return IEEE80211_IF_TYPE_WDS;
default:
return IEEE80211_IF_TYPE_INVALID;
}
struct sta_info *sta = NULL;
enum ieee80211_key_alg alg;
struct ieee80211_key *key;
+ int err;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (!key)
return -ENOMEM;
+ rcu_read_lock();
+
if (mac_addr) {
sta = sta_info_get(sdata->local, mac_addr);
if (!sta) {
ieee80211_key_free(key);
- return -ENOENT;
+ err = -ENOENT;
+ goto out_unlock;
}
}
ieee80211_key_link(key, sdata, sta);
- return 0;
+ err = 0;
+ out_unlock:
+ rcu_read_unlock();
+
+ return err;
}
static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ rcu_read_lock();
+
if (mac_addr) {
+ ret = -ENOENT;
+
sta = sta_info_get(sdata->local, mac_addr);
if (!sta)
- return -ENOENT;
+ goto out_unlock;
- ret = 0;
if (sta->key) {
ieee80211_key_free(sta->key);
WARN_ON(sta->key);
- } else
- ret = -ENOENT;
+ ret = 0;
+ }
- return ret;
+ goto out_unlock;
}
- if (!sdata->keys[key_idx])
- return -ENOENT;
+ if (!sdata->keys[key_idx]) {
+ ret = -ENOENT;
+ goto out_unlock;
+ }
ieee80211_key_free(sdata->keys[key_idx]);
WARN_ON(sdata->keys[key_idx]);
- return 0;
+ ret = 0;
+ out_unlock:
+ rcu_read_unlock();
+
+ return ret;
}
static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
u16 iv16;
int err = -ENOENT;
+ rcu_read_lock();
+
if (mac_addr) {
sta = sta_info_get(sdata->local, mac_addr);
if (!sta)
err = 0;
out:
+ rcu_read_unlock();
return err;
}
{
struct ieee80211_sub_if_data *sdata;
+ rcu_read_lock();
+
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
ieee80211_set_default_key(sdata, key_idx);
+ rcu_read_unlock();
+
return 0;
}
err = sta_info_insert(sta);
if (err) {
- sta_info_destroy(sta);
+ /* STA has been freed */
rcu_read_unlock();
return err;
}
struct sta_info *sta;
if (mac) {
+ rcu_read_lock();
+
/* XXX: get sta belonging to dev */
sta = sta_info_get(local, mac);
- if (!sta)
+ if (!sta) {
+ rcu_read_unlock();
return -ENOENT;
+ }
sta_info_unlink(&sta);
+ rcu_read_unlock();
- if (sta) {
- synchronize_rcu();
- sta_info_destroy(sta);
- }
+ sta_info_destroy(sta);
} else
sta_info_flush(local, sdata);
struct sta_info *sta;
struct ieee80211_sub_if_data *vlansdata;
+ rcu_read_lock();
+
/* XXX: get sta belonging to dev */
sta = sta_info_get(local, mac);
- if (!sta)
+ if (!sta) {
+ rcu_read_unlock();
return -ENOENT;
+ }
if (params->vlan && params->vlan != sta->sdata->dev) {
vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN ||
- vlansdata->vif.type != IEEE80211_IF_TYPE_AP)
+ vlansdata->vif.type != IEEE80211_IF_TYPE_AP) {
+ rcu_read_unlock();
return -EINVAL;
+ }
sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
ieee80211_send_layer2_update(sta);
sta_apply_parameters(local, sta, params);
+ rcu_read_unlock();
+
return 0;
}