aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-03-31 16:39:04 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-31 16:39:04 -0400
commit7b6249bba940f57c20cdde793b306ca3831778c7 (patch)
tree24caf2ec9ea6fca08fe225228614807d0919b4b2 /net/wireless
parentfbcb21705930f2930f506149d0b8d36dfbe45107 (diff)
parent2c44be81f0fc147eed9dc63e2601318b2c007aeb (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/Kconfig8
-rw-r--r--net/wireless/ibss.c2
-rw-r--r--net/wireless/mlme.c6
-rw-r--r--net/wireless/nl80211.c84
-rw-r--r--net/wireless/rdev-ops.h5
-rw-r--r--net/wireless/reg.c111
-rw-r--r--net/wireless/reg.h15
-rw-r--r--net/wireless/scan.c302
-rw-r--r--net/wireless/sme.c16
-rw-r--r--net/wireless/trace.h32
-rw-r--r--net/wireless/util.c130
-rw-r--r--net/wireless/wext-compat.c18
-rw-r--r--net/wireless/wext-compat.h6
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
186config 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
185config LIB80211 193config 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, &params); 2670 NET_NAME_USER, type, err ? NULL : &flags,
2671 &params);
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[],
4968static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) 4968static 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
7390static struct sk_buff * 7411static 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
7437struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy, 7468struct 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}
7466EXPORT_SYMBOL(__cfg80211_alloc_event_skb); 7498EXPORT_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
36static inline struct wireless_dev 36static 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 */
90enum reg_request_treatment { 86enum 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
98static struct regulatory_request core_request_world = { 93static 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 */
138static bool reg_is_indoor; 132static bool reg_is_indoor;
133static spinlock_t reg_indoor_lock;
134
135/* Used to track the userspace process controlling the indoor setting */
136static u32 reg_is_indoor_portid;
139 137
140static const struct ieee80211_regdomain *get_cfg80211_regdom(void) 138static 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 &reg_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
1251static 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
1258bool reg_last_request_cell_base(void) 1252bool 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(&reg_requests_lock); 1795 spin_unlock(&reg_requests_lock);
1802 1796
1803 if (lr->initiator == NL80211_REGDOM_SET_BY_USER) 1797 cancel_delayed_work(&reg_timeout);
1804 cancel_delayed_work(&reg_timeout);
1805 1798
1806 if (need_more_processing) 1799 if (need_more_processing)
1807 schedule_work(&reg_work); 1800 schedule_work(&reg_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 &reg_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(&reg_requests_lock);
2166 if (!list_empty(&reg_requests_list) && lr && lr->processed)
2167 schedule_work(&reg_work);
2168 spin_unlock(&reg_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
2312int regulatory_hint_indoor_user(void) 2301int regulatory_hint_indoor(bool is_indoor, u32 portid)
2313{ 2302{
2314 struct regulatory_request *request; 2303 spin_lock(&reg_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(&reg_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
2328void regulatory_netlink_notify(u32 portid)
2329{
2330 spin_lock(&reg_indoor_lock);
2331
2332 if (reg_is_indoor_portid != portid) {
2333 spin_unlock(&reg_indoor_lock);
2334 return;
2335 }
2336
2337 reg_is_indoor = false;
2338 reg_is_indoor_portid = 0;
2339
2340 spin_unlock(&reg_indoor_lock);
2341
2342 reg_check_channels();
2343}
2344
2328/* Driver hints */ 2345/* Driver hints */
2329int regulatory_hint(struct wiphy *wiphy, const char *alpha2) 2346int 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(&reg_indoor_lock);
2517 if (reg_is_indoor && !reg_is_indoor_portid) {
2518 reg_is_indoor = false;
2519 reg_check_channels();
2520 }
2521 spin_unlock(&reg_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(&reg_requests_lock); 2532 spin_lock(&reg_requests_lock);
2507 list_for_each_entry_safe(reg_request, tmp, &reg_requests_list, list) { 2533 list_splice_tail_init(&reg_requests_list, &tmp_reg_req_list);
2508 if (reg_request->initiator != NL80211_REGDOM_SET_BY_USER)
2509 continue;
2510 list_move_tail(&reg_request->list, &tmp_reg_req_list);
2511 }
2512 spin_unlock(&reg_requests_lock); 2534 spin_unlock(&reg_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(&reg_requests_lock); 3112 spin_lock_init(&reg_requests_lock);
3091 spin_lock_init(&reg_pending_beacons_lock); 3113 spin_lock_init(&reg_pending_beacons_lock);
3114 spin_lock_init(&reg_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
26int regulatory_hint_user(const char *alpha2, 26int 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);
28int 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 */
35int 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 */
41void regulatory_netlink_notify(u32 portid);
29 42
30void wiphy_regulatory_register(struct wiphy *wiphy); 43void wiphy_regulatory_register(struct wiphy *wiphy);
31void wiphy_regulatory_deregister(struct wiphy *wiphy); 44void 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
534static 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. */
535struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, 581struct 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}
1240EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); 1310EXPORT_WEXT_HANDLER(cfg80211_wext_siwscan);
1241 1311
1242static void ieee80211_scan_add_ies(struct iw_request_info *info, 1312static 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
1284static char * 1359static 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, &current_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}
1548EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan); 1678EXPORT_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
660DEFINE_EVENT(station_add_change, rdev_add_station, 664DEFINE_EVENT(station_add_change, rdev_add_station,
@@ -2637,28 +2641,30 @@ DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_stopped,
2637TRACE_EVENT(cfg80211_get_bss, 2641TRACE_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
2664TRACE_EVENT(cfg80211_inform_bss_width_frame, 2670TRACE_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}
1314EXPORT_SYMBOL(ieee80211_operating_class_to_band); 1315EXPORT_SYMBOL(ieee80211_operating_class_to_band);
1315 1316
1317bool 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}
1444EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
1445
1316int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, 1446int 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}
66EXPORT_SYMBOL_GPL(cfg80211_wext_giwname); 66EXPORT_WEXT_HANDLER(cfg80211_wext_giwname);
67 67
68int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, 68int 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}
102EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode); 102EXPORT_WEXT_HANDLER(cfg80211_wext_siwmode);
103 103
104int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, 104int 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}
137EXPORT_SYMBOL_GPL(cfg80211_wext_giwmode); 137EXPORT_WEXT_HANDLER(cfg80211_wext_giwmode);
138 138
139 139
140int cfg80211_wext_giwrange(struct net_device *dev, 140int 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}
251EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange); 251EXPORT_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}
306EXPORT_SYMBOL_GPL(cfg80211_wext_siwrts); 306EXPORT_WEXT_HANDLER(cfg80211_wext_siwrts);
307 307
308int cfg80211_wext_giwrts(struct net_device *dev, 308int 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}
320EXPORT_SYMBOL_GPL(cfg80211_wext_giwrts); 320EXPORT_WEXT_HANDLER(cfg80211_wext_giwrts);
321 321
322int cfg80211_wext_siwfrag(struct net_device *dev, 322int 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}
346EXPORT_SYMBOL_GPL(cfg80211_wext_siwfrag); 346EXPORT_WEXT_HANDLER(cfg80211_wext_siwfrag);
347 347
348int cfg80211_wext_giwfrag(struct net_device *dev, 348int 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}
360EXPORT_SYMBOL_GPL(cfg80211_wext_giwfrag); 360EXPORT_WEXT_HANDLER(cfg80211_wext_giwfrag);
361 361
362static int cfg80211_wext_siwretry(struct net_device *dev, 362static 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}
430EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); 430EXPORT_WEXT_HANDLER(cfg80211_wext_giwretry);
431 431
432static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, 432static 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
7int cfg80211_ibss_wext_siwfreq(struct net_device *dev, 13int 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);