18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - Glue code to setup EAPOL and RSN modules
3807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_supp/eapol_supp_sm.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "l2_packet/l2_packet.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_common.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver_i.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/pmksa_cache.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sme.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_ctrl.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpas_glue.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_supplicant.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "bss.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "scan.h"
28c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt#include "notify.h"
295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "wpas_kay.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA)
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_set_config_blob(void *ctx,
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   struct wpa_config_blob *blob)
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_set_blob(wpa_s->conf, blob);
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->conf->update_config) {
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret) {
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Failed to update config after "
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "blob set");
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const struct wpa_config_blob *
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_get_config_blob(void *ctx, const char *name)
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_config_get_blob(wpa_s->conf, name);
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) */
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA)
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type,
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const void *data, u16 data_len,
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    size_t *msg_len, void **data_pos)
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_1x_hdr *hdr;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*msg_len = sizeof(*hdr) + data_len;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = os_malloc(*msg_len);
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr == NULL)
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr->version = wpa_s->conf->eapol_version;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr->type = type;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr->length = host_to_be16(data_len);
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data)
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(hdr + 1, data, data_len);
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(hdr + 1, 0, data_len);
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data_pos)
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*data_pos = hdr + 1;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return (u8 *) hdr;
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_ether_send - Send Ethernet frame
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dest: Destination MAC address
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @proto: Ethertype in host byte order
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Frame payload starting from IEEE 802.1X header
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Frame payload length
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: >=0 on success, <0 on failure
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  u16 proto, const u8 *buf, size_t len)
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS
1006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (wpa_s->ext_eapol_frame_io && proto == ETH_P_EAPOL) {
1016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		size_t hex_len = 2 * len + 1;
1026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		char *hex = os_malloc(hex_len);
1036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (hex == NULL)
1056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			return -1;
1066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_snprintf_hex(hex, hex_len, buf, len);
1076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_msg(wpa_s, MSG_INFO, "EAPOL-TX " MACSTR " %s",
1086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			MAC2STR(dest), hex);
1096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		os_free(hex);
1106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 0;
1116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
1126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */
1136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->l2) {
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return -1;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL || !CONFIG_NO_WPA */
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_eapol_send - Send IEEE 802.1X EAPOL packet to Authenticator
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Pointer to wpa_supplicant data (wpa_s)
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*)
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: EAPOL payload (after IEEE 802.1X header)
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: EAPOL payload length
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: >=0 on success, <0 on failure
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to the current Authenticator.
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf,
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     size_t len)
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *msg, *dst, bssid[ETH_ALEN];
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t msglen;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: could add l2_packet_sendmsg that allows fragments to avoid
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * extra copy here */
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Current SSID is not using IEEE 802.1X/EAP, so drop possible
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * EAPOL frames (mainly, EAPOL-Start) from EAPOL state
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * machines. */
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WPA: drop TX EAPOL in non-IEEE 802.1X "
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "mode (type=%d len=%lu)", type,
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len);
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pmksa_cache_get_current(wpa_s->wpa) &&
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    type == IEEE802_1X_TYPE_EAPOL_START) {
160661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		/*
161661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * We were trying to use PMKSA caching and sending EAPOL-Start
162661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * would abort that and trigger full EAPOL authentication.
163661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * However, we've already waited for the AP/Authenticator to
164661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * start 4-way handshake or EAP authentication, and apparently
165661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * it has not done so since the startWhen timer has reached zero
166661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * to get the state machine sending EAPOL-Start. This is not
167661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * really supposed to happen, but an interoperability issue with
168661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * a deployed AP has been identified where the connection fails
169661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * due to that AP failing to operate correctly if PMKID is
170661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * included in the Association Request frame. To work around
171661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * this, assume PMKSA caching failed and try to initiate full
172661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 * EAP authentication.
173661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		 */
174661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		if (!wpa_s->current_ssid ||
175661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		    wpa_s->current_ssid->eap_workaround) {
176661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			wpa_printf(MSG_DEBUG,
177661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt				   "RSN: Timeout on waiting for the AP to initiate 4-way handshake for PMKSA caching or EAP authentication - try to force it to start EAP authentication");
178661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		} else {
179661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			wpa_printf(MSG_DEBUG,
180661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt				   "RSN: PMKSA caching - do not send EAPOL-Start");
181661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			return -1;
182661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		}
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_zero_ether_addr(wpa_s->bssid)) {
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an "
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "EAPOL frame");
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    !is_zero_ether_addr(bssid)) {
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dst = bssid;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " from the driver as the EAPOL destination",
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   MAC2STR(dst));
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dst = wpa_s->last_eapol_src;
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Using the source address of the"
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " last received EAPOL frame " MACSTR " as "
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "the EAPOL destination",
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   MAC2STR(dst));
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* BSSID was already set (from (Re)Assoc event, so use it as
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the EAPOL destination. */
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dst = wpa_s->bssid;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = wpa_alloc_eapol(wpa_s, type, buf, len, &msglen, NULL);
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg == NULL)
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TX EAPOL: dst=" MACSTR, MAC2STR(dst));
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen);
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, msg, msglen);
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(msg);
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_eapol_set_wep_key - set WEP key for the driver
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Pointer to wpa_supplicant data (wpa_s)
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @unicast: 1 = individual unicast key, 0 = broadcast key
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @keyidx: WEP key index (0..3)
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to key data
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @keylen: Key length in bytes
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success or < 0 on error.
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx,
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 const u8 *key, size_t keylen)
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int cipher = (keylen == 5) ? WPA_CIPHER_WEP40 :
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_CIPHER_WEP104;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (unicast)
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s->pairwise_cipher = cipher;
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s->group_cipher = cipher;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_drv_set_key(wpa_s, WPA_ALG_WEP,
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       unicast ? wpa_s->bssid : NULL,
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       keyidx, unicast, NULL, 0, key, keylen);
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_aborted_cached(void *ctx)
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_aborted_cached(wpa_s->wpa);
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
253344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidtstatic const char * result_str(enum eapol_supp_result result)
254344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt{
255344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	switch (result) {
256344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	case EAPOL_SUPP_RESULT_FAILURE:
257344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt		return "FAILURE";
258344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	case EAPOL_SUPP_RESULT_SUCCESS:
259344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt		return "SUCCESS";
260344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	case EAPOL_SUPP_RESULT_EXPECTED_FAILURE:
261344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt		return "EXPECTED_FAILURE";
262344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	}
263344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	return "?";
264344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt}
265344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt
266344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt
267344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidtstatic void wpa_supplicant_eapol_cb(struct eapol_sm *eapol,
268344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt				    enum eapol_supp_result result,
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    void *ctx)
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res, pmk_len;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 pmk[PMK_LEN];
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
275344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAPOL authentication completed - result=%s",
276344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt		   result_str(result));
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpas_wps_eapol_cb(wpa_s) > 0)
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
281344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	wpa_s->eap_expected_failure = result ==
282344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt		EAPOL_SUPP_RESULT_EXPECTED_FAILURE;
283344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt
284344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	if (result != EAPOL_SUPP_RESULT_SUCCESS) {
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Make sure we do not get stuck here waiting for long EAPOL
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * timeout if the AP does not disconnect in case of
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * authentication failure.
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_req_auth_timeout(wpa_s, 2, 0);
2915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
2925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_notify_create_actor(wpa_s, wpa_s->last_eapol_src);
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
295344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	if (result != EAPOL_SUPP_RESULT_SUCCESS ||
296344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	    !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt))
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Configure PMK for driver-based RSN 4-way "
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "handshake");
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pmk_len = PMK_LEN;
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) {
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 buf[2 * PMK_LEN];
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "RSN: Use FT XXKey as PMK for "
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "driver-based 4-way hs and FT");
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = eapol_sm_get_key(eapol, buf, 2 * PMK_LEN);
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res == 0) {
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(pmk, buf + PMK_LEN, PMK_LEN);
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(buf, 0, sizeof(buf));
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211R */
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = -1;
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = eapol_sm_get_key(eapol, pmk, PMK_LEN);
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res) {
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * EAP-LEAP is an exception from other EAP methods: it
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * uses only 16-byte PMK.
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res = eapol_sm_get_key(eapol, pmk, 16);
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pmk_len = 16;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res) {
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Failed to get PMK from EAPOL state "
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "machines");
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "RSN: Configure PMK for driver-based 4-way "
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"handshake", pmk, pmk_len);
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk,
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    pmk_len)) {
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver");
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_cancel_scan(wpa_s);
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_cancel_auth_timeout(wpa_s);
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_notify_eapol_done(void *ctx)
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(wpa_s, MSG_DEBUG, "WPA: EAPOL processing complete");
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE);
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_cancel_auth_timeout(wpa_s);
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_WPA
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_bss *curr = NULL, *bss;
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid = wpa_s->current_ssid;
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *ie;
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) != 0)
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid == NULL ||
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ((bss->ssid_len == ssid->ssid_len &&
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      os_memcmp(bss->ssid, ssid->ssid, ssid->ssid_len) == 0) ||
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     ssid->ssid_len == 0)) {
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			curr = bss;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (curr) {
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ie = wpa_bss_get_vendor_ie(curr, WPA_IE_VENDOR_TYPE);
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ie = wpa_bss_get_ie(curr, WLAN_EID_RSN);
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -1;
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_get_beacon_ie(void *ctx)
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_get_beacon_ie(wpa_s) == 0) {
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No WPA/RSN IE found in the cached scan results. Try to get updated
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * scan results from the driver. */
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_update_scan_results(wpa_s) < 0)
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_get_beacon_ie(wpa_s);
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * _wpa_alloc_eapol(void *wpa_s, u8 type,
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     const void *data, u16 data_len,
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     size_t *msg_len, void **data_pos)
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_alloc_eapol(wpa_s, type, data, data_len, msg_len, data_pos);
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int _wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto,
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   const u8 *buf, size_t len)
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ether_send(wpa_s, dest, proto, buf, len);
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void _wpa_supplicant_cancel_auth_timeout(void *wpa_s)
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_cancel_auth_timeout(wpa_s);
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void _wpa_supplicant_set_state(void *wpa_s, enum wpa_states state)
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_set_state(wpa_s, state);
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_get_state - Get the connection state
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: The current connection state (WPA_*)
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum wpa_states wpa_supplicant_get_state(struct wpa_supplicant *wpa_s)
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_s->wpa_state;
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum wpa_states _wpa_supplicant_get_state(void *wpa_s)
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_supplicant_get_state(wpa_s);
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code)
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_deauthenticate(wpa_s, reason_code);
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Schedule a scan to make sure we continue looking for networks */
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_req_scan(wpa_s, 5, 0);
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * wpa_supplicant_get_network_ctx(void *wpa_s)
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_supplicant_get_ssid(wpa_s);
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_get_bssid(void *ctx, u8 *bssid)
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_drv_get_bssid(wpa_s, bssid);
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg,
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const u8 *addr, int key_idx, int set_tx,
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const u8 *seq, size_t seq_len,
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const u8 *key, size_t key_len)
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = _wpa_s;
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (alg == WPA_ALG_TKIP && key_idx == 0 && key_len == 32) {
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Clear the MIC error counter when setting a new PTK. */
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->mic_errors_seen = 0;
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
495b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt#ifdef CONFIG_TESTING_GET_GTK
496b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (key_idx > 0 && addr && is_broadcast_ether_addr(addr) &&
497b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	    alg != WPA_ALG_NONE && key_len <= sizeof(wpa_s->last_gtk)) {
498b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		os_memcpy(wpa_s->last_gtk, key, key_len);
499b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_s->last_gtk_len = key_len;
500b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	}
501b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt#endif /* CONFIG_TESTING_GET_GTK */
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       key, key_len);
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr,
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     int protection_type,
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     int key_type)
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_drv_mlme_setprotection(wpa_s, addr, protection_type,
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  key_type);
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_add_pmkid(void *wpa_s,
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const u8 *bssid, const u8 *pmkid)
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_drv_add_pmkid(wpa_s, bssid, pmkid);
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_remove_pmkid(void *wpa_s,
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *bssid, const u8 *pmkid)
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_drv_remove_pmkid(wpa_s, bssid, pmkid);
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_update_ft_ies(void *ctx, const u8 *md,
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					const u8 *ies, size_t ies_len)
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return sme_update_ft_ies(wpa_s, md, ies, ies_len);
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_drv_update_ft_ies(wpa_s, md, ies, ies_len);
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_send_ft_action(void *ctx, u8 action,
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const u8 *target_ap,
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const u8 *ies, size_t ies_len)
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
5466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	int ret;
5476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	u8 *data, *pos;
5486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	size_t data_len;
5496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (action != 1) {
5516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR, "Unsupported send_ft_action action %d",
5526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   action);
5536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return -1;
5546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
5556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/*
5576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * Action frame payload:
5586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * Category[1] = 6 (Fast BSS Transition)
5596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * Action[1] = 1 (Fast BSS Transition Request)
5606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * STA Address
5616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * Target AP Address
5626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 * FT IEs
5636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	 */
5646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	data_len = 2 + 2 * ETH_ALEN + ies_len;
5666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	data = os_malloc(data_len);
5676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (data == NULL)
5686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return -1;
5696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	pos = data;
5706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	*pos++ = 0x06; /* FT Action category */
5716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	*pos++ = action;
5726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memcpy(pos, wpa_s->own_addr, ETH_ALEN);
5736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	pos += ETH_ALEN;
5746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memcpy(pos, target_ap, ETH_ALEN);
5756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	pos += ETH_ALEN;
5766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memcpy(pos, ies, ies_len);
5776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0,
5796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				  wpa_s->bssid, wpa_s->own_addr, wpa_s->bssid,
5806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				  data, data_len, 0);
5816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_free(data);
5826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
5836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return ret;
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_mark_authenticated(void *ctx, const u8 *target_ap)
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_auth_params params;
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_bss *bss;
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bss = wpa_bss_get_bssid(wpa_s, target_ap);
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bss == NULL)
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&params, 0, sizeof(params));
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.bssid = target_ap;
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.freq = bss->freq;
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.ssid = bss->ssid;
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.ssid_len = bss->ssid_len;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.auth_alg = WPA_AUTH_ALG_FT;
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	params.local_state_change = 1;
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_drv_authenticate(wpa_s, &params);
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpa_supplicant_tdls_get_capa(void *ctx, int *tdls_supported,
6126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt					int *tdls_ext_setup,
6136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt					int *tdls_chan_switch)
6141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
6151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
6161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	*tdls_supported = 0;
6181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	*tdls_ext_setup = 0;
6196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	*tdls_chan_switch = 0;
6201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!wpa_s->drv_capa_known)
6221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
6231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)
6251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		*tdls_supported = 1;
6261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP)
6281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		*tdls_ext_setup = 1;
6291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH)
6316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		*tdls_chan_switch = 1;
6326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 0;
6341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
6351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_send_tdls_mgmt(void *ctx, const u8 *dst,
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 u8 action_code, u8 dialog_token,
639df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt					 u16 status_code, u32 peer_capab,
6409ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt					 int initiator, const u8 *buf,
6419ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt					 size_t len)
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_drv_send_tdls_mgmt(wpa_s, dst, action_code, dialog_token,
6459ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt				      status_code, peer_capab, initiator, buf,
6469ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt				      len);
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_tdls_oper(void *ctx, int oper, const u8 *peer)
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_drv_tdls_oper(wpa_s, oper, peer);
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpa_supplicant_tdls_peer_addset(
65851b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt	void *ctx, const u8 *peer, int add, u16 aid, u16 capability,
659f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	const u8 *supp_rates, size_t supp_rates_len,
660f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	const struct ieee80211_ht_capabilities *ht_capab,
66133e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt	const struct ieee80211_vht_capabilities *vht_capab,
6629ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt	u8 qosinfo, int wmm, const u8 *ext_capab, size_t ext_capab_len,
663344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	const u8 *supp_channels, size_t supp_channels_len,
664344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	const u8 *supp_oper_classes, size_t supp_oper_classes_len)
6651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
6661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
6671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct hostapd_sta_add_params params;
6681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
669f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	os_memset(&params, 0, sizeof(params));
670f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
6711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	params.addr = peer;
67251b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt	params.aid = aid;
6731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	params.capability = capability;
6741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED;
675f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
676f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	/*
6779ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt	 * Don't rely only on qosinfo for WMM capability. It may be 0 even when
6789ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt	 * present. Allow the WMM IE to also indicate QoS support.
679f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	 */
6809ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt	if (wmm || qosinfo)
681f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		params.flags |= WPA_STA_WMM;
682f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
683f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	params.ht_capabilities = ht_capab;
68433e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt	params.vht_capabilities = vht_capab;
685f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	params.qosinfo = qosinfo;
6861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	params.listen_interval = 0;
6871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	params.supp_rates = supp_rates;
6881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	params.supp_rates_len = supp_rates_len;
6891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	params.set = !add;
690f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	params.ext_capab = ext_capab;
691f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	params.ext_capab_len = ext_capab_len;
692344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	params.supp_channels = supp_channels;
693344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	params.supp_channels_len = supp_channels_len;
694344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	params.supp_oper_classes = supp_oper_classes;
695344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	params.supp_oper_classes_len = supp_oper_classes_len;
6961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return wpa_drv_sta_add(wpa_s, &params);
6981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
6991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
7016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_supplicant_tdls_enable_channel_switch(
7026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	void *ctx, const u8 *addr, u8 oper_class,
7036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	const struct hostapd_freq_params *params)
7046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
7056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
7066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
7076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return wpa_drv_tdls_enable_channel_switch(wpa_s, addr, oper_class,
7086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt						  params);
7096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
7106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
7116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
7126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_supplicant_tdls_disable_channel_switch(void *ctx, const u8 *addr)
7136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
7146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
7156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
7166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	return wpa_drv_tdls_disable_channel_switch(wpa_s, addr);
7176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
7186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
72134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* CONFIG_NO_WPA */
72234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtenum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field)
7251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
7261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (os_strcmp(field, "IDENTITY") == 0)
7271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return WPA_CTRL_REQ_EAP_IDENTITY;
7281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else if (os_strcmp(field, "PASSWORD") == 0)
7291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return WPA_CTRL_REQ_EAP_PASSWORD;
7301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else if (os_strcmp(field, "NEW_PASSWORD") == 0)
7311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return WPA_CTRL_REQ_EAP_NEW_PASSWORD;
7321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else if (os_strcmp(field, "PIN") == 0)
7331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return WPA_CTRL_REQ_EAP_PIN;
7341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else if (os_strcmp(field, "OTP") == 0)
7351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return WPA_CTRL_REQ_EAP_OTP;
7361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else if (os_strcmp(field, "PASSPHRASE") == 0)
7371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return WPA_CTRL_REQ_EAP_PASSPHRASE;
738051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	else if (os_strcmp(field, "SIM") == 0)
739051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return WPA_CTRL_REQ_SIM;
740912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	else if (os_strcmp(field, "PSK_PASSPHRASE") == 0)
741912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt		return WPA_CTRL_REQ_PSK_PASSPHRASE;
7421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	else if (os_strcmp(field, "EXT_CERT_CHECK") == 0)
7431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		return WPA_CTRL_REQ_EXT_CERT_CHECK;
7441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return WPA_CTRL_REQ_UNKNOWN;
7451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
7461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field,
7491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       const char *default_txt,
7501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       const char **txt)
7511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
7521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	const char *ret = NULL;
7531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	*txt = default_txt;
7551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (field) {
7571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_IDENTITY:
7581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		*txt = "Identity";
7591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = "IDENTITY";
7601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
7611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_PASSWORD:
7621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		*txt = "Password";
7631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = "PASSWORD";
7641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
7651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
7661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		*txt = "New Password";
7671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = "NEW_PASSWORD";
7681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
7691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_PIN:
7701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		*txt = "PIN";
7711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = "PIN";
7721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
7731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_OTP:
7741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = "OTP";
7751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
7761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_PASSPHRASE:
7771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		*txt = "Private key passphrase";
7781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = "PASSPHRASE";
7791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
780051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	case WPA_CTRL_REQ_SIM:
781051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		ret = "SIM";
782051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		break;
783912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	case WPA_CTRL_REQ_PSK_PASSPHRASE:
784912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt		*txt = "PSK or passphrase";
785912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt		ret = "PSK_PASSPHRASE";
786912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt		break;
7871b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	case WPA_CTRL_REQ_EXT_CERT_CHECK:
7881b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		*txt = "External server certificate validation";
7891b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		ret = "EXT_CERT_CHECK";
7901b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		break;
7911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	default:
7921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
7931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
7941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* txt needs to be something */
7961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (*txt == NULL) {
7971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_WARNING, "No message for request %d", field);
7981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = NULL;
7991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
8001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
8011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return ret;
8021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
8031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
804912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt
805912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidtvoid wpas_send_ctrl_req(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
806912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt			const char *field_name, const char *txt)
807912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt{
808912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	char *buf;
809912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	size_t buflen;
810912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	int len;
811912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt
812912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	buflen = 100 + os_strlen(txt) + ssid->ssid_len;
813912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	buf = os_malloc(buflen);
814912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	if (buf == NULL)
815912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt		return;
816912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	len = os_snprintf(buf, buflen, "%s-%d:%s needed for SSID ",
817912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt			  field_name, ssid->id, txt);
818912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	if (os_snprintf_error(buflen, len)) {
819912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt		os_free(buf);
820912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt		return;
821912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	}
822912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	if (ssid->ssid && buflen > len + ssid->ssid_len) {
823912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt		os_memcpy(buf + len, ssid->ssid, ssid->ssid_len);
824912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt		len += ssid->ssid_len;
825912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt		buf[len] = '\0';
826912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	}
827912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	buf[buflen - 1] = '\0';
828912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	wpa_msg(wpa_s, MSG_INFO, WPA_CTRL_REQ "%s", buf);
829912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	os_free(buf);
830912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt}
831912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt
832912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
8351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void wpa_supplicant_eap_param_needed(void *ctx,
8361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					    enum wpa_ctrl_req_type field,
8371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					    const char *default_txt)
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid = wpa_s->current_ssid;
8411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	const char *field_name, *txt = NULL;
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL)
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	if (field == WPA_CTRL_REQ_EXT_CERT_CHECK)
8471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		ssid->eap.pending_ext_cert_check = PENDING_CHECK;
8481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpas_notify_network_request(wpa_s, ssid, field, default_txt);
8491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
8501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	field_name = wpa_supplicant_ctrl_req_to_string(field, default_txt,
8511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt						       &txt);
8521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (field_name == NULL) {
8531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_WARNING, "Unhandled EAP param %d needed",
8541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   field);
8551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
8561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
8571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
858a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	wpas_notify_eap_status(wpa_s, "eap parameter needed", field_name);
859a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
860912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	wpas_send_ctrl_req(wpa_s, ssid, field_name, txt);
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define wpa_supplicant_eap_param_needed NULL
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
867203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt#ifdef CONFIG_EAP_PROXY
868203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidtstatic void wpa_supplicant_eap_proxy_cb(void *ctx)
869203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt{
870203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
871203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	size_t len;
872203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt
873203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol,
874203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt						     wpa_s->imsi, &len);
875203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	if (wpa_s->mnc_len > 0) {
876203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		wpa_s->imsi[len] = '\0';
877203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
878203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt			   wpa_s->imsi, wpa_s->mnc_len);
879203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	} else {
880203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
881203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	}
882203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt}
883203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt#endif /* CONFIG_EAP_PROXY */
884203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt
885203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_port_cb(void *ctx, int authorized)
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_AP
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->ap_iface) {
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "AP mode active - skip EAPOL Supplicant "
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "port status: %s",
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   authorized ? "Authorized" : "Unauthorized");
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_AP */
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAPOL: Supplicant port status: %s",
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   authorized ? "Authorized" : "Unauthorized");
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_drv_set_supp_port(wpa_s, authorized);
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
901c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
902c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
903c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidtstatic void wpa_supplicant_cert_cb(void *ctx, int depth, const char *subject,
9042f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				   const char *altsubject[], int num_altsubject,
905c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				   const char *cert_hash,
906c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				   const struct wpabuf *cert)
907c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt{
908c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
909c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
9102f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	wpas_notify_certification(wpa_s, depth, subject, altsubject,
9112f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				  num_altsubject, cert_hash, cert);
912c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt}
91304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
91404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
91504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void wpa_supplicant_status_cb(void *ctx, const char *status,
91604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				     const char *parameter)
91704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
91804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
91904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
92004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpas_notify_eap_status(wpa_s, status, parameter);
92104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
9224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
9234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
9244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len)
9254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
9264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
9274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *str;
9284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int res;
9294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
9304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity",
9314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			  id, len);
9324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
9334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (wpa_s->current_ssid == NULL)
9344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return;
9354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
9364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (id == NULL) {
9374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
9384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   "NULL", 0) < 0)
9394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return;
9404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	} else {
9414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		str = os_malloc(len * 2 + 1);
9424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (str == NULL)
9434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return;
9444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_snprintf_hex(str, len * 2 + 1, id, len);
9454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
9464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     str, 0);
9474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		os_free(str);
9484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (res < 0)
9494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return;
9504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
9514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
9524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (wpa_s->conf->update_config) {
9534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		res = wpa_config_write(wpa_s->confname, wpa_s->conf);
9544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (res) {
9554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Failed to update config after "
9564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   "anonymous_id update");
9574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		}
9584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
9594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_ctx *ctx;
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL) {
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context.");
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->ctx = wpa_s;
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->msg_ctx = wpa_s;
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eapol_send_ctx = wpa_s;
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->preauth = 0;
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done;
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eapol_send = wpa_supplicant_eapol_send;
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->set_wep_key = wpa_eapol_set_wep_key;
980700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->set_config_blob = wpa_supplicant_set_config_blob;
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_config_blob = wpa_supplicant_get_config_blob;
983700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->aborted_cached = wpa_supplicant_aborted_cached;
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
9886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ctx->openssl_ciphers = wpa_s->conf->openssl_ciphers;
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->wps = wpa_s->wps;
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eap_param_needed = wpa_supplicant_eap_param_needed;
991203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt#ifdef CONFIG_EAP_PROXY
992203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	ctx->eap_proxy_cb = wpa_supplicant_eap_proxy_cb;
993203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt#endif /* CONFIG_EAP_PROXY */
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->port_cb = wpa_supplicant_port_cb;
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->cb = wpa_supplicant_eapol_cb;
996c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	ctx->cert_cb = wpa_supplicant_cert_cb;
9972f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	ctx->cert_in_cb = wpa_s->conf->cert_in_cb;
99804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	ctx->status_cb = wpa_supplicant_status_cb;
9994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	ctx->set_anon_id = wpa_supplicant_set_anon_id;
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->cb_ctx = wpa_s;
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->eapol = eapol_sm_init(ctx);
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->eapol == NULL) {
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize EAPOL state "
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "machines.");
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1014a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifndef CONFIG_NO_WPA
1015807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtstatic void wpa_supplicant_set_rekey_offload(void *ctx,
1016807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt					     const u8 *kek, size_t kek_len,
1017807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt					     const u8 *kck, size_t kck_len,
10181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					     const u8 *replay_ctr)
10191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
10201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
10211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1022807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	wpa_drv_set_rekey_info(wpa_s, kek, kek_len, kck, kck_len, replay_ctr);
10231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
10241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk,
10276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt					   size_t pmk_len)
10286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
10296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
10306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10311d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt	if (wpa_s->conf->key_mgmt_offload &&
10321d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD))
10336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0,
10346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				       NULL, 0, pmk, pmk_len);
10356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	else
10366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 0;
10376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
1038d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#endif /* CONFIG_NO_WPA */
10396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_WPA
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm_ctx *ctx;
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL) {
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to allocate WPA context.");
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->ctx = wpa_s;
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->msg_ctx = wpa_s;
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->set_state = _wpa_supplicant_set_state;
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_state = _wpa_supplicant_get_state;
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->deauthenticate = _wpa_supplicant_deauthenticate;
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->set_key = wpa_supplicant_set_key;
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_network_ctx = wpa_supplicant_get_network_ctx;
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_bssid = wpa_supplicant_get_bssid;
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->ether_send = _wpa_ether_send;
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie;
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->alloc_eapol = _wpa_alloc_eapol;
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout;
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->add_pmkid = wpa_supplicant_add_pmkid;
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->remove_pmkid = wpa_supplicant_remove_pmkid;
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->set_config_blob = wpa_supplicant_set_config_blob;
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_config_blob = wpa_supplicant_get_config_blob;
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->update_ft_ies = wpa_supplicant_update_ft_ies;
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->send_ft_action = wpa_supplicant_send_ft_action;
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->mark_authenticated = wpa_supplicant_mark_authenticated;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS
10761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ctx->tdls_get_capa = wpa_supplicant_tdls_get_capa;
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->send_tdls_mgmt = wpa_supplicant_send_tdls_mgmt;
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->tdls_oper = wpa_supplicant_tdls_oper;
10791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ctx->tdls_peer_addset = wpa_supplicant_tdls_peer_addset;
10806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ctx->tdls_enable_channel_switch =
10816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_supplicant_tdls_enable_channel_switch;
10826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ctx->tdls_disable_channel_switch =
10836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_supplicant_tdls_disable_channel_switch;
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */
10851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload;
10866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk;
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->wpa = wpa_sm_init(ctx);
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->wpa == NULL) {
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "machine");
1092ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		os_free(ctx);
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_WPA */
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct wpa_ssid *ssid)
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct rsn_supp_config conf;
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid) {
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&conf, 0, sizeof(conf));
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.network_ctx = ssid;
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.peerkey_enabled = ssid->peerkey;
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.allowed_pairwise_cipher = ssid->pairwise_cipher;
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
1111d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		conf.proactive_key_caching = ssid->proactive_key_caching < 0 ?
1112d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			wpa_s->conf->okc : ssid->proactive_key_caching;
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.eap_workaround = ssid->eap_workaround;
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.eap_conf_ctx = &ssid->eap;
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.ssid = ssid->ssid;
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.ssid_len = ssid->ssid_len;
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey;
1119cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P
1120cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		if (ssid->p2p_group && wpa_s->current_bss &&
1121cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		    !wpa_s->p2p_disable_ip_addr_req) {
1122cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			struct wpabuf *p2p;
1123cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			p2p = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
1124cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt							  P2P_IE_VENDOR_TYPE);
1125cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			if (p2p) {
1126cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				u8 group_capab;
1127cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				group_capab = p2p_get_group_capab(p2p);
1128cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				if (group_capab &
1129cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				    P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION)
1130cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					conf.p2p = 1;
1131cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				wpabuf_free(p2p);
1132cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			}
1133cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		}
1134cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */
1135d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		conf.wpa_rsc_relaxation = wpa_s->conf->wpa_rsc_relaxation;
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1139