summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/tx.c31
2 files changed, 34 insertions, 0 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 00cda1ea15f9..53eb41fad033 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1634,6 +1634,9 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
u32 info_flags);
void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
struct sk_buff_head *skbs);
+struct sk_buff *
+ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, u32 info_flags);
/* HT */
void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 55d69fda4c6a..2dd89670e1cd 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2277,6 +2277,37 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+struct sk_buff *
+ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, u32 info_flags)
+{
+ struct ieee80211_hdr *hdr;
+ struct ieee80211_tx_data tx = {
+ .local = sdata->local,
+ .sdata = sdata,
+ };
+
+ rcu_read_lock();
+
+ skb = ieee80211_build_hdr(sdata, skb, info_flags);
+ if (IS_ERR(skb))
+ goto out;
+
+ hdr = (void *)skb->data;
+ tx.sta = sta_info_get(sdata, hdr->addr1);
+ tx.skb = skb;
+
+ if (ieee80211_tx_h_select_key(&tx) != TX_CONTINUE) {
+ rcu_read_unlock();
+ kfree_skb(skb);
+ return ERR_PTR(-EINVAL);
+ }
+
+out:
+ rcu_read_unlock();
+ return skb;
+}
+
/*
* ieee80211_clear_tx_pending may not be called in a context where
* it is possible that it packets could come in again.