Accumulative patch from commit 565110cd554801fa301c55010b3e9e14f43d7973

nl80211: Include interface name in more debug prints
Convert WPS NFC python scripts from using wpactrl to wpaspy
wpa_supplicant: Fix lookup of cached PMKSA
Add capability flag for IBSS and add get_capability modes
hostapd: Fix client reassociation after disconnect due to ACK failure
Fix build with CONFIG_NO_CONFIG_BLOBS
Fix build without CONFIG_CTRL_IFACE or CONFIG_NO_STDOUT_DEBUG
libtommath: Avoid a compiler warning on unused variable
libtommath: Condition fast_s_mp_mul_digs() on LTM_FAST
P2P: Remove persistent group peer if it rejects invitation
P2P: Allow shared interface channel preference to be ignored
P2P: Fix shared frequency preference for concurrent operations
P2P: Use best-overall channel in p2p_reselect_channel()
P2P: Allow all channels for multi-channel concurrency (no negotiation)
TDLS: Disable link to existing peer with lower address
Fix compiler warning when CONFIG_IEEE80211R is not included
WPS NFC: Fix build without CONFIG_WPS_ER
FT: Add support for IEEE 802.11r with driver-based SME

Change-Id: I1d5ced870c33d5cb73ecc6f04e272a3cf50f344a
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 8ada121..cbafb47 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -576,7 +576,7 @@
 {
 	wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
 		   hapd->conf->iface, MAC2STR(sta->addr));
-	sta->flags &= ~WLAN_STA_ASSOC;
+	sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
 	ap_sta_set_authorized(hapd, sta, 0);
 	sta->timeout_next = STA_DEAUTH;
 	wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 652476f..f782c86 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -1005,6 +1005,8 @@
 /* AKM suite selectors */
 #define WLAN_AKM_SUITE_8021X		0x000FAC01
 #define WLAN_AKM_SUITE_PSK		0x000FAC02
+#define WLAN_AKM_SUITE_FT_8021X		0x000FAC03
+#define WLAN_AKM_SUITE_FT_PSK		0x000FAC04
 #define WLAN_AKM_SUITE_CCKM		0x00409600
 
 
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index f12f4bc..63f90bc 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -864,6 +864,8 @@
 #define WPA_DRIVER_FLAGS_SAE				0x02000000
 /* Driver makes use of OBSS scan mechanism in wpa_supplicant */
 #define WPA_DRIVER_FLAGS_OBSS_SCAN			0x04000000
+/* Driver supports IBSS (Ad-hoc) mode */
+#define WPA_DRIVER_FLAGS_IBSS				0x08000000
 	unsigned int flags;
 
 	int max_scan_ssids;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 3a35a6b..efd5cab 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -1642,6 +1642,34 @@
 }
 
 
+static void mlme_event_ft_event(struct wpa_driver_nl80211_data *drv,
+				struct nlattr *tb[])
+{
+	union wpa_event_data data;
+
+	os_memset(&data, 0, sizeof(data));
+
+	if (tb[NL80211_ATTR_IE]) {
+		data.ft_ies.ies = nla_data(tb[NL80211_ATTR_IE]);
+		data.ft_ies.ies_len = nla_len(tb[NL80211_ATTR_IE]);
+	}
+
+	if (tb[NL80211_ATTR_IE_RIC]) {
+		data.ft_ies.ric_ies = nla_data(tb[NL80211_ATTR_IE_RIC]);
+		data.ft_ies.ric_ies_len = nla_len(tb[NL80211_ATTR_IE_RIC]);
+	}
+
+	if (tb[NL80211_ATTR_MAC])
+		os_memcpy(data.ft_ies.target_ap,
+			  nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
+
+	wpa_printf(MSG_DEBUG, "nl80211: FT event target_ap " MACSTR,
+		   MAC2STR(data.ft_ies.target_ap));
+
+	wpa_supplicant_event(drv->ctx, EVENT_FT_RESPONSE, &data);
+}
+
+
 static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
 			    struct nlattr *tb[])
 {
@@ -2232,29 +2260,30 @@
 
 	switch (cmd) {
 	case NL80211_CMD_TRIGGER_SCAN:
-		wpa_printf(MSG_DEBUG, "nl80211: Scan trigger");
+		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger");
 		break;
 	case NL80211_CMD_START_SCHED_SCAN:
-		wpa_printf(MSG_DEBUG, "nl80211: Sched scan started");
+		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started");
 		break;
 	case NL80211_CMD_SCHED_SCAN_STOPPED:
-		wpa_printf(MSG_DEBUG, "nl80211: Sched scan stopped");
+		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
 		wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
 		break;
 	case NL80211_CMD_NEW_SCAN_RESULTS:
-		wpa_printf(MSG_DEBUG, "nl80211: New scan results available");
+		wpa_dbg(drv->ctx, MSG_DEBUG,
+			"nl80211: New scan results available");
 		drv->scan_complete_events = 1;
 		eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
 				     drv->ctx);
 		send_scan_event(drv, 0, tb);
 		break;
 	case NL80211_CMD_SCHED_SCAN_RESULTS:
-		wpa_printf(MSG_DEBUG,
-			   "nl80211: New sched scan results available");
+		wpa_dbg(drv->ctx, MSG_DEBUG,
+			"nl80211: New sched scan results available");
 		send_scan_event(drv, 0, tb);
 		break;
 	case NL80211_CMD_SCAN_ABORTED:
-		wpa_printf(MSG_DEBUG, "nl80211: Scan aborted");
+		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
 		/*
 		 * Need to indicate that scan results are available in order
 		 * not to make wpa_supplicant stop its scanning.
@@ -2339,9 +2368,12 @@
 	case NL80211_CMD_CONN_FAILED:
 		nl80211_connect_failed_event(drv, tb);
 		break;
+	case NL80211_CMD_FT_EVENT:
+		mlme_event_ft_event(drv, tb);
+		break;
 	default:
-		wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
-			   "(cmd=%d)", cmd);
+		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
+			"(cmd=%d)", cmd);
 		break;
 	}
 }
@@ -2569,6 +2601,9 @@
 		case NL80211_IFTYPE_AP:
 			info->capa->flags |= WPA_DRIVER_FLAGS_AP;
 			break;
+		case NL80211_IFTYPE_ADHOC:
+			info->capa->flags |= WPA_DRIVER_FLAGS_IBSS;
+			break;
 		case NL80211_IFTYPE_P2P_GO:
 			info->p2p_go_supported = 1;
 			break;
@@ -3831,6 +3866,7 @@
 	int ret = -1, timeout;
 	struct nl_msg *msg, *rates = NULL;
 
+	wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
 	drv->scan_for_auth = 0;
 
 	msg = nl80211_scan_common(drv, NL80211_CMD_TRIGGER_SCAN, params);
@@ -3932,6 +3968,8 @@
 	struct nl_msg *match_set_rssi = NULL;
 	size_t i;
 
+	wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: sched_scan request");
+
 #ifdef ANDROID
 	if (!drv->capa.sched_scan_supported)
 		return android_pno_start(bss, params);
@@ -7173,6 +7211,8 @@
 
 	if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
 	    params->key_mgmt_suite == KEY_MGMT_PSK ||
+	    params->key_mgmt_suite == KEY_MGMT_FT_802_1X ||
+	    params->key_mgmt_suite == KEY_MGMT_FT_PSK ||
 	    params->key_mgmt_suite == KEY_MGMT_CCKM) {
 		int mgmt = WLAN_AKM_SUITE_PSK;
 
@@ -7183,6 +7223,12 @@
 		case KEY_MGMT_802_1X:
 			mgmt = WLAN_AKM_SUITE_8021X;
 			break;
+		case KEY_MGMT_FT_802_1X:
+			mgmt = WLAN_AKM_SUITE_FT_8021X;
+			break;
+		case KEY_MGMT_FT_PSK:
+			mgmt = WLAN_AKM_SUITE_FT_PSK;
+			break;
 		case KEY_MGMT_PSK:
 		default:
 			mgmt = WLAN_AKM_SUITE_PSK;
@@ -9676,6 +9722,39 @@
 }
 
 
+static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md,
+					    const u8 *ies, size_t ies_len)
+{
+	int ret;
+	struct nl_msg *msg;
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	u16 mdid = WPA_GET_LE16(md);
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -ENOMEM;
+
+	wpa_printf(MSG_DEBUG, "nl80211: Updating FT IEs");
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_UPDATE_FT_IES);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+	NLA_PUT(msg, NL80211_ATTR_IE, ies_len, ies);
+	NLA_PUT_U16(msg, NL80211_ATTR_MDID, mdid);
+
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed "
+			   "err=%d (%s)", ret, strerror(-ret));
+	}
+
+	return ret;
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+
+
 const struct wpa_driver_ops wpa_driver_nl80211_ops = {
 	.name = "nl80211",
 	.desc = "Linux nl80211/cfg80211",
@@ -9751,6 +9830,7 @@
 	.send_tdls_mgmt = nl80211_send_tdls_mgmt,
 	.tdls_oper = nl80211_tdls_oper,
 #endif /* CONFIG_TDLS */
+	.update_ft_ies = wpa_driver_nl80211_update_ft_ies,
 #ifdef ANDROID_P2P
 	.set_noa = wpa_driver_set_p2p_noa,
 	.get_noa = wpa_driver_get_p2p_noa,
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 704e531..2b5e5bd 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -3490,7 +3490,8 @@
 				"P2P: Invitation Request retry limit reached");
 			if (p2p->cfg->invitation_result)
 				p2p->cfg->invitation_result(
-					p2p->cfg->cb_ctx, -1, NULL, NULL);
+					p2p->cfg->cb_ctx, -1, NULL, NULL,
+					p2p->invite_peer->info.p2p_device_addr);
 		}
 		p2p_set_state(p2p, P2P_IDLE);
 	}
@@ -4319,6 +4320,14 @@
 }
 
 
+void p2p_set_own_freq_preference(struct p2p_data *p2p, int freq)
+{
+	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own frequency preference: "
+		"%d MHz", freq);
+	p2p->own_freq_preference = freq;
+}
+
+
 const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p)
 {
 	if (p2p == NULL || p2p->go_neg_peer == NULL)
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 4f9b75d..28a0a1d 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -743,6 +743,7 @@
 	 * @status: Negotiation result (Status Code)
 	 * @bssid: P2P Group BSSID or %NULL if not received
 	 * @channels: Available operating channels for the group
+	 * @addr: Peer address
 	 *
 	 * This callback is used to indicate result of an Invitation procedure
 	 * started with a call to p2p_invite(). The indicated status code is
@@ -751,7 +752,8 @@
 	 * local failure in transmitting the Invitation Request.
 	 */
 	void (*invitation_result)(void *ctx, int status, const u8 *bssid,
-				  const struct p2p_channels *channels);
+				  const struct p2p_channels *channels,
+				  const u8 *addr);
 
 	/**
 	 * go_connected - Check whether we are connected to a GO
@@ -1658,6 +1660,17 @@
 void p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
 			   int freq_overall);
 
+/**
+ * p2p_set_own_freq_preference - Set own preference for channel
+ * @p2p: P2P module context from p2p_init()
+ * @freq: Frequency (MHz) of the preferred channel or 0 if no preference
+ *
+ * This function can be used to set a preference on the operating channel based
+ * on frequencies used on the other virtual interfaces that share the same
+ * radio. If non-zero, this is used to try to avoid multi-channel concurrency.
+ */
+void p2p_set_own_freq_preference(struct p2p_data *p2p, int freq);
+
 const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p);
 
 /**
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index 61153d4..c143ef4 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -350,14 +350,36 @@
 	u8 op_reg_class, op_channel;
 	unsigned int i;
 
-	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating "
-		"channel (reg_class %u channel %u) not acceptable to the "
-		"peer", p2p->op_reg_class, p2p->op_channel);
+	if (p2p->own_freq_preference > 0 &&
+	    p2p_freq_to_channel(p2p->cfg->country, p2p->own_freq_preference,
+				&op_reg_class, &op_channel) == 0 &&
+	    p2p_channels_includes(intersection, op_reg_class, op_channel)) {
+		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick own channel "
+			"preference (reg_class %u channel %u) from "
+			"intersection", op_reg_class, op_channel);
+		p2p->op_reg_class = op_reg_class;
+		p2p->op_channel = op_channel;
+		return;
+	}
+
+	if (p2p->best_freq_overall > 0 &&
+	    p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_overall,
+				&op_reg_class, &op_channel) == 0 &&
+	    p2p_channels_includes(intersection, op_reg_class, op_channel)) {
+		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best overall "
+			"channel (reg_class %u channel %u) from intersection",
+			op_reg_class, op_channel);
+		p2p->op_reg_class = op_reg_class;
+		p2p->op_channel = op_channel;
+		return;
+	}
 
 	/* First, try to pick the best channel from another band */
 	freq = p2p_channel_to_freq(p2p->cfg->country, p2p->op_reg_class,
 				   p2p->op_channel);
 	if (freq >= 2400 && freq < 2500 && p2p->best_freq_5 > 0 &&
+	    !p2p_channels_includes(intersection, p2p->op_reg_class,
+				   p2p->op_channel) &&
 	    p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_5,
 				&op_reg_class, &op_channel) == 0 &&
 	    p2p_channels_includes(intersection, op_reg_class, op_channel)) {
@@ -370,6 +392,8 @@
 	}
 
 	if (freq >= 4900 && freq < 6000 && p2p->best_freq_24 > 0 &&
+	    !p2p_channels_includes(intersection, p2p->op_reg_class,
+				   p2p->op_channel) &&
 	    p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_24,
 				&op_reg_class, &op_channel) == 0 &&
 	    p2p_channels_includes(intersection, op_reg_class, op_channel)) {
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 5286b02..d5ce52f 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -430,6 +430,7 @@
 	int best_freq_24;
 	int best_freq_5;
 	int best_freq_overall;
+	int own_freq_preference;
 
 	/**
 	 * wps_vendor_ext - WPS Vendor Extensions to add
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index 43d9475..2ed9730 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -466,7 +466,7 @@
 
 	if (p2p->cfg->invitation_result)
 		p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
-					    msg.group_bssid, channels);
+					    msg.group_bssid, channels, sa);
 
 	p2p_parse_free(&msg);
 
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 09abdbb..bcd924c 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -1636,7 +1636,7 @@
 					   MACSTR " (terminate previously "
 					   "initiated negotiation",
 					   MAC2STR(src_addr));
-				wpa_tdls_peer_free(sm, peer);
+				wpa_tdls_disable_link(sm, peer->addr);
 			}
 		}
 	}
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 2df060c..4b08a62 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -788,9 +788,12 @@
 	if (parse.ric) {
 		wpa_hexdump(MSG_MSGDUMP, "FT: RIC Response",
 			    parse.ric, parse.ric_len);
-		/* TODO: parse response and inform driver about results */
+		/* TODO: parse response and inform driver about results when
+		 * using wpa_supplicant SME */
 	}
 
+	wpa_printf(MSG_DEBUG, "FT: Completed successfully");
+
 	return 0;
 }
 
diff --git a/src/tls/libtommath.c b/src/tls/libtommath.c
index 741b442..3fb8fbe 100644
--- a/src/tls/libtommath.c
+++ b/src/tls/libtommath.c
@@ -42,6 +42,9 @@
 /* Include faster sqr at the cost of about 0.5 kB in code */
 #define BN_FAST_S_MP_SQR_C
 
+/* About 0.25 kB of code, but ~1.7kB of stack space! */
+#define BN_FAST_S_MP_MUL_DIGS_C
+
 #else /* LTM_FAST */
 
 #define BN_MP_DIV_SMALL
@@ -139,7 +142,9 @@
 static int s_mp_sqr(mp_int * a, mp_int * b);
 static int s_mp_mul_high_digs(mp_int * a, mp_int * b, mp_int * c, int digs);
 
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
 static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+#endif
 
 #ifdef BN_MP_INIT_MULTI_C
 static int mp_init_multi(mp_int *mp, ...);
@@ -671,6 +676,9 @@
 #ifdef BN_MP_EXPTMOD_FAST_C
   }
 #endif
+  if (dr == 0) {
+    /* avoid compiler warnings about possibly unused variable */
+  }
 }
 
 
@@ -2339,12 +2347,14 @@
   mp_word r;
   mp_digit tmpx, *tmpt, *tmpy;
 
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
   /* can we use the fast multiplier? */
   if (((digs) < MP_WARRAY) &&
       MIN (a->used, b->used) < 
           (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
     return fast_s_mp_mul_digs (a, b, c, digs);
   }
+#endif
 
   if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
     return res;
@@ -2397,6 +2407,7 @@
 }
 
 
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
 /* Fast (comba) multiplier
  *
  * This is the fast column-array [comba] multiplier.  It is 
@@ -2482,6 +2493,7 @@
   mp_clamp (c);
   return MP_OKAY;
 }
+#endif /* BN_FAST_S_MP_MUL_DIGS_C */
 
 
 /* init an mp_init for a given size */