diff options
Diffstat (limited to 'net/wireless/nl80211.c')
-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 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 | ||
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 | } |