aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c65
1 files changed, 48 insertions, 17 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 45c5f9c8e51..da450ef1fc7 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}