}
+static void mlme_event_ft_event(struct wpa_driver_nl80211_data *drv,
+ struct nlattr *tb[])
+{
+ union wpa_event_data data;
+
+ os_memset(&data, 0, sizeof(data));
+
+ if (tb[NL80211_ATTR_IE]) {
+ data.ft_ies.ies = nla_data(tb[NL80211_ATTR_IE]);
+ data.ft_ies.ies_len = nla_len(tb[NL80211_ATTR_IE]);
+ }
+
+ if (tb[NL80211_ATTR_IE_RIC]) {
+ data.ft_ies.ric_ies = nla_data(tb[NL80211_ATTR_IE_RIC]);
+ data.ft_ies.ric_ies_len = nla_len(tb[NL80211_ATTR_IE_RIC]);
+ }
+
+ if (tb[NL80211_ATTR_MAC])
+ os_memcpy(data.ft_ies.target_ap,
+ nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
+
+ wpa_printf(MSG_DEBUG, "nl80211: FT event target_ap " MACSTR,
+ MAC2STR(data.ft_ies.target_ap));
+
+ wpa_supplicant_event(drv->ctx, EVENT_FT_RESPONSE, &data);
+}
+
+
static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
struct nlattr *tb[])
{
case NL80211_CMD_CONN_FAILED:
nl80211_connect_failed_event(drv, tb);
break;
+ case NL80211_CMD_FT_EVENT:
+ mlme_event_ft_event(drv, tb);
+ break;
default:
wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
"(cmd=%d)", cmd);
if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
params->key_mgmt_suite == KEY_MGMT_PSK ||
+ params->key_mgmt_suite == KEY_MGMT_FT_802_1X ||
+ params->key_mgmt_suite == KEY_MGMT_FT_PSK ||
params->key_mgmt_suite == KEY_MGMT_CCKM) {
int mgmt = WLAN_AKM_SUITE_PSK;
case KEY_MGMT_802_1X:
mgmt = WLAN_AKM_SUITE_8021X;
break;
+ case KEY_MGMT_FT_802_1X:
+ mgmt = WLAN_AKM_SUITE_FT_8021X;
+ break;
+ case KEY_MGMT_FT_PSK:
+ mgmt = WLAN_AKM_SUITE_FT_PSK;
+ break;
case KEY_MGMT_PSK:
default:
mgmt = WLAN_AKM_SUITE_PSK;
}
+static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md,
+ const u8 *ies, size_t ies_len)
+{
+ int ret;
+ struct nl_msg *msg;
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ u16 mdid = WPA_GET_LE16(md);
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Updating FT IEs");
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_UPDATE_FT_IES);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+ NLA_PUT(msg, NL80211_ATTR_IE, ies_len, ies);
+ NLA_PUT_U16(msg, NL80211_ATTR_MDID, mdid);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed "
+ "err=%d (%s)", ret, strerror(-ret));
+ }
+
+ return ret;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+
+
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
.send_tdls_mgmt = nl80211_send_tdls_mgmt,
.tdls_oper = nl80211_tdls_oper,
#endif /* CONFIG_TDLS */
+ .update_ft_ies = wpa_driver_nl80211_update_ft_ies,
};
{
int l, len, found = 0, wpa_found, rsn_found;
const u8 *p;
+ u8 bssid[ETH_ALEN];
wpa_dbg(wpa_s, MSG_DEBUG, "Association info event");
if (data->assoc_info.req_ies)
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_SME
if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) {
- u8 bssid[ETH_ALEN];
if (wpa_drv_get_bssid(wpa_s, bssid) < 0 ||
wpa_ft_validate_reassoc_resp(wpa_s->wpa,
data->assoc_info.resp_ies,
}
#endif /* CONFIG_SME */
+ /* Process FT when SME is in the driver */
+ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ wpa_ft_is_completed(wpa_s->wpa)) {
+ if (wpa_drv_get_bssid(wpa_s, bssid) < 0 ||
+ wpa_ft_validate_reassoc_resp(wpa_s->wpa,
+ data->assoc_info.resp_ies,
+ data->assoc_info.resp_ies_len,
+ bssid) < 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "FT: Validation of "
+ "Reassociation Response failed");
+ wpa_supplicant_deauthenticate(
+ wpa_s, WLAN_REASON_INVALID_IE);
+ return -1;
+ }
+ wpa_dbg(wpa_s, MSG_DEBUG, "FT: Reassociation Response done");
+ }
+
wpa_sm_set_ft_params(wpa_s->wpa, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len);
#endif /* CONFIG_IEEE80211R */