aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-04-18 19:02:55 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-04-18 19:02:55 -0400
commit97990a060e6757f48b931a3946b17c1c4362c3fb (patch)
tree56a673ad85a06fdca40b9e58c1eff54551b3c529 /net/wireless
parent1b737f88dc1b05cf571e96d42f748aaff6df1eb5 (diff)
nl80211: allow using wdev identifiers to get scan results
Most dump callbacks, including the scan results one, use the netdev to identify what to do, which is incorrect for the P2P_DEVICE support, it needs to be able to get the scan result from the wdev. Change all dumps to unify the code, but ones other than scan don't really support being executed on a wdev that has no netdev. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c166
1 files changed, 91 insertions, 75 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f924d45af1b8..8c8a57937b22 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -447,62 +447,69 @@ nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
447 [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 }, 447 [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
448}; 448};
449 449
450/* ifidx get helper */ 450static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
451static int nl80211_get_ifidx(struct netlink_callback *cb) 451 struct netlink_callback *cb,
452 struct cfg80211_registered_device **rdev,
453 struct wireless_dev **wdev)
452{ 454{
453 int res; 455 int err;
454
455 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
456 nl80211_fam.attrbuf, nl80211_fam.maxattr,
457 nl80211_policy);
458 if (res)
459 return res;
460
461 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
462 return -EINVAL;
463 456
464 res = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]); 457 rtnl_lock();
465 if (!res) 458 mutex_lock(&cfg80211_mutex);
466 return -EINVAL;
467 return res;
468}
469 459
470static int nl80211_prepare_netdev_dump(struct sk_buff *skb, 460 if (!cb->args[0]) {
471 struct netlink_callback *cb, 461 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
472 struct cfg80211_registered_device **rdev, 462 nl80211_fam.attrbuf, nl80211_fam.maxattr,
473 struct net_device **dev) 463 nl80211_policy);
474{ 464 if (err)
475 int ifidx = cb->args[0]; 465 goto out_unlock;
476 int err;
477 466
478 if (!ifidx) 467 *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
479 ifidx = nl80211_get_ifidx(cb); 468 nl80211_fam.attrbuf);
480 if (ifidx < 0) 469 if (IS_ERR(*wdev)) {
481 return ifidx; 470 err = PTR_ERR(*wdev);
471 goto out_unlock;
472 }
473 *rdev = wiphy_to_dev((*wdev)->wiphy);
474 cb->args[0] = (*rdev)->wiphy_idx;
475 cb->args[1] = (*wdev)->identifier;
476 } else {
477 struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0]);
478 struct wireless_dev *tmp;
482 479
483 cb->args[0] = ifidx; 480 if (!wiphy) {
481 err = -ENODEV;
482 goto out_unlock;
483 }
484 *rdev = wiphy_to_dev(wiphy);
485 *wdev = NULL;
484 486
485 rtnl_lock(); 487 mutex_lock(&(*rdev)->devlist_mtx);
488 list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
489 if (tmp->identifier == cb->args[1]) {
490 *wdev = tmp;
491 break;
492 }
493 }
494 mutex_unlock(&(*rdev)->devlist_mtx);
486 495
487 *dev = __dev_get_by_index(sock_net(skb->sk), ifidx); 496 if (!*wdev) {
488 if (!*dev) { 497 err = -ENODEV;
489 err = -ENODEV; 498 goto out_unlock;
490 goto out_rtnl; 499 }
491 } 500 }
492 501
493 *rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx); 502 cfg80211_lock_rdev(*rdev);
494 if (IS_ERR(*rdev)) {
495 err = PTR_ERR(*rdev);
496 goto out_rtnl;
497 }
498 503
504 mutex_unlock(&cfg80211_mutex);
499 return 0; 505 return 0;
500 out_rtnl: 506 out_unlock:
507 mutex_unlock(&cfg80211_mutex);
501 rtnl_unlock(); 508 rtnl_unlock();
502 return err; 509 return err;
503} 510}
504 511
505static void nl80211_finish_netdev_dump(struct cfg80211_registered_device *rdev) 512static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
506{ 513{
507 cfg80211_unlock_rdev(rdev); 514 cfg80211_unlock_rdev(rdev);
508 rtnl_unlock(); 515 rtnl_unlock();
@@ -3525,15 +3532,20 @@ static int nl80211_dump_station(struct sk_buff *skb,
3525{ 3532{
3526 struct station_info sinfo; 3533 struct station_info sinfo;
3527 struct cfg80211_registered_device *dev; 3534 struct cfg80211_registered_device *dev;
3528 struct net_device *netdev; 3535 struct wireless_dev *wdev;
3529 u8 mac_addr[ETH_ALEN]; 3536 u8 mac_addr[ETH_ALEN];
3530 int sta_idx = cb->args[1]; 3537 int sta_idx = cb->args[2];
3531 int err; 3538 int err;
3532 3539
3533 err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev); 3540 err = nl80211_prepare_wdev_dump(skb, cb, &dev, &wdev);
3534 if (err) 3541 if (err)
3535 return err; 3542 return err;
3536 3543
3544 if (!wdev->netdev) {
3545 err = -EINVAL;
3546 goto out_err;
3547 }
3548
3537 if (!dev->ops->dump_station) { 3549 if (!dev->ops->dump_station) {
3538 err = -EOPNOTSUPP; 3550 err = -EOPNOTSUPP;
3539 goto out_err; 3551 goto out_err;
@@ -3541,7 +3553,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
3541 3553
3542 while (1) { 3554 while (1) {
3543 memset(&sinfo, 0, sizeof(sinfo)); 3555 memset(&sinfo, 0, sizeof(sinfo));
3544 err = rdev_dump_station(dev, netdev, sta_idx, 3556 err = rdev_dump_station(dev, wdev->netdev, sta_idx,
3545 mac_addr, &sinfo); 3557 mac_addr, &sinfo);
3546 if (err == -ENOENT) 3558 if (err == -ENOENT)
3547 break; 3559 break;
@@ -3551,7 +3563,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
3551 if (nl80211_send_station(skb, 3563 if (nl80211_send_station(skb,
3552 NETLINK_CB(cb->skb).portid, 3564 NETLINK_CB(cb->skb).portid,
3553 cb->nlh->nlmsg_seq, NLM_F_MULTI, 3565 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3554 dev, netdev, mac_addr, 3566 dev, wdev->netdev, mac_addr,
3555 &sinfo) < 0) 3567 &sinfo) < 0)
3556 goto out; 3568 goto out;
3557 3569
@@ -3560,10 +3572,10 @@ static int nl80211_dump_station(struct sk_buff *skb,
3560 3572
3561 3573
3562 out: 3574 out:
3563 cb->args[1] = sta_idx; 3575 cb->args[2] = sta_idx;
3564 err = skb->len; 3576 err = skb->len;
3565 out_err: 3577 out_err:
3566 nl80211_finish_netdev_dump(dev); 3578 nl80211_finish_wdev_dump(dev);
3567 3579
3568 return err; 3580 return err;
3569} 3581}
@@ -4167,13 +4179,13 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
4167{ 4179{
4168 struct mpath_info pinfo; 4180 struct mpath_info pinfo;
4169 struct cfg80211_registered_device *dev; 4181 struct cfg80211_registered_device *dev;
4170 struct net_device *netdev; 4182 struct wireless_dev *wdev;
4171 u8 dst[ETH_ALEN]; 4183 u8 dst[ETH_ALEN];
4172 u8 next_hop[ETH_ALEN]; 4184 u8 next_hop[ETH_ALEN];
4173 int path_idx = cb->args[1]; 4185 int path_idx = cb->args[2];
4174 int err; 4186 int err;
4175 4187
4176 err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev); 4188 err = nl80211_prepare_wdev_dump(skb, cb, &dev, &wdev);
4177 if (err) 4189 if (err)
4178 return err; 4190 return err;
4179 4191
@@ -4182,14 +4194,14 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
4182 goto out_err; 4194 goto out_err;
4183 } 4195 }
4184 4196
4185 if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { 4197 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
4186 err = -EOPNOTSUPP; 4198 err = -EOPNOTSUPP;
4187 goto out_err; 4199 goto out_err;
4188 } 4200 }
4189 4201
4190 while (1) { 4202 while (1) {
4191 err = rdev_dump_mpath(dev, netdev, path_idx, dst, next_hop, 4203 err = rdev_dump_mpath(dev, wdev->netdev, path_idx, dst,
4192 &pinfo); 4204 next_hop, &pinfo);
4193 if (err == -ENOENT) 4205 if (err == -ENOENT)
4194 break; 4206 break;
4195 if (err) 4207 if (err)
@@ -4197,7 +4209,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
4197 4209
4198 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid, 4210 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
4199 cb->nlh->nlmsg_seq, NLM_F_MULTI, 4211 cb->nlh->nlmsg_seq, NLM_F_MULTI,
4200 netdev, dst, next_hop, 4212 wdev->netdev, dst, next_hop,
4201 &pinfo) < 0) 4213 &pinfo) < 0)
4202 goto out; 4214 goto out;
4203 4215
@@ -4206,10 +4218,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
4206 4218
4207 4219
4208 out: 4220 out:
4209 cb->args[1] = path_idx; 4221 cb->args[2] = path_idx;
4210 err = skb->len; 4222 err = skb->len;
4211 out_err: 4223 out_err:
4212 nl80211_finish_netdev_dump(dev); 4224 nl80211_finish_wdev_dump(dev);
4213 return err; 4225 return err;
4214} 4226}
4215 4227
@@ -5552,9 +5564,13 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
5552 5564
5553 genl_dump_check_consistent(cb, hdr, &nl80211_fam); 5565 genl_dump_check_consistent(cb, hdr, &nl80211_fam);
5554 5566
5555 if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation) || 5567 if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation))
5568 goto nla_put_failure;
5569 if (wdev->netdev &&
5556 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex)) 5570 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
5557 goto nla_put_failure; 5571 goto nla_put_failure;
5572 if (nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
5573 goto nla_put_failure;
5558 5574
5559 bss = nla_nest_start(msg, NL80211_ATTR_BSS); 5575 bss = nla_nest_start(msg, NL80211_ATTR_BSS);
5560 if (!bss) 5576 if (!bss)
@@ -5634,22 +5650,18 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
5634 return -EMSGSIZE; 5650 return -EMSGSIZE;
5635} 5651}
5636 5652
5637static int nl80211_dump_scan(struct sk_buff *skb, 5653static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
5638 struct netlink_callback *cb)
5639{ 5654{
5640 struct cfg80211_registered_device *rdev; 5655 struct cfg80211_registered_device *rdev;
5641 struct net_device *dev;
5642 struct cfg80211_internal_bss *scan; 5656 struct cfg80211_internal_bss *scan;
5643 struct wireless_dev *wdev; 5657 struct wireless_dev *wdev;
5644 int start = cb->args[1], idx = 0; 5658 int start = cb->args[2], idx = 0;
5645 int err; 5659 int err;
5646 5660
5647 err = nl80211_prepare_netdev_dump(skb, cb, &rdev, &dev); 5661 err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
5648 if (err) 5662 if (err)
5649 return err; 5663 return err;
5650 5664
5651 wdev = dev->ieee80211_ptr;
5652
5653 wdev_lock(wdev); 5665 wdev_lock(wdev);
5654 spin_lock_bh(&rdev->bss_lock); 5666 spin_lock_bh(&rdev->bss_lock);
5655 cfg80211_bss_expire(rdev); 5667 cfg80211_bss_expire(rdev);
@@ -5670,8 +5682,8 @@ static int nl80211_dump_scan(struct sk_buff *skb,
5670 spin_unlock_bh(&rdev->bss_lock); 5682 spin_unlock_bh(&rdev->bss_lock);
5671 wdev_unlock(wdev); 5683 wdev_unlock(wdev);
5672 5684
5673 cb->args[1] = idx; 5685 cb->args[2] = idx;
5674 nl80211_finish_netdev_dump(rdev); 5686 nl80211_finish_wdev_dump(rdev);
5675 5687
5676 return skb->len; 5688 return skb->len;
5677} 5689}
@@ -5740,14 +5752,19 @@ static int nl80211_dump_survey(struct sk_buff *skb,
5740{ 5752{
5741 struct survey_info survey; 5753 struct survey_info survey;
5742 struct cfg80211_registered_device *dev; 5754 struct cfg80211_registered_device *dev;
5743 struct net_device *netdev; 5755 struct wireless_dev *wdev;
5744 int survey_idx = cb->args[1]; 5756 int survey_idx = cb->args[2];
5745 int res; 5757 int res;
5746 5758
5747 res = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev); 5759 res = nl80211_prepare_wdev_dump(skb, cb, &dev, &wdev);
5748 if (res) 5760 if (res)
5749 return res; 5761 return res;
5750 5762
5763 if (!wdev->netdev) {
5764 res = -EINVAL;
5765 goto out_err;
5766 }
5767
5751 if (!dev->ops->dump_survey) { 5768 if (!dev->ops->dump_survey) {
5752 res = -EOPNOTSUPP; 5769 res = -EOPNOTSUPP;
5753 goto out_err; 5770 goto out_err;
@@ -5756,7 +5773,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
5756 while (1) { 5773 while (1) {
5757 struct ieee80211_channel *chan; 5774 struct ieee80211_channel *chan;
5758 5775
5759 res = rdev_dump_survey(dev, netdev, survey_idx, &survey); 5776 res = rdev_dump_survey(dev, wdev->netdev, survey_idx, &survey);
5760 if (res == -ENOENT) 5777 if (res == -ENOENT)
5761 break; 5778 break;
5762 if (res) 5779 if (res)
@@ -5778,17 +5795,16 @@ static int nl80211_dump_survey(struct sk_buff *skb,
5778 if (nl80211_send_survey(skb, 5795 if (nl80211_send_survey(skb,
5779 NETLINK_CB(cb->skb).portid, 5796 NETLINK_CB(cb->skb).portid,
5780 cb->nlh->nlmsg_seq, NLM_F_MULTI, 5797 cb->nlh->nlmsg_seq, NLM_F_MULTI,
5781 netdev, 5798 wdev->netdev, &survey) < 0)
5782 &survey) < 0)
5783 goto out; 5799 goto out;
5784 survey_idx++; 5800 survey_idx++;
5785 } 5801 }
5786 5802
5787 out: 5803 out:
5788 cb->args[1] = survey_idx; 5804 cb->args[2] = survey_idx;
5789 res = skb->len; 5805 res = skb->len;
5790 out_err: 5806 out_err:
5791 nl80211_finish_netdev_dump(dev); 5807 nl80211_finish_wdev_dump(dev);
5792 return res; 5808 return res;
5793} 5809}
5794 5810