aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/reg.c
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2014-11-27 02:44:55 -0500
committerJohannes Berg <johannes.berg@intel.com>2014-11-28 08:33:41 -0500
commitad932f046fbe9839479350e7b88082a7d1dea498 (patch)
treebde027962f8f061558db060102872d7de0435adf /net/wireless/reg.c
parent336004e29115e47253f7e7d007df9e1f9e73dcdd (diff)
cfg80211: leave invalid channels on regdomain change
When the regulatory settings change, some channels might become invalid. Disconnect interfaces acting on these channels, after giving userspace code a grace period to leave them. This mode is currently opt-in, and not all interface operating modes are supported for regulatory-enforcement checks. A wiphy that wishes to use the new enforcement code must specify an appropriate regulatory flag, and all its supported interface modes must be supported by the checking code. Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com> Reviewed-by: Luis R. Rodriguez <mcgrof@suse.com> [fix some indentation, typos] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r--net/wireless/reg.c107
1 files changed, 106 insertions, 1 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 32d8310b0f85..47be6163381c 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -56,6 +56,7 @@
56#include <net/cfg80211.h> 56#include <net/cfg80211.h>
57#include "core.h" 57#include "core.h"
58#include "reg.h" 58#include "reg.h"
59#include "rdev-ops.h"
59#include "regdb.h" 60#include "regdb.h"
60#include "nl80211.h" 61#include "nl80211.h"
61 62
@@ -66,6 +67,12 @@
66#define REG_DBG_PRINT(args...) 67#define REG_DBG_PRINT(args...)
67#endif 68#endif
68 69
70/*
71 * Grace period we give before making sure all current interfaces reside on
72 * channels allowed by the current regulatory domain.
73 */
74#define REG_ENFORCE_GRACE_MS 60000
75
69/** 76/**
70 * enum reg_request_treatment - regulatory request treatment 77 * enum reg_request_treatment - regulatory request treatment
71 * 78 *
@@ -210,6 +217,9 @@ struct reg_beacon {
210 struct ieee80211_channel chan; 217 struct ieee80211_channel chan;
211}; 218};
212 219
220static void reg_check_chans_work(struct work_struct *work);
221static DECLARE_DELAYED_WORK(reg_check_chans, reg_check_chans_work);
222
213static void reg_todo(struct work_struct *work); 223static void reg_todo(struct work_struct *work);
214static DECLARE_WORK(reg_work, reg_todo); 224static DECLARE_WORK(reg_work, reg_todo);
215 225
@@ -1518,6 +1528,96 @@ static void reg_call_notifier(struct wiphy *wiphy,
1518 wiphy->reg_notifier(wiphy, request); 1528 wiphy->reg_notifier(wiphy, request);
1519} 1529}
1520 1530
1531static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
1532{
1533 struct ieee80211_channel *ch;
1534 struct cfg80211_chan_def chandef;
1535 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1536 bool ret = true;
1537
1538 wdev_lock(wdev);
1539
1540 if (!wdev->netdev || !netif_running(wdev->netdev))
1541 goto out;
1542
1543 switch (wdev->iftype) {
1544 case NL80211_IFTYPE_AP:
1545 case NL80211_IFTYPE_P2P_GO:
1546 if (!wdev->beacon_interval)
1547 goto out;
1548
1549 ret = cfg80211_reg_can_beacon(wiphy,
1550 &wdev->chandef, wdev->iftype);
1551 break;
1552 case NL80211_IFTYPE_STATION:
1553 case NL80211_IFTYPE_P2P_CLIENT:
1554 case NL80211_IFTYPE_ADHOC:
1555 if (!wdev->current_bss ||
1556 !wdev->current_bss->pub.channel)
1557 goto out;
1558
1559 ch = wdev->current_bss->pub.channel;
1560 if (rdev->ops->get_channel &&
1561 !rdev_get_channel(rdev, wdev, &chandef))
1562 ret = cfg80211_chandef_usable(wiphy, &chandef,
1563 IEEE80211_CHAN_DISABLED);
1564 else
1565 ret = !(ch->flags & IEEE80211_CHAN_DISABLED);
1566 break;
1567 case NL80211_IFTYPE_MONITOR:
1568 case NL80211_IFTYPE_AP_VLAN:
1569 case NL80211_IFTYPE_P2P_DEVICE:
1570 /* no enforcement required */
1571 break;
1572 default:
1573 /* others not implemented for now */
1574 WARN_ON(1);
1575 break;
1576 }
1577
1578out:
1579 wdev_unlock(wdev);
1580 return ret;
1581}
1582
1583static void reg_leave_invalid_chans(struct wiphy *wiphy)
1584{
1585 struct wireless_dev *wdev;
1586 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
1587
1588 ASSERT_RTNL();
1589
1590 list_for_each_entry(wdev, &rdev->wdev_list, list)
1591 if (!reg_wdev_chan_valid(wiphy, wdev))
1592 cfg80211_leave(rdev, wdev);
1593}
1594
1595static void reg_check_chans_work(struct work_struct *work)
1596{
1597 struct cfg80211_registered_device *rdev;
1598
1599 REG_DBG_PRINT("Verifying active interfaces after reg change\n");
1600 rtnl_lock();
1601
1602 list_for_each_entry(rdev, &cfg80211_rdev_list, list)
1603 if (!(rdev->wiphy.regulatory_flags &
1604 REGULATORY_IGNORE_STALE_KICKOFF))
1605 reg_leave_invalid_chans(&rdev->wiphy);
1606
1607 rtnl_unlock();
1608}
1609
1610static void reg_check_channels(void)
1611{
1612 /*
1613 * Give usermode a chance to do something nicer (move to another
1614 * channel, orderly disconnection), before forcing a disconnection.
1615 */
1616 mod_delayed_work(system_power_efficient_wq,
1617 &reg_check_chans,
1618 msecs_to_jiffies(REG_ENFORCE_GRACE_MS));
1619}
1620
1521static void wiphy_update_regulatory(struct wiphy *wiphy, 1621static void wiphy_update_regulatory(struct wiphy *wiphy,
1522 enum nl80211_reg_initiator initiator) 1622 enum nl80211_reg_initiator initiator)
1523{ 1623{
@@ -1557,6 +1657,8 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
1557 wiphy = &rdev->wiphy; 1657 wiphy = &rdev->wiphy;
1558 wiphy_update_regulatory(wiphy, initiator); 1658 wiphy_update_regulatory(wiphy, initiator);
1559 } 1659 }
1660
1661 reg_check_channels();
1560} 1662}
1561 1663
1562static void handle_channel_custom(struct wiphy *wiphy, 1664static void handle_channel_custom(struct wiphy *wiphy,
@@ -1976,8 +2078,10 @@ static void reg_process_hint(struct regulatory_request *reg_request)
1976 2078
1977 /* This is required so that the orig_* parameters are saved */ 2079 /* This is required so that the orig_* parameters are saved */
1978 if (treatment == REG_REQ_ALREADY_SET && wiphy && 2080 if (treatment == REG_REQ_ALREADY_SET && wiphy &&
1979 wiphy->regulatory_flags & REGULATORY_STRICT_REG) 2081 wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
1980 wiphy_update_regulatory(wiphy, reg_request->initiator); 2082 wiphy_update_regulatory(wiphy, reg_request->initiator);
2083 reg_check_channels();
2084 }
1981 2085
1982 return; 2086 return;
1983 2087
@@ -2858,6 +2962,7 @@ void regulatory_exit(void)
2858 2962
2859 cancel_work_sync(&reg_work); 2963 cancel_work_sync(&reg_work);
2860 cancel_delayed_work_sync(&reg_timeout); 2964 cancel_delayed_work_sync(&reg_timeout);
2965 cancel_delayed_work_sync(&reg_check_chans);
2861 2966
2862 /* Lock to suppress warnings */ 2967 /* Lock to suppress warnings */
2863 rtnl_lock(); 2968 rtnl_lock();