diff options
author | Jouni Malinen <jouni.malinen@atheros.com> | 2009-03-19 07:39:22 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-27 20:13:02 -0400 |
commit | 636a5d3625993c5ca59abc81794b9ded93cdb740 (patch) | |
tree | 53ee8d522153c36c631f8cb733a6e808c20ef332 /net/mac80211/mlme.c | |
parent | 6039f6d23fe792d615da5449e9fa1c6b43caacf6 (diff) |
nl80211: Add MLME primitives to support external SME
This patch adds new nl80211 commands to allow user space to request
authentication and association (and also deauthentication and
disassociation). The commands are structured to allow separate
authentication and association steps, i.e., the interface between
kernel and user space is similar to the MLME SAP interface in IEEE
802.11 standard and an user space application takes the role of the
SME.
The patch introduces MLME-AUTHENTICATE.request,
MLME-{,RE}ASSOCIATE.request, MLME-DEAUTHENTICATE.request, and
MLME-DISASSOCIATE.request primitives. The authentication and
association commands request the actual operations in two steps
(assuming the driver supports this; if not, separate authentication
step is skipped; this could end up being a separate "connect"
command).
The initial implementation for mac80211 uses the current
net/mac80211/mlme.c for actual sending and processing of management
frames and the new nl80211 commands will just stop the current state
machine from moving automatically from authentication to association.
Future cleanup may move more of the MLME operations into cfg80211.
The goal of this design is to provide more control of authentication and
association process to user space without having to move the full MLME
implementation. This should be enough to allow IEEE 802.11r FT protocol
and 802.11s SAE authentication to be implemented. Obviously, this will
also bring the extra benefit of not having to use WEXT for association
requests with mac80211. An example implementation of a user space SME
using the new nl80211 commands is available for wpa_supplicant.
This patch is enough to get IEEE 802.11r FT protocol working with
over-the-air mechanism (over-the-DS will need additional MLME
primitives for handling the FT Action frames).
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6dc7a61bc18b..d1bcc8438772 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -730,6 +730,8 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata) | |||
730 | { | 730 | { |
731 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 731 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
732 | struct ieee80211_local *local = sdata->local; | 732 | struct ieee80211_local *local = sdata->local; |
733 | u8 *ies; | ||
734 | size_t ies_len; | ||
733 | 735 | ||
734 | ifmgd->auth_tries++; | 736 | ifmgd->auth_tries++; |
735 | if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) { | 737 | if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) { |
@@ -755,7 +757,14 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata) | |||
755 | printk(KERN_DEBUG "%s: authenticate with AP %pM\n", | 757 | printk(KERN_DEBUG "%s: authenticate with AP %pM\n", |
756 | sdata->dev->name, ifmgd->bssid); | 758 | sdata->dev->name, ifmgd->bssid); |
757 | 759 | ||
758 | ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, NULL, 0, | 760 | if (ifmgd->flags & IEEE80211_STA_EXT_SME) { |
761 | ies = ifmgd->sme_auth_ie; | ||
762 | ies_len = ifmgd->sme_auth_ie_len; | ||
763 | } else { | ||
764 | ies = NULL; | ||
765 | ies_len = 0; | ||
766 | } | ||
767 | ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, ies, ies_len, | ||
759 | ifmgd->bssid, 0); | 768 | ifmgd->bssid, 0); |
760 | ifmgd->auth_transaction = 2; | 769 | ifmgd->auth_transaction = 2; |
761 | 770 | ||
@@ -870,7 +879,8 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata) | |||
870 | int wep_privacy; | 879 | int wep_privacy; |
871 | int privacy_invoked; | 880 | int privacy_invoked; |
872 | 881 | ||
873 | if (!ifmgd || (ifmgd->flags & IEEE80211_STA_MIXED_CELL)) | 882 | if (!ifmgd || (ifmgd->flags & (IEEE80211_STA_MIXED_CELL | |
883 | IEEE80211_STA_EXT_SME))) | ||
874 | return 0; | 884 | return 0; |
875 | 885 | ||
876 | bss = ieee80211_rx_bss_get(local, ifmgd->bssid, | 886 | bss = ieee80211_rx_bss_get(local, ifmgd->bssid, |
@@ -998,7 +1008,11 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata) | |||
998 | 1008 | ||
999 | printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); | 1009 | printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); |
1000 | ifmgd->flags |= IEEE80211_STA_AUTHENTICATED; | 1010 | ifmgd->flags |= IEEE80211_STA_AUTHENTICATED; |
1001 | ieee80211_associate(sdata); | 1011 | if (ifmgd->flags & IEEE80211_STA_EXT_SME) { |
1012 | /* Wait for SME to request association */ | ||
1013 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; | ||
1014 | } else | ||
1015 | ieee80211_associate(sdata); | ||
1002 | } | 1016 | } |
1003 | 1017 | ||
1004 | 1018 | ||
@@ -1084,6 +1098,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1084 | switch (ifmgd->auth_alg) { | 1098 | switch (ifmgd->auth_alg) { |
1085 | case WLAN_AUTH_OPEN: | 1099 | case WLAN_AUTH_OPEN: |
1086 | case WLAN_AUTH_LEAP: | 1100 | case WLAN_AUTH_LEAP: |
1101 | case WLAN_AUTH_FT: | ||
1087 | ieee80211_auth_completed(sdata); | 1102 | ieee80211_auth_completed(sdata); |
1088 | cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len); | 1103 | cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len); |
1089 | break; | 1104 | break; |
@@ -1117,9 +1132,10 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1117 | printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n", | 1132 | printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n", |
1118 | sdata->dev->name, reason_code); | 1133 | sdata->dev->name, reason_code); |
1119 | 1134 | ||
1120 | if (ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE || | 1135 | if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) && |
1121 | ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE || | 1136 | (ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE || |
1122 | ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) { | 1137 | ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE || |
1138 | ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)) { | ||
1123 | ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE; | 1139 | ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE; |
1124 | mod_timer(&ifmgd->timer, jiffies + | 1140 | mod_timer(&ifmgd->timer, jiffies + |
1125 | IEEE80211_RETRY_AUTH_INTERVAL); | 1141 | IEEE80211_RETRY_AUTH_INTERVAL); |
@@ -1150,7 +1166,8 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1150 | printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", | 1166 | printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", |
1151 | sdata->dev->name, reason_code); | 1167 | sdata->dev->name, reason_code); |
1152 | 1168 | ||
1153 | if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) { | 1169 | if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) && |
1170 | ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) { | ||
1154 | ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE; | 1171 | ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE; |
1155 | mod_timer(&ifmgd->timer, jiffies + | 1172 | mod_timer(&ifmgd->timer, jiffies + |
1156 | IEEE80211_RETRY_AUTH_INTERVAL); | 1173 | IEEE80211_RETRY_AUTH_INTERVAL); |
@@ -1664,6 +1681,8 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata) | |||
1664 | ifmgd->auth_alg = WLAN_AUTH_SHARED_KEY; | 1681 | ifmgd->auth_alg = WLAN_AUTH_SHARED_KEY; |
1665 | else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP) | 1682 | else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP) |
1666 | ifmgd->auth_alg = WLAN_AUTH_LEAP; | 1683 | ifmgd->auth_alg = WLAN_AUTH_LEAP; |
1684 | else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_FT) | ||
1685 | ifmgd->auth_alg = WLAN_AUTH_FT; | ||
1667 | else | 1686 | else |
1668 | ifmgd->auth_alg = WLAN_AUTH_OPEN; | 1687 | ifmgd->auth_alg = WLAN_AUTH_OPEN; |
1669 | ifmgd->auth_transaction = -1; | 1688 | ifmgd->auth_transaction = -1; |
@@ -1687,7 +1706,8 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata) | |||
1687 | u16 capa_val = WLAN_CAPABILITY_ESS; | 1706 | u16 capa_val = WLAN_CAPABILITY_ESS; |
1688 | struct ieee80211_channel *chan = local->oper_channel; | 1707 | struct ieee80211_channel *chan = local->oper_channel; |
1689 | 1708 | ||
1690 | if (ifmgd->flags & (IEEE80211_STA_AUTO_SSID_SEL | | 1709 | if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) && |
1710 | ifmgd->flags & (IEEE80211_STA_AUTO_SSID_SEL | | ||
1691 | IEEE80211_STA_AUTO_BSSID_SEL | | 1711 | IEEE80211_STA_AUTO_BSSID_SEL | |
1692 | IEEE80211_STA_AUTO_CHANNEL_SEL)) { | 1712 | IEEE80211_STA_AUTO_CHANNEL_SEL)) { |
1693 | capa_mask |= WLAN_CAPABILITY_PRIVACY; | 1713 | capa_mask |= WLAN_CAPABILITY_PRIVACY; |
@@ -1884,7 +1904,11 @@ void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata) | |||
1884 | ieee80211_set_disassoc(sdata, true, true, | 1904 | ieee80211_set_disassoc(sdata, true, true, |
1885 | WLAN_REASON_DEAUTH_LEAVING); | 1905 | WLAN_REASON_DEAUTH_LEAVING); |
1886 | 1906 | ||
1887 | set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); | 1907 | if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) || |
1908 | ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE) | ||
1909 | set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); | ||
1910 | else if (ifmgd->flags & IEEE80211_STA_EXT_SME) | ||
1911 | set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request); | ||
1888 | queue_work(local->hw.workqueue, &ifmgd->work); | 1912 | queue_work(local->hw.workqueue, &ifmgd->work); |
1889 | } | 1913 | } |
1890 | } | 1914 | } |
@@ -1953,7 +1977,8 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) | |||
1953 | return ieee80211_sta_commit(sdata); | 1977 | return ieee80211_sta_commit(sdata); |
1954 | } | 1978 | } |
1955 | 1979 | ||
1956 | int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) | 1980 | int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, |
1981 | const char *ie, size_t len) | ||
1957 | { | 1982 | { |
1958 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1983 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1959 | 1984 | ||