diff options
author | Jouni Malinen <j@w1.fi> | 2010-04-04 02:37:19 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-04-07 14:37:56 -0400 |
commit | d5cdfacb35ed886271d1ccfffbded98d3447da17 (patch) | |
tree | 8233a713949c4c8da8c98e75868efc74d5613c3d /net/wireless/nl80211.c | |
parent | 7590a550b88b8c3cb025f0a8ed58e279ad62e4c1 (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.c | 19 |
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 | ||
3478 | out: | 3483 | out: |
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 | ||
3700 | out: | 3709 | out: |
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 | ||
3762 | out: | 3775 | out: |
3763 | cfg80211_unlock_rdev(rdev); | 3776 | cfg80211_unlock_rdev(rdev); |