aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-05-13 04:58:57 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-05-16 14:10:40 -0400
commit7527a782e187d1214a5b3dc2897ce441033bb4ef (patch)
tree3310adf988e72cb91736c0638d4c17edcccebfe1
parent805d7d23ef9806e47b550ad80270c4cea4ffc984 (diff)
cfg80211: advertise possible interface combinations
Add the ability to advertise interface combinations in nl80211. This allows the driver to indicate what the combinations are that it supports. "Combinations" of just a single interface are implicit, as previously. Note that cfg80211 will enforce that the restrictions are met, but not for all drivers yet (once all drivers are updated, we can remove the flag and enforce for all). When no combinations are actually supported, an empty list will be exported so that userspace can know if the kernel exported this info or not (although it isn't clear to me what tools using the info should do if the kernel didn't export it). Since some interface types are purely virtual/software and don't fit the restrictions, those are exposed in a new list of pure SW types, not subject to restrictions. This mainly exists to handle AP-VLAN and monitor interfaces in mac80211. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/linux/nl80211.h122
-rw-r--r--include/net/cfg80211.h88
-rw-r--r--net/mac80211/main.c16
-rw-r--r--net/wireless/core.c69
-rw-r--r--net/wireless/core.h11
-rw-r--r--net/wireless/nl80211.c105
-rw-r--r--net/wireless/util.c80
7 files changed, 472 insertions, 19 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 281a2bb6a6ec..0ea497cb607c 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -77,6 +77,39 @@
77 */ 77 */
78 78
79/** 79/**
80 * DOC: Virtual interface / concurrency capabilities
81 *
82 * Some devices are able to operate with virtual MACs, they can have
83 * more than one virtual interface. The capability handling for this
84 * is a bit complex though, as there may be a number of restrictions
85 * on the types of concurrency that are supported.
86 *
87 * To start with, each device supports the interface types listed in
88 * the %NL80211_ATTR_SUPPORTED_IFTYPES attribute, but by listing the
89 * types there no concurrency is implied.
90 *
91 * Once concurrency is desired, more attributes must be observed:
92 * To start with, since some interface types are purely managed in
93 * software, like the AP-VLAN type in mac80211 for example, there's
94 * an additional list of these, they can be added at any time and
95 * are only restricted by some semantic restrictions (e.g. AP-VLAN
96 * cannot be added without a corresponding AP interface). This list
97 * is exported in the %NL80211_ATTR_SOFTWARE_IFTYPES attribute.
98 *
99 * Further, the list of supported combinations is exported. This is
100 * in the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute. Basically,
101 * it exports a list of "groups", and at any point in time the
102 * interfaces that are currently active must fall into any one of
103 * the advertised groups. Within each group, there are restrictions
104 * on the number of interfaces of different types that are supported
105 * and also the number of different channels, along with potentially
106 * some other restrictions. See &enum nl80211_if_combination_attrs.
107 *
108 * All together, these attributes define the concurrency of virtual
109 * interfaces that a given device supports.
110 */
111
112/**
80 * enum nl80211_commands - supported nl80211 commands 113 * enum nl80211_commands - supported nl80211 commands
81 * 114 *
82 * @NL80211_CMD_UNSPEC: unspecified command to catch errors 115 * @NL80211_CMD_UNSPEC: unspecified command to catch errors
@@ -954,6 +987,14 @@ enum nl80211_commands {
954 * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan 987 * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan
955 * cycles, in msecs. 988 * cycles, in msecs.
956 * 989 *
990 * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported
991 * interface combinations. In each nested item, it contains attributes
992 * defined in &enum nl80211_if_combination_attrs.
993 * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like
994 * %NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that
995 * are managed in software: interfaces of these types aren't subject to
996 * any restrictions in their number or combinations.
997 *
957 * @NL80211_ATTR_MAX: highest attribute number currently defined 998 * @NL80211_ATTR_MAX: highest attribute number currently defined
958 * @__NL80211_ATTR_AFTER_LAST: internal use 999 * @__NL80211_ATTR_AFTER_LAST: internal use
959 */ 1000 */
@@ -1149,6 +1190,9 @@ enum nl80211_attrs {
1149 1190
1150 NL80211_ATTR_SCHED_SCAN_INTERVAL, 1191 NL80211_ATTR_SCHED_SCAN_INTERVAL,
1151 1192
1193 NL80211_ATTR_INTERFACE_COMBINATIONS,
1194 NL80211_ATTR_SOFTWARE_IFTYPES,
1195
1152 /* add attributes here, update the policy in nl80211.c */ 1196 /* add attributes here, update the policy in nl80211.c */
1153 1197
1154 __NL80211_ATTR_AFTER_LAST, 1198 __NL80211_ATTR_AFTER_LAST,
@@ -1201,7 +1245,9 @@ enum nl80211_attrs {
1201 * @NL80211_IFTYPE_ADHOC: independent BSS member 1245 * @NL80211_IFTYPE_ADHOC: independent BSS member
1202 * @NL80211_IFTYPE_STATION: managed BSS member 1246 * @NL80211_IFTYPE_STATION: managed BSS member
1203 * @NL80211_IFTYPE_AP: access point 1247 * @NL80211_IFTYPE_AP: access point
1204 * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points 1248 * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points; VLAN interfaces
1249 * are a bit special in that they must always be tied to a pre-existing
1250 * AP type interface.
1205 * @NL80211_IFTYPE_WDS: wireless distribution interface 1251 * @NL80211_IFTYPE_WDS: wireless distribution interface
1206 * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames 1252 * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
1207 * @NL80211_IFTYPE_MESH_POINT: mesh point 1253 * @NL80211_IFTYPE_MESH_POINT: mesh point
@@ -2206,4 +2252,78 @@ enum nl80211_wowlan_triggers {
2206 MAX_NL80211_WOWLAN_TRIG = NUM_NL80211_WOWLAN_TRIG - 1 2252 MAX_NL80211_WOWLAN_TRIG = NUM_NL80211_WOWLAN_TRIG - 1
2207}; 2253};
2208 2254
2255/**
2256 * enum nl80211_iface_limit_attrs - limit attributes
2257 * @NL80211_IFACE_LIMIT_UNSPEC: (reserved)
2258 * @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that
2259 * can be chosen from this set of interface types (u32)
2260 * @NL80211_IFACE_LIMIT_TYPES: nested attribute containing a
2261 * flag attribute for each interface type in this set
2262 * @NUM_NL80211_IFACE_LIMIT: number of attributes
2263 * @MAX_NL80211_IFACE_LIMIT: highest attribute number
2264 */
2265enum nl80211_iface_limit_attrs {
2266 NL80211_IFACE_LIMIT_UNSPEC,
2267 NL80211_IFACE_LIMIT_MAX,
2268 NL80211_IFACE_LIMIT_TYPES,
2269
2270 /* keep last */
2271 NUM_NL80211_IFACE_LIMIT,
2272 MAX_NL80211_IFACE_LIMIT = NUM_NL80211_IFACE_LIMIT - 1
2273};
2274
2275/**
2276 * enum nl80211_if_combination_attrs -- interface combination attributes
2277 *
2278 * @NL80211_IFACE_COMB_UNSPEC: (reserved)
2279 * @NL80211_IFACE_COMB_LIMITS: Nested attributes containing the limits
2280 * for given interface types, see &enum nl80211_iface_limit_attrs.
2281 * @NL80211_IFACE_COMB_MAXNUM: u32 attribute giving the total number of
2282 * interfaces that can be created in this group. This number doesn't
2283 * apply to interfaces purely managed in software, which are listed
2284 * in a separate attribute %NL80211_ATTR_INTERFACES_SOFTWARE.
2285 * @NL80211_IFACE_COMB_STA_AP_BI_MATCH: flag attribute specifying that
2286 * beacon intervals within this group must be all the same even for
2287 * infrastructure and AP/GO combinations, i.e. the GO(s) must adopt
2288 * the infrastructure network's beacon interval.
2289 * @NL80211_IFACE_COMB_NUM_CHANNELS: u32 attribute specifying how many
2290 * different channels may be used within this group.
2291 * @NUM_NL80211_IFACE_COMB: number of attributes
2292 * @MAX_NL80211_IFACE_COMB: highest attribute number
2293 *
2294 * Examples:
2295 * limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2
2296 * => allows an AP and a STA that must match BIs
2297 *
2298 * numbers = [ #{AP, P2P-GO} <= 8 ], channels = 1, max = 8
2299 * => allows 8 of AP/GO
2300 *
2301 * numbers = [ #{STA} <= 2 ], channels = 2, max = 2
2302 * => allows two STAs on different channels
2303 *
2304 * numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4
2305 * => allows a STA plus three P2P interfaces
2306 *
2307 * The list of these four possiblities could completely be contained
2308 * within the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute to indicate
2309 * that any of these groups must match.
2310 *
2311 * "Combinations" of just a single interface will not be listed here,
2312 * a single interface of any valid interface type is assumed to always
2313 * be possible by itself. This means that implicitly, for each valid
2314 * interface type, the following group always exists:
2315 * numbers = [ #{<type>} <= 1 ], channels = 1, max = 1
2316 */
2317enum nl80211_if_combination_attrs {
2318 NL80211_IFACE_COMB_UNSPEC,
2319 NL80211_IFACE_COMB_LIMITS,
2320 NL80211_IFACE_COMB_MAXNUM,
2321 NL80211_IFACE_COMB_STA_AP_BI_MATCH,
2322 NL80211_IFACE_COMB_NUM_CHANNELS,
2323
2324 /* keep last */
2325 NUM_NL80211_IFACE_COMB,
2326 MAX_NL80211_IFACE_COMB = NUM_NL80211_IFACE_COMB - 1
2327};
2328
2209#endif /* __LINUX_NL80211_H */ 2329#endif /* __LINUX_NL80211_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index e1f1b41f7b13..04afcfb9eaf4 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1547,6 +1547,10 @@ struct cfg80211_ops {
1547 * hints read the documenation for regulatory_hint_found_beacon() 1547 * hints read the documenation for regulatory_hint_found_beacon()
1548 * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this 1548 * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this
1549 * wiphy at all 1549 * wiphy at all
1550 * @WIPHY_FLAG_ENFORCE_COMBINATIONS: Set this flag to enforce interface
1551 * combinations for this device. This flag is used for backward
1552 * compatibility only until all drivers advertise combinations and
1553 * they will always be enforced.
1550 * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled 1554 * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled
1551 * by default -- this flag will be set depending on the kernel's default 1555 * by default -- this flag will be set depending on the kernel's default
1552 * on wiphy_new(), but can be changed by the driver if it has a good 1556 * on wiphy_new(), but can be changed by the driver if it has a good
@@ -1574,6 +1578,81 @@ enum wiphy_flags {
1574 WIPHY_FLAG_IBSS_RSN = BIT(8), 1578 WIPHY_FLAG_IBSS_RSN = BIT(8),
1575 WIPHY_FLAG_MESH_AUTH = BIT(10), 1579 WIPHY_FLAG_MESH_AUTH = BIT(10),
1576 WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11), 1580 WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11),
1581 WIPHY_FLAG_ENFORCE_COMBINATIONS = BIT(12),
1582};
1583
1584/**
1585 * struct ieee80211_iface_limit - limit on certain interface types
1586 * @max: maximum number of interfaces of these types
1587 * @types: interface types (bits)
1588 */
1589struct ieee80211_iface_limit {
1590 u16 max;
1591 u16 types;
1592};
1593
1594/**
1595 * struct ieee80211_iface_combination - possible interface combination
1596 * @limits: limits for the given interface types
1597 * @n_limits: number of limitations
1598 * @num_different_channels: can use up to this many different channels
1599 * @max_interfaces: maximum number of interfaces in total allowed in this
1600 * group
1601 * @beacon_int_infra_match: In this combination, the beacon intervals
1602 * between infrastructure and AP types must match. This is required
1603 * only in special cases.
1604 *
1605 * These examples can be expressed as follows:
1606 *
1607 * Allow #STA <= 1, #AP <= 1, matching BI, channels = 1, 2 total:
1608 *
1609 * struct ieee80211_iface_limit limits1[] = {
1610 * { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), },
1611 * { .max = 1, .types = BIT(NL80211_IFTYPE_AP}, },
1612 * };
1613 * struct ieee80211_iface_combination combination1 = {
1614 * .limits = limits1,
1615 * .n_limits = ARRAY_SIZE(limits1),
1616 * .max_interfaces = 2,
1617 * .beacon_int_infra_match = true,
1618 * };
1619 *
1620 *
1621 * Allow #{AP, P2P-GO} <= 8, channels = 1, 8 total:
1622 *
1623 * struct ieee80211_iface_limit limits2[] = {
1624 * { .max = 8, .types = BIT(NL80211_IFTYPE_AP) |
1625 * BIT(NL80211_IFTYPE_P2P_GO), },
1626 * };
1627 * struct ieee80211_iface_combination combination2 = {
1628 * .limits = limits2,
1629 * .n_limits = ARRAY_SIZE(limits2),
1630 * .max_interfaces = 8,
1631 * .num_different_channels = 1,
1632 * };
1633 *
1634 *
1635 * Allow #STA <= 1, #{P2P-client,P2P-GO} <= 3 on two channels, 4 total.
1636 * This allows for an infrastructure connection and three P2P connections.
1637 *
1638 * struct ieee80211_iface_limit limits3[] = {
1639 * { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), },
1640 * { .max = 3, .types = BIT(NL80211_IFTYPE_P2P_GO) |
1641 * BIT(NL80211_IFTYPE_P2P_CLIENT), },
1642 * };
1643 * struct ieee80211_iface_combination combination3 = {
1644 * .limits = limits3,
1645 * .n_limits = ARRAY_SIZE(limits3),
1646 * .max_interfaces = 4,
1647 * .num_different_channels = 2,
1648 * };
1649 */
1650struct ieee80211_iface_combination {
1651 const struct ieee80211_iface_limit *limits;
1652 u32 num_different_channels;
1653 u16 max_interfaces;
1654 u8 n_limits;
1655 bool beacon_int_infra_match;
1577}; 1656};
1578 1657
1579struct mac_address { 1658struct mac_address {
@@ -1653,6 +1732,11 @@ struct wiphy_wowlan_support {
1653 * @priv: driver private data (sized according to wiphy_new() parameter) 1732 * @priv: driver private data (sized according to wiphy_new() parameter)
1654 * @interface_modes: bitmask of interfaces types valid for this wiphy, 1733 * @interface_modes: bitmask of interfaces types valid for this wiphy,
1655 * must be set by driver 1734 * must be set by driver
1735 * @iface_combinations: Valid interface combinations array, should not
1736 * list single interface types.
1737 * @n_iface_combinations: number of entries in @iface_combinations array.
1738 * @software_iftypes: bitmask of software interface types, these are not
1739 * subject to any restrictions since they are purely managed in SW.
1656 * @flags: wiphy flags, see &enum wiphy_flags 1740 * @flags: wiphy flags, see &enum wiphy_flags
1657 * @bss_priv_size: each BSS struct has private data allocated with it, 1741 * @bss_priv_size: each BSS struct has private data allocated with it,
1658 * this variable determines its size 1742 * this variable determines its size
@@ -1697,6 +1781,10 @@ struct wiphy {
1697 1781
1698 const struct ieee80211_txrx_stypes *mgmt_stypes; 1782 const struct ieee80211_txrx_stypes *mgmt_stypes;
1699 1783
1784 const struct ieee80211_iface_combination *iface_combinations;
1785 int n_iface_combinations;
1786 u16 software_iftypes;
1787
1700 u16 n_addresses; 1788 u16 n_addresses;
1701 1789
1702 /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ 1790 /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 7f89011fa22d..79a2281678bf 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -685,7 +685,7 @@ EXPORT_SYMBOL(ieee80211_alloc_hw);
685int ieee80211_register_hw(struct ieee80211_hw *hw) 685int ieee80211_register_hw(struct ieee80211_hw *hw)
686{ 686{
687 struct ieee80211_local *local = hw_to_local(hw); 687 struct ieee80211_local *local = hw_to_local(hw);
688 int result; 688 int result, i;
689 enum ieee80211_band band; 689 enum ieee80211_band band;
690 int channels, max_bitrates; 690 int channels, max_bitrates;
691 bool supp_ht; 691 bool supp_ht;
@@ -743,11 +743,19 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
743 return -ENOMEM; 743 return -ENOMEM;
744 744
745 /* if low-level driver supports AP, we also support VLAN */ 745 /* if low-level driver supports AP, we also support VLAN */
746 if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) 746 if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
747 local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); 747 hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
748 hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
749 }
748 750
749 /* mac80211 always supports monitor */ 751 /* mac80211 always supports monitor */
750 local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); 752 hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
753 hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
754
755 /* mac80211 doesn't support more than 1 channel */
756 for (i = 0; i < hw->wiphy->n_iface_combinations; i++)
757 if (hw->wiphy->iface_combinations[i].num_different_channels > 1)
758 return -EINVAL;
751 759
752#ifndef CONFIG_MAC80211_MESH 760#ifndef CONFIG_MAC80211_MESH
753 /* mesh depends on Kconfig, but drivers should set it if they want */ 761 /* mesh depends on Kconfig, but drivers should set it if they want */
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 18b002f16860..c22ef3492ee6 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -416,6 +416,67 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
416} 416}
417EXPORT_SYMBOL(wiphy_new); 417EXPORT_SYMBOL(wiphy_new);
418 418
419static int wiphy_verify_combinations(struct wiphy *wiphy)
420{
421 const struct ieee80211_iface_combination *c;
422 int i, j;
423
424 /* If we have combinations enforce them */
425 if (wiphy->n_iface_combinations)
426 wiphy->flags |= WIPHY_FLAG_ENFORCE_COMBINATIONS;
427
428 for (i = 0; i < wiphy->n_iface_combinations; i++) {
429 u32 cnt = 0;
430 u16 all_iftypes = 0;
431
432 c = &wiphy->iface_combinations[i];
433
434 /* Combinations with just one interface aren't real */
435 if (WARN_ON(c->max_interfaces < 2))
436 return -EINVAL;
437
438 /* Need at least one channel */
439 if (WARN_ON(!c->num_different_channels))
440 return -EINVAL;
441
442 if (WARN_ON(!c->n_limits))
443 return -EINVAL;
444
445 for (j = 0; j < c->n_limits; j++) {
446 u16 types = c->limits[j].types;
447
448 /*
449 * interface types shouldn't overlap, this is
450 * used in cfg80211_can_change_interface()
451 */
452 if (WARN_ON(types & all_iftypes))
453 return -EINVAL;
454 all_iftypes |= types;
455
456 if (WARN_ON(!c->limits[j].max))
457 return -EINVAL;
458
459 /* Shouldn't list software iftypes in combinations! */
460 if (WARN_ON(wiphy->software_iftypes & types))
461 return -EINVAL;
462
463 cnt += c->limits[j].max;
464 /*
465 * Don't advertise an unsupported type
466 * in a combination.
467 */
468 if (WARN_ON((wiphy->interface_modes & types) != types))
469 return -EINVAL;
470 }
471
472 /* You can't even choose that many! */
473 if (WARN_ON(cnt < c->max_interfaces))
474 return -EINVAL;
475 }
476
477 return 0;
478}
479
419int wiphy_register(struct wiphy *wiphy) 480int wiphy_register(struct wiphy *wiphy)
420{ 481{
421 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 482 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
@@ -444,6 +505,10 @@ int wiphy_register(struct wiphy *wiphy)
444 if (WARN_ON(ifmodes != wiphy->interface_modes)) 505 if (WARN_ON(ifmodes != wiphy->interface_modes))
445 wiphy->interface_modes = ifmodes; 506 wiphy->interface_modes = ifmodes;
446 507
508 res = wiphy_verify_combinations(wiphy);
509 if (res)
510 return res;
511
447 /* sanity check supported bands/channels */ 512 /* sanity check supported bands/channels */
448 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 513 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
449 sband = wiphy->bands[band]; 514 sband = wiphy->bands[band];
@@ -698,6 +763,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
698 struct net_device *dev = ndev; 763 struct net_device *dev = ndev;
699 struct wireless_dev *wdev = dev->ieee80211_ptr; 764 struct wireless_dev *wdev = dev->ieee80211_ptr;
700 struct cfg80211_registered_device *rdev; 765 struct cfg80211_registered_device *rdev;
766 int ret;
701 767
702 if (!wdev) 768 if (!wdev)
703 return NOTIFY_DONE; 769 return NOTIFY_DONE;
@@ -893,6 +959,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
893 return notifier_from_errno(-EOPNOTSUPP); 959 return notifier_from_errno(-EOPNOTSUPP);
894 if (rfkill_blocked(rdev->rfkill)) 960 if (rfkill_blocked(rdev->rfkill))
895 return notifier_from_errno(-ERFKILL); 961 return notifier_from_errno(-ERFKILL);
962 ret = cfg80211_can_add_interface(rdev, wdev->iftype);
963 if (ret)
964 return notifier_from_errno(ret);
896 break; 965 break;
897 } 966 }
898 967
diff --git a/net/wireless/core.h b/net/wireless/core.h
index d4b8f4c0bbbb..bf0fb40e3c8b 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -422,6 +422,17 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
422 u32 *flags, struct vif_params *params); 422 u32 *flags, struct vif_params *params);
423void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); 423void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
424 424
425int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
426 struct wireless_dev *wdev,
427 enum nl80211_iftype iftype);
428
429static inline int
430cfg80211_can_add_interface(struct cfg80211_registered_device *rdev,
431 enum nl80211_iftype iftype)
432{
433 return cfg80211_can_change_interface(rdev, NULL, iftype);
434}
435
425struct ieee80211_channel * 436struct ieee80211_channel *
426rdev_freq_to_chan(struct cfg80211_registered_device *rdev, 437rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
427 int freq, enum nl80211_channel_type channel_type); 438 int freq, enum nl80211_channel_type channel_type);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9ef8e287d61b..beac296b1fde 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -564,6 +564,88 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
564 return 0; 564 return 0;
565} 565}
566 566
567static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes)
568{
569 struct nlattr *nl_modes = nla_nest_start(msg, attr);
570 int i;
571
572 if (!nl_modes)
573 goto nla_put_failure;
574
575 i = 0;
576 while (ifmodes) {
577 if (ifmodes & 1)
578 NLA_PUT_FLAG(msg, i);
579 ifmodes >>= 1;
580 i++;
581 }
582
583 nla_nest_end(msg, nl_modes);
584 return 0;
585
586nla_put_failure:
587 return -ENOBUFS;
588}
589
590static int nl80211_put_iface_combinations(struct wiphy *wiphy,
591 struct sk_buff *msg)
592{
593 struct nlattr *nl_combis;
594 int i, j;
595
596 nl_combis = nla_nest_start(msg,
597 NL80211_ATTR_INTERFACE_COMBINATIONS);
598 if (!nl_combis)
599 goto nla_put_failure;
600
601 for (i = 0; i < wiphy->n_iface_combinations; i++) {
602 const struct ieee80211_iface_combination *c;
603 struct nlattr *nl_combi, *nl_limits;
604
605 c = &wiphy->iface_combinations[i];
606
607 nl_combi = nla_nest_start(msg, i + 1);
608 if (!nl_combi)
609 goto nla_put_failure;
610
611 nl_limits = nla_nest_start(msg, NL80211_IFACE_COMB_LIMITS);
612 if (!nl_limits)
613 goto nla_put_failure;
614
615 for (j = 0; j < c->n_limits; j++) {
616 struct nlattr *nl_limit;
617
618 nl_limit = nla_nest_start(msg, j + 1);
619 if (!nl_limit)
620 goto nla_put_failure;
621 NLA_PUT_U32(msg, NL80211_IFACE_LIMIT_MAX,
622 c->limits[j].max);
623 if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES,
624 c->limits[j].types))
625 goto nla_put_failure;
626 nla_nest_end(msg, nl_limit);
627 }
628
629 nla_nest_end(msg, nl_limits);
630
631 if (c->beacon_int_infra_match)
632 NLA_PUT_FLAG(msg,
633 NL80211_IFACE_COMB_STA_AP_BI_MATCH);
634 NLA_PUT_U32(msg, NL80211_IFACE_COMB_NUM_CHANNELS,
635 c->num_different_channels);
636 NLA_PUT_U32(msg, NL80211_IFACE_COMB_MAXNUM,
637 c->max_interfaces);
638
639 nla_nest_end(msg, nl_combi);
640 }
641
642 nla_nest_end(msg, nl_combis);
643
644 return 0;
645nla_put_failure:
646 return -ENOBUFS;
647}
648
567static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, 649static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
568 struct cfg80211_registered_device *dev) 650 struct cfg80211_registered_device *dev)
569{ 651{
@@ -571,13 +653,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
571 struct nlattr *nl_bands, *nl_band; 653 struct nlattr *nl_bands, *nl_band;
572 struct nlattr *nl_freqs, *nl_freq; 654 struct nlattr *nl_freqs, *nl_freq;
573 struct nlattr *nl_rates, *nl_rate; 655 struct nlattr *nl_rates, *nl_rate;
574 struct nlattr *nl_modes;
575 struct nlattr *nl_cmds; 656 struct nlattr *nl_cmds;
576 enum ieee80211_band band; 657 enum ieee80211_band band;
577 struct ieee80211_channel *chan; 658 struct ieee80211_channel *chan;
578 struct ieee80211_rate *rate; 659 struct ieee80211_rate *rate;
579 int i; 660 int i;
580 u16 ifmodes = dev->wiphy.interface_modes;
581 const struct ieee80211_txrx_stypes *mgmt_stypes = 661 const struct ieee80211_txrx_stypes *mgmt_stypes =
582 dev->wiphy.mgmt_stypes; 662 dev->wiphy.mgmt_stypes;
583 663
@@ -637,20 +717,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
637 } 717 }
638 } 718 }
639 719
640 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); 720 if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
641 if (!nl_modes) 721 dev->wiphy.interface_modes))
642 goto nla_put_failure; 722 goto nla_put_failure;
643 723
644 i = 0;
645 while (ifmodes) {
646 if (ifmodes & 1)
647 NLA_PUT_FLAG(msg, i);
648 ifmodes >>= 1;
649 i++;
650 }
651
652 nla_nest_end(msg, nl_modes);
653
654 nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); 724 nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
655 if (!nl_bands) 725 if (!nl_bands)
656 goto nla_put_failure; 726 goto nla_put_failure;
@@ -865,6 +935,13 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
865 nla_nest_end(msg, nl_wowlan); 935 nla_nest_end(msg, nl_wowlan);
866 } 936 }
867 937
938 if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
939 dev->wiphy.software_iftypes))
940 goto nla_put_failure;
941
942 if (nl80211_put_iface_combinations(&dev->wiphy, msg))
943 goto nla_put_failure;
944
868 return genlmsg_end(msg, hdr); 945 return genlmsg_end(msg, hdr);
869 946
870 nla_put_failure: 947 nla_put_failure:
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 414c9f604df6..95e4e254da0a 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -803,6 +803,11 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
803 return -EBUSY; 803 return -EBUSY;
804 804
805 if (ntype != otype) { 805 if (ntype != otype) {
806 err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
807 ntype);
808 if (err)
809 return err;
810
806 dev->ieee80211_ptr->use_4addr = false; 811 dev->ieee80211_ptr->use_4addr = false;
807 dev->ieee80211_ptr->mesh_id_up_len = 0; 812 dev->ieee80211_ptr->mesh_id_up_len = 0;
808 813
@@ -921,3 +926,78 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
921 926
922 return res; 927 return res;
923} 928}
929
930int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
931 struct wireless_dev *wdev,
932 enum nl80211_iftype iftype)
933{
934 struct wireless_dev *wdev_iter;
935 int num[NUM_NL80211_IFTYPES];
936 int total = 1;
937 int i, j;
938
939 ASSERT_RTNL();
940
941 /* Always allow software iftypes */
942 if (rdev->wiphy.software_iftypes & BIT(iftype))
943 return 0;
944
945 /*
946 * Drivers will gradually all set this flag, until all
947 * have it we only enforce for those that set it.
948 */
949 if (!(rdev->wiphy.flags & WIPHY_FLAG_ENFORCE_COMBINATIONS))
950 return 0;
951
952 memset(num, 0, sizeof(num));
953
954 num[iftype] = 1;
955
956 mutex_lock(&rdev->devlist_mtx);
957 list_for_each_entry(wdev_iter, &rdev->netdev_list, list) {
958 if (wdev_iter == wdev)
959 continue;
960 if (!netif_running(wdev_iter->netdev))
961 continue;
962
963 if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype))
964 continue;
965
966 num[wdev_iter->iftype]++;
967 total++;
968 }
969 mutex_unlock(&rdev->devlist_mtx);
970
971 for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) {
972 const struct ieee80211_iface_combination *c;
973 struct ieee80211_iface_limit *limits;
974
975 c = &rdev->wiphy.iface_combinations[i];
976
977 limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits,
978 GFP_KERNEL);
979 if (!limits)
980 return -ENOMEM;
981 if (total > c->max_interfaces)
982 goto cont;
983
984 for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
985 if (rdev->wiphy.software_iftypes & BIT(iftype))
986 continue;
987 for (j = 0; j < c->n_limits; j++) {
988 if (!(limits[j].types & iftype))
989 continue;
990 if (limits[j].max < num[iftype])
991 goto cont;
992 limits[j].max -= num[iftype];
993 }
994 }
995 /* yay, it fits */
996 kfree(limits);
997 return 0;
998 cont:
999 kfree(limits);
1000 }
1001
1002 return -EBUSY;
1003}