diff options
author | David S. Miller <davem@davemloft.net> | 2015-03-31 16:39:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-31 16:39:04 -0400 |
commit | 7b6249bba940f57c20cdde793b306ca3831778c7 (patch) | |
tree | 24caf2ec9ea6fca08fe225228614807d0919b4b2 /net/wireless | |
parent | fbcb21705930f2930f506149d0b8d36dfbe45107 (diff) | |
parent | 2c44be81f0fc147eed9dc63e2601318b2c007aeb (diff) |
Merge tag 'mac80211-next-for-davem-2015-03-30' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg says:
====================
Lots of updates for net-next; along with the usual flurry
of small fixes, cleanups and internal features we have:
* VHT support for TDLS and IBSS (conditional on drivers though)
* first TX performance improvements (the biggest will come later)
* many suspend/resume (race) fixes
* name_assign_type support from Tom Gundersen
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/Kconfig | 8 | ||||
-rw-r--r-- | net/wireless/ibss.c | 2 | ||||
-rw-r--r-- | net/wireless/mlme.c | 6 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 84 | ||||
-rw-r--r-- | net/wireless/rdev-ops.h | 5 | ||||
-rw-r--r-- | net/wireless/reg.c | 111 | ||||
-rw-r--r-- | net/wireless/reg.h | 15 | ||||
-rw-r--r-- | net/wireless/scan.c | 302 | ||||
-rw-r--r-- | net/wireless/sme.c | 16 | ||||
-rw-r--r-- | net/wireless/trace.h | 32 | ||||
-rw-r--r-- | net/wireless/util.c | 130 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 18 | ||||
-rw-r--r-- | net/wireless/wext-compat.h | 6 |
13 files changed, 556 insertions, 179 deletions
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 29c8675f9a11..b13dfb4ff001 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -178,10 +178,18 @@ config CFG80211_WEXT | |||
178 | bool "cfg80211 wireless extensions compatibility" | 178 | bool "cfg80211 wireless extensions compatibility" |
179 | depends on CFG80211 | 179 | depends on CFG80211 |
180 | select WEXT_CORE | 180 | select WEXT_CORE |
181 | default y if CFG80211_WEXT_EXPORT | ||
181 | help | 182 | help |
182 | Enable this option if you need old userspace for wireless | 183 | Enable this option if you need old userspace for wireless |
183 | extensions with cfg80211-based drivers. | 184 | extensions with cfg80211-based drivers. |
184 | 185 | ||
186 | config CFG80211_WEXT_EXPORT | ||
187 | bool | ||
188 | depends on CFG80211 | ||
189 | help | ||
190 | Drivers should select this option if they require cfg80211's | ||
191 | wext compatibility symbols to be exported. | ||
192 | |||
185 | config LIB80211 | 193 | config LIB80211 |
186 | tristate | 194 | tristate |
187 | default n | 195 | default n |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 6309b9c0bcd5..4c55fab9b4e4 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -30,7 +30,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, | |||
30 | return; | 30 | return; |
31 | 31 | ||
32 | bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0, | 32 | bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0, |
33 | WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); | 33 | IEEE80211_BSS_TYPE_IBSS, IEEE80211_PRIVACY_ANY); |
34 | 34 | ||
35 | if (WARN_ON(!bss)) | 35 | if (WARN_ON(!bss)) |
36 | return; | 36 | return; |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 2c52b59e43f3..7aae329e2b4e 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -229,7 +229,8 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
229 | return -EALREADY; | 229 | return -EALREADY; |
230 | 230 | ||
231 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, | 231 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, |
232 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | 232 | IEEE80211_BSS_TYPE_ESS, |
233 | IEEE80211_PRIVACY_ANY); | ||
233 | if (!req.bss) | 234 | if (!req.bss) |
234 | return -ENOENT; | 235 | return -ENOENT; |
235 | 236 | ||
@@ -296,7 +297,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
296 | rdev->wiphy.vht_capa_mod_mask); | 297 | rdev->wiphy.vht_capa_mod_mask); |
297 | 298 | ||
298 | req->bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, | 299 | req->bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, |
299 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | 300 | IEEE80211_BSS_TYPE_ESS, |
301 | IEEE80211_PRIVACY_ANY); | ||
300 | if (!req->bss) | 302 | if (!req->bss) |
301 | return -ENOENT; | 303 | return -ENOENT; |
302 | 304 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2fb804bfa361..6dd1ab3b10ea 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -399,6 +399,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { | |||
399 | [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG }, | 399 | [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG }, |
400 | [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 }, | 400 | [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 }, |
401 | [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 }, | 401 | [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 }, |
402 | [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG }, | ||
402 | }; | 403 | }; |
403 | 404 | ||
404 | /* policy for the key attributes */ | 405 | /* policy for the key attributes */ |
@@ -1098,8 +1099,6 @@ static int nl80211_send_wowlan(struct sk_buff *msg, | |||
1098 | if (large && nl80211_send_wowlan_tcp_caps(rdev, msg)) | 1099 | if (large && nl80211_send_wowlan_tcp_caps(rdev, msg)) |
1099 | return -ENOBUFS; | 1100 | return -ENOBUFS; |
1100 | 1101 | ||
1101 | /* TODO: send wowlan net detect */ | ||
1102 | |||
1103 | nla_nest_end(msg, nl_wowlan); | 1102 | nla_nest_end(msg, nl_wowlan); |
1104 | 1103 | ||
1105 | return 0; | 1104 | return 0; |
@@ -2668,7 +2667,8 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2668 | 2667 | ||
2669 | wdev = rdev_add_virtual_intf(rdev, | 2668 | wdev = rdev_add_virtual_intf(rdev, |
2670 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), | 2669 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), |
2671 | type, err ? NULL : &flags, ¶ms); | 2670 | NET_NAME_USER, type, err ? NULL : &flags, |
2671 | ¶ms); | ||
2672 | if (WARN_ON(!wdev)) { | 2672 | if (WARN_ON(!wdev)) { |
2673 | nlmsg_free(msg); | 2673 | nlmsg_free(msg); |
2674 | return -EPROTO; | 2674 | return -EPROTO; |
@@ -4968,7 +4968,10 @@ static int parse_reg_rule(struct nlattr *tb[], | |||
4968 | static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | 4968 | static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) |
4969 | { | 4969 | { |
4970 | char *data = NULL; | 4970 | char *data = NULL; |
4971 | bool is_indoor; | ||
4971 | enum nl80211_user_reg_hint_type user_reg_hint_type; | 4972 | enum nl80211_user_reg_hint_type user_reg_hint_type; |
4973 | u32 owner_nlportid; | ||
4974 | |||
4972 | 4975 | ||
4973 | /* | 4976 | /* |
4974 | * You should only get this when cfg80211 hasn't yet initialized | 4977 | * You should only get this when cfg80211 hasn't yet initialized |
@@ -4994,7 +4997,15 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
4994 | data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); | 4997 | data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); |
4995 | return regulatory_hint_user(data, user_reg_hint_type); | 4998 | return regulatory_hint_user(data, user_reg_hint_type); |
4996 | case NL80211_USER_REG_HINT_INDOOR: | 4999 | case NL80211_USER_REG_HINT_INDOOR: |
4997 | return regulatory_hint_indoor_user(); | 5000 | if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) { |
5001 | owner_nlportid = info->snd_portid; | ||
5002 | is_indoor = !!info->attrs[NL80211_ATTR_REG_INDOOR]; | ||
5003 | } else { | ||
5004 | owner_nlportid = 0; | ||
5005 | is_indoor = true; | ||
5006 | } | ||
5007 | |||
5008 | return regulatory_hint_indoor(is_indoor, owner_nlportid); | ||
4998 | default: | 5009 | default: |
4999 | return -EINVAL; | 5010 | return -EINVAL; |
5000 | } | 5011 | } |
@@ -5275,7 +5286,7 @@ do { \ | |||
5275 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, | 5286 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, |
5276 | 0, 65535, mask, | 5287 | 0, 65535, mask, |
5277 | NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16); | 5288 | NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16); |
5278 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 1, 0xffffffff, | 5289 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 0, 0xffffffff, |
5279 | mask, NL80211_MESHCONF_PLINK_TIMEOUT, | 5290 | mask, NL80211_MESHCONF_PLINK_TIMEOUT, |
5280 | nla_get_u32); | 5291 | nla_get_u32); |
5281 | if (mask_out) | 5292 | if (mask_out) |
@@ -7275,8 +7286,18 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
7275 | break; | 7286 | break; |
7276 | case NL80211_CHAN_WIDTH_20: | 7287 | case NL80211_CHAN_WIDTH_20: |
7277 | case NL80211_CHAN_WIDTH_40: | 7288 | case NL80211_CHAN_WIDTH_40: |
7278 | if (rdev->wiphy.features & NL80211_FEATURE_HT_IBSS) | 7289 | if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)) |
7279 | break; | 7290 | return -EINVAL; |
7291 | break; | ||
7292 | case NL80211_CHAN_WIDTH_80: | ||
7293 | case NL80211_CHAN_WIDTH_80P80: | ||
7294 | case NL80211_CHAN_WIDTH_160: | ||
7295 | if (!(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)) | ||
7296 | return -EINVAL; | ||
7297 | if (!wiphy_ext_feature_isset(&rdev->wiphy, | ||
7298 | NL80211_EXT_FEATURE_VHT_IBSS)) | ||
7299 | return -EINVAL; | ||
7300 | break; | ||
7280 | default: | 7301 | default: |
7281 | return -EINVAL; | 7302 | return -EINVAL; |
7282 | } | 7303 | } |
@@ -7389,8 +7410,8 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info) | |||
7389 | 7410 | ||
7390 | static struct sk_buff * | 7411 | static struct sk_buff * |
7391 | __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev, | 7412 | __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev, |
7392 | int approxlen, u32 portid, u32 seq, | 7413 | struct wireless_dev *wdev, int approxlen, |
7393 | enum nl80211_commands cmd, | 7414 | u32 portid, u32 seq, enum nl80211_commands cmd, |
7394 | enum nl80211_attrs attr, | 7415 | enum nl80211_attrs attr, |
7395 | const struct nl80211_vendor_cmd_info *info, | 7416 | const struct nl80211_vendor_cmd_info *info, |
7396 | gfp_t gfp) | 7417 | gfp_t gfp) |
@@ -7421,6 +7442,16 @@ __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev, | |||
7421 | goto nla_put_failure; | 7442 | goto nla_put_failure; |
7422 | } | 7443 | } |
7423 | 7444 | ||
7445 | if (wdev) { | ||
7446 | if (nla_put_u64(skb, NL80211_ATTR_WDEV, | ||
7447 | wdev_id(wdev))) | ||
7448 | goto nla_put_failure; | ||
7449 | if (wdev->netdev && | ||
7450 | nla_put_u32(skb, NL80211_ATTR_IFINDEX, | ||
7451 | wdev->netdev->ifindex)) | ||
7452 | goto nla_put_failure; | ||
7453 | } | ||
7454 | |||
7424 | data = nla_nest_start(skb, attr); | 7455 | data = nla_nest_start(skb, attr); |
7425 | 7456 | ||
7426 | ((void **)skb->cb)[0] = rdev; | 7457 | ((void **)skb->cb)[0] = rdev; |
@@ -7435,6 +7466,7 @@ __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev, | |||
7435 | } | 7466 | } |
7436 | 7467 | ||
7437 | struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy, | 7468 | struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy, |
7469 | struct wireless_dev *wdev, | ||
7438 | enum nl80211_commands cmd, | 7470 | enum nl80211_commands cmd, |
7439 | enum nl80211_attrs attr, | 7471 | enum nl80211_attrs attr, |
7440 | int vendor_event_idx, | 7472 | int vendor_event_idx, |
@@ -7460,7 +7492,7 @@ struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy, | |||
7460 | return NULL; | 7492 | return NULL; |
7461 | } | 7493 | } |
7462 | 7494 | ||
7463 | return __cfg80211_alloc_vendor_skb(rdev, approxlen, 0, 0, | 7495 | return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, 0, 0, |
7464 | cmd, attr, info, gfp); | 7496 | cmd, attr, info, gfp); |
7465 | } | 7497 | } |
7466 | EXPORT_SYMBOL(__cfg80211_alloc_event_skb); | 7498 | EXPORT_SYMBOL(__cfg80211_alloc_event_skb); |
@@ -8808,6 +8840,9 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg, | |||
8808 | if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, req->interval)) | 8840 | if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, req->interval)) |
8809 | return -ENOBUFS; | 8841 | return -ENOBUFS; |
8810 | 8842 | ||
8843 | if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay)) | ||
8844 | return -ENOBUFS; | ||
8845 | |||
8811 | freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES); | 8846 | freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES); |
8812 | if (!freqs) | 8847 | if (!freqs) |
8813 | return -ENOBUFS; | 8848 | return -ENOBUFS; |
@@ -9094,6 +9129,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
9094 | const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan; | 9129 | const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan; |
9095 | int err, i; | 9130 | int err, i; |
9096 | bool prev_enabled = rdev->wiphy.wowlan_config; | 9131 | bool prev_enabled = rdev->wiphy.wowlan_config; |
9132 | bool regular = false; | ||
9097 | 9133 | ||
9098 | if (!wowlan) | 9134 | if (!wowlan) |
9099 | return -EOPNOTSUPP; | 9135 | return -EOPNOTSUPP; |
@@ -9121,12 +9157,14 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
9121 | if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT)) | 9157 | if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT)) |
9122 | return -EINVAL; | 9158 | return -EINVAL; |
9123 | new_triggers.disconnect = true; | 9159 | new_triggers.disconnect = true; |
9160 | regular = true; | ||
9124 | } | 9161 | } |
9125 | 9162 | ||
9126 | if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) { | 9163 | if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) { |
9127 | if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT)) | 9164 | if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT)) |
9128 | return -EINVAL; | 9165 | return -EINVAL; |
9129 | new_triggers.magic_pkt = true; | 9166 | new_triggers.magic_pkt = true; |
9167 | regular = true; | ||
9130 | } | 9168 | } |
9131 | 9169 | ||
9132 | if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED]) | 9170 | if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED]) |
@@ -9136,24 +9174,28 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
9136 | if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE)) | 9174 | if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE)) |
9137 | return -EINVAL; | 9175 | return -EINVAL; |
9138 | new_triggers.gtk_rekey_failure = true; | 9176 | new_triggers.gtk_rekey_failure = true; |
9177 | regular = true; | ||
9139 | } | 9178 | } |
9140 | 9179 | ||
9141 | if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) { | 9180 | if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) { |
9142 | if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ)) | 9181 | if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ)) |
9143 | return -EINVAL; | 9182 | return -EINVAL; |
9144 | new_triggers.eap_identity_req = true; | 9183 | new_triggers.eap_identity_req = true; |
9184 | regular = true; | ||
9145 | } | 9185 | } |
9146 | 9186 | ||
9147 | if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) { | 9187 | if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) { |
9148 | if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE)) | 9188 | if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE)) |
9149 | return -EINVAL; | 9189 | return -EINVAL; |
9150 | new_triggers.four_way_handshake = true; | 9190 | new_triggers.four_way_handshake = true; |
9191 | regular = true; | ||
9151 | } | 9192 | } |
9152 | 9193 | ||
9153 | if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) { | 9194 | if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) { |
9154 | if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE)) | 9195 | if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE)) |
9155 | return -EINVAL; | 9196 | return -EINVAL; |
9156 | new_triggers.rfkill_release = true; | 9197 | new_triggers.rfkill_release = true; |
9198 | regular = true; | ||
9157 | } | 9199 | } |
9158 | 9200 | ||
9159 | if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { | 9201 | if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { |
@@ -9162,6 +9204,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
9162 | int rem, pat_len, mask_len, pkt_offset; | 9204 | int rem, pat_len, mask_len, pkt_offset; |
9163 | struct nlattr *pat_tb[NUM_NL80211_PKTPAT]; | 9205 | struct nlattr *pat_tb[NUM_NL80211_PKTPAT]; |
9164 | 9206 | ||
9207 | regular = true; | ||
9208 | |||
9165 | nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], | 9209 | nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], |
9166 | rem) | 9210 | rem) |
9167 | n_patterns++; | 9211 | n_patterns++; |
@@ -9223,6 +9267,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
9223 | } | 9267 | } |
9224 | 9268 | ||
9225 | if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) { | 9269 | if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) { |
9270 | regular = true; | ||
9226 | err = nl80211_parse_wowlan_tcp( | 9271 | err = nl80211_parse_wowlan_tcp( |
9227 | rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION], | 9272 | rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION], |
9228 | &new_triggers); | 9273 | &new_triggers); |
@@ -9231,6 +9276,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
9231 | } | 9276 | } |
9232 | 9277 | ||
9233 | if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) { | 9278 | if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) { |
9279 | regular = true; | ||
9234 | err = nl80211_parse_wowlan_nd( | 9280 | err = nl80211_parse_wowlan_nd( |
9235 | rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT], | 9281 | rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT], |
9236 | &new_triggers); | 9282 | &new_triggers); |
@@ -9238,6 +9284,17 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
9238 | goto error; | 9284 | goto error; |
9239 | } | 9285 | } |
9240 | 9286 | ||
9287 | /* The 'any' trigger means the device continues operating more or less | ||
9288 | * as in its normal operation mode and wakes up the host on most of the | ||
9289 | * normal interrupts (like packet RX, ...) | ||
9290 | * It therefore makes little sense to combine with the more constrained | ||
9291 | * wakeup trigger modes. | ||
9292 | */ | ||
9293 | if (new_triggers.any && regular) { | ||
9294 | err = -EINVAL; | ||
9295 | goto error; | ||
9296 | } | ||
9297 | |||
9241 | ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL); | 9298 | ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL); |
9242 | if (!ntrig) { | 9299 | if (!ntrig) { |
9243 | err = -ENOMEM; | 9300 | err = -ENOMEM; |
@@ -9906,7 +9963,7 @@ struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy, | |||
9906 | if (WARN_ON(!rdev->cur_cmd_info)) | 9963 | if (WARN_ON(!rdev->cur_cmd_info)) |
9907 | return NULL; | 9964 | return NULL; |
9908 | 9965 | ||
9909 | return __cfg80211_alloc_vendor_skb(rdev, approxlen, | 9966 | return __cfg80211_alloc_vendor_skb(rdev, NULL, approxlen, |
9910 | rdev->cur_cmd_info->snd_portid, | 9967 | rdev->cur_cmd_info->snd_portid, |
9911 | rdev->cur_cmd_info->snd_seq, | 9968 | rdev->cur_cmd_info->snd_seq, |
9912 | cmd, attr, NULL, GFP_KERNEL); | 9969 | cmd, attr, NULL, GFP_KERNEL); |
@@ -12775,6 +12832,11 @@ static int nl80211_netlink_notify(struct notifier_block * nb, | |||
12775 | 12832 | ||
12776 | rcu_read_unlock(); | 12833 | rcu_read_unlock(); |
12777 | 12834 | ||
12835 | /* | ||
12836 | * It is possible that the user space process that is controlling the | ||
12837 | * indoor setting disappeared, so notify the regulatory core. | ||
12838 | */ | ||
12839 | regulatory_netlink_notify(notify->portid); | ||
12778 | return NOTIFY_OK; | 12840 | return NOTIFY_OK; |
12779 | } | 12841 | } |
12780 | 12842 | ||
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index 35cfb7134bdb..c6e83a7468c0 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h | |||
@@ -35,13 +35,14 @@ static inline void rdev_set_wakeup(struct cfg80211_registered_device *rdev, | |||
35 | 35 | ||
36 | static inline struct wireless_dev | 36 | static inline struct wireless_dev |
37 | *rdev_add_virtual_intf(struct cfg80211_registered_device *rdev, char *name, | 37 | *rdev_add_virtual_intf(struct cfg80211_registered_device *rdev, char *name, |
38 | unsigned char name_assign_type, | ||
38 | enum nl80211_iftype type, u32 *flags, | 39 | enum nl80211_iftype type, u32 *flags, |
39 | struct vif_params *params) | 40 | struct vif_params *params) |
40 | { | 41 | { |
41 | struct wireless_dev *ret; | 42 | struct wireless_dev *ret; |
42 | trace_rdev_add_virtual_intf(&rdev->wiphy, name, type); | 43 | trace_rdev_add_virtual_intf(&rdev->wiphy, name, type); |
43 | ret = rdev->ops->add_virtual_intf(&rdev->wiphy, name, type, flags, | 44 | ret = rdev->ops->add_virtual_intf(&rdev->wiphy, name, name_assign_type, |
44 | params); | 45 | type, flags, params); |
45 | trace_rdev_return_wdev(&rdev->wiphy, ret); | 46 | trace_rdev_return_wdev(&rdev->wiphy, ret); |
46 | return ret; | 47 | return ret; |
47 | } | 48 | } |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 48dfc7b4e981..be5f81caa488 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -82,17 +82,12 @@ | |||
82 | * be intersected with the current one. | 82 | * be intersected with the current one. |
83 | * @REG_REQ_ALREADY_SET: the regulatory request will not change the current | 83 | * @REG_REQ_ALREADY_SET: the regulatory request will not change the current |
84 | * regulatory settings, and no further processing is required. | 84 | * regulatory settings, and no further processing is required. |
85 | * @REG_REQ_USER_HINT_HANDLED: a non alpha2 user hint was handled and no | ||
86 | * further processing is required, i.e., not need to update last_request | ||
87 | * etc. This should be used for user hints that do not provide an alpha2 | ||
88 | * but some other type of regulatory hint, i.e., indoor operation. | ||
89 | */ | 85 | */ |
90 | enum reg_request_treatment { | 86 | enum reg_request_treatment { |
91 | REG_REQ_OK, | 87 | REG_REQ_OK, |
92 | REG_REQ_IGNORE, | 88 | REG_REQ_IGNORE, |
93 | REG_REQ_INTERSECT, | 89 | REG_REQ_INTERSECT, |
94 | REG_REQ_ALREADY_SET, | 90 | REG_REQ_ALREADY_SET, |
95 | REG_REQ_USER_HINT_HANDLED, | ||
96 | }; | 91 | }; |
97 | 92 | ||
98 | static struct regulatory_request core_request_world = { | 93 | static struct regulatory_request core_request_world = { |
@@ -133,9 +128,12 @@ static int reg_num_devs_support_basehint; | |||
133 | * State variable indicating if the platform on which the devices | 128 | * State variable indicating if the platform on which the devices |
134 | * are attached is operating in an indoor environment. The state variable | 129 | * are attached is operating in an indoor environment. The state variable |
135 | * is relevant for all registered devices. | 130 | * is relevant for all registered devices. |
136 | * (protected by RTNL) | ||
137 | */ | 131 | */ |
138 | static bool reg_is_indoor; | 132 | static bool reg_is_indoor; |
133 | static spinlock_t reg_indoor_lock; | ||
134 | |||
135 | /* Used to track the userspace process controlling the indoor setting */ | ||
136 | static u32 reg_is_indoor_portid; | ||
139 | 137 | ||
140 | static const struct ieee80211_regdomain *get_cfg80211_regdom(void) | 138 | static const struct ieee80211_regdomain *get_cfg80211_regdom(void) |
141 | { | 139 | { |
@@ -554,6 +552,9 @@ reg_call_crda(struct regulatory_request *request) | |||
554 | { | 552 | { |
555 | if (call_crda(request->alpha2)) | 553 | if (call_crda(request->alpha2)) |
556 | return REG_REQ_IGNORE; | 554 | return REG_REQ_IGNORE; |
555 | |||
556 | queue_delayed_work(system_power_efficient_wq, | ||
557 | ®_timeout, msecs_to_jiffies(3142)); | ||
557 | return REG_REQ_OK; | 558 | return REG_REQ_OK; |
558 | } | 559 | } |
559 | 560 | ||
@@ -1248,13 +1249,6 @@ static bool reg_request_cell_base(struct regulatory_request *request) | |||
1248 | return request->user_reg_hint_type == NL80211_USER_REG_HINT_CELL_BASE; | 1249 | return request->user_reg_hint_type == NL80211_USER_REG_HINT_CELL_BASE; |
1249 | } | 1250 | } |
1250 | 1251 | ||
1251 | static bool reg_request_indoor(struct regulatory_request *request) | ||
1252 | { | ||
1253 | if (request->initiator != NL80211_REGDOM_SET_BY_USER) | ||
1254 | return false; | ||
1255 | return request->user_reg_hint_type == NL80211_USER_REG_HINT_INDOOR; | ||
1256 | } | ||
1257 | |||
1258 | bool reg_last_request_cell_base(void) | 1252 | bool reg_last_request_cell_base(void) |
1259 | { | 1253 | { |
1260 | return reg_request_cell_base(get_last_request()); | 1254 | return reg_request_cell_base(get_last_request()); |
@@ -1800,8 +1794,7 @@ static void reg_set_request_processed(void) | |||
1800 | need_more_processing = true; | 1794 | need_more_processing = true; |
1801 | spin_unlock(®_requests_lock); | 1795 | spin_unlock(®_requests_lock); |
1802 | 1796 | ||
1803 | if (lr->initiator == NL80211_REGDOM_SET_BY_USER) | 1797 | cancel_delayed_work(®_timeout); |
1804 | cancel_delayed_work(®_timeout); | ||
1805 | 1798 | ||
1806 | if (need_more_processing) | 1799 | if (need_more_processing) |
1807 | schedule_work(®_work); | 1800 | schedule_work(®_work); |
@@ -1833,11 +1826,6 @@ __reg_process_hint_user(struct regulatory_request *user_request) | |||
1833 | { | 1826 | { |
1834 | struct regulatory_request *lr = get_last_request(); | 1827 | struct regulatory_request *lr = get_last_request(); |
1835 | 1828 | ||
1836 | if (reg_request_indoor(user_request)) { | ||
1837 | reg_is_indoor = true; | ||
1838 | return REG_REQ_USER_HINT_HANDLED; | ||
1839 | } | ||
1840 | |||
1841 | if (reg_request_cell_base(user_request)) | 1829 | if (reg_request_cell_base(user_request)) |
1842 | return reg_ignore_cell_hint(user_request); | 1830 | return reg_ignore_cell_hint(user_request); |
1843 | 1831 | ||
@@ -1885,8 +1873,7 @@ reg_process_hint_user(struct regulatory_request *user_request) | |||
1885 | 1873 | ||
1886 | treatment = __reg_process_hint_user(user_request); | 1874 | treatment = __reg_process_hint_user(user_request); |
1887 | if (treatment == REG_REQ_IGNORE || | 1875 | if (treatment == REG_REQ_IGNORE || |
1888 | treatment == REG_REQ_ALREADY_SET || | 1876 | treatment == REG_REQ_ALREADY_SET) { |
1889 | treatment == REG_REQ_USER_HINT_HANDLED) { | ||
1890 | reg_free_request(user_request); | 1877 | reg_free_request(user_request); |
1891 | return treatment; | 1878 | return treatment; |
1892 | } | 1879 | } |
@@ -1947,7 +1934,6 @@ reg_process_hint_driver(struct wiphy *wiphy, | |||
1947 | case REG_REQ_OK: | 1934 | case REG_REQ_OK: |
1948 | break; | 1935 | break; |
1949 | case REG_REQ_IGNORE: | 1936 | case REG_REQ_IGNORE: |
1950 | case REG_REQ_USER_HINT_HANDLED: | ||
1951 | reg_free_request(driver_request); | 1937 | reg_free_request(driver_request); |
1952 | return treatment; | 1938 | return treatment; |
1953 | case REG_REQ_INTERSECT: | 1939 | case REG_REQ_INTERSECT: |
@@ -2047,7 +2033,6 @@ reg_process_hint_country_ie(struct wiphy *wiphy, | |||
2047 | case REG_REQ_OK: | 2033 | case REG_REQ_OK: |
2048 | break; | 2034 | break; |
2049 | case REG_REQ_IGNORE: | 2035 | case REG_REQ_IGNORE: |
2050 | case REG_REQ_USER_HINT_HANDLED: | ||
2051 | /* fall through */ | 2036 | /* fall through */ |
2052 | case REG_REQ_ALREADY_SET: | 2037 | case REG_REQ_ALREADY_SET: |
2053 | reg_free_request(country_ie_request); | 2038 | reg_free_request(country_ie_request); |
@@ -2086,11 +2071,8 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
2086 | case NL80211_REGDOM_SET_BY_USER: | 2071 | case NL80211_REGDOM_SET_BY_USER: |
2087 | treatment = reg_process_hint_user(reg_request); | 2072 | treatment = reg_process_hint_user(reg_request); |
2088 | if (treatment == REG_REQ_IGNORE || | 2073 | if (treatment == REG_REQ_IGNORE || |
2089 | treatment == REG_REQ_ALREADY_SET || | 2074 | treatment == REG_REQ_ALREADY_SET) |
2090 | treatment == REG_REQ_USER_HINT_HANDLED) | ||
2091 | return; | 2075 | return; |
2092 | queue_delayed_work(system_power_efficient_wq, | ||
2093 | ®_timeout, msecs_to_jiffies(3142)); | ||
2094 | return; | 2076 | return; |
2095 | case NL80211_REGDOM_SET_BY_DRIVER: | 2077 | case NL80211_REGDOM_SET_BY_DRIVER: |
2096 | if (!wiphy) | 2078 | if (!wiphy) |
@@ -2177,6 +2159,13 @@ static void reg_process_pending_hints(void) | |||
2177 | } | 2159 | } |
2178 | 2160 | ||
2179 | reg_process_hint(reg_request); | 2161 | reg_process_hint(reg_request); |
2162 | |||
2163 | lr = get_last_request(); | ||
2164 | |||
2165 | spin_lock(®_requests_lock); | ||
2166 | if (!list_empty(®_requests_list) && lr && lr->processed) | ||
2167 | schedule_work(®_work); | ||
2168 | spin_unlock(®_requests_lock); | ||
2180 | } | 2169 | } |
2181 | 2170 | ||
2182 | /* Processes beacon hints -- this has nothing to do with country IEs */ | 2171 | /* Processes beacon hints -- this has nothing to do with country IEs */ |
@@ -2309,22 +2298,50 @@ int regulatory_hint_user(const char *alpha2, | |||
2309 | return 0; | 2298 | return 0; |
2310 | } | 2299 | } |
2311 | 2300 | ||
2312 | int regulatory_hint_indoor_user(void) | 2301 | int regulatory_hint_indoor(bool is_indoor, u32 portid) |
2313 | { | 2302 | { |
2314 | struct regulatory_request *request; | 2303 | spin_lock(®_indoor_lock); |
2315 | 2304 | ||
2316 | request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); | 2305 | /* It is possible that more than one user space process is trying to |
2317 | if (!request) | 2306 | * configure the indoor setting. To handle such cases, clear the indoor |
2318 | return -ENOMEM; | 2307 | * setting in case that some process does not think that the device |
2308 | * is operating in an indoor environment. In addition, if a user space | ||
2309 | * process indicates that it is controlling the indoor setting, save its | ||
2310 | * portid, i.e., make it the owner. | ||
2311 | */ | ||
2312 | reg_is_indoor = is_indoor; | ||
2313 | if (reg_is_indoor) { | ||
2314 | if (!reg_is_indoor_portid) | ||
2315 | reg_is_indoor_portid = portid; | ||
2316 | } else { | ||
2317 | reg_is_indoor_portid = 0; | ||
2318 | } | ||
2319 | 2319 | ||
2320 | request->wiphy_idx = WIPHY_IDX_INVALID; | 2320 | spin_unlock(®_indoor_lock); |
2321 | request->initiator = NL80211_REGDOM_SET_BY_USER; | 2321 | |
2322 | request->user_reg_hint_type = NL80211_USER_REG_HINT_INDOOR; | 2322 | if (!is_indoor) |
2323 | queue_regulatory_request(request); | 2323 | reg_check_channels(); |
2324 | 2324 | ||
2325 | return 0; | 2325 | return 0; |
2326 | } | 2326 | } |
2327 | 2327 | ||
2328 | void regulatory_netlink_notify(u32 portid) | ||
2329 | { | ||
2330 | spin_lock(®_indoor_lock); | ||
2331 | |||
2332 | if (reg_is_indoor_portid != portid) { | ||
2333 | spin_unlock(®_indoor_lock); | ||
2334 | return; | ||
2335 | } | ||
2336 | |||
2337 | reg_is_indoor = false; | ||
2338 | reg_is_indoor_portid = 0; | ||
2339 | |||
2340 | spin_unlock(®_indoor_lock); | ||
2341 | |||
2342 | reg_check_channels(); | ||
2343 | } | ||
2344 | |||
2328 | /* Driver hints */ | 2345 | /* Driver hints */ |
2329 | int regulatory_hint(struct wiphy *wiphy, const char *alpha2) | 2346 | int regulatory_hint(struct wiphy *wiphy, const char *alpha2) |
2330 | { | 2347 | { |
@@ -2486,13 +2503,22 @@ static void restore_regulatory_settings(bool reset_user) | |||
2486 | char alpha2[2]; | 2503 | char alpha2[2]; |
2487 | char world_alpha2[2]; | 2504 | char world_alpha2[2]; |
2488 | struct reg_beacon *reg_beacon, *btmp; | 2505 | struct reg_beacon *reg_beacon, *btmp; |
2489 | struct regulatory_request *reg_request, *tmp; | ||
2490 | LIST_HEAD(tmp_reg_req_list); | 2506 | LIST_HEAD(tmp_reg_req_list); |
2491 | struct cfg80211_registered_device *rdev; | 2507 | struct cfg80211_registered_device *rdev; |
2492 | 2508 | ||
2493 | ASSERT_RTNL(); | 2509 | ASSERT_RTNL(); |
2494 | 2510 | ||
2495 | reg_is_indoor = false; | 2511 | /* |
2512 | * Clear the indoor setting in case that it is not controlled by user | ||
2513 | * space, as otherwise there is no guarantee that the device is still | ||
2514 | * operating in an indoor environment. | ||
2515 | */ | ||
2516 | spin_lock(®_indoor_lock); | ||
2517 | if (reg_is_indoor && !reg_is_indoor_portid) { | ||
2518 | reg_is_indoor = false; | ||
2519 | reg_check_channels(); | ||
2520 | } | ||
2521 | spin_unlock(®_indoor_lock); | ||
2496 | 2522 | ||
2497 | reset_regdomains(true, &world_regdom); | 2523 | reset_regdomains(true, &world_regdom); |
2498 | restore_alpha2(alpha2, reset_user); | 2524 | restore_alpha2(alpha2, reset_user); |
@@ -2504,11 +2530,7 @@ static void restore_regulatory_settings(bool reset_user) | |||
2504 | * settings. | 2530 | * settings. |
2505 | */ | 2531 | */ |
2506 | spin_lock(®_requests_lock); | 2532 | spin_lock(®_requests_lock); |
2507 | list_for_each_entry_safe(reg_request, tmp, ®_requests_list, list) { | 2533 | list_splice_tail_init(®_requests_list, &tmp_reg_req_list); |
2508 | if (reg_request->initiator != NL80211_REGDOM_SET_BY_USER) | ||
2509 | continue; | ||
2510 | list_move_tail(®_request->list, &tmp_reg_req_list); | ||
2511 | } | ||
2512 | spin_unlock(®_requests_lock); | 2534 | spin_unlock(®_requests_lock); |
2513 | 2535 | ||
2514 | /* Clear beacon hints */ | 2536 | /* Clear beacon hints */ |
@@ -3089,6 +3111,7 @@ int __init regulatory_init(void) | |||
3089 | 3111 | ||
3090 | spin_lock_init(®_requests_lock); | 3112 | spin_lock_init(®_requests_lock); |
3091 | spin_lock_init(®_pending_beacons_lock); | 3113 | spin_lock_init(®_pending_beacons_lock); |
3114 | spin_lock_init(®_indoor_lock); | ||
3092 | 3115 | ||
3093 | reg_regdb_size_check(); | 3116 | reg_regdb_size_check(); |
3094 | 3117 | ||
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 4b45d6e61d24..a2c4e16459da 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -25,7 +25,20 @@ enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy); | |||
25 | 25 | ||
26 | int regulatory_hint_user(const char *alpha2, | 26 | int regulatory_hint_user(const char *alpha2, |
27 | enum nl80211_user_reg_hint_type user_reg_hint_type); | 27 | enum nl80211_user_reg_hint_type user_reg_hint_type); |
28 | int regulatory_hint_indoor_user(void); | 28 | |
29 | /** | ||
30 | * regulatory_hint_indoor - hint operation in indoor env. or not | ||
31 | * @is_indoor: if true indicates that user space thinks that the | ||
32 | * device is operating in an indoor environment. | ||
33 | * @portid: the netlink port ID on which the hint was given. | ||
34 | */ | ||
35 | int regulatory_hint_indoor(bool is_indoor, u32 portid); | ||
36 | |||
37 | /** | ||
38 | * regulatory_netlink_notify - notify on released netlink socket | ||
39 | * @portid: the netlink socket port ID | ||
40 | */ | ||
41 | void regulatory_netlink_notify(u32 portid); | ||
29 | 42 | ||
30 | void wiphy_regulatory_register(struct wiphy *wiphy); | 43 | void wiphy_regulatory_register(struct wiphy *wiphy); |
31 | void wiphy_regulatory_deregister(struct wiphy *wiphy); | 44 | void wiphy_regulatory_deregister(struct wiphy *wiphy); |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index c705c3e2b751..3a50aa2553bf 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -531,24 +531,78 @@ static int cmp_bss(struct cfg80211_bss *a, | |||
531 | } | 531 | } |
532 | } | 532 | } |
533 | 533 | ||
534 | static bool cfg80211_bss_type_match(u16 capability, | ||
535 | enum ieee80211_band band, | ||
536 | enum ieee80211_bss_type bss_type) | ||
537 | { | ||
538 | bool ret = true; | ||
539 | u16 mask, val; | ||
540 | |||
541 | if (bss_type == IEEE80211_BSS_TYPE_ANY) | ||
542 | return ret; | ||
543 | |||
544 | if (band == IEEE80211_BAND_60GHZ) { | ||
545 | mask = WLAN_CAPABILITY_DMG_TYPE_MASK; | ||
546 | switch (bss_type) { | ||
547 | case IEEE80211_BSS_TYPE_ESS: | ||
548 | val = WLAN_CAPABILITY_DMG_TYPE_AP; | ||
549 | break; | ||
550 | case IEEE80211_BSS_TYPE_PBSS: | ||
551 | val = WLAN_CAPABILITY_DMG_TYPE_PBSS; | ||
552 | break; | ||
553 | case IEEE80211_BSS_TYPE_IBSS: | ||
554 | val = WLAN_CAPABILITY_DMG_TYPE_IBSS; | ||
555 | break; | ||
556 | default: | ||
557 | return false; | ||
558 | } | ||
559 | } else { | ||
560 | mask = WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS; | ||
561 | switch (bss_type) { | ||
562 | case IEEE80211_BSS_TYPE_ESS: | ||
563 | val = WLAN_CAPABILITY_ESS; | ||
564 | break; | ||
565 | case IEEE80211_BSS_TYPE_IBSS: | ||
566 | val = WLAN_CAPABILITY_IBSS; | ||
567 | break; | ||
568 | case IEEE80211_BSS_TYPE_MBSS: | ||
569 | val = 0; | ||
570 | break; | ||
571 | default: | ||
572 | return false; | ||
573 | } | ||
574 | } | ||
575 | |||
576 | ret = ((capability & mask) == val); | ||
577 | return ret; | ||
578 | } | ||
579 | |||
534 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | 580 | /* Returned bss is reference counted and must be cleaned up appropriately. */ |
535 | struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, | 581 | struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, |
536 | struct ieee80211_channel *channel, | 582 | struct ieee80211_channel *channel, |
537 | const u8 *bssid, | 583 | const u8 *bssid, |
538 | const u8 *ssid, size_t ssid_len, | 584 | const u8 *ssid, size_t ssid_len, |
539 | u16 capa_mask, u16 capa_val) | 585 | enum ieee80211_bss_type bss_type, |
586 | enum ieee80211_privacy privacy) | ||
540 | { | 587 | { |
541 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | 588 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); |
542 | struct cfg80211_internal_bss *bss, *res = NULL; | 589 | struct cfg80211_internal_bss *bss, *res = NULL; |
543 | unsigned long now = jiffies; | 590 | unsigned long now = jiffies; |
591 | int bss_privacy; | ||
544 | 592 | ||
545 | trace_cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, capa_mask, | 593 | trace_cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, bss_type, |
546 | capa_val); | 594 | privacy); |
547 | 595 | ||
548 | spin_lock_bh(&rdev->bss_lock); | 596 | spin_lock_bh(&rdev->bss_lock); |
549 | 597 | ||
550 | list_for_each_entry(bss, &rdev->bss_list, list) { | 598 | list_for_each_entry(bss, &rdev->bss_list, list) { |
551 | if ((bss->pub.capability & capa_mask) != capa_val) | 599 | if (!cfg80211_bss_type_match(bss->pub.capability, |
600 | bss->pub.channel->band, bss_type)) | ||
601 | continue; | ||
602 | |||
603 | bss_privacy = (bss->pub.capability & WLAN_CAPABILITY_PRIVACY); | ||
604 | if ((privacy == IEEE80211_PRIVACY_ON && !bss_privacy) || | ||
605 | (privacy == IEEE80211_PRIVACY_OFF && bss_privacy)) | ||
552 | continue; | 606 | continue; |
553 | if (channel && bss->pub.channel != channel) | 607 | if (channel && bss->pub.channel != channel) |
554 | continue; | 608 | continue; |
@@ -896,6 +950,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, | |||
896 | struct cfg80211_bss_ies *ies; | 950 | struct cfg80211_bss_ies *ies; |
897 | struct ieee80211_channel *channel; | 951 | struct ieee80211_channel *channel; |
898 | struct cfg80211_internal_bss tmp = {}, *res; | 952 | struct cfg80211_internal_bss tmp = {}, *res; |
953 | int bss_type; | ||
899 | bool signal_valid; | 954 | bool signal_valid; |
900 | 955 | ||
901 | if (WARN_ON(!wiphy)) | 956 | if (WARN_ON(!wiphy)) |
@@ -950,8 +1005,15 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, | |||
950 | if (!res) | 1005 | if (!res) |
951 | return NULL; | 1006 | return NULL; |
952 | 1007 | ||
953 | if (res->pub.capability & WLAN_CAPABILITY_ESS) | 1008 | if (channel->band == IEEE80211_BAND_60GHZ) { |
954 | regulatory_hint_found_beacon(wiphy, channel, gfp); | 1009 | bss_type = res->pub.capability & WLAN_CAPABILITY_DMG_TYPE_MASK; |
1010 | if (bss_type == WLAN_CAPABILITY_DMG_TYPE_AP || | ||
1011 | bss_type == WLAN_CAPABILITY_DMG_TYPE_PBSS) | ||
1012 | regulatory_hint_found_beacon(wiphy, channel, gfp); | ||
1013 | } else { | ||
1014 | if (res->pub.capability & WLAN_CAPABILITY_ESS) | ||
1015 | regulatory_hint_found_beacon(wiphy, channel, gfp); | ||
1016 | } | ||
955 | 1017 | ||
956 | trace_cfg80211_return_bss(&res->pub); | 1018 | trace_cfg80211_return_bss(&res->pub); |
957 | /* cfg80211_bss_update gives us a referenced result */ | 1019 | /* cfg80211_bss_update gives us a referenced result */ |
@@ -973,6 +1035,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | |||
973 | bool signal_valid; | 1035 | bool signal_valid; |
974 | size_t ielen = len - offsetof(struct ieee80211_mgmt, | 1036 | size_t ielen = len - offsetof(struct ieee80211_mgmt, |
975 | u.probe_resp.variable); | 1037 | u.probe_resp.variable); |
1038 | int bss_type; | ||
976 | 1039 | ||
977 | BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != | 1040 | BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != |
978 | offsetof(struct ieee80211_mgmt, u.beacon.variable)); | 1041 | offsetof(struct ieee80211_mgmt, u.beacon.variable)); |
@@ -1025,8 +1088,15 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | |||
1025 | if (!res) | 1088 | if (!res) |
1026 | return NULL; | 1089 | return NULL; |
1027 | 1090 | ||
1028 | if (res->pub.capability & WLAN_CAPABILITY_ESS) | 1091 | if (channel->band == IEEE80211_BAND_60GHZ) { |
1029 | regulatory_hint_found_beacon(wiphy, channel, gfp); | 1092 | bss_type = res->pub.capability & WLAN_CAPABILITY_DMG_TYPE_MASK; |
1093 | if (bss_type == WLAN_CAPABILITY_DMG_TYPE_AP || | ||
1094 | bss_type == WLAN_CAPABILITY_DMG_TYPE_PBSS) | ||
1095 | regulatory_hint_found_beacon(wiphy, channel, gfp); | ||
1096 | } else { | ||
1097 | if (res->pub.capability & WLAN_CAPABILITY_ESS) | ||
1098 | regulatory_hint_found_beacon(wiphy, channel, gfp); | ||
1099 | } | ||
1030 | 1100 | ||
1031 | trace_cfg80211_return_bss(&res->pub); | 1101 | trace_cfg80211_return_bss(&res->pub); |
1032 | /* cfg80211_bss_update gives us a referenced result */ | 1102 | /* cfg80211_bss_update gives us a referenced result */ |
@@ -1237,17 +1307,17 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
1237 | kfree(creq); | 1307 | kfree(creq); |
1238 | return err; | 1308 | return err; |
1239 | } | 1309 | } |
1240 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); | 1310 | EXPORT_WEXT_HANDLER(cfg80211_wext_siwscan); |
1241 | 1311 | ||
1242 | static void ieee80211_scan_add_ies(struct iw_request_info *info, | 1312 | static char *ieee80211_scan_add_ies(struct iw_request_info *info, |
1243 | const struct cfg80211_bss_ies *ies, | 1313 | const struct cfg80211_bss_ies *ies, |
1244 | char **current_ev, char *end_buf) | 1314 | char *current_ev, char *end_buf) |
1245 | { | 1315 | { |
1246 | const u8 *pos, *end, *next; | 1316 | const u8 *pos, *end, *next; |
1247 | struct iw_event iwe; | 1317 | struct iw_event iwe; |
1248 | 1318 | ||
1249 | if (!ies) | 1319 | if (!ies) |
1250 | return; | 1320 | return current_ev; |
1251 | 1321 | ||
1252 | /* | 1322 | /* |
1253 | * If needed, fragment the IEs buffer (at IE boundaries) into short | 1323 | * If needed, fragment the IEs buffer (at IE boundaries) into short |
@@ -1264,10 +1334,11 @@ static void ieee80211_scan_add_ies(struct iw_request_info *info, | |||
1264 | memset(&iwe, 0, sizeof(iwe)); | 1334 | memset(&iwe, 0, sizeof(iwe)); |
1265 | iwe.cmd = IWEVGENIE; | 1335 | iwe.cmd = IWEVGENIE; |
1266 | iwe.u.data.length = next - pos; | 1336 | iwe.u.data.length = next - pos; |
1267 | *current_ev = iwe_stream_add_point(info, *current_ev, | 1337 | current_ev = iwe_stream_add_point_check(info, current_ev, |
1268 | end_buf, &iwe, | 1338 | end_buf, &iwe, |
1269 | (void *)pos); | 1339 | (void *)pos); |
1270 | 1340 | if (IS_ERR(current_ev)) | |
1341 | return current_ev; | ||
1271 | pos = next; | 1342 | pos = next; |
1272 | } | 1343 | } |
1273 | 1344 | ||
@@ -1275,10 +1346,14 @@ static void ieee80211_scan_add_ies(struct iw_request_info *info, | |||
1275 | memset(&iwe, 0, sizeof(iwe)); | 1346 | memset(&iwe, 0, sizeof(iwe)); |
1276 | iwe.cmd = IWEVGENIE; | 1347 | iwe.cmd = IWEVGENIE; |
1277 | iwe.u.data.length = end - pos; | 1348 | iwe.u.data.length = end - pos; |
1278 | *current_ev = iwe_stream_add_point(info, *current_ev, | 1349 | current_ev = iwe_stream_add_point_check(info, current_ev, |
1279 | end_buf, &iwe, | 1350 | end_buf, &iwe, |
1280 | (void *)pos); | 1351 | (void *)pos); |
1352 | if (IS_ERR(current_ev)) | ||
1353 | return current_ev; | ||
1281 | } | 1354 | } |
1355 | |||
1356 | return current_ev; | ||
1282 | } | 1357 | } |
1283 | 1358 | ||
1284 | static char * | 1359 | static char * |
@@ -1289,7 +1364,8 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1289 | const struct cfg80211_bss_ies *ies; | 1364 | const struct cfg80211_bss_ies *ies; |
1290 | struct iw_event iwe; | 1365 | struct iw_event iwe; |
1291 | const u8 *ie; | 1366 | const u8 *ie; |
1292 | u8 *buf, *cfg, *p; | 1367 | u8 buf[50]; |
1368 | u8 *cfg, *p, *tmp; | ||
1293 | int rem, i, sig; | 1369 | int rem, i, sig; |
1294 | bool ismesh = false; | 1370 | bool ismesh = false; |
1295 | 1371 | ||
@@ -1297,22 +1373,28 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1297 | iwe.cmd = SIOCGIWAP; | 1373 | iwe.cmd = SIOCGIWAP; |
1298 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 1374 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
1299 | memcpy(iwe.u.ap_addr.sa_data, bss->pub.bssid, ETH_ALEN); | 1375 | memcpy(iwe.u.ap_addr.sa_data, bss->pub.bssid, ETH_ALEN); |
1300 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | 1376 | current_ev = iwe_stream_add_event_check(info, current_ev, end_buf, &iwe, |
1301 | IW_EV_ADDR_LEN); | 1377 | IW_EV_ADDR_LEN); |
1378 | if (IS_ERR(current_ev)) | ||
1379 | return current_ev; | ||
1302 | 1380 | ||
1303 | memset(&iwe, 0, sizeof(iwe)); | 1381 | memset(&iwe, 0, sizeof(iwe)); |
1304 | iwe.cmd = SIOCGIWFREQ; | 1382 | iwe.cmd = SIOCGIWFREQ; |
1305 | iwe.u.freq.m = ieee80211_frequency_to_channel(bss->pub.channel->center_freq); | 1383 | iwe.u.freq.m = ieee80211_frequency_to_channel(bss->pub.channel->center_freq); |
1306 | iwe.u.freq.e = 0; | 1384 | iwe.u.freq.e = 0; |
1307 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | 1385 | current_ev = iwe_stream_add_event_check(info, current_ev, end_buf, &iwe, |
1308 | IW_EV_FREQ_LEN); | 1386 | IW_EV_FREQ_LEN); |
1387 | if (IS_ERR(current_ev)) | ||
1388 | return current_ev; | ||
1309 | 1389 | ||
1310 | memset(&iwe, 0, sizeof(iwe)); | 1390 | memset(&iwe, 0, sizeof(iwe)); |
1311 | iwe.cmd = SIOCGIWFREQ; | 1391 | iwe.cmd = SIOCGIWFREQ; |
1312 | iwe.u.freq.m = bss->pub.channel->center_freq; | 1392 | iwe.u.freq.m = bss->pub.channel->center_freq; |
1313 | iwe.u.freq.e = 6; | 1393 | iwe.u.freq.e = 6; |
1314 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | 1394 | current_ev = iwe_stream_add_event_check(info, current_ev, end_buf, &iwe, |
1315 | IW_EV_FREQ_LEN); | 1395 | IW_EV_FREQ_LEN); |
1396 | if (IS_ERR(current_ev)) | ||
1397 | return current_ev; | ||
1316 | 1398 | ||
1317 | if (wiphy->signal_type != CFG80211_SIGNAL_TYPE_NONE) { | 1399 | if (wiphy->signal_type != CFG80211_SIGNAL_TYPE_NONE) { |
1318 | memset(&iwe, 0, sizeof(iwe)); | 1400 | memset(&iwe, 0, sizeof(iwe)); |
@@ -1341,8 +1423,11 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1341 | /* not reached */ | 1423 | /* not reached */ |
1342 | break; | 1424 | break; |
1343 | } | 1425 | } |
1344 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, | 1426 | current_ev = iwe_stream_add_event_check(info, current_ev, |
1345 | &iwe, IW_EV_QUAL_LEN); | 1427 | end_buf, &iwe, |
1428 | IW_EV_QUAL_LEN); | ||
1429 | if (IS_ERR(current_ev)) | ||
1430 | return current_ev; | ||
1346 | } | 1431 | } |
1347 | 1432 | ||
1348 | memset(&iwe, 0, sizeof(iwe)); | 1433 | memset(&iwe, 0, sizeof(iwe)); |
@@ -1352,8 +1437,10 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1352 | else | 1437 | else |
1353 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 1438 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
1354 | iwe.u.data.length = 0; | 1439 | iwe.u.data.length = 0; |
1355 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | 1440 | current_ev = iwe_stream_add_point_check(info, current_ev, end_buf, |
1356 | &iwe, ""); | 1441 | &iwe, ""); |
1442 | if (IS_ERR(current_ev)) | ||
1443 | return current_ev; | ||
1357 | 1444 | ||
1358 | rcu_read_lock(); | 1445 | rcu_read_lock(); |
1359 | ies = rcu_dereference(bss->pub.ies); | 1446 | ies = rcu_dereference(bss->pub.ies); |
@@ -1371,66 +1458,91 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1371 | iwe.cmd = SIOCGIWESSID; | 1458 | iwe.cmd = SIOCGIWESSID; |
1372 | iwe.u.data.length = ie[1]; | 1459 | iwe.u.data.length = ie[1]; |
1373 | iwe.u.data.flags = 1; | 1460 | iwe.u.data.flags = 1; |
1374 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | 1461 | current_ev = iwe_stream_add_point_check(info, |
1375 | &iwe, (u8 *)ie + 2); | 1462 | current_ev, |
1463 | end_buf, &iwe, | ||
1464 | (u8 *)ie + 2); | ||
1465 | if (IS_ERR(current_ev)) | ||
1466 | goto unlock; | ||
1376 | break; | 1467 | break; |
1377 | case WLAN_EID_MESH_ID: | 1468 | case WLAN_EID_MESH_ID: |
1378 | memset(&iwe, 0, sizeof(iwe)); | 1469 | memset(&iwe, 0, sizeof(iwe)); |
1379 | iwe.cmd = SIOCGIWESSID; | 1470 | iwe.cmd = SIOCGIWESSID; |
1380 | iwe.u.data.length = ie[1]; | 1471 | iwe.u.data.length = ie[1]; |
1381 | iwe.u.data.flags = 1; | 1472 | iwe.u.data.flags = 1; |
1382 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | 1473 | current_ev = iwe_stream_add_point_check(info, |
1383 | &iwe, (u8 *)ie + 2); | 1474 | current_ev, |
1475 | end_buf, &iwe, | ||
1476 | (u8 *)ie + 2); | ||
1477 | if (IS_ERR(current_ev)) | ||
1478 | goto unlock; | ||
1384 | break; | 1479 | break; |
1385 | case WLAN_EID_MESH_CONFIG: | 1480 | case WLAN_EID_MESH_CONFIG: |
1386 | ismesh = true; | 1481 | ismesh = true; |
1387 | if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) | 1482 | if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) |
1388 | break; | 1483 | break; |
1389 | buf = kmalloc(50, GFP_ATOMIC); | ||
1390 | if (!buf) | ||
1391 | break; | ||
1392 | cfg = (u8 *)ie + 2; | 1484 | cfg = (u8 *)ie + 2; |
1393 | memset(&iwe, 0, sizeof(iwe)); | 1485 | memset(&iwe, 0, sizeof(iwe)); |
1394 | iwe.cmd = IWEVCUSTOM; | 1486 | iwe.cmd = IWEVCUSTOM; |
1395 | sprintf(buf, "Mesh Network Path Selection Protocol ID: " | 1487 | sprintf(buf, "Mesh Network Path Selection Protocol ID: " |
1396 | "0x%02X", cfg[0]); | 1488 | "0x%02X", cfg[0]); |
1397 | iwe.u.data.length = strlen(buf); | 1489 | iwe.u.data.length = strlen(buf); |
1398 | current_ev = iwe_stream_add_point(info, current_ev, | 1490 | current_ev = iwe_stream_add_point_check(info, |
1399 | end_buf, | 1491 | current_ev, |
1400 | &iwe, buf); | 1492 | end_buf, |
1493 | &iwe, buf); | ||
1494 | if (IS_ERR(current_ev)) | ||
1495 | goto unlock; | ||
1401 | sprintf(buf, "Path Selection Metric ID: 0x%02X", | 1496 | sprintf(buf, "Path Selection Metric ID: 0x%02X", |
1402 | cfg[1]); | 1497 | cfg[1]); |
1403 | iwe.u.data.length = strlen(buf); | 1498 | iwe.u.data.length = strlen(buf); |
1404 | current_ev = iwe_stream_add_point(info, current_ev, | 1499 | current_ev = iwe_stream_add_point_check(info, |
1405 | end_buf, | 1500 | current_ev, |
1406 | &iwe, buf); | 1501 | end_buf, |
1502 | &iwe, buf); | ||
1503 | if (IS_ERR(current_ev)) | ||
1504 | goto unlock; | ||
1407 | sprintf(buf, "Congestion Control Mode ID: 0x%02X", | 1505 | sprintf(buf, "Congestion Control Mode ID: 0x%02X", |
1408 | cfg[2]); | 1506 | cfg[2]); |
1409 | iwe.u.data.length = strlen(buf); | 1507 | iwe.u.data.length = strlen(buf); |
1410 | current_ev = iwe_stream_add_point(info, current_ev, | 1508 | current_ev = iwe_stream_add_point_check(info, |
1411 | end_buf, | 1509 | current_ev, |
1412 | &iwe, buf); | 1510 | end_buf, |
1511 | &iwe, buf); | ||
1512 | if (IS_ERR(current_ev)) | ||
1513 | goto unlock; | ||
1413 | sprintf(buf, "Synchronization ID: 0x%02X", cfg[3]); | 1514 | sprintf(buf, "Synchronization ID: 0x%02X", cfg[3]); |
1414 | iwe.u.data.length = strlen(buf); | 1515 | iwe.u.data.length = strlen(buf); |
1415 | current_ev = iwe_stream_add_point(info, current_ev, | 1516 | current_ev = iwe_stream_add_point_check(info, |
1416 | end_buf, | 1517 | current_ev, |
1417 | &iwe, buf); | 1518 | end_buf, |
1519 | &iwe, buf); | ||
1520 | if (IS_ERR(current_ev)) | ||
1521 | goto unlock; | ||
1418 | sprintf(buf, "Authentication ID: 0x%02X", cfg[4]); | 1522 | sprintf(buf, "Authentication ID: 0x%02X", cfg[4]); |
1419 | iwe.u.data.length = strlen(buf); | 1523 | iwe.u.data.length = strlen(buf); |
1420 | current_ev = iwe_stream_add_point(info, current_ev, | 1524 | current_ev = iwe_stream_add_point_check(info, |
1421 | end_buf, | 1525 | current_ev, |
1422 | &iwe, buf); | 1526 | end_buf, |
1527 | &iwe, buf); | ||
1528 | if (IS_ERR(current_ev)) | ||
1529 | goto unlock; | ||
1423 | sprintf(buf, "Formation Info: 0x%02X", cfg[5]); | 1530 | sprintf(buf, "Formation Info: 0x%02X", cfg[5]); |
1424 | iwe.u.data.length = strlen(buf); | 1531 | iwe.u.data.length = strlen(buf); |
1425 | current_ev = iwe_stream_add_point(info, current_ev, | 1532 | current_ev = iwe_stream_add_point_check(info, |
1426 | end_buf, | 1533 | current_ev, |
1427 | &iwe, buf); | 1534 | end_buf, |
1535 | &iwe, buf); | ||
1536 | if (IS_ERR(current_ev)) | ||
1537 | goto unlock; | ||
1428 | sprintf(buf, "Capabilities: 0x%02X", cfg[6]); | 1538 | sprintf(buf, "Capabilities: 0x%02X", cfg[6]); |
1429 | iwe.u.data.length = strlen(buf); | 1539 | iwe.u.data.length = strlen(buf); |
1430 | current_ev = iwe_stream_add_point(info, current_ev, | 1540 | current_ev = iwe_stream_add_point_check(info, |
1431 | end_buf, | 1541 | current_ev, |
1432 | &iwe, buf); | 1542 | end_buf, |
1433 | kfree(buf); | 1543 | &iwe, buf); |
1544 | if (IS_ERR(current_ev)) | ||
1545 | goto unlock; | ||
1434 | break; | 1546 | break; |
1435 | case WLAN_EID_SUPP_RATES: | 1547 | case WLAN_EID_SUPP_RATES: |
1436 | case WLAN_EID_EXT_SUPP_RATES: | 1548 | case WLAN_EID_EXT_SUPP_RATES: |
@@ -1445,8 +1557,14 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1445 | for (i = 0; i < ie[1]; i++) { | 1557 | for (i = 0; i < ie[1]; i++) { |
1446 | iwe.u.bitrate.value = | 1558 | iwe.u.bitrate.value = |
1447 | ((ie[i + 2] & 0x7f) * 500000); | 1559 | ((ie[i + 2] & 0x7f) * 500000); |
1560 | tmp = p; | ||
1448 | p = iwe_stream_add_value(info, current_ev, p, | 1561 | p = iwe_stream_add_value(info, current_ev, p, |
1449 | end_buf, &iwe, IW_EV_PARAM_LEN); | 1562 | end_buf, &iwe, |
1563 | IW_EV_PARAM_LEN); | ||
1564 | if (p == tmp) { | ||
1565 | current_ev = ERR_PTR(-E2BIG); | ||
1566 | goto unlock; | ||
1567 | } | ||
1450 | } | 1568 | } |
1451 | current_ev = p; | 1569 | current_ev = p; |
1452 | break; | 1570 | break; |
@@ -1465,31 +1583,35 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1465 | iwe.u.mode = IW_MODE_MASTER; | 1583 | iwe.u.mode = IW_MODE_MASTER; |
1466 | else | 1584 | else |
1467 | iwe.u.mode = IW_MODE_ADHOC; | 1585 | iwe.u.mode = IW_MODE_ADHOC; |
1468 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, | 1586 | current_ev = iwe_stream_add_event_check(info, current_ev, |
1469 | &iwe, IW_EV_UINT_LEN); | 1587 | end_buf, &iwe, |
1470 | } | 1588 | IW_EV_UINT_LEN); |
1471 | 1589 | if (IS_ERR(current_ev)) | |
1472 | buf = kmalloc(31, GFP_ATOMIC); | 1590 | goto unlock; |
1473 | if (buf) { | ||
1474 | memset(&iwe, 0, sizeof(iwe)); | ||
1475 | iwe.cmd = IWEVCUSTOM; | ||
1476 | sprintf(buf, "tsf=%016llx", (unsigned long long)(ies->tsf)); | ||
1477 | iwe.u.data.length = strlen(buf); | ||
1478 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
1479 | &iwe, buf); | ||
1480 | memset(&iwe, 0, sizeof(iwe)); | ||
1481 | iwe.cmd = IWEVCUSTOM; | ||
1482 | sprintf(buf, " Last beacon: %ums ago", | ||
1483 | elapsed_jiffies_msecs(bss->ts)); | ||
1484 | iwe.u.data.length = strlen(buf); | ||
1485 | current_ev = iwe_stream_add_point(info, current_ev, | ||
1486 | end_buf, &iwe, buf); | ||
1487 | kfree(buf); | ||
1488 | } | 1591 | } |
1489 | 1592 | ||
1490 | ieee80211_scan_add_ies(info, ies, ¤t_ev, end_buf); | 1593 | memset(&iwe, 0, sizeof(iwe)); |
1594 | iwe.cmd = IWEVCUSTOM; | ||
1595 | sprintf(buf, "tsf=%016llx", (unsigned long long)(ies->tsf)); | ||
1596 | iwe.u.data.length = strlen(buf); | ||
1597 | current_ev = iwe_stream_add_point_check(info, current_ev, end_buf, | ||
1598 | &iwe, buf); | ||
1599 | if (IS_ERR(current_ev)) | ||
1600 | goto unlock; | ||
1601 | memset(&iwe, 0, sizeof(iwe)); | ||
1602 | iwe.cmd = IWEVCUSTOM; | ||
1603 | sprintf(buf, " Last beacon: %ums ago", | ||
1604 | elapsed_jiffies_msecs(bss->ts)); | ||
1605 | iwe.u.data.length = strlen(buf); | ||
1606 | current_ev = iwe_stream_add_point_check(info, current_ev, | ||
1607 | end_buf, &iwe, buf); | ||
1608 | if (IS_ERR(current_ev)) | ||
1609 | goto unlock; | ||
1610 | |||
1611 | current_ev = ieee80211_scan_add_ies(info, ies, current_ev, end_buf); | ||
1612 | |||
1613 | unlock: | ||
1491 | rcu_read_unlock(); | 1614 | rcu_read_unlock(); |
1492 | |||
1493 | return current_ev; | 1615 | return current_ev; |
1494 | } | 1616 | } |
1495 | 1617 | ||
@@ -1501,19 +1623,27 @@ static int ieee80211_scan_results(struct cfg80211_registered_device *rdev, | |||
1501 | char *current_ev = buf; | 1623 | char *current_ev = buf; |
1502 | char *end_buf = buf + len; | 1624 | char *end_buf = buf + len; |
1503 | struct cfg80211_internal_bss *bss; | 1625 | struct cfg80211_internal_bss *bss; |
1626 | int err = 0; | ||
1504 | 1627 | ||
1505 | spin_lock_bh(&rdev->bss_lock); | 1628 | spin_lock_bh(&rdev->bss_lock); |
1506 | cfg80211_bss_expire(rdev); | 1629 | cfg80211_bss_expire(rdev); |
1507 | 1630 | ||
1508 | list_for_each_entry(bss, &rdev->bss_list, list) { | 1631 | list_for_each_entry(bss, &rdev->bss_list, list) { |
1509 | if (buf + len - current_ev <= IW_EV_ADDR_LEN) { | 1632 | if (buf + len - current_ev <= IW_EV_ADDR_LEN) { |
1510 | spin_unlock_bh(&rdev->bss_lock); | 1633 | err = -E2BIG; |
1511 | return -E2BIG; | 1634 | break; |
1512 | } | 1635 | } |
1513 | current_ev = ieee80211_bss(&rdev->wiphy, info, bss, | 1636 | current_ev = ieee80211_bss(&rdev->wiphy, info, bss, |
1514 | current_ev, end_buf); | 1637 | current_ev, end_buf); |
1638 | if (IS_ERR(current_ev)) { | ||
1639 | err = PTR_ERR(current_ev); | ||
1640 | break; | ||
1641 | } | ||
1515 | } | 1642 | } |
1516 | spin_unlock_bh(&rdev->bss_lock); | 1643 | spin_unlock_bh(&rdev->bss_lock); |
1644 | |||
1645 | if (err) | ||
1646 | return err; | ||
1517 | return current_ev - buf; | 1647 | return current_ev - buf; |
1518 | } | 1648 | } |
1519 | 1649 | ||
@@ -1545,5 +1675,5 @@ int cfg80211_wext_giwscan(struct net_device *dev, | |||
1545 | 1675 | ||
1546 | return res; | 1676 | return res; |
1547 | } | 1677 | } |
1548 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan); | 1678 | EXPORT_WEXT_HANDLER(cfg80211_wext_giwscan); |
1549 | #endif | 1679 | #endif |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 0ab3711c79a0..ea1da6621ff0 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -257,19 +257,15 @@ static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev) | |||
257 | { | 257 | { |
258 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | 258 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); |
259 | struct cfg80211_bss *bss; | 259 | struct cfg80211_bss *bss; |
260 | u16 capa = WLAN_CAPABILITY_ESS; | ||
261 | 260 | ||
262 | ASSERT_WDEV_LOCK(wdev); | 261 | ASSERT_WDEV_LOCK(wdev); |
263 | 262 | ||
264 | if (wdev->conn->params.privacy) | ||
265 | capa |= WLAN_CAPABILITY_PRIVACY; | ||
266 | |||
267 | bss = cfg80211_get_bss(wdev->wiphy, wdev->conn->params.channel, | 263 | bss = cfg80211_get_bss(wdev->wiphy, wdev->conn->params.channel, |
268 | wdev->conn->params.bssid, | 264 | wdev->conn->params.bssid, |
269 | wdev->conn->params.ssid, | 265 | wdev->conn->params.ssid, |
270 | wdev->conn->params.ssid_len, | 266 | wdev->conn->params.ssid_len, |
271 | WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY, | 267 | IEEE80211_BSS_TYPE_ESS, |
272 | capa); | 268 | IEEE80211_PRIVACY(wdev->conn->params.privacy)); |
273 | if (!bss) | 269 | if (!bss) |
274 | return NULL; | 270 | return NULL; |
275 | 271 | ||
@@ -637,8 +633,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
637 | WARN_ON_ONCE(!wiphy_to_rdev(wdev->wiphy)->ops->connect); | 633 | WARN_ON_ONCE(!wiphy_to_rdev(wdev->wiphy)->ops->connect); |
638 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, | 634 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, |
639 | wdev->ssid, wdev->ssid_len, | 635 | wdev->ssid, wdev->ssid_len, |
640 | WLAN_CAPABILITY_ESS, | 636 | IEEE80211_BSS_TYPE_ESS, |
641 | WLAN_CAPABILITY_ESS); | 637 | IEEE80211_PRIVACY_ANY); |
642 | if (bss) | 638 | if (bss) |
643 | cfg80211_hold_bss(bss_from_pub(bss)); | 639 | cfg80211_hold_bss(bss_from_pub(bss)); |
644 | } | 640 | } |
@@ -795,8 +791,8 @@ void cfg80211_roamed(struct net_device *dev, | |||
795 | struct cfg80211_bss *bss; | 791 | struct cfg80211_bss *bss; |
796 | 792 | ||
797 | bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, wdev->ssid, | 793 | bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, wdev->ssid, |
798 | wdev->ssid_len, WLAN_CAPABILITY_ESS, | 794 | wdev->ssid_len, |
799 | WLAN_CAPABILITY_ESS); | 795 | IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY); |
800 | if (WARN_ON(!bss)) | 796 | if (WARN_ON(!bss)) |
801 | return; | 797 | return; |
802 | 798 | ||
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index a00ee8897dc6..af3617c9879e 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -628,6 +628,7 @@ DECLARE_EVENT_CLASS(station_add_change, | |||
628 | __field(u8, plink_state) | 628 | __field(u8, plink_state) |
629 | __field(u8, uapsd_queues) | 629 | __field(u8, uapsd_queues) |
630 | __array(u8, ht_capa, (int)sizeof(struct ieee80211_ht_cap)) | 630 | __array(u8, ht_capa, (int)sizeof(struct ieee80211_ht_cap)) |
631 | __array(char, vlan, IFNAMSIZ) | ||
631 | ), | 632 | ), |
632 | TP_fast_assign( | 633 | TP_fast_assign( |
633 | WIPHY_ASSIGN; | 634 | WIPHY_ASSIGN; |
@@ -645,16 +646,19 @@ DECLARE_EVENT_CLASS(station_add_change, | |||
645 | if (params->ht_capa) | 646 | if (params->ht_capa) |
646 | memcpy(__entry->ht_capa, params->ht_capa, | 647 | memcpy(__entry->ht_capa, params->ht_capa, |
647 | sizeof(struct ieee80211_ht_cap)); | 648 | sizeof(struct ieee80211_ht_cap)); |
649 | memset(__entry->vlan, 0, sizeof(__entry->vlan)); | ||
650 | if (params->vlan) | ||
651 | memcpy(__entry->vlan, params->vlan->name, IFNAMSIZ); | ||
648 | ), | 652 | ), |
649 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT | 653 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT |
650 | ", station flags mask: %u, station flags set: %u, " | 654 | ", station flags mask: %u, station flags set: %u, " |
651 | "station modify mask: %u, listen interval: %d, aid: %u, " | 655 | "station modify mask: %u, listen interval: %d, aid: %u, " |
652 | "plink action: %u, plink state: %u, uapsd queues: %u", | 656 | "plink action: %u, plink state: %u, uapsd queues: %u, vlan:%s", |
653 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac), | 657 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac), |
654 | __entry->sta_flags_mask, __entry->sta_flags_set, | 658 | __entry->sta_flags_mask, __entry->sta_flags_set, |
655 | __entry->sta_modify_mask, __entry->listen_interval, | 659 | __entry->sta_modify_mask, __entry->listen_interval, |
656 | __entry->aid, __entry->plink_action, __entry->plink_state, | 660 | __entry->aid, __entry->plink_action, __entry->plink_state, |
657 | __entry->uapsd_queues) | 661 | __entry->uapsd_queues, __entry->vlan) |
658 | ); | 662 | ); |
659 | 663 | ||
660 | DEFINE_EVENT(station_add_change, rdev_add_station, | 664 | DEFINE_EVENT(station_add_change, rdev_add_station, |
@@ -2637,28 +2641,30 @@ DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_stopped, | |||
2637 | TRACE_EVENT(cfg80211_get_bss, | 2641 | TRACE_EVENT(cfg80211_get_bss, |
2638 | TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel, | 2642 | TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel, |
2639 | const u8 *bssid, const u8 *ssid, size_t ssid_len, | 2643 | const u8 *bssid, const u8 *ssid, size_t ssid_len, |
2640 | u16 capa_mask, u16 capa_val), | 2644 | enum ieee80211_bss_type bss_type, |
2641 | TP_ARGS(wiphy, channel, bssid, ssid, ssid_len, capa_mask, capa_val), | 2645 | enum ieee80211_privacy privacy), |
2646 | TP_ARGS(wiphy, channel, bssid, ssid, ssid_len, bss_type, privacy), | ||
2642 | TP_STRUCT__entry( | 2647 | TP_STRUCT__entry( |
2643 | WIPHY_ENTRY | 2648 | WIPHY_ENTRY |
2644 | CHAN_ENTRY | 2649 | CHAN_ENTRY |
2645 | MAC_ENTRY(bssid) | 2650 | MAC_ENTRY(bssid) |
2646 | __dynamic_array(u8, ssid, ssid_len) | 2651 | __dynamic_array(u8, ssid, ssid_len) |
2647 | __field(u16, capa_mask) | 2652 | __field(enum ieee80211_bss_type, bss_type) |
2648 | __field(u16, capa_val) | 2653 | __field(enum ieee80211_privacy, privacy) |
2649 | ), | 2654 | ), |
2650 | TP_fast_assign( | 2655 | TP_fast_assign( |
2651 | WIPHY_ASSIGN; | 2656 | WIPHY_ASSIGN; |
2652 | CHAN_ASSIGN(channel); | 2657 | CHAN_ASSIGN(channel); |
2653 | MAC_ASSIGN(bssid, bssid); | 2658 | MAC_ASSIGN(bssid, bssid); |
2654 | memcpy(__get_dynamic_array(ssid), ssid, ssid_len); | 2659 | memcpy(__get_dynamic_array(ssid), ssid, ssid_len); |
2655 | __entry->capa_mask = capa_mask; | 2660 | __entry->bss_type = bss_type; |
2656 | __entry->capa_val = capa_val; | 2661 | __entry->privacy = privacy; |
2657 | ), | 2662 | ), |
2658 | TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT ", " MAC_PR_FMT ", buf: %#.2x, " | 2663 | TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT ", " MAC_PR_FMT |
2659 | "capa_mask: %d, capa_val: %u", WIPHY_PR_ARG, CHAN_PR_ARG, | 2664 | ", buf: %#.2x, bss_type: %d, privacy: %d", |
2660 | MAC_PR_ARG(bssid), ((u8 *)__get_dynamic_array(ssid))[0], | 2665 | WIPHY_PR_ARG, CHAN_PR_ARG, MAC_PR_ARG(bssid), |
2661 | __entry->capa_mask, __entry->capa_val) | 2666 | ((u8 *)__get_dynamic_array(ssid))[0], __entry->bss_type, |
2667 | __entry->privacy) | ||
2662 | ); | 2668 | ); |
2663 | 2669 | ||
2664 | TRACE_EVENT(cfg80211_inform_bss_width_frame, | 2670 | TRACE_EVENT(cfg80211_inform_bss_width_frame, |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 6903dbdcb8c1..f218b151530a 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -1296,6 +1296,7 @@ bool ieee80211_operating_class_to_band(u8 operating_class, | |||
1296 | switch (operating_class) { | 1296 | switch (operating_class) { |
1297 | case 112: | 1297 | case 112: |
1298 | case 115 ... 127: | 1298 | case 115 ... 127: |
1299 | case 128 ... 130: | ||
1299 | *band = IEEE80211_BAND_5GHZ; | 1300 | *band = IEEE80211_BAND_5GHZ; |
1300 | return true; | 1301 | return true; |
1301 | case 81: | 1302 | case 81: |
@@ -1313,6 +1314,135 @@ bool ieee80211_operating_class_to_band(u8 operating_class, | |||
1313 | } | 1314 | } |
1314 | EXPORT_SYMBOL(ieee80211_operating_class_to_band); | 1315 | EXPORT_SYMBOL(ieee80211_operating_class_to_band); |
1315 | 1316 | ||
1317 | bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, | ||
1318 | u8 *op_class) | ||
1319 | { | ||
1320 | u8 vht_opclass; | ||
1321 | u16 freq = chandef->center_freq1; | ||
1322 | |||
1323 | if (freq >= 2412 && freq <= 2472) { | ||
1324 | if (chandef->width > NL80211_CHAN_WIDTH_40) | ||
1325 | return false; | ||
1326 | |||
1327 | /* 2.407 GHz, channels 1..13 */ | ||
1328 | if (chandef->width == NL80211_CHAN_WIDTH_40) { | ||
1329 | if (freq > chandef->chan->center_freq) | ||
1330 | *op_class = 83; /* HT40+ */ | ||
1331 | else | ||
1332 | *op_class = 84; /* HT40- */ | ||
1333 | } else { | ||
1334 | *op_class = 81; | ||
1335 | } | ||
1336 | |||
1337 | return true; | ||
1338 | } | ||
1339 | |||
1340 | if (freq == 2484) { | ||
1341 | if (chandef->width > NL80211_CHAN_WIDTH_40) | ||
1342 | return false; | ||
1343 | |||
1344 | *op_class = 82; /* channel 14 */ | ||
1345 | return true; | ||
1346 | } | ||
1347 | |||
1348 | switch (chandef->width) { | ||
1349 | case NL80211_CHAN_WIDTH_80: | ||
1350 | vht_opclass = 128; | ||
1351 | break; | ||
1352 | case NL80211_CHAN_WIDTH_160: | ||
1353 | vht_opclass = 129; | ||
1354 | break; | ||
1355 | case NL80211_CHAN_WIDTH_80P80: | ||
1356 | vht_opclass = 130; | ||
1357 | break; | ||
1358 | case NL80211_CHAN_WIDTH_10: | ||
1359 | case NL80211_CHAN_WIDTH_5: | ||
1360 | return false; /* unsupported for now */ | ||
1361 | default: | ||
1362 | vht_opclass = 0; | ||
1363 | break; | ||
1364 | } | ||
1365 | |||
1366 | /* 5 GHz, channels 36..48 */ | ||
1367 | if (freq >= 5180 && freq <= 5240) { | ||
1368 | if (vht_opclass) { | ||
1369 | *op_class = vht_opclass; | ||
1370 | } else if (chandef->width == NL80211_CHAN_WIDTH_40) { | ||
1371 | if (freq > chandef->chan->center_freq) | ||
1372 | *op_class = 116; | ||
1373 | else | ||
1374 | *op_class = 117; | ||
1375 | } else { | ||
1376 | *op_class = 115; | ||
1377 | } | ||
1378 | |||
1379 | return true; | ||
1380 | } | ||
1381 | |||
1382 | /* 5 GHz, channels 52..64 */ | ||
1383 | if (freq >= 5260 && freq <= 5320) { | ||
1384 | if (vht_opclass) { | ||
1385 | *op_class = vht_opclass; | ||
1386 | } else if (chandef->width == NL80211_CHAN_WIDTH_40) { | ||
1387 | if (freq > chandef->chan->center_freq) | ||
1388 | *op_class = 119; | ||
1389 | else | ||
1390 | *op_class = 120; | ||
1391 | } else { | ||
1392 | *op_class = 118; | ||
1393 | } | ||
1394 | |||
1395 | return true; | ||
1396 | } | ||
1397 | |||
1398 | /* 5 GHz, channels 100..144 */ | ||
1399 | if (freq >= 5500 && freq <= 5720) { | ||
1400 | if (vht_opclass) { | ||
1401 | *op_class = vht_opclass; | ||
1402 | } else if (chandef->width == NL80211_CHAN_WIDTH_40) { | ||
1403 | if (freq > chandef->chan->center_freq) | ||
1404 | *op_class = 122; | ||
1405 | else | ||
1406 | *op_class = 123; | ||
1407 | } else { | ||
1408 | *op_class = 121; | ||
1409 | } | ||
1410 | |||
1411 | return true; | ||
1412 | } | ||
1413 | |||
1414 | /* 5 GHz, channels 149..169 */ | ||
1415 | if (freq >= 5745 && freq <= 5845) { | ||
1416 | if (vht_opclass) { | ||
1417 | *op_class = vht_opclass; | ||
1418 | } else if (chandef->width == NL80211_CHAN_WIDTH_40) { | ||
1419 | if (freq > chandef->chan->center_freq) | ||
1420 | *op_class = 126; | ||
1421 | else | ||
1422 | *op_class = 127; | ||
1423 | } else if (freq <= 5805) { | ||
1424 | *op_class = 124; | ||
1425 | } else { | ||
1426 | *op_class = 125; | ||
1427 | } | ||
1428 | |||
1429 | return true; | ||
1430 | } | ||
1431 | |||
1432 | /* 56.16 GHz, channel 1..4 */ | ||
1433 | if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) { | ||
1434 | if (chandef->width >= NL80211_CHAN_WIDTH_40) | ||
1435 | return false; | ||
1436 | |||
1437 | *op_class = 180; | ||
1438 | return true; | ||
1439 | } | ||
1440 | |||
1441 | /* not supported yet */ | ||
1442 | return false; | ||
1443 | } | ||
1444 | EXPORT_SYMBOL(ieee80211_chandef_to_operating_class); | ||
1445 | |||
1316 | int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | 1446 | int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, |
1317 | u32 beacon_int) | 1447 | u32 beacon_int) |
1318 | { | 1448 | { |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 5b24d39d7903..fff1bef6ed6d 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -63,7 +63,7 @@ int cfg80211_wext_giwname(struct net_device *dev, | |||
63 | 63 | ||
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
66 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwname); | 66 | EXPORT_WEXT_HANDLER(cfg80211_wext_giwname); |
67 | 67 | ||
68 | int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, | 68 | int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, |
69 | u32 *mode, char *extra) | 69 | u32 *mode, char *extra) |
@@ -99,7 +99,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, | |||
99 | 99 | ||
100 | return cfg80211_change_iface(rdev, dev, type, NULL, &vifparams); | 100 | return cfg80211_change_iface(rdev, dev, type, NULL, &vifparams); |
101 | } | 101 | } |
102 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode); | 102 | EXPORT_WEXT_HANDLER(cfg80211_wext_siwmode); |
103 | 103 | ||
104 | int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, | 104 | int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, |
105 | u32 *mode, char *extra) | 105 | u32 *mode, char *extra) |
@@ -134,7 +134,7 @@ int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, | |||
134 | } | 134 | } |
135 | return 0; | 135 | return 0; |
136 | } | 136 | } |
137 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwmode); | 137 | EXPORT_WEXT_HANDLER(cfg80211_wext_giwmode); |
138 | 138 | ||
139 | 139 | ||
140 | int cfg80211_wext_giwrange(struct net_device *dev, | 140 | int cfg80211_wext_giwrange(struct net_device *dev, |
@@ -248,7 +248,7 @@ int cfg80211_wext_giwrange(struct net_device *dev, | |||
248 | 248 | ||
249 | return 0; | 249 | return 0; |
250 | } | 250 | } |
251 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange); | 251 | EXPORT_WEXT_HANDLER(cfg80211_wext_giwrange); |
252 | 252 | ||
253 | 253 | ||
254 | /** | 254 | /** |
@@ -303,7 +303,7 @@ int cfg80211_wext_siwrts(struct net_device *dev, | |||
303 | 303 | ||
304 | return err; | 304 | return err; |
305 | } | 305 | } |
306 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwrts); | 306 | EXPORT_WEXT_HANDLER(cfg80211_wext_siwrts); |
307 | 307 | ||
308 | int cfg80211_wext_giwrts(struct net_device *dev, | 308 | int cfg80211_wext_giwrts(struct net_device *dev, |
309 | struct iw_request_info *info, | 309 | struct iw_request_info *info, |
@@ -317,7 +317,7 @@ int cfg80211_wext_giwrts(struct net_device *dev, | |||
317 | 317 | ||
318 | return 0; | 318 | return 0; |
319 | } | 319 | } |
320 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwrts); | 320 | EXPORT_WEXT_HANDLER(cfg80211_wext_giwrts); |
321 | 321 | ||
322 | int cfg80211_wext_siwfrag(struct net_device *dev, | 322 | int cfg80211_wext_siwfrag(struct net_device *dev, |
323 | struct iw_request_info *info, | 323 | struct iw_request_info *info, |
@@ -343,7 +343,7 @@ int cfg80211_wext_siwfrag(struct net_device *dev, | |||
343 | 343 | ||
344 | return err; | 344 | return err; |
345 | } | 345 | } |
346 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwfrag); | 346 | EXPORT_WEXT_HANDLER(cfg80211_wext_siwfrag); |
347 | 347 | ||
348 | int cfg80211_wext_giwfrag(struct net_device *dev, | 348 | int cfg80211_wext_giwfrag(struct net_device *dev, |
349 | struct iw_request_info *info, | 349 | struct iw_request_info *info, |
@@ -357,7 +357,7 @@ int cfg80211_wext_giwfrag(struct net_device *dev, | |||
357 | 357 | ||
358 | return 0; | 358 | return 0; |
359 | } | 359 | } |
360 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwfrag); | 360 | EXPORT_WEXT_HANDLER(cfg80211_wext_giwfrag); |
361 | 361 | ||
362 | static int cfg80211_wext_siwretry(struct net_device *dev, | 362 | static int cfg80211_wext_siwretry(struct net_device *dev, |
363 | struct iw_request_info *info, | 363 | struct iw_request_info *info, |
@@ -427,7 +427,7 @@ int cfg80211_wext_giwretry(struct net_device *dev, | |||
427 | 427 | ||
428 | return 0; | 428 | return 0; |
429 | } | 429 | } |
430 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); | 430 | EXPORT_WEXT_HANDLER(cfg80211_wext_giwretry); |
431 | 431 | ||
432 | static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | 432 | static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, |
433 | struct net_device *dev, bool pairwise, | 433 | struct net_device *dev, bool pairwise, |
diff --git a/net/wireless/wext-compat.h b/net/wireless/wext-compat.h index ebcacca2f731..94c7405a5413 100644 --- a/net/wireless/wext-compat.h +++ b/net/wireless/wext-compat.h | |||
@@ -4,6 +4,12 @@ | |||
4 | #include <net/iw_handler.h> | 4 | #include <net/iw_handler.h> |
5 | #include <linux/wireless.h> | 5 | #include <linux/wireless.h> |
6 | 6 | ||
7 | #ifdef CONFIG_CFG80211_WEXT_EXPORT | ||
8 | #define EXPORT_WEXT_HANDLER(h) EXPORT_SYMBOL_GPL(h) | ||
9 | #else | ||
10 | #define EXPORT_WEXT_HANDLER(h) | ||
11 | #endif /* CONFIG_CFG80211_WEXT_EXPORT */ | ||
12 | |||
7 | int cfg80211_ibss_wext_siwfreq(struct net_device *dev, | 13 | int cfg80211_ibss_wext_siwfreq(struct net_device *dev, |
8 | struct iw_request_info *info, | 14 | struct iw_request_info *info, |
9 | struct iw_freq *freq, char *extra); | 15 | struct iw_freq *freq, char *extra); |