diff options
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a8eda12b46a8..68b6708b996f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -891,6 +891,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
891 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) | 891 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) |
892 | CMD(sched_scan_start, START_SCHED_SCAN); | 892 | CMD(sched_scan_start, START_SCHED_SCAN); |
893 | CMD(probe_client, PROBE_CLIENT); | 893 | CMD(probe_client, PROBE_CLIENT); |
894 | if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) { | ||
895 | i++; | ||
896 | NLA_PUT_U32(msg, i, NL80211_CMD_REGISTER_BEACONS); | ||
897 | } | ||
894 | 898 | ||
895 | #undef CMD | 899 | #undef CMD |
896 | 900 | ||
@@ -5907,6 +5911,21 @@ static int nl80211_probe_client(struct sk_buff *skb, | |||
5907 | return err; | 5911 | return err; |
5908 | } | 5912 | } |
5909 | 5913 | ||
5914 | static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info) | ||
5915 | { | ||
5916 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
5917 | |||
5918 | if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS)) | ||
5919 | return -EOPNOTSUPP; | ||
5920 | |||
5921 | if (rdev->ap_beacons_nlpid) | ||
5922 | return -EBUSY; | ||
5923 | |||
5924 | rdev->ap_beacons_nlpid = info->snd_pid; | ||
5925 | |||
5926 | return 0; | ||
5927 | } | ||
5928 | |||
5910 | #define NL80211_FLAG_NEED_WIPHY 0x01 | 5929 | #define NL80211_FLAG_NEED_WIPHY 0x01 |
5911 | #define NL80211_FLAG_NEED_NETDEV 0x02 | 5930 | #define NL80211_FLAG_NEED_NETDEV 0x02 |
5912 | #define NL80211_FLAG_NEED_RTNL 0x04 | 5931 | #define NL80211_FLAG_NEED_RTNL 0x04 |
@@ -6478,6 +6497,14 @@ static struct genl_ops nl80211_ops[] = { | |||
6478 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6497 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
6479 | NL80211_FLAG_NEED_RTNL, | 6498 | NL80211_FLAG_NEED_RTNL, |
6480 | }, | 6499 | }, |
6500 | { | ||
6501 | .cmd = NL80211_CMD_REGISTER_BEACONS, | ||
6502 | .doit = nl80211_register_beacons, | ||
6503 | .policy = nl80211_policy, | ||
6504 | .flags = GENL_ADMIN_PERM, | ||
6505 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | ||
6506 | NL80211_FLAG_NEED_RTNL, | ||
6507 | }, | ||
6481 | }; | 6508 | }; |
6482 | 6509 | ||
6483 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 6510 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
@@ -7582,6 +7609,44 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr, | |||
7582 | } | 7609 | } |
7583 | EXPORT_SYMBOL(cfg80211_probe_status); | 7610 | EXPORT_SYMBOL(cfg80211_probe_status); |
7584 | 7611 | ||
7612 | void cfg80211_report_obss_beacon(struct wiphy *wiphy, | ||
7613 | const u8 *frame, size_t len, | ||
7614 | int freq, gfp_t gfp) | ||
7615 | { | ||
7616 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
7617 | struct sk_buff *msg; | ||
7618 | void *hdr; | ||
7619 | u32 nlpid = ACCESS_ONCE(rdev->ap_beacons_nlpid); | ||
7620 | |||
7621 | if (!nlpid) | ||
7622 | return; | ||
7623 | |||
7624 | msg = nlmsg_new(len + 100, gfp); | ||
7625 | if (!msg) | ||
7626 | return; | ||
7627 | |||
7628 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME); | ||
7629 | if (!hdr) { | ||
7630 | nlmsg_free(msg); | ||
7631 | return; | ||
7632 | } | ||
7633 | |||
7634 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | ||
7635 | if (freq) | ||
7636 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); | ||
7637 | NLA_PUT(msg, NL80211_ATTR_FRAME, len, frame); | ||
7638 | |||
7639 | genlmsg_end(msg, hdr); | ||
7640 | |||
7641 | genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlpid); | ||
7642 | return; | ||
7643 | |||
7644 | nla_put_failure: | ||
7645 | genlmsg_cancel(msg, hdr); | ||
7646 | nlmsg_free(msg); | ||
7647 | } | ||
7648 | EXPORT_SYMBOL(cfg80211_report_obss_beacon); | ||
7649 | |||
7585 | static int nl80211_netlink_notify(struct notifier_block * nb, | 7650 | static int nl80211_netlink_notify(struct notifier_block * nb, |
7586 | unsigned long state, | 7651 | unsigned long state, |
7587 | void *_notify) | 7652 | void *_notify) |
@@ -7595,9 +7660,12 @@ static int nl80211_netlink_notify(struct notifier_block * nb, | |||
7595 | 7660 | ||
7596 | rcu_read_lock(); | 7661 | rcu_read_lock(); |
7597 | 7662 | ||
7598 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) | 7663 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) { |
7599 | list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) | 7664 | list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) |
7600 | cfg80211_mlme_unregister_socket(wdev, notify->pid); | 7665 | cfg80211_mlme_unregister_socket(wdev, notify->pid); |
7666 | if (rdev->ap_beacons_nlpid == notify->pid) | ||
7667 | rdev->ap_beacons_nlpid = 0; | ||
7668 | } | ||
7601 | 7669 | ||
7602 | rcu_read_unlock(); | 7670 | rcu_read_unlock(); |
7603 | 7671 | ||