aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-12-09 13:58:59 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-13 15:23:28 -0500
commitdbd2fd656f2060abfd3a16257f8b51ec60f6d2ed (patch)
tree71e61430bd8593f2ad8f1c741b5a8a8be4a9d690 /net/wireless/nl80211.c
parent897bed8b4320774e56f282cdc1cceb4d77442797 (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>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c125
1 files changed, 107 insertions, 18 deletions
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 */
190static const struct nla_policy
191nl80211_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
319static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) 329static 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;