aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-11-04 06:18:17 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-11-09 16:13:51 -0500
commit5e760230e42cf759bd923457ca2753aacf2e656e (patch)
treec5fd969b75460a915f604fa10bf635999d09989f /net/wireless/nl80211.c
parent06500736c5d26bff93a4f358713689073e66d0f5 (diff)
cfg80211: allow registering to beacons
Add the ability to register to received beacon frames to allow implementing OLBC logic in userspace. The registration is per wiphy since there's no point in receiving the same frame multiple times. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c70
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
5914static 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
6483static struct genl_multicast_group nl80211_mlme_mcgrp = { 6510static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -7582,6 +7609,44 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
7582} 7609}
7583EXPORT_SYMBOL(cfg80211_probe_status); 7610EXPORT_SYMBOL(cfg80211_probe_status);
7584 7611
7612void 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}
7648EXPORT_SYMBOL(cfg80211_report_obss_beacon);
7649
7585static int nl80211_netlink_notify(struct notifier_block * nb, 7650static 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