Commit e8cbb4cb authored by Johannes Berg's avatar Johannes Berg Committed by David S. Miller

mac80211: support adding/removing keys via cfg80211

This adds the necessary hooks to mac80211 to allow userspace
to edit keys with cfg80211 (through nl80211.)
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 41ade00f
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* This file is GPLv2 as found in COPYING. * This file is GPLv2 as found in COPYING.
*/ */
#include <linux/ieee80211.h>
#include <linux/nl80211.h> #include <linux/nl80211.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <net/net_namespace.h> #include <net/net_namespace.h>
...@@ -99,8 +100,98 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, ...@@ -99,8 +100,98 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
return 0; return 0;
} }
static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
u8 key_idx, u8 *mac_addr,
struct key_params *params)
{
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta = NULL;
enum ieee80211_key_alg alg;
int ret;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
switch (params->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
alg = ALG_WEP;
break;
case WLAN_CIPHER_SUITE_TKIP:
alg = ALG_TKIP;
break;
case WLAN_CIPHER_SUITE_CCMP:
alg = ALG_CCMP;
break;
default:
return -EINVAL;
}
if (mac_addr) {
sta = sta_info_get(sdata->local, mac_addr);
if (!sta)
return -ENOENT;
}
ret = 0;
if (!ieee80211_key_alloc(sdata, sta, alg, key_idx,
params->key_len, params->key))
ret = -ENOMEM;
if (sta)
sta_info_put(sta);
return ret;
}
static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
u8 key_idx, u8 *mac_addr)
{
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
int ret;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (mac_addr) {
sta = sta_info_get(sdata->local, mac_addr);
if (!sta)
return -ENOENT;
ret = 0;
if (sta->key)
ieee80211_key_free(sta->key);
else
ret = -ENOENT;
sta_info_put(sta);
return ret;
}
if (!sdata->keys[key_idx])
return -ENOENT;
ieee80211_key_free(sdata->keys[key_idx]);
return 0;
}
static int ieee80211_config_default_key(struct wiphy *wiphy,
struct net_device *dev,
u8 key_idx)
{
struct ieee80211_sub_if_data *sdata;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
ieee80211_set_default_key(sdata, key_idx);
return 0;
}
struct cfg80211_ops mac80211_config_ops = { struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface, .add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface, .del_virtual_intf = ieee80211_del_iface,
.change_virtual_intf = ieee80211_change_iface, .change_virtual_intf = ieee80211_change_iface,
.add_key = ieee80211_add_key,
.del_key = ieee80211_del_key,
.set_default_key = ieee80211_config_default_key,
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment