diff options
Diffstat (limited to 'package/mac80211/patches/021-mac80211-beacon-via-nl80211.patch')
-rw-r--r-- | package/mac80211/patches/021-mac80211-beacon-via-nl80211.patch | 484 |
1 files changed, 0 insertions, 484 deletions
diff --git a/package/mac80211/patches/021-mac80211-beacon-via-nl80211.patch b/package/mac80211/patches/021-mac80211-beacon-via-nl80211.patch deleted file mode 100644 index 702c68f98f..0000000000 --- a/package/mac80211/patches/021-mac80211-beacon-via-nl80211.patch +++ /dev/null @@ -1,484 +0,0 @@ -Subject: mac80211: add beacon configuration via cfg80211 - -This patch implements the cfg80211 hooks for configuring beaconing -on an access point interface in mac80211. While doing so, it fixes -a number of races that could badly crash the machine when the -beacon is changed while being requested by the driver. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> - ---- -The dtim_count field should possibly also be part of the beacon -structure, but the possible race there doesn't really matter, -worst thing is that one beacon will be sent with a wrong dtim -count if (and only if) userspace changes the dtim period during -operation. - - net/mac80211/cfg.c | 156 +++++++++++++++++++++++++++++++++++++++++ - net/mac80211/debugfs_netdev.c | 27 ------- - net/mac80211/ieee80211_i.h | 14 ++- - net/mac80211/ieee80211_iface.c | 4 - - net/mac80211/tx.c | 63 ++++++++++------ - 5 files changed, 204 insertions(+), 60 deletions(-) - -Index: mac80211/net/mac80211/cfg.c -=================================================================== ---- mac80211.orig/net/mac80211/cfg.c 2007-11-11 15:17:12.837164411 +0100 -+++ mac80211/net/mac80211/cfg.c 2007-11-11 15:18:36.853952256 +0100 -@@ -9,6 +9,7 @@ - #include <linux/ieee80211.h> - #include <linux/nl80211.h> - #include <linux/rtnetlink.h> -+#include <linux/rcupdate.h> - #include <net/cfg80211.h> - #include "ieee80211_i.h" - #include "cfg.h" -@@ -274,6 +275,158 @@ - return 0; - } - -+/* -+ * This handles both adding a beacon and setting new beacon info -+ */ -+static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, -+ struct beacon_parameters *params) -+{ -+ struct beacon_data *new, *old; -+ int new_head_len, new_tail_len; -+ int size; -+ int err = -EINVAL; -+ -+ old = sdata->u.ap.beacon; -+ -+ /* head must not be zero-length */ -+ if (params->head && !params->head_len) -+ return -EINVAL; -+ -+ /* -+ * This is a kludge. beacon interval should really be part -+ * of the beacon information. -+ */ -+ if (params->interval) { -+ sdata->local->hw.conf.beacon_int = params->interval; -+ if (ieee80211_hw_config(sdata->local)) -+ return -EINVAL; -+ /* -+ * We updated some parameter so if below bails out -+ * it's not an error. -+ */ -+ err = 0; -+ } -+ -+ /* Need to have a beacon head if we don't have one yet */ -+ if (!params->head && !old) -+ return err; -+ -+ /* sorry, no way to start beaconing without dtim period */ -+ if (!params->dtim_period && !old) -+ return err; -+ -+ /* new or old head? */ -+ if (params->head) -+ new_head_len = params->head_len; -+ else -+ new_head_len = old->head_len; -+ -+ /* new or old tail? */ -+ if (params->tail || !old) -+ /* params->tail_len will be zero for !params->tail */ -+ new_tail_len = params->tail_len; -+ else -+ new_tail_len = old->tail_len; -+ -+ size = sizeof(*new) + new_head_len + new_tail_len; -+ -+ new = kzalloc(size, GFP_KERNEL); -+ if (!new) -+ return -ENOMEM; -+ -+ /* start filling the new info now */ -+ -+ /* new or old dtim period? */ -+ if (params->dtim_period) -+ new->dtim_period = params->dtim_period; -+ else -+ new->dtim_period = old->dtim_period; -+ -+ /* -+ * pointers go into the block we allocated, -+ * memory is | beacon_data | head | tail | -+ */ -+ new->head = ((u8 *) new) + sizeof(*new); -+ new->tail = new->head + new_head_len; -+ new->head_len = new_head_len; -+ new->tail_len = new_tail_len; -+ -+ /* copy in head */ -+ if (params->head) -+ memcpy(new->head, params->head, new_head_len); -+ else -+ memcpy(new->head, old->head, new_head_len); -+ -+ /* copy in optional tail */ -+ if (params->tail) -+ memcpy(new->tail, params->tail, new_tail_len); -+ else -+ if (old) -+ memcpy(new->tail, old->tail, new_tail_len); -+ -+ rcu_assign_pointer(sdata->u.ap.beacon, new); -+ -+ synchronize_rcu(); -+ -+ kfree(old); -+ -+ return ieee80211_if_config_beacon(sdata->dev); -+} -+ -+static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, -+ struct beacon_parameters *params) -+{ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ struct beacon_data *old; -+ -+ if (sdata->type != IEEE80211_IF_TYPE_AP) -+ return -EINVAL; -+ -+ old = sdata->u.ap.beacon; -+ -+ if (old) -+ return -EALREADY; -+ -+ return ieee80211_config_beacon(sdata, params); -+} -+ -+static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, -+ struct beacon_parameters *params) -+{ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ struct beacon_data *old; -+ -+ if (sdata->type != IEEE80211_IF_TYPE_AP) -+ return -EINVAL; -+ -+ old = sdata->u.ap.beacon; -+ -+ if (!old) -+ return -ENOENT; -+ -+ return ieee80211_config_beacon(sdata, params); -+} -+ -+static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) -+{ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ struct beacon_data *old; -+ -+ if (sdata->type != IEEE80211_IF_TYPE_AP) -+ return -EINVAL; -+ -+ old = sdata->u.ap.beacon; -+ -+ if (!old) -+ return -ENOENT; -+ -+ rcu_assign_pointer(sdata->u.ap.beacon, NULL); -+ synchronize_rcu(); -+ kfree(old); -+ -+ return ieee80211_if_config_beacon(dev); -+} -+ - struct cfg80211_ops mac80211_config_ops = { - .add_virtual_intf = ieee80211_add_iface, - .del_virtual_intf = ieee80211_del_iface, -@@ -282,4 +435,7 @@ - .del_key = ieee80211_del_key, - .get_key = ieee80211_get_key, - .set_default_key = ieee80211_config_default_key, -+ .add_beacon = ieee80211_add_beacon, -+ .set_beacon = ieee80211_set_beacon, -+ .del_beacon = ieee80211_del_beacon, - }; -Index: mac80211/net/mac80211/debugfs_netdev.c -=================================================================== ---- mac80211.orig/net/mac80211/debugfs_netdev.c 2007-10-14 00:42:30.054156000 +0200 -+++ mac80211/net/mac80211/debugfs_netdev.c 2007-11-11 15:18:11.852527505 +0100 -@@ -124,7 +124,6 @@ - - /* AP attributes */ - IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); --IEEE80211_IF_FILE(dtim_period, u.ap.dtim_period, DEC); - IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); - IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC); - IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC); -@@ -138,26 +137,6 @@ - } - __IEEE80211_IF_FILE(num_buffered_multicast); - --static ssize_t ieee80211_if_fmt_beacon_head_len( -- const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) --{ -- if (sdata->u.ap.beacon_head) -- return scnprintf(buf, buflen, "%d\n", -- sdata->u.ap.beacon_head_len); -- return scnprintf(buf, buflen, "\n"); --} --__IEEE80211_IF_FILE(beacon_head_len); -- --static ssize_t ieee80211_if_fmt_beacon_tail_len( -- const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) --{ -- if (sdata->u.ap.beacon_tail) -- return scnprintf(buf, buflen, "%d\n", -- sdata->u.ap.beacon_tail_len); -- return scnprintf(buf, buflen, "\n"); --} --__IEEE80211_IF_FILE(beacon_tail_len); -- - /* WDS attributes */ - IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); - -@@ -194,14 +173,11 @@ - DEBUGFS_ADD(eapol, ap); - DEBUGFS_ADD(ieee8021_x, ap); - DEBUGFS_ADD(num_sta_ps, ap); -- DEBUGFS_ADD(dtim_period, ap); - DEBUGFS_ADD(dtim_count, ap); - DEBUGFS_ADD(num_beacons, ap); - DEBUGFS_ADD(force_unicast_rateidx, ap); - DEBUGFS_ADD(max_ratectrl_rateidx, ap); - DEBUGFS_ADD(num_buffered_multicast, ap); -- DEBUGFS_ADD(beacon_head_len, ap); -- DEBUGFS_ADD(beacon_tail_len, ap); - } - - static void add_wds_files(struct ieee80211_sub_if_data *sdata) -@@ -287,14 +263,11 @@ - DEBUGFS_DEL(eapol, ap); - DEBUGFS_DEL(ieee8021_x, ap); - DEBUGFS_DEL(num_sta_ps, ap); -- DEBUGFS_DEL(dtim_period, ap); - DEBUGFS_DEL(dtim_count, ap); - DEBUGFS_DEL(num_beacons, ap); - DEBUGFS_DEL(force_unicast_rateidx, ap); - DEBUGFS_DEL(max_ratectrl_rateidx, ap); - DEBUGFS_DEL(num_buffered_multicast, ap); -- DEBUGFS_DEL(beacon_head_len, ap); -- DEBUGFS_DEL(beacon_tail_len, ap); - } - - static void del_wds_files(struct ieee80211_sub_if_data *sdata) -Index: mac80211/net/mac80211/ieee80211_i.h -=================================================================== ---- mac80211.orig/net/mac80211/ieee80211_i.h 2007-11-11 15:15:53.792659922 +0100 -+++ mac80211/net/mac80211/ieee80211_i.h 2007-11-11 15:18:11.864528190 +0100 -@@ -190,9 +190,14 @@ - typedef ieee80211_txrx_result (*ieee80211_rx_handler) - (struct ieee80211_txrx_data *rx); - -+struct beacon_data { -+ u8 *head, *tail; -+ int head_len, tail_len; -+ int dtim_period; -+}; -+ - struct ieee80211_if_ap { -- u8 *beacon_head, *beacon_tail; -- int beacon_head_len, beacon_tail_len; -+ struct beacon_data *beacon; - - struct list_head vlans; - -@@ -205,7 +210,7 @@ - u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; - atomic_t num_sta_ps; /* number of stations in PS mode */ - struct sk_buff_head ps_bc_buf; -- int dtim_period, dtim_count; -+ int dtim_count; - int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ - int max_ratectrl_rateidx; /* max TX rateidx for rate control */ - int num_beacons; /* number of TXed beacon frames for this BSS */ -@@ -361,14 +366,11 @@ - struct dentry *eapol; - struct dentry *ieee8021_x; - struct dentry *num_sta_ps; -- struct dentry *dtim_period; - struct dentry *dtim_count; - struct dentry *num_beacons; - struct dentry *force_unicast_rateidx; - struct dentry *max_ratectrl_rateidx; - struct dentry *num_buffered_multicast; -- struct dentry *beacon_head_len; -- struct dentry *beacon_tail_len; - } ap; - struct { - struct dentry *channel_use; -Index: mac80211/net/mac80211/ieee80211_iface.c -=================================================================== ---- mac80211.orig/net/mac80211/ieee80211_iface.c 2007-11-11 15:15:53.796660158 +0100 -+++ mac80211/net/mac80211/ieee80211_iface.c 2007-11-11 15:18:11.868528415 +0100 -@@ -187,7 +187,6 @@ - sdata->u.vlan.ap = NULL; - break; - case IEEE80211_IF_TYPE_AP: -- sdata->u.ap.dtim_period = 2; - sdata->u.ap.force_unicast_rateidx = -1; - sdata->u.ap.max_ratectrl_rateidx = -1; - skb_queue_head_init(&sdata->u.ap.ps_bc_buf); -@@ -271,8 +270,7 @@ - } - } - -- kfree(sdata->u.ap.beacon_head); -- kfree(sdata->u.ap.beacon_tail); -+ kfree(sdata->u.ap.beacon); - - while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { - local->total_ps_buffered--; -Index: mac80211/net/mac80211/tx.c -=================================================================== ---- mac80211.orig/net/mac80211/tx.c 2007-11-11 15:15:53.804660611 +0100 -+++ mac80211/net/mac80211/tx.c 2007-11-11 15:18:11.868528415 +0100 -@@ -1656,7 +1656,8 @@ - - static void ieee80211_beacon_add_tim(struct ieee80211_local *local, - struct ieee80211_if_ap *bss, -- struct sk_buff *skb) -+ struct sk_buff *skb, -+ struct beacon_data *beacon) - { - u8 *pos, *tim; - int aid0 = 0; -@@ -1672,7 +1673,7 @@ - IEEE80211_MAX_AID+1); - - if (bss->dtim_count == 0) -- bss->dtim_count = bss->dtim_period - 1; -+ bss->dtim_count = beacon->dtim_period - 1; - else - bss->dtim_count--; - -@@ -1680,7 +1681,7 @@ - *pos++ = WLAN_EID_TIM; - *pos++ = 4; - *pos++ = bss->dtim_count; -- *pos++ = bss->dtim_period; -+ *pos++ = beacon->dtim_period; - - if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf)) - aid0 = 1; -@@ -1728,8 +1729,9 @@ - struct ieee80211_if_ap *ap = NULL; - struct ieee80211_rate *rate; - struct rate_control_extra extra; -- u8 *b_head, *b_tail; -- int bh_len, bt_len; -+ struct beacon_data *beacon; -+ -+ rcu_read_lock(); - - bdev = dev_get_by_index(if_id); - if (bdev) { -@@ -1738,37 +1740,35 @@ - dev_put(bdev); - } - -- if (!ap || sdata->type != IEEE80211_IF_TYPE_AP || -- !ap->beacon_head) { -+ beacon = rcu_dereference(ap->beacon); -+ -+ if (!ap || sdata->type != IEEE80211_IF_TYPE_AP || !beacon) { - #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - if (net_ratelimit()) - printk(KERN_DEBUG "no beacon data avail for idx=%d " - "(%s)\n", if_id, bdev ? bdev->name : "N/A"); - #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ -- return NULL; -+ skb = NULL; -+ goto out; - } - -- /* Assume we are generating the normal beacon locally */ -- b_head = ap->beacon_head; -- b_tail = ap->beacon_tail; -- bh_len = ap->beacon_head_len; -- bt_len = ap->beacon_tail_len; -- -- skb = dev_alloc_skb(local->tx_headroom + -- bh_len + bt_len + 256 /* maximum TIM len */); -+ /* headroom, head length, tail length and maximum TIM length */ -+ skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + -+ beacon->tail_len + 256); - if (!skb) -- return NULL; -+ goto out; - - skb_reserve(skb, local->tx_headroom); -- memcpy(skb_put(skb, bh_len), b_head, bh_len); -+ memcpy(skb_put(skb, beacon->head_len), beacon->head, -+ beacon->head_len); - - ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data); - -- ieee80211_beacon_add_tim(local, ap, skb); -+ ieee80211_beacon_add_tim(local, ap, skb, beacon); - -- if (b_tail) { -- memcpy(skb_put(skb, bt_len), b_tail, bt_len); -- } -+ if (beacon->tail) -+ memcpy(skb_put(skb, beacon->tail_len), beacon->tail, -+ beacon->tail_len); - - if (control) { - memset(&extra, 0, sizeof(extra)); -@@ -1781,7 +1781,8 @@ - "found\n", wiphy_name(local->hw.wiphy)); - } - dev_kfree_skb(skb); -- return NULL; -+ skb = NULL; -+ goto out; - } - - control->tx_rate = -@@ -1796,6 +1797,9 @@ - } - - ap->num_beacons++; -+ -+ out: -+ rcu_read_unlock(); - return skb; - } - EXPORT_SYMBOL(ieee80211_beacon_get); -@@ -1844,6 +1848,7 @@ - struct net_device *bdev; - struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_ap *bss = NULL; -+ struct beacon_data *beacon; - - bdev = dev_get_by_index(if_id); - if (bdev) { -@@ -1851,9 +1856,19 @@ - bss = &sdata->u.ap; - dev_put(bdev); - } -- if (!bss || sdata->type != IEEE80211_IF_TYPE_AP || !bss->beacon_head) -+ -+ if (!bss) - return NULL; - -+ rcu_read_lock(); -+ beacon = rcu_dereference(bss->beacon); -+ -+ if (sdata->type != IEEE80211_IF_TYPE_AP || !beacon || !beacon->head) { -+ rcu_read_unlock(); -+ return NULL; -+ } -+ rcu_read_unlock(); -+ - if (bss->dtim_count != 0) - return NULL; /* send buffered bc/mc only after DTIM beacon */ - memset(control, 0, sizeof(*control)); |