From: Samuel Ortiz <samuel@sortiz.org>
To: Johannes Berg <johannes@sipsolutions.net>
Cc: linux-wireless <linux-wireless@vger.kernel.org>,
Ivo van Doorn <ivdoorn@gmail.com>, Chr <chunkeey@web.de>,
Tomas Winkler <tomasw@gmail.com>,
"Luis R. Rodriguez" <mcgrof@gmail.com>,
Nick Kossifidis <mickflemm@gmail.com>,
Bob Copeland <me@bobcopeland.com>, Michael Buesch <mb@bu3sch.de>,
Sujith Manoharan <Sujith.Manoharan@atheros.com>,
Kalle Valo <kalle.valo@nokia.com>
Subject: Re: [RFT] mac80211: clean up set_key callback
Date: Tue, 9 Dec 2008 11:38:18 +0100 [thread overview]
Message-ID: <20081209103818.GA2595@sortiz.org> (raw)
In-Reply-To: <1228757035.22164.94.camel@johannes.berg>
On Mon, Dec 08, 2008 at 06:23:55PM +0100, Johannes Berg wrote:
> The set_key callback now seems rather odd, passing a MAC address
> instead of a station struct, and a local address instead of a
> vif struct. Change that.
Seems to work for iwl3945, thanks.
Cheers,
Samuel.
> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> ---
> That all-zeroes vs. all-ones for group/tx-only keys was confusing and is
> removed, this could possibly affect drivers that support multi-BSS
> operation.
>
> iwlwifi said:
>
> if (is_zero_ether_addr(addr))
> /* only support pairwise keys */
> return -EOPNOTSUPP;
>
> but the comment is obviously wrong since we used to pass in all-ones for
> the address for group keys, so it did support them. Change this
> accordingly, and ignore the multi-BSS case since iwlwifi doesn't support
> AP operation at all.
>
> drivers/net/wireless/ath5k/base.c | 9 ++--
> drivers/net/wireless/ath9k/main.c | 20 ++++------
> drivers/net/wireless/b43/main.c | 18 ++++-----
> drivers/net/wireless/iwlwifi/iwl-agn.c | 10 +++--
> drivers/net/wireless/iwlwifi/iwl3945-base.c | 12 +++---
> drivers/net/wireless/p54/p54common.c | 6 +--
> drivers/net/wireless/rt2x00/rt2x00.h | 2 -
> drivers/net/wireless/rt2x00/rt2x00mac.c | 14 +++----
> include/net/mac80211.h | 20 ++++------
> net/mac80211/key.c | 53 ++++++++++++++--------------
> 10 files changed, 80 insertions(+), 84 deletions(-)
>
> --- everything.orig/include/net/mac80211.h 2008-12-08 17:25:24.000000000 +0100
> +++ everything/include/net/mac80211.h 2008-12-08 17:58:51.000000000 +0100
> @@ -710,8 +710,8 @@ enum ieee80211_key_flags {
> * - Temporal Encryption Key (128 bits)
> * - Temporal Authenticator Tx MIC Key (64 bits)
> * - Temporal Authenticator Rx MIC Key (64 bits)
> - * @icv_len: FIXME
> - * @iv_len: FIXME
> + * @icv_len: The ICV length for this key type
> + * @iv_len: The IV length for this key type
> */
> struct ieee80211_key_conf {
> enum ieee80211_key_alg alg;
> @@ -1017,16 +1017,12 @@ ieee80211_get_alt_retry_rate(const struc
> *
> * The set_key() callback in the &struct ieee80211_ops for a given
> * device is called to enable hardware acceleration of encryption and
> - * decryption. The callback takes an @address parameter that will be
> - * the broadcast address for default keys, the other station's hardware
> - * address for individual keys or the zero address for keys that will
> - * be used only for transmission.
> + * decryption. The callback takes a @sta parameter that will be NULL
> + * for default keys or keys used for transmission only, or point to
> + * the station information for the peer for individual keys.
> * Multiple transmission keys with the same key index may be used when
> * VLANs are configured for an access point.
> *
> - * The @local_address parameter will always be set to our own address,
> - * this is only relevant if you support multiple local addresses.
> - *
> * When transmitting, the TX control data will use the @hw_key_idx
> * selected by the driver by modifying the &struct ieee80211_key_conf
> * pointed to by the @key parameter to the set_key() function.
> @@ -1231,8 +1227,8 @@ enum ieee80211_ampdu_mlme_action {
> *
> * @set_key: See the section "Hardware crypto acceleration"
> * This callback can sleep, and is only called between add_interface
> - * and remove_interface calls, i.e. while the interface with the
> - * given local_address is enabled.
> + * and remove_interface calls, i.e. while the given virtual interface
> + * is enabled.
> *
> * @update_tkip_key: See the section "Hardware crypto acceleration"
> * This callback will be called in the context of Rx. Called for drivers
> @@ -1311,7 +1307,7 @@ struct ieee80211_ops {
> int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
> bool set);
> int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
> - const u8 *local_address, const u8 *address,
> + struct ieee80211_vif *vif, struct ieee80211_sta *sta,
> struct ieee80211_key_conf *key);
> void (*update_tkip_key)(struct ieee80211_hw *hw,
> struct ieee80211_key_conf *conf, const u8 *address,
> --- everything.orig/net/mac80211/key.c 2008-12-08 17:26:21.000000000 +0100
> +++ everything/net/mac80211/key.c 2008-12-08 17:38:32.000000000 +0100
> @@ -47,7 +47,6 @@
> */
>
> static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
> -static const u8 zero_addr[ETH_ALEN];
>
> /* key mutex: used to synchronise todo runners */
> static DEFINE_MUTEX(key_mutex);
> @@ -108,29 +107,18 @@ static void assert_key_lock(void)
> WARN_ON(!mutex_is_locked(&key_mutex));
> }
>
> -static const u8 *get_mac_for_key(struct ieee80211_key *key)
> +static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
> {
> - const u8 *addr = bcast_addr;
> -
> - /*
> - * If we're an AP we won't ever receive frames with a non-WEP
> - * group key so we tell the driver that by using the zero MAC
> - * address to indicate a transmit-only key.
> - */
> - if (key->conf.alg != ALG_WEP &&
> - (key->sdata->vif.type == NL80211_IFTYPE_AP ||
> - key->sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
> - addr = zero_addr;
> -
> if (key->sta)
> - addr = key->sta->sta.addr;
> + return &key->sta->sta;
>
> - return addr;
> + return NULL;
> }
>
> static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
> {
> - const u8 *addr;
> + struct ieee80211_sub_if_data *sdata;
> + struct ieee80211_sta *sta;
> int ret;
> DECLARE_MAC_BUF(mac);
>
> @@ -140,11 +128,16 @@ static void ieee80211_key_enable_hw_acce
> if (!key->local->ops->set_key)
> return;
>
> - addr = get_mac_for_key(key);
> + sta = get_sta_for_key(key);
> +
> + sdata = key->sdata;
> + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
> + sdata = container_of(sdata->bss,
> + struct ieee80211_sub_if_data,
> + u.ap);
>
> ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY,
> - key->sdata->dev->dev_addr, addr,
> - &key->conf);
> + &sdata->vif, sta, &key->conf);
>
> if (!ret) {
> spin_lock(&todo_lock);
> @@ -156,12 +149,14 @@ static void ieee80211_key_enable_hw_acce
> printk(KERN_ERR "mac80211-%s: failed to set key "
> "(%d, %s) to hardware (%d)\n",
> wiphy_name(key->local->hw.wiphy),
> - key->conf.keyidx, print_mac(mac, addr), ret);
> + key->conf.keyidx,
> + print_mac(mac, sta ? sta->addr : bcast_addr), ret);
> }
>
> static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
> {
> - const u8 *addr;
> + struct ieee80211_sub_if_data *sdata;
> + struct ieee80211_sta *sta;
> int ret;
> DECLARE_MAC_BUF(mac);
>
> @@ -178,17 +173,23 @@ static void ieee80211_key_disable_hw_acc
> }
> spin_unlock(&todo_lock);
>
> - addr = get_mac_for_key(key);
> + sta = get_sta_for_key(key);
> + sdata = key->sdata;
> +
> + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
> + sdata = container_of(sdata->bss,
> + struct ieee80211_sub_if_data,
> + u.ap);
>
> ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY,
> - key->sdata->dev->dev_addr, addr,
> - &key->conf);
> + &sdata->vif, sta, &key->conf);
>
> if (ret)
> printk(KERN_ERR "mac80211-%s: failed to remove key "
> "(%d, %s) from hardware (%d)\n",
> wiphy_name(key->local->hw.wiphy),
> - key->conf.keyidx, print_mac(mac, addr), ret);
> + key->conf.keyidx,
> + print_mac(mac, sta ? sta->addr : bcast_addr), ret);
>
> spin_lock(&todo_lock);
> key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
> --- everything.orig/drivers/net/wireless/ath5k/base.c 2008-12-08 17:39:05.000000000 +0100
> +++ everything/drivers/net/wireless/ath5k/base.c 2008-12-08 17:41:03.000000000 +0100
> @@ -232,7 +232,7 @@ static void ath5k_configure_filter(struc
> int mc_count, struct dev_mc_list *mclist);
> static int ath5k_set_key(struct ieee80211_hw *hw,
> enum set_key_cmd cmd,
> - const u8 *local_addr, const u8 *addr,
> + struct ieee80211_vif *vif, struct ieee80211_sta *sta,
> struct ieee80211_key_conf *key);
> static int ath5k_get_stats(struct ieee80211_hw *hw,
> struct ieee80211_low_level_stats *stats);
> @@ -2986,8 +2986,8 @@ static void ath5k_configure_filter(struc
>
> static int
> ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
> - const u8 *local_addr, const u8 *addr,
> - struct ieee80211_key_conf *key)
> + struct ieee80211_vif *vif, struct ieee80211_sta *sta,
> + struct ieee80211_key_conf *key)
> {
> struct ath5k_softc *sc = hw->priv;
> int ret = 0;
> @@ -3010,7 +3010,8 @@ ath5k_set_key(struct ieee80211_hw *hw, e
>
> switch (cmd) {
> case SET_KEY:
> - ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, addr);
> + ret = ath5k_hw_set_key(sc->ah, key->keyidx, key,
> + sta ? sta->addr : NULL);
> if (ret) {
> ATH5K_ERR(sc, "can't set the key\n");
> goto unlock;
> --- everything.orig/drivers/net/wireless/ath9k/main.c 2008-12-08 17:41:24.000000000 +0100
> +++ everything/drivers/net/wireless/ath9k/main.c 2008-12-08 18:10:07.000000000 +0100
> @@ -724,9 +724,10 @@ static int ath_key_config(struct ath_sof
> {
> struct ieee80211_vif *vif;
> struct ath9k_keyval hk;
> - const u8 *mac = NULL;
> int ret = 0;
> enum nl80211_iftype opmode;
> + static const u8 bcast_addr[ETH_ALEN] =
> + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
>
> memset(&hk, 0, sizeof(hk));
>
> @@ -767,29 +768,26 @@ static int ath_key_config(struct ath_sof
> * BUT we will plumb a cleartext key so that we can do
> * per-Sta default key table lookup in software.
> */
> - if (is_broadcast_ether_addr(addr)) {
> + if (!addr) {
> switch (opmode) {
> case NL80211_IFTYPE_STATION:
> /* default key: could be group WPA key
> * or could be static WEP key */
> - mac = NULL;
> break;
> case NL80211_IFTYPE_ADHOC:
> - break;
> case NL80211_IFTYPE_AP:
> + addr = bcast_addr;
> break;
> default:
> ASSERT(0);
> break;
> }
> - } else {
> - mac = addr;
> }
>
> if (key->alg == ALG_TKIP)
> - ret = ath_setkey_tkip(sc, key, &hk, mac);
> + ret = ath_setkey_tkip(sc, key, &hk, addr);
> else
> - ret = ath_keyset(sc, key->keyidx, &hk, mac);
> + ret = ath_keyset(sc, key->keyidx, &hk, addr);
>
> if (!ret)
> return -EIO;
> @@ -2302,8 +2300,8 @@ static int ath9k_conf_tx(struct ieee8021
>
> static int ath9k_set_key(struct ieee80211_hw *hw,
> enum set_key_cmd cmd,
> - const u8 *local_addr,
> - const u8 *addr,
> + struct ieee80211_vif *vif,
> + struct ieee80211_sta *sta,
> struct ieee80211_key_conf *key)
> {
> struct ath_softc *sc = hw->priv;
> @@ -2313,7 +2311,7 @@ static int ath9k_set_key(struct ieee8021
>
> switch (cmd) {
> case SET_KEY:
> - ret = ath_key_config(sc, addr, key);
> + ret = ath_key_config(sc, sta ? sta->addr : NULL, key);
> if (!ret) {
> set_bit(key->keyidx, sc->sc_keymap);
> key->hw_key_idx = key->keyidx;
> --- everything.orig/drivers/net/wireless/b43/main.c 2008-12-08 17:42:05.000000000 +0100
> +++ everything/drivers/net/wireless/b43/main.c 2008-12-08 17:49:40.000000000 +0100
> @@ -3508,8 +3508,8 @@ static void b43_op_bss_info_changed(stru
> }
>
> static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
> - const u8 *local_addr, const u8 *addr,
> - struct ieee80211_key_conf *key)
> + struct ieee80211_vif *vif, struct ieee80211_sta *sta,
> + struct ieee80211_key_conf *key)
> {
> struct b43_wl *wl = hw_to_b43_wl(hw);
> struct b43_wldev *dev;
> @@ -3567,17 +3567,13 @@ static int b43_op_set_key(struct ieee802
> goto out_unlock;
> }
>
> - if (is_broadcast_ether_addr(addr)) {
> + if (!sta) {
> /* addr is FF:FF:FF:FF:FF:FF for default keys */
> err = b43_key_write(dev, index, algorithm,
> key->key, key->keylen, NULL, key);
> } else {
> - /*
> - * either pairwise key or address is 00:00:00:00:00:00
> - * for transmit-only keys
> - */
> - err = b43_key_write(dev, -1, algorithm,
> - key->key, key->keylen, addr, key);
> + err = b43_key_write(dev, -1, algorithm, key->key,
> + key->keylen, sta->addr, key);
> }
> if (err)
> goto out_unlock;
> @@ -3604,10 +3600,12 @@ out_unlock:
> spin_unlock_irqrestore(&wl->irq_lock, flags);
> mutex_unlock(&wl->mutex);
> if (!err) {
> + static const u8 bcast_addr[ETH_ALEN] =
> + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
> b43dbg(wl, "%s hardware based encryption for keyidx: %d, "
> "mac: %s\n",
> cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
> - print_mac(mac, addr));
> + print_mac(mac, sta ? sta->addr : bcast_addr));
> }
> return err;
> }
> --- everything.orig/drivers/net/wireless/iwlwifi/iwl-agn.c 2008-12-08 17:46:45.000000000 +0100
> +++ everything/drivers/net/wireless/iwlwifi/iwl-agn.c 2008-12-08 18:13:37.000000000 +0100
> @@ -3039,7 +3039,8 @@ static void iwl_mac_update_tkip_key(stru
> }
>
> static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
> - const u8 *local_addr, const u8 *addr,
> + struct ieee80211_vif *vif,
> + struct ieee80211_sta *sta,
> struct ieee80211_key_conf *key)
> {
> struct iwl_priv *priv = hw->priv;
> @@ -3047,6 +3048,9 @@ static int iwl_mac_set_key(struct ieee80
> int ret = 0;
> u8 sta_id = IWL_INVALID_STATION;
> u8 is_default_wep_key = 0;
> + static const u8 bcast_addr[ETH_ALEN] =
> + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
> + static const u8 *addr;
>
> IWL_DEBUG_MAC80211("enter\n");
>
> @@ -3055,9 +3059,7 @@ static int iwl_mac_set_key(struct ieee80
> return -EOPNOTSUPP;
> }
>
> - if (is_zero_ether_addr(addr))
> - /* only support pairwise keys */
> - return -EOPNOTSUPP;
> + addr = sta ? sta->addr : bcast_addr;
>
> sta_id = iwl_find_station(priv, addr);
> if (sta_id == IWL_INVALID_STATION) {
> --- everything.orig/drivers/net/wireless/iwlwifi/iwl3945-base.c 2008-12-08 17:46:16.000000000 +0100
> +++ everything/drivers/net/wireless/iwlwifi/iwl3945-base.c 2008-12-08 18:14:45.000000000 +0100
> @@ -7033,12 +7033,16 @@ out_unlock:
> }
>
> static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
> - const u8 *local_addr, const u8 *addr,
> - struct ieee80211_key_conf *key)
> + struct ieee80211_vif *vif,
> + struct ieee80211_sta *sta,
> + struct ieee80211_key_conf *key)
> {
> struct iwl3945_priv *priv = hw->priv;
> int rc = 0;
> u8 sta_id;
> + static const u8 bcast_addr[ETH_ALEN] =
> + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
> + const u8 *addr;
>
> IWL_DEBUG_MAC80211("enter\n");
>
> @@ -7047,9 +7051,7 @@ static int iwl3945_mac_set_key(struct ie
> return -EOPNOTSUPP;
> }
>
> - if (is_zero_ether_addr(addr))
> - /* only support pairwise keys */
> - return -EOPNOTSUPP;
> + addr = sta ? sta->addr : bcast_addr;
>
> sta_id = iwl3945_hw_find_station(priv, addr);
> if (sta_id == IWL_INVALID_STATION) {
> --- everything.orig/drivers/net/wireless/p54/p54common.c 2008-12-08 17:47:11.000000000 +0100
> +++ everything/drivers/net/wireless/p54/p54common.c 2008-12-08 17:53:09.000000000 +0100
> @@ -1938,7 +1938,7 @@ static void p54_bss_info_changed(struct
> }
>
> static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
> - const u8 *local_address, const u8 *address,
> + struct ieee80211_vif *vif, struct ieee80211_sta *sta,
> struct ieee80211_key_conf *key)
> {
> struct p54_common *priv = dev->priv;
> @@ -2002,8 +2002,8 @@ static int p54_set_key(struct ieee80211_
> rxkey->entry = key->keyidx;
> rxkey->key_id = key->keyidx;
> rxkey->key_type = algo;
> - if (address)
> - memcpy(rxkey->mac, address, ETH_ALEN);
> + if (sta)
> + memcpy(rxkey->mac, sta->addr, ETH_ALEN);
> else
> memset(rxkey->mac, ~0, ETH_ALEN);
> if (key->alg != ALG_TKIP) {
> --- everything.orig/drivers/net/wireless/rt2x00/rt2x00.h 2008-12-08 17:47:42.000000000 +0100
> +++ everything/drivers/net/wireless/rt2x00/rt2x00.h 2008-12-08 17:47:52.000000000 +0100
> @@ -982,7 +982,7 @@ void rt2x00mac_configure_filter(struct i
> int mc_count, struct dev_addr_list *mc_list);
> #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_vif *vif, struct ieee80211_sta *sta,
> struct ieee80211_key_conf *key);
> #else
> #define rt2x00mac_set_key NULL
> --- everything.orig/drivers/net/wireless/rt2x00/rt2x00mac.c 2008-12-08 17:48:03.000000000 +0100
> +++ everything/drivers/net/wireless/rt2x00/rt2x00mac.c 2008-12-08 17:57:43.000000000 +0100
> @@ -483,15 +483,17 @@ EXPORT_SYMBOL_GPL(rt2x00mac_configure_fi
>
> #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_vif *vif, struct ieee80211_sta *sta,
> struct ieee80211_key_conf *key)
> {
> struct rt2x00_dev *rt2x00dev = hw->priv;
> - struct ieee80211_sta *sta;
> + struct rt2x00_intf *intf = vif_to_intf(vif);
> int (*set_key) (struct rt2x00_dev *rt2x00dev,
> struct rt2x00lib_crypto *crypto,
> struct ieee80211_key_conf *key);
> struct rt2x00lib_crypto crypto;
> + static const u8 bcast_addr[ETH_ALEN] =
> + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
>
> if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
> return 0;
> @@ -509,15 +511,14 @@ int rt2x00mac_set_key(struct ieee80211_h
> if (rt2x00dev->intf_sta_count)
> crypto.bssidx = 0;
> else
> - crypto.bssidx =
> - local_address[5] & (rt2x00dev->ops->max_ap_intf - 1);
> + crypto.bssidx = intf->mac[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;
> + crypto.address = sta ? sta->addr : bcast_addr;
>
> if (crypto.cipher == CIPHER_TKIP) {
> if (key->keylen > NL80211_TKIP_DATA_OFFSET_ENCR_KEY)
> @@ -542,11 +543,8 @@ int rt2x00mac_set_key(struct ieee80211_h
> * Some drivers need this information when updating the
> * hardware key (either adding or removing).
> */
> - rcu_read_lock();
> - sta = ieee80211_find_sta(hw, address);
> if (sta)
> crypto.aid = sta->aid;
> - rcu_read_unlock();
>
> /*
> * Each BSS has a maximum of 4 shared keys.
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Intel Open Source Technology Centre
http://oss.intel.com/
next prev parent reply other threads:[~2008-12-09 10:42 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-12-08 17:23 [RFT] mac80211: clean up set_key callback Johannes Berg
2008-12-08 20:11 ` Michael Buesch
2008-12-08 20:13 ` Johannes Berg
2008-12-08 22:53 ` Ivo van Doorn
2008-12-08 23:01 ` Johannes Berg
2008-12-09 1:01 ` Bob Copeland
2008-12-09 1:07 ` Johannes Berg
2008-12-09 10:23 ` Kalle Valo
2008-12-09 10:38 ` Samuel Ortiz [this message]
2008-12-09 12:36 ` Christian Lamparter
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=20081209103818.GA2595@sortiz.org \
--to=samuel@sortiz.org \
--cc=Sujith.Manoharan@atheros.com \
--cc=chunkeey@web.de \
--cc=ivdoorn@gmail.com \
--cc=johannes@sipsolutions.net \
--cc=kalle.valo@nokia.com \
--cc=linux-wireless@vger.kernel.org \
--cc=mb@bu3sch.de \
--cc=mcgrof@gmail.com \
--cc=me@bobcopeland.com \
--cc=mickflemm@gmail.com \
--cc=tomasw@gmail.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.