aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
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/nl80211.c
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/nl80211.c')
-rw-r--r--net/wireless/nl80211.c87
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 */
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 ||