mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 16:54:20 +08:00
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
John W. Linville says: ==================== This is a batch of fixes intended for the 3.7 stream. Dan Carpenter brings a fix for a simple signedness bug that could prevent the proper termination of a loop. Felix Fietkau found a few more places that need to use ieee80211_free_txskb for properly releasing SKBs used by mac80211. Franky Lin offers a pair of brcmfmac fixes, both fixing simple state reporting errors. Hante Meuleman corrects an error reporting case that wasn't handling all types of errors properly. Johan Hedberg offers a fix for an issue discovered at the Bluetooth UnPlug Fest. Gustavo says "the patch fixes a failure to pair with devices that support the LE Secure Connections feature." Johannes Berg sends an iwlwifi fix to handle a message type that is too large for the normal command mechanism. He also provides a mac80211 fix to use HT20 channels when HT40 channels are not permitted. Jouni Malinen offers a mac80211 fix for a masking error that was incorrectly marking some frames. Piotr Haber provides a fix to make sure bcma devices are unregistered properly. Stanislav Yakovlev gives us a fix for a panic in the ipw2200 driver. Stanislaw Gruszka sends a pair of fixes: one prevents a mismatch on connection states between cfg80211 and mac80211; the other prevents some frame corruption related to handling encryption. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
e6e71054cd
@ -158,9 +158,10 @@ static int bcma_register_cores(struct bcma_bus *bus)
|
||||
|
||||
static void bcma_unregister_cores(struct bcma_bus *bus)
|
||||
{
|
||||
struct bcma_device *core;
|
||||
struct bcma_device *core, *tmp;
|
||||
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
list_for_each_entry_safe(core, tmp, &bus->cores, list) {
|
||||
list_del(&core->list);
|
||||
if (core->dev_registered)
|
||||
device_unregister(&core->dev);
|
||||
}
|
||||
|
@ -1339,7 +1339,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
|
||||
}
|
||||
|
||||
ret = brcmf_bus_start(dev);
|
||||
if (ret == -ENOLINK) {
|
||||
if (ret) {
|
||||
brcmf_dbg(ERROR, "dongle is not responding\n");
|
||||
brcmf_detach(dev);
|
||||
goto fail;
|
||||
|
@ -3972,7 +3972,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
|
||||
u8 *iovar_ie_buf;
|
||||
u8 *curr_ie_buf;
|
||||
u8 *mgmt_ie_buf = NULL;
|
||||
u32 mgmt_ie_buf_len = 0;
|
||||
int mgmt_ie_buf_len;
|
||||
u32 *mgmt_ie_len = 0;
|
||||
u32 del_add_ie_buf_len = 0;
|
||||
u32 total_ie_buf_len = 0;
|
||||
@ -3982,7 +3982,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
|
||||
struct parsed_vndr_ie_info *vndrie_info;
|
||||
s32 i;
|
||||
u8 *ptr;
|
||||
u32 remained_buf_len;
|
||||
int remained_buf_len;
|
||||
|
||||
WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag);
|
||||
iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
|
||||
@ -4606,12 +4606,13 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_cfg80211_profile *profile = cfg->profile;
|
||||
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
|
||||
struct wiphy *wiphy = cfg_to_wiphy(cfg);
|
||||
struct brcmf_channel_info_le channel_le;
|
||||
struct ieee80211_channel *notify_channel;
|
||||
struct ieee80211_channel *notify_channel = NULL;
|
||||
struct ieee80211_supported_band *band;
|
||||
struct brcmf_bss_info_le *bi;
|
||||
u32 freq;
|
||||
s32 err = 0;
|
||||
u32 target_channel;
|
||||
u8 *buf;
|
||||
|
||||
WL_TRACE("Enter\n");
|
||||
|
||||
@ -4619,11 +4620,22 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
|
||||
memcpy(profile->bssid, e->addr, ETH_ALEN);
|
||||
brcmf_update_bss_info(cfg);
|
||||
|
||||
brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
|
||||
sizeof(channel_le));
|
||||
buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
|
||||
if (buf == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
target_channel = le32_to_cpu(channel_le.target_channel);
|
||||
WL_CONN("Roamed to channel %d\n", target_channel);
|
||||
/* data sent to dongle has to be little endian */
|
||||
*(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
|
||||
err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
|
||||
|
||||
if (err)
|
||||
goto done;
|
||||
|
||||
bi = (struct brcmf_bss_info_le *)(buf + 4);
|
||||
target_channel = bi->ctl_ch ? bi->ctl_ch :
|
||||
CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
|
||||
|
||||
if (target_channel <= CH_MAX_2G_CHANNEL)
|
||||
band = wiphy->bands[IEEE80211_BAND_2GHZ];
|
||||
@ -4633,6 +4645,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
|
||||
freq = ieee80211_channel_to_frequency(target_channel, band->band);
|
||||
notify_channel = ieee80211_get_channel(wiphy, freq);
|
||||
|
||||
done:
|
||||
kfree(buf);
|
||||
cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid,
|
||||
conn_info->req_ie, conn_info->req_ie_len,
|
||||
conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
|
||||
@ -5186,41 +5200,6 @@ brcmf_cfg80211_event(struct net_device *ndev,
|
||||
schedule_work(&cfg->event_work);
|
||||
}
|
||||
|
||||
static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
|
||||
{
|
||||
s32 infra = 0;
|
||||
s32 err = 0;
|
||||
|
||||
switch (iftype) {
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
case NL80211_IFTYPE_WDS:
|
||||
WL_ERR("type (%d) : currently we do not support this mode\n",
|
||||
iftype);
|
||||
err = -EINVAL;
|
||||
return err;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
infra = 0;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
infra = 1;
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
infra = 1;
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
WL_ERR("invalid type (%d)\n", iftype);
|
||||
return err;
|
||||
}
|
||||
err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
|
||||
if (err) {
|
||||
WL_ERR("WLC_SET_INFRA error (%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
|
||||
{
|
||||
/* Room for "event_msgs" + '\0' + bitvec */
|
||||
@ -5439,7 +5418,8 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
|
||||
WL_BEACON_TIMEOUT);
|
||||
if (err)
|
||||
goto default_conf_out;
|
||||
err = brcmf_dongle_mode(ndev, wdev->iftype);
|
||||
err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
|
||||
NULL, NULL);
|
||||
if (err && err != -EINPROGRESS)
|
||||
goto default_conf_out;
|
||||
err = brcmf_dongle_probecap(cfg);
|
||||
|
@ -10472,7 +10472,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
|
||||
} else
|
||||
len = src->len;
|
||||
|
||||
dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC);
|
||||
dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC);
|
||||
if (!dst)
|
||||
continue;
|
||||
|
||||
|
@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
||||
* See iwlagn_mac_channel_switch.
|
||||
*/
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct iwl6000_channel_switch_cmd cmd;
|
||||
struct iwl6000_channel_switch_cmd *cmd;
|
||||
u32 switch_time_in_usec, ucode_switch_time;
|
||||
u16 ch;
|
||||
u32 tsf_low;
|
||||
@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif = ctx->vif;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = REPLY_CHANNEL_SWITCH,
|
||||
.len = { sizeof(cmd), },
|
||||
.len = { sizeof(*cmd), },
|
||||
.flags = CMD_SYNC,
|
||||
.data = { &cmd, },
|
||||
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
|
||||
};
|
||||
int err;
|
||||
|
||||
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
hcmd.data[0] = cmd;
|
||||
|
||||
cmd->band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
ch = ch_switch->channel->hw_value;
|
||||
IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
|
||||
ctx->active.channel, ch);
|
||||
cmd.channel = cpu_to_le16(ch);
|
||||
cmd.rxon_flags = ctx->staging.flags;
|
||||
cmd.rxon_filter_flags = ctx->staging.filter_flags;
|
||||
cmd->channel = cpu_to_le16(ch);
|
||||
cmd->rxon_flags = ctx->staging.flags;
|
||||
cmd->rxon_filter_flags = ctx->staging.filter_flags;
|
||||
switch_count = ch_switch->count;
|
||||
tsf_low = ch_switch->timestamp & 0x0ffffffff;
|
||||
/*
|
||||
@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
||||
switch_count = 0;
|
||||
}
|
||||
if (switch_count <= 1)
|
||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
else {
|
||||
switch_time_in_usec =
|
||||
vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
|
||||
ucode_switch_time = iwl_usecs_to_beacons(priv,
|
||||
switch_time_in_usec,
|
||||
beacon_interval);
|
||||
cmd.switch_time = iwl_add_beacon_time(priv,
|
||||
priv->ucode_beacon_time,
|
||||
ucode_switch_time,
|
||||
beacon_interval);
|
||||
cmd->switch_time = iwl_add_beacon_time(priv,
|
||||
priv->ucode_beacon_time,
|
||||
ucode_switch_time,
|
||||
beacon_interval);
|
||||
}
|
||||
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
|
||||
cmd.switch_time);
|
||||
cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
|
||||
cmd->switch_time);
|
||||
cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
|
||||
|
||||
return iwl_dvm_send_cmd(priv, &hcmd);
|
||||
err = iwl_dvm_send_cmd(priv, &hcmd);
|
||||
kfree(cmd);
|
||||
return err;
|
||||
}
|
||||
|
||||
struct iwl_lib_ops iwl6000_lib = {
|
||||
|
@ -1218,6 +1218,7 @@ struct cfg80211_deauth_request {
|
||||
const u8 *ie;
|
||||
size_t ie_len;
|
||||
u16 reason_code;
|
||||
bool local_state_change;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -32,6 +32,8 @@
|
||||
|
||||
#define SMP_TIMEOUT msecs_to_jiffies(30000)
|
||||
|
||||
#define AUTH_REQ_MASK 0x07
|
||||
|
||||
static inline void swap128(u8 src[16], u8 dst[16])
|
||||
{
|
||||
int i;
|
||||
@ -230,7 +232,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
|
||||
req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
|
||||
req->init_key_dist = 0;
|
||||
req->resp_key_dist = dist_keys;
|
||||
req->auth_req = authreq;
|
||||
req->auth_req = (authreq & AUTH_REQ_MASK);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -239,7 +241,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
|
||||
rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
|
||||
rsp->init_key_dist = 0;
|
||||
rsp->resp_key_dist = req->resp_key_dist & dist_keys;
|
||||
rsp->auth_req = authreq;
|
||||
rsp->auth_req = (authreq & AUTH_REQ_MASK);
|
||||
}
|
||||
|
||||
static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
|
||||
|
@ -853,7 +853,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
if (info->control.vif == &sdata->vif) {
|
||||
__skb_unlink(skb, &local->pending[i]);
|
||||
dev_kfree_skb_irq(skb);
|
||||
ieee80211_free_txskb(&local->hw, skb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3099,22 +3099,32 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
|
||||
ht_cfreq, ht_oper->primary_chan,
|
||||
cbss->channel->band);
|
||||
ht_oper = NULL;
|
||||
} else {
|
||||
channel_type = NL80211_CHAN_HT20;
|
||||
}
|
||||
}
|
||||
|
||||
if (ht_oper) {
|
||||
channel_type = NL80211_CHAN_HT20;
|
||||
if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
|
||||
/*
|
||||
* cfg80211 already verified that the channel itself can
|
||||
* be used, but it didn't check that we can do the right
|
||||
* HT type, so do that here as well. If HT40 isn't allowed
|
||||
* on this channel, disable 40 MHz operation.
|
||||
*/
|
||||
|
||||
if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
|
||||
switch (ht_oper->ht_param &
|
||||
IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
|
||||
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
|
||||
switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
|
||||
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
|
||||
if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS)
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
|
||||
else
|
||||
channel_type = NL80211_CHAN_HT40PLUS;
|
||||
break;
|
||||
case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
|
||||
break;
|
||||
case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
|
||||
if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS)
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
|
||||
else
|
||||
channel_type = NL80211_CHAN_HT40MINUS;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3549,6 +3559,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
||||
{
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
|
||||
bool tx = !req->local_state_change;
|
||||
|
||||
mutex_lock(&ifmgd->mtx);
|
||||
|
||||
@ -3565,12 +3576,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
||||
if (ifmgd->associated &&
|
||||
ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
|
||||
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
|
||||
req->reason_code, true, frame_buf);
|
||||
req->reason_code, tx, frame_buf);
|
||||
} else {
|
||||
drv_mgd_prepare_tx(sdata->local, sdata);
|
||||
ieee80211_send_deauth_disassoc(sdata, req->bssid,
|
||||
IEEE80211_STYPE_DEAUTH,
|
||||
req->reason_code, true,
|
||||
req->reason_code, tx,
|
||||
frame_buf);
|
||||
}
|
||||
|
||||
|
@ -650,7 +650,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local,
|
||||
*/
|
||||
if (!skb)
|
||||
break;
|
||||
dev_kfree_skb(skb);
|
||||
ieee80211_free_txskb(&local->hw, skb);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -679,7 +679,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local,
|
||||
local->total_ps_buffered--;
|
||||
ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n",
|
||||
sta->sta.addr);
|
||||
dev_kfree_skb(skb);
|
||||
ieee80211_free_txskb(&local->hw, skb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -406,7 +406,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
|
||||
int queue = info->hw_queue;
|
||||
|
||||
if (WARN_ON(!info->control.vif)) {
|
||||
kfree_skb(skb);
|
||||
ieee80211_free_txskb(&local->hw, skb);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -431,7 +431,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
if (WARN_ON(!info->control.vif)) {
|
||||
kfree_skb(skb);
|
||||
ieee80211_free_txskb(&local->hw, skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
|
||||
if (status->flag & RX_FLAG_MMIC_ERROR)
|
||||
goto mic_fail;
|
||||
|
||||
if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key)
|
||||
if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key &&
|
||||
rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
|
||||
goto update_iv;
|
||||
|
||||
return RX_CONTINUE;
|
||||
@ -545,14 +546,19 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
|
||||
|
||||
static void bip_aad(struct sk_buff *skb, u8 *aad)
|
||||
{
|
||||
__le16 mask_fc;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
|
||||
/* BIP AAD: FC(masked) || A1 || A2 || A3 */
|
||||
|
||||
/* FC type/subtype */
|
||||
aad[0] = skb->data[0];
|
||||
/* Mask FC Retry, PwrMgt, MoreData flags to zero */
|
||||
aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6));
|
||||
mask_fc = hdr->frame_control;
|
||||
mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM |
|
||||
IEEE80211_FCTL_MOREDATA);
|
||||
put_unaligned(mask_fc, (__le16 *) &aad[0]);
|
||||
/* A1 || A2 || A3 */
|
||||
memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN);
|
||||
memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN);
|
||||
}
|
||||
|
||||
|
||||
|
@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
|
||||
.reason_code = reason,
|
||||
.ie = ie,
|
||||
.ie_len = ie_len,
|
||||
.local_state_change = local_state_change,
|
||||
};
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
if (local_state_change) {
|
||||
if (wdev->current_bss &&
|
||||
ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
|
||||
cfg80211_unhold_bss(wdev->current_bss);
|
||||
cfg80211_put_bss(&wdev->current_bss->pub);
|
||||
wdev->current_bss = NULL;
|
||||
}
|
||||
|
||||
if (local_state_change && (!wdev->current_bss ||
|
||||
!ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rdev->ops->deauth(&rdev->wiphy, dev, &req);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user