aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-07-10 12:42:31 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-24 15:05:11 -0400
commit48ab905d1a81b7df33a33def04a890e4e0c51460 (patch)
tree928fb9eeb2edd8ff89138016f7ca4ffddb833821
parent4697fe4f78df14d37cffa7e8d27cbb02a351c139 (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>
-rw-r--r--include/linux/nl80211.h11
-rw-r--r--net/wireless/nl80211.c65
2 files changed, 59 insertions, 17 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index b043b78dd2c3..962e2232a074 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1260,6 +1260,7 @@ enum nl80211_channel_type {
1260 * in mBm (100 * dBm) (s32) 1260 * in mBm (100 * dBm) (s32)
1261 * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon 1261 * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
1262 * in unspecified units, scaled to 0..100 (u8) 1262 * in unspecified units, scaled to 0..100 (u8)
1263 * @NL80211_BSS_STATUS: status, if this BSS is "used"
1263 * @__NL80211_BSS_AFTER_LAST: internal 1264 * @__NL80211_BSS_AFTER_LAST: internal
1264 * @NL80211_BSS_MAX: highest BSS attribute 1265 * @NL80211_BSS_MAX: highest BSS attribute
1265 */ 1266 */
@@ -1273,6 +1274,7 @@ enum nl80211_bss {
1273 NL80211_BSS_INFORMATION_ELEMENTS, 1274 NL80211_BSS_INFORMATION_ELEMENTS,
1274 NL80211_BSS_SIGNAL_MBM, 1275 NL80211_BSS_SIGNAL_MBM,
1275 NL80211_BSS_SIGNAL_UNSPEC, 1276 NL80211_BSS_SIGNAL_UNSPEC,
1277 NL80211_BSS_STATUS,
1276 1278
1277 /* keep last */ 1279 /* keep last */
1278 __NL80211_BSS_AFTER_LAST, 1280 __NL80211_BSS_AFTER_LAST,
@@ -1280,6 +1282,15 @@ enum nl80211_bss {
1280}; 1282};
1281 1283
1282/** 1284/**
1285 * enum nl80211_bss_status - BSS "status"
1286 */
1287enum nl80211_bss_status {
1288 NL80211_BSS_STATUS_AUTHENTICATED,
1289 NL80211_BSS_STATUS_ASSOCIATED,
1290 NL80211_BSS_STATUS_IBSS_JOINED,
1291};
1292
1293/**
1283 * enum nl80211_auth_type - AuthenticationType 1294 * enum nl80211_auth_type - AuthenticationType
1284 * 1295 *
1285 * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication 1296 * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication
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
3095static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, 3095static 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,
3148static int nl80211_dump_scan(struct sk_buff *skb, 3174static 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}