aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2010-04-04 02:37:19 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-07 14:37:56 -0400
commitd5cdfacb35ed886271d1ccfffbded98d3447da17 (patch)
tree8233a713949c4c8da8c98e75868efc74d5613c3d /net/wireless/nl80211.c
parent7590a550b88b8c3cb025f0a8ed58e279ad62e4c1 (diff)
cfg80211: Add local-state-change-only auth/deauth/disassoc
cfg80211 is quite strict on allowing authentication and association commands only in certain states. In order to meet these requirements, user space applications may need to clear authentication or association state in some cases. Currently, this can be done with deauth/disassoc command, but that ends up sending out Deauthentication or Disassociation frame unnecessarily. Add a new nl80211 attribute to allow this sending of the frame be skipped, but with all other deauth/disassoc operations being completed. Similar state change is also needed for IEEE 802.11r FT protocol in the FT-over-DS case which does not use Authentication frame exchange in a transition to another BSS. For this to work with cfg80211, an authentication entry needs to be created for the target BSS without sending out an Authentication frame. The nl80211 authentication command can be used for this purpose, too, with the new attribute to indicate that the command is only for changing local state. This enables wpa_supplicant to complete FT-over-DS transition successfully. Signed-off-by: Jouni Malinen <j@w1.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 95149f303409..df5505b3930c 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -150,6 +150,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
150 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, }, 150 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
151 [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, 151 [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 },
152 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, 152 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
153 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
153}; 154};
154 155
155/* policy for the attributes */ 156/* policy for the attributes */
@@ -3393,6 +3394,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3393 int err, ssid_len, ie_len = 0; 3394 int err, ssid_len, ie_len = 0;
3394 enum nl80211_auth_type auth_type; 3395 enum nl80211_auth_type auth_type;
3395 struct key_parse key; 3396 struct key_parse key;
3397 bool local_state_change;
3396 3398
3397 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3399 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3398 return -EINVAL; 3400 return -EINVAL;
@@ -3471,9 +3473,12 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3471 goto out; 3473 goto out;
3472 } 3474 }
3473 3475
3476 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3477
3474 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 3478 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
3475 ssid, ssid_len, ie, ie_len, 3479 ssid, ssid_len, ie, ie_len,
3476 key.p.key, key.p.key_len, key.idx); 3480 key.p.key, key.p.key_len, key.idx,
3481 local_state_change);
3477 3482
3478out: 3483out:
3479 cfg80211_unlock_rdev(rdev); 3484 cfg80211_unlock_rdev(rdev);
@@ -3650,6 +3655,7 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
3650 const u8 *ie = NULL, *bssid; 3655 const u8 *ie = NULL, *bssid;
3651 int err, ie_len = 0; 3656 int err, ie_len = 0;
3652 u16 reason_code; 3657 u16 reason_code;
3658 bool local_state_change;
3653 3659
3654 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3660 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3655 return -EINVAL; 3661 return -EINVAL;
@@ -3695,7 +3701,10 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
3695 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 3701 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
3696 } 3702 }
3697 3703
3698 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code); 3704 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3705
3706 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
3707 local_state_change);
3699 3708
3700out: 3709out:
3701 cfg80211_unlock_rdev(rdev); 3710 cfg80211_unlock_rdev(rdev);
@@ -3712,6 +3721,7 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
3712 const u8 *ie = NULL, *bssid; 3721 const u8 *ie = NULL, *bssid;
3713 int err, ie_len = 0; 3722 int err, ie_len = 0;
3714 u16 reason_code; 3723 u16 reason_code;
3724 bool local_state_change;
3715 3725
3716 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3726 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3717 return -EINVAL; 3727 return -EINVAL;
@@ -3757,7 +3767,10 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
3757 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 3767 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
3758 } 3768 }
3759 3769
3760 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code); 3770 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3771
3772 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
3773 local_state_change);
3761 3774
3762out: 3775out:
3763 cfg80211_unlock_rdev(rdev); 3776 cfg80211_unlock_rdev(rdev);