Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 277786
b: refs/heads/master
c: 5e76023
h: refs/heads/master
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed Nov 9, 2011
1 parent 8ae4bde commit ece41d0
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 06500736c5d26bff93a4f358713689073e66d0f5
refs/heads/master: 5e760230e42cf759bd923457ca2753aacf2e656e
7 changes: 7 additions & 0 deletions trunk/include/linux/nl80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,11 @@
* up the event with the request. The event includes the same data and
* has %NL80211_ATTR_ACK set if the frame was ACKed.
*
* @NL80211_CMD_REGISTER_BEACONS: Register this socket to receive beacons from
* other BSSes when any interfaces are in AP mode. This helps implement
* OLBC handling in hostapd. Beacons are reported in %NL80211_CMD_FRAME
* messages. Note that per PHY only one application may register.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
Expand Down Expand Up @@ -660,6 +665,8 @@ enum nl80211_commands {

NL80211_CMD_PROBE_CLIENT,

NL80211_CMD_REGISTER_BEACONS,

/* add new commands above here */

/* used to define NL80211_CMD_MAX below */
Expand Down
20 changes: 20 additions & 0 deletions trunk/include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1686,6 +1686,9 @@ struct cfg80211_ops {
* command. When this flag is not set, @NL80211_CMD_TDLS_OPER should be
* used for asking the driver/firmware to perform a TDLS operation.
* @WIPHY_FLAG_HAVE_AP_SME: device integrates AP SME
* @WIPHY_FLAG_REPORTS_OBSS: the device will report beacons from other BSSes
* when there are virtual interfaces in AP mode by calling
* cfg80211_report_obss_beacon().
*/
enum wiphy_flags {
WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0),
Expand All @@ -1705,6 +1708,7 @@ enum wiphy_flags {
WIPHY_FLAG_SUPPORTS_TDLS = BIT(15),
WIPHY_FLAG_TDLS_EXTERNAL_SETUP = BIT(16),
WIPHY_FLAG_HAVE_AP_SME = BIT(17),
WIPHY_FLAG_REPORTS_OBSS = BIT(18),
};

/**
Expand Down Expand Up @@ -3233,6 +3237,22 @@ bool cfg80211_rx_spurious_frame(struct net_device *dev,
void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
u64 cookie, bool acked, gfp_t gfp);

/**
* cfg80211_report_obss_beacon - report beacon from other APs
* @wiphy: The wiphy that received the beacon
* @frame: the frame
* @len: length of the frame
* @freq: frequency the frame was received on
* @gfp: allocation flags
*
* Use this function to report to userspace when a beacon was
* received. It is not useful to call this when there is no
* netdev that is in AP/GO mode.
*/
void cfg80211_report_obss_beacon(struct wiphy *wiphy,
const u8 *frame, size_t len,
int freq, gfp_t gfp);

/* Logging, debugging and troubleshooting/diagnostic helpers. */

/* wiphy_printk helpers, similar to dev_printk */
Expand Down
2 changes: 2 additions & 0 deletions trunk/net/wireless/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ struct cfg80211_registered_device {
int opencount; /* also protected by devlist_mtx */
wait_queue_head_t dev_wait;

u32 ap_beacons_nlpid;

/* BSSes/scanning */
spinlock_t bss_lock;
struct list_head bss_list;
Expand Down
70 changes: 69 additions & 1 deletion trunk/net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
CMD(sched_scan_start, START_SCHED_SCAN);
CMD(probe_client, PROBE_CLIENT);
if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
i++;
NLA_PUT_U32(msg, i, NL80211_CMD_REGISTER_BEACONS);
}

#undef CMD

Expand Down Expand Up @@ -5907,6 +5911,21 @@ static int nl80211_probe_client(struct sk_buff *skb,
return err;
}

static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];

if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS))
return -EOPNOTSUPP;

if (rdev->ap_beacons_nlpid)
return -EBUSY;

rdev->ap_beacons_nlpid = info->snd_pid;

return 0;
}

#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
Expand Down Expand Up @@ -6478,6 +6497,14 @@ static struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV |
NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_REGISTER_BEACONS,
.doit = nl80211_register_beacons,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WIPHY |
NL80211_FLAG_NEED_RTNL,
},
};

static struct genl_multicast_group nl80211_mlme_mcgrp = {
Expand Down Expand Up @@ -7582,6 +7609,44 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
}
EXPORT_SYMBOL(cfg80211_probe_status);

void cfg80211_report_obss_beacon(struct wiphy *wiphy,
const u8 *frame, size_t len,
int freq, gfp_t gfp)
{
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
struct sk_buff *msg;
void *hdr;
u32 nlpid = ACCESS_ONCE(rdev->ap_beacons_nlpid);

if (!nlpid)
return;

msg = nlmsg_new(len + 100, gfp);
if (!msg)
return;

hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
if (!hdr) {
nlmsg_free(msg);
return;
}

NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
if (freq)
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
NLA_PUT(msg, NL80211_ATTR_FRAME, len, frame);

genlmsg_end(msg, hdr);

genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlpid);
return;

nla_put_failure:
genlmsg_cancel(msg, hdr);
nlmsg_free(msg);
}
EXPORT_SYMBOL(cfg80211_report_obss_beacon);

static int nl80211_netlink_notify(struct notifier_block * nb,
unsigned long state,
void *_notify)
Expand All @@ -7595,9 +7660,12 @@ static int nl80211_netlink_notify(struct notifier_block * nb,

rcu_read_lock();

list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list)
list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
list_for_each_entry_rcu(wdev, &rdev->netdev_list, list)
cfg80211_mlme_unregister_socket(wdev, notify->pid);
if (rdev->ap_beacons_nlpid == notify->pid)
rdev->ap_beacons_nlpid = 0;
}

rcu_read_unlock();

Expand Down

0 comments on commit ece41d0

Please sign in to comment.