aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-07-02 11:20:43 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 15:01:53 -0400
commit19957bb399e2722719c0e20c9ae91cf8b6aaff04 (patch)
tree9c4d53fe5938ceee41333a1afd5be0ed5c1ce313 /net/wireless/nl80211.c
parent517357c685ccc4b5783cc7dbdae8824ada19a97f (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.c144
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
3114out: 3113out:
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
3184static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) 3183static 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
3258out: 3256out:
3259 cfg80211_put_dev(drv); 3257 cfg80211_put_dev(rdev);
3260 dev_put(dev); 3258 dev_put(dev);
3261unlock_rtnl: 3259unlock_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
3323out: 3318out:
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
3388out: 3380out:
3389 cfg80211_put_dev(drv); 3381 cfg80211_put_dev(drv);