diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-07-10 12:42:31 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-24 15:05:11 -0400 |
commit | 48ab905d1a81b7df33a33def04a890e4e0c51460 (patch) | |
tree | 928fb9eeb2edd8ff89138016f7ca4ffddb833821 /net | |
parent | 4697fe4f78df14d37cffa7e8d27cbb02a351c139 (diff) |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/wireless/nl80211.c | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 45c5f9c8e51b..da450ef1fc7e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -3094,11 +3094,15 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
3094 | 3094 | ||
3095 | static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | 3095 | static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, |
3096 | struct cfg80211_registered_device *rdev, | 3096 | struct cfg80211_registered_device *rdev, |
3097 | struct net_device *dev, | 3097 | struct wireless_dev *wdev, |
3098 | struct cfg80211_bss *res) | 3098 | struct cfg80211_internal_bss *intbss) |
3099 | { | 3099 | { |
3100 | struct cfg80211_bss *res = &intbss->pub; | ||
3100 | void *hdr; | 3101 | void *hdr; |
3101 | struct nlattr *bss; | 3102 | struct nlattr *bss; |
3103 | int i; | ||
3104 | |||
3105 | ASSERT_WDEV_LOCK(wdev); | ||
3102 | 3106 | ||
3103 | hdr = nl80211hdr_put(msg, pid, seq, flags, | 3107 | hdr = nl80211hdr_put(msg, pid, seq, flags, |
3104 | NL80211_CMD_NEW_SCAN_RESULTS); | 3108 | NL80211_CMD_NEW_SCAN_RESULTS); |
@@ -3107,7 +3111,7 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
3107 | 3111 | ||
3108 | NLA_PUT_U32(msg, NL80211_ATTR_SCAN_GENERATION, | 3112 | NLA_PUT_U32(msg, NL80211_ATTR_SCAN_GENERATION, |
3109 | rdev->bss_generation); | 3113 | rdev->bss_generation); |
3110 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | 3114 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex); |
3111 | 3115 | ||
3112 | bss = nla_nest_start(msg, NL80211_ATTR_BSS); | 3116 | bss = nla_nest_start(msg, NL80211_ATTR_BSS); |
3113 | if (!bss) | 3117 | if (!bss) |
@@ -3136,6 +3140,28 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
3136 | break; | 3140 | break; |
3137 | } | 3141 | } |
3138 | 3142 | ||
3143 | switch (wdev->iftype) { | ||
3144 | case NL80211_IFTYPE_STATION: | ||
3145 | if (intbss == wdev->current_bss) | ||
3146 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, | ||
3147 | NL80211_BSS_STATUS_ASSOCIATED); | ||
3148 | else for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
3149 | if (intbss != wdev->auth_bsses[i]) | ||
3150 | continue; | ||
3151 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, | ||
3152 | NL80211_BSS_STATUS_AUTHENTICATED); | ||
3153 | break; | ||
3154 | } | ||
3155 | break; | ||
3156 | case NL80211_IFTYPE_ADHOC: | ||
3157 | if (intbss == wdev->current_bss) | ||
3158 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, | ||
3159 | NL80211_BSS_STATUS_IBSS_JOINED); | ||
3160 | break; | ||
3161 | default: | ||
3162 | break; | ||
3163 | } | ||
3164 | |||
3139 | nla_nest_end(msg, bss); | 3165 | nla_nest_end(msg, bss); |
3140 | 3166 | ||
3141 | return genlmsg_end(msg, hdr); | 3167 | return genlmsg_end(msg, hdr); |
@@ -3148,9 +3174,10 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
3148 | static int nl80211_dump_scan(struct sk_buff *skb, | 3174 | static int nl80211_dump_scan(struct sk_buff *skb, |
3149 | struct netlink_callback *cb) | 3175 | struct netlink_callback *cb) |
3150 | { | 3176 | { |
3151 | struct cfg80211_registered_device *dev; | 3177 | struct cfg80211_registered_device *rdev; |
3152 | struct net_device *netdev; | 3178 | struct net_device *dev; |
3153 | struct cfg80211_internal_bss *scan; | 3179 | struct cfg80211_internal_bss *scan; |
3180 | struct wireless_dev *wdev; | ||
3154 | int ifidx = cb->args[0]; | 3181 | int ifidx = cb->args[0]; |
3155 | int start = cb->args[1], idx = 0; | 3182 | int start = cb->args[1], idx = 0; |
3156 | int err; | 3183 | int err; |
@@ -3171,39 +3198,43 @@ static int nl80211_dump_scan(struct sk_buff *skb, | |||
3171 | cb->args[0] = ifidx; | 3198 | cb->args[0] = ifidx; |
3172 | } | 3199 | } |
3173 | 3200 | ||
3174 | netdev = dev_get_by_index(&init_net, ifidx); | 3201 | dev = dev_get_by_index(&init_net, ifidx); |
3175 | if (!netdev) | 3202 | if (!dev) |
3176 | return -ENODEV; | 3203 | return -ENODEV; |
3177 | 3204 | ||
3178 | dev = cfg80211_get_dev_from_ifindex(ifidx); | 3205 | rdev = cfg80211_get_dev_from_ifindex(ifidx); |
3179 | if (IS_ERR(dev)) { | 3206 | if (IS_ERR(rdev)) { |
3180 | err = PTR_ERR(dev); | 3207 | err = PTR_ERR(rdev); |
3181 | goto out_put_netdev; | 3208 | goto out_put_netdev; |
3182 | } | 3209 | } |
3183 | 3210 | ||
3184 | spin_lock_bh(&dev->bss_lock); | 3211 | wdev = dev->ieee80211_ptr; |
3185 | cfg80211_bss_expire(dev); | ||
3186 | 3212 | ||
3187 | list_for_each_entry(scan, &dev->bss_list, list) { | 3213 | wdev_lock(wdev); |
3214 | spin_lock_bh(&rdev->bss_lock); | ||
3215 | cfg80211_bss_expire(rdev); | ||
3216 | |||
3217 | list_for_each_entry(scan, &rdev->bss_list, list) { | ||
3188 | if (++idx <= start) | 3218 | if (++idx <= start) |
3189 | continue; | 3219 | continue; |
3190 | if (nl80211_send_bss(skb, | 3220 | if (nl80211_send_bss(skb, |
3191 | NETLINK_CB(cb->skb).pid, | 3221 | NETLINK_CB(cb->skb).pid, |
3192 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 3222 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
3193 | dev, netdev, &scan->pub) < 0) { | 3223 | rdev, wdev, scan) < 0) { |
3194 | idx--; | 3224 | idx--; |
3195 | goto out; | 3225 | goto out; |
3196 | } | 3226 | } |
3197 | } | 3227 | } |
3198 | 3228 | ||
3199 | out: | 3229 | out: |
3200 | spin_unlock_bh(&dev->bss_lock); | 3230 | spin_unlock_bh(&rdev->bss_lock); |
3231 | wdev_unlock(wdev); | ||
3201 | 3232 | ||
3202 | cb->args[1] = idx; | 3233 | cb->args[1] = idx; |
3203 | err = skb->len; | 3234 | err = skb->len; |
3204 | cfg80211_unlock_rdev(dev); | 3235 | cfg80211_unlock_rdev(rdev); |
3205 | out_put_netdev: | 3236 | out_put_netdev: |
3206 | dev_put(netdev); | 3237 | dev_put(dev); |
3207 | 3238 | ||
3208 | return err; | 3239 | return err; |
3209 | } | 3240 | } |