Linux wireless drivers development
 help / color / mirror / Atom feed
From: "Emmanuel Grumbach" <egrumbach@gmail.com>
To: "Volker Braun" <vbraun@physics.upenn.edu>
Cc: "Tomas Winkler" <tomasw@gmail.com>,
	"Linux Wireless" <linux-wireless@vger.kernel.org>
Subject: Re: dynamic wep with mulitple keys
Date: Mon, 12 May 2008 12:13:49 +0300	[thread overview]
Message-ID: <8704f27d0805120213w197327b0r2fa490df1e5399d1@mail.gmail.com> (raw)
In-Reply-To: <8704f27d0805081149wa91072en32ce8912ba1a14ff@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 7349 bytes --]

here is the patch I promised last week, can you please try it ?
You might have some trouble to apply since my code base slightly
differs from yours.

--------------------------------

>From 860fe4a63b1e9be8047f1b2f37c9072e92df5a5b Mon Sep 17 00:00:00 2001
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Date: Mon, 12 May 2008 10:21:01 +0300
Subject: [PATCH] iwlwifi: code clean up in security

This patch cleans up code in security. This clean up uses the
new pointer to ieee80211_key_conf passed with the tx_control.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-sta.c      |   24 +++++++--------
 drivers/net/wireless/iwlwifi/iwl4965-base.c |   43 +++++++++------------------
 2 files changed, 25 insertions(+), 42 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c
b/drivers/net/wireless/iwlwifi/iwl-sta.c
index c8e468f..ab3e223 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -324,7 +324,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
 	unsigned long flags;

 	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
-	keyconf->hw_key_idx = keyconf->keyidx;
+	keyconf->hw_key_idx = 1;
 	priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;

 	spin_lock_irqsave(&priv->sta_lock, flags);
@@ -354,7 +354,6 @@ static int iwl_set_wep_dynamic_key_info(struct
iwl_priv *priv,
 	int ret;

 	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
-	keyconf->hw_key_idx = keyconf->keyidx;

 	key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
 	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
@@ -411,7 +410,6 @@ static int iwl_set_ccmp_dynamic_key_info(struct
iwl_priv *priv,
 		key_flags |= STA_KEY_MULTICAST_MSK;

 	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-	keyconf->hw_key_idx = keyconf->keyidx;

 	spin_lock_irqsave(&priv->sta_lock, flags);
 	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
@@ -449,12 +447,10 @@ static int iwl_set_tkip_dynamic_key_info(struct
iwl_priv *priv,

 	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-	keyconf->hw_key_idx = keyconf->keyidx;

 	spin_lock_irqsave(&priv->sta_lock, flags);

 	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
-	priv->stations[sta_id].keyinfo.conf = keyconf;
 	priv->stations[sta_id].keyinfo.keylen = 16;

 	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
@@ -483,7 +479,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
 	u16 key_flags;
 	u8 keyidx;

-	priv->key_mapping_key = 0;
+	priv->key_mapping_key--;

 	spin_lock_irqsave(&priv->sta_lock, flags);
 	key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
@@ -521,24 +517,26 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
 EXPORT_SYMBOL(iwl_remove_dynamic_key);

 int iwl_set_dynamic_key(struct iwl_priv *priv,
-				struct ieee80211_key_conf *key, u8 sta_id)
+				struct ieee80211_key_conf *keyconf, u8 sta_id)
 {
 	int ret;

-	priv->key_mapping_key = 1;
+	priv->key_mapping_key++;
+	priv->stations[sta_id].keyinfo.conf = keyconf;
+	keyconf->hw_key_idx = 0;

-	switch (key->alg) {
+	switch (keyconf->alg) {
 	case ALG_CCMP:
-		ret = iwl_set_ccmp_dynamic_key_info(priv, key, sta_id);
+		ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
 		break;
 	case ALG_TKIP:
-		ret = iwl_set_tkip_dynamic_key_info(priv, key, sta_id);
+		ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
 		break;
 	case ALG_WEP:
-		ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id);
+		ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id);
 		break;
 	default:
-		IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg);
+		IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
 		ret = -EINVAL;
 	}

diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c
b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 481e943..492fc63 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1466,16 +1466,13 @@ static void
iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
 				      struct sk_buff *skb_frag,
 				      int sta_id)
 {
-	struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
-	struct iwl_wep_key *wepkey;
 	int keyidx = 0;
+	struct ieee80211_key_conf *keyconf = ctl->hw_key;

-	BUG_ON(ctl->hw_key->hw_key_idx > 3);
-
-	switch (keyinfo->alg) {
+	switch (keyconf->alg) {
 	case ALG_CCMP:
 		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
-		memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
+		memcpy(cmd->cmd.tx.key, keyconf->key, keyconf->keylen);
 		if (ctl->flags & IEEE80211_TXCTL_AMPDU)
 			cmd->cmd.tx.tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
 		IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
@@ -1483,39 +1480,26 @@ static void
iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,

 	case ALG_TKIP:
 		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP;
-		ieee80211_get_tkip_key(keyinfo->conf, skb_frag,
+		ieee80211_get_tkip_key(keyconf, skb_frag,
 			IEEE80211_TKIP_P2_KEY, cmd->cmd.tx.key);
 		IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n");
 		break;

 	case ALG_WEP:
-		wepkey = &priv->wep_keys[ctl->hw_key->hw_key_idx];
-		cmd->cmd.tx.sec_ctl = 0;
-		if (priv->default_wep_key) {
-			/* the WEP key was sent as static */
-			keyidx = ctl->hw_key->hw_key_idx;
-			memcpy(&cmd->cmd.tx.key[3], wepkey->key,
-							wepkey->key_size);
-			if (wepkey->key_size == WEP_KEY_LEN_128)
-				cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
-		} else {
-			/* the WEP key was sent as dynamic */
-			keyidx = keyinfo->keyidx;
-			memcpy(&cmd->cmd.tx.key[3], keyinfo->key,
-							keyinfo->keylen);
-			if (keyinfo->keylen == WEP_KEY_LEN_128)
-				cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
-		}
+		cmd->cmd.tx.sec_ctl = (TX_CMD_SEC_WEP |
+			(keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);

-		cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP |
-			(keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
+		if (keyconf->keylen == WEP_KEY_LEN_128)
+			cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
+
+		memcpy(&cmd->cmd.tx.key[3], keyconf->key, keyconf->keylen);

 		IWL_DEBUG_TX("Configuring packet for WEP encryption "
 			     "with key %d\n", keyidx);
 		break;

 	default:
-		printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg);
+		printk(KERN_ERR "Unknown encode alg %d\n", keyconf->alg);
 		break;
 	}
 }
@@ -5579,11 +5563,11 @@ static int iwl4965_mac_set_key(struct
ieee80211_hw *hw, enum set_key_cmd cmd,
 		if (cmd == SET_KEY)
 			is_default_wep_key = !priv->key_mapping_key;
 		else
-			is_default_wep_key = priv->default_wep_key;
+			is_default_wep_key = key->hw_key_idx;
 	}
-
 	switch (cmd) {
 	case SET_KEY:
+		printk(KERN_ERR "Set key: static = %d, keyidx = %d sta = %d default
= %d\n", is_default_wep_key, key->keyidx, sta_id,
priv->key_mapping_key);
 		if (is_default_wep_key)
 			ret = iwl_set_default_wep_key(priv, key);
 		else
@@ -5592,6 +5576,7 @@ static int iwl4965_mac_set_key(struct
ieee80211_hw *hw, enum set_key_cmd cmd,
 		IWL_DEBUG_MAC80211("enable hwcrypto key\n");
 		break;
 	case DISABLE_KEY:
+		printk(KERN_ERR "Remove key: static = %d, keyidx = %d sta = %d
default = %d\n", is_default_wep_key, key->keyidx, sta_id,
priv->key_mapping_key);
 		if (is_default_wep_key)
 			ret = iwl_remove_default_wep_key(priv, key);
 		else
-- 
1.5.4.1



-- 
Emmanuel Grumbach
egrumbach@gmail.com

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-iwlwifi-code-clean-up-in-security.patch --]
[-- Type: text/x-patch; name=0001-iwlwifi-code-clean-up-in-security.patch, Size: 7142 bytes --]

From 860fe4a63b1e9be8047f1b2f37c9072e92df5a5b Mon Sep 17 00:00:00 2001
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Date: Mon, 12 May 2008 10:21:01 +0300
Subject: [PATCH] iwlwifi: code clean up in security

This patch cleans up code in security. This clean up uses the
new pointer to ieee80211_key_conf passed with the tx_control.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-sta.c      |   24 +++++++--------
 drivers/net/wireless/iwlwifi/iwl4965-base.c |   43 +++++++++------------------
 2 files changed, 25 insertions(+), 42 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index c8e468f..ab3e223 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -324,7 +324,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
 	unsigned long flags;
 
 	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
-	keyconf->hw_key_idx = keyconf->keyidx;
+	keyconf->hw_key_idx = 1;
 	priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
@@ -354,7 +354,6 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
 	int ret;
 
 	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
-	keyconf->hw_key_idx = keyconf->keyidx;
 
 	key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
 	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
@@ -411,7 +410,6 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
 		key_flags |= STA_KEY_MULTICAST_MSK;
 
 	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-	keyconf->hw_key_idx = keyconf->keyidx;
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
 	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
@@ -449,12 +447,10 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
 
 	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-	keyconf->hw_key_idx = keyconf->keyidx;
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
 
 	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
-	priv->stations[sta_id].keyinfo.conf = keyconf;
 	priv->stations[sta_id].keyinfo.keylen = 16;
 
 	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
@@ -483,7 +479,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
 	u16 key_flags;
 	u8 keyidx;
 
-	priv->key_mapping_key = 0;
+	priv->key_mapping_key--;
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
 	key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
@@ -521,24 +517,26 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
 EXPORT_SYMBOL(iwl_remove_dynamic_key);
 
 int iwl_set_dynamic_key(struct iwl_priv *priv,
-				struct ieee80211_key_conf *key, u8 sta_id)
+				struct ieee80211_key_conf *keyconf, u8 sta_id)
 {
 	int ret;
 
-	priv->key_mapping_key = 1;
+	priv->key_mapping_key++;
+	priv->stations[sta_id].keyinfo.conf = keyconf;
+	keyconf->hw_key_idx = 0;
 
-	switch (key->alg) {
+	switch (keyconf->alg) {
 	case ALG_CCMP:
-		ret = iwl_set_ccmp_dynamic_key_info(priv, key, sta_id);
+		ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
 		break;
 	case ALG_TKIP:
-		ret = iwl_set_tkip_dynamic_key_info(priv, key, sta_id);
+		ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
 		break;
 	case ALG_WEP:
-		ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id);
+		ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id);
 		break;
 	default:
-		IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg);
+		IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
 		ret = -EINVAL;
 	}
 
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 481e943..492fc63 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1466,16 +1466,13 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
 				      struct sk_buff *skb_frag,
 				      int sta_id)
 {
-	struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
-	struct iwl_wep_key *wepkey;
 	int keyidx = 0;
+	struct ieee80211_key_conf *keyconf = ctl->hw_key;
 
-	BUG_ON(ctl->hw_key->hw_key_idx > 3);
-
-	switch (keyinfo->alg) {
+	switch (keyconf->alg) {
 	case ALG_CCMP:
 		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
-		memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
+		memcpy(cmd->cmd.tx.key, keyconf->key, keyconf->keylen);
 		if (ctl->flags & IEEE80211_TXCTL_AMPDU)
 			cmd->cmd.tx.tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
 		IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
@@ -1483,39 +1480,26 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
 
 	case ALG_TKIP:
 		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP;
-		ieee80211_get_tkip_key(keyinfo->conf, skb_frag,
+		ieee80211_get_tkip_key(keyconf, skb_frag,
 			IEEE80211_TKIP_P2_KEY, cmd->cmd.tx.key);
 		IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n");
 		break;
 
 	case ALG_WEP:
-		wepkey = &priv->wep_keys[ctl->hw_key->hw_key_idx];
-		cmd->cmd.tx.sec_ctl = 0;
-		if (priv->default_wep_key) {
-			/* the WEP key was sent as static */
-			keyidx = ctl->hw_key->hw_key_idx;
-			memcpy(&cmd->cmd.tx.key[3], wepkey->key,
-							wepkey->key_size);
-			if (wepkey->key_size == WEP_KEY_LEN_128)
-				cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
-		} else {
-			/* the WEP key was sent as dynamic */
-			keyidx = keyinfo->keyidx;
-			memcpy(&cmd->cmd.tx.key[3], keyinfo->key,
-							keyinfo->keylen);
-			if (keyinfo->keylen == WEP_KEY_LEN_128)
-				cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
-		}
+		cmd->cmd.tx.sec_ctl = (TX_CMD_SEC_WEP |
+			(keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
 
-		cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP |
-			(keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
+		if (keyconf->keylen == WEP_KEY_LEN_128)
+			cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
+
+		memcpy(&cmd->cmd.tx.key[3], keyconf->key, keyconf->keylen);
 
 		IWL_DEBUG_TX("Configuring packet for WEP encryption "
 			     "with key %d\n", keyidx);
 		break;
 
 	default:
-		printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg);
+		printk(KERN_ERR "Unknown encode alg %d\n", keyconf->alg);
 		break;
 	}
 }
@@ -5579,11 +5563,11 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		if (cmd == SET_KEY)
 			is_default_wep_key = !priv->key_mapping_key;
 		else
-			is_default_wep_key = priv->default_wep_key;
+			is_default_wep_key = key->hw_key_idx;
 	}
-
 	switch (cmd) {
 	case SET_KEY:
+		printk(KERN_ERR "Set key: static = %d, keyidx = %d sta = %d default = %d\n", is_default_wep_key, key->keyidx, sta_id, priv->key_mapping_key);
 		if (is_default_wep_key)
 			ret = iwl_set_default_wep_key(priv, key);
 		else
@@ -5592,6 +5576,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		IWL_DEBUG_MAC80211("enable hwcrypto key\n");
 		break;
 	case DISABLE_KEY:
+		printk(KERN_ERR "Remove key: static = %d, keyidx = %d sta = %d default = %d\n", is_default_wep_key, key->keyidx, sta_id, priv->key_mapping_key);
 		if (is_default_wep_key)
 			ret = iwl_remove_default_wep_key(priv, key);
 		else
-- 
1.5.4.1


  reply	other threads:[~2008-05-12  9:13 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-23 16:52 dynamic wep with mulitple keys Volker Braun
2008-04-23 17:15 ` Tomas Winkler
2008-05-05 14:36   ` Emmanuel Grumbach
     [not found]   ` <8704f27d0805050735s647ac4aaq469630bde6bc341e@mail.gmail.com>
2008-05-05 15:58     ` Volker Braun
2008-05-06  6:46       ` Emmanuel Grumbach
2008-05-06  7:22         ` drago01
2008-05-06  7:32           ` Emmanuel Grumbach
2008-05-06 12:10             ` drago01
2008-05-06 12:14               ` Emmanuel Grumbach
2008-05-12 11:47                 ` drago01
2008-05-12 12:07                   ` Tomas Winkler
2008-05-12 12:10                     ` drago01
2008-05-12 12:22                       ` Tomas Winkler
2008-05-12 12:38                         ` drago01
2008-05-13  9:24                           ` Johannes Berg
2008-05-13  9:44                             ` drago01
2008-05-13 10:07                               ` Johannes Berg
2008-05-13 10:13                                 ` drago01
2008-05-13 10:18                                   ` Johannes Berg
2008-05-08 18:31         ` Volker Braun
2008-05-08 18:49           ` Emmanuel Grumbach
2008-05-12  9:13             ` Emmanuel Grumbach [this message]
2008-05-12 11:55               ` Emmanuel Grumbach
2008-05-13 13:53               ` Volker Braun
2008-05-13 14:06                 ` Emmanuel Grumbach
2008-05-13 14:15                   ` Tomas Winkler
2008-05-05 16:04 ` Emmanuel Grumbach
  -- strict thread matches above, loose matches on Subject: below --
2008-03-31 19:37 drago01

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8704f27d0805120213w197327b0r2fa490df1e5399d1@mail.gmail.com \
    --to=egrumbach@gmail.com \
    --cc=linux-wireless@vger.kernel.org \
    --cc=tomasw@gmail.com \
    --cc=vbraun@physics.upenn.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox