summaryrefslogtreecommitdiff
path: root/net/mac80211/cfg.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/mac80211/cfg.c
parent0c1aa495961f03c964b3287cf5800217cf6f2cee (diff)
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/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 72c106915433..d1ac3ab2c515 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1175,6 +1175,87 @@ static int ieee80211_set_channel(struct wiphy *wiphy,
return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
}
+static int set_mgmt_extra_ie_sta(struct ieee80211_if_sta *ifsta, u8 subtype,
+ u8 *ies, size_t ies_len)
+{
+ switch (subtype) {
+ case IEEE80211_STYPE_PROBE_REQ >> 4:
+ kfree(ifsta->ie_probereq);
+ ifsta->ie_probereq = ies;
+ ifsta->ie_probereq_len = ies_len;
+ return 0;
+ case IEEE80211_STYPE_PROBE_RESP >> 4:
+ kfree(ifsta->ie_proberesp);
+ ifsta->ie_proberesp = ies;
+ ifsta->ie_proberesp_len = ies_len;
+ return 0;
+ case IEEE80211_STYPE_AUTH >> 4:
+ kfree(ifsta->ie_auth);
+ ifsta->ie_auth = ies;
+ ifsta->ie_auth_len = ies_len;
+ return 0;
+ case IEEE80211_STYPE_ASSOC_REQ >> 4:
+ kfree(ifsta->ie_assocreq);
+ ifsta->ie_assocreq = ies;
+ ifsta->ie_assocreq_len = ies_len;
+ return 0;
+ case IEEE80211_STYPE_REASSOC_REQ >> 4:
+ kfree(ifsta->ie_reassocreq);
+ ifsta->ie_reassocreq = ies;
+ ifsta->ie_reassocreq_len = ies_len;
+ return 0;
+ case IEEE80211_STYPE_DEAUTH >> 4:
+ kfree(ifsta->ie_deauth);
+ ifsta->ie_deauth = ies;
+ ifsta->ie_deauth_len = ies_len;
+ return 0;
+ case IEEE80211_STYPE_DISASSOC >> 4:
+ kfree(ifsta->ie_disassoc);
+ ifsta->ie_disassoc = ies;
+ ifsta->ie_disassoc_len = ies_len;
+ return 0;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static int ieee80211_set_mgmt_extra_ie(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct mgmt_extra_ie_params *params)
+{
+ struct ieee80211_sub_if_data *sdata;
+ u8 *ies;
+ size_t ies_len;
+ int ret = -EOPNOTSUPP;
+
+ if (params->ies) {
+ ies = kmemdup(params->ies, params->ies_len, GFP_KERNEL);
+ if (ies == NULL)
+ return -ENOMEM;
+ ies_len = params->ies_len;
+ } else {
+ ies = NULL;
+ ies_len = 0;
+ }
+
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
+ ret = set_mgmt_extra_ie_sta(&sdata->u.sta, params->subtype,
+ ies, ies_len);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ if (ret)
+ kfree(ies);
+ return ret;
+}
+
struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -1204,4 +1285,5 @@ struct cfg80211_ops mac80211_config_ops = {
.change_bss = ieee80211_change_bss,
.set_txq_params = ieee80211_set_txq_params,
.set_channel = ieee80211_set_channel,
+ .set_mgmt_extra_ie = ieee80211_set_mgmt_extra_ie,
};