diff options
-rw-r--r-- | include/net/cfg80211.h | 4 | ||||
-rw-r--r-- | net/wireless/core.c | 1 | ||||
-rw-r--r-- | net/wireless/core.h | 3 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 40 | ||||
-rw-r--r-- | net/wireless/util.c | 25 |
5 files changed, 56 insertions, 17 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 1f1e221b6ce3..a46adb7a91b7 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1908,6 +1908,8 @@ struct cfg80211_cached_keys; | |||
1908 | * @mgmt_registrations_lock: lock for the list | 1908 | * @mgmt_registrations_lock: lock for the list |
1909 | * @mtx: mutex used to lock data in this struct | 1909 | * @mtx: mutex used to lock data in this struct |
1910 | * @cleanup_work: work struct used for cleanup that can't be done directly | 1910 | * @cleanup_work: work struct used for cleanup that can't be done directly |
1911 | * @beacon_interval: beacon interval used on this device for transmitting | ||
1912 | * beacons, 0 when not valid | ||
1911 | */ | 1913 | */ |
1912 | struct wireless_dev { | 1914 | struct wireless_dev { |
1913 | struct wiphy *wiphy; | 1915 | struct wiphy *wiphy; |
@@ -1948,6 +1950,8 @@ struct wireless_dev { | |||
1948 | bool ps; | 1950 | bool ps; |
1949 | int ps_timeout; | 1951 | int ps_timeout; |
1950 | 1952 | ||
1953 | int beacon_interval; | ||
1954 | |||
1951 | #ifdef CONFIG_CFG80211_WEXT | 1955 | #ifdef CONFIG_CFG80211_WEXT |
1952 | /* wext data */ | 1956 | /* wext data */ |
1953 | struct { | 1957 | struct { |
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 | ||
434 | u16 cfg80211_calculate_bitrate(struct rate_info *rate); | 434 | u16 cfg80211_calculate_bitrate(struct rate_info *rate); |
435 | 435 | ||
436 | int 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(¶ms, 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(¶ms, 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, ¶ms); | 1939 | err = call(&rdev->wiphy, dev, ¶ms); |
1940 | if (!err && params.interval) | ||
1941 | wdev->beacon_interval = params.interval; | ||
1942 | return err; | ||
1942 | } | 1943 | } |
1943 | 1944 | ||
1944 | static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) | 1945 | static 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 | ||
1959 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { | 1965 | static 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 | |||
900 | int 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 | } | ||