diff options
-rw-r--r-- | net/mac80211/cfg.c | 16 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 8 | ||||
-rw-r--r-- | net/mac80211/iface.c | 4 | ||||
-rw-r--r-- | net/mac80211/tx.c | 7 |
4 files changed, 21 insertions, 14 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index df64b455821d..8052a7ad03a6 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -725,25 +725,23 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | |||
725 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | 725 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, |
726 | const u8 *resp, size_t resp_len) | 726 | const u8 *resp, size_t resp_len) |
727 | { | 727 | { |
728 | struct sk_buff *new, *old; | 728 | struct probe_resp *new, *old; |
729 | 729 | ||
730 | if (!resp || !resp_len) | 730 | if (!resp || !resp_len) |
731 | return 1; | 731 | return -EINVAL; |
732 | 732 | ||
733 | old = rtnl_dereference(sdata->u.ap.probe_resp); | 733 | old = rtnl_dereference(sdata->u.ap.probe_resp); |
734 | 734 | ||
735 | new = dev_alloc_skb(resp_len); | 735 | new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL); |
736 | if (!new) | 736 | if (!new) |
737 | return -ENOMEM; | 737 | return -ENOMEM; |
738 | 738 | ||
739 | memcpy(skb_put(new, resp_len), resp, resp_len); | 739 | new->len = resp_len; |
740 | memcpy(new->data, resp, resp_len); | ||
740 | 741 | ||
741 | rcu_assign_pointer(sdata->u.ap.probe_resp, new); | 742 | rcu_assign_pointer(sdata->u.ap.probe_resp, new); |
742 | if (old) { | 743 | if (old) |
743 | /* TODO: use call_rcu() */ | 744 | kfree_rcu(old, rcu_head); |
744 | synchronize_rcu(); | ||
745 | dev_kfree_skb(old); | ||
746 | } | ||
747 | 745 | ||
748 | return 0; | 746 | return 0; |
749 | } | 747 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d1a7c58a8c62..e22aee83ba53 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -272,9 +272,15 @@ struct beacon_data { | |||
272 | struct rcu_head rcu_head; | 272 | struct rcu_head rcu_head; |
273 | }; | 273 | }; |
274 | 274 | ||
275 | struct probe_resp { | ||
276 | struct rcu_head rcu_head; | ||
277 | int len; | ||
278 | u8 data[0]; | ||
279 | }; | ||
280 | |||
275 | struct ieee80211_if_ap { | 281 | struct ieee80211_if_ap { |
276 | struct beacon_data __rcu *beacon; | 282 | struct beacon_data __rcu *beacon; |
277 | struct sk_buff __rcu *probe_resp; | 283 | struct probe_resp __rcu *probe_resp; |
278 | 284 | ||
279 | struct list_head vlans; | 285 | struct list_head vlans; |
280 | 286 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index abee3a0c25ed..fbab7a84ca21 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -715,7 +715,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
715 | struct ieee80211_sub_if_data *vlan, *tmpsdata; | 715 | struct ieee80211_sub_if_data *vlan, *tmpsdata; |
716 | struct beacon_data *old_beacon = | 716 | struct beacon_data *old_beacon = |
717 | rtnl_dereference(sdata->u.ap.beacon); | 717 | rtnl_dereference(sdata->u.ap.beacon); |
718 | struct sk_buff *old_probe_resp = | 718 | struct probe_resp *old_probe_resp = |
719 | rtnl_dereference(sdata->u.ap.probe_resp); | 719 | rtnl_dereference(sdata->u.ap.probe_resp); |
720 | 720 | ||
721 | /* sdata_running will return false, so this will disable */ | 721 | /* sdata_running will return false, so this will disable */ |
@@ -727,7 +727,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
727 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); | 727 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); |
728 | synchronize_rcu(); | 728 | synchronize_rcu(); |
729 | kfree(old_beacon); | 729 | kfree(old_beacon); |
730 | kfree_skb(old_probe_resp); | 730 | kfree(old_probe_resp); |
731 | 731 | ||
732 | /* down all dependent devices, that is VLANs */ | 732 | /* down all dependent devices, that is VLANs */ |
733 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, | 733 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 7dbcf293708b..2d004ba0615e 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -2481,7 +2481,8 @@ struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw, | |||
2481 | struct ieee80211_vif *vif) | 2481 | struct ieee80211_vif *vif) |
2482 | { | 2482 | { |
2483 | struct ieee80211_if_ap *ap = NULL; | 2483 | struct ieee80211_if_ap *ap = NULL; |
2484 | struct sk_buff *presp = NULL, *skb = NULL; | 2484 | struct sk_buff *skb = NULL; |
2485 | struct probe_resp *presp = NULL; | ||
2485 | struct ieee80211_hdr *hdr; | 2486 | struct ieee80211_hdr *hdr; |
2486 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 2487 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
2487 | 2488 | ||
@@ -2495,10 +2496,12 @@ struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw, | |||
2495 | if (!presp) | 2496 | if (!presp) |
2496 | goto out; | 2497 | goto out; |
2497 | 2498 | ||
2498 | skb = skb_copy(presp, GFP_ATOMIC); | 2499 | skb = dev_alloc_skb(presp->len); |
2499 | if (!skb) | 2500 | if (!skb) |
2500 | goto out; | 2501 | goto out; |
2501 | 2502 | ||
2503 | memcpy(skb_put(skb, presp->len), presp->data, presp->len); | ||
2504 | |||
2502 | hdr = (struct ieee80211_hdr *) skb->data; | 2505 | hdr = (struct ieee80211_hdr *) skb->data; |
2503 | memset(hdr->addr1, 0, sizeof(hdr->addr1)); | 2506 | memset(hdr->addr1, 0, sizeof(hdr->addr1)); |
2504 | 2507 | ||