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/nl80211.c | |
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/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 87 |
1 files changed, 79 insertions, 8 deletions
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 || |