aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-10-05 13:39:30 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-10-06 16:30:40 -0400
commite31b82136d1adc7a599b6e99d3321e5831841f5a (patch)
treec72d78d4cccfd08587e909c7efe59956f1cbc23e /net/wireless
parent53f73c09d64f1fa7d7e6e8b6bb7468d42eddc92d (diff)
cfg80211/mac80211: allow per-station GTKs
This adds API to allow adding per-station GTKs, updates mac80211 to support it, and also allows drivers to remove a key from hwaccel again when this may be necessary due to multiple GTKs. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.h2
-rw-r--r--net/wireless/ibss.c2
-rw-r--r--net/wireless/nl80211.c87
-rw-r--r--net/wireless/sme.c2
-rw-r--r--net/wireless/util.c12
-rw-r--r--net/wireless/wext-compat.c38
6 files changed, 116 insertions, 27 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 37580e090a3d..2d1d4c70113c 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -375,7 +375,7 @@ bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev);
375/* internal helpers */ 375/* internal helpers */
376int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, 376int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
377 struct key_params *params, int key_idx, 377 struct key_params *params, int key_idx,
378 const u8 *mac_addr); 378 bool pairwise, const u8 *mac_addr);
379void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, 379void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
380 size_t ie_len, u16 reason, bool from_ap); 380 size_t ie_len, u16 reason, bool from_ap);
381void cfg80211_sme_scan_done(struct net_device *dev); 381void cfg80211_sme_scan_done(struct net_device *dev);
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 8cb6e08373b9..f33fbb79437c 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -160,7 +160,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
160 */ 160 */
161 if (rdev->ops->del_key) 161 if (rdev->ops->del_key)
162 for (i = 0; i < 6; i++) 162 for (i = 0; i < 6; i++)
163 rdev->ops->del_key(wdev->wiphy, dev, i, NULL); 163 rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
164 164
165 if (wdev->current_bss) { 165 if (wdev->current_bss) {
166 cfg80211_unhold_bss(wdev->current_bss); 166 cfg80211_unhold_bss(wdev->current_bss);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0c9497170f1f..8826888cc14e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -93,6 +93,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
93 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, 93 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
94 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, 94 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
95 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, 95 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
96 [NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 },
96 97
97 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, 98 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
98 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, 99 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
@@ -168,7 +169,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
168 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, 169 [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
169}; 170};
170 171
171/* policy for the attributes */ 172/* policy for the key attributes */
172static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { 173static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
173 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN }, 174 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
174 [NL80211_KEY_IDX] = { .type = NLA_U8 }, 175 [NL80211_KEY_IDX] = { .type = NLA_U8 },
@@ -176,6 +177,7 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
176 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, 177 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
177 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, 178 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
178 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, 179 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
180 [NL80211_KEY_TYPE] = { .type = NLA_U32 },
179}; 181};
180 182
181/* ifidx get helper */ 183/* ifidx get helper */
@@ -306,6 +308,7 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
306struct key_parse { 308struct key_parse {
307 struct key_params p; 309 struct key_params p;
308 int idx; 310 int idx;
311 int type;
309 bool def, defmgmt; 312 bool def, defmgmt;
310}; 313};
311 314
@@ -336,6 +339,12 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
336 if (tb[NL80211_KEY_CIPHER]) 339 if (tb[NL80211_KEY_CIPHER])
337 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]); 340 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
338 341
342 if (tb[NL80211_KEY_TYPE]) {
343 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
344 if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
345 return -EINVAL;
346 }
347
339 return 0; 348 return 0;
340} 349}
341 350
@@ -360,6 +369,12 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
360 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT]; 369 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
361 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]; 370 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
362 371
372 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
373 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
374 if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
375 return -EINVAL;
376 }
377
363 return 0; 378 return 0;
364} 379}
365 380
@@ -369,6 +384,7 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
369 384
370 memset(k, 0, sizeof(*k)); 385 memset(k, 0, sizeof(*k));
371 k->idx = -1; 386 k->idx = -1;
387 k->type = -1;
372 388
373 if (info->attrs[NL80211_ATTR_KEY]) 389 if (info->attrs[NL80211_ATTR_KEY])
374 err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k); 390 err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k);
@@ -433,7 +449,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
433 } else if (parse.defmgmt) 449 } else if (parse.defmgmt)
434 goto error; 450 goto error;
435 err = cfg80211_validate_key_settings(rdev, &parse.p, 451 err = cfg80211_validate_key_settings(rdev, &parse.p,
436 parse.idx, NULL); 452 parse.idx, false, NULL);
437 if (err) 453 if (err)
438 goto error; 454 goto error;
439 result->params[parse.idx].cipher = parse.p.cipher; 455 result->params[parse.idx].cipher = parse.p.cipher;
@@ -516,6 +532,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
516 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, 532 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
517 dev->wiphy.max_scan_ie_len); 533 dev->wiphy.max_scan_ie_len);
518 534
535 if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)
536 NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN);
537
519 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, 538 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES,
520 sizeof(u32) * dev->wiphy.n_cipher_suites, 539 sizeof(u32) * dev->wiphy.n_cipher_suites,
521 dev->wiphy.cipher_suites); 540 dev->wiphy.cipher_suites);
@@ -1446,7 +1465,8 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1446 int err; 1465 int err;
1447 struct net_device *dev = info->user_ptr[1]; 1466 struct net_device *dev = info->user_ptr[1];
1448 u8 key_idx = 0; 1467 u8 key_idx = 0;
1449 u8 *mac_addr = NULL; 1468 const u8 *mac_addr = NULL;
1469 bool pairwise;
1450 struct get_key_cookie cookie = { 1470 struct get_key_cookie cookie = {
1451 .error = 0, 1471 .error = 0,
1452 }; 1472 };
@@ -1462,6 +1482,17 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1462 if (info->attrs[NL80211_ATTR_MAC]) 1482 if (info->attrs[NL80211_ATTR_MAC])
1463 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1483 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1464 1484
1485 pairwise = !!mac_addr;
1486 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
1487 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
1488 if (kt >= NUM_NL80211_KEYTYPES)
1489 return -EINVAL;
1490 if (kt != NL80211_KEYTYPE_GROUP &&
1491 kt != NL80211_KEYTYPE_PAIRWISE)
1492 return -EINVAL;
1493 pairwise = kt == NL80211_KEYTYPE_PAIRWISE;
1494 }
1495
1465 if (!rdev->ops->get_key) 1496 if (!rdev->ops->get_key)
1466 return -EOPNOTSUPP; 1497 return -EOPNOTSUPP;
1467 1498
@@ -1482,8 +1513,12 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
1482 if (mac_addr) 1513 if (mac_addr)
1483 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); 1514 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
1484 1515
1485 err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, mac_addr, 1516 if (pairwise && mac_addr &&
1486 &cookie, get_key_callback); 1517 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
1518 return -ENOENT;
1519
1520 err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, pairwise,
1521 mac_addr, &cookie, get_key_callback);
1487 1522
1488 if (err) 1523 if (err)
1489 goto free_msg; 1524 goto free_msg;
@@ -1553,7 +1588,7 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1553 int err; 1588 int err;
1554 struct net_device *dev = info->user_ptr[1]; 1589 struct net_device *dev = info->user_ptr[1];
1555 struct key_parse key; 1590 struct key_parse key;
1556 u8 *mac_addr = NULL; 1591 const u8 *mac_addr = NULL;
1557 1592
1558 err = nl80211_parse_key(info, &key); 1593 err = nl80211_parse_key(info, &key);
1559 if (err) 1594 if (err)
@@ -1565,16 +1600,31 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1565 if (info->attrs[NL80211_ATTR_MAC]) 1600 if (info->attrs[NL80211_ATTR_MAC])
1566 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1601 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1567 1602
1603 if (key.type == -1) {
1604 if (mac_addr)
1605 key.type = NL80211_KEYTYPE_PAIRWISE;
1606 else
1607 key.type = NL80211_KEYTYPE_GROUP;
1608 }
1609
1610 /* for now */
1611 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
1612 key.type != NL80211_KEYTYPE_GROUP)
1613 return -EINVAL;
1614
1568 if (!rdev->ops->add_key) 1615 if (!rdev->ops->add_key)
1569 return -EOPNOTSUPP; 1616 return -EOPNOTSUPP;
1570 1617
1571 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr)) 1618 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
1619 key.type == NL80211_KEYTYPE_PAIRWISE,
1620 mac_addr))
1572 return -EINVAL; 1621 return -EINVAL;
1573 1622
1574 wdev_lock(dev->ieee80211_ptr); 1623 wdev_lock(dev->ieee80211_ptr);
1575 err = nl80211_key_allowed(dev->ieee80211_ptr); 1624 err = nl80211_key_allowed(dev->ieee80211_ptr);
1576 if (!err) 1625 if (!err)
1577 err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx, 1626 err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx,
1627 key.type == NL80211_KEYTYPE_PAIRWISE,
1578 mac_addr, &key.p); 1628 mac_addr, &key.p);
1579 wdev_unlock(dev->ieee80211_ptr); 1629 wdev_unlock(dev->ieee80211_ptr);
1580 1630
@@ -1596,13 +1646,32 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1596 if (info->attrs[NL80211_ATTR_MAC]) 1646 if (info->attrs[NL80211_ATTR_MAC])
1597 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1647 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1598 1648
1649 if (key.type == -1) {
1650 if (mac_addr)
1651 key.type = NL80211_KEYTYPE_PAIRWISE;
1652 else
1653 key.type = NL80211_KEYTYPE_GROUP;
1654 }
1655
1656 /* for now */
1657 if (key.type != NL80211_KEYTYPE_PAIRWISE &&
1658 key.type != NL80211_KEYTYPE_GROUP)
1659 return -EINVAL;
1660
1599 if (!rdev->ops->del_key) 1661 if (!rdev->ops->del_key)
1600 return -EOPNOTSUPP; 1662 return -EOPNOTSUPP;
1601 1663
1602 wdev_lock(dev->ieee80211_ptr); 1664 wdev_lock(dev->ieee80211_ptr);
1603 err = nl80211_key_allowed(dev->ieee80211_ptr); 1665 err = nl80211_key_allowed(dev->ieee80211_ptr);
1666
1667 if (key.type == NL80211_KEYTYPE_PAIRWISE && mac_addr &&
1668 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
1669 err = -ENOENT;
1670
1604 if (!err) 1671 if (!err)
1605 err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr); 1672 err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx,
1673 key.type == NL80211_KEYTYPE_PAIRWISE,
1674 mac_addr);
1606 1675
1607#ifdef CONFIG_CFG80211_WEXT 1676#ifdef CONFIG_CFG80211_WEXT
1608 if (!err) { 1677 if (!err) {
@@ -3212,6 +3281,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3212 return err; 3281 return err;
3213 3282
3214 if (key.idx >= 0) { 3283 if (key.idx >= 0) {
3284 if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP)
3285 return -EINVAL;
3215 if (!key.p.key || !key.p.key_len) 3286 if (!key.p.key || !key.p.key_len)
3216 return -EINVAL; 3287 return -EINVAL;
3217 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 || 3288 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index f161b9844542..e17b0bee6bdc 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -698,7 +698,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
698 */ 698 */
699 if (rdev->ops->del_key) 699 if (rdev->ops->del_key)
700 for (i = 0; i < 6; i++) 700 for (i = 0; i < 6; i++)
701 rdev->ops->del_key(wdev->wiphy, dev, i, NULL); 701 rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
702 702
703#ifdef CONFIG_CFG80211_WEXT 703#ifdef CONFIG_CFG80211_WEXT
704 memset(&wrqu, 0, sizeof(wrqu)); 704 memset(&wrqu, 0, sizeof(wrqu));
diff --git a/net/wireless/util.c b/net/wireless/util.c
index fb5448f7d55a..76120aeda57d 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -144,19 +144,25 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
144 144
145int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, 145int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
146 struct key_params *params, int key_idx, 146 struct key_params *params, int key_idx,
147 const u8 *mac_addr) 147 bool pairwise, const u8 *mac_addr)
148{ 148{
149 int i; 149 int i;
150 150
151 if (key_idx > 5) 151 if (key_idx > 5)
152 return -EINVAL; 152 return -EINVAL;
153 153
154 if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
155 return -EINVAL;
156
157 if (pairwise && !mac_addr)
158 return -EINVAL;
159
154 /* 160 /*
155 * Disallow pairwise keys with non-zero index unless it's WEP 161 * Disallow pairwise keys with non-zero index unless it's WEP
156 * (because current deployments use pairwise WEP keys with 162 * (because current deployments use pairwise WEP keys with
157 * non-zero indizes but 802.11i clearly specifies to use zero) 163 * non-zero indizes but 802.11i clearly specifies to use zero)
158 */ 164 */
159 if (mac_addr && key_idx && 165 if (pairwise && key_idx &&
160 params->cipher != WLAN_CIPHER_SUITE_WEP40 && 166 params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
161 params->cipher != WLAN_CIPHER_SUITE_WEP104) 167 params->cipher != WLAN_CIPHER_SUITE_WEP104)
162 return -EINVAL; 168 return -EINVAL;
@@ -677,7 +683,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
677 for (i = 0; i < 6; i++) { 683 for (i = 0; i < 6; i++) {
678 if (!wdev->connect_keys->params[i].cipher) 684 if (!wdev->connect_keys->params[i].cipher)
679 continue; 685 continue;
680 if (rdev->ops->add_key(wdev->wiphy, dev, i, NULL, 686 if (rdev->ops->add_key(wdev->wiphy, dev, i, false, NULL,
681 &wdev->connect_keys->params[i])) { 687 &wdev->connect_keys->params[i])) {
682 printk(KERN_ERR "%s: failed to set key %d\n", 688 printk(KERN_ERR "%s: failed to set key %d\n",
683 dev->name, i); 689 dev->name, i);
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 7e5c3a45f811..6002265289c6 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -432,14 +432,17 @@ int cfg80211_wext_giwretry(struct net_device *dev,
432EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); 432EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
433 433
434static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, 434static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
435 struct net_device *dev, const u8 *addr, 435 struct net_device *dev, bool pairwise,
436 bool remove, bool tx_key, int idx, 436 const u8 *addr, bool remove, bool tx_key,
437 struct key_params *params) 437 int idx, struct key_params *params)
438{ 438{
439 struct wireless_dev *wdev = dev->ieee80211_ptr; 439 struct wireless_dev *wdev = dev->ieee80211_ptr;
440 int err, i; 440 int err, i;
441 bool rejoin = false; 441 bool rejoin = false;
442 442
443 if (pairwise && !addr)
444 return -EINVAL;
445
443 if (!wdev->wext.keys) { 446 if (!wdev->wext.keys) {
444 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), 447 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
445 GFP_KERNEL); 448 GFP_KERNEL);
@@ -478,7 +481,13 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
478 __cfg80211_leave_ibss(rdev, wdev->netdev, true); 481 __cfg80211_leave_ibss(rdev, wdev->netdev, true);
479 rejoin = true; 482 rejoin = true;
480 } 483 }
481 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); 484
485 if (!pairwise && addr &&
486 !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
487 err = -ENOENT;
488 else
489 err = rdev->ops->del_key(&rdev->wiphy, dev, idx,
490 pairwise, addr);
482 } 491 }
483 wdev->wext.connect.privacy = false; 492 wdev->wext.connect.privacy = false;
484 /* 493 /*
@@ -507,12 +516,13 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
507 if (addr) 516 if (addr)
508 tx_key = false; 517 tx_key = false;
509 518
510 if (cfg80211_validate_key_settings(rdev, params, idx, addr)) 519 if (cfg80211_validate_key_settings(rdev, params, idx, pairwise, addr))
511 return -EINVAL; 520 return -EINVAL;
512 521
513 err = 0; 522 err = 0;
514 if (wdev->current_bss) 523 if (wdev->current_bss)
515 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params); 524 err = rdev->ops->add_key(&rdev->wiphy, dev, idx,
525 pairwise, addr, params);
516 if (err) 526 if (err)
517 return err; 527 return err;
518 528
@@ -563,17 +573,17 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
563} 573}
564 574
565static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, 575static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
566 struct net_device *dev, const u8 *addr, 576 struct net_device *dev, bool pairwise,
567 bool remove, bool tx_key, int idx, 577 const u8 *addr, bool remove, bool tx_key,
568 struct key_params *params) 578 int idx, struct key_params *params)
569{ 579{
570 int err; 580 int err;
571 581
572 /* devlist mutex needed for possible IBSS re-join */ 582 /* devlist mutex needed for possible IBSS re-join */
573 mutex_lock(&rdev->devlist_mtx); 583 mutex_lock(&rdev->devlist_mtx);
574 wdev_lock(dev->ieee80211_ptr); 584 wdev_lock(dev->ieee80211_ptr);
575 err = __cfg80211_set_encryption(rdev, dev, addr, remove, 585 err = __cfg80211_set_encryption(rdev, dev, pairwise, addr,
576 tx_key, idx, params); 586 remove, tx_key, idx, params);
577 wdev_unlock(dev->ieee80211_ptr); 587 wdev_unlock(dev->ieee80211_ptr);
578 mutex_unlock(&rdev->devlist_mtx); 588 mutex_unlock(&rdev->devlist_mtx);
579 589
@@ -635,7 +645,7 @@ int cfg80211_wext_siwencode(struct net_device *dev,
635 else if (!remove) 645 else if (!remove)
636 return -EINVAL; 646 return -EINVAL;
637 647
638 return cfg80211_set_encryption(rdev, dev, NULL, remove, 648 return cfg80211_set_encryption(rdev, dev, false, NULL, remove,
639 wdev->wext.default_key == -1, 649 wdev->wext.default_key == -1,
640 idx, &params); 650 idx, &params);
641} 651}
@@ -725,7 +735,9 @@ int cfg80211_wext_siwencodeext(struct net_device *dev,
725 } 735 }
726 736
727 return cfg80211_set_encryption( 737 return cfg80211_set_encryption(
728 rdev, dev, addr, remove, 738 rdev, dev,
739 !(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY),
740 addr, remove,
729 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, 741 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
730 idx, &params); 742 idx, &params);
731} 743}