diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-07-02 11:20:43 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-10 15:01:53 -0400 |
commit | 19957bb399e2722719c0e20c9ae91cf8b6aaff04 (patch) | |
tree | 9c4d53fe5938ceee41333a1afd5be0ed5c1ce313 /net/wireless/nl80211.c | |
parent | 517357c685ccc4b5783cc7dbdae8824ada19a97f (diff) |
cfg80211: keep track of BSSes
In order to avoid problems with BSS structs going away
while they're in use, I've long wanted to make cfg80211
keep track of them. Without the SME, that wasn't doable
but now that we have the SME we can do this too. It can
keep track of up to four separate authentications and
one association, regardless of whether it's controlled
by the cfg80211 SME or the userspace SME.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 144 |
1 files changed, 68 insertions, 76 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 0008144b354b..aa2b3f35cc48 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -3044,9 +3044,10 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3044 | { | 3044 | { |
3045 | struct cfg80211_registered_device *drv; | 3045 | struct cfg80211_registered_device *drv; |
3046 | struct net_device *dev; | 3046 | struct net_device *dev; |
3047 | struct cfg80211_auth_request req; | 3047 | struct ieee80211_channel *chan; |
3048 | struct wiphy *wiphy; | 3048 | const u8 *bssid, *ssid, *ie = NULL; |
3049 | int err; | 3049 | int err, ssid_len, ie_len = 0; |
3050 | enum nl80211_auth_type auth_type; | ||
3050 | 3051 | ||
3051 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3052 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3052 | return -EINVAL; | 3053 | return -EINVAL; |
@@ -3057,6 +3058,12 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3057 | if (!info->attrs[NL80211_ATTR_AUTH_TYPE]) | 3058 | if (!info->attrs[NL80211_ATTR_AUTH_TYPE]) |
3058 | return -EINVAL; | 3059 | return -EINVAL; |
3059 | 3060 | ||
3061 | if (!info->attrs[NL80211_ATTR_SSID]) | ||
3062 | return -EINVAL; | ||
3063 | |||
3064 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) | ||
3065 | return -EINVAL; | ||
3066 | |||
3060 | rtnl_lock(); | 3067 | rtnl_lock(); |
3061 | 3068 | ||
3062 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 3069 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
@@ -3078,38 +3085,30 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3078 | goto out; | 3085 | goto out; |
3079 | } | 3086 | } |
3080 | 3087 | ||
3081 | wiphy = &drv->wiphy; | 3088 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
3082 | memset(&req, 0, sizeof(req)); | 3089 | chan = ieee80211_get_channel(&drv->wiphy, |
3083 | 3090 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); | |
3084 | req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 3091 | if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) { |
3085 | 3092 | err = -EINVAL; | |
3086 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 3093 | goto out; |
3087 | req.chan = ieee80211_get_channel( | ||
3088 | wiphy, | ||
3089 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); | ||
3090 | if (!req.chan) { | ||
3091 | err = -EINVAL; | ||
3092 | goto out; | ||
3093 | } | ||
3094 | } | 3094 | } |
3095 | 3095 | ||
3096 | if (info->attrs[NL80211_ATTR_SSID]) { | 3096 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
3097 | req.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 3097 | ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); |
3098 | req.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); | ||
3099 | } | ||
3100 | 3098 | ||
3101 | if (info->attrs[NL80211_ATTR_IE]) { | 3099 | if (info->attrs[NL80211_ATTR_IE]) { |
3102 | req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); | 3100 | ie = nla_data(info->attrs[NL80211_ATTR_IE]); |
3103 | req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 3101 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
3104 | } | 3102 | } |
3105 | 3103 | ||
3106 | req.auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); | 3104 | auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); |
3107 | if (!nl80211_valid_auth_type(req.auth_type)) { | 3105 | if (!nl80211_valid_auth_type(auth_type)) { |
3108 | err = -EINVAL; | 3106 | err = -EINVAL; |
3109 | goto out; | 3107 | goto out; |
3110 | } | 3108 | } |
3111 | 3109 | ||
3112 | err = drv->ops->auth(&drv->wiphy, dev, &req); | 3110 | err = cfg80211_mlme_auth(drv, dev, chan, auth_type, bssid, |
3111 | ssid, ssid_len, ie, ie_len); | ||
3113 | 3112 | ||
3114 | out: | 3113 | out: |
3115 | cfg80211_put_dev(drv); | 3114 | cfg80211_put_dev(drv); |
@@ -3183,26 +3182,29 @@ static int nl80211_crypto_settings(struct genl_info *info, | |||
3183 | 3182 | ||
3184 | static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | 3183 | static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) |
3185 | { | 3184 | { |
3186 | struct cfg80211_registered_device *drv; | 3185 | struct cfg80211_registered_device *rdev; |
3187 | struct net_device *dev; | 3186 | struct net_device *dev; |
3188 | struct cfg80211_assoc_request req; | 3187 | struct cfg80211_crypto_settings crypto; |
3189 | struct wiphy *wiphy; | 3188 | struct ieee80211_channel *chan; |
3190 | int err; | 3189 | const u8 *bssid, *ssid, *ie = NULL; |
3190 | int err, ssid_len, ie_len = 0; | ||
3191 | bool use_mfp = false; | ||
3191 | 3192 | ||
3192 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3193 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3193 | return -EINVAL; | 3194 | return -EINVAL; |
3194 | 3195 | ||
3195 | if (!info->attrs[NL80211_ATTR_MAC] || | 3196 | if (!info->attrs[NL80211_ATTR_MAC] || |
3196 | !info->attrs[NL80211_ATTR_SSID]) | 3197 | !info->attrs[NL80211_ATTR_SSID] || |
3198 | !info->attrs[NL80211_ATTR_WIPHY_FREQ]) | ||
3197 | return -EINVAL; | 3199 | return -EINVAL; |
3198 | 3200 | ||
3199 | rtnl_lock(); | 3201 | rtnl_lock(); |
3200 | 3202 | ||
3201 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 3203 | err = get_drv_dev_by_info_ifindex(info->attrs, &rdev, &dev); |
3202 | if (err) | 3204 | if (err) |
3203 | goto unlock_rtnl; | 3205 | goto unlock_rtnl; |
3204 | 3206 | ||
3205 | if (!drv->ops->assoc) { | 3207 | if (!rdev->ops->assoc) { |
3206 | err = -EOPNOTSUPP; | 3208 | err = -EOPNOTSUPP; |
3207 | goto out; | 3209 | goto out; |
3208 | } | 3210 | } |
@@ -3217,46 +3219,42 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
3217 | goto out; | 3219 | goto out; |
3218 | } | 3220 | } |
3219 | 3221 | ||
3220 | wiphy = &drv->wiphy; | 3222 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
3221 | memset(&req, 0, sizeof(req)); | ||
3222 | |||
3223 | req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | ||
3224 | 3223 | ||
3225 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 3224 | chan = ieee80211_get_channel(&rdev->wiphy, |
3226 | req.chan = ieee80211_get_channel( | 3225 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); |
3227 | wiphy, | 3226 | if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) { |
3228 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); | 3227 | err = -EINVAL; |
3229 | if (!req.chan) { | 3228 | goto out; |
3230 | err = -EINVAL; | ||
3231 | goto out; | ||
3232 | } | ||
3233 | } | 3229 | } |
3234 | 3230 | ||
3235 | req.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 3231 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
3236 | req.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); | 3232 | ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); |
3237 | 3233 | ||
3238 | if (info->attrs[NL80211_ATTR_IE]) { | 3234 | if (info->attrs[NL80211_ATTR_IE]) { |
3239 | req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); | 3235 | ie = nla_data(info->attrs[NL80211_ATTR_IE]); |
3240 | req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 3236 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
3241 | } | 3237 | } |
3242 | 3238 | ||
3243 | if (info->attrs[NL80211_ATTR_USE_MFP]) { | 3239 | if (info->attrs[NL80211_ATTR_USE_MFP]) { |
3244 | enum nl80211_mfp use_mfp = | 3240 | enum nl80211_mfp use_mfp = |
3245 | nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); | 3241 | nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); |
3246 | if (use_mfp == NL80211_MFP_REQUIRED) | 3242 | if (use_mfp == NL80211_MFP_REQUIRED) |
3247 | req.use_mfp = true; | 3243 | use_mfp = true; |
3248 | else if (use_mfp != NL80211_MFP_NO) { | 3244 | else if (use_mfp != NL80211_MFP_NO) { |
3249 | err = -EINVAL; | 3245 | err = -EINVAL; |
3250 | goto out; | 3246 | goto out; |
3251 | } | 3247 | } |
3252 | } | 3248 | } |
3253 | 3249 | ||
3254 | err = nl80211_crypto_settings(info, &req.crypto); | 3250 | err = nl80211_crypto_settings(info, &crypto); |
3255 | if (!err) | 3251 | if (!err) |
3256 | err = drv->ops->assoc(&drv->wiphy, dev, &req); | 3252 | err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, ssid, |
3253 | ssid_len, ie, ie_len, use_mfp, | ||
3254 | &crypto); | ||
3257 | 3255 | ||
3258 | out: | 3256 | out: |
3259 | cfg80211_put_dev(drv); | 3257 | cfg80211_put_dev(rdev); |
3260 | dev_put(dev); | 3258 | dev_put(dev); |
3261 | unlock_rtnl: | 3259 | unlock_rtnl: |
3262 | rtnl_unlock(); | 3260 | rtnl_unlock(); |
@@ -3267,9 +3265,9 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
3267 | { | 3265 | { |
3268 | struct cfg80211_registered_device *drv; | 3266 | struct cfg80211_registered_device *drv; |
3269 | struct net_device *dev; | 3267 | struct net_device *dev; |
3270 | struct cfg80211_deauth_request req; | 3268 | const u8 *ie = NULL, *bssid; |
3271 | struct wiphy *wiphy; | 3269 | int err, ie_len = 0; |
3272 | int err; | 3270 | u16 reason_code; |
3273 | 3271 | ||
3274 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3272 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3275 | return -EINVAL; | 3273 | return -EINVAL; |
@@ -3301,24 +3299,21 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
3301 | goto out; | 3299 | goto out; |
3302 | } | 3300 | } |
3303 | 3301 | ||
3304 | wiphy = &drv->wiphy; | 3302 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
3305 | memset(&req, 0, sizeof(req)); | ||
3306 | |||
3307 | req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | ||
3308 | 3303 | ||
3309 | req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); | 3304 | reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); |
3310 | if (req.reason_code == 0) { | 3305 | if (reason_code == 0) { |
3311 | /* Reason Code 0 is reserved */ | 3306 | /* Reason Code 0 is reserved */ |
3312 | err = -EINVAL; | 3307 | err = -EINVAL; |
3313 | goto out; | 3308 | goto out; |
3314 | } | 3309 | } |
3315 | 3310 | ||
3316 | if (info->attrs[NL80211_ATTR_IE]) { | 3311 | if (info->attrs[NL80211_ATTR_IE]) { |
3317 | req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); | 3312 | ie = nla_data(info->attrs[NL80211_ATTR_IE]); |
3318 | req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 3313 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
3319 | } | 3314 | } |
3320 | 3315 | ||
3321 | err = drv->ops->deauth(&drv->wiphy, dev, &req); | 3316 | err = cfg80211_mlme_deauth(drv, dev, bssid, ie, ie_len, reason_code); |
3322 | 3317 | ||
3323 | out: | 3318 | out: |
3324 | cfg80211_put_dev(drv); | 3319 | cfg80211_put_dev(drv); |
@@ -3332,9 +3327,9 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
3332 | { | 3327 | { |
3333 | struct cfg80211_registered_device *drv; | 3328 | struct cfg80211_registered_device *drv; |
3334 | struct net_device *dev; | 3329 | struct net_device *dev; |
3335 | struct cfg80211_disassoc_request req; | 3330 | const u8 *ie = NULL, *bssid; |
3336 | struct wiphy *wiphy; | 3331 | int err, ie_len = 0; |
3337 | int err; | 3332 | u16 reason_code; |
3338 | 3333 | ||
3339 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3334 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3340 | return -EINVAL; | 3335 | return -EINVAL; |
@@ -3366,24 +3361,21 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
3366 | goto out; | 3361 | goto out; |
3367 | } | 3362 | } |
3368 | 3363 | ||
3369 | wiphy = &drv->wiphy; | 3364 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
3370 | memset(&req, 0, sizeof(req)); | ||
3371 | |||
3372 | req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | ||
3373 | 3365 | ||
3374 | req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); | 3366 | reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); |
3375 | if (req.reason_code == 0) { | 3367 | if (reason_code == 0) { |
3376 | /* Reason Code 0 is reserved */ | 3368 | /* Reason Code 0 is reserved */ |
3377 | err = -EINVAL; | 3369 | err = -EINVAL; |
3378 | goto out; | 3370 | goto out; |
3379 | } | 3371 | } |
3380 | 3372 | ||
3381 | if (info->attrs[NL80211_ATTR_IE]) { | 3373 | if (info->attrs[NL80211_ATTR_IE]) { |
3382 | req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); | 3374 | ie = nla_data(info->attrs[NL80211_ATTR_IE]); |
3383 | req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 3375 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
3384 | } | 3376 | } |
3385 | 3377 | ||
3386 | err = drv->ops->disassoc(&drv->wiphy, dev, &req); | 3378 | err = cfg80211_mlme_disassoc(drv, dev, bssid, ie, ie_len, reason_code); |
3387 | 3379 | ||
3388 | out: | 3380 | out: |
3389 | cfg80211_put_dev(drv); | 3381 | cfg80211_put_dev(drv); |