aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-12-18 20:03:33 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:09:38 -0500
commit5dfdaf58d61f06a458529430c24b1191ea4d1a27 (patch)
treebd3fac57f66e80bf2a31d253af19093f4020ba79 /net/mac80211/tx.c
parent51fb61e76d952e6bc2fbdd9f0d38425fbab1cf31 (diff)
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> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c65
1 files changed, 40 insertions, 25 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 99590e4ce30b..51c0f00d02d1 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1628,7 +1628,8 @@ void ieee80211_tx_pending(unsigned long data)
1628 1628
1629static void ieee80211_beacon_add_tim(struct ieee80211_local *local, 1629static void ieee80211_beacon_add_tim(struct ieee80211_local *local,
1630 struct ieee80211_if_ap *bss, 1630 struct ieee80211_if_ap *bss,
1631 struct sk_buff *skb) 1631 struct sk_buff *skb,
1632 struct beacon_data *beacon)
1632{ 1633{
1633 u8 *pos, *tim; 1634 u8 *pos, *tim;
1634 int aid0 = 0; 1635 int aid0 = 0;
@@ -1644,7 +1645,7 @@ static void ieee80211_beacon_add_tim(struct ieee80211_local *local,
1644 IEEE80211_MAX_AID+1); 1645 IEEE80211_MAX_AID+1);
1645 1646
1646 if (bss->dtim_count == 0) 1647 if (bss->dtim_count == 0)
1647 bss->dtim_count = bss->dtim_period - 1; 1648 bss->dtim_count = beacon->dtim_period - 1;
1648 else 1649 else
1649 bss->dtim_count--; 1650 bss->dtim_count--;
1650 1651
@@ -1652,7 +1653,7 @@ static void ieee80211_beacon_add_tim(struct ieee80211_local *local,
1652 *pos++ = WLAN_EID_TIM; 1653 *pos++ = WLAN_EID_TIM;
1653 *pos++ = 4; 1654 *pos++ = 4;
1654 *pos++ = bss->dtim_count; 1655 *pos++ = bss->dtim_count;
1655 *pos++ = bss->dtim_period; 1656 *pos++ = beacon->dtim_period;
1656 1657
1657 if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf)) 1658 if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf))
1658 aid0 = 1; 1659 aid0 = 1;
@@ -1700,44 +1701,43 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
1700 struct ieee80211_sub_if_data *sdata = NULL; 1701 struct ieee80211_sub_if_data *sdata = NULL;
1701 struct ieee80211_if_ap *ap = NULL; 1702 struct ieee80211_if_ap *ap = NULL;
1702 struct rate_selection rsel; 1703 struct rate_selection rsel;
1703 u8 *b_head, *b_tail; 1704 struct beacon_data *beacon;
1704 int bh_len, bt_len; 1705
1706 rcu_read_lock();
1705 1707
1706 sdata = vif_to_sdata(vif); 1708 sdata = vif_to_sdata(vif);
1707 bdev = sdata->dev; 1709 bdev = sdata->dev;
1708 ap = &sdata->u.ap; 1710 ap = &sdata->u.ap;
1709 1711
1710 if (!ap || sdata->vif.type != IEEE80211_IF_TYPE_AP || 1712 beacon = rcu_dereference(ap->beacon);
1711 !ap->beacon_head) { 1713
1714 if (!ap || sdata->vif.type != IEEE80211_IF_TYPE_AP || !beacon) {
1712#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 1715#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1713 if (net_ratelimit()) 1716 if (net_ratelimit())
1714 printk(KERN_DEBUG "no beacon data avail for %s\n", 1717 printk(KERN_DEBUG "no beacon data avail for %s\n",
1715 bdev->name); 1718 bdev->name);
1716#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ 1719#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
1717 return NULL; 1720 skb = NULL;
1721 goto out;
1718 } 1722 }
1719 1723
1720 /* Assume we are generating the normal beacon locally */ 1724 /* headroom, head length, tail length and maximum TIM length */
1721 b_head = ap->beacon_head; 1725 skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
1722 b_tail = ap->beacon_tail; 1726 beacon->tail_len + 256);
1723 bh_len = ap->beacon_head_len;
1724 bt_len = ap->beacon_tail_len;
1725
1726 skb = dev_alloc_skb(local->tx_headroom +
1727 bh_len + bt_len + 256 /* maximum TIM len */);
1728 if (!skb) 1727 if (!skb)
1729 return NULL; 1728 goto out;
1730 1729
1731 skb_reserve(skb, local->tx_headroom); 1730 skb_reserve(skb, local->tx_headroom);
1732 memcpy(skb_put(skb, bh_len), b_head, bh_len); 1731 memcpy(skb_put(skb, beacon->head_len), beacon->head,
1732 beacon->head_len);
1733 1733
1734 ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data); 1734 ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data);
1735 1735
1736 ieee80211_beacon_add_tim(local, ap, skb); 1736 ieee80211_beacon_add_tim(local, ap, skb, beacon);
1737 1737
1738 if (b_tail) { 1738 if (beacon->tail)
1739 memcpy(skb_put(skb, bt_len), b_tail, bt_len); 1739 memcpy(skb_put(skb, beacon->tail_len), beacon->tail,
1740 } 1740 beacon->tail_len);
1741 1741
1742 if (control) { 1742 if (control) {
1743 rate_control_get_rate(local->mdev, local->oper_hw_mode, skb, 1743 rate_control_get_rate(local->mdev, local->oper_hw_mode, skb,
@@ -1749,7 +1749,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
1749 wiphy_name(local->hw.wiphy)); 1749 wiphy_name(local->hw.wiphy));
1750 } 1750 }
1751 dev_kfree_skb(skb); 1751 dev_kfree_skb(skb);
1752 return NULL; 1752 skb = NULL;
1753 goto out;
1753 } 1754 }
1754 1755
1755 control->tx_rate = 1756 control->tx_rate =
@@ -1764,6 +1765,9 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
1764 } 1765 }
1765 1766
1766 ap->num_beacons++; 1767 ap->num_beacons++;
1768
1769 out:
1770 rcu_read_unlock();
1767 return skb; 1771 return skb;
1768} 1772}
1769EXPORT_SYMBOL(ieee80211_beacon_get); 1773EXPORT_SYMBOL(ieee80211_beacon_get);
@@ -1815,13 +1819,24 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
1815 struct net_device *bdev; 1819 struct net_device *bdev;
1816 struct ieee80211_sub_if_data *sdata; 1820 struct ieee80211_sub_if_data *sdata;
1817 struct ieee80211_if_ap *bss = NULL; 1821 struct ieee80211_if_ap *bss = NULL;
1822 struct beacon_data *beacon;
1818 1823
1819 sdata = vif_to_sdata(vif); 1824 sdata = vif_to_sdata(vif);
1820 bdev = sdata->dev; 1825 bdev = sdata->dev;
1821 1826
1822 if (!bss || sdata->vif.type != IEEE80211_IF_TYPE_AP || 1827
1823 !bss->beacon_head) 1828 if (!bss)
1829 return NULL;
1830
1831 rcu_read_lock();
1832 beacon = rcu_dereference(bss->beacon);
1833
1834 if (sdata->vif.type != IEEE80211_IF_TYPE_AP || !beacon ||
1835 !beacon->head) {
1836 rcu_read_unlock();
1824 return NULL; 1837 return NULL;
1838 }
1839 rcu_read_unlock();
1825 1840
1826 if (bss->dtim_count != 0) 1841 if (bss->dtim_count != 0)
1827 return NULL; /* send buffered bc/mc only after DTIM beacon */ 1842 return NULL; /* send buffered bc/mc only after DTIM beacon */