aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ieee80211.h9
-rw-r--r--include/net/mac80211.h30
-rw-r--r--net/mac80211/tx.c78
3 files changed, 117 insertions, 0 deletions
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index aeea282bd2fe..602c0692c3fc 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -130,6 +130,15 @@ struct ieee80211_hdr {
130 u8 addr4[6]; 130 u8 addr4[6];
131} __attribute__ ((packed)); 131} __attribute__ ((packed));
132 132
133struct ieee80211_hdr_3addr {
134 __le16 frame_control;
135 __le16 duration_id;
136 u8 addr1[6];
137 u8 addr2[6];
138 u8 addr3[6];
139 __le16 seq_ctrl;
140} __attribute__ ((packed));
141
133/** 142/**
134 * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set 143 * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set
135 * @fc: frame control bytes in little-endian byteorder 144 * @fc: frame control bytes in little-endian byteorder
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 7e5af6d90b93..75f46e26ad60 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1875,6 +1875,36 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
1875} 1875}
1876 1876
1877/** 1877/**
1878 * ieee80211_pspoll_get - retrieve a PS Poll template
1879 * @hw: pointer obtained from ieee80211_alloc_hw().
1880 * @vif: &struct ieee80211_vif pointer from the add_interface callback.
1881 *
1882 * Creates a PS Poll a template which can, for example, uploaded to
1883 * hardware. The template must be updated after association so that correct
1884 * AID, BSSID and MAC address is used.
1885 *
1886 * Note: Caller (or hardware) is responsible for setting the
1887 * &IEEE80211_FCTL_PM bit.
1888 */
1889struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
1890 struct ieee80211_vif *vif);
1891
1892/**
1893 * ieee80211_nullfunc_get - retrieve a nullfunc template
1894 * @hw: pointer obtained from ieee80211_alloc_hw().
1895 * @vif: &struct ieee80211_vif pointer from the add_interface callback.
1896 *
1897 * Creates a Nullfunc template which can, for example, uploaded to
1898 * hardware. The template must be updated after association so that correct
1899 * BSSID and address is used.
1900 *
1901 * Note: Caller (or hardware) is responsible for setting the
1902 * &IEEE80211_FCTL_PM bit as well as Duration and Sequence Control fields.
1903 */
1904struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
1905 struct ieee80211_vif *vif);
1906
1907/**
1878 * ieee80211_rts_get - RTS frame generation function 1908 * ieee80211_rts_get - RTS frame generation function
1879 * @hw: pointer obtained from ieee80211_alloc_hw(). 1909 * @hw: pointer obtained from ieee80211_alloc_hw().
1880 * @vif: &struct ieee80211_vif pointer from the add_interface callback. 1910 * @vif: &struct ieee80211_vif pointer from the add_interface callback.
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index d3a44812f8bf..055b45b146d9 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2200,6 +2200,84 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2200} 2200}
2201EXPORT_SYMBOL(ieee80211_beacon_get_tim); 2201EXPORT_SYMBOL(ieee80211_beacon_get_tim);
2202 2202
2203struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
2204 struct ieee80211_vif *vif)
2205{
2206 struct ieee80211_sub_if_data *sdata;
2207 struct ieee80211_if_managed *ifmgd;
2208 struct ieee80211_pspoll *pspoll;
2209 struct ieee80211_local *local;
2210 struct sk_buff *skb;
2211
2212 if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
2213 return NULL;
2214
2215 sdata = vif_to_sdata(vif);
2216 ifmgd = &sdata->u.mgd;
2217 local = sdata->local;
2218
2219 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
2220 if (!skb) {
2221 printk(KERN_DEBUG "%s: failed to allocate buffer for "
2222 "pspoll template\n", sdata->name);
2223 return NULL;
2224 }
2225 skb_reserve(skb, local->hw.extra_tx_headroom);
2226
2227 pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll));
2228 memset(pspoll, 0, sizeof(*pspoll));
2229 pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
2230 IEEE80211_STYPE_PSPOLL);
2231 pspoll->aid = cpu_to_le16(ifmgd->aid);
2232
2233 /* aid in PS-Poll has its two MSBs each set to 1 */
2234 pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
2235
2236 memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
2237 memcpy(pspoll->ta, vif->addr, ETH_ALEN);
2238
2239 return skb;
2240}
2241EXPORT_SYMBOL(ieee80211_pspoll_get);
2242
2243struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
2244 struct ieee80211_vif *vif)
2245{
2246 struct ieee80211_hdr_3addr *nullfunc;
2247 struct ieee80211_sub_if_data *sdata;
2248 struct ieee80211_if_managed *ifmgd;
2249 struct ieee80211_local *local;
2250 struct sk_buff *skb;
2251
2252 if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
2253 return NULL;
2254
2255 sdata = vif_to_sdata(vif);
2256 ifmgd = &sdata->u.mgd;
2257 local = sdata->local;
2258
2259 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*nullfunc));
2260 if (!skb) {
2261 printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
2262 "template\n", sdata->name);
2263 return NULL;
2264 }
2265 skb_reserve(skb, local->hw.extra_tx_headroom);
2266
2267 nullfunc = (struct ieee80211_hdr_3addr *) skb_put(skb,
2268 sizeof(*nullfunc));
2269 memset(nullfunc, 0, sizeof(*nullfunc));
2270 nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
2271 IEEE80211_STYPE_NULLFUNC |
2272 IEEE80211_FCTL_TODS);
2273 memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN);
2274 memcpy(nullfunc->addr2, vif->addr, ETH_ALEN);
2275 memcpy(nullfunc->addr3, ifmgd->bssid, ETH_ALEN);
2276
2277 return skb;
2278}
2279EXPORT_SYMBOL(ieee80211_nullfunc_get);
2280
2203void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 2281void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2204 const void *frame, size_t frame_len, 2282 const void *frame, size_t frame_len,
2205 const struct ieee80211_tx_info *frame_txctl, 2283 const struct ieee80211_tx_info *frame_txctl,