nl80211: report BSS status
When connected to a BSS, or joined to an IBSS, we'll want to know in userspace without using wireless extensions, so report the BSS status in the BSS list. Userspace can query the BSS list, display all the information and retrieve the station information as well. For example (from hwsim): $ iw dev wlan1 scan dump BSS 02:00:00:00:00:00 (on wlan1) -- associated freq: 2462 beacon interval: 100 capability: ESS ShortSlotTime (0x0401) signal: -50.00 dBm SSID: j Supported rates: 1.0* 2.0* 5.5* 11.0* 6.0 9.0 12.0 18.0 DS Paramater set: channel 11 ERP: <no flags> Extended supported rates: 24.0 36.0 48.0 54.0 Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
4697fe4f78
commit
48ab905d1a
|
@ -1260,6 +1260,7 @@ enum nl80211_channel_type {
|
||||||
* in mBm (100 * dBm) (s32)
|
* in mBm (100 * dBm) (s32)
|
||||||
* @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
|
* @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
|
||||||
* in unspecified units, scaled to 0..100 (u8)
|
* in unspecified units, scaled to 0..100 (u8)
|
||||||
|
* @NL80211_BSS_STATUS: status, if this BSS is "used"
|
||||||
* @__NL80211_BSS_AFTER_LAST: internal
|
* @__NL80211_BSS_AFTER_LAST: internal
|
||||||
* @NL80211_BSS_MAX: highest BSS attribute
|
* @NL80211_BSS_MAX: highest BSS attribute
|
||||||
*/
|
*/
|
||||||
|
@ -1273,12 +1274,22 @@ enum nl80211_bss {
|
||||||
NL80211_BSS_INFORMATION_ELEMENTS,
|
NL80211_BSS_INFORMATION_ELEMENTS,
|
||||||
NL80211_BSS_SIGNAL_MBM,
|
NL80211_BSS_SIGNAL_MBM,
|
||||||
NL80211_BSS_SIGNAL_UNSPEC,
|
NL80211_BSS_SIGNAL_UNSPEC,
|
||||||
|
NL80211_BSS_STATUS,
|
||||||
|
|
||||||
/* keep last */
|
/* keep last */
|
||||||
__NL80211_BSS_AFTER_LAST,
|
__NL80211_BSS_AFTER_LAST,
|
||||||
NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1
|
NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum nl80211_bss_status - BSS "status"
|
||||||
|
*/
|
||||||
|
enum nl80211_bss_status {
|
||||||
|
NL80211_BSS_STATUS_AUTHENTICATED,
|
||||||
|
NL80211_BSS_STATUS_ASSOCIATED,
|
||||||
|
NL80211_BSS_STATUS_IBSS_JOINED,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum nl80211_auth_type - AuthenticationType
|
* enum nl80211_auth_type - AuthenticationType
|
||||||
*
|
*
|
||||||
|
|
|
@ -3094,11 +3094,15 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
||||||
|
|
||||||
static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
|
static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
|
||||||
struct cfg80211_registered_device *rdev,
|
struct cfg80211_registered_device *rdev,
|
||||||
struct net_device *dev,
|
struct wireless_dev *wdev,
|
||||||
struct cfg80211_bss *res)
|
struct cfg80211_internal_bss *intbss)
|
||||||
{
|
{
|
||||||
|
struct cfg80211_bss *res = &intbss->pub;
|
||||||
void *hdr;
|
void *hdr;
|
||||||
struct nlattr *bss;
|
struct nlattr *bss;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ASSERT_WDEV_LOCK(wdev);
|
||||||
|
|
||||||
hdr = nl80211hdr_put(msg, pid, seq, flags,
|
hdr = nl80211hdr_put(msg, pid, seq, flags,
|
||||||
NL80211_CMD_NEW_SCAN_RESULTS);
|
NL80211_CMD_NEW_SCAN_RESULTS);
|
||||||
|
@ -3107,7 +3111,7 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
|
||||||
|
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_SCAN_GENERATION,
|
NLA_PUT_U32(msg, NL80211_ATTR_SCAN_GENERATION,
|
||||||
rdev->bss_generation);
|
rdev->bss_generation);
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex);
|
||||||
|
|
||||||
bss = nla_nest_start(msg, NL80211_ATTR_BSS);
|
bss = nla_nest_start(msg, NL80211_ATTR_BSS);
|
||||||
if (!bss)
|
if (!bss)
|
||||||
|
@ -3136,6 +3140,28 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (wdev->iftype) {
|
||||||
|
case NL80211_IFTYPE_STATION:
|
||||||
|
if (intbss == wdev->current_bss)
|
||||||
|
NLA_PUT_U32(msg, NL80211_BSS_STATUS,
|
||||||
|
NL80211_BSS_STATUS_ASSOCIATED);
|
||||||
|
else for (i = 0; i < MAX_AUTH_BSSES; i++) {
|
||||||
|
if (intbss != wdev->auth_bsses[i])
|
||||||
|
continue;
|
||||||
|
NLA_PUT_U32(msg, NL80211_BSS_STATUS,
|
||||||
|
NL80211_BSS_STATUS_AUTHENTICATED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NL80211_IFTYPE_ADHOC:
|
||||||
|
if (intbss == wdev->current_bss)
|
||||||
|
NLA_PUT_U32(msg, NL80211_BSS_STATUS,
|
||||||
|
NL80211_BSS_STATUS_IBSS_JOINED);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
nla_nest_end(msg, bss);
|
nla_nest_end(msg, bss);
|
||||||
|
|
||||||
return genlmsg_end(msg, hdr);
|
return genlmsg_end(msg, hdr);
|
||||||
|
@ -3148,9 +3174,10 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
|
||||||
static int nl80211_dump_scan(struct sk_buff *skb,
|
static int nl80211_dump_scan(struct sk_buff *skb,
|
||||||
struct netlink_callback *cb)
|
struct netlink_callback *cb)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *dev;
|
struct cfg80211_registered_device *rdev;
|
||||||
struct net_device *netdev;
|
struct net_device *dev;
|
||||||
struct cfg80211_internal_bss *scan;
|
struct cfg80211_internal_bss *scan;
|
||||||
|
struct wireless_dev *wdev;
|
||||||
int ifidx = cb->args[0];
|
int ifidx = cb->args[0];
|
||||||
int start = cb->args[1], idx = 0;
|
int start = cb->args[1], idx = 0;
|
||||||
int err;
|
int err;
|
||||||
|
@ -3171,39 +3198,43 @@ static int nl80211_dump_scan(struct sk_buff *skb,
|
||||||
cb->args[0] = ifidx;
|
cb->args[0] = ifidx;
|
||||||
}
|
}
|
||||||
|
|
||||||
netdev = dev_get_by_index(&init_net, ifidx);
|
dev = dev_get_by_index(&init_net, ifidx);
|
||||||
if (!netdev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
dev = cfg80211_get_dev_from_ifindex(ifidx);
|
rdev = cfg80211_get_dev_from_ifindex(ifidx);
|
||||||
if (IS_ERR(dev)) {
|
if (IS_ERR(rdev)) {
|
||||||
err = PTR_ERR(dev);
|
err = PTR_ERR(rdev);
|
||||||
goto out_put_netdev;
|
goto out_put_netdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_bh(&dev->bss_lock);
|
wdev = dev->ieee80211_ptr;
|
||||||
cfg80211_bss_expire(dev);
|
|
||||||
|
|
||||||
list_for_each_entry(scan, &dev->bss_list, list) {
|
wdev_lock(wdev);
|
||||||
|
spin_lock_bh(&rdev->bss_lock);
|
||||||
|
cfg80211_bss_expire(rdev);
|
||||||
|
|
||||||
|
list_for_each_entry(scan, &rdev->bss_list, list) {
|
||||||
if (++idx <= start)
|
if (++idx <= start)
|
||||||
continue;
|
continue;
|
||||||
if (nl80211_send_bss(skb,
|
if (nl80211_send_bss(skb,
|
||||||
NETLINK_CB(cb->skb).pid,
|
NETLINK_CB(cb->skb).pid,
|
||||||
cb->nlh->nlmsg_seq, NLM_F_MULTI,
|
cb->nlh->nlmsg_seq, NLM_F_MULTI,
|
||||||
dev, netdev, &scan->pub) < 0) {
|
rdev, wdev, scan) < 0) {
|
||||||
idx--;
|
idx--;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
spin_unlock_bh(&dev->bss_lock);
|
spin_unlock_bh(&rdev->bss_lock);
|
||||||
|
wdev_unlock(wdev);
|
||||||
|
|
||||||
cb->args[1] = idx;
|
cb->args[1] = idx;
|
||||||
err = skb->len;
|
err = skb->len;
|
||||||
cfg80211_unlock_rdev(dev);
|
cfg80211_unlock_rdev(rdev);
|
||||||
out_put_netdev:
|
out_put_netdev:
|
||||||
dev_put(netdev);
|
dev_put(dev);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue