[PATCH] ieee80211: Mixed PTK/GTK CCMP/TKIP support

tree 5c7559a1216ae1121487f6aed94a6017490729b3
parent c1ff4c22e5622c8987bf96c09158c4924cde98c2
author Hong Liu <hong.liu@intel.com> 1125482767 +0800
committer James Ketrenos <jketreno@linux.intel.com> 1127314427 -0500

Mixed PTK/GTK CCMP/TKIP support.

Signed-off-by: Hong Liu <hong.liu@intel.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 931737e..ef85a96 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -851,6 +851,9 @@
 	int host_encrypt;
 	int host_encrypt_msdu;
 	int host_decrypt;
+	/* host performs multicast decryption */
+	int host_mc_decrypt;
+
 	int host_open_frag;
 	int ieee802_1x;		/* is IEEE 802.1X used */
 
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index dddc616..941f1a1 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -133,6 +133,8 @@
 	/* Default to enabling full open WEP with host based encrypt/decrypt */
 	ieee->host_encrypt = 1;
 	ieee->host_decrypt = 1;
+	ieee->host_mc_decrypt = 1;
+
 	/* Host fragementation in Open mode. Default is enabled.
 	 * Note: host fragmentation is always enabled if host encryption
 	 * is enabled. For cards can do hardware encryption, they must do
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 8bcdbab..65315bc 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -409,7 +409,8 @@
 		return 1;
 	}
 
-	if (ieee->host_decrypt) {
+	if (is_multicast_ether_addr(hdr->addr1) ? ieee->host_mc_decrypt :
+	    ieee->host_decrypt) {
 		int idx = 0;
 		if (skb->len >= hdrlen + 3)
 			idx = skb->data[hdrlen + 3] >> 6;
@@ -1066,7 +1067,7 @@
 	network->flags = 0;
 	network->atim_window = 0;
 	network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
-		0x3 : 0x0;
+	    0x3 : 0x0;
 
 	if (stats->freq == IEEE80211_52GHZ_BAND) {
 		/* for A band (No DS info) */
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index db66217..d710f47 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -493,6 +493,7 @@
 	struct iw_point *encoding = &wrqu->encoding;
 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
 	int i, idx, ret = 0;
+	int group_key = 0;
 	const char *alg, *module;
 	struct ieee80211_crypto_ops *ops;
 	struct ieee80211_crypt_data **crypt;
@@ -509,9 +510,10 @@
 	} else
 		idx = ieee->tx_keyidx;
 
-	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
 		crypt = &ieee->crypt[idx];
-	else {
+		group_key = 1;
+	} else {
 		if (idx != 0)
 			return -EINVAL;
 		if (ieee->iw_mode == IW_MODE_INFRA)
@@ -542,7 +544,9 @@
 	sec.enabled = 1;
 	sec.encrypt = 1;
 
-	if (!(ieee->host_encrypt || ieee->host_decrypt))
+	if (group_key ? !ieee->host_mc_decrypt :
+	    !(ieee->host_encrypt || ieee->host_decrypt ||
+	      ieee->host_encrypt_msdu))
 		goto skip_host_crypt;
 
 	switch (ext->alg) {
@@ -632,6 +636,9 @@
 			sec.flags |= SEC_LEVEL;
 			sec.level = SEC_LEVEL_3;
 		}
+		/* Don't set sec level for group keys. */
+		if (group_key)
+			sec.flags &= ~SEC_LEVEL;
 	}
       done:
 	if (ieee->set_security)