aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ieee80211.h2
-rw-r--r--include/linux/nl80211.h11
-rw-r--r--include/net/cfg80211.h28
-rw-r--r--net/wireless/nl80211.c120
4 files changed, 161 insertions, 0 deletions
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index afa8e0ac27a7..d9724a28c0c2 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1266,6 +1266,8 @@ enum ieee80211_sa_query_action {
1266 1266
1267#define WLAN_MAX_KEY_LEN 32 1267#define WLAN_MAX_KEY_LEN 32
1268 1268
1269#define WLAN_PMKID_LEN 16
1270
1269/** 1271/**
1270 * ieee80211_get_qos_ctl - get pointer to qos control bytes 1272 * ieee80211_get_qos_ctl - get pointer to qos control bytes
1271 * @hdr: the frame 1273 * @hdr: the frame
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 45db17f81aa3..da8ea2e19273 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -349,6 +349,10 @@ enum nl80211_commands {
349 NL80211_CMD_GET_SURVEY, 349 NL80211_CMD_GET_SURVEY,
350 NL80211_CMD_NEW_SURVEY_RESULTS, 350 NL80211_CMD_NEW_SURVEY_RESULTS,
351 351
352 NL80211_CMD_SET_PMKSA,
353 NL80211_CMD_DEL_PMKSA,
354 NL80211_CMD_FLUSH_PMKSA,
355
352 /* add new commands above here */ 356 /* add new commands above here */
353 357
354 /* used to define NL80211_CMD_MAX below */ 358 /* used to define NL80211_CMD_MAX below */
@@ -598,6 +602,10 @@ enum nl80211_commands {
598 * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute 602 * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute
599 * containing info as possible, see &enum survey_info. 603 * containing info as possible, see &enum survey_info.
600 * 604 *
605 * @NL80211_ATTR_PMKID: PMK material for PMKSA caching.
606 * @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can
607 * cache, a wiphy attribute.
608 *
601 * @NL80211_ATTR_MAX: highest attribute number currently defined 609 * @NL80211_ATTR_MAX: highest attribute number currently defined
602 * @__NL80211_ATTR_AFTER_LAST: internal use 610 * @__NL80211_ATTR_AFTER_LAST: internal use
603 */ 611 */
@@ -732,6 +740,9 @@ enum nl80211_attrs {
732 740
733 NL80211_ATTR_SURVEY_INFO, 741 NL80211_ATTR_SURVEY_INFO,
734 742
743 NL80211_ATTR_PMKID,
744 NL80211_ATTR_MAX_NUM_PMKIDS,
745
735 /* add attributes here, update the policy in nl80211.c */ 746 /* add attributes here, update the policy in nl80211.c */
736 747
737 __NL80211_ATTR_AFTER_LAST, 748 __NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a6492e9bca97..0884b9a0f778 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -871,6 +871,19 @@ struct cfg80211_bitrate_mask {
871 u32 fixed; /* fixed bitrate, 0 == not fixed */ 871 u32 fixed; /* fixed bitrate, 0 == not fixed */
872 u32 maxrate; /* in kbps, 0 == no limit */ 872 u32 maxrate; /* in kbps, 0 == no limit */
873}; 873};
874/**
875 * struct cfg80211_pmksa - PMK Security Association
876 *
877 * This structure is passed to the set/del_pmksa() method for PMKSA
878 * caching.
879 *
880 * @bssid: The AP's BSSID.
881 * @pmkid: The PMK material itself.
882 */
883struct cfg80211_pmksa {
884 u8 *bssid;
885 u8 *pmkid;
886};
874 887
875/** 888/**
876 * struct cfg80211_ops - backend description for wireless configuration 889 * struct cfg80211_ops - backend description for wireless configuration
@@ -976,6 +989,13 @@ struct cfg80211_bitrate_mask {
976 * @dump_survey: get site survey information. 989 * @dump_survey: get site survey information.
977 * 990 *
978 * @testmode_cmd: run a test mode command 991 * @testmode_cmd: run a test mode command
992 *
993 * @set_pmksa: Cache a PMKID for a BSSID. This is mostly useful for fullmac
994 * devices running firmwares capable of generating the (re) association
995 * RSN IE. It allows for faster roaming between WPA2 BSSIDs.
996 * @del_pmksa: Delete a cached PMKID.
997 * @flush_pmksa: Flush all cached PMKIDs.
998 *
979 */ 999 */
980struct cfg80211_ops { 1000struct cfg80211_ops {
981 int (*suspend)(struct wiphy *wiphy); 1001 int (*suspend)(struct wiphy *wiphy);
@@ -1097,6 +1117,12 @@ struct cfg80211_ops {
1097 int (*dump_survey)(struct wiphy *wiphy, struct net_device *netdev, 1117 int (*dump_survey)(struct wiphy *wiphy, struct net_device *netdev,
1098 int idx, struct survey_info *info); 1118 int idx, struct survey_info *info);
1099 1119
1120 int (*set_pmksa)(struct wiphy *wiphy, struct net_device *netdev,
1121 struct cfg80211_pmksa *pmksa);
1122 int (*del_pmksa)(struct wiphy *wiphy, struct net_device *netdev,
1123 struct cfg80211_pmksa *pmksa);
1124 int (*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev);
1125
1100 /* some temporary stuff to finish wext */ 1126 /* some temporary stuff to finish wext */
1101 int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, 1127 int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
1102 bool enabled, int timeout); 1128 bool enabled, int timeout);
@@ -1195,6 +1221,8 @@ struct wiphy {
1195 char fw_version[ETHTOOL_BUSINFO_LEN]; 1221 char fw_version[ETHTOOL_BUSINFO_LEN];
1196 u32 hw_version; 1222 u32 hw_version;
1197 1223
1224 u8 max_num_pmkids;
1225
1198 /* If multiple wiphys are registered and you're handed e.g. 1226 /* If multiple wiphys are registered and you're handed e.g.
1199 * a regular netdev with assigned ieee80211_ptr, you won't 1227 * a regular netdev with assigned ieee80211_ptr, you won't
1200 * know whether it points to a wiphy your driver has registered 1228 * know whether it points to a wiphy your driver has registered
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 149539ade15e..a6028433e3a0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -139,6 +139,8 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
139 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, 139 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
140 [NL80211_ATTR_PID] = { .type = NLA_U32 }, 140 [NL80211_ATTR_PID] = { .type = NLA_U32 },
141 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, 141 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
142 [NL80211_ATTR_PMKID] = { .type = NLA_BINARY,
143 .len = WLAN_PMKID_LEN },
142}; 144};
143 145
144/* policy for the attributes */ 146/* policy for the attributes */
@@ -450,6 +452,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
450 sizeof(u32) * dev->wiphy.n_cipher_suites, 452 sizeof(u32) * dev->wiphy.n_cipher_suites,
451 dev->wiphy.cipher_suites); 453 dev->wiphy.cipher_suites);
452 454
455 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
456 dev->wiphy.max_num_pmkids);
457
453 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); 458 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
454 if (!nl_modes) 459 if (!nl_modes)
455 goto nla_put_failure; 460 goto nla_put_failure;
@@ -561,6 +566,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
561 CMD(deauth, DEAUTHENTICATE); 566 CMD(deauth, DEAUTHENTICATE);
562 CMD(disassoc, DISASSOCIATE); 567 CMD(disassoc, DISASSOCIATE);
563 CMD(join_ibss, JOIN_IBSS); 568 CMD(join_ibss, JOIN_IBSS);
569 CMD(set_pmksa, SET_PMKSA);
570 CMD(del_pmksa, DEL_PMKSA);
571 CMD(flush_pmksa, FLUSH_PMKSA);
564 if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { 572 if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
565 i++; 573 i++;
566 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); 574 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
@@ -4221,6 +4229,99 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
4221 return err; 4229 return err;
4222} 4230}
4223 4231
4232static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
4233{
4234 struct cfg80211_registered_device *rdev;
4235 int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
4236 struct cfg80211_pmksa *pmksa) = NULL;
4237 int err;
4238 struct net_device *dev;
4239 struct cfg80211_pmksa pmksa;
4240
4241 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
4242
4243 if (!info->attrs[NL80211_ATTR_MAC])
4244 return -EINVAL;
4245
4246 if (!info->attrs[NL80211_ATTR_PMKID])
4247 return -EINVAL;
4248
4249 rtnl_lock();
4250
4251 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4252 if (err)
4253 goto out_rtnl;
4254
4255 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
4256 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
4257
4258 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
4259 err = -EOPNOTSUPP;
4260 goto out;
4261 }
4262
4263 switch (info->genlhdr->cmd) {
4264 case NL80211_CMD_SET_PMKSA:
4265 rdev_ops = rdev->ops->set_pmksa;
4266 break;
4267 case NL80211_CMD_DEL_PMKSA:
4268 rdev_ops = rdev->ops->del_pmksa;
4269 break;
4270 default:
4271 WARN_ON(1);
4272 break;
4273 }
4274
4275 if (!rdev_ops) {
4276 err = -EOPNOTSUPP;
4277 goto out;
4278 }
4279
4280 err = rdev_ops(&rdev->wiphy, dev, &pmksa);
4281
4282 out:
4283 cfg80211_unlock_rdev(rdev);
4284 dev_put(dev);
4285 out_rtnl:
4286 rtnl_unlock();
4287
4288 return err;
4289}
4290
4291static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
4292{
4293 struct cfg80211_registered_device *rdev;
4294 int err;
4295 struct net_device *dev;
4296
4297 rtnl_lock();
4298
4299 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4300 if (err)
4301 goto out_rtnl;
4302
4303 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
4304 err = -EOPNOTSUPP;
4305 goto out;
4306 }
4307
4308 if (!rdev->ops->flush_pmksa) {
4309 err = -EOPNOTSUPP;
4310 goto out;
4311 }
4312
4313 err = rdev->ops->flush_pmksa(&rdev->wiphy, dev);
4314
4315 out:
4316 cfg80211_unlock_rdev(rdev);
4317 dev_put(dev);
4318 out_rtnl:
4319 rtnl_unlock();
4320
4321 return err;
4322
4323}
4324
4224static struct genl_ops nl80211_ops[] = { 4325static struct genl_ops nl80211_ops[] = {
4225 { 4326 {
4226 .cmd = NL80211_CMD_GET_WIPHY, 4327 .cmd = NL80211_CMD_GET_WIPHY,
@@ -4465,6 +4566,25 @@ static struct genl_ops nl80211_ops[] = {
4465 .policy = nl80211_policy, 4566 .policy = nl80211_policy,
4466 .dumpit = nl80211_dump_survey, 4567 .dumpit = nl80211_dump_survey,
4467 }, 4568 },
4569 {
4570 .cmd = NL80211_CMD_SET_PMKSA,
4571 .doit = nl80211_setdel_pmksa,
4572 .policy = nl80211_policy,
4573 .flags = GENL_ADMIN_PERM,
4574 },
4575 {
4576 .cmd = NL80211_CMD_DEL_PMKSA,
4577 .doit = nl80211_setdel_pmksa,
4578 .policy = nl80211_policy,
4579 .flags = GENL_ADMIN_PERM,
4580 },
4581 {
4582 .cmd = NL80211_CMD_FLUSH_PMKSA,
4583 .doit = nl80211_flush_pmksa,
4584 .policy = nl80211_policy,
4585 .flags = GENL_ADMIN_PERM,
4586 },
4587
4468}; 4588};
4469static struct genl_multicast_group nl80211_mlme_mcgrp = { 4589static struct genl_multicast_group nl80211_mlme_mcgrp = {
4470 .name = "mlme", 4590 .name = "mlme",