cfg80211: fix error path in cfg80211_wext_siwscan
[safe/jmp/linux-2.6] / net / mac80211 / wpa.c
index 53e11e6..5332014 100644 (file)
@@ -85,16 +85,16 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
        u8 *data, *key = NULL, key_offset;
        size_t data_len;
        unsigned int hdrlen;
-       struct ieee80211_hdr *hdr;
        u8 mic[MICHAEL_MIC_LEN];
        struct sk_buff *skb = rx->skb;
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        int authenticator = 1, wpa_test = 0;
 
        /* No way to verify the MIC if the hardware stripped it */
-       if (rx->status->flag & RX_FLAG_MMIC_STRIPPED)
+       if (status->flag & RX_FLAG_MMIC_STRIPPED)
                return RX_CONTINUE;
 
-       hdr = (struct ieee80211_hdr *)skb->data;
        if (!rx->key || rx->key->conf.alg != ALG_TKIP ||
            !ieee80211_has_protected(hdr->frame_control) ||
            !ieee80211_is_data_present(hdr->frame_control))
@@ -122,7 +122,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
                        return RX_DROP_UNUSABLE;
 
                mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx,
-                                               (void *) skb->data);
+                                               (void *) skb->data, NULL,
+                                               GFP_ATOMIC);
                return RX_DROP_UNUSABLE;
        }
 
@@ -196,19 +197,13 @@ ieee80211_tx_result
 ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
 {
        struct sk_buff *skb = tx->skb;
-       int i;
 
        ieee80211_tx_set_protected(tx);
 
-       if (tkip_encrypt_skb(tx, skb) < 0)
-               return TX_DROP;
-
-       if (tx->extra_frag) {
-               for (i = 0; i < tx->num_extra_frag; i++) {
-                       if (tkip_encrypt_skb(tx, tx->extra_frag[i]))
-                               return TX_DROP;
-               }
-       }
+       do {
+               if (tkip_encrypt_skb(tx, skb) < 0)
+                       return TX_DROP;
+       } while ((skb = skb->next));
 
        return TX_CONTINUE;
 }
@@ -221,6 +216,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
        int hdrlen, res, hwaccel = 0, wpa_test = 0;
        struct ieee80211_key *key = rx->key;
        struct sk_buff *skb = rx->skb;
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
 
@@ -230,8 +226,8 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
        if (!rx->sta || skb->len - hdrlen < 12)
                return RX_DROP_UNUSABLE;
 
-       if (rx->status->flag & RX_FLAG_DECRYPTED) {
-               if (rx->status->flag & RX_FLAG_IV_STRIPPED) {
+       if (status->flag & RX_FLAG_DECRYPTED) {
+               if (status->flag & RX_FLAG_IV_STRIPPED) {
                        /*
                         * Hardware took care of all processing, including
                         * replay protection, and stripped the ICV/IV so
@@ -367,9 +363,14 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
        int hdrlen, len, tail;
        u8 *pos, *pn;
        int i;
+       bool skip_hw;
+
+       skip_hw = (tx->key->conf.flags & IEEE80211_KEY_FLAG_SW_MGMT) &&
+               ieee80211_is_mgmt(hdr->frame_control);
 
        if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
-           !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
+           !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
+           !skip_hw) {
                /* hwaccel - with no need for preallocated room for CCMP
                 * header or MIC fields */
                info->control.hw_key = &tx->key->conf;
@@ -404,7 +405,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 
        ccmp_pn2hdr(pos, pn, key->conf.keyidx);
 
-       if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
+       if ((key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !skip_hw) {
                /* hwaccel - with preallocated room for CCMP header */
                info->control.hw_key = &tx->key->conf;
                return 0;
@@ -423,19 +424,13 @@ ieee80211_tx_result
 ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
 {
        struct sk_buff *skb = tx->skb;
-       int i;
 
        ieee80211_tx_set_protected(tx);
 
-       if (ccmp_encrypt_skb(tx, skb) < 0)
-               return TX_DROP;
-
-       if (tx->extra_frag) {
-               for (i = 0; i < tx->num_extra_frag; i++) {
-                       if (ccmp_encrypt_skb(tx, tx->extra_frag[i]))
-                               return TX_DROP;
-               }
-       }
+       do {
+               if (ccmp_encrypt_skb(tx, skb) < 0)
+                       return TX_DROP;
+       } while ((skb = skb->next));
 
        return TX_CONTINUE;
 }
@@ -448,6 +443,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
        int hdrlen;
        struct ieee80211_key *key = rx->key;
        struct sk_buff *skb = rx->skb;
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        u8 pn[CCMP_PN_LEN];
        int data_len;
 
@@ -461,8 +457,8 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
        if (!rx->sta || data_len < 0)
                return RX_DROP_UNUSABLE;
 
-       if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
-           (rx->status->flag & RX_FLAG_IV_STRIPPED))
+       if ((status->flag & RX_FLAG_DECRYPTED) &&
+           (status->flag & RX_FLAG_IV_STRIPPED))
                return RX_CONTINUE;
 
        ccmp_hdr2pn(pn, skb->data + hdrlen);
@@ -472,7 +468,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
                return RX_DROP_UNUSABLE;
        }
 
-       if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
+       if (!(status->flag & RX_FLAG_DECRYPTED)) {
                /* hardware didn't decrypt/verify MIC */
                ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1);
 
@@ -569,6 +565,7 @@ ieee80211_rx_result
 ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
 {
        struct sk_buff *skb = rx->skb;
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct ieee80211_key *key = rx->key;
        struct ieee80211_mmie *mmie;
        u8 aad[20], mic[8], ipn[6];
@@ -577,8 +574,8 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
        if (!ieee80211_is_mgmt(hdr->frame_control))
                return RX_CONTINUE;
 
-       if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
-           (rx->status->flag & RX_FLAG_IV_STRIPPED))
+       if ((status->flag & RX_FLAG_DECRYPTED) &&
+           (status->flag & RX_FLAG_IV_STRIPPED))
                return RX_CONTINUE;
 
        if (skb->len < 24 + sizeof(*mmie))
@@ -597,7 +594,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
                return RX_DROP_UNUSABLE;
        }
 
-       if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
+       if (!(status->flag & RX_FLAG_DECRYPTED)) {
                /* hardware didn't decrypt/verify MIC */
                bip_aad(skb, aad);
                ieee80211_aes_cmac(key->u.aes_cmac.tfm,