mac80211: fix monitor mode tx radiotap header handling
[safe/jmp/linux-2.6] / net / mac80211 / tx.c
index e3d8ff5..e7b1cdc 100644 (file)
@@ -547,9 +547,10 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
                            !ieee80211_use_mfp(hdr->frame_control, tx->sta,
                                               tx->skb))
                                tx->key = NULL;
-                       skip_hw = (tx->key->conf.flags &
-                                               IEEE80211_KEY_FLAG_SW_MGMT) &&
-                                  ieee80211_is_mgmt(hdr->frame_control);
+                       else
+                               skip_hw = (tx->key->conf.flags &
+                                          IEEE80211_KEY_FLAG_SW_MGMT) &&
+                                       ieee80211_is_mgmt(hdr->frame_control);
                        break;
                case ALG_AES_CMAC:
                        if (!ieee80211_is_mgmt(hdr->frame_control))
@@ -557,8 +558,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
                        break;
                }
 
-               if (!skip_hw &&
-                   tx->key->conf.flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
+               if (!skip_hw && tx->key &&
+                   tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
                        info->control.hw_key = &tx->key->conf;
        }
 
@@ -1107,7 +1108,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
        tx->flags |= IEEE80211_TX_FRAGMENTED;
 
        /* process and remove the injection radiotap header */
-       if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) {
+       if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) {
                if (!__ieee80211_parse_tx_radiotap(tx, skb))
                        return TX_DROP;
 
@@ -1116,6 +1117,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
                 * the radiotap header that was present and pre-filled
                 * 'tx' with tx control information.
                 */
+               info->flags &= ~IEEE80211_TX_INTFL_HAS_RADIOTAP;
        }
 
        /*
@@ -1285,6 +1287,7 @@ static int __ieee80211_tx(struct ieee80211_local *local,
 static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
 {
        struct sk_buff *skb = tx->skb;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        ieee80211_tx_result res = TX_DROP;
 
 #define CALL_TXH(txh) \
@@ -1299,9 +1302,13 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
        CALL_TXH(ieee80211_tx_h_ps_buf);
        CALL_TXH(ieee80211_tx_h_select_key);
        CALL_TXH(ieee80211_tx_h_sta);
-       CALL_TXH(ieee80211_tx_h_michael_mic_add);
        if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
                CALL_TXH(ieee80211_tx_h_rate_ctrl);
+
+       if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION))
+               goto txh_done;
+
+       CALL_TXH(ieee80211_tx_h_michael_mic_add);
        CALL_TXH(ieee80211_tx_h_sequence);
        CALL_TXH(ieee80211_tx_h_fragment);
        /* handlers after fragment must be aware of tx info fragmentation! */
@@ -1493,7 +1500,8 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
                int hdrlen;
                u16 len_rthdr;
 
-               info->flags |= IEEE80211_TX_CTL_INJECTED;
+               info->flags |= IEEE80211_TX_CTL_INJECTED |
+                              IEEE80211_TX_INTFL_HAS_RADIOTAP;
 
                len_rthdr = ieee80211_get_radiotap_len(skb->data);
                hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);