Cumulative patch from commit f95a4524c2c00476e46b7999426ffdcbc7cd538f

f95a452 nl80211: Improve debug output by printing SA and DA in frames
dedfa44 Print frame type name in debug output
57a8f8a nl80211: Use low-priority scan for OBSS scan
1b928f9 P2P: Allow passphrase length to be configured
e985246 eapol_test: Add PC/SC reader and PIN command line arguments
5a62060 Use pcsc_reader configuration in one for scard_init() call
f3c6b23 EAP-SIM': Fix AT_KDF parser to avoid infinite loop
79122f9 EAP-SIM/AKA: Remove unused RESULT_FAILURE state

Change-Id: I142bed35a75ed228e145e50c961dcde22a9815f7
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index ccbbab5..39edbd7 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -230,11 +230,12 @@
 	if (mgmt == NULL)
 		return -1;
 
-	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR
-		" with minor reason code %u (stype=%u)",
-		MAC2STR(addr), minor_reason_code, stype);
-
 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR
+		" with minor reason code %u (stype=%u (%s))",
+		MAC2STR(addr), minor_reason_code, stype,
+		fc2str(mgmt->frame_control));
+
 	os_memcpy(mgmt->da, addr, ETH_ALEN);
 	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
 	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index faa6a39..173a400 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -546,3 +546,60 @@
 
 	return num_11b > 0 && num_others == 0;
 }
+
+
+const char * fc2str(u16 fc)
+{
+	u16 stype = WLAN_FC_GET_STYPE(fc);
+#define C2S(x) case x: return #x;
+
+	switch (WLAN_FC_GET_TYPE(fc)) {
+	case WLAN_FC_TYPE_MGMT:
+		switch (stype) {
+		C2S(WLAN_FC_STYPE_ASSOC_REQ)
+		C2S(WLAN_FC_STYPE_ASSOC_RESP)
+		C2S(WLAN_FC_STYPE_REASSOC_REQ)
+		C2S(WLAN_FC_STYPE_REASSOC_RESP)
+		C2S(WLAN_FC_STYPE_PROBE_REQ)
+		C2S(WLAN_FC_STYPE_PROBE_RESP)
+		C2S(WLAN_FC_STYPE_BEACON)
+		C2S(WLAN_FC_STYPE_ATIM)
+		C2S(WLAN_FC_STYPE_DISASSOC)
+		C2S(WLAN_FC_STYPE_AUTH)
+		C2S(WLAN_FC_STYPE_DEAUTH)
+		C2S(WLAN_FC_STYPE_ACTION)
+		}
+		break;
+	case WLAN_FC_TYPE_CTRL:
+		switch (stype) {
+		C2S(WLAN_FC_STYPE_PSPOLL)
+		C2S(WLAN_FC_STYPE_RTS)
+		C2S(WLAN_FC_STYPE_CTS)
+		C2S(WLAN_FC_STYPE_ACK)
+		C2S(WLAN_FC_STYPE_CFEND)
+		C2S(WLAN_FC_STYPE_CFENDACK)
+		}
+		break;
+	case WLAN_FC_TYPE_DATA:
+		switch (stype) {
+		C2S(WLAN_FC_STYPE_DATA)
+		C2S(WLAN_FC_STYPE_DATA_CFACK)
+		C2S(WLAN_FC_STYPE_DATA_CFPOLL)
+		C2S(WLAN_FC_STYPE_DATA_CFACKPOLL)
+		C2S(WLAN_FC_STYPE_NULLFUNC)
+		C2S(WLAN_FC_STYPE_CFACK)
+		C2S(WLAN_FC_STYPE_CFPOLL)
+		C2S(WLAN_FC_STYPE_CFACKPOLL)
+		C2S(WLAN_FC_STYPE_QOS_DATA)
+		C2S(WLAN_FC_STYPE_QOS_DATA_CFACK)
+		C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL)
+		C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL)
+		C2S(WLAN_FC_STYPE_QOS_NULL)
+		C2S(WLAN_FC_STYPE_QOS_CFPOLL)
+		C2S(WLAN_FC_STYPE_QOS_CFACKPOLL)
+		}
+		break;
+	}
+	return "WLAN_FC_TYPE_UNKNOWN";
+#undef C2S
+}
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 9b8bbd1..cf83057 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -98,4 +98,5 @@
 
 int supp_rates_11b_only(struct ieee802_11_elems *elems);
 
+const char * fc2str(u16 fc);
 #endif /* IEEE802_11_COMMON_H */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 6e47b86..33f53af 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -351,7 +351,7 @@
 	 * Mbps from the support rates element(s) in the Probe Request frames
 	 * and not to transmit the frames at any of those rates.
 	 */
-	u8 p2p_probe;
+	unsigned int p2p_probe:1;
 
 	/**
 	 * only_new_results - Request driver to report only new results
@@ -360,7 +360,15 @@
 	 * been detected after this scan request has been started, i.e., to
 	 * flush old cached BSS entries.
 	 */
-	int only_new_results;
+	unsigned int only_new_results:1;
+
+	/**
+	 * low_priority - Requests driver to use a lower scan priority
+	 *
+	 * This is used to request the driver to use a lower scan priority
+	 * if it supports such a thing.
+	 */
+	unsigned int low_priority:1;
 
 	/*
 	 * NOTE: Whenever adding new parameters here, please make sure
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index aa2cd04..c154ec2 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -307,6 +307,7 @@
 	unsigned int test_use_roc_tx:1;
 	unsigned int ignore_deauth_event:1;
 	unsigned int dfs_vendor_cmd_avail:1;
+	unsigned int have_low_prio_scan:1;
 
 	u64 remain_on_chan_cookie;
 	u64 send_action_cookie;
@@ -1735,8 +1736,10 @@
 		rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
 	}
 	wpa_printf(MSG_DEBUG,
-		   "nl80211: RX frame freq=%d ssi_signal=%d stype=%u len=%u",
-		   rx_freq, ssi_signal, stype, (unsigned int) len);
+		   "nl80211: RX frame sa=" MACSTR
+		   " freq=%d ssi_signal=%d stype=%u (%s) len=%u",
+		   MAC2STR(mgmt->sa), rx_freq, ssi_signal, stype, fc2str(fc),
+		   (unsigned int) len);
 	event.rx_mgmt.frame = frame;
 	event.rx_mgmt.frame_len = len;
 	event.rx_mgmt.ssi_signal = ssi_signal;
@@ -3411,6 +3414,7 @@
 	unsigned int p2p_concurrent:1;
 	unsigned int channel_switch_supported:1;
 	unsigned int set_qos_map_supported:1;
+	unsigned int have_low_prio_scan:1;
 };
 
 
@@ -3689,6 +3693,9 @@
 
 	if (flags & NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE)
 		capa->flags |= WPA_DRIVER_FLAGS_HT_2040_COEX;
+
+	if (flags & NL80211_FEATURE_LOW_PRIORITY_SCAN)
+		info->have_low_prio_scan = 1;
 }
 
 
@@ -3981,6 +3988,7 @@
 	drv->data_tx_status = info.data_tx_status;
 	if (info.set_qos_map_supported)
 		drv->capa.flags |= WPA_DRIVER_FLAGS_QOS_MAPPING;
+	drv->have_low_prio_scan = info.have_low_prio_scan;
 
 	/*
 	 * If poll command and tx status are supported, mac80211 is new enough
@@ -4384,8 +4392,8 @@
 
 	buf[0] = '\0';
 	wpa_snprintf_hex(buf, sizeof(buf), match, match_len);
-	wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x nl_handle=%p match=%s",
-		   type, nl_handle, buf);
+	wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x (%s) nl_handle=%p match=%s",
+		   type, fc2str(type), nl_handle, buf);
 
 	nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_ACTION);
 
@@ -4949,6 +4957,7 @@
 {
 	struct nl_msg *msg;
 	size_t i;
+	u32 scan_flags = 0;
 
 	msg = nlmsg_alloc();
 	if (!msg)
@@ -5007,10 +5016,18 @@
 
 	if (params->only_new_results) {
 		wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_FLUSH");
-		NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS,
-			    NL80211_SCAN_FLAG_FLUSH);
+		scan_flags |= NL80211_SCAN_FLAG_FLUSH;
 	}
 
+	if (params->low_priority && drv->have_low_prio_scan) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Add NL80211_SCAN_FLAG_LOW_PRIORITY");
+		scan_flags |= NL80211_SCAN_FLAG_LOW_PRIORITY;
+	}
+
+	if (scan_flags)
+		NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS, scan_flags);
+
 	return msg;
 
 fail:
@@ -7070,8 +7087,10 @@
 
 	mgmt = (struct ieee80211_mgmt *) data;
 	fc = le_to_host16(mgmt->frame_control);
-	wpa_printf(MSG_DEBUG, "nl80211: send_mlme - noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u fc=0x%x nlmode=%d",
-		   noack, freq, no_cck, offchanok, wait_time, fc, drv->nlmode);
+	wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da= " MACSTR
+		   " noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u fc=0x%x (%s) nlmode=%d",
+		   MAC2STR(mgmt->da), noack, freq, no_cck, offchanok, wait_time,
+		   fc, fc2str(fc), drv->nlmode);
 
 	if ((is_sta_interface(drv->nlmode) ||
 	     drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) &&
diff --git a/src/eap_common/eap_sim_common.c b/src/eap_common/eap_sim_common.c
index e1773bf..ae02185 100644
--- a/src/eap_common/eap_sim_common.c
+++ b/src/eap_common/eap_sim_common.c
@@ -893,7 +893,7 @@
 			if (attr->kdf_count == EAP_AKA_PRIME_KDF_MAX) {
 				wpa_printf(MSG_DEBUG, "EAP-AKA': Too many "
 					   "AT_KDF attributes - ignore this");
-				continue;
+				break;
 			}
 			attr->kdf[attr->kdf_count] = WPA_GET_BE16(apos);
 			attr->kdf_count++;
diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c
index fee1b7b..3f31866 100644
--- a/src/eap_peer/eap_aka.c
+++ b/src/eap_peer/eap_aka.c
@@ -42,7 +42,7 @@
 	u8 *last_eap_identity;
 	size_t last_eap_identity_len;
 	enum {
-		CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE
+		CONTINUE, RESULT_SUCCESS, SUCCESS, FAILURE
 	} state;
 
 	struct wpabuf *id_msgs;
@@ -64,8 +64,6 @@
 		return "CONTINUE";
 	case RESULT_SUCCESS:
 		return "RESULT_SUCCESS";
-	case RESULT_FAILURE:
-		return "RESULT_FAILURE";
 	case SUCCESS:
 		return "SUCCESS";
 	case FAILURE:
@@ -1025,7 +1023,7 @@
 	if (data->result_ind && attr->result_ind)
 		data->use_result_ind = 1;
 
-	if (data->state != FAILURE && data->state != RESULT_FAILURE) {
+	if (data->state != FAILURE) {
 		eap_aka_state(data, data->use_result_ind ?
 			      RESULT_SUCCESS : SUCCESS);
 	}
@@ -1241,7 +1239,7 @@
 	if (data->result_ind && attr->result_ind)
 		data->use_result_ind = 1;
 
-	if (data->state != FAILURE && data->state != RESULT_FAILURE) {
+	if (data->state != FAILURE) {
 		eap_aka_state(data, data->use_result_ind ?
 			      RESULT_SUCCESS : SUCCESS);
 	}
@@ -1347,9 +1345,7 @@
 		 */
 		ret->methodState = data->use_result_ind ?
 			METHOD_DONE : METHOD_MAY_CONT;
-	} else if (data->state == RESULT_FAILURE)
-		ret->methodState = METHOD_CONT;
-	else if (data->state == RESULT_SUCCESS)
+	} else if (data->state == RESULT_SUCCESS)
 		ret->methodState = METHOD_CONT;
 
 	if (ret->methodState == METHOD_DONE) {
diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c
index fc9df96..63c8939 100644
--- a/src/eap_peer/eap_sim.c
+++ b/src/eap_peer/eap_sim.c
@@ -43,7 +43,7 @@
 	u8 *last_eap_identity;
 	size_t last_eap_identity_len;
 	enum {
-		CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE
+		CONTINUE, RESULT_SUCCESS, SUCCESS, FAILURE
 	} state;
 	int result_ind, use_result_ind;
 };
@@ -57,8 +57,6 @@
 		return "CONTINUE";
 	case RESULT_SUCCESS:
 		return "RESULT_SUCCESS";
-	case RESULT_FAILURE:
-		return "RESULT_FAILURE";
 	case SUCCESS:
 		return "SUCCESS";
 	case FAILURE:
@@ -788,7 +786,7 @@
 	if (data->result_ind && attr->result_ind)
 		data->use_result_ind = 1;
 
-	if (data->state != FAILURE && data->state != RESULT_FAILURE) {
+	if (data->state != FAILURE) {
 		eap_sim_state(data, data->use_result_ind ?
 			      RESULT_SUCCESS : SUCCESS);
 	}
@@ -989,7 +987,7 @@
 	if (data->result_ind && attr->result_ind)
 		data->use_result_ind = 1;
 
-	if (data->state != FAILURE && data->state != RESULT_FAILURE) {
+	if (data->state != FAILURE) {
 		eap_sim_state(data, data->use_result_ind ?
 			      RESULT_SUCCESS : SUCCESS);
 	}
@@ -1088,9 +1086,7 @@
 			DECISION_UNCOND_SUCC : DECISION_COND_SUCC;
 		ret->methodState = data->use_result_ind ?
 			METHOD_DONE : METHOD_MAY_CONT;
-	} else if (data->state == RESULT_FAILURE)
-		ret->methodState = METHOD_CONT;
-	else if (data->state == RESULT_SUCCESS)
+	} else if (data->state == RESULT_SUCCESS)
 		ret->methodState = METHOD_CONT;
 
 	if (ret->methodState == METHOD_DONE) {
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 104f77b..d0191e7 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1561,7 +1561,7 @@
 int p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params)
 {
 	p2p_build_ssid(p2p, params->ssid, &params->ssid_len);
-	p2p_random(params->passphrase, 8);
+	p2p_random(params->passphrase, p2p->cfg->passphrase_len);
 	return 0;
 }
 
@@ -1595,7 +1595,7 @@
 					       p2p->op_channel);
 		os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
 		res.ssid_len = p2p->ssid_len;
-		p2p_random(res.passphrase, 8);
+		p2p_random(res.passphrase, p2p->cfg->passphrase_len);
 	} else {
 		res.freq = peer->oper_freq;
 		if (p2p->ssid_len) {
@@ -2388,7 +2388,8 @@
 {
 	struct p2p_data *p2p;
 
-	if (cfg->max_peers < 1)
+	if (cfg->max_peers < 1 ||
+	    cfg->passphrase_len < 8 || cfg->passphrase_len > 63)
 		return NULL;
 
 	p2p = os_zalloc(sizeof(*p2p) + sizeof(*cfg));
@@ -4719,3 +4720,12 @@
 }
 
 #endif /* CONFIG_WPS_NFC */
+
+
+int p2p_set_passphrase_len(struct p2p_data *p2p, unsigned int len)
+{
+	if (len < 8 || len > 63)
+		return -1;
+	p2p->cfg->passphrase_len = len;
+	return 0;
+}
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 9cf100f..5938aa7 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -395,6 +395,14 @@
 	unsigned int max_listen;
 
 	/**
+	 * passphrase_len - Passphrase length (8..63)
+	 *
+	 * This parameter controls the length of the random passphrase that is
+	 * generated at the GO.
+	 */
+	unsigned int passphrase_len;
+
+	/**
 	 * cb_ctx - Context to use with callback functions
 	 */
 	void *cb_ctx;
@@ -1960,4 +1968,6 @@
 				      int go_intent,
 				      const u8 *own_interface_addr);
 
+int p2p_set_passphrase_len(struct p2p_data *p2p, unsigned int len);
+
 #endif /* P2P_H */