diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/main.c | 7 | ||||
-rw-r--r-- | net/wireless/core.c | 9 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 22 |
3 files changed, 35 insertions, 3 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 638b75f36e23..396cfb2d0f46 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -1675,6 +1675,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1675 | } | 1675 | } |
1676 | } | 1676 | } |
1677 | 1677 | ||
1678 | /* if low-level driver supports AP, we also support VLAN */ | ||
1679 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) | ||
1680 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); | ||
1681 | |||
1682 | /* mac80211 always supports monitor */ | ||
1683 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); | ||
1684 | |||
1678 | result = wiphy_register(local->hw.wiphy); | 1685 | result = wiphy_register(local->hw.wiphy); |
1679 | if (result < 0) | 1686 | if (result < 0) |
1680 | return result; | 1687 | return result; |
diff --git a/net/wireless/core.c b/net/wireless/core.c index f1da0b93bc56..7e995ac06a0c 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This is the linux wireless configuration interface. | 2 | * This is the linux wireless configuration interface. |
3 | * | 3 | * |
4 | * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net> |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/if.h> | 7 | #include <linux/if.h> |
@@ -259,6 +259,13 @@ int wiphy_register(struct wiphy *wiphy) | |||
259 | struct ieee80211_supported_band *sband; | 259 | struct ieee80211_supported_band *sband; |
260 | bool have_band = false; | 260 | bool have_band = false; |
261 | int i; | 261 | int i; |
262 | u16 ifmodes = wiphy->interface_modes; | ||
263 | |||
264 | /* sanity check ifmodes */ | ||
265 | WARN_ON(!ifmodes); | ||
266 | ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; | ||
267 | if (WARN_ON(ifmodes != wiphy->interface_modes)) | ||
268 | wiphy->interface_modes = ifmodes; | ||
262 | 269 | ||
263 | /* sanity check supported bands/channels */ | 270 | /* sanity check supported bands/channels */ |
264 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 271 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4d6c02afd6f5..77880ba8b619 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -113,10 +113,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
113 | struct nlattr *nl_bands, *nl_band; | 113 | struct nlattr *nl_bands, *nl_band; |
114 | struct nlattr *nl_freqs, *nl_freq; | 114 | struct nlattr *nl_freqs, *nl_freq; |
115 | struct nlattr *nl_rates, *nl_rate; | 115 | struct nlattr *nl_rates, *nl_rate; |
116 | struct nlattr *nl_modes; | ||
116 | enum ieee80211_band band; | 117 | enum ieee80211_band band; |
117 | struct ieee80211_channel *chan; | 118 | struct ieee80211_channel *chan; |
118 | struct ieee80211_rate *rate; | 119 | struct ieee80211_rate *rate; |
119 | int i; | 120 | int i; |
121 | u16 ifmodes = dev->wiphy.interface_modes; | ||
120 | 122 | ||
121 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); | 123 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); |
122 | if (!hdr) | 124 | if (!hdr) |
@@ -125,6 +127,20 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
125 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); | 127 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); |
126 | NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); | 128 | NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); |
127 | 129 | ||
130 | nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); | ||
131 | if (!nl_modes) | ||
132 | goto nla_put_failure; | ||
133 | |||
134 | i = 0; | ||
135 | while (ifmodes) { | ||
136 | if (ifmodes & 1) | ||
137 | NLA_PUT_FLAG(msg, i); | ||
138 | ifmodes >>= 1; | ||
139 | i++; | ||
140 | } | ||
141 | |||
142 | nla_nest_end(msg, nl_modes); | ||
143 | |||
128 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); | 144 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); |
129 | if (!nl_bands) | 145 | if (!nl_bands) |
130 | goto nla_put_failure; | 146 | goto nla_put_failure; |
@@ -415,7 +431,8 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
415 | ifindex = dev->ifindex; | 431 | ifindex = dev->ifindex; |
416 | dev_put(dev); | 432 | dev_put(dev); |
417 | 433 | ||
418 | if (!drv->ops->change_virtual_intf) { | 434 | if (!drv->ops->change_virtual_intf || |
435 | !(drv->wiphy.interface_modes & (1 << type))) { | ||
419 | err = -EOPNOTSUPP; | 436 | err = -EOPNOTSUPP; |
420 | goto unlock; | 437 | goto unlock; |
421 | } | 438 | } |
@@ -462,7 +479,8 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
462 | if (IS_ERR(drv)) | 479 | if (IS_ERR(drv)) |
463 | return PTR_ERR(drv); | 480 | return PTR_ERR(drv); |
464 | 481 | ||
465 | if (!drv->ops->add_virtual_intf) { | 482 | if (!drv->ops->add_virtual_intf || |
483 | !(drv->wiphy.interface_modes & (1 << type))) { | ||
466 | err = -EOPNOTSUPP; | 484 | err = -EOPNOTSUPP; |
467 | goto unlock; | 485 | goto unlock; |
468 | } | 486 | } |