aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.c7
-rw-r--r--net/wireless/core.h4
-rw-r--r--net/wireless/nl80211.c109
-rw-r--r--net/wireless/scan.c4
-rw-r--r--net/wireless/util.c38
5 files changed, 140 insertions, 22 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 880dbe2e6f94..645437cfc464 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -488,6 +488,10 @@ int wiphy_register(struct wiphy *wiphy)
488 int i; 488 int i;
489 u16 ifmodes = wiphy->interface_modes; 489 u16 ifmodes = wiphy->interface_modes;
490 490
491 if (WARN_ON((wiphy->wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
492 !(wiphy->wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)))
493 return -EINVAL;
494
491 if (WARN_ON(wiphy->addresses && !wiphy->n_addresses)) 495 if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
492 return -EINVAL; 496 return -EINVAL;
493 497
@@ -918,7 +922,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
918 * Configure power management to the driver here so that its 922 * Configure power management to the driver here so that its
919 * correctly set also after interface type changes etc. 923 * correctly set also after interface type changes etc.
920 */ 924 */
921 if (wdev->iftype == NL80211_IFTYPE_STATION && 925 if ((wdev->iftype == NL80211_IFTYPE_STATION ||
926 wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
922 rdev->ops->set_power_mgmt) 927 rdev->ops->set_power_mgmt)
923 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, 928 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
924 wdev->ps, 929 wdev->ps,
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a570ff9214ec..8672e028022f 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -447,6 +447,10 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
447 447
448u16 cfg80211_calculate_bitrate(struct rate_info *rate); 448u16 cfg80211_calculate_bitrate(struct rate_info *rate);
449 449
450int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
451 const u8 *rates, unsigned int n_rates,
452 u32 *mask);
453
450int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, 454int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
451 u32 beacon_int); 455 u32 beacon_int);
452 456
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 6a82c898f831..28d2aa109bee 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -177,6 +177,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
177 [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 }, 177 [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 },
178 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, 178 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
179 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED }, 179 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
180 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
180}; 181};
181 182
182/* policy for the key attributes */ 183/* policy for the key attributes */
@@ -205,6 +206,10 @@ nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
205 [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG }, 206 [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG },
206 [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG }, 207 [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG },
207 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED }, 208 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
209 [NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG },
210 [NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG },
211 [NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
212 [NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
208}; 213};
209 214
210/* policy for GTK rekey offload attributes */ 215/* policy for GTK rekey offload attributes */
@@ -692,8 +697,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
692 dev->wiphy.coverage_class); 697 dev->wiphy.coverage_class);
693 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, 698 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
694 dev->wiphy.max_scan_ssids); 699 dev->wiphy.max_scan_ssids);
700 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
701 dev->wiphy.max_sched_scan_ssids);
695 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, 702 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
696 dev->wiphy.max_scan_ie_len); 703 dev->wiphy.max_scan_ie_len);
704 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
705 dev->wiphy.max_sched_scan_ie_len);
697 706
698 if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) 707 if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)
699 NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN); 708 NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN);
@@ -929,6 +938,16 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
929 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); 938 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT);
930 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) 939 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT)
931 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); 940 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
941 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)
942 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED);
943 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE)
944 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE);
945 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ)
946 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST);
947 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE)
948 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE);
949 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE)
950 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE);
932 if (dev->wiphy.wowlan.n_patterns) { 951 if (dev->wiphy.wowlan.n_patterns) {
933 struct nl80211_wowlan_pattern_support pat = { 952 struct nl80211_wowlan_pattern_support pat = {
934 .max_patterns = dev->wiphy.wowlan.n_patterns, 953 .max_patterns = dev->wiphy.wowlan.n_patterns,
@@ -3306,7 +3325,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3306 struct nlattr *attr; 3325 struct nlattr *attr;
3307 struct wiphy *wiphy; 3326 struct wiphy *wiphy;
3308 int err, tmp, n_ssids = 0, n_channels, i; 3327 int err, tmp, n_ssids = 0, n_channels, i;
3309 enum ieee80211_band band;
3310 size_t ie_len; 3328 size_t ie_len;
3311 3329
3312 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3330 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
@@ -3326,6 +3344,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3326 if (!n_channels) 3344 if (!n_channels)
3327 return -EINVAL; 3345 return -EINVAL;
3328 } else { 3346 } else {
3347 enum ieee80211_band band;
3329 n_channels = 0; 3348 n_channels = 0;
3330 3349
3331 for (band = 0; band < IEEE80211_NUM_BANDS; band++) 3350 for (band = 0; band < IEEE80211_NUM_BANDS; band++)
@@ -3386,6 +3405,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3386 i++; 3405 i++;
3387 } 3406 }
3388 } else { 3407 } else {
3408 enum ieee80211_band band;
3409
3389 /* all channels */ 3410 /* all channels */
3390 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 3411 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
3391 int j; 3412 int j;
@@ -3432,6 +3453,30 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3432 request->ie_len); 3453 request->ie_len);
3433 } 3454 }
3434 3455
3456 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
3457 if (wiphy->bands[i])
3458 request->rates[i] =
3459 (1 << wiphy->bands[i]->n_bitrates) - 1;
3460
3461 if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
3462 nla_for_each_nested(attr,
3463 info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
3464 tmp) {
3465 enum ieee80211_band band = nla_type(attr);
3466
3467 if (band < 0 || band > IEEE80211_NUM_BANDS) {
3468 err = -EINVAL;
3469 goto out_free;
3470 }
3471 err = ieee80211_get_ratemask(wiphy->bands[band],
3472 nla_data(attr),
3473 nla_len(attr),
3474 &request->rates[band]);
3475 if (err)
3476 goto out_free;
3477 }
3478 }
3479
3435 request->dev = dev; 3480 request->dev = dev;
3436 request->wiphy = &rdev->wiphy; 3481 request->wiphy = &rdev->wiphy;
3437 3482
@@ -3497,7 +3542,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
3497 tmp) 3542 tmp)
3498 n_ssids++; 3543 n_ssids++;
3499 3544
3500 if (n_ssids > wiphy->max_scan_ssids) 3545 if (n_ssids > wiphy->max_sched_scan_ssids)
3501 return -EINVAL; 3546 return -EINVAL;
3502 3547
3503 if (info->attrs[NL80211_ATTR_IE]) 3548 if (info->attrs[NL80211_ATTR_IE])
@@ -3505,7 +3550,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
3505 else 3550 else
3506 ie_len = 0; 3551 ie_len = 0;
3507 3552
3508 if (ie_len > wiphy->max_scan_ie_len) 3553 if (ie_len > wiphy->max_sched_scan_ie_len)
3509 return -EINVAL; 3554 return -EINVAL;
3510 3555
3511 mutex_lock(&rdev->sched_scan_mtx); 3556 mutex_lock(&rdev->sched_scan_mtx);
@@ -4318,25 +4363,12 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4318 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); 4363 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
4319 struct ieee80211_supported_band *sband = 4364 struct ieee80211_supported_band *sband =
4320 wiphy->bands[ibss.channel->band]; 4365 wiphy->bands[ibss.channel->band];
4321 int i, j; 4366 int err;
4322 4367
4323 if (n_rates == 0) 4368 err = ieee80211_get_ratemask(sband, rates, n_rates,
4324 return -EINVAL; 4369 &ibss.basic_rates);
4325 4370 if (err)
4326 for (i = 0; i < n_rates; i++) { 4371 return err;
4327 int rate = (rates[i] & 0x7f) * 5;
4328 bool found = false;
4329
4330 for (j = 0; j < sband->n_bitrates; j++) {
4331 if (sband->bitrates[j].bitrate == rate) {
4332 found = true;
4333 ibss.basic_rates |= BIT(j);
4334 break;
4335 }
4336 }
4337 if (!found)
4338 return -EINVAL;
4339 }
4340 } 4372 }
4341 4373
4342 if (info->attrs[NL80211_ATTR_MCAST_RATE] && 4374 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
@@ -5272,6 +5304,14 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
5272 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); 5304 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT);
5273 if (rdev->wowlan->magic_pkt) 5305 if (rdev->wowlan->magic_pkt)
5274 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); 5306 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
5307 if (rdev->wowlan->gtk_rekey_failure)
5308 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE);
5309 if (rdev->wowlan->eap_identity_req)
5310 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST);
5311 if (rdev->wowlan->four_way_handshake)
5312 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE);
5313 if (rdev->wowlan->rfkill_release)
5314 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE);
5275 if (rdev->wowlan->n_patterns) { 5315 if (rdev->wowlan->n_patterns) {
5276 struct nlattr *nl_pats, *nl_pat; 5316 struct nlattr *nl_pats, *nl_pat;
5277 int i, pat_len; 5317 int i, pat_len;
@@ -5348,6 +5388,33 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
5348 new_triggers.magic_pkt = true; 5388 new_triggers.magic_pkt = true;
5349 } 5389 }
5350 5390
5391 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
5392 return -EINVAL;
5393
5394 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) {
5395 if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
5396 return -EINVAL;
5397 new_triggers.gtk_rekey_failure = true;
5398 }
5399
5400 if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
5401 if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
5402 return -EINVAL;
5403 new_triggers.eap_identity_req = true;
5404 }
5405
5406 if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
5407 if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
5408 return -EINVAL;
5409 new_triggers.four_way_handshake = true;
5410 }
5411
5412 if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
5413 if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
5414 return -EINVAL;
5415 new_triggers.rfkill_release = true;
5416 }
5417
5351 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { 5418 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
5352 struct nlattr *pat; 5419 struct nlattr *pat;
5353 int n_patterns = 0; 5420 int n_patterns = 0;
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 1c4672e35144..2936cb809152 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -862,6 +862,10 @@ int cfg80211_wext_siwscan(struct net_device *dev,
862 creq->n_ssids = 0; 862 creq->n_ssids = 0;
863 } 863 }
864 864
865 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
866 if (wiphy->bands[i])
867 creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
868
865 rdev->scan_req = creq; 869 rdev->scan_req = creq;
866 err = rdev->ops->scan(wiphy, dev, creq); 870 err = rdev->ops->scan(wiphy, dev, creq);
867 if (err) { 871 if (err) {
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 4d7b83fbc32f..be75a3a0424e 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1006,3 +1006,41 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
1006 1006
1007 return -EBUSY; 1007 return -EBUSY;
1008} 1008}
1009
1010int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
1011 const u8 *rates, unsigned int n_rates,
1012 u32 *mask)
1013{
1014 int i, j;
1015
1016 if (!sband)
1017 return -EINVAL;
1018
1019 if (n_rates == 0 || n_rates > NL80211_MAX_SUPP_RATES)
1020 return -EINVAL;
1021
1022 *mask = 0;
1023
1024 for (i = 0; i < n_rates; i++) {
1025 int rate = (rates[i] & 0x7f) * 5;
1026 bool found = false;
1027
1028 for (j = 0; j < sband->n_bitrates; j++) {
1029 if (sband->bitrates[j].bitrate == rate) {
1030 found = true;
1031 *mask |= BIT(j);
1032 break;
1033 }
1034 }
1035 if (!found)
1036 return -EINVAL;
1037 }
1038
1039 /*
1040 * mask must have at least one bit set here since we
1041 * didn't accept a 0-length rates array nor allowed
1042 * entries in the array that didn't exist
1043 */
1044
1045 return 0;
1046}