diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ipw2200.c | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index d417ed7af7c1..c9b306a8116c 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c | |||
@@ -5771,7 +5771,8 @@ static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) | |||
5771 | DCT_FLAG_EXT_SECURITY_CCM, | 5771 | DCT_FLAG_EXT_SECURITY_CCM, |
5772 | priv->ieee->sec.active_key); | 5772 | priv->ieee->sec.active_key); |
5773 | 5773 | ||
5774 | ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_CCM); | 5774 | if (!priv->ieee->host_mc_decrypt) |
5775 | ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_CCM); | ||
5775 | break; | 5776 | break; |
5776 | case SEC_LEVEL_2: | 5777 | case SEC_LEVEL_2: |
5777 | if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) | 5778 | if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) |
@@ -5786,9 +5787,6 @@ static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) | |||
5786 | default: | 5787 | default: |
5787 | break; | 5788 | break; |
5788 | } | 5789 | } |
5789 | |||
5790 | ipw_set_hw_decrypt_unicast(priv, priv->ieee->sec.level); | ||
5791 | ipw_set_hw_decrypt_multicast(priv, priv->ieee->sec.level); | ||
5792 | } | 5790 | } |
5793 | 5791 | ||
5794 | static void ipw_adhoc_check(void *data) | 5792 | static void ipw_adhoc_check(void *data) |
@@ -6473,6 +6471,7 @@ static int ipw_wpa_set_encryption(struct net_device *dev, | |||
6473 | struct ipw_param *param, int param_len) | 6471 | struct ipw_param *param, int param_len) |
6474 | { | 6472 | { |
6475 | int ret = 0; | 6473 | int ret = 0; |
6474 | int group_key = 0; | ||
6476 | struct ipw_priv *priv = ieee80211_priv(dev); | 6475 | struct ipw_priv *priv = ieee80211_priv(dev); |
6477 | struct ieee80211_device *ieee = priv->ieee; | 6476 | struct ieee80211_device *ieee = priv->ieee; |
6478 | struct ieee80211_crypto_ops *ops; | 6477 | struct ieee80211_crypto_ops *ops; |
@@ -6502,6 +6501,9 @@ static int ipw_wpa_set_encryption(struct net_device *dev, | |||
6502 | return -EINVAL; | 6501 | return -EINVAL; |
6503 | } | 6502 | } |
6504 | 6503 | ||
6504 | if (param->u.crypt.idx != 0) | ||
6505 | group_key = 1; | ||
6506 | |||
6505 | sec.flags |= SEC_ENABLED | SEC_ENCRYPT; | 6507 | sec.flags |= SEC_ENABLED | SEC_ENCRYPT; |
6506 | if (strcmp(param->u.crypt.alg, "none") == 0) { | 6508 | if (strcmp(param->u.crypt.alg, "none") == 0) { |
6507 | if (crypt) { | 6509 | if (crypt) { |
@@ -6517,11 +6519,19 @@ static int ipw_wpa_set_encryption(struct net_device *dev, | |||
6517 | sec.encrypt = 1; | 6519 | sec.encrypt = 1; |
6518 | 6520 | ||
6519 | /* IPW HW cannot build TKIP MIC, host decryption still needed. */ | 6521 | /* IPW HW cannot build TKIP MIC, host decryption still needed. */ |
6520 | if (strcmp(param->u.crypt.alg, "TKIP") == 0) | 6522 | if (strcmp(param->u.crypt.alg, "TKIP") == 0) { |
6521 | ieee->host_encrypt_msdu = 1; | 6523 | if (group_key) |
6524 | ieee->host_mc_decrypt = 1; | ||
6525 | else | ||
6526 | ieee->host_encrypt_msdu = 1; | ||
6527 | } | ||
6522 | 6528 | ||
6523 | if (!(ieee->host_encrypt || ieee->host_encrypt_msdu || | 6529 | /*if (!(ieee->host_encrypt || ieee->host_encrypt_msdu || |
6524 | ieee->host_decrypt)) | 6530 | ieee->host_decrypt)) |
6531 | goto skip_host_crypt; */ | ||
6532 | if (group_key ? !ieee->host_mc_decrypt : | ||
6533 | !(ieee->host_encrypt || ieee->host_decrypt || | ||
6534 | ieee->host_encrypt_msdu)) | ||
6525 | goto skip_host_crypt; | 6535 | goto skip_host_crypt; |
6526 | 6536 | ||
6527 | ops = ieee80211_get_crypto_ops(param->u.crypt.alg); | 6537 | ops = ieee80211_get_crypto_ops(param->u.crypt.alg); |
@@ -6604,6 +6614,9 @@ static int ipw_wpa_set_encryption(struct net_device *dev, | |||
6604 | sec.flags |= SEC_LEVEL; | 6614 | sec.flags |= SEC_LEVEL; |
6605 | sec.level = SEC_LEVEL_3; | 6615 | sec.level = SEC_LEVEL_3; |
6606 | } | 6616 | } |
6617 | /* Don't set sec level for group keys. */ | ||
6618 | if (group_key) | ||
6619 | sec.flags &= ~SEC_LEVEL; | ||
6607 | } | 6620 | } |
6608 | done: | 6621 | done: |
6609 | if (ieee->set_security) | 6622 | if (ieee->set_security) |
@@ -6953,15 +6966,21 @@ static int ipw_wx_set_encodeext(struct net_device *dev, | |||
6953 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | 6966 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; |
6954 | 6967 | ||
6955 | if (hwcrypto) { | 6968 | if (hwcrypto) { |
6956 | /* IPW HW can't build TKIP MIC, host decryption still needed */ | ||
6957 | if (ext->alg == IW_ENCODE_ALG_TKIP) { | 6969 | if (ext->alg == IW_ENCODE_ALG_TKIP) { |
6958 | priv->ieee->host_encrypt = 0; | 6970 | /* IPW HW can't build TKIP MIC, |
6959 | priv->ieee->host_encrypt_msdu = 1; | 6971 | host decryption still needed */ |
6960 | priv->ieee->host_decrypt = 1; | 6972 | if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) |
6973 | priv->ieee->host_mc_decrypt = 1; | ||
6974 | else { | ||
6975 | priv->ieee->host_encrypt = 0; | ||
6976 | priv->ieee->host_encrypt_msdu = 1; | ||
6977 | priv->ieee->host_decrypt = 1; | ||
6978 | } | ||
6961 | } else { | 6979 | } else { |
6962 | priv->ieee->host_encrypt = 0; | 6980 | priv->ieee->host_encrypt = 0; |
6963 | priv->ieee->host_encrypt_msdu = 0; | 6981 | priv->ieee->host_encrypt_msdu = 0; |
6964 | priv->ieee->host_decrypt = 0; | 6982 | priv->ieee->host_decrypt = 0; |
6983 | priv->ieee->host_mc_decrypt = 0; | ||
6965 | } | 6984 | } |
6966 | } | 6985 | } |
6967 | 6986 | ||
@@ -7878,6 +7897,7 @@ static void ipw_handle_data_packet(struct ipw_priv *priv, | |||
7878 | struct ipw_rx_mem_buffer *rxb, | 7897 | struct ipw_rx_mem_buffer *rxb, |
7879 | struct ieee80211_rx_stats *stats) | 7898 | struct ieee80211_rx_stats *stats) |
7880 | { | 7899 | { |
7900 | struct ieee80211_hdr_4addr *hdr; | ||
7881 | struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; | 7901 | struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; |
7882 | 7902 | ||
7883 | /* We received data from the HW, so stop the watchdog */ | 7903 | /* We received data from the HW, so stop the watchdog */ |
@@ -7907,7 +7927,10 @@ static void ipw_handle_data_packet(struct ipw_priv *priv, | |||
7907 | IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); | 7927 | IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); |
7908 | 7928 | ||
7909 | /* HW decrypt will not clear the WEP bit, MIC, PN, etc. */ | 7929 | /* HW decrypt will not clear the WEP bit, MIC, PN, etc. */ |
7910 | if (!priv->ieee->host_decrypt && priv->ieee->iw_mode != IW_MODE_MONITOR) | 7930 | hdr = (struct ieee80211_hdr_4addr *)rxb->skb->data; |
7931 | if (priv->ieee->iw_mode != IW_MODE_MONITOR && | ||
7932 | (is_multicast_ether_addr(hdr->addr1) ? | ||
7933 | !priv->ieee->host_mc_decrypt : !priv->ieee->host_decrypt)) | ||
7911 | ipw_rebuild_decrypted_skb(priv, rxb->skb); | 7934 | ipw_rebuild_decrypted_skb(priv, rxb->skb); |
7912 | 7935 | ||
7913 | if (!ieee80211_rx(priv->ieee, rxb->skb, stats)) | 7936 | if (!ieee80211_rx(priv->ieee, rxb->skb, stats)) |
@@ -8508,6 +8531,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init) | |||
8508 | priv->ieee->host_encrypt = 0; | 8531 | priv->ieee->host_encrypt = 0; |
8509 | priv->ieee->host_encrypt_msdu = 0; | 8532 | priv->ieee->host_encrypt_msdu = 0; |
8510 | priv->ieee->host_decrypt = 0; | 8533 | priv->ieee->host_decrypt = 0; |
8534 | priv->ieee->host_mc_decrypt = 0; | ||
8511 | } | 8535 | } |
8512 | IPW_DEBUG_INFO("Hardware crypto [%s]\n", hwcrypto ? "on" : "off"); | 8536 | IPW_DEBUG_INFO("Hardware crypto [%s]\n", hwcrypto ? "on" : "off"); |
8513 | 8537 | ||