diff options
Diffstat (limited to 'net/ieee80211/ieee80211_tx.c')
-rw-r--r-- | net/ieee80211/ieee80211_tx.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index 233d527c6953..6a5de1b84459 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c | |||
@@ -555,7 +555,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
555 | /* Incoming 802.11 strucure is converted to a TXB | 555 | /* Incoming 802.11 strucure is converted to a TXB |
556 | * a block of 802.11 fragment packets (stored as skbs) */ | 556 | * a block of 802.11 fragment packets (stored as skbs) */ |
557 | int ieee80211_tx_frame(struct ieee80211_device *ieee, | 557 | int ieee80211_tx_frame(struct ieee80211_device *ieee, |
558 | struct ieee80211_hdr *frame, int len) | 558 | struct ieee80211_hdr *frame, int hdr_len, int total_len, |
559 | int encrypt_mpdu) | ||
559 | { | 560 | { |
560 | struct ieee80211_txb *txb = NULL; | 561 | struct ieee80211_txb *txb = NULL; |
561 | unsigned long flags; | 562 | unsigned long flags; |
@@ -565,6 +566,9 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee, | |||
565 | 566 | ||
566 | spin_lock_irqsave(&ieee->lock, flags); | 567 | spin_lock_irqsave(&ieee->lock, flags); |
567 | 568 | ||
569 | if (encrypt_mpdu && !ieee->sec.encrypt) | ||
570 | encrypt_mpdu = 0; | ||
571 | |||
568 | /* If there is no driver handler to take the TXB, dont' bother | 572 | /* If there is no driver handler to take the TXB, dont' bother |
569 | * creating it... */ | 573 | * creating it... */ |
570 | if (!ieee->hard_start_xmit) { | 574 | if (!ieee->hard_start_xmit) { |
@@ -572,32 +576,41 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee, | |||
572 | goto success; | 576 | goto success; |
573 | } | 577 | } |
574 | 578 | ||
575 | if (unlikely(len < 24)) { | 579 | if (unlikely(total_len < 24)) { |
576 | printk(KERN_WARNING "%s: skb too small (%d).\n", | 580 | printk(KERN_WARNING "%s: skb too small (%d).\n", |
577 | ieee->dev->name, len); | 581 | ieee->dev->name, total_len); |
578 | goto success; | 582 | goto success; |
579 | } | 583 | } |
580 | 584 | ||
585 | if (encrypt_mpdu) | ||
586 | frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | ||
587 | |||
581 | /* When we allocate the TXB we allocate enough space for the reserve | 588 | /* When we allocate the TXB we allocate enough space for the reserve |
582 | * and full fragment bytes (bytes_per_frag doesn't include prefix, | 589 | * and full fragment bytes (bytes_per_frag doesn't include prefix, |
583 | * postfix, header, FCS, etc.) */ | 590 | * postfix, header, FCS, etc.) */ |
584 | txb = ieee80211_alloc_txb(1, len, ieee->tx_headroom, GFP_ATOMIC); | 591 | txb = ieee80211_alloc_txb(1, total_len, ieee->tx_headroom, GFP_ATOMIC); |
585 | if (unlikely(!txb)) { | 592 | if (unlikely(!txb)) { |
586 | printk(KERN_WARNING "%s: Could not allocate TXB\n", | 593 | printk(KERN_WARNING "%s: Could not allocate TXB\n", |
587 | ieee->dev->name); | 594 | ieee->dev->name); |
588 | goto failed; | 595 | goto failed; |
589 | } | 596 | } |
590 | txb->encrypted = 0; | 597 | txb->encrypted = 0; |
591 | txb->payload_size = len; | 598 | txb->payload_size = total_len; |
592 | 599 | ||
593 | skb_frag = txb->fragments[0]; | 600 | skb_frag = txb->fragments[0]; |
594 | 601 | ||
595 | memcpy(skb_put(skb_frag, len), frame, len); | 602 | memcpy(skb_put(skb_frag, total_len), frame, total_len); |
596 | 603 | ||
597 | if (ieee->config & | 604 | if (ieee->config & |
598 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) | 605 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) |
599 | skb_put(skb_frag, 4); | 606 | skb_put(skb_frag, 4); |
600 | 607 | ||
608 | /* To avoid overcomplicating things, we do the corner-case frame | ||
609 | * encryption in software. The only real situation where encryption is | ||
610 | * needed here is during software-based shared key authentication. */ | ||
611 | if (encrypt_mpdu) | ||
612 | ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); | ||
613 | |||
601 | success: | 614 | success: |
602 | spin_unlock_irqrestore(&ieee->lock, flags); | 615 | spin_unlock_irqrestore(&ieee->lock, flags); |
603 | 616 | ||