aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211/ieee80211_rx.c
diff options
context:
space:
mode:
authorDaniel Drake <dsd@gentoo.org>2006-09-26 22:50:31 -0400
committerJeff Garzik <jeff@garzik.org>2006-12-02 00:11:56 -0500
commitc9308b06c049a107edfbd4e5271771564eb6024d (patch)
treea065438a0f279a96988c3730a4d644ce2b94061d /net/ieee80211/ieee80211_rx.c
parentf2423723d70298e04179f934ff17346c3e06f408 (diff)
[PATCH] ieee80211: Move IV/ICV stripping into ieee80211_rx
This patch adds a host_strip_iv_icv flag to ieee80211 which indicates that ieee80211_rx should strip the IV/ICV/other security features from the payload. This saves on some memmove() calls in the driver and seems like something that belongs in the stack as it can be used by bcm43xx, ipw2200, and zd1211rw I will submit the ipw2200 patch separately as it needs testing. This patch also adds some sensible variable reuse (idx vs keyidx) in ieee80211_rx Signed-off-by: Daniel Drake <dsd@gentoo.org> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/ieee80211/ieee80211_rx.c')
-rw-r--r--net/ieee80211/ieee80211_rx.c56
1 files changed, 50 insertions, 6 deletions
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 2759312a4204..d9265195656d 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -415,17 +415,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
415 ieee->host_mc_decrypt : ieee->host_decrypt; 415 ieee->host_mc_decrypt : ieee->host_decrypt;
416 416
417 if (can_be_decrypted) { 417 if (can_be_decrypted) {
418 int idx = 0;
419 if (skb->len >= hdrlen + 3) { 418 if (skb->len >= hdrlen + 3) {
420 /* Top two-bits of byte 3 are the key index */ 419 /* Top two-bits of byte 3 are the key index */
421 idx = skb->data[hdrlen + 3] >> 6; 420 keyidx = skb->data[hdrlen + 3] >> 6;
422 } 421 }
423 422
424 /* ieee->crypt[] is WEP_KEY (4) in length. Given that idx 423 /* ieee->crypt[] is WEP_KEY (4) in length. Given that keyidx
425 * is only allowed 2-bits of storage, no value of idx can 424 * is only allowed 2-bits of storage, no value of keyidx can
426 * be provided via above code that would result in idx 425 * be provided via above code that would result in keyidx
427 * being out of range */ 426 * being out of range */
428 crypt = ieee->crypt[idx]; 427 crypt = ieee->crypt[keyidx];
429 428
430#ifdef NOT_YET 429#ifdef NOT_YET
431 sta = NULL; 430 sta = NULL;
@@ -655,6 +654,51 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
655 goto rx_dropped; 654 goto rx_dropped;
656 } 655 }
657 656
657 /* If the frame was decrypted in hardware, we may need to strip off
658 * any security data (IV, ICV, etc) that was left behind */
659 if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) &&
660 ieee->host_strip_iv_icv) {
661 int trimlen = 0;
662
663 /* Top two-bits of byte 3 are the key index */
664 if (skb->len >= hdrlen + 3)
665 keyidx = skb->data[hdrlen + 3] >> 6;
666
667 /* To strip off any security data which appears before the
668 * payload, we simply increase hdrlen (as the header gets
669 * chopped off immediately below). For the security data which
670 * appears after the payload, we use skb_trim. */
671
672 switch (ieee->sec.encode_alg[keyidx]) {
673 case SEC_ALG_WEP:
674 /* 4 byte IV */
675 hdrlen += 4;
676 /* 4 byte ICV */
677 trimlen = 4;
678 break;
679 case SEC_ALG_TKIP:
680 /* 4 byte IV, 4 byte ExtIV */
681 hdrlen += 8;
682 /* 8 byte MIC, 4 byte ICV */
683 trimlen = 12;
684 break;
685 case SEC_ALG_CCMP:
686 /* 8 byte CCMP header */
687 hdrlen += 8;
688 /* 8 byte MIC */
689 trimlen = 8;
690 break;
691 }
692
693 if (skb->len < trimlen)
694 goto rx_dropped;
695
696 __skb_trim(skb, skb->len - trimlen);
697
698 if (skb->len < hdrlen)
699 goto rx_dropped;
700 }
701
658 /* skb: hdr + (possible reassembled) full plaintext payload */ 702 /* skb: hdr + (possible reassembled) full plaintext payload */
659 703
660 payload = skb->data + hdrlen; 704 payload = skb->data + hdrlen;