aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2007-12-19 22:38:33 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:08:50 -0500
commit0300b3321d9ed73a0c3f575f2df250c577852356 (patch)
treef08a833e60d4276fabbd79a20361acec740fa725 /drivers/net
parent851b3e5e3de0feea7bfee634f99a940648de58c8 (diff)
airo: bug in airo_interrupt() handling on incoming 802.11
On big-endian we end up with swapped first two bytes in packet, due to earlier conversion to host-endian and forgotten conversion back. The code we calculated that host-endian for had been duplicated several time - it finds the 802.11 MAC header length by the first two bytes of packet; taken into a new helper (header_len(__le16 ctl)). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/airo.c74
1 files changed, 23 insertions, 51 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 6d4cc684afa6..9d3f3357b6e1 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -3177,6 +3177,21 @@ static int airo_thread(void *data) {
3177 return 0; 3177 return 0;
3178} 3178}
3179 3179
3180static int header_len(__le16 ctl)
3181{
3182 u16 fc = le16_to_cpu(ctl);
3183 switch (fc & 0xc) {
3184 case 4:
3185 if ((fc & 0xe0) == 0xc0)
3186 return 10; /* one-address control packet */
3187 return 16; /* two-address control packet */
3188 case 8:
3189 if ((fc & 0x300) == 0x300)
3190 return 30; /* WDS packet */
3191 }
3192 return 24;
3193}
3194
3180static irqreturn_t airo_interrupt(int irq, void *dev_id) 3195static irqreturn_t airo_interrupt(int irq, void *dev_id)
3181{ 3196{
3182 struct net_device *dev = dev_id; 3197 struct net_device *dev = dev_id;
@@ -3330,23 +3345,8 @@ static irqreturn_t airo_interrupt(int irq, void *dev_id)
3330 goto badrx; 3345 goto badrx;
3331 3346
3332 if (test_bit(FLAG_802_11, &apriv->flags)) { 3347 if (test_bit(FLAG_802_11, &apriv->flags)) {
3333 bap_read (apriv, (u16*)&fc, sizeof(fc), BAP0); 3348 bap_read (apriv, &fc, sizeof(fc), BAP0);
3334 fc = le16_to_cpu(fc); 3349 hdrlen = header_len(fc);
3335 switch (fc & 0xc) {
3336 case 4:
3337 if ((fc & 0xe0) == 0xc0)
3338 hdrlen = 10;
3339 else
3340 hdrlen = 16;
3341 break;
3342 case 8:
3343 if ((fc&0x300)==0x300){
3344 hdrlen = 30;
3345 break;
3346 }
3347 default:
3348 hdrlen = 24;
3349 }
3350 } else 3350 } else
3351 hdrlen = ETH_ALEN * 2; 3351 hdrlen = ETH_ALEN * 2;
3352 3352
@@ -3677,7 +3677,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
3677{ 3677{
3678 RxFid rxd; 3678 RxFid rxd;
3679 struct sk_buff *skb = NULL; 3679 struct sk_buff *skb = NULL;
3680 u16 fc, len, hdrlen = 0; 3680 u16 len, hdrlen = 0;
3681 __le16 fc;
3681#pragma pack(1) 3682#pragma pack(1)
3682 struct { 3683 struct {
3683 u16 status, len; 3684 u16 status, len;
@@ -3707,23 +3708,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
3707 if (len == 0) 3708 if (len == 0)
3708 goto badrx; 3709 goto badrx;
3709 3710
3710 memcpy ((char *)&fc, ptr, sizeof(fc)); 3711 fc = get_unaligned((__le16 *)ptr);
3711 fc = le16_to_cpu(fc); 3712 hdrlen = header_len(fc);
3712 switch (fc & 0xc) {
3713 case 4:
3714 if ((fc & 0xe0) == 0xc0)
3715 hdrlen = 10;
3716 else
3717 hdrlen = 16;
3718 break;
3719 case 8:
3720 if ((fc&0x300)==0x300){
3721 hdrlen = 30;
3722 break;
3723 }
3724 default:
3725 hdrlen = 24;
3726 }
3727 3713
3728 skb = dev_alloc_skb( len + hdrlen + 2 ); 3714 skb = dev_alloc_skb( len + hdrlen + 2 );
3729 if ( !skb ) { 3715 if ( !skb ) {
@@ -4370,22 +4356,8 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
4370 u16 txFid = len; 4356 u16 txFid = len;
4371 len >>= 16; 4357 len >>= 16;
4372 4358
4373 fc = le16_to_cpu(*(const u16*)pPacket); 4359 fc = *(__le16*)pPacket;
4374 switch (fc & 0xc) { 4360 hdrlen = header_len(fc);
4375 case 4:
4376 if ((fc & 0xe0) == 0xc0)
4377 hdrlen = 10;
4378 else
4379 hdrlen = 16;
4380 break;
4381 case 8:
4382 if ((fc&0x300)==0x300){
4383 hdrlen = 30;
4384 break;
4385 }
4386 default:
4387 hdrlen = 24;
4388 }
4389 4361
4390 if (len < hdrlen) { 4362 if (len < hdrlen) {
4391 airo_print_warn(ai->dev->name, "Short packet %d", len); 4363 airo_print_warn(ai->dev->name, "Short packet %d", len);