diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-10-05 13:39:30 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-10-06 16:30:40 -0400 |
commit | e31b82136d1adc7a599b6e99d3321e5831841f5a (patch) | |
tree | c72d78d4cccfd08587e909c7efe59956f1cbc23e /net/wireless | |
parent | 53f73c09d64f1fa7d7e6e8b6bb7468d42eddc92d (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.h | 2 | ||||
-rw-r--r-- | net/wireless/ibss.c | 2 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 87 | ||||
-rw-r--r-- | net/wireless/sme.c | 2 | ||||
-rw-r--r-- | net/wireless/util.c | 12 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 38 |
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 */ |
376 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | 376 | int 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); |
379 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | 379 | void __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); |
381 | void cfg80211_sme_scan_done(struct net_device *dev); | 381 | void 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 */ |
172 | static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { | 173 | static 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, | |||
306 | struct key_parse { | 308 | struct 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 | ||
145 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | 145 | int 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, | |||
432 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); | 432 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); |
433 | 433 | ||
434 | static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | 434 | static 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 | ||
565 | static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | 575 | static 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, ¶ms); | 650 | idx, ¶ms); |
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, ¶ms); | 742 | idx, ¶ms); |
731 | } | 743 | } |