aboutsummaryrefslogtreecommitdiff
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2009-01-13 16:03:29 +0200
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:00:35 -0500
commit9aed3cc124343d92be6697e9af3928bdfe8eb03e (patch)
tree6a49a68422656790f944f37e3f34379b753d1dab /net/wireless/nl80211.c
parent0c1aa495961f03c964b3287cf5800217cf6f2cee (diff)
downloadlinux-9aed3cc124343d92be6697e9af3928bdfe8eb03e.tar.gz
nl80211: New command for adding extra IE(s) into management frames
A new nl80211 command, NL80211_CMD_SET_MGMT_EXTRA_IE, can be used to add arbitrary IE data into the end of management frames. The interface allows extra IEs to be configured for each management frame subtype, but only some of them (ProbeReq, ProbeResp, Auth, (Re)AssocReq, Deauth, Disassoc) are currently accepted in mac80211 implementation. This makes it easier to implement IEEE 802.11 extensions like WPS and FT that add IE(s) into some management frames. In addition, this can be useful for testing and experimentation purposes. Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 123d3b160fa..09a5d0f1d6d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -105,6 +105,10 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
[NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY,
.len = NL80211_HT_CAPABILITY_LEN },
+
+ [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
+ [NL80211_ATTR_IE] = { .type = NLA_BINARY,
+ .len = IEEE80211_MAX_DATA_LEN },
};
/* message building helper */
@@ -2149,6 +2153,43 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
+static int nl80211_set_mgmt_extra_ie(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *drv;
+ int err;
+ struct net_device *dev;
+ struct mgmt_extra_ie_params params;
+
+ memset(&params, 0, sizeof(params));
+
+ if (!info->attrs[NL80211_ATTR_MGMT_SUBTYPE])
+ return -EINVAL;
+ params.subtype = nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
+ if (params.subtype > 15)
+ return -EINVAL; /* FC Subtype field is 4 bits (0..15) */
+
+ if (info->attrs[NL80211_ATTR_IE]) {
+ params.ies = nla_data(info->attrs[NL80211_ATTR_IE]);
+ params.ies_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+ }
+
+ err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ if (err)
+ return err;
+
+ if (drv->ops->set_mgmt_extra_ie) {
+ rtnl_lock();
+ err = drv->ops->set_mgmt_extra_ie(&drv->wiphy, dev, &params);
+ rtnl_unlock();
+ } else
+ err = -EOPNOTSUPP;
+
+ cfg80211_put_dev(drv);
+ dev_put(dev);
+ return err;
+}
+
static struct genl_ops nl80211_ops[] = {
{
.cmd = NL80211_CMD_GET_WIPHY,
@@ -2310,6 +2351,12 @@ static struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
},
+ {
+ .cmd = NL80211_CMD_SET_MGMT_EXTRA_IE,
+ .doit = nl80211_set_mgmt_extra_ie,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
};
/* multicast groups */