diff options
Diffstat (limited to 'net/ieee80211/ieee80211_tx.c')
-rw-r--r-- | net/ieee80211/ieee80211_tx.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index 24ade5f68e02..8d87897d7eb7 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -227,7 +227,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) rts_required; unsigned long flags; struct net_device_stats *stats = &ieee->stats; - int ether_type, encrypt, host_encrypt, host_encrypt_msdu; + int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv; int bytes, fc, hdr_len; struct sk_buff *skb_frag; struct ieee80211_hdr_3addr header = { /* Ensure zero initialized */ @@ -263,8 +263,10 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && ieee->sec.encrypt; + host_encrypt = ieee->host_encrypt && encrypt; host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt; + host_build_iv = ieee->host_build_iv && encrypt; if (!encrypt && ieee->ieee802_1x && ieee->drop_unencrypted && ether_type != ETH_P_PAE) { @@ -310,8 +312,10 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len + crypt->ops->extra_msdu_postfix_len; struct sk_buff *skb_new = dev_alloc_skb(len); + if (unlikely(!skb_new)) goto failed; + skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len); memcpy(skb_put(skb_new, hdr_len), &header, hdr_len); snapped = 1; @@ -418,7 +422,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) for (; i < nr_frags; i++) { skb_frag = txb->fragments[i]; - if (host_encrypt) + if (host_encrypt || host_build_iv) skb_reserve(skb_frag, crypt->ops->extra_mpdu_prefix_len); @@ -453,6 +457,16 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) * to insert the IV between the header and the payload */ if (host_encrypt) ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); + else if (host_build_iv) { + struct ieee80211_crypt_data *crypt; + + crypt = ieee->crypt[ieee->tx_keyidx]; + atomic_inc(&crypt->refcnt); + if (crypt->ops->build_iv) + crypt->ops->build_iv(skb_frag, hdr_len, + crypt->priv); + atomic_dec(&crypt->refcnt); + } if (ieee->config & (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) |