Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
@@ -74,12 +74,6 @@ config CFG80211_REG_DEBUG
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config CFG80211_DEFAULT_PS_VALUE
|
||||
int
|
||||
default 1 if CFG80211_DEFAULT_PS
|
||||
default 0
|
||||
depends on CFG80211
|
||||
|
||||
config CFG80211_DEFAULT_PS
|
||||
bool "enable powersave by default"
|
||||
depends on CFG80211
|
||||
|
||||
+13
-4
@@ -231,7 +231,7 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev;
|
||||
int err = 0;
|
||||
|
||||
if (!rdev->wiphy.netnsok)
|
||||
if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
list_for_each_entry(wdev, &rdev->netdev_list, list) {
|
||||
@@ -368,7 +368,9 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
|
||||
rdev->wiphy.dev.class = &ieee80211_class;
|
||||
rdev->wiphy.dev.platform_data = rdev;
|
||||
|
||||
rdev->wiphy.ps_default = CONFIG_CFG80211_DEFAULT_PS_VALUE;
|
||||
#ifdef CONFIG_CFG80211_DEFAULT_PS
|
||||
rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
#endif
|
||||
|
||||
wiphy_net_set(&rdev->wiphy, &init_net);
|
||||
|
||||
@@ -483,7 +485,7 @@ int wiphy_register(struct wiphy *wiphy)
|
||||
if (IS_ERR(rdev->wiphy.debugfsdir))
|
||||
rdev->wiphy.debugfsdir = NULL;
|
||||
|
||||
if (wiphy->custom_regulatory) {
|
||||
if (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) {
|
||||
struct regulatory_request request;
|
||||
|
||||
request.wiphy_idx = get_wiphy_idx(wiphy);
|
||||
@@ -681,7 +683,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
wdev->wext.default_key = -1;
|
||||
wdev->wext.default_mgmt_key = -1;
|
||||
wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
||||
wdev->wext.ps = wdev->wiphy->ps_default;
|
||||
if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
|
||||
wdev->wext.ps = true;
|
||||
else
|
||||
wdev->wext.ps = false;
|
||||
wdev->wext.ps_timeout = 100;
|
||||
if (rdev->ops->set_power_mgmt)
|
||||
if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
|
||||
@@ -693,6 +698,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
#endif
|
||||
if (!dev->ethtool_ops)
|
||||
dev->ethtool_ops = &cfg80211_ethtool_ops;
|
||||
|
||||
if ((wdev->iftype == NL80211_IFTYPE_STATION ||
|
||||
wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
|
||||
dev->priv_flags |= IFF_DONT_BRIDGE;
|
||||
break;
|
||||
case NETDEV_GOING_DOWN:
|
||||
switch (wdev->iftype) {
|
||||
|
||||
@@ -273,6 +273,8 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
||||
struct cfg80211_ibss_params *params,
|
||||
struct cfg80211_cached_keys *connkeys);
|
||||
void cfg80211_clear_ibss(struct net_device *dev, bool nowext);
|
||||
int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, bool nowext);
|
||||
int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, bool nowext);
|
||||
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
|
||||
|
||||
+2
-2
@@ -169,8 +169,8 @@ void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
|
||||
wdev_unlock(wdev);
|
||||
}
|
||||
|
||||
static int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, bool nowext)
|
||||
int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, bool nowext)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err;
|
||||
|
||||
+43
-13
@@ -243,21 +243,12 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_send_disassoc);
|
||||
|
||||
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
|
||||
static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
int i;
|
||||
bool done = false;
|
||||
|
||||
wdev_lock(wdev);
|
||||
|
||||
nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
|
||||
if (wdev->sme_state == CFG80211_SME_CONNECTING)
|
||||
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
false, NULL);
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
|
||||
if (wdev->authtry_bsses[i] &&
|
||||
@@ -272,6 +263,29 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
|
||||
}
|
||||
|
||||
WARN_ON(!done);
|
||||
}
|
||||
|
||||
void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr)
|
||||
{
|
||||
__cfg80211_auth_remove(dev->ieee80211_ptr, addr);
|
||||
}
|
||||
EXPORT_SYMBOL(__cfg80211_auth_canceled);
|
||||
|
||||
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
|
||||
wdev_lock(wdev);
|
||||
|
||||
nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
|
||||
if (wdev->sme_state == CFG80211_SME_CONNECTING)
|
||||
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
false, NULL);
|
||||
|
||||
__cfg80211_auth_remove(wdev, addr);
|
||||
|
||||
wdev_unlock(wdev);
|
||||
}
|
||||
@@ -446,12 +460,23 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
|
||||
struct cfg80211_assoc_request req;
|
||||
struct cfg80211_internal_bss *bss;
|
||||
int i, err, slot = -1;
|
||||
bool was_connected = false;
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
||||
if (wdev->current_bss)
|
||||
if (wdev->current_bss && prev_bssid &&
|
||||
memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) {
|
||||
/*
|
||||
* Trying to reassociate: Allow this to proceed and let the old
|
||||
* association to be dropped when the new one is completed.
|
||||
*/
|
||||
if (wdev->sme_state == CFG80211_SME_CONNECTED) {
|
||||
was_connected = true;
|
||||
wdev->sme_state = CFG80211_SME_CONNECTING;
|
||||
}
|
||||
} else if (wdev->current_bss)
|
||||
return -EALREADY;
|
||||
|
||||
req.ie = ie;
|
||||
@@ -461,8 +486,11 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
|
||||
req.prev_bssid = prev_bssid;
|
||||
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
|
||||
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
|
||||
if (!req.bss)
|
||||
if (!req.bss) {
|
||||
if (was_connected)
|
||||
wdev->sme_state = CFG80211_SME_CONNECTED;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
bss = bss_from_pub(req.bss);
|
||||
|
||||
@@ -480,6 +508,8 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
|
||||
|
||||
err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
|
||||
out:
|
||||
if (err && was_connected)
|
||||
wdev->sme_state = CFG80211_SME_CONNECTED;
|
||||
/* still a reference in wdev->auth_bsses[slot] */
|
||||
cfg80211_put_bss(req.bss);
|
||||
return err;
|
||||
|
||||
+38
-2
@@ -561,7 +561,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
|
||||
CMD(deauth, DEAUTHENTICATE);
|
||||
CMD(disassoc, DISASSOCIATE);
|
||||
CMD(join_ibss, JOIN_IBSS);
|
||||
if (dev->wiphy.netnsok) {
|
||||
if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
|
||||
i++;
|
||||
NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
|
||||
}
|
||||
@@ -968,6 +968,32 @@ static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev, u8 use_4addr,
|
||||
enum nl80211_iftype iftype)
|
||||
{
|
||||
if (!use_4addr) {
|
||||
if (netdev && netdev->br_port)
|
||||
return -EBUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (iftype) {
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
|
||||
return 0;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
@@ -1011,6 +1037,9 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
|
||||
if (info->attrs[NL80211_ATTR_4ADDR]) {
|
||||
params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
|
||||
change = true;
|
||||
err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
|
||||
if (err)
|
||||
goto unlock;
|
||||
} else {
|
||||
params.use_4addr = -1;
|
||||
}
|
||||
@@ -1034,6 +1063,9 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
|
||||
else
|
||||
err = 0;
|
||||
|
||||
if (!err && params.use_4addr != -1)
|
||||
dev->ieee80211_ptr->use_4addr = params.use_4addr;
|
||||
|
||||
unlock:
|
||||
dev_put(dev);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
@@ -1081,8 +1113,12 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
|
||||
params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_4ADDR])
|
||||
if (info->attrs[NL80211_ATTR_4ADDR]) {
|
||||
params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
|
||||
err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
|
||||
info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
|
||||
|
||||
+7
-6
@@ -1008,7 +1008,7 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
|
||||
|
||||
if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
|
||||
request_wiphy && request_wiphy == wiphy &&
|
||||
request_wiphy->strict_regulatory) {
|
||||
request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
|
||||
/*
|
||||
* This gaurantees the driver's requested regulatory domain
|
||||
* will always be used as a base for further regulatory
|
||||
@@ -1051,13 +1051,13 @@ static bool ignore_reg_update(struct wiphy *wiphy,
|
||||
if (!last_request)
|
||||
return true;
|
||||
if (initiator == NL80211_REGDOM_SET_BY_CORE &&
|
||||
wiphy->custom_regulatory)
|
||||
wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)
|
||||
return true;
|
||||
/*
|
||||
* wiphy->regd will be set once the device has its own
|
||||
* desired regulatory domain set
|
||||
*/
|
||||
if (wiphy->strict_regulatory && !wiphy->regd &&
|
||||
if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd &&
|
||||
!is_world_regdom(last_request->alpha2))
|
||||
return true;
|
||||
return false;
|
||||
@@ -1093,7 +1093,7 @@ static void handle_reg_beacon(struct wiphy *wiphy,
|
||||
|
||||
chan->beacon_found = true;
|
||||
|
||||
if (wiphy->disable_beacon_hints)
|
||||
if (wiphy->flags & WIPHY_FLAG_DISABLE_BEACON_HINTS)
|
||||
return;
|
||||
|
||||
chan_before.center_freq = chan->center_freq;
|
||||
@@ -1164,7 +1164,7 @@ static bool reg_is_world_roaming(struct wiphy *wiphy)
|
||||
return true;
|
||||
if (last_request &&
|
||||
last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
|
||||
wiphy->custom_regulatory)
|
||||
wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -1591,7 +1591,8 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
||||
|
||||
r = __regulatory_hint(wiphy, reg_request);
|
||||
/* This is required so that the orig_* parameters are saved */
|
||||
if (r == -EALREADY && wiphy && wiphy->strict_regulatory)
|
||||
if (r == -EALREADY && wiphy &&
|
||||
wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
|
||||
wiphy_update_regulatory(wiphy, reg_request->initiator);
|
||||
out:
|
||||
mutex_unlock(®_mutex);
|
||||
|
||||
+23
-17
@@ -217,7 +217,7 @@ static bool is_mesh(struct cfg80211_bss *a,
|
||||
a->len_information_elements);
|
||||
if (!ie)
|
||||
return false;
|
||||
if (ie[1] != IEEE80211_MESH_CONFIG_LEN)
|
||||
if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
|
||||
return false;
|
||||
|
||||
/*
|
||||
@@ -225,7 +225,8 @@ static bool is_mesh(struct cfg80211_bss *a,
|
||||
* comparing since that may differ between stations taking
|
||||
* part in the same mesh.
|
||||
*/
|
||||
return memcmp(ie + 2, meshcfg, IEEE80211_MESH_CONFIG_LEN - 2) == 0;
|
||||
return memcmp(ie + 2, meshcfg,
|
||||
sizeof(struct ieee80211_meshconf_ie) - 2) == 0;
|
||||
}
|
||||
|
||||
static int cmp_bss(struct cfg80211_bss *a,
|
||||
@@ -399,7 +400,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
|
||||
res->pub.information_elements,
|
||||
res->pub.len_information_elements);
|
||||
if (!meshid || !meshcfg ||
|
||||
meshcfg[1] != IEEE80211_MESH_CONFIG_LEN) {
|
||||
meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) {
|
||||
/* bogus mesh */
|
||||
kref_put(&res->ref, bss_release);
|
||||
return NULL;
|
||||
@@ -865,7 +866,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
|
||||
break;
|
||||
case WLAN_EID_MESH_CONFIG:
|
||||
ismesh = true;
|
||||
if (ie[1] != IEEE80211_MESH_CONFIG_LEN)
|
||||
if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
|
||||
break;
|
||||
buf = kmalloc(50, GFP_ATOMIC);
|
||||
if (!buf)
|
||||
@@ -873,35 +874,40 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
|
||||
cfg = ie + 2;
|
||||
memset(&iwe, 0, sizeof(iwe));
|
||||
iwe.cmd = IWEVCUSTOM;
|
||||
sprintf(buf, "Mesh network (version %d)", cfg[0]);
|
||||
sprintf(buf, "Mesh Network Path Selection Protocol ID: "
|
||||
"0x%02X", cfg[0]);
|
||||
iwe.u.data.length = strlen(buf);
|
||||
current_ev = iwe_stream_add_point(info, current_ev,
|
||||
end_buf,
|
||||
&iwe, buf);
|
||||
sprintf(buf, "Path Selection Protocol ID: "
|
||||
"0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3],
|
||||
cfg[4]);
|
||||
sprintf(buf, "Path Selection Metric ID: 0x%02X",
|
||||
cfg[1]);
|
||||
iwe.u.data.length = strlen(buf);
|
||||
current_ev = iwe_stream_add_point(info, current_ev,
|
||||
end_buf,
|
||||
&iwe, buf);
|
||||
sprintf(buf, "Path Selection Metric ID: "
|
||||
"0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7],
|
||||
cfg[8]);
|
||||
sprintf(buf, "Congestion Control Mode ID: 0x%02X",
|
||||
cfg[2]);
|
||||
iwe.u.data.length = strlen(buf);
|
||||
current_ev = iwe_stream_add_point(info, current_ev,
|
||||
end_buf,
|
||||
&iwe, buf);
|
||||
sprintf(buf, "Congestion Control Mode ID: "
|
||||
"0x%02X%02X%02X%02X", cfg[9], cfg[10],
|
||||
cfg[11], cfg[12]);
|
||||
sprintf(buf, "Synchronization ID: 0x%02X", cfg[3]);
|
||||
iwe.u.data.length = strlen(buf);
|
||||
current_ev = iwe_stream_add_point(info, current_ev,
|
||||
end_buf,
|
||||
&iwe, buf);
|
||||
sprintf(buf, "Channel Precedence: "
|
||||
"0x%02X%02X%02X%02X", cfg[13], cfg[14],
|
||||
cfg[15], cfg[16]);
|
||||
sprintf(buf, "Authentication ID: 0x%02X", cfg[4]);
|
||||
iwe.u.data.length = strlen(buf);
|
||||
current_ev = iwe_stream_add_point(info, current_ev,
|
||||
end_buf,
|
||||
&iwe, buf);
|
||||
sprintf(buf, "Formation Info: 0x%02X", cfg[5]);
|
||||
iwe.u.data.length = strlen(buf);
|
||||
current_ev = iwe_stream_add_point(info, current_ev,
|
||||
end_buf,
|
||||
&iwe, buf);
|
||||
sprintf(buf, "Capabilities: 0x%02X", cfg[6]);
|
||||
iwe.u.data.length = strlen(buf);
|
||||
current_ev = iwe_stream_add_point(info, current_ev,
|
||||
end_buf,
|
||||
|
||||
@@ -658,7 +658,14 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||
!(rdev->wiphy.interface_modes & (1 << ntype)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* if it's part of a bridge, reject changing type to station/ibss */
|
||||
if (dev->br_port && (ntype == NL80211_IFTYPE_ADHOC ||
|
||||
ntype == NL80211_IFTYPE_STATION))
|
||||
return -EBUSY;
|
||||
|
||||
if (ntype != otype) {
|
||||
dev->ieee80211_ptr->use_4addr = false;
|
||||
|
||||
switch (otype) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
cfg80211_leave_ibss(rdev, dev, false);
|
||||
@@ -682,5 +689,34 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||
|
||||
WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype);
|
||||
|
||||
if (!err && params && params->use_4addr != -1)
|
||||
dev->ieee80211_ptr->use_4addr = params->use_4addr;
|
||||
|
||||
if (!err) {
|
||||
dev->priv_flags &= ~IFF_DONT_BRIDGE;
|
||||
switch (ntype) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (dev->ieee80211_ptr->use_4addr)
|
||||
break;
|
||||
/* fall through */
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
dev->priv_flags |= IFF_DONT_BRIDGE;
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
case NL80211_IFTYPE_WDS:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
/* bridging OK */
|
||||
break;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
/* monitor can't bridge anyway */
|
||||
break;
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
case __NL80211_IFTYPE_AFTER_LAST:
|
||||
/* not happening */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -437,6 +437,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err, i;
|
||||
bool rejoin = false;
|
||||
|
||||
if (!wdev->wext.keys) {
|
||||
wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
|
||||
@@ -466,8 +467,24 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
||||
|
||||
if (remove) {
|
||||
err = 0;
|
||||
if (wdev->current_bss)
|
||||
if (wdev->current_bss) {
|
||||
/*
|
||||
* If removing the current TX key, we will need to
|
||||
* join a new IBSS without the privacy bit clear.
|
||||
*/
|
||||
if (idx == wdev->wext.default_key &&
|
||||
wdev->iftype == NL80211_IFTYPE_ADHOC) {
|
||||
__cfg80211_leave_ibss(rdev, wdev->netdev, true);
|
||||
rejoin = true;
|
||||
}
|
||||
err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
|
||||
}
|
||||
/*
|
||||
* Applications using wireless extensions expect to be
|
||||
* able to delete keys that don't exist, so allow that.
|
||||
*/
|
||||
if (err == -ENOENT)
|
||||
err = 0;
|
||||
if (!err) {
|
||||
if (!addr) {
|
||||
wdev->wext.keys->params[idx].key_len = 0;
|
||||
@@ -478,12 +495,9 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
||||
else if (idx == wdev->wext.default_mgmt_key)
|
||||
wdev->wext.default_mgmt_key = -1;
|
||||
}
|
||||
/*
|
||||
* Applications using wireless extensions expect to be
|
||||
* able to delete keys that don't exist, so allow that.
|
||||
*/
|
||||
if (err == -ENOENT)
|
||||
return 0;
|
||||
|
||||
if (!err && rejoin)
|
||||
err = cfg80211_ibss_wext_join(rdev, wdev);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -511,11 +525,25 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
||||
if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
|
||||
params->cipher == WLAN_CIPHER_SUITE_WEP104) &&
|
||||
(tx_key || (!addr && wdev->wext.default_key == -1))) {
|
||||
if (wdev->current_bss)
|
||||
if (wdev->current_bss) {
|
||||
/*
|
||||
* If we are getting a new TX key from not having
|
||||
* had one before we need to join a new IBSS with
|
||||
* the privacy bit set.
|
||||
*/
|
||||
if (wdev->iftype == NL80211_IFTYPE_ADHOC &&
|
||||
wdev->wext.default_key == -1) {
|
||||
__cfg80211_leave_ibss(rdev, wdev->netdev, true);
|
||||
rejoin = true;
|
||||
}
|
||||
err = rdev->ops->set_default_key(&rdev->wiphy,
|
||||
dev, idx);
|
||||
if (!err)
|
||||
}
|
||||
if (!err) {
|
||||
wdev->wext.default_key = idx;
|
||||
if (rejoin)
|
||||
err = cfg80211_ibss_wext_join(rdev, wdev);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -539,10 +567,13 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
||||
{
|
||||
int err;
|
||||
|
||||
/* devlist mutex needed for possible IBSS re-join */
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
err = __cfg80211_set_encryption(rdev, dev, addr, remove,
|
||||
tx_key, idx, params);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user