aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-05-09 12:41:15 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-05-12 14:10:47 -0400
commit56d1893d94bc06d0b1aa3a53f924ed02f9e207bf (patch)
tree90862ae6788cf267631bd9ddebf4bc450d0d2b26 /net/wireless
parent15cb309614f35df344b9f06a9ea9f077d1e449db (diff)
cfg80211: restrict AP beacon intervals
Multiple virtual AP interfaces can currently try to use different beacon intervals, but that just leads to problems since it won't actually be done that way by drivers. Return an error in this case to make sure it won't be done wrong. Also, ignore attempts to change the DTIM period or beacon interval during the lifetime of the BSS. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.c1
-rw-r--r--net/wireless/core.h3
-rw-r--r--net/wireless/nl80211.c40
-rw-r--r--net/wireless/util.c25
4 files changed, 52 insertions, 17 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index f924a49b2425..e2ab65d7c86d 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -787,6 +787,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
787 default: 787 default:
788 break; 788 break;
789 } 789 }
790 wdev->beacon_interval = 0;
790 break; 791 break;
791 case NETDEV_DOWN: 792 case NETDEV_DOWN:
792 dev_hold(dev); 793 dev_hold(dev);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index e3f7b1d995cd..fd9135f9b5be 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -433,6 +433,9 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
433 433
434u16 cfg80211_calculate_bitrate(struct rate_info *rate); 434u16 cfg80211_calculate_bitrate(struct rate_info *rate);
435 435
436int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
437 u32 beacon_int);
438
436#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS 439#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
437#define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond) 440#define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond)
438#else 441#else
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b5b050b62f2a..9ef8e287d61b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1876,8 +1876,9 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1876 struct beacon_parameters *info); 1876 struct beacon_parameters *info);
1877 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 1877 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1878 struct net_device *dev = info->user_ptr[1]; 1878 struct net_device *dev = info->user_ptr[1];
1879 struct wireless_dev *wdev = dev->ieee80211_ptr;
1879 struct beacon_parameters params; 1880 struct beacon_parameters params;
1880 int haveinfo = 0; 1881 int haveinfo = 0, err;
1881 1882
1882 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) 1883 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]))
1883 return -EINVAL; 1884 return -EINVAL;
@@ -1886,6 +1887,8 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1886 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) 1887 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
1887 return -EOPNOTSUPP; 1888 return -EOPNOTSUPP;
1888 1889
1890 memset(&params, 0, sizeof(params));
1891
1889 switch (info->genlhdr->cmd) { 1892 switch (info->genlhdr->cmd) {
1890 case NL80211_CMD_NEW_BEACON: 1893 case NL80211_CMD_NEW_BEACON:
1891 /* these are required for NEW_BEACON */ 1894 /* these are required for NEW_BEACON */
@@ -1894,6 +1897,15 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1894 !info->attrs[NL80211_ATTR_BEACON_HEAD]) 1897 !info->attrs[NL80211_ATTR_BEACON_HEAD])
1895 return -EINVAL; 1898 return -EINVAL;
1896 1899
1900 params.interval =
1901 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
1902 params.dtim_period =
1903 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
1904
1905 err = cfg80211_validate_beacon_int(rdev, params.interval);
1906 if (err)
1907 return err;
1908
1897 call = rdev->ops->add_beacon; 1909 call = rdev->ops->add_beacon;
1898 break; 1910 break;
1899 case NL80211_CMD_SET_BEACON: 1911 case NL80211_CMD_SET_BEACON:
@@ -1907,20 +1919,6 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1907 if (!call) 1919 if (!call)
1908 return -EOPNOTSUPP; 1920 return -EOPNOTSUPP;
1909 1921
1910 memset(&params, 0, sizeof(params));
1911
1912 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
1913 params.interval =
1914 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
1915 haveinfo = 1;
1916 }
1917
1918 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
1919 params.dtim_period =
1920 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
1921 haveinfo = 1;
1922 }
1923
1924 if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { 1922 if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
1925 params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); 1923 params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
1926 params.head_len = 1924 params.head_len =
@@ -1938,13 +1936,18 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1938 if (!haveinfo) 1936 if (!haveinfo)
1939 return -EINVAL; 1937 return -EINVAL;
1940 1938
1941 return call(&rdev->wiphy, dev, &params); 1939 err = call(&rdev->wiphy, dev, &params);
1940 if (!err && params.interval)
1941 wdev->beacon_interval = params.interval;
1942 return err;
1942} 1943}
1943 1944
1944static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) 1945static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
1945{ 1946{
1946 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 1947 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1947 struct net_device *dev = info->user_ptr[1]; 1948 struct net_device *dev = info->user_ptr[1];
1949 struct wireless_dev *wdev = dev->ieee80211_ptr;
1950 int err;
1948 1951
1949 if (!rdev->ops->del_beacon) 1952 if (!rdev->ops->del_beacon)
1950 return -EOPNOTSUPP; 1953 return -EOPNOTSUPP;
@@ -1953,7 +1956,10 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
1953 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) 1956 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
1954 return -EOPNOTSUPP; 1957 return -EOPNOTSUPP;
1955 1958
1956 return rdev->ops->del_beacon(&rdev->wiphy, dev); 1959 err = rdev->ops->del_beacon(&rdev->wiphy, dev);
1960 if (!err)
1961 wdev->beacon_interval = 0;
1962 return err;
1957} 1963}
1958 1964
1959static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { 1965static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 6a750bc6bcfe..414c9f604df6 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -896,3 +896,28 @@ u16 cfg80211_calculate_bitrate(struct rate_info *rate)
896 /* do NOT round down here */ 896 /* do NOT round down here */
897 return (bitrate + 50000) / 100000; 897 return (bitrate + 50000) / 100000;
898} 898}
899
900int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
901 u32 beacon_int)
902{
903 struct wireless_dev *wdev;
904 int res = 0;
905
906 if (!beacon_int)
907 return -EINVAL;
908
909 mutex_lock(&rdev->devlist_mtx);
910
911 list_for_each_entry(wdev, &rdev->netdev_list, list) {
912 if (!wdev->beacon_interval)
913 continue;
914 if (wdev->beacon_interval != beacon_int) {
915 res = -EINVAL;
916 break;
917 }
918 }
919
920 mutex_unlock(&rdev->devlist_mtx);
921
922 return res;
923}