diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f0d42498c257..43da6227b37c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -131,6 +131,12 @@ u64 ieee80211_sta_get_rates(struct ieee80211_local *local, | |||
131 | 131 | ||
132 | /* frame sending functions */ | 132 | /* frame sending functions */ |
133 | 133 | ||
134 | static void add_extra_ies(struct sk_buff *skb, u8 *ies, size_t ies_len) | ||
135 | { | ||
136 | if (ies) | ||
137 | memcpy(skb_put(skb, ies_len), ies, ies_len); | ||
138 | } | ||
139 | |||
134 | /* also used by scanning code */ | 140 | /* also used by scanning code */ |
135 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 141 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
136 | u8 *ssid, size_t ssid_len) | 142 | u8 *ssid, size_t ssid_len) |
@@ -142,7 +148,8 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
142 | u8 *pos, *supp_rates, *esupp_rates = NULL; | 148 | u8 *pos, *supp_rates, *esupp_rates = NULL; |
143 | int i; | 149 | int i; |
144 | 150 | ||
145 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200); | 151 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + |
152 | sdata->u.sta.ie_probereq_len); | ||
146 | if (!skb) { | 153 | if (!skb) { |
147 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " | 154 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " |
148 | "request\n", sdata->dev->name); | 155 | "request\n", sdata->dev->name); |
@@ -189,6 +196,9 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
189 | *pos = rate->bitrate / 5; | 196 | *pos = rate->bitrate / 5; |
190 | } | 197 | } |
191 | 198 | ||
199 | add_extra_ies(skb, sdata->u.sta.ie_probereq, | ||
200 | sdata->u.sta.ie_probereq_len); | ||
201 | |||
192 | ieee80211_tx_skb(sdata, skb, 0); | 202 | ieee80211_tx_skb(sdata, skb, 0); |
193 | } | 203 | } |
194 | 204 | ||
@@ -202,7 +212,8 @@ static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
202 | struct ieee80211_mgmt *mgmt; | 212 | struct ieee80211_mgmt *mgmt; |
203 | 213 | ||
204 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 214 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
205 | sizeof(*mgmt) + 6 + extra_len); | 215 | sizeof(*mgmt) + 6 + extra_len + |
216 | sdata->u.sta.ie_auth_len); | ||
206 | if (!skb) { | 217 | if (!skb) { |
207 | printk(KERN_DEBUG "%s: failed to allocate buffer for auth " | 218 | printk(KERN_DEBUG "%s: failed to allocate buffer for auth " |
208 | "frame\n", sdata->dev->name); | 219 | "frame\n", sdata->dev->name); |
@@ -225,6 +236,7 @@ static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
225 | mgmt->u.auth.status_code = cpu_to_le16(0); | 236 | mgmt->u.auth.status_code = cpu_to_le16(0); |
226 | if (extra) | 237 | if (extra) |
227 | memcpy(skb_put(skb, extra_len), extra, extra_len); | 238 | memcpy(skb_put(skb, extra_len), extra, extra_len); |
239 | add_extra_ies(skb, sdata->u.sta.ie_auth, sdata->u.sta.ie_auth_len); | ||
228 | 240 | ||
229 | ieee80211_tx_skb(sdata, skb, encrypt); | 241 | ieee80211_tx_skb(sdata, skb, encrypt); |
230 | } | 242 | } |
@@ -235,17 +247,26 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
235 | struct ieee80211_local *local = sdata->local; | 247 | struct ieee80211_local *local = sdata->local; |
236 | struct sk_buff *skb; | 248 | struct sk_buff *skb; |
237 | struct ieee80211_mgmt *mgmt; | 249 | struct ieee80211_mgmt *mgmt; |
238 | u8 *pos, *ies, *ht_ie; | 250 | u8 *pos, *ies, *ht_ie, *e_ies; |
239 | int i, len, count, rates_len, supp_rates_len; | 251 | int i, len, count, rates_len, supp_rates_len; |
240 | u16 capab; | 252 | u16 capab; |
241 | struct ieee80211_bss *bss; | 253 | struct ieee80211_bss *bss; |
242 | int wmm = 0; | 254 | int wmm = 0; |
243 | struct ieee80211_supported_band *sband; | 255 | struct ieee80211_supported_band *sband; |
244 | u64 rates = 0; | 256 | u64 rates = 0; |
257 | size_t e_ies_len; | ||
258 | |||
259 | if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { | ||
260 | e_ies = sdata->u.sta.ie_reassocreq; | ||
261 | e_ies_len = sdata->u.sta.ie_reassocreq_len; | ||
262 | } else { | ||
263 | e_ies = sdata->u.sta.ie_assocreq; | ||
264 | e_ies_len = sdata->u.sta.ie_assocreq_len; | ||
265 | } | ||
245 | 266 | ||
246 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 267 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
247 | sizeof(*mgmt) + 200 + ifsta->extra_ie_len + | 268 | sizeof(*mgmt) + 200 + ifsta->extra_ie_len + |
248 | ifsta->ssid_len); | 269 | ifsta->ssid_len + e_ies_len); |
249 | if (!skb) { | 270 | if (!skb) { |
250 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " | 271 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " |
251 | "frame\n", sdata->dev->name); | 272 | "frame\n", sdata->dev->name); |
@@ -436,6 +457,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
436 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | 457 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); |
437 | } | 458 | } |
438 | 459 | ||
460 | add_extra_ies(skb, e_ies, e_ies_len); | ||
461 | |||
439 | kfree(ifsta->assocreq_ies); | 462 | kfree(ifsta->assocreq_ies); |
440 | ifsta->assocreq_ies_len = (skb->data + skb->len) - ies; | 463 | ifsta->assocreq_ies_len = (skb->data + skb->len) - ies; |
441 | ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL); | 464 | ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL); |
@@ -453,8 +476,19 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
453 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 476 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
454 | struct sk_buff *skb; | 477 | struct sk_buff *skb; |
455 | struct ieee80211_mgmt *mgmt; | 478 | struct ieee80211_mgmt *mgmt; |
479 | u8 *ies; | ||
480 | size_t ies_len; | ||
456 | 481 | ||
457 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); | 482 | if (stype == IEEE80211_STYPE_DEAUTH) { |
483 | ies = sdata->u.sta.ie_deauth; | ||
484 | ies_len = sdata->u.sta.ie_deauth_len; | ||
485 | } else { | ||
486 | ies = sdata->u.sta.ie_disassoc; | ||
487 | ies_len = sdata->u.sta.ie_disassoc_len; | ||
488 | } | ||
489 | |||
490 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + | ||
491 | ies_len); | ||
458 | if (!skb) { | 492 | if (!skb) { |
459 | printk(KERN_DEBUG "%s: failed to allocate buffer for " | 493 | printk(KERN_DEBUG "%s: failed to allocate buffer for " |
460 | "deauth/disassoc frame\n", sdata->dev->name); | 494 | "deauth/disassoc frame\n", sdata->dev->name); |
@@ -472,6 +506,8 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
472 | /* u.deauth.reason_code == u.disassoc.reason_code */ | 506 | /* u.deauth.reason_code == u.disassoc.reason_code */ |
473 | mgmt->u.deauth.reason_code = cpu_to_le16(reason); | 507 | mgmt->u.deauth.reason_code = cpu_to_le16(reason); |
474 | 508 | ||
509 | add_extra_ies(skb, ies, ies_len); | ||
510 | |||
475 | ieee80211_tx_skb(sdata, skb, ifsta->flags & IEEE80211_STA_MFP_ENABLED); | 511 | ieee80211_tx_skb(sdata, skb, ifsta->flags & IEEE80211_STA_MFP_ENABLED); |
476 | } | 512 | } |
477 | 513 | ||
@@ -1473,7 +1509,8 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1473 | struct ieee80211_supported_band *sband; | 1509 | struct ieee80211_supported_band *sband; |
1474 | union iwreq_data wrqu; | 1510 | union iwreq_data wrqu; |
1475 | 1511 | ||
1476 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 1512 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + |
1513 | sdata->u.sta.ie_proberesp_len); | ||
1477 | if (!skb) { | 1514 | if (!skb) { |
1478 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " | 1515 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " |
1479 | "response\n", sdata->dev->name); | 1516 | "response\n", sdata->dev->name); |
@@ -1556,6 +1593,9 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1556 | memcpy(pos, &bss->supp_rates[8], rates); | 1593 | memcpy(pos, &bss->supp_rates[8], rates); |
1557 | } | 1594 | } |
1558 | 1595 | ||
1596 | add_extra_ies(skb, sdata->u.sta.ie_proberesp, | ||
1597 | sdata->u.sta.ie_proberesp_len); | ||
1598 | |||
1559 | ifsta->probe_resp = skb; | 1599 | ifsta->probe_resp = skb; |
1560 | 1600 | ||
1561 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 1601 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |