|
@@ -36,22 +36,22 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
|
|
|
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb);
|
|
|
struct ieee80211_tx_info *rts_info;
|
|
|
struct sk_buff *skb;
|
|
|
- int size;
|
|
|
+ unsigned int data_length;
|
|
|
int retval = 0;
|
|
|
|
|
|
if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
|
|
|
- size = sizeof(struct ieee80211_cts);
|
|
|
+ data_length = sizeof(struct ieee80211_cts);
|
|
|
else
|
|
|
- size = sizeof(struct ieee80211_rts);
|
|
|
+ data_length = sizeof(struct ieee80211_rts);
|
|
|
|
|
|
- skb = dev_alloc_skb(size + rt2x00dev->hw->extra_tx_headroom);
|
|
|
+ skb = dev_alloc_skb(data_length + rt2x00dev->hw->extra_tx_headroom);
|
|
|
if (unlikely(!skb)) {
|
|
|
WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n");
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom);
|
|
|
- skb_put(skb, size);
|
|
|
+ skb_put(skb, data_length);
|
|
|
|
|
|
/*
|
|
|
* Copy TX information over from original frame to
|
|
@@ -64,7 +64,6 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
|
|
|
*/
|
|
|
memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb));
|
|
|
rts_info = IEEE80211_SKB_CB(skb);
|
|
|
- rts_info->control.hw_key = NULL;
|
|
|
rts_info->flags &= ~IEEE80211_TX_CTL_USE_RTS_CTS;
|
|
|
rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT;
|
|
|
rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS;
|
|
@@ -74,13 +73,24 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
|
|
|
else
|
|
|
rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
|
|
|
|
|
|
+ skb->do_not_encrypt = 1;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * RTS/CTS frame should use the length of the frame plus any
|
|
|
+ * encryption overhead that will be added by the hardware.
|
|
|
+ */
|
|
|
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
|
|
|
+ if (!frag_skb->do_not_encrypt)
|
|
|
+ data_length += rt2x00crypto_tx_overhead(tx_info);
|
|
|
+#endif /* CONFIG_RT2X00_LIB_CRYPTO */
|
|
|
+
|
|
|
if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
|
|
|
ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif,
|
|
|
- frag_skb->data, size, tx_info,
|
|
|
+ frag_skb->data, data_length, tx_info,
|
|
|
(struct ieee80211_cts *)(skb->data));
|
|
|
else
|
|
|
ieee80211_rts_get(rt2x00dev->hw, tx_info->control.vif,
|
|
|
- frag_skb->data, size, tx_info,
|
|
|
+ frag_skb->data, data_length, tx_info,
|
|
|
(struct ieee80211_rts *)(skb->data));
|
|
|
|
|
|
retval = rt2x00queue_write_tx_frame(queue, skb);
|
|
@@ -464,6 +474,90 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
|
|
|
|
|
|
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
|
|
|
+int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
|
+ const u8 *local_address, const u8 *address,
|
|
|
+ struct ieee80211_key_conf *key)
|
|
|
+{
|
|
|
+ struct rt2x00_dev *rt2x00dev = hw->priv;
|
|
|
+ int (*set_key) (struct rt2x00_dev *rt2x00dev,
|
|
|
+ struct rt2x00lib_crypto *crypto,
|
|
|
+ struct ieee80211_key_conf *key);
|
|
|
+ struct rt2x00lib_crypto crypto;
|
|
|
+
|
|
|
+ if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ else if (key->keylen > 32)
|
|
|
+ return -ENOSPC;
|
|
|
+
|
|
|
+ memset(&crypto, 0, sizeof(crypto));
|
|
|
+
|
|
|
+ /*
|
|
|
+ * When in STA mode, bssidx is always 0 otherwise local_address[5]
|
|
|
+ * contains the bss number, see BSS_ID_MASK comments for details.
|
|
|
+ */
|
|
|
+ if (rt2x00dev->intf_sta_count)
|
|
|
+ crypto.bssidx = 0;
|
|
|
+ else
|
|
|
+ crypto.bssidx =
|
|
|
+ local_address[5] & (rt2x00dev->ops->max_ap_intf - 1);
|
|
|
+
|
|
|
+ crypto.cipher = rt2x00crypto_key_to_cipher(key);
|
|
|
+ if (crypto.cipher == CIPHER_NONE)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ crypto.cmd = cmd;
|
|
|
+ crypto.address = address;
|
|
|
+
|
|
|
+ if (crypto.cipher == CIPHER_TKIP) {
|
|
|
+ if (key->keylen > NL80211_TKIP_DATA_OFFSET_ENCR_KEY)
|
|
|
+ memcpy(&crypto.key,
|
|
|
+ &key->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY],
|
|
|
+ sizeof(crypto.key));
|
|
|
+
|
|
|
+ if (key->keylen > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
|
|
|
+ memcpy(&crypto.tx_mic,
|
|
|
+ &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
|
|
|
+ sizeof(crypto.tx_mic));
|
|
|
+
|
|
|
+ if (key->keylen > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY)
|
|
|
+ memcpy(&crypto.rx_mic,
|
|
|
+ &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
|
|
|
+ sizeof(crypto.rx_mic));
|
|
|
+ } else
|
|
|
+ memcpy(&crypto.key, &key->key[0], key->keylen);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Each BSS has a maximum of 4 shared keys.
|
|
|
+ * Shared key index values:
|
|
|
+ * 0) BSS0 key0
|
|
|
+ * 1) BSS0 key1
|
|
|
+ * ...
|
|
|
+ * 4) BSS1 key0
|
|
|
+ * ...
|
|
|
+ * 8) BSS2 key0
|
|
|
+ * ...
|
|
|
+ * Both pairwise as shared key indeces are determined by
|
|
|
+ * driver. This is required because the hardware requires
|
|
|
+ * keys to be assigned in correct order (When key 1 is
|
|
|
+ * provided but key 0 is not, then the key is not found
|
|
|
+ * by the hardware during RX).
|
|
|
+ */
|
|
|
+ key->hw_key_idx = 0;
|
|
|
+
|
|
|
+ if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
|
|
|
+ set_key = rt2x00dev->ops->lib->config_pairwise_key;
|
|
|
+ else
|
|
|
+ set_key = rt2x00dev->ops->lib->config_shared_key;
|
|
|
+
|
|
|
+ if (!set_key)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ return set_key(rt2x00dev, &crypto, key);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
|
|
|
+#endif /* CONFIG_RT2X00_LIB_CRYPTO */
|
|
|
+
|
|
|
int rt2x00mac_get_stats(struct ieee80211_hw *hw,
|
|
|
struct ieee80211_low_level_stats *stats)
|
|
|
{
|