wpas_glue.c revision 807291d85bf857320aff6a8ade38c5f622ab9df8
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;
7401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return WPA_CTRL_REQ_UNKNOWN;
7411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
7421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field,
7451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       const char *default_txt,
7461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       const char **txt)
7471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
7481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	const char *ret = NULL;
7491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	*txt = default_txt;
7511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (field) {
7531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_IDENTITY:
7541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		*txt = "Identity";
7551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = "IDENTITY";
7561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
7571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_PASSWORD:
7581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		*txt = "Password";
7591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = "PASSWORD";
7601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
7611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
7621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		*txt = "New Password";
7631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = "NEW_PASSWORD";
7641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
7651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_PIN:
7661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		*txt = "PIN";
7671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = "PIN";
7681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
7691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_OTP:
7701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = "OTP";
7711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
7721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_PASSPHRASE:
7731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		*txt = "Private key passphrase";
7741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = "PASSPHRASE";
7751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
776051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	case WPA_CTRL_REQ_SIM:
777051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		ret = "SIM";
778051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		break;
7791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	default:
7801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
7811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
7821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* txt needs to be something */
7841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (*txt == NULL) {
7851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_WARNING, "No message for request %d", field);
7861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ret = NULL;
7871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
7881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return ret;
7901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
7911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
7941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void wpa_supplicant_eap_param_needed(void *ctx,
7951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					    enum wpa_ctrl_req_type field,
7961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					    const char *default_txt)
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid = wpa_s->current_ssid;
8001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	const char *field_name, *txt = NULL;
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf;
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t buflen;
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL)
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpas_notify_network_request(wpa_s, ssid, field, default_txt);
8091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
8101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	field_name = wpa_supplicant_ctrl_req_to_string(field, default_txt,
8111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt						       &txt);
8121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (field_name == NULL) {
8131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_WARNING, "Unhandled EAP param %d needed",
8141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   field);
8151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
8161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
8171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
818a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	wpas_notify_eap_status(wpa_s, "eap parameter needed", field_name);
819a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buflen = 100 + os_strlen(txt) + ssid->ssid_len;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(buflen);
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_snprintf(buf, buflen,
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
8261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			  field_name, ssid->id, txt);
8276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(buflen, len)) {
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->ssid && buflen > len + ssid->ssid_len) {
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf + len, ssid->ssid, ssid->ssid_len);
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ssid->ssid_len;
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[len] = '\0';
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[buflen - 1] = '\0';
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(wpa_s, MSG_INFO, "%s", buf);
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define wpa_supplicant_eap_param_needed NULL
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_port_cb(void *ctx, int authorized)
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_AP
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->ap_iface) {
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "AP mode active - skip EAPOL Supplicant "
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "port status: %s",
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   authorized ? "Authorized" : "Unauthorized");
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_AP */
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAPOL: Supplicant port status: %s",
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   authorized ? "Authorized" : "Unauthorized");
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_drv_set_supp_port(wpa_s, authorized);
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
860c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
861c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
862c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidtstatic void wpa_supplicant_cert_cb(void *ctx, int depth, const char *subject,
8632f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				   const char *altsubject[], int num_altsubject,
864c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				   const char *cert_hash,
865c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				   const struct wpabuf *cert)
866c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt{
867c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
868c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
8692f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	wpas_notify_certification(wpa_s, depth, subject, altsubject,
8702f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				  num_altsubject, cert_hash, cert);
871c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt}
87204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
87304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
87404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void wpa_supplicant_status_cb(void *ctx, const char *status,
87504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				     const char *parameter)
87604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
87704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
87804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
87904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpas_notify_eap_status(wpa_s, status, parameter);
88004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
8814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
8824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
8834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len)
8844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
8854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
8864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *str;
8874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int res;
8884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
8894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity",
8904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			  id, len);
8914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
8924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (wpa_s->current_ssid == NULL)
8934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return;
8944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
8954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (id == NULL) {
8964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
8974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   "NULL", 0) < 0)
8984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return;
8994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	} else {
9004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		str = os_malloc(len * 2 + 1);
9014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (str == NULL)
9024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return;
9034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_snprintf_hex(str, len * 2 + 1, id, len);
9044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
9054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     str, 0);
9064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		os_free(str);
9074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (res < 0)
9084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return;
9094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
9104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
9114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (wpa_s->conf->update_config) {
9124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		res = wpa_config_write(wpa_s->confname, wpa_s->conf);
9134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (res) {
9144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Failed to update config after "
9154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   "anonymous_id update");
9164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		}
9174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
9184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_ctx *ctx;
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL) {
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context.");
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->ctx = wpa_s;
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->msg_ctx = wpa_s;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eapol_send_ctx = wpa_s;
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->preauth = 0;
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done;
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eapol_send = wpa_supplicant_eapol_send;
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->set_wep_key = wpa_eapol_set_wep_key;
939700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->set_config_blob = wpa_supplicant_set_config_blob;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_config_blob = wpa_supplicant_get_config_blob;
942700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->aborted_cached = wpa_supplicant_aborted_cached;
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
9476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ctx->openssl_ciphers = wpa_s->conf->openssl_ciphers;
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->wps = wpa_s->wps;
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eap_param_needed = wpa_supplicant_eap_param_needed;
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->port_cb = wpa_supplicant_port_cb;
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->cb = wpa_supplicant_eapol_cb;
952c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	ctx->cert_cb = wpa_supplicant_cert_cb;
9532f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	ctx->cert_in_cb = wpa_s->conf->cert_in_cb;
95404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	ctx->status_cb = wpa_supplicant_status_cb;
9554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	ctx->set_anon_id = wpa_supplicant_set_anon_id;
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->cb_ctx = wpa_s;
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->eapol = eapol_sm_init(ctx);
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->eapol == NULL) {
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize EAPOL state "
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "machines.");
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
970a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifndef CONFIG_NO_WPA
971807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtstatic void wpa_supplicant_set_rekey_offload(void *ctx,
972807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt					     const u8 *kek, size_t kek_len,
973807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt					     const u8 *kck, size_t kck_len,
9741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					     const u8 *replay_ctr)
9751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
9761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
9771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
978807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	wpa_drv_set_rekey_info(wpa_s, kek, kek_len, kck, kck_len, replay_ctr);
9791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
980a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#endif /* CONFIG_NO_WPA */
9811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk,
9846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt					   size_t pmk_len)
9856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
9866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
9876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (wpa_s->conf->key_mgmt_offload)
9896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0,
9906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				       NULL, 0, pmk, pmk_len);
9916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	else
9926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return 0;
9936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
9946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_WPA
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm_ctx *ctx;
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL) {
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to allocate WPA context.");
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->ctx = wpa_s;
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->msg_ctx = wpa_s;
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->set_state = _wpa_supplicant_set_state;
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_state = _wpa_supplicant_get_state;
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->deauthenticate = _wpa_supplicant_deauthenticate;
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->set_key = wpa_supplicant_set_key;
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_network_ctx = wpa_supplicant_get_network_ctx;
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_bssid = wpa_supplicant_get_bssid;
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->ether_send = _wpa_ether_send;
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie;
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->alloc_eapol = _wpa_alloc_eapol;
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout;
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->add_pmkid = wpa_supplicant_add_pmkid;
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->remove_pmkid = wpa_supplicant_remove_pmkid;
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->set_config_blob = wpa_supplicant_set_config_blob;
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_config_blob = wpa_supplicant_get_config_blob;
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->update_ft_ies = wpa_supplicant_update_ft_ies;
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->send_ft_action = wpa_supplicant_send_ft_action;
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->mark_authenticated = wpa_supplicant_mark_authenticated;
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS
10311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ctx->tdls_get_capa = wpa_supplicant_tdls_get_capa;
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->send_tdls_mgmt = wpa_supplicant_send_tdls_mgmt;
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->tdls_oper = wpa_supplicant_tdls_oper;
10341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ctx->tdls_peer_addset = wpa_supplicant_tdls_peer_addset;
10356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ctx->tdls_enable_channel_switch =
10366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_supplicant_tdls_enable_channel_switch;
10376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ctx->tdls_disable_channel_switch =
10386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_supplicant_tdls_disable_channel_switch;
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */
10401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload;
10416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk;
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->wpa = wpa_sm_init(ctx);
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->wpa == NULL) {
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "machine");
1047ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		os_free(ctx);
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_WPA */
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct wpa_ssid *ssid)
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct rsn_supp_config conf;
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid) {
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&conf, 0, sizeof(conf));
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.network_ctx = ssid;
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.peerkey_enabled = ssid->peerkey;
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.allowed_pairwise_cipher = ssid->pairwise_cipher;
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
1066d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		conf.proactive_key_caching = ssid->proactive_key_caching < 0 ?
1067d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			wpa_s->conf->okc : ssid->proactive_key_caching;
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.eap_workaround = ssid->eap_workaround;
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.eap_conf_ctx = &ssid->eap;
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.ssid = ssid->ssid;
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.ssid_len = ssid->ssid_len;
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey;
1074cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P
1075cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		if (ssid->p2p_group && wpa_s->current_bss &&
1076cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		    !wpa_s->p2p_disable_ip_addr_req) {
1077cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			struct wpabuf *p2p;
1078cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			p2p = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
1079cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt							  P2P_IE_VENDOR_TYPE);
1080cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			if (p2p) {
1081cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				u8 group_capab;
1082cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				group_capab = p2p_get_group_capab(p2p);
1083cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				if (group_capab &
1084cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				    P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION)
1085cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					conf.p2p = 1;
1086cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				wpabuf_free(p2p);
1087cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			}
1088cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		}
1089cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1093