aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2009-01-13 09:03:29 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:00:35 -0500
commit9aed3cc124343d92be6697e9af3928bdfe8eb03e (patch)
tree6a49a68422656790f944f37e3f34379b753d1dab /net/mac80211/mlme.c
parent0c1aa495961f03c964b3287cf5800217cf6f2cee (diff)
nl80211: New command for adding extra IE(s) into management frames
A new nl80211 command, NL80211_CMD_SET_MGMT_EXTRA_IE, can be used to add arbitrary IE data into the end of management frames. The interface allows extra IEs to be configured for each management frame subtype, but only some of them (ProbeReq, ProbeResp, Auth, (Re)AssocReq, Deauth, Disassoc) are currently accepted in mac80211 implementation. This makes it easier to implement IEEE 802.11 extensions like WPS and FT that add IE(s) into some management frames. In addition, this can be useful for testing and experimentation purposes. Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c52
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
134static 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 */
135void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 141void 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);