diff options
author | Arik Nemtsov <arik@wizery.com> | 2011-11-10 04:28:57 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-11-11 12:32:51 -0500 |
commit | 029458212604570eec4789049a8a74428484dbb4 (patch) | |
tree | cabbe65d50e83498300a25b02a67f8475c02c3b7 /net | |
parent | 00f740e1a3b7abb51980371ee8fa113df22ae0b8 (diff) |
mac80211: Save probe response data for bss
Allow setting a probe response template for an interface operating in
AP mode. Low level drivers are notified about changes in the probe
response template and are able to retrieve a copy of the current probe
response. This data can, for example, be uploaded to hardware as a
template.
Signed-off-by: Guy Eilam <guy@wizery.com>
Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 38 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/iface.c | 6 | ||||
-rw-r--r-- | net/mac80211/tx.c | 31 | ||||
-rw-r--r-- | net/mac80211/util.c | 3 |
5 files changed, 74 insertions, 5 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 192f213cf43e..c2416fbd1b27 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -491,6 +491,31 @@ static void ieee80211_config_ap_ssid(struct ieee80211_sub_if_data *sdata, | |||
491 | (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); | 491 | (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); |
492 | } | 492 | } |
493 | 493 | ||
494 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | ||
495 | u8 *resp, size_t resp_len) | ||
496 | { | ||
497 | struct sk_buff *new, *old; | ||
498 | |||
499 | if (!resp || !resp_len) | ||
500 | return -EINVAL; | ||
501 | |||
502 | old = sdata->u.ap.probe_resp; | ||
503 | |||
504 | new = dev_alloc_skb(resp_len); | ||
505 | if (!new) | ||
506 | return -ENOMEM; | ||
507 | |||
508 | memcpy(skb_put(new, resp_len), resp, resp_len); | ||
509 | |||
510 | rcu_assign_pointer(sdata->u.ap.probe_resp, new); | ||
511 | synchronize_rcu(); | ||
512 | |||
513 | if (old) | ||
514 | dev_kfree_skb(old); | ||
515 | |||
516 | return 0; | ||
517 | } | ||
518 | |||
494 | /* | 519 | /* |
495 | * This handles both adding a beacon and setting new beacon info | 520 | * This handles both adding a beacon and setting new beacon info |
496 | */ | 521 | */ |
@@ -501,6 +526,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
501 | int new_head_len, new_tail_len; | 526 | int new_head_len, new_tail_len; |
502 | int size; | 527 | int size; |
503 | int err = -EINVAL; | 528 | int err = -EINVAL; |
529 | u32 changed = 0; | ||
504 | 530 | ||
505 | old = rtnl_dereference(sdata->u.ap.beacon); | 531 | old = rtnl_dereference(sdata->u.ap.beacon); |
506 | 532 | ||
@@ -584,11 +610,17 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
584 | 610 | ||
585 | kfree(old); | 611 | kfree(old); |
586 | 612 | ||
613 | err = ieee80211_set_probe_resp(sdata, params->probe_resp, | ||
614 | params->probe_resp_len); | ||
615 | if (!err) | ||
616 | changed |= BSS_CHANGED_AP_PROBE_RESP; | ||
617 | |||
587 | ieee80211_config_ap_ssid(sdata, params); | 618 | ieee80211_config_ap_ssid(sdata, params); |
619 | changed |= BSS_CHANGED_BEACON_ENABLED | | ||
620 | BSS_CHANGED_BEACON | | ||
621 | BSS_CHANGED_SSID; | ||
588 | 622 | ||
589 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | | 623 | ieee80211_bss_info_change_notify(sdata, changed); |
590 | BSS_CHANGED_BEACON | | ||
591 | BSS_CHANGED_SSID); | ||
592 | return 0; | 624 | return 0; |
593 | } | 625 | } |
594 | 626 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 873d681a8e52..068cc92d16aa 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -232,6 +232,7 @@ struct beacon_data { | |||
232 | 232 | ||
233 | struct ieee80211_if_ap { | 233 | struct ieee80211_if_ap { |
234 | struct beacon_data __rcu *beacon; | 234 | struct beacon_data __rcu *beacon; |
235 | struct sk_buff __rcu *probe_resp; | ||
235 | 236 | ||
236 | struct list_head vlans; | 237 | struct list_head vlans; |
237 | 238 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 7b0c25bf8bbf..12a6d4bb5d37 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -462,15 +462,19 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
462 | struct ieee80211_sub_if_data *vlan, *tmpsdata; | 462 | struct ieee80211_sub_if_data *vlan, *tmpsdata; |
463 | struct beacon_data *old_beacon = | 463 | struct beacon_data *old_beacon = |
464 | rtnl_dereference(sdata->u.ap.beacon); | 464 | rtnl_dereference(sdata->u.ap.beacon); |
465 | struct sk_buff *old_probe_resp = | ||
466 | rtnl_dereference(sdata->u.ap.probe_resp); | ||
465 | 467 | ||
466 | /* sdata_running will return false, so this will disable */ | 468 | /* sdata_running will return false, so this will disable */ |
467 | ieee80211_bss_info_change_notify(sdata, | 469 | ieee80211_bss_info_change_notify(sdata, |
468 | BSS_CHANGED_BEACON_ENABLED); | 470 | BSS_CHANGED_BEACON_ENABLED); |
469 | 471 | ||
470 | /* remove beacon */ | 472 | /* remove beacon and probe response */ |
471 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); | 473 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); |
474 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); | ||
472 | synchronize_rcu(); | 475 | synchronize_rcu(); |
473 | kfree(old_beacon); | 476 | kfree(old_beacon); |
477 | kfree(old_probe_resp); | ||
474 | 478 | ||
475 | /* down all dependent devices, that is VLANs */ | 479 | /* down all dependent devices, that is VLANs */ |
476 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, | 480 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ab6cb56bc74d..2b413d38daa7 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -2415,6 +2415,37 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2415 | } | 2415 | } |
2416 | EXPORT_SYMBOL(ieee80211_beacon_get_tim); | 2416 | EXPORT_SYMBOL(ieee80211_beacon_get_tim); |
2417 | 2417 | ||
2418 | struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw, | ||
2419 | struct ieee80211_vif *vif) | ||
2420 | { | ||
2421 | struct ieee80211_if_ap *ap = NULL; | ||
2422 | struct sk_buff *presp = NULL, *skb = NULL; | ||
2423 | struct ieee80211_hdr *hdr; | ||
2424 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
2425 | |||
2426 | if (sdata->vif.type != NL80211_IFTYPE_AP) | ||
2427 | return NULL; | ||
2428 | |||
2429 | rcu_read_lock(); | ||
2430 | |||
2431 | ap = &sdata->u.ap; | ||
2432 | presp = rcu_dereference(ap->probe_resp); | ||
2433 | if (!presp) | ||
2434 | goto out; | ||
2435 | |||
2436 | skb = skb_copy(presp, GFP_ATOMIC); | ||
2437 | if (!skb) | ||
2438 | goto out; | ||
2439 | |||
2440 | hdr = (struct ieee80211_hdr *) skb->data; | ||
2441 | memset(hdr->addr1, 0, sizeof(hdr->addr1)); | ||
2442 | |||
2443 | out: | ||
2444 | rcu_read_unlock(); | ||
2445 | return skb; | ||
2446 | } | ||
2447 | EXPORT_SYMBOL(ieee80211_proberesp_get); | ||
2448 | |||
2418 | struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, | 2449 | struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, |
2419 | struct ieee80211_vif *vif) | 2450 | struct ieee80211_vif *vif) |
2420 | { | 2451 | { |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 6ed0aa430789..4cf25b0eea74 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1071,7 +1071,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1071 | changed |= BSS_CHANGED_IBSS; | 1071 | changed |= BSS_CHANGED_IBSS; |
1072 | /* fall through */ | 1072 | /* fall through */ |
1073 | case NL80211_IFTYPE_AP: | 1073 | case NL80211_IFTYPE_AP: |
1074 | changed |= BSS_CHANGED_SSID; | 1074 | changed |= BSS_CHANGED_SSID | |
1075 | BSS_CHANGED_AP_PROBE_RESP; | ||
1075 | /* fall through */ | 1076 | /* fall through */ |
1076 | case NL80211_IFTYPE_MESH_POINT: | 1077 | case NL80211_IFTYPE_MESH_POINT: |
1077 | changed |= BSS_CHANGED_BEACON | | 1078 | changed |= BSS_CHANGED_BEACON | |