aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/wireless/core.h10
-rw-r--r--net/wireless/mlme.c37
-rw-r--r--net/wireless/nl80211.c44
-rw-r--r--net/wireless/sme.c7
4 files changed, 91 insertions, 7 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 1c7d4df5418c..fb08c28fc90a 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -341,13 +341,17 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
341 const u8 *bssid, const u8 *prev_bssid, 341 const u8 *bssid, const u8 *prev_bssid,
342 const u8 *ssid, int ssid_len, 342 const u8 *ssid, int ssid_len,
343 const u8 *ie, int ie_len, bool use_mfp, 343 const u8 *ie, int ie_len, bool use_mfp,
344 struct cfg80211_crypto_settings *crypt); 344 struct cfg80211_crypto_settings *crypt,
345 u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
346 struct ieee80211_ht_cap *ht_capa_mask);
345int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 347int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
346 struct net_device *dev, struct ieee80211_channel *chan, 348 struct net_device *dev, struct ieee80211_channel *chan,
347 const u8 *bssid, const u8 *prev_bssid, 349 const u8 *bssid, const u8 *prev_bssid,
348 const u8 *ssid, int ssid_len, 350 const u8 *ssid, int ssid_len,
349 const u8 *ie, int ie_len, bool use_mfp, 351 const u8 *ie, int ie_len, bool use_mfp,
350 struct cfg80211_crypto_settings *crypt); 352 struct cfg80211_crypto_settings *crypt,
353 u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
354 struct ieee80211_ht_cap *ht_capa_mask);
351int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 355int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
352 struct net_device *dev, const u8 *bssid, 356 struct net_device *dev, const u8 *bssid,
353 const u8 *ie, int ie_len, u16 reason, 357 const u8 *ie, int ie_len, u16 reason,
@@ -379,6 +383,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
379 bool channel_type_valid, unsigned int wait, 383 bool channel_type_valid, unsigned int wait,
380 const u8 *buf, size_t len, bool no_cck, 384 const u8 *buf, size_t len, bool no_cck,
381 bool dont_wait_for_ack, u64 *cookie); 385 bool dont_wait_for_ack, u64 *cookie);
386void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
387 const struct ieee80211_ht_cap *ht_capa_mask);
382 388
383/* SME */ 389/* SME */
384int __cfg80211_connect(struct cfg80211_registered_device *rdev, 390int __cfg80211_connect(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 6c1bafd508c8..438dfc105b4a 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -501,13 +501,32 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
501 return err; 501 return err;
502} 502}
503 503
504/* Do a logical ht_capa &= ht_capa_mask. */
505void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
506 const struct ieee80211_ht_cap *ht_capa_mask)
507{
508 int i;
509 u8 *p1, *p2;
510 if (!ht_capa_mask) {
511 memset(ht_capa, 0, sizeof(*ht_capa));
512 return;
513 }
514
515 p1 = (u8*)(ht_capa);
516 p2 = (u8*)(ht_capa_mask);
517 for (i = 0; i<sizeof(*ht_capa); i++)
518 p1[i] &= p2[i];
519}
520
504int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 521int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
505 struct net_device *dev, 522 struct net_device *dev,
506 struct ieee80211_channel *chan, 523 struct ieee80211_channel *chan,
507 const u8 *bssid, const u8 *prev_bssid, 524 const u8 *bssid, const u8 *prev_bssid,
508 const u8 *ssid, int ssid_len, 525 const u8 *ssid, int ssid_len,
509 const u8 *ie, int ie_len, bool use_mfp, 526 const u8 *ie, int ie_len, bool use_mfp,
510 struct cfg80211_crypto_settings *crypt) 527 struct cfg80211_crypto_settings *crypt,
528 u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
529 struct ieee80211_ht_cap *ht_capa_mask)
511{ 530{
512 struct wireless_dev *wdev = dev->ieee80211_ptr; 531 struct wireless_dev *wdev = dev->ieee80211_ptr;
513 struct cfg80211_assoc_request req; 532 struct cfg80211_assoc_request req;
@@ -537,6 +556,15 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
537 memcpy(&req.crypto, crypt, sizeof(req.crypto)); 556 memcpy(&req.crypto, crypt, sizeof(req.crypto));
538 req.use_mfp = use_mfp; 557 req.use_mfp = use_mfp;
539 req.prev_bssid = prev_bssid; 558 req.prev_bssid = prev_bssid;
559 req.flags = assoc_flags;
560 if (ht_capa)
561 memcpy(&req.ht_capa, ht_capa, sizeof(req.ht_capa));
562 if (ht_capa_mask)
563 memcpy(&req.ht_capa_mask, ht_capa_mask,
564 sizeof(req.ht_capa_mask));
565 cfg80211_oper_and_ht_capa(&req.ht_capa_mask,
566 rdev->wiphy.ht_capa_mod_mask);
567
540 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, 568 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
541 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); 569 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
542 if (!req.bss) { 570 if (!req.bss) {
@@ -574,14 +602,17 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
574 const u8 *bssid, const u8 *prev_bssid, 602 const u8 *bssid, const u8 *prev_bssid,
575 const u8 *ssid, int ssid_len, 603 const u8 *ssid, int ssid_len,
576 const u8 *ie, int ie_len, bool use_mfp, 604 const u8 *ie, int ie_len, bool use_mfp,
577 struct cfg80211_crypto_settings *crypt) 605 struct cfg80211_crypto_settings *crypt,
606 u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
607 struct ieee80211_ht_cap *ht_capa_mask)
578{ 608{
579 struct wireless_dev *wdev = dev->ieee80211_ptr; 609 struct wireless_dev *wdev = dev->ieee80211_ptr;
580 int err; 610 int err;
581 611
582 wdev_lock(wdev); 612 wdev_lock(wdev);
583 err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, 613 err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
584 ssid, ssid_len, ie, ie_len, use_mfp, crypt); 614 ssid, ssid_len, ie, ie_len, use_mfp, crypt,
615 assoc_flags, ht_capa, ht_capa_mask);
585 wdev_unlock(wdev); 616 wdev_unlock(wdev);
586 617
587 return err; 618 return err;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 889f06483862..a1cabde7cb5f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -200,6 +200,10 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
200 [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY, 200 [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
201 .len = IEEE80211_MAX_DATA_LEN }, 201 .len = IEEE80211_MAX_DATA_LEN },
202 [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 }, 202 [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
203 [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
204 [NL80211_ATTR_HT_CAPABILITY_MASK] = {
205 .len = NL80211_HT_CAPABILITY_LEN
206 },
203}; 207};
204 208
205/* policy for the key attributes */ 209/* policy for the key attributes */
@@ -1032,6 +1036,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
1032 1036
1033 NLA_PUT_U32(msg, NL80211_ATTR_FEATURE_FLAGS, dev->wiphy.features); 1037 NLA_PUT_U32(msg, NL80211_ATTR_FEATURE_FLAGS, dev->wiphy.features);
1034 1038
1039 if (dev->wiphy.ht_capa_mod_mask)
1040 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
1041 sizeof(*dev->wiphy.ht_capa_mod_mask),
1042 dev->wiphy.ht_capa_mod_mask);
1043
1035 return genlmsg_end(msg, hdr); 1044 return genlmsg_end(msg, hdr);
1036 1045
1037 nla_put_failure: 1046 nla_put_failure:
@@ -4413,6 +4422,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
4413 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; 4422 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
4414 int err, ssid_len, ie_len = 0; 4423 int err, ssid_len, ie_len = 0;
4415 bool use_mfp = false; 4424 bool use_mfp = false;
4425 u32 flags = 0;
4426 struct ieee80211_ht_cap *ht_capa = NULL;
4427 struct ieee80211_ht_cap *ht_capa_mask = NULL;
4416 4428
4417 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 4429 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
4418 return -EINVAL; 4430 return -EINVAL;
@@ -4456,11 +4468,25 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
4456 if (info->attrs[NL80211_ATTR_PREV_BSSID]) 4468 if (info->attrs[NL80211_ATTR_PREV_BSSID])
4457 prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); 4469 prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
4458 4470
4471 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
4472 flags |= ASSOC_REQ_DISABLE_HT;
4473
4474 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
4475 ht_capa_mask =
4476 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]);
4477
4478 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
4479 if (!ht_capa_mask)
4480 return -EINVAL;
4481 ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
4482 }
4483
4459 err = nl80211_crypto_settings(rdev, info, &crypto, 1); 4484 err = nl80211_crypto_settings(rdev, info, &crypto, 1);
4460 if (!err) 4485 if (!err)
4461 err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, 4486 err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
4462 ssid, ssid_len, ie, ie_len, use_mfp, 4487 ssid, ssid_len, ie, ie_len, use_mfp,
4463 &crypto); 4488 &crypto, flags, ht_capa,
4489 ht_capa_mask);
4464 4490
4465 return err; 4491 return err;
4466} 4492}
@@ -4950,6 +4976,22 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
4950 return PTR_ERR(connkeys); 4976 return PTR_ERR(connkeys);
4951 } 4977 }
4952 4978
4979 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
4980 connect.flags |= ASSOC_REQ_DISABLE_HT;
4981
4982 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
4983 memcpy(&connect.ht_capa_mask,
4984 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
4985 sizeof(connect.ht_capa_mask));
4986
4987 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
4988 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
4989 return -EINVAL;
4990 memcpy(&connect.ht_capa,
4991 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
4992 sizeof(connect.ht_capa));
4993 }
4994
4953 err = cfg80211_connect(rdev, dev, &connect, connkeys); 4995 err = cfg80211_connect(rdev, dev, &connect, connkeys);
4954 if (err) 4996 if (err)
4955 kfree(connkeys); 4997 kfree(connkeys);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 6e86d5acf145..ed9d0e6f4a06 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -189,7 +189,9 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
189 prev_bssid, 189 prev_bssid,
190 params->ssid, params->ssid_len, 190 params->ssid, params->ssid_len,
191 params->ie, params->ie_len, 191 params->ie, params->ie_len,
192 false, &params->crypto); 192 false, &params->crypto,
193 params->flags, &params->ht_capa,
194 &params->ht_capa_mask);
193 if (err) 195 if (err)
194 __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, 196 __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
195 NULL, 0, 197 NULL, 0,
@@ -773,6 +775,9 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
773 wdev->connect_keys = NULL; 775 wdev->connect_keys = NULL;
774 } 776 }
775 777
778 cfg80211_oper_and_ht_capa(&connect->ht_capa_mask,
779 rdev->wiphy.ht_capa_mod_mask);
780
776 if (connkeys && connkeys->def >= 0) { 781 if (connkeys && connkeys->def >= 0) {
777 int idx; 782 int idx;
778 u32 cipher; 783 u32 cipher;