diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-12-09 13:58:59 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-12-13 15:23:28 -0500 |
commit | dbd2fd656f2060abfd3a16257f8b51ec60f6d2ed (patch) | |
tree | 71e61430bd8593f2ad8f1c741b5a8a8be4a9d690 | |
parent | 897bed8b4320774e56f282cdc1cceb4d77442797 (diff) |
cfg80211/nl80211: separate unicast/multicast default TX keys
Allow userspace to specify that a given key
is default only for unicast and/or multicast
transmissions. Only WEP keys are for both,
WPA/RSN keys set here are GTKs for multicast
only. For more future flexibility, allow to
specify all combiations.
Wireless extensions can only set both so use
nl80211; WEP keys (connect keys) must be set
as default for both (but 802.1X WEP is still
possible).
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/cfg80211.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/cfg.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/rndis_wlan.c | 4 | ||||
-rw-r--r-- | include/linux/nl80211.h | 27 | ||||
-rw-r--r-- | include/net/cfg80211.h | 5 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 3 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 125 | ||||
-rw-r--r-- | net/wireless/util.c | 3 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 8 |
9 files changed, 152 insertions, 29 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index c6c0eff9b5ed..5a4982271e96 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c | |||
@@ -225,7 +225,8 @@ static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, | |||
225 | 225 | ||
226 | static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, | 226 | static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, |
227 | struct net_device *ndev, | 227 | struct net_device *ndev, |
228 | u8 key_index) | 228 | u8 key_index, bool unicast, |
229 | bool multicast) | ||
229 | { | 230 | { |
230 | struct iwm_priv *iwm = ndev_to_iwm(ndev); | 231 | struct iwm_priv *iwm = ndev_to_iwm(ndev); |
231 | 232 | ||
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index dee32d3681a5..300be1931826 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -1422,7 +1422,8 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev, | |||
1422 | 1422 | ||
1423 | static int lbs_cfg_set_default_key(struct wiphy *wiphy, | 1423 | static int lbs_cfg_set_default_key(struct wiphy *wiphy, |
1424 | struct net_device *netdev, | 1424 | struct net_device *netdev, |
1425 | u8 key_index) | 1425 | u8 key_index, bool unicast, |
1426 | bool multicast) | ||
1426 | { | 1427 | { |
1427 | struct lbs_private *priv = wiphy_priv(wiphy); | 1428 | struct lbs_private *priv = wiphy_priv(wiphy); |
1428 | 1429 | ||
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 19f3d568f700..4a4f00591447 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -554,7 +554,7 @@ static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, | |||
554 | u8 key_index, bool pairwise, const u8 *mac_addr); | 554 | u8 key_index, bool pairwise, const u8 *mac_addr); |
555 | 555 | ||
556 | static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, | 556 | static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, |
557 | u8 key_index); | 557 | u8 key_index, bool unicast, bool multicast); |
558 | 558 | ||
559 | static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, | 559 | static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, |
560 | u8 *mac, struct station_info *sinfo); | 560 | u8 *mac, struct station_info *sinfo); |
@@ -2381,7 +2381,7 @@ static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, | |||
2381 | } | 2381 | } |
2382 | 2382 | ||
2383 | static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, | 2383 | static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, |
2384 | u8 key_index) | 2384 | u8 key_index, bool unicast, bool multicast) |
2385 | { | 2385 | { |
2386 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | 2386 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); |
2387 | struct usbnet *usbdev = priv->usbdev; | 2387 | struct usbnet *usbdev = priv->usbdev; |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 380421253d16..b8fa25d741ba 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -851,6 +851,10 @@ enum nl80211_commands { | |||
851 | * | 851 | * |
852 | * @NL80211_ATTR_BSS_HTOPMODE: HT operation mode (u16) | 852 | * @NL80211_ATTR_BSS_HTOPMODE: HT operation mode (u16) |
853 | * | 853 | * |
854 | * @NL80211_ATTR_KEY_DEFAULT_TYPES: A nested attribute containing flags | ||
855 | * attributes, specifying what a key should be set as default as. | ||
856 | * See &enum nl80211_key_default_types. | ||
857 | * | ||
854 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 858 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
855 | * @__NL80211_ATTR_AFTER_LAST: internal use | 859 | * @__NL80211_ATTR_AFTER_LAST: internal use |
856 | */ | 860 | */ |
@@ -1029,6 +1033,8 @@ enum nl80211_attrs { | |||
1029 | 1033 | ||
1030 | NL80211_ATTR_BSS_HT_OPMODE, | 1034 | NL80211_ATTR_BSS_HT_OPMODE, |
1031 | 1035 | ||
1036 | NL80211_ATTR_KEY_DEFAULT_TYPES, | ||
1037 | |||
1032 | /* add attributes here, update the policy in nl80211.c */ | 1038 | /* add attributes here, update the policy in nl80211.c */ |
1033 | 1039 | ||
1034 | __NL80211_ATTR_AFTER_LAST, | 1040 | __NL80211_ATTR_AFTER_LAST, |
@@ -1775,6 +1781,23 @@ enum nl80211_wpa_versions { | |||
1775 | }; | 1781 | }; |
1776 | 1782 | ||
1777 | /** | 1783 | /** |
1784 | * enum nl80211_key_default_types - key default types | ||
1785 | * @__NL80211_KEY_DEFAULT_TYPE_INVALID: invalid | ||
1786 | * @NL80211_KEY_DEFAULT_TYPE_UNICAST: key should be used as default | ||
1787 | * unicast key | ||
1788 | * @NL80211_KEY_DEFAULT_TYPE_MULTICAST: key should be used as default | ||
1789 | * multicast key | ||
1790 | * @NUM_NL80211_KEY_DEFAULT_TYPES: number of default types | ||
1791 | */ | ||
1792 | enum nl80211_key_default_types { | ||
1793 | __NL80211_KEY_DEFAULT_TYPE_INVALID, | ||
1794 | NL80211_KEY_DEFAULT_TYPE_UNICAST, | ||
1795 | NL80211_KEY_DEFAULT_TYPE_MULTICAST, | ||
1796 | |||
1797 | NUM_NL80211_KEY_DEFAULT_TYPES | ||
1798 | }; | ||
1799 | |||
1800 | /** | ||
1778 | * enum nl80211_key_attributes - key attributes | 1801 | * enum nl80211_key_attributes - key attributes |
1779 | * @__NL80211_KEY_INVALID: invalid | 1802 | * @__NL80211_KEY_INVALID: invalid |
1780 | * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of | 1803 | * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of |
@@ -1790,6 +1813,9 @@ enum nl80211_wpa_versions { | |||
1790 | * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not | 1813 | * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not |
1791 | * specified the default depends on whether a MAC address was | 1814 | * specified the default depends on whether a MAC address was |
1792 | * given with the command using the key or not (u32) | 1815 | * given with the command using the key or not (u32) |
1816 | * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags | ||
1817 | * attributes, specifying what a key should be set as default as. | ||
1818 | * See &enum nl80211_key_default_types. | ||
1793 | * @__NL80211_KEY_AFTER_LAST: internal | 1819 | * @__NL80211_KEY_AFTER_LAST: internal |
1794 | * @NL80211_KEY_MAX: highest key attribute | 1820 | * @NL80211_KEY_MAX: highest key attribute |
1795 | */ | 1821 | */ |
@@ -1802,6 +1828,7 @@ enum nl80211_key_attributes { | |||
1802 | NL80211_KEY_DEFAULT, | 1828 | NL80211_KEY_DEFAULT, |
1803 | NL80211_KEY_DEFAULT_MGMT, | 1829 | NL80211_KEY_DEFAULT_MGMT, |
1804 | NL80211_KEY_TYPE, | 1830 | NL80211_KEY_TYPE, |
1831 | NL80211_KEY_DEFAULT_TYPES, | ||
1805 | 1832 | ||
1806 | /* keep last */ | 1833 | /* keep last */ |
1807 | __NL80211_KEY_AFTER_LAST, | 1834 | __NL80211_KEY_AFTER_LAST, |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 4d5acb013636..22be7c625b70 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1211,7 +1211,7 @@ struct cfg80211_ops { | |||
1211 | u8 key_index, bool pairwise, const u8 *mac_addr); | 1211 | u8 key_index, bool pairwise, const u8 *mac_addr); |
1212 | int (*set_default_key)(struct wiphy *wiphy, | 1212 | int (*set_default_key)(struct wiphy *wiphy, |
1213 | struct net_device *netdev, | 1213 | struct net_device *netdev, |
1214 | u8 key_index); | 1214 | u8 key_index, bool unicast, bool multicast); |
1215 | int (*set_default_mgmt_key)(struct wiphy *wiphy, | 1215 | int (*set_default_mgmt_key)(struct wiphy *wiphy, |
1216 | struct net_device *netdev, | 1216 | struct net_device *netdev, |
1217 | u8 key_index); | 1217 | u8 key_index); |
@@ -1393,6 +1393,8 @@ struct cfg80211_ops { | |||
1393 | * control port protocol ethertype. The device also honours the | 1393 | * control port protocol ethertype. The device also honours the |
1394 | * control_port_no_encrypt flag. | 1394 | * control_port_no_encrypt flag. |
1395 | * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN. | 1395 | * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN. |
1396 | * @WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS: The device supports separate | ||
1397 | * unicast and multicast TX keys. | ||
1396 | */ | 1398 | */ |
1397 | enum wiphy_flags { | 1399 | enum wiphy_flags { |
1398 | WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), | 1400 | WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), |
@@ -1404,6 +1406,7 @@ enum wiphy_flags { | |||
1404 | WIPHY_FLAG_4ADDR_STATION = BIT(6), | 1406 | WIPHY_FLAG_4ADDR_STATION = BIT(6), |
1405 | WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), | 1407 | WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), |
1406 | WIPHY_FLAG_IBSS_RSN = BIT(8), | 1408 | WIPHY_FLAG_IBSS_RSN = BIT(8), |
1409 | WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS= BIT(9), | ||
1407 | }; | 1410 | }; |
1408 | 1411 | ||
1409 | struct mac_address { | 1412 | struct mac_address { |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c30b8b72eedb..12f7dc048d34 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -295,7 +295,8 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
295 | 295 | ||
296 | static int ieee80211_config_default_key(struct wiphy *wiphy, | 296 | static int ieee80211_config_default_key(struct wiphy *wiphy, |
297 | struct net_device *dev, | 297 | struct net_device *dev, |
298 | u8 key_idx) | 298 | u8 key_idx, bool uni, |
299 | bool multi) | ||
299 | { | 300 | { |
300 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 301 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
301 | 302 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 73a7f6d354c9..53f044370cde 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -171,6 +171,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
171 | [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 }, | 171 | [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 }, |
172 | [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 }, | 172 | [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 }, |
173 | [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, | 173 | [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, |
174 | [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, | ||
174 | }; | 175 | }; |
175 | 176 | ||
176 | /* policy for the key attributes */ | 177 | /* policy for the key attributes */ |
@@ -182,6 +183,14 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { | |||
182 | [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, | 183 | [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, |
183 | [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, | 184 | [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, |
184 | [NL80211_KEY_TYPE] = { .type = NLA_U32 }, | 185 | [NL80211_KEY_TYPE] = { .type = NLA_U32 }, |
186 | [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, | ||
187 | }; | ||
188 | |||
189 | /* policy for the key default flags */ | ||
190 | static const struct nla_policy | ||
191 | nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = { | ||
192 | [NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG }, | ||
193 | [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG }, | ||
185 | }; | 194 | }; |
186 | 195 | ||
187 | /* ifidx get helper */ | 196 | /* ifidx get helper */ |
@@ -314,6 +323,7 @@ struct key_parse { | |||
314 | int idx; | 323 | int idx; |
315 | int type; | 324 | int type; |
316 | bool def, defmgmt; | 325 | bool def, defmgmt; |
326 | bool def_uni, def_multi; | ||
317 | }; | 327 | }; |
318 | 328 | ||
319 | static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) | 329 | static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) |
@@ -327,6 +337,13 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) | |||
327 | k->def = !!tb[NL80211_KEY_DEFAULT]; | 337 | k->def = !!tb[NL80211_KEY_DEFAULT]; |
328 | k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT]; | 338 | k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT]; |
329 | 339 | ||
340 | if (k->def) { | ||
341 | k->def_uni = true; | ||
342 | k->def_multi = true; | ||
343 | } | ||
344 | if (k->defmgmt) | ||
345 | k->def_multi = true; | ||
346 | |||
330 | if (tb[NL80211_KEY_IDX]) | 347 | if (tb[NL80211_KEY_IDX]) |
331 | k->idx = nla_get_u8(tb[NL80211_KEY_IDX]); | 348 | k->idx = nla_get_u8(tb[NL80211_KEY_IDX]); |
332 | 349 | ||
@@ -349,6 +366,19 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) | |||
349 | return -EINVAL; | 366 | return -EINVAL; |
350 | } | 367 | } |
351 | 368 | ||
369 | if (tb[NL80211_KEY_DEFAULT_TYPES]) { | ||
370 | struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES]; | ||
371 | int err = nla_parse_nested(kdt, | ||
372 | NUM_NL80211_KEY_DEFAULT_TYPES - 1, | ||
373 | tb[NL80211_KEY_DEFAULT_TYPES], | ||
374 | nl80211_key_default_policy); | ||
375 | if (err) | ||
376 | return err; | ||
377 | |||
378 | k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST]; | ||
379 | k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST]; | ||
380 | } | ||
381 | |||
352 | return 0; | 382 | return 0; |
353 | } | 383 | } |
354 | 384 | ||
@@ -373,12 +403,32 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k) | |||
373 | k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT]; | 403 | k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT]; |
374 | k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]; | 404 | k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]; |
375 | 405 | ||
406 | if (k->def) { | ||
407 | k->def_uni = true; | ||
408 | k->def_multi = true; | ||
409 | } | ||
410 | if (k->defmgmt) | ||
411 | k->def_multi = true; | ||
412 | |||
376 | if (info->attrs[NL80211_ATTR_KEY_TYPE]) { | 413 | if (info->attrs[NL80211_ATTR_KEY_TYPE]) { |
377 | k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]); | 414 | k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]); |
378 | if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) | 415 | if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) |
379 | return -EINVAL; | 416 | return -EINVAL; |
380 | } | 417 | } |
381 | 418 | ||
419 | if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) { | ||
420 | struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES]; | ||
421 | int err = nla_parse_nested( | ||
422 | kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1, | ||
423 | info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES], | ||
424 | nl80211_key_default_policy); | ||
425 | if (err) | ||
426 | return err; | ||
427 | |||
428 | k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST]; | ||
429 | k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST]; | ||
430 | } | ||
431 | |||
382 | return 0; | 432 | return 0; |
383 | } | 433 | } |
384 | 434 | ||
@@ -401,6 +451,11 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k) | |||
401 | if (k->def && k->defmgmt) | 451 | if (k->def && k->defmgmt) |
402 | return -EINVAL; | 452 | return -EINVAL; |
403 | 453 | ||
454 | if (k->defmgmt) { | ||
455 | if (k->def_uni || !k->def_multi) | ||
456 | return -EINVAL; | ||
457 | } | ||
458 | |||
404 | if (k->idx != -1) { | 459 | if (k->idx != -1) { |
405 | if (k->defmgmt) { | 460 | if (k->defmgmt) { |
406 | if (k->idx < 4 || k->idx > 5) | 461 | if (k->idx < 4 || k->idx > 5) |
@@ -450,6 +505,8 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, | |||
450 | goto error; | 505 | goto error; |
451 | def = 1; | 506 | def = 1; |
452 | result->def = parse.idx; | 507 | result->def = parse.idx; |
508 | if (!parse.def_uni || !parse.def_multi) | ||
509 | goto error; | ||
453 | } else if (parse.defmgmt) | 510 | } else if (parse.defmgmt) |
454 | goto error; | 511 | goto error; |
455 | err = cfg80211_validate_key_settings(rdev, &parse.p, | 512 | err = cfg80211_validate_key_settings(rdev, &parse.p, |
@@ -1586,8 +1643,6 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1586 | struct key_parse key; | 1643 | struct key_parse key; |
1587 | int err; | 1644 | int err; |
1588 | struct net_device *dev = info->user_ptr[1]; | 1645 | struct net_device *dev = info->user_ptr[1]; |
1589 | int (*func)(struct wiphy *wiphy, struct net_device *netdev, | ||
1590 | u8 key_index); | ||
1591 | 1646 | ||
1592 | err = nl80211_parse_key(info, &key); | 1647 | err = nl80211_parse_key(info, &key); |
1593 | if (err) | 1648 | if (err) |
@@ -1600,27 +1655,61 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1600 | if (!key.def && !key.defmgmt) | 1655 | if (!key.def && !key.defmgmt) |
1601 | return -EINVAL; | 1656 | return -EINVAL; |
1602 | 1657 | ||
1603 | if (key.def) | 1658 | wdev_lock(dev->ieee80211_ptr); |
1604 | func = rdev->ops->set_default_key; | ||
1605 | else | ||
1606 | func = rdev->ops->set_default_mgmt_key; | ||
1607 | 1659 | ||
1608 | if (!func) | 1660 | if (key.def) { |
1609 | return -EOPNOTSUPP; | 1661 | if (!rdev->ops->set_default_key) { |
1662 | err = -EOPNOTSUPP; | ||
1663 | goto out; | ||
1664 | } | ||
1610 | 1665 | ||
1611 | wdev_lock(dev->ieee80211_ptr); | 1666 | err = nl80211_key_allowed(dev->ieee80211_ptr); |
1612 | err = nl80211_key_allowed(dev->ieee80211_ptr); | 1667 | if (err) |
1613 | if (!err) | 1668 | goto out; |
1614 | err = func(&rdev->wiphy, dev, key.idx); | 1669 | |
1670 | if (!(rdev->wiphy.flags & | ||
1671 | WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS)) { | ||
1672 | if (!key.def_uni || !key.def_multi) { | ||
1673 | err = -EOPNOTSUPP; | ||
1674 | goto out; | ||
1675 | } | ||
1676 | } | ||
1677 | |||
1678 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx, | ||
1679 | key.def_uni, key.def_multi); | ||
1680 | |||
1681 | if (err) | ||
1682 | goto out; | ||
1615 | 1683 | ||
1616 | #ifdef CONFIG_CFG80211_WEXT | 1684 | #ifdef CONFIG_CFG80211_WEXT |
1617 | if (!err) { | 1685 | dev->ieee80211_ptr->wext.default_key = key.idx; |
1618 | if (func == rdev->ops->set_default_key) | 1686 | #endif |
1619 | dev->ieee80211_ptr->wext.default_key = key.idx; | 1687 | } else { |
1620 | else | 1688 | if (key.def_uni || !key.def_multi) { |
1621 | dev->ieee80211_ptr->wext.default_mgmt_key = key.idx; | 1689 | err = -EINVAL; |
1622 | } | 1690 | goto out; |
1691 | } | ||
1692 | |||
1693 | if (!rdev->ops->set_default_mgmt_key) { | ||
1694 | err = -EOPNOTSUPP; | ||
1695 | goto out; | ||
1696 | } | ||
1697 | |||
1698 | err = nl80211_key_allowed(dev->ieee80211_ptr); | ||
1699 | if (err) | ||
1700 | goto out; | ||
1701 | |||
1702 | err = rdev->ops->set_default_mgmt_key(&rdev->wiphy, | ||
1703 | dev, key.idx); | ||
1704 | if (err) | ||
1705 | goto out; | ||
1706 | |||
1707 | #ifdef CONFIG_CFG80211_WEXT | ||
1708 | dev->ieee80211_ptr->wext.default_mgmt_key = key.idx; | ||
1623 | #endif | 1709 | #endif |
1710 | } | ||
1711 | |||
1712 | out: | ||
1624 | wdev_unlock(dev->ieee80211_ptr); | 1713 | wdev_unlock(dev->ieee80211_ptr); |
1625 | 1714 | ||
1626 | return err; | 1715 | return err; |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 4de624ca4c63..7620ae2fcf18 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -689,7 +689,8 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev) | |||
689 | continue; | 689 | continue; |
690 | } | 690 | } |
691 | if (wdev->connect_keys->def == i) | 691 | if (wdev->connect_keys->def == i) |
692 | if (rdev->ops->set_default_key(wdev->wiphy, dev, i)) { | 692 | if (rdev->ops->set_default_key(wdev->wiphy, dev, |
693 | i, true, true)) { | ||
693 | netdev_err(dev, "failed to set defkey %d\n", i); | 694 | netdev_err(dev, "failed to set defkey %d\n", i); |
694 | continue; | 695 | continue; |
695 | } | 696 | } |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 12222ee6ebf2..3e5dbd4e4cd5 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -548,8 +548,8 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
548 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); | 548 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); |
549 | rejoin = true; | 549 | rejoin = true; |
550 | } | 550 | } |
551 | err = rdev->ops->set_default_key(&rdev->wiphy, | 551 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, |
552 | dev, idx); | 552 | idx, true, true); |
553 | } | 553 | } |
554 | if (!err) { | 554 | if (!err) { |
555 | wdev->wext.default_key = idx; | 555 | wdev->wext.default_key = idx; |
@@ -627,8 +627,8 @@ int cfg80211_wext_siwencode(struct net_device *dev, | |||
627 | err = 0; | 627 | err = 0; |
628 | wdev_lock(wdev); | 628 | wdev_lock(wdev); |
629 | if (wdev->current_bss) | 629 | if (wdev->current_bss) |
630 | err = rdev->ops->set_default_key(&rdev->wiphy, | 630 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, |
631 | dev, idx); | 631 | idx, true, true); |
632 | if (!err) | 632 | if (!err) |
633 | wdev->wext.default_key = idx; | 633 | wdev->wext.default_key = idx; |
634 | wdev_unlock(wdev); | 634 | wdev_unlock(wdev); |