We set the cipher_pairwise and cipher_group to WEP104 only if they
are not set already. Otherwise WEP40 has no way to be configured.
This problem is found on 802.1X with static WEP.
Signed-off-by: Zhu Yi <[email protected]>
---
wpa_supplicant/wpa_supplicant.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index d03e9da..f1f929a 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1116,7 +1116,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
!wep_keys_set) {
use_crypt = 0;
- } else {
+ } else if (cipher_pairwise == WPA_CIPHER_NONE &&
+ cipher_group == WPA_CIPHER_NONE) {
/* Assume that dynamic WEP-104 keys will be used and
* set cipher suites in order for drivers to expect
* encryption. */
--
1.6.0.4
On Thu, Aug 13, 2009 at 05:29:37PM +0800, Zhu Yi wrote:
> The connect API wraps auth/assoc commands in cfg80211 SME. For example,
> when cfg80211 receives NL80211_CMD_CONNECT (cfg80211_connect), it checks
> if connect API is supported or not. If it is not supported (for all
> mac80211 based drivers), it uses the common cfg80211_conn_do_work() to
> do auth/assoc the same way as it handles NL80211_CMD_AUTHENTICATE. So
> from user space point of view, if connect API is supported, it can use
> it directly and let cfg80211 to maintain the state of auth and assoc.
It is not about whether it would be possible to use connect or not; it
is about whether the additional features provided by separate auth/assoc
commands are of use--and they are. wpa_supplicant will provide more
functionality, e.g., FT, when using these commands. Any change to add
support for the new NL80211_CMD_CONNECT must not break this existing
mechanism; it is only to add support for drivers that cannot support the
auth/assoc interface that provides more control to user space.
--
Jouni Malinen PGP id EFC895FA
On Fri, 2009-08-14 at 12:17 +0800, Zhu Yi wrote:
> Johannes, I think we need a way in cfg80211 to tell connect vs.
> auth/assoc. The current capability method (nl80211_send_wiphy) cannot do
> this. For example,
>
> if (dev->ops->connect || dev->ops->auth)
> NLA_PUT_U32(msg, i, NL80211_CMD_CONNECT);
>
> We need to either make NL80211_CMD_CONNECT only depends on ops->connect
> or make NL80211_CMD_AUTH depends on ops->auth. Johannes, which one do
> you prefer?
The latter is already there as far as I can see?
CMD(auth, AUTHENTICATE);
CMD(assoc, ASSOCIATE);
CMD(deauth, DEAUTHENTICATE);
CMD(disassoc, DISASSOCIATE);
so you should be able to check for these.
johannes
On Fri, 2009-08-14 at 13:50 +0800, Johannes Berg wrote:
> On Fri, 2009-08-14 at 12:17 +0800, Zhu Yi wrote:
>
> > Johannes, I think we need a way in cfg80211 to tell connect vs.
> > auth/assoc. The current capability method (nl80211_send_wiphy) cannot do
> > this. For example,
> >
> > if (dev->ops->connect || dev->ops->auth)
> > NLA_PUT_U32(msg, i, NL80211_CMD_CONNECT);
> >
> > We need to either make NL80211_CMD_CONNECT only depends on ops->connect
> > or make NL80211_CMD_AUTH depends on ops->auth. Johannes, which one do
> > you prefer?
>
> The latter is already there as far as I can see?
>
> CMD(auth, AUTHENTICATE);
> CMD(assoc, ASSOCIATE);
> CMD(deauth, DEAUTHENTICATE);
> CMD(disassoc, DISASSOCIATE);
>
> so you should be able to check for these.
My bad. I'll use NL80211_CMD_AUTHENTICATE.
Thanks,
-yi
On Thu, Aug 13, 2009 at 04:55:31PM +0800, Zhu Yi wrote:
> - * authenticate - Request driver to authenticate
> + * authenticate - Request driver to authenticate (deprecated)
> + * This is an optional function that to make compatibility for wireless
> + * stack that doesn't support connect API when driver SME is used
> + * (WPA_DRIVER_FLAGS_SME).
Thanks for the patch. If I understood this correctly, wpa_supplicant
would be converted to use the new connect command whenever it is
supported. While it is nice to get support for connect added, this is
not how it should be done as it breaks all the new work we have been
enabling with mac80211. The separate auth/assoc commands should be the
default operation and only if the driver does not support this, should
the connect command be used.
--
Jouni Malinen PGP id EFC895FA
Hi Jouni,
On Thu, 2009-08-13 at 17:11 +0800, Jouni Malinen wrote:
> On Thu, Aug 13, 2009 at 04:55:31PM +0800, Zhu Yi wrote:
>
> > - * authenticate - Request driver to authenticate
> > + * authenticate - Request driver to authenticate (deprecated)
>
> > + * This is an optional function that to make compatibility for wireless
> > + * stack that doesn't support connect API when driver SME is used
> > + * (WPA_DRIVER_FLAGS_SME).
>
> Thanks for the patch. If I understood this correctly, wpa_supplicant
> would be converted to use the new connect command whenever it is
> supported. While it is nice to get support for connect added, this is
> not how it should be done as it breaks all the new work we have been
> enabling with mac80211. The separate auth/assoc commands should be the
> default operation and only if the driver does not support this, should
> the connect command be used.
The connect API wraps auth/assoc commands in cfg80211 SME. For example,
when cfg80211 receives NL80211_CMD_CONNECT (cfg80211_connect), it checks
if connect API is supported or not. If it is not supported (for all
mac80211 based drivers), it uses the common cfg80211_conn_do_work() to
do auth/assoc the same way as it handles NL80211_CMD_AUTHENTICATE. So
from user space point of view, if connect API is supported, it can use
it directly and let cfg80211 to maintain the state of auth and assoc.
Thanks,
-yi
On Thu, 2009-08-13 at 18:46 +0800, Jouni Malinen wrote:
> It is not about whether it would be possible to use connect or not; it
> is about whether the additional features provided by separate auth/assoc
> commands are of use--and they are. wpa_supplicant will provide more
> functionality, e.g., FT, when using these commands. Any change to add
> support for the new NL80211_CMD_CONNECT must not break this existing
> mechanism; it is only to add support for drivers that cannot support the
> auth/assoc interface that provides more control to user space.
Ah, I see. This makes sense to me. I ignored the 11r code when I wrote
the code. Now I realized what it is used for (i.e. sme_event_auth). I'm
not sure if it can be done in cfg80211 SME easily, but it doesn't help
for connect API anyway. I'll send V2 according to your suggestion.
Johannes, I think we need a way in cfg80211 to tell connect vs.
auth/assoc. The current capability method (nl80211_send_wiphy) cannot do
this. For example,
if (dev->ops->connect || dev->ops->auth)
NLA_PUT_U32(msg, i, NL80211_CMD_CONNECT);
We need to either make NL80211_CMD_CONNECT only depends on ops->connect
or make NL80211_CMD_AUTH depends on ops->auth. Johannes, which one do
you prefer?
Thanks,
-yi
Cc: Johannes Berg <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Signed-off-by: Zhu Yi <[email protected]>
---
src/common/ieee802_11_defs.h | 15 ++
src/common/nl80211_copy.h | 65 +++++++++
src/drivers/driver.h | 28 +++-
src/drivers/driver_nl80211.c | 289 ++++++++++++++++++++++++++++++++++++-
wpa_supplicant/driver_i.h | 18 +++
wpa_supplicant/sme.c | 43 +++++--
wpa_supplicant/sme.h | 15 ++-
wpa_supplicant/wpa_supplicant.c | 9 +-
wpa_supplicant/wpa_supplicant_i.h | 2 +
9 files changed, 455 insertions(+), 29 deletions(-)
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index b4c804e..e1bd487 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -679,4 +679,19 @@ enum {
#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
+/* cipher suite selectors */
+#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00
+#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01
+#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02
+/* reserved: 0x000FAC03 */
+#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
+#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
+#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
+
+/* AKM suite selectors */
+#define WLAN_AKM_SUITE_8021X 0x000FAC01
+#define WLAN_AKM_SUITE_PSK 0x000FAC02
+
+#define WLAN_MAX_KEY_LEN 32
+
#endif /* IEEE802_11_DEFS_H */
diff --git a/src/common/nl80211_copy.h b/src/common/nl80211_copy.h
index dbea93b..c019a16 100644
--- a/src/common/nl80211_copy.h
+++ b/src/common/nl80211_copy.h
@@ -310,6 +310,14 @@ enum nl80211_commands {
NL80211_CMD_JOIN_IBSS,
NL80211_CMD_LEAVE_IBSS,
+ NL80211_CMD_TESTMODE,
+
+ NL80211_CMD_CONNECT,
+ NL80211_CMD_ROAM,
+ NL80211_CMD_DISCONNECT,
+
+ NL80211_CMD_SET_WIPHY_NETNS,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -619,6 +627,28 @@ enum nl80211_attrs {
NL80211_ATTR_CONTROL_PORT,
+ NL80211_ATTR_TESTDATA,
+
+ NL80211_ATTR_PRIVACY,
+
+ NL80211_ATTR_DISCONNECTED_BY_AP,
+ NL80211_ATTR_STATUS_CODE,
+
+ NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
+ NL80211_ATTR_CIPHER_SUITE_GROUP,
+ NL80211_ATTR_WPA_VERSIONS,
+ NL80211_ATTR_AKM_SUITES,
+
+ NL80211_ATTR_REQ_IE,
+ NL80211_ATTR_RESP_IE,
+
+ NL80211_ATTR_PREV_BSSID,
+
+ NL80211_ATTR_KEY,
+ NL80211_ATTR_KEYS,
+
+ NL80211_ATTR_PID,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -1224,4 +1254,39 @@ enum nl80211_mfp {
NL80211_MFP_REQUIRED,
};
+enum nl80211_wpa_versions {
+ NL80211_WPA_VERSION_1 = 1 << 0,
+ NL80211_WPA_VERSION_2 = 1 << 1,
+};
+
+/**
+ * enum nl80211_key_attributes - key attributes
+ * @__NL80211_KEY_INVALID: invalid
+ * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of
+ * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC
+ * keys
+ * @NL80211_KEY_IDX: key ID (u8, 0-3)
+ * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11
+ * section 7.3.2.25.1, e.g. 0x000FAC04)
+ * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
+ * CCMP keys, each six bytes in little endian
+ * @NL80211_KEY_DEFAULT: flag indicating default key
+ * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key
+ * @__NL80211_KEY_AFTER_LAST: internal
+ * @NL80211_KEY_MAX: highest key attribute
+ */
+enum nl80211_key_attributes {
+ __NL80211_KEY_INVALID,
+ NL80211_KEY_DATA,
+ NL80211_KEY_IDX,
+ NL80211_KEY_CIPHER,
+ NL80211_KEY_SEQ,
+ NL80211_KEY_DEFAULT,
+ NL80211_KEY_DEFAULT_MGMT,
+
+ /* keep last */
+ __NL80211_KEY_AFTER_LAST,
+ NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 2ae5b1a..cc56124 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -444,6 +444,8 @@ struct wpa_driver_capa {
#define WPA_DRIVER_FLAGS_SME 0x00000020
/* Driver supports AP mode */
#define WPA_DRIVER_FLAGS_AP 0x00000040
+/* Driver supports connect API */
+#define WPA_DRIVER_FLAGS_CONNECT 0x00000080
unsigned int flags;
int max_scan_ssids;
@@ -1184,16 +1186,14 @@ struct wpa_driver_ops {
int (*scan2)(void *priv, struct wpa_driver_scan_params *params);
/**
- * authenticate - Request driver to authenticate
+ * authenticate - Request driver to authenticate (deprecated)
* @priv: private driver interface data
* @params: authentication parameters
* Returns: 0 on success, -1 on failure
*
- * This is an optional function that can be used with drivers that
- * support separate authentication and association steps, i.e., when
- * wpa_supplicant can act as the SME. If not implemented, associate()
- * function is expected to take care of IEEE 802.11 authentication,
- * too.
+ * This is an optional function that to make compatibility for wireless
+ * stack that doesn't support connect API when driver SME is used
+ * (WPA_DRIVER_FLAGS_SME).
*/
int (*authenticate)(void *priv,
struct wpa_driver_auth_params *params);
@@ -1333,6 +1333,22 @@ struct wpa_driver_ops {
* Returns: 0 on success, -1 on failure
*/
int (*set_supp_port)(void *priv, int authorized);
+
+ /**
+ * connect - Request driver to connect
+ * @priv: private driver interface data
+ * @params: connect parameters
+ * Returns: 0 on success, -1 on failure
+ *
+ * This is an optional function that can be used with drivers that
+ * support connect (both authentication and association) step, i.e.,
+ * when wpa_supplicant can act as the SME. If driver SME is not
+ * supported (both connect and authenticate are not implemented),
+ * associate() function is expected to take care of IEEE 802.11
+ * authentication, too.
+ */
+ int (*connect)(void *priv, struct wpa_driver_associate_params *params);
+ int (*disconnect)(void *priv, u8 *addr, int reason_code);
};
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 9b2bf7c..ca3670c 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -739,6 +739,40 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
}
+static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
+ enum nl80211_commands cmd, struct nlattr *status,
+ struct nlattr *addr, struct nlattr *req_ie,
+ struct nlattr *resp_ie)
+{
+ union wpa_event_data event;
+
+ os_memset(&event, 0, sizeof(event));
+ if (cmd == NL80211_CMD_CONNECT &&
+ nla_get_u16(status) != WLAN_STATUS_SUCCESS) {
+ if (resp_ie) {
+ event.assoc_reject.resp_ies = nla_data(resp_ie);
+ event.assoc_reject.resp_ies_len = nla_len(resp_ie);
+ }
+ event.assoc_reject.status_code = nla_get_u16(status);
+ wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
+ return;
+ }
+
+ drv->associated = 1;
+ if (addr)
+ os_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);
+
+ if (req_ie) {
+ event.assoc_info.req_ies = nla_data(req_ie);
+ event.assoc_info.req_ies_len = nla_len(req_ie);
+ }
+ if (resp_ie) {
+ event.assoc_info.resp_ies = nla_data(resp_ie);
+ event.assoc_info.resp_ies_len = nla_len(resp_ie);
+ }
+
+ wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
+}
static void mlme_timeout_event(struct wpa_driver_nl80211_data *drv,
enum nl80211_commands cmd, struct nlattr *addr)
@@ -895,6 +929,17 @@ static int process_event(struct nl_msg *msg, void *arg)
mlme_event(drv, gnlh->cmd, tb[NL80211_ATTR_FRAME],
tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT]);
break;
+ case NL80211_CMD_CONNECT:
+ case NL80211_CMD_ROAM:
+ mlme_event_connect(drv, gnlh->cmd, tb[NL80211_ATTR_STATUS_CODE],
+ tb[NL80211_ATTR_MAC],
+ tb[NL80211_ATTR_REQ_IE],
+ tb[NL80211_ATTR_RESP_IE]);
+ break;
+ case NL80211_CMD_DISCONNECT:
+ drv->associated = 0;
+ wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
+ break;
#endif /* HOSTAPD */
case NL80211_CMD_MICHAEL_MIC_FAILURE:
mlme_event_michael_mic_failure(drv, tb);
@@ -1003,6 +1048,7 @@ nla_put_failure:
struct wiphy_info_data {
int max_scan_ssids;
int ap_supported;
+ int connect_supported;
};
@@ -1031,6 +1077,19 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
}
}
+ info->connect_supported = 0;
+ if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) {
+ struct nlattr *nl_cmd;
+ int i;
+
+ nla_for_each_nested(nl_cmd,
+ tb[NL80211_ATTR_SUPPORTED_COMMANDS], i)
+ if (nla_get_u32(nl_cmd) == NL80211_CMD_CONNECT) {
+ info->connect_supported = 1;
+ break;
+ }
+ }
+
return NL_SKIP;
}
@@ -1078,6 +1137,9 @@ static void wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
drv->capa.max_scan_ssids = info.max_scan_ssids;
if (info.ap_supported)
drv->capa.flags |= WPA_DRIVER_FLAGS_AP;
+
+ if (info.connect_supported)
+ drv->capa.flags |= WPA_DRIVER_FLAGS_CONNECT;
}
#endif /* HOSTAPD */
@@ -1658,19 +1720,22 @@ static int nl_set_encr(int ifindex, struct wpa_driver_nl80211_data *drv,
case WPA_ALG_WEP:
if (key_len == 5)
NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
- 0x000FAC01);
+ WLAN_CIPHER_SUITE_WEP40);
else
NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
- 0x000FAC05);
+ WLAN_CIPHER_SUITE_WEP104);
break;
case WPA_ALG_TKIP:
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC02);
+ NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
+ WLAN_CIPHER_SUITE_TKIP);
break;
case WPA_ALG_CCMP:
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC04);
+ NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
+ WLAN_CIPHER_SUITE_CCMP);
break;
case WPA_ALG_IGTK:
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC06);
+ NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
+ WLAN_CIPHER_SUITE_AES_CMAC);
break;
default:
wpa_printf(MSG_ERROR, "%s: Unsupported encryption "
@@ -1737,6 +1802,60 @@ nla_put_failure:
#ifndef HOSTAPD
+static int nl80211_set_conn_keys(void *priv,
+ struct wpa_driver_associate_params *params,
+ struct nl_msg *msg)
+{
+ int i, privacy = 0;
+ struct nlattr *nl_keys, *nl_key;
+
+ for (i = 0; i < 4; i++) {
+ if (!params->wep_key[i])
+ continue;
+ privacy = 1;
+ break;
+ }
+ if (!privacy)
+ return 0;
+
+ NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
+
+ nl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
+ if (!nl_keys)
+ goto nla_put_failure;
+
+ for (i = 0; i < 4; i++) {
+ if (!params->wep_key[i])
+ continue;
+
+ nl_key = nla_nest_start(msg, i);
+ if (!nl_key)
+ goto nla_put_failure;
+
+ NLA_PUT(msg, NL80211_KEY_DATA, params->wep_key_len[i],
+ params->wep_key[i]);
+ if (params->wep_key_len[i] == 5)
+ NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
+ WLAN_CIPHER_SUITE_WEP40);
+ else
+ NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
+ WLAN_CIPHER_SUITE_WEP104);
+
+ NLA_PUT_U8(msg, NL80211_KEY_IDX, i);
+
+ if (i == params->wep_tx_keyidx)
+ NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
+
+ nla_nest_end(msg, nl_key);
+ }
+ nla_nest_end(msg, nl_keys);
+
+ return 0;
+
+nla_put_failure:
+ return -ENOBUFS;
+}
+
static int wpa_driver_nl80211_set_key(void *priv, wpa_alg alg,
const u8 *addr, int key_idx,
int set_tx, const u8 *seq,
@@ -1883,6 +2002,164 @@ nla_put_failure:
return ret;
}
+static int wpa_driver_nl80211_connect(
+ void *priv, struct wpa_driver_associate_params *params)
+{
+ struct wpa_driver_nl80211_data *drv = priv;
+ struct nl_msg *msg;
+ enum nl80211_auth_type type;
+ int ret = 0;
+
+ if (!(drv->capa.flags & WPA_DRIVER_FLAGS_CONNECT))
+ return -EOPNOTSUPP;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -1;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
+ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
+ NL80211_CMD_CONNECT, 0);
+
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+ if (params->bssid) {
+ wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
+ MAC2STR(params->bssid));
+ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
+ }
+ if (params->freq) {
+ wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
+ }
+ if (params->ssid) {
+ wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
+ params->ssid, params->ssid_len);
+ NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
+ params->ssid);
+ if (params->ssid_len > sizeof(drv->ssid))
+ goto nla_put_failure;
+ os_memcpy(drv->ssid, params->ssid, params->ssid_len);
+ drv->ssid_len = params->ssid_len;
+ }
+ wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len);
+ if (params->wpa_ie)
+ NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
+ params->wpa_ie);
+
+ if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM)
+ type = NL80211_AUTHTYPE_OPEN_SYSTEM;
+ else if (params->auth_alg & AUTH_ALG_SHARED_KEY)
+ type = NL80211_AUTHTYPE_SHARED_KEY;
+ else if (params->auth_alg & AUTH_ALG_LEAP)
+ type = NL80211_AUTHTYPE_NETWORK_EAP;
+ else if (params->auth_alg & AUTH_ALG_FT)
+ type = NL80211_AUTHTYPE_FT;
+ else
+ goto nla_put_failure;
+
+ wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
+ NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);
+
+ if (params->wpa_ie && params->wpa_ie_len) {
+ enum nl80211_wpa_versions ver;
+
+ if (params->wpa_ie[0] == WLAN_EID_RSN)
+ ver = NL80211_WPA_VERSION_2;
+ else
+ ver = NL80211_WPA_VERSION_1;
+
+ wpa_printf(MSG_DEBUG, " * WPA Version %d", ver);
+ NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
+ }
+
+ if (params->pairwise_suite != CIPHER_NONE) {
+ int cipher = IW_AUTH_CIPHER_NONE;
+
+ switch (params->pairwise_suite) {
+ case CIPHER_WEP40:
+ cipher = WLAN_CIPHER_SUITE_WEP40;
+ break;
+ case CIPHER_WEP104:
+ cipher = WLAN_CIPHER_SUITE_WEP104;
+ break;
+ case CIPHER_CCMP:
+ cipher = WLAN_CIPHER_SUITE_CCMP;
+ break;
+ case CIPHER_TKIP:
+ default:
+ cipher = WLAN_CIPHER_SUITE_TKIP;
+ break;
+ }
+ NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);
+ }
+
+ if (params->group_suite != CIPHER_NONE) {
+ int cipher = IW_AUTH_CIPHER_NONE;
+
+ switch (params->group_suite) {
+ case CIPHER_WEP40:
+ cipher = WLAN_CIPHER_SUITE_WEP40;
+ break;
+ case CIPHER_WEP104:
+ cipher = WLAN_CIPHER_SUITE_WEP104;
+ break;
+ case CIPHER_CCMP:
+ cipher = WLAN_CIPHER_SUITE_CCMP;
+ break;
+ case CIPHER_TKIP:
+ default:
+ cipher = WLAN_CIPHER_SUITE_TKIP;
+ break;
+ }
+ NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);
+ }
+
+ if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
+ params->key_mgmt_suite == KEY_MGMT_PSK) {
+ int mgmt = WLAN_AKM_SUITE_PSK;
+
+ switch (params->key_mgmt_suite) {
+ case KEY_MGMT_802_1X:
+ mgmt = WLAN_AKM_SUITE_8021X;
+ break;
+ case KEY_MGMT_PSK:
+ default:
+ mgmt = WLAN_AKM_SUITE_PSK;
+ break;
+ }
+ NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, mgmt);
+ }
+
+ ret = nl80211_set_conn_keys(drv, params, msg);
+ if (ret)
+ goto nla_put_failure;
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
+ "(%s)", ret, strerror(-ret));
+ goto nla_put_failure;
+ }
+ ret = 0;
+ wpa_printf(MSG_DEBUG, "nl80211: Connect request send successfully");
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return ret;
+
+}
+
+static int wpa_driver_nl80211_disconnect(void *priv, u8 *addr, int reason_code)
+{
+ struct wpa_driver_nl80211_data *drv = priv;
+
+ wpa_printf(MSG_DEBUG, "%s", __func__);
+ drv->associated = 0;
+ return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DISCONNECT,
+ reason_code);
+}
+
#endif /* HOSTAPD */
@@ -4060,6 +4337,8 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.get_capa = wpa_driver_nl80211_get_capa,
.set_operstate = wpa_driver_nl80211_set_operstate,
.set_supp_port = wpa_driver_nl80211_set_supp_port,
+ .connect = wpa_driver_nl80211_connect,
+ .disconnect = wpa_driver_nl80211_disconnect,
#endif /* HOSTAPD */
.set_country = wpa_driver_nl80211_set_country,
.set_mode = wpa_driver_nl80211_set_mode,
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 4cb5372..8e59de2 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -448,4 +448,22 @@ static inline int wpa_drv_set_supp_port(struct wpa_supplicant *wpa_s,
return 0;
}
+static inline int wpa_drv_connect(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_associate_params *params)
+{
+ if (wpa_s->driver->connect)
+ return wpa_s->driver->connect(wpa_s->drv_priv, params);
+
+ return -EOPNOTSUPP;
+}
+
+static inline int wpa_drv_disconnect(struct wpa_supplicant *wpa_s, u8 *addr,
+ int reason_code)
+{
+ if (wpa_s->driver->disconnect)
+ return wpa_s->driver->disconnect(wpa_s->drv_priv, addr,
+ reason_code);
+ return -EOPNOTSUPP;
+}
+
#endif /* DRIVER_I_H */
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 0d729ef..3582c20 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -27,10 +27,10 @@
#include "wps_supplicant.h"
#include "sme.h"
-void sme_authenticate(struct wpa_supplicant *wpa_s,
- struct wpa_scan_res *bss, struct wpa_ssid *ssid)
+void sme_connect(struct wpa_supplicant *wpa_s, struct wpa_scan_res *bss,
+ struct wpa_ssid *ssid)
{
- struct wpa_driver_auth_params params;
+ struct wpa_driver_associate_params params;
const u8 *ie;
#ifdef CONFIG_IEEE80211R
const u8 *md = NULL;
@@ -181,8 +181,6 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
wpa_printf(MSG_DEBUG, "SME: Trying to use FT "
"over-the-air");
params.auth_alg = AUTH_ALG_FT;
- params.ie = wpa_s->sme.ft_ies;
- params.ie_len = wpa_s->sme.ft_ies_len;
}
}
#endif /* CONFIG_IEEE80211R */
@@ -224,10 +222,37 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
wpa_supplicant_initiate_eapol(wpa_s);
- if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) {
- wpa_msg(wpa_s, MSG_INFO, "Authentication request to the "
- "driver failed");
- return;
+ params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt);
+ params.wpa_ie = wpa_s->sme.assoc_req_ie;
+ params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
+ params.pairwise_suite = cipher_suite2driver(wpa_s->pairwise_cipher);
+ params.group_suite = cipher_suite2driver(wpa_s->group_cipher);
+
+ if (wpa_drv_connect(wpa_s, ¶ms) == -EOPNOTSUPP) {
+ struct wpa_driver_auth_params auth;
+
+ os_memset(&auth, 0, sizeof(auth));
+ auth.freq = params.freq;
+ auth.bssid = params.bssid;
+ auth.ssid = params.ssid;
+ auth.ssid_len = params.ssid_len;
+ auth.auth_alg = params.auth_alg;
+ if (auth.auth_alg == AUTH_ALG_FT) {
+ auth.ie = wpa_s->sme.ft_ies;
+ auth.ie_len = wpa_s->sme.ft_ies_len;
+ }
+ for (i = 0; i < NUM_WEP_KEYS; i++) {
+ if (params.wep_key_len[i])
+ auth.wep_key[i] = params.wep_key[i];
+ auth.wep_key_len[i] = params.wep_key_len[i];
+ }
+ auth.wep_tx_keyidx = params.wep_tx_keyidx;
+
+ if (wpa_drv_authenticate(wpa_s, &auth) < 0) {
+ wpa_msg(wpa_s, MSG_INFO, "Authentication request to "
+ "the driver failed");
+ return;
+ }
}
/* TODO: add timeout on authentication */
diff --git a/wpa_supplicant/sme.h b/wpa_supplicant/sme.h
index 2780041..87804e3 100644
--- a/wpa_supplicant/sme.h
+++ b/wpa_supplicant/sme.h
@@ -17,8 +17,8 @@
#ifdef CONFIG_SME
-void sme_authenticate(struct wpa_supplicant *wpa_s,
- struct wpa_scan_res *bss, struct wpa_ssid *ssid);
+void sme_connect(struct wpa_supplicant *wpa_s, struct wpa_scan_res *bss,
+ struct wpa_ssid *ssid);
void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data);
int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
const u8 *ies, size_t ies_len);
@@ -31,9 +31,9 @@ void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
#else /* CONFIG_SME */
-static inline void sme_authenticate(struct wpa_supplicant *wpa_s,
- struct wpa_scan_res *bss,
- struct wpa_ssid *ssid)
+static inline void sme_connect(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_res *bss,
+ struct wpa_ssid *ssid)
{
}
@@ -64,6 +64,11 @@ static inline void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
{
}
+void sme_connect(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_res *bss, struct wpa_ssid *ssid);
+{
+}
+
#endif /* CONFIG_SME */
#endif /* SME_H */
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index f1f929a..3797955 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -640,7 +640,7 @@ static void wpa_supplicant_reconfig(int sig, void *eloop_ctx,
}
-static wpa_cipher cipher_suite2driver(int cipher)
+wpa_cipher cipher_suite2driver(int cipher)
{
switch (cipher) {
case WPA_CIPHER_NONE:
@@ -658,7 +658,7 @@ static wpa_cipher cipher_suite2driver(int cipher)
}
-static wpa_key_mgmt key_mgmt2driver(int key_mgmt)
+wpa_key_mgmt key_mgmt2driver(int key_mgmt)
{
switch (key_mgmt) {
case WPA_KEY_MGMT_NONE:
@@ -966,7 +966,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
}
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
- sme_authenticate(wpa_s, bss, ssid);
+ sme_connect(wpa_s, bss, ssid);
return;
}
@@ -1303,7 +1303,8 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
if (!is_zero_ether_addr(wpa_s->bssid)) {
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
ieee80211_sta_deauthenticate(wpa_s, reason_code);
- else
+ else if (wpa_drv_disconnect(wpa_s, wpa_s->bssid, reason_code)
+ == -EOPNOTSUPP)
wpa_drv_deauthenticate(wpa_s, wpa_s->bssid,
reason_code);
addr = wpa_s->bssid;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 63984d8..13896d9 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -392,6 +392,8 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s);
const char * wpa_supplicant_state_txt(int state);
int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s);
+wpa_cipher cipher_suite2driver(int cipher);
+wpa_key_mgmt key_mgmt2driver(int key_mgmt);
int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
struct wpa_scan_res *bss,
struct wpa_ssid *ssid,
--
1.6.0.4