aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2009-11-24 17:59:15 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-11-28 15:05:05 -0500
commit67fbb16be69d138a3b6645ec5395b487cb915c58 (patch)
tree8dde9e1c42db515a5703e3bc142279cf2280c9ae /net/wireless/nl80211.c
parenta830df0714117574fd0d5fe98477059b3e9fd5bf (diff)
nl80211: PMKSA caching support
This is an interface to set, delete and flush PMKIDs through nl80211. Main users would be fullmac devices which firmwares are capable of generating the RSN IEs for the re-association requests, e.g. iwmc3200wifi. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c120
1 files changed, 120 insertions, 0 deletions
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",