Accumulative patch from commit b57b560034f1bb1ad3a3892228940dde97323c0e

b57b560 wpa_supplicant: Default to nl80211 instead of wext
ee28f08 hostapd: Add more messages for error paths
61d2ce2 hostapd: Reject configuration file without interface parameter
a8a7890 Clear extra_blacklist_count on FLUSH command
c646862 WPS ER: Allow UPnP interface to be forced
728d971 Use status code 17 (unable to handle new STA) on max-STA limitation
5e24dc8 Add dup_binstr() to help common binary string tasks
8b44ad7 Use os_zalloc() instead of os_malloc() + os_memset()
2c48211 FT RRB: Validate os_malloc() return value before using it
7ca902b Make vlan_file optional if dynamic_vlan is used
bdb112d Add bitfield routines
04382f7 NFC: Add no waiting and no multiple operations options for scripts
fe90496 WPS: Fix AP auto configuration on config token generation
28fcfb6 NFC: Increase wpa_cli command buffer size
8f7a6dd WPS NFC: Allow Device Password ID override for selected registrar
aaecb69 WPS: Use generic MAC Address attribute builder
9ccd916 P2P: Clean up channel--frequency conversion functions
e864c0a Use a common frequency to channel conversion function
02db75b FT: Reset FT flag upon STA deauthentication
7800d45 P2P: Set P2P_DEV_PEER_WAITING_RESPONSE from TX status callback
d78d3c6 EAP peer: Add check before calling getSessionId method
dd57970 Disable network temporarily on repeated connection failures

Change-Id: If8078d5c1ff40ea806e844543cf6f2bf9d24b7ac
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/README b/wpa_supplicant/README
index d84e61e..f439632 100644
--- a/wpa_supplicant/README
+++ b/wpa_supplicant/README
@@ -115,13 +115,15 @@
 - NetBSD-current
 - Microsoft Windows with WinPcap (at least WinXP, may work with other versions)
 - drivers:
-	Linux drivers that support WPA/WPA2 configuration with the generic
-	Linux wireless extensions (WE-18 or newer). Even though there are
+	Linux drivers that support cfg80211/nl80211. Even though there are
 	number of driver specific interface included in wpa_supplicant, please
-	note that Linux drivers are moving to use generic wireless extensions
-	and driver_wext (-Dwext on wpa_supplicant command line) should be the
-	default option to start with before falling back to driver specific
-	interface.
+	note that Linux drivers are moving to use generic wireless configuration
+	interface driver_nl80211 (-Dnl80211 on wpa_supplicant command line)
+	should be the default option to start with before falling back to driver
+	specific interface.
+
+	Linux drivers that support WPA/WPA2 configuration with the generic
+	Linux wireless extensions (WE-18 or newer). Obsoleted by nl80211.
 
 	In theory, any driver that supports Linux wireless extensions can be
 	used with IEEE 802.1X (i.e., not WPA) when using ap_scan=0 option in
@@ -436,6 +438,7 @@
   -N = start describing new interface
 
 drivers:
+  nl80211 = Linux nl80211/cfg80211
   wext = Linux wireless extensions (generic)
   wired = wpa_supplicant wired Ethernet driver
   roboswitch = wpa_supplicant Broadcom switch driver
@@ -477,7 +480,7 @@
 interface needs to be configured to wpa_supplicant in addition to the
 main interface:
 
-wpa_supplicant -cw.conf -Dwext -iwlan0 -bbr0
+wpa_supplicant -cw.conf -Dnl80211 -iwlan0 -bbr0
 
 
 Configuration file
@@ -869,10 +872,10 @@
 # Start wpa_supplicant in the background
 wpa_supplicant -g/var/run/wpa_supplicant-global -B
 
-# Add a new interface (wlan0, no configuration file, driver=wext, and
+# Add a new interface (wlan0, no configuration file, driver=nl80211, and
 # enable control interface)
 wpa_cli -g/var/run/wpa_supplicant-global interface_add wlan0 \
-	"" wext /var/run/wpa_supplicant
+	"" nl80211 /var/run/wpa_supplicant
 
 # Configure a network using the newly added network interface:
 wpa_cli -iwlan0 add_network
@@ -933,7 +936,7 @@
   chmod 0750 /var/run/wpa_priv
 - start wpa_priv as root (e.g., from system startup scripts) with the
   enabled interfaces configured on the command line:
-  wpa_priv -B -P /var/run/wpa_priv.pid wext:ath0
+  wpa_priv -B -P /var/run/wpa_priv.pid nl80211:wlan0
 - run wpa_supplicant as non-root with a user that is in wpapriv group:
   wpa_supplicant -i ath0 -c wpa_supplicant.conf
 
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 4033492..d9e1f82 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -55,21 +55,14 @@
 		/* default channel 11 */
 		conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
 		conf->channel = 11;
-	} else if (ssid->frequency >= 2412 && ssid->frequency <= 2472) {
-		conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
-		conf->channel = (ssid->frequency - 2407) / 5;
-	} else if ((ssid->frequency >= 5180 && ssid->frequency <= 5240) ||
-		   (ssid->frequency >= 5745 && ssid->frequency <= 5825)) {
-		conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
-		conf->channel = (ssid->frequency - 5000) / 5;
-	} else if (ssid->frequency >= 56160 + 2160 * 1 &&
-		   ssid->frequency <= 56160 + 2160 * 4) {
-		conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
-		conf->channel = (ssid->frequency - 56160) / 2160;
 	} else {
-		wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
-			   ssid->frequency);
-		return -1;
+		conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
+						       &conf->channel);
+		if (conf->hw_mode == NUM_HOSTAPD_MODES) {
+			wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: "
+				   "%d MHz", ssid->frequency);
+			return -1;
+		}
 	}
 
 	/* TODO: enable HT40 if driver supports it;
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 0d98884..2de7845 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -322,11 +322,9 @@
 			return 0;
 		ssid->psk_set = 0;
 		os_free(ssid->passphrase);
-		ssid->passphrase = os_malloc(len + 1);
+		ssid->passphrase = dup_binstr(value, len);
 		if (ssid->passphrase == NULL)
 			return -1;
-		os_memcpy(ssid->passphrase, value, len);
-		ssid->passphrase[len] = '\0';
 		return 0;
 #else /* CONFIG_NO_PBKDF2 */
 		wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not "
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index f118cbf..8c06334 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -5092,6 +5092,7 @@
 
 	wpa_bss_flush(wpa_s);
 	wpa_blacklist_clear(wpa_s);
+	wpa_s->extra_blacklist_count = 0;
 	wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
 	wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
 }
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index aafa182..650221a 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2477,6 +2477,7 @@
 					    data->deauth_info.ie,
 					    data->deauth_info.ie_len);
 			}
+			wpa_reset_ft_completed(wpa_s->wpa);
 		}
 #ifdef CONFIG_AP
 		if (wpa_s->ap_iface && data && data->deauth_info.addr) {
diff --git a/wpa_supplicant/examples/wps-nfc.py b/wpa_supplicant/examples/wps-nfc.py
index dbc143a..d6dec85 100755
--- a/wpa_supplicant/examples/wps-nfc.py
+++ b/wpa_supplicant/examples/wps-nfc.py
@@ -49,17 +49,22 @@
 def wpas_tag_read(message):
     wpas = wpas_connect()
     if (wpas == None):
-        return
-    print wpas.request("WPS_NFC_TAG_READ " + message.encode("hex"))
-
+        return False
+    if "FAIL" in wpas.request("WPS_NFC_TAG_READ " + message.encode("hex")):
+        return False
+    return True
 
 def wpas_get_config_token(id=None):
     wpas = wpas_connect()
     if (wpas == None):
         return None
     if id:
-        return wpas.request("WPS_NFC_CONFIG_TOKEN NDEF " + id).rstrip().decode("hex")
-    return wpas.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip().decode("hex")
+        ret = wpas.request("WPS_NFC_CONFIG_TOKEN NDEF " + id)
+    else:
+        ret = wpas.request("WPS_NFC_CONFIG_TOKEN NDEF")
+    if "FAIL" in ret:
+        return None
+    return ret.rstrip().decode("hex")
 
 
 def wpas_get_er_config_token(uuid):
@@ -241,7 +246,8 @@
     print "Done with handover"
 
 
-def wps_tag_read(tag):
+def wps_tag_read(tag, wait_remove=True):
+    success = False
     if len(tag.ndef.message):
         message = nfc.ndef.Message(tag.ndef.message)
         print "message type " + message.type
@@ -250,21 +256,25 @@
             print "record type " + record.type
             if record.type == "application/vnd.wfa.wsc":
                 print "WPS tag - send to wpa_supplicant"
-                wpas_tag_read(tag.ndef.message)
+                success = wpas_tag_read(tag.ndef.message)
                 break
     else:
         print "Empty tag"
 
-    print "Remove tag"
-    while tag.is_present:
-        time.sleep(0.1)
+    if wait_remove:
+        print "Remove tag"
+        while tag.is_present:
+            time.sleep(0.1)
+
+    return success
 
 
-def wps_write_config_tag(clf, id=None):
+def wps_write_config_tag(clf, id=None, wait_remove=True):
     print "Write WPS config token"
     data = wpas_get_config_token(id)
     if (data == None):
         print "Could not get WPS config token from wpa_supplicant"
+        sys.exit(1)
         return
 
     print "Touch an NFC tag"
@@ -278,7 +288,7 @@
     print "Tag found - writing"
     tag.ndef.message = data
     print "Done - remove tag"
-    while tag.is_present:
+    while wait_remove and tag.is_present:
         time.sleep(0.1)
 
 
@@ -304,7 +314,7 @@
         time.sleep(0.1)
 
 
-def wps_write_password_tag(clf):
+def wps_write_password_tag(clf, wait_remove=True):
     print "Write WPS password token"
     data = wpas_get_password_token()
     if (data == None):
@@ -322,7 +332,7 @@
     print "Tag found - writing"
     tag.ndef.message = data
     print "Done - remove tag"
-    while tag.is_present:
+    while wait_remove and tag.is_present:
         time.sleep(0.1)
 
 
@@ -359,13 +369,22 @@
 
     try:
         arg_uuid = None
-        if len(sys.argv) > 1:
+        if len(sys.argv) > 1 and sys.argv[1] != '-1':
             arg_uuid = sys.argv[1]
 
+        if len(sys.argv) > 1 and sys.argv[1] == '-1':
+            only_one = True
+        else:
+            only_one = False
+
         if len(sys.argv) > 1 and sys.argv[1] == "write-config":
             wps_write_config_tag(clf)
             raise SystemExit
 
+        if len(sys.argv) > 1 and sys.argv[1] == "write-config-no-wait":
+            wps_write_config_tag(clf, wait_remove=False)
+            raise SystemExit
+
         if len(sys.argv) > 2 and sys.argv[1] == "write-config-id":
             wps_write_config_tag(clf, sys.argv[2])
             raise SystemExit
@@ -378,6 +397,10 @@
             wps_write_password_tag(clf)
             raise SystemExit
 
+        if len(sys.argv) > 1 and sys.argv[1] == "write-password-no-wait":
+            wps_write_password_tag(clf, wait_remove=False)
+            raise SystemExit
+
         while True:
             print "Waiting for a tag or peer to be touched"
 
@@ -389,13 +412,21 @@
                     wps_handover_resp(tag, None)
                 else:
                     wps_handover_resp(tag, arg_uuid)
+                if only_one:
+                    break
                 continue
 
             if tag.ndef:
-                wps_tag_read(tag)
+                success = wps_tag_read(tag, not only_one)
+                if only_one:
+                    if not success:
+                        sys.exit(1)
+                    break
                 continue
 
             print "Not an NDEF tag - remove tag"
+            if only_one:
+                sys.exit(1)
             while tag.is_present:
                 time.sleep(0.1)
 
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index b59dd6a..e35628b 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -408,11 +408,9 @@
 		return NULL;
 	}
 	wpa_hexdump_ascii(MSG_DEBUG, "NAI Realm", pos, realm_len);
-	r->realm = os_malloc(realm_len + 1);
+	r->realm = dup_binstr(pos, realm_len);
 	if (r->realm == NULL)
 		return NULL;
-	os_memcpy(r->realm, pos, realm_len);
-	r->realm[realm_len] = '\0';
 	pos += realm_len;
 
 	if (pos + 1 > f_end) {
diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c
index 1744620..f45c1b7 100644
--- a/wpa_supplicant/main.c
+++ b/wpa_supplicant/main.c
@@ -84,7 +84,7 @@
 
 	printf("example:\n"
 	       "  wpa_supplicant -D%s -iwlan0 -c/etc/wpa_supplicant.conf\n",
-	       wpa_drivers[i] ? wpa_drivers[i]->name : "wext");
+	       wpa_drivers[0] ? wpa_drivers[0]->name : "nl80211");
 #endif /* CONFIG_NO_STDOUT_DEBUG */
 }
 
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 4c78161..982e124 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -942,39 +942,6 @@
 }
 
 
-/**
- * enum wpas_band - Frequency band
- * @WPAS_BAND_2GHZ: 2.4 GHz ISM band
- * @WPAS_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz)
- */
-enum wpas_band {
-	WPAS_BAND_2GHZ,
-	WPAS_BAND_5GHZ,
-	WPAS_BAND_INVALID
-};
-
-/**
- * freq_to_channel - Convert frequency into channel info
- * @channel: Buffer for returning channel number
- * Returns: Band (2 or 5 GHz)
- */
-static enum wpas_band freq_to_channel(int freq, u8 *channel)
-{
-	enum wpas_band band = (freq <= 2484) ? WPAS_BAND_2GHZ : WPAS_BAND_5GHZ;
-	u8 chan = 0;
-
-	if (freq >= 2412 && freq <= 2472)
-		chan = (freq - 2407) / 5;
-	else if (freq == 2484)
-		chan = 14;
-	else if (freq >= 5180 && freq <= 5805)
-		chan = (freq - 5000) / 5;
-
-	*channel = chan;
-	return band;
-}
-
-
 int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
 {
 	struct wpa_bss *bss;
@@ -1011,7 +978,10 @@
 
 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
 		/* Skip other band bss */
-		if (freq_to_channel(bss->freq, &channel) != WPAS_BAND_2GHZ)
+		enum hostapd_hw_mode mode;
+		mode = ieee80211_freq_to_chan(bss->freq, &channel);
+		if (mode != HOSTAPD_MODE_IEEE80211G &&
+		    mode != HOSTAPD_MODE_IEEE80211B)
 			continue;
 
 		ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 6238c11..204d13e 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -176,11 +176,9 @@
 	end = os_strchr(txt, ' ');
 	if (end == NULL)
 		end = txt + os_strlen(txt);
-	buf = os_malloc(end - txt + 1);
+	buf = dup_binstr(txt, end - txt);
 	if (buf == NULL)
 		return;
-	os_memcpy(buf, txt, end - txt);
-	buf[end - txt] = '\0';
 	cli_txt_list_del(txt_list, buf);
 	os_free(buf);
 }
@@ -226,11 +224,9 @@
 	end = os_strchr(txt, ' ');
 	if (end == NULL)
 		end = txt + os_strlen(txt);
-	buf = os_malloc(end - txt + 1);
+	buf = dup_binstr(txt, end - txt);
 	if (buf == NULL)
 		return -1;
-	os_memcpy(buf, txt, end - txt);
-	buf[end - txt] = '\0';
 	ret = cli_txt_list_add(txt_list, buf);
 	os_free(buf);
 	return ret;
@@ -489,7 +485,7 @@
 static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
 		       int argc, char *argv[])
 {
-	char buf[256];
+	char buf[4096];
 	if (argc < min_args) {
 		printf("Invalid %s command - at least %d argument%s "
 		       "required.\n", cmd, min_args,
diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c
index ad6a080..4afaae9 100644
--- a/wpa_supplicant/wpa_priv.c
+++ b/wpa_supplicant/wpa_priv.c
@@ -573,13 +573,11 @@
 	iface->fd = -1;
 
 	len = pos - params;
-	iface->driver_name = os_malloc(len + 1);
+	iface->driver_name = dup_binstr(params, len);
 	if (iface->driver_name == NULL) {
 		wpa_priv_interface_deinit(iface);
 		return NULL;
 	}
-	os_memcpy(iface->driver_name, params, len);
-	iface->driver_name[len] = '\0';
 
 	for (i = 0; wpa_drivers[i]; i++) {
 		if (os_strcmp(iface->driver_name,
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 4ef9408..a66f654 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3584,6 +3584,12 @@
 	 */
 	count += wpa_s->extra_blacklist_count;
 
+	if (count > 3 && wpa_s->current_ssid) {
+		wpa_printf(MSG_DEBUG, "Continuous association failures - "
+			   "consider temporary network disabling");
+		wpas_auth_failed(wpa_s);
+	}
+
 	switch (count) {
 	case 1:
 		timeout = 100;