From: Johannes Berg <johannes@sipsolutions.net>
To: John Linville <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org
Subject: [PATCH 2/3] cfg80211/nl80211: separate unicast/multicast default TX keys
Date: Thu, 09 Dec 2010 19:49:01 +0100 [thread overview]
Message-ID: <20101209185002.763284359@sipsolutions.net> (raw)
In-Reply-To: 20101209184859.155955840@sipsolutions.net
From: Johannes Berg <johannes.berg@intel.com>
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>
---
drivers/net/wireless/iwmc3200wifi/cfg80211.c | 3
drivers/net/wireless/libertas/cfg.c | 3
drivers/net/wireless/rndis_wlan.c | 4
include/linux/nl80211.h | 27 +++++
include/net/cfg80211.h | 5 -
net/mac80211/cfg.c | 3
net/wireless/nl80211.c | 123 +++++++++++++++++++++++----
net/wireless/util.c | 3
net/wireless/wext-compat.c | 8 -
9 files changed, 150 insertions(+), 29 deletions(-)
--- wireless-testing.orig/include/linux/nl80211.h 2010-12-06 10:44:24.000000000 +0100
+++ wireless-testing/include/linux/nl80211.h 2010-12-06 10:45:11.000000000 +0100
@@ -849,6 +849,10 @@ enum nl80211_commands {
* flag isn't set, the frame will be rejected. This is also used as an
* nl80211 capability flag.
*
+ * @NL80211_ATTR_KEY_DEFAULT_TYPES: A nested attribute containing flags
+ * attributes, specifying what a key should be set as default as.
+ * See &enum nl80211_key_default_types.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1025,6 +1029,8 @@ enum nl80211_attrs {
NL80211_ATTR_OFFCHANNEL_TX_OK,
+ NL80211_ATTR_KEY_DEFAULT_TYPES,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -1769,6 +1775,23 @@ enum nl80211_wpa_versions {
};
/**
+ * enum nl80211_key_default_types - key default types
+ * @__NL80211_KEY_DEFAULT_TYPE_INVALID: invalid
+ * @NL80211_KEY_DEFAULT_TYPE_UNICAST: key should be used as default
+ * unicast key
+ * @NL80211_KEY_DEFAULT_TYPE_MULTICAST: key should be used as default
+ * multicast key
+ * @NUM_NL80211_KEY_DEFAULT_TYPES: number of default types
+ */
+enum nl80211_key_default_types {
+ __NL80211_KEY_DEFAULT_TYPE_INVALID,
+ NL80211_KEY_DEFAULT_TYPE_UNICAST,
+ NL80211_KEY_DEFAULT_TYPE_MULTICAST,
+
+ NUM_NL80211_KEY_DEFAULT_TYPES
+};
+
+/**
* enum nl80211_key_attributes - key attributes
* @__NL80211_KEY_INVALID: invalid
* @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of
@@ -1784,6 +1807,9 @@ enum nl80211_wpa_versions {
* @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not
* specified the default depends on whether a MAC address was
* given with the command using the key or not (u32)
+ * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags
+ * attributes, specifying what a key should be set as default as.
+ * See &enum nl80211_key_default_types.
* @__NL80211_KEY_AFTER_LAST: internal
* @NL80211_KEY_MAX: highest key attribute
*/
@@ -1796,6 +1822,7 @@ enum nl80211_key_attributes {
NL80211_KEY_DEFAULT,
NL80211_KEY_DEFAULT_MGMT,
NL80211_KEY_TYPE,
+ NL80211_KEY_DEFAULT_TYPES,
/* keep last */
__NL80211_KEY_AFTER_LAST,
--- wireless-testing.orig/drivers/net/wireless/iwmc3200wifi/cfg80211.c 2010-12-06 10:44:24.000000000 +0100
+++ wireless-testing/drivers/net/wireless/iwmc3200wifi/cfg80211.c 2010-12-06 10:45:11.000000000 +0100
@@ -225,7 +225,8 @@ static int iwm_cfg80211_del_key(struct w
static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
struct net_device *ndev,
- u8 key_index)
+ u8 key_index, bool unicast,
+ bool multicast)
{
struct iwm_priv *iwm = ndev_to_iwm(ndev);
--- wireless-testing.orig/drivers/net/wireless/libertas/cfg.c 2010-12-06 10:44:24.000000000 +0100
+++ wireless-testing/drivers/net/wireless/libertas/cfg.c 2010-12-06 10:45:11.000000000 +0100
@@ -1422,7 +1422,8 @@ static int lbs_cfg_disconnect(struct wip
static int lbs_cfg_set_default_key(struct wiphy *wiphy,
struct net_device *netdev,
- u8 key_index)
+ u8 key_index, bool unicast,
+ bool multicast)
{
struct lbs_private *priv = wiphy_priv(wiphy);
--- wireless-testing.orig/drivers/net/wireless/rndis_wlan.c 2010-12-06 10:44:24.000000000 +0100
+++ wireless-testing/drivers/net/wireless/rndis_wlan.c 2010-12-06 10:45:11.000000000 +0100
@@ -554,7 +554,7 @@ static int rndis_del_key(struct wiphy *w
u8 key_index, bool pairwise, const u8 *mac_addr);
static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
- u8 key_index);
+ u8 key_index, bool unicast, bool multicast);
static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
u8 *mac, struct station_info *sinfo);
@@ -2381,7 +2381,7 @@ static int rndis_del_key(struct wiphy *w
}
static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
- u8 key_index)
+ u8 key_index, bool unicast, bool multicast)
{
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
struct usbnet *usbdev = priv->usbdev;
--- wireless-testing.orig/include/net/cfg80211.h 2010-12-06 10:44:24.000000000 +0100
+++ wireless-testing/include/net/cfg80211.h 2010-12-06 10:45:11.000000000 +0100
@@ -1204,7 +1204,7 @@ struct cfg80211_ops {
u8 key_index, bool pairwise, const u8 *mac_addr);
int (*set_default_key)(struct wiphy *wiphy,
struct net_device *netdev,
- u8 key_index);
+ u8 key_index, bool unicast, bool multicast);
int (*set_default_mgmt_key)(struct wiphy *wiphy,
struct net_device *netdev,
u8 key_index);
@@ -1386,6 +1386,8 @@ struct cfg80211_ops {
* control port protocol ethertype. The device also honours the
* control_port_no_encrypt flag.
* @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN.
+ * @WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS: The device supports separate
+ * unicast and multicast TX keys.
*/
enum wiphy_flags {
WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0),
@@ -1397,6 +1399,7 @@ enum wiphy_flags {
WIPHY_FLAG_4ADDR_STATION = BIT(6),
WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7),
WIPHY_FLAG_IBSS_RSN = BIT(8),
+ WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS= BIT(9),
};
struct mac_address {
--- wireless-testing.orig/net/wireless/nl80211.c 2010-12-06 10:44:24.000000000 +0100
+++ wireless-testing/net/wireless/nl80211.c 2010-12-06 10:45:11.000000000 +0100
@@ -183,6 +183,13 @@ static const struct nla_policy nl80211_k
[NL80211_KEY_TYPE] = { .type = NLA_U32 },
};
+/* policy for the key default flags */
+static const struct nla_policy
+nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
+ [NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG },
+ [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
+};
+
/* ifidx get helper */
static int nl80211_get_ifidx(struct netlink_callback *cb)
{
@@ -313,6 +320,7 @@ struct key_parse {
int idx;
int type;
bool def, defmgmt;
+ bool def_uni, def_multi;
};
static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
@@ -326,6 +334,13 @@ static int nl80211_parse_key_new(struct
k->def = !!tb[NL80211_KEY_DEFAULT];
k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
+ if (k->def) {
+ k->def_uni = true;
+ k->def_multi = true;
+ }
+ if (k->defmgmt)
+ k->def_multi = true;
+
if (tb[NL80211_KEY_IDX])
k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);
@@ -348,6 +363,19 @@ static int nl80211_parse_key_new(struct
return -EINVAL;
}
+ if (tb[NL80211_KEY_DEFAULT_TYPES]) {
+ struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
+ int err = nla_parse_nested(kdt,
+ NUM_NL80211_KEY_DEFAULT_TYPES - 1,
+ tb[NL80211_KEY_DEFAULT_TYPES],
+ nl80211_key_default_policy);
+ if (err)
+ return err;
+
+ k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
+ k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
+ }
+
return 0;
}
@@ -372,12 +400,32 @@ static int nl80211_parse_key_old(struct
k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
+ if (k->def) {
+ k->def_uni = true;
+ k->def_multi = true;
+ }
+ if (k->defmgmt)
+ k->def_multi = true;
+
if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
return -EINVAL;
}
+ if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
+ struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
+ int err = nla_parse_nested(
+ kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1,
+ info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES],
+ nl80211_key_default_policy);
+ if (err)
+ return err;
+
+ k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
+ k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
+ }
+
return 0;
}
@@ -400,6 +448,11 @@ static int nl80211_parse_key(struct genl
if (k->def && k->defmgmt)
return -EINVAL;
+ if (k->defmgmt) {
+ if (k->def_uni || !k->def_multi)
+ return -EINVAL;
+ }
+
if (k->idx != -1) {
if (k->defmgmt) {
if (k->idx < 4 || k->idx > 5)
@@ -449,6 +502,8 @@ nl80211_parse_connkeys(struct cfg80211_r
goto error;
def = 1;
result->def = parse.idx;
+ if (!parse.def_uni || !parse.def_multi)
+ goto error;
} else if (parse.defmgmt)
goto error;
err = cfg80211_validate_key_settings(rdev, &parse.p,
@@ -1574,8 +1629,6 @@ static int nl80211_set_key(struct sk_buf
struct key_parse key;
int err;
struct net_device *dev = info->user_ptr[1];
- int (*func)(struct wiphy *wiphy, struct net_device *netdev,
- u8 key_index);
err = nl80211_parse_key(info, &key);
if (err)
@@ -1588,27 +1641,61 @@ static int nl80211_set_key(struct sk_buf
if (!key.def && !key.defmgmt)
return -EINVAL;
- if (key.def)
- func = rdev->ops->set_default_key;
- else
- func = rdev->ops->set_default_mgmt_key;
+ wdev_lock(dev->ieee80211_ptr);
- if (!func)
- return -EOPNOTSUPP;
+ if (key.def) {
+ if (!rdev->ops->set_default_key) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
- wdev_lock(dev->ieee80211_ptr);
- err = nl80211_key_allowed(dev->ieee80211_ptr);
- if (!err)
- err = func(&rdev->wiphy, dev, key.idx);
+ err = nl80211_key_allowed(dev->ieee80211_ptr);
+ if (err)
+ goto out;
+
+ if (!(rdev->wiphy.flags &
+ WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS)) {
+ if (!key.def_uni || !key.def_multi) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+ }
+
+ err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx,
+ key.def_uni, key.def_multi);
+
+ if (err)
+ goto out;
#ifdef CONFIG_CFG80211_WEXT
- if (!err) {
- if (func == rdev->ops->set_default_key)
- dev->ieee80211_ptr->wext.default_key = key.idx;
- else
- dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
- }
+ dev->ieee80211_ptr->wext.default_key = key.idx;
+#endif
+ } else {
+ if (key.def_uni || !key.def_multi) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (!rdev->ops->set_default_mgmt_key) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ err = nl80211_key_allowed(dev->ieee80211_ptr);
+ if (err)
+ goto out;
+
+ err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
+ dev, key.idx);
+ if (err)
+ goto out;
+
+#ifdef CONFIG_CFG80211_WEXT
+ dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
#endif
+ }
+
+ out:
wdev_unlock(dev->ieee80211_ptr);
return err;
--- wireless-testing.orig/net/mac80211/cfg.c 2010-12-06 10:44:24.000000000 +0100
+++ wireless-testing/net/mac80211/cfg.c 2010-12-06 10:45:11.000000000 +0100
@@ -295,7 +295,8 @@ static int ieee80211_get_key(struct wiph
static int ieee80211_config_default_key(struct wiphy *wiphy,
struct net_device *dev,
- u8 key_idx)
+ u8 key_idx, bool uni,
+ bool multi)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
--- wireless-testing.orig/net/wireless/util.c 2010-12-06 10:44:24.000000000 +0100
+++ wireless-testing/net/wireless/util.c 2010-12-06 10:45:11.000000000 +0100
@@ -689,7 +689,8 @@ void cfg80211_upload_connect_keys(struct
continue;
}
if (wdev->connect_keys->def == i)
- if (rdev->ops->set_default_key(wdev->wiphy, dev, i)) {
+ if (rdev->ops->set_default_key(wdev->wiphy, dev,
+ i, true, true)) {
netdev_err(dev, "failed to set defkey %d\n", i);
continue;
}
--- wireless-testing.orig/net/wireless/wext-compat.c 2010-12-06 10:44:24.000000000 +0100
+++ wireless-testing/net/wireless/wext-compat.c 2010-12-06 10:45:11.000000000 +0100
@@ -548,8 +548,8 @@ static int __cfg80211_set_encryption(str
__cfg80211_leave_ibss(rdev, wdev->netdev, true);
rejoin = true;
}
- err = rdev->ops->set_default_key(&rdev->wiphy,
- dev, idx);
+ err = rdev->ops->set_default_key(&rdev->wiphy, dev,
+ idx, true, true);
}
if (!err) {
wdev->wext.default_key = idx;
@@ -627,8 +627,8 @@ int cfg80211_wext_siwencode(struct net_d
err = 0;
wdev_lock(wdev);
if (wdev->current_bss)
- err = rdev->ops->set_default_key(&rdev->wiphy,
- dev, idx);
+ err = rdev->ops->set_default_key(&rdev->wiphy, dev,
+ idx, true, true);
if (!err)
wdev->wext.default_key = idx;
wdev_unlock(wdev);
next prev parent reply other threads:[~2010-12-09 18:52 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-09 18:48 [PATCH 0/3] key handling for IBSS RSN Johannes Berg
2010-12-09 18:49 ` [PATCH 1/3] mac80211: clean up RX key checks Johannes Berg
2010-12-09 18:49 ` Johannes Berg [this message]
2010-12-09 18:58 ` [PATCH 2/3 v2] cfg80211/nl80211: separate unicast/multicast default TX keys Johannes Berg
2010-12-09 18:49 ` [PATCH 3/3] mac80211: support separate default keys Johannes Berg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20101209185002.763284359@sipsolutions.net \
--to=johannes@sipsolutions.net \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).