diff options
-rw-r--r-- | include/linux/ieee80211.h | 9 | ||||
-rw-r--r-- | include/net/mac80211.h | 30 | ||||
-rw-r--r-- | net/mac80211/tx.c | 78 |
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 | ||
133 | struct 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 | */ | ||
1889 | struct 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 | */ | ||
1904 | struct 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 | } |
2201 | EXPORT_SYMBOL(ieee80211_beacon_get_tim); | 2201 | EXPORT_SYMBOL(ieee80211_beacon_get_tim); |
2202 | 2202 | ||
2203 | struct 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 | } | ||
2241 | EXPORT_SYMBOL(ieee80211_pspoll_get); | ||
2242 | |||
2243 | struct 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 | } | ||
2279 | EXPORT_SYMBOL(ieee80211_nullfunc_get); | ||
2280 | |||
2203 | void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 2281 | void 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, |