Update to new version 0.8.16 from BRCM

Sync with main tree commit b8349523e460493fa0b4de36c689595109e45e91
Author: Neeraj Kumar Garg <neerajkg@broadcom.com>
Date:   Tue Dec 27 23:21:45 2011 +0200
    P2P: Reject p2p_group_add if forced frequency is not acceptable

Change-Id: Icb4541a371b05c270e80440d7a7fdea7f33ff61e
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 4f555a0..255c802 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -19,7 +19,7 @@
 L_CFLAGS += -DANDROID_LOG_NAME=\"hostapd\"
 
 ifeq ($(BOARD_WLAN_DEVICE), bcmdhd)
-L_CFLAGS += -DANDROID_BRCM_P2P_PATCH
+L_CFLAGS += -DANDROID_P2P
 endif
 
 # To force sizeof(enum) = 4
@@ -79,6 +79,8 @@
 OBJS += src/ap/wpa_auth_ie.c
 OBJS += src/ap/preauth_auth.c
 OBJS += src/ap/pmksa_cache_auth.c
+OBJS += src/ap/ieee802_11_shared.c
+OBJS += src/ap/beacon.c
 OBJS_d =
 OBJS_p =
 LIBS =
@@ -756,7 +758,6 @@
 endif
 
 ifdef NEED_AP_MLME
-OBJS += src/ap/beacon.c
 OBJS += src/ap/wmm.c
 OBJS += src/ap/ap_list.c
 OBJS += src/ap/ieee802_11.c
@@ -772,6 +773,8 @@
 OBJS += src/ap/p2p_hostapd.c
 endif
 
+OBJS += src/drivers/driver_common.c
+
 ifdef CONFIG_NO_STDOUT_DEBUG
 L_CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
 endif
@@ -785,9 +788,15 @@
 endif
 
 OBJS_c = hostapd_cli.c src/common/wpa_ctrl.c src/utils/os_$(CONFIG_OS).c
+OBJS_c += src/utils/eloop.c
 ifdef CONFIG_WPA_TRACE
 OBJS_c += src/utils/trace.c
+endif
 OBJS_c += src/utils/wpa_debug.c
+ifdef CONFIG_WPA_CLI_EDIT
+OBJS_c += src/utils/edit.c
+else
+OBJS_c += src/utils/edit_simple.c
 endif
 
 ########################
diff --git a/hostapd/ChangeLog b/hostapd/ChangeLog
index a8417d6..47f2423 100644
--- a/hostapd/ChangeLog
+++ b/hostapd/ChangeLog
@@ -82,7 +82,7 @@
 	* updated management frame protection to use IEEE Std 802.11w-2009
 	* fixed number of small WPS issues and added workarounds to
 	  interoperate with common deployed broken implementations
-	* added some IEEE 802.11n co-existance rules to disable 40 MHz channels
+	* added some IEEE 802.11n co-existence rules to disable 40 MHz channels
 	  or modify primary/secondary channels if needed based on neighboring
 	  networks
 	* added support for NFC out-of-band mechanism with WPS
diff --git a/hostapd/Makefile b/hostapd/Makefile
index d05975b..22c09c1 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -51,6 +51,10 @@
 OBJS += ../src/ap/wpa_auth_ie.o
 OBJS += ../src/ap/preauth_auth.o
 OBJS += ../src/ap/pmksa_cache_auth.o
+OBJS += ../src/ap/ieee802_11_shared.o
+OBJS += ../src/ap/beacon.o
+
+OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
 
 NEED_RC4=y
 NEED_AES=y
@@ -74,9 +78,14 @@
 endif
 endif
 
-OBJS += ../src/utils/eloop.o
+ifndef CONFIG_ELOOP
+CONFIG_ELOOP=eloop
+endif
+OBJS += ../src/utils/$(CONFIG_ELOOP).o
+OBJS_c += ../src/utils/$(CONFIG_ELOOP).o
 OBJS += ../src/utils/common.o
 OBJS += ../src/utils/wpa_debug.o
+OBJS_c += ../src/utils/wpa_debug.o
 OBJS += ../src/utils/wpabuf.o
 OBJS += ../src/utils/os_$(CONFIG_OS).o
 OBJS += ../src/utils/ip_addr.o
@@ -427,6 +436,15 @@
 CONFIG_TLS=openssl
 endif
 
+ifdef CONFIG_TLSV11
+CFLAGS += -DCONFIG_TLSV11
+endif
+
+ifdef CONFIG_TLSV12
+CFLAGS += -DCONFIG_TLSV12
+NEED_SHA256=y
+endif
+
 ifeq ($(CONFIG_TLS), openssl)
 ifdef TLS_FUNCS
 OBJS += ../src/crypto/tls_openssl.o
@@ -445,10 +463,6 @@
 ifdef TLS_FUNCS
 OBJS += ../src/crypto/tls_gnutls.o
 LIBS += -lgnutls -lgpg-error
-ifdef CONFIG_GNUTLS_EXTRA
-CFLAGS += -DCONFIG_GNUTLS_EXTRA
-LIBS += -lgnutls-extra
-endif
 endif
 OBJS += ../src/crypto/crypto_gnutls.o
 HOBJS += ../src/crypto/crypto_gnutls.o
@@ -510,6 +524,9 @@
 NEED_SHA256=y
 NEED_BASE64=y
 NEED_TLS_PRF=y
+ifdef CONFIG_TLSV12
+NEED_TLS_PRF_SHA256=y
+endif
 NEED_MODEXP=y
 NEED_CIPHER=y
 CFLAGS += -DCONFIG_TLS_INTERNAL
@@ -669,10 +686,14 @@
 endif
 
 ifdef NEED_SHA256
+CFLAGS += -DCONFIG_SHA256
 OBJS += ../src/crypto/sha256.o
 ifdef CONFIG_INTERNAL_SHA256
 OBJS += ../src/crypto/sha256-internal.o
 endif
+ifdef NEED_TLS_PRF_SHA256
+OBJS += ../src/crypto/sha256-tlsprf.o
+endif
 endif
 
 ifdef NEED_DH_GROUPS
@@ -692,6 +713,7 @@
 else
 OBJS += ../src/crypto/random.o
 HOBJS += ../src/crypto/random.o
+HOBJS += ../src/utils/eloop.o
 HOBJS += $(SHA1OBJS)
 HOBJS += ../src/crypto/md5.o
 endif
@@ -720,7 +742,6 @@
 endif
 
 ifdef NEED_AP_MLME
-OBJS += ../src/ap/beacon.o
 OBJS += ../src/ap/wmm.o
 OBJS += ../src/ap/ap_list.o
 OBJS += ../src/ap/ieee802_11.o
@@ -736,6 +757,18 @@
 OBJS += ../src/ap/p2p_hostapd.o
 endif
 
+ifdef CONFIG_INTERWORKING
+CFLAGS += -DCONFIG_INTERWORKING
+endif
+
+OBJS += ../src/drivers/driver_common.o
+
+ifdef CONFIG_WPA_CLI_EDIT
+OBJS_c += ../src/utils/edit.o
+else
+OBJS_c += ../src/utils/edit_simple.o
+endif
+
 ifdef CONFIG_NO_STDOUT_DEBUG
 CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
 endif
@@ -784,10 +817,8 @@
 	$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
 	@$(E) "  LD " $@
 
-OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
 ifdef CONFIG_WPA_TRACE
 OBJS_c += ../src/utils/trace.o
-OBJS_c += ../src/utils/wpa_debug.o
 endif
 hostapd_cli: $(OBJS_c)
 	$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index bfd4809..467d39f 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -330,7 +330,7 @@
 			}
 
 			num_methods++;
-			if (num_methods >= EAP_USER_MAX_METHODS)
+			if (num_methods >= EAP_MAX_METHODS)
 				break;
 		skip_eap:
 			if (pos3 == NULL)
@@ -1050,9 +1050,18 @@
 		return -1;
 	}
 
+	if (bss->wpa && bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
+	    bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
+		wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no "
+			   "RADIUS checking (macaddr_acl=2) enabled.");
+		return -1;
+	}
+
 	if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
 	    bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL &&
-	    bss->ssid.wpa_psk_file == NULL) {
+	    bss->ssid.wpa_psk_file == NULL &&
+	    (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED ||
+	     bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) {
 		wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase "
 			   "is not configured.");
 		return -1;
@@ -1075,8 +1084,7 @@
 	}
 
 #ifdef CONFIG_IEEE80211R
-	if ((bss->wpa_key_mgmt &
-	     (WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_FT_IEEE8021X)) &&
+	if (wpa_key_mgmt_ft(bss->wpa_key_mgmt) &&
 	    (bss->nas_identifier == NULL ||
 	     os_strlen(bss->nas_identifier) < 1 ||
 	     os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) {
@@ -1142,6 +1150,40 @@
 }
 
 
+#ifdef CONFIG_INTERWORKING
+static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos,
+				    int line)
+{
+	size_t len = os_strlen(pos);
+	u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
+
+	struct hostapd_roaming_consortium *rc;
+
+	if ((len & 1) || len < 2 * 3 || len / 2 > MAX_ROAMING_CONSORTIUM_LEN ||
+	    hexstr2bin(pos, oi, len / 2)) {
+		wpa_printf(MSG_ERROR, "Line %d: invalid roaming_consortium "
+			   "'%s'", line, pos);
+		return -1;
+	}
+	len /= 2;
+
+	rc = os_realloc(bss->roaming_consortium,
+			sizeof(struct hostapd_roaming_consortium) *
+			(bss->roaming_consortium_count + 1));
+	if (rc == NULL)
+		return -1;
+
+	os_memcpy(rc[bss->roaming_consortium_count].oi, oi, len);
+	rc[bss->roaming_consortium_count].len = len;
+
+	bss->roaming_consortium = rc;
+	bss->roaming_consortium_count++;
+
+	return 0;
+}
+#endif /* CONFIG_INTERWORKING */
+
+
 /**
  * hostapd_config_read - Read and parse a configuration file
  * @fname: Configuration file name (including path, if needed)
@@ -1292,6 +1334,8 @@
 			bss->isolate = atoi(pos);
 		} else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
 			bss->ap_max_inactivity = atoi(pos);
+		} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
+			bss->skip_inactivity_poll = atoi(pos);
 		} else if (os_strcmp(buf, "country_code") == 0) {
 			os_memcpy(conf->country, pos, 2);
 			/* FIX: make this configurable */
@@ -1596,6 +1640,16 @@
 				hostapd_config_parse_key_mgmt(line, pos);
 			if (bss->wpa_key_mgmt == -1)
 				errors++;
+		} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
+			bss->wpa_psk_radius = atoi(pos);
+			if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
+			    bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED &&
+			    bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) {
+				wpa_printf(MSG_ERROR, "Line %d: unknown "
+					   "wpa_psk_radius %d",
+					   line, bss->wpa_psk_radius);
+				errors++;
+			}
 		} else if (os_strcmp(buf, "wpa_pairwise") == 0) {
 			bss->wpa_pairwise =
 				hostapd_config_parse_cipher(line, pos);
@@ -1735,6 +1789,21 @@
 					   "hw_mode '%s'", line, pos);
 				errors++;
 			}
+		} else if (os_strcmp(buf, "wps_rf_bands") == 0) {
+			if (os_strcmp(pos, "a") == 0)
+				bss->wps_rf_bands = WPS_RF_50GHZ;
+			else if (os_strcmp(pos, "g") == 0 ||
+				 os_strcmp(pos, "b") == 0)
+				bss->wps_rf_bands = WPS_RF_24GHZ;
+			else if (os_strcmp(pos, "ag") == 0 ||
+				 os_strcmp(pos, "ga") == 0)
+				bss->wps_rf_bands =
+					WPS_RF_24GHZ | WPS_RF_50GHZ;
+			else {
+				wpa_printf(MSG_ERROR, "Line %d: unknown "
+					   "wps_rf_band '%s'", line, pos);
+				errors++;
+			}
 		} else if (os_strcmp(buf, "channel") == 0) {
 			conf->channel = atoi(pos);
 		} else if (os_strcmp(buf, "beacon_int") == 0) {
@@ -2058,6 +2127,60 @@
 			extern int rsn_testing;
 			rsn_testing = atoi(pos);
 #endif /* CONFIG_RSN_TESTING */
+		} else if (os_strcmp(buf, "time_advertisement") == 0) {
+			bss->time_advertisement = atoi(pos);
+		} else if (os_strcmp(buf, "time_zone") == 0) {
+			size_t tz_len = os_strlen(pos);
+			if (tz_len < 4 || tz_len > 255) {
+				wpa_printf(MSG_DEBUG, "Line %d: invalid "
+					   "time_zone", line);
+				errors++;
+				continue;
+			}
+			os_free(bss->time_zone);
+			bss->time_zone = os_strdup(pos);
+			if (bss->time_zone == NULL)
+				errors++;
+#ifdef CONFIG_INTERWORKING
+		} else if (os_strcmp(buf, "interworking") == 0) {
+			bss->interworking = atoi(pos);
+		} else if (os_strcmp(buf, "access_network_type") == 0) {
+			bss->access_network_type = atoi(pos);
+			if (bss->access_network_type < 0 ||
+			    bss->access_network_type > 15) {
+				wpa_printf(MSG_ERROR, "Line %d: invalid "
+					   "access_network_type", line);
+				errors++;
+			}
+		} else if (os_strcmp(buf, "internet") == 0) {
+			bss->internet = atoi(pos);
+		} else if (os_strcmp(buf, "asra") == 0) {
+			bss->asra = atoi(pos);
+		} else if (os_strcmp(buf, "esr") == 0) {
+			bss->esr = atoi(pos);
+		} else if (os_strcmp(buf, "uesa") == 0) {
+			bss->uesa = atoi(pos);
+		} else if (os_strcmp(buf, "venue_group") == 0) {
+			bss->venue_group = atoi(pos);
+			bss->venue_info_set = 1;
+		} else if (os_strcmp(buf, "venue_type") == 0) {
+			bss->venue_type = atoi(pos);
+			bss->venue_info_set = 1;
+		} else if (os_strcmp(buf, "hessid") == 0) {
+			if (hwaddr_aton(pos, bss->hessid)) {
+				wpa_printf(MSG_ERROR, "Line %d: invalid "
+					   "hessid", line);
+				errors++;
+			}
+		} else if (os_strcmp(buf, "roaming_consortium") == 0) {
+			if (parse_roaming_consortium(bss, pos, line) < 0)
+				errors++;
+#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_RADIUS_TEST
+		} else if (os_strcmp(buf, "dump_msk_file") == 0) {
+			os_free(bss->dump_msk_file);
+			bss->dump_msk_file = os_strdup(pos);
+#endif /* CONFIG_RADIUS_TEST */
 		} else {
 			wpa_printf(MSG_ERROR, "Line %d: unknown configuration "
 				   "item '%s'", line, buf);
@@ -2099,12 +2222,29 @@
 		} else if (bss->wpa) {
 			bss->ssid.security_policy = SECURITY_WPA_PSK;
 		} else if (bss->ieee802_1x) {
+			int cipher = WPA_CIPHER_NONE;
 			bss->ssid.security_policy = SECURITY_IEEE_802_1X;
 			bss->ssid.wep.default_len = bss->default_wep_key_len;
-		} else if (bss->ssid.wep.keys_set)
+			if (bss->default_wep_key_len)
+				cipher = bss->default_wep_key_len >= 13 ?
+					WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
+			bss->wpa_group = cipher;
+			bss->wpa_pairwise = cipher;
+			bss->rsn_pairwise = cipher;
+		} else if (bss->ssid.wep.keys_set) {
+			int cipher = WPA_CIPHER_WEP40;
+			if (bss->ssid.wep.len[0] >= 13)
+				cipher = WPA_CIPHER_WEP104;
 			bss->ssid.security_policy = SECURITY_STATIC_WEP;
-		else
+			bss->wpa_group = cipher;
+			bss->wpa_pairwise = cipher;
+			bss->rsn_pairwise = cipher;
+		} else {
 			bss->ssid.security_policy = SECURITY_PLAINTEXT;
+			bss->wpa_group = WPA_CIPHER_NONE;
+			bss->wpa_pairwise = WPA_CIPHER_NONE;
+			bss->rsn_pairwise = WPA_CIPHER_NONE;
+		}
 	}
 
 	if (hostapd_config_check(conf))
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 195b8a7..a38d77c 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -32,7 +32,6 @@
 #include "ap/wpa_auth.h"
 #include "ap/ieee802_11.h"
 #include "ap/sta_info.h"
-#include "ap/accounting.h"
 #include "ap/wps_hostapd.h"
 #include "ap/ctrl_iface_ap.h"
 #include "ap/ap_drv_ops.h"
@@ -174,9 +173,9 @@
 	if (mgmt == NULL)
 		return -1;
 
-	wpa_printf(MSG_DEBUG, "P2P: Disconnect STA " MACSTR " with minor "
-		   "reason code %u (stype=%u)",
-		   MAC2STR(addr), minor_reason_code, stype);
+	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);
 	os_memcpy(mgmt->da, addr, ETH_ALEN);
@@ -219,7 +218,8 @@
 	struct sta_info *sta;
 	const char *pos;
 
-	wpa_printf(MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", txtaddr);
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s",
+		txtaddr);
 
 	if (hwaddr_aton(txtaddr, addr))
 		return -1;
@@ -275,7 +275,8 @@
 	struct sta_info *sta;
 	const char *pos;
 
-	wpa_printf(MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", txtaddr);
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s",
+		txtaddr);
 
 	if (hwaddr_aton(txtaddr, addr))
 		return -1;
@@ -526,6 +527,57 @@
 #endif /* CONFIG_WPS */
 
 
+static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
+					   const char *cmd)
+{
+	u8 addr[ETH_ALEN];
+	const char *url;
+	u8 buf[1000], *pos;
+	struct ieee80211_mgmt *mgmt;
+	size_t url_len;
+
+	if (hwaddr_aton(cmd, addr))
+		return -1;
+	url = cmd + 17;
+	if (*url != ' ')
+		return -1;
+	url++;
+	url_len = os_strlen(url);
+	if (url_len > 255)
+		return -1;
+
+	os_memset(buf, 0, sizeof(buf));
+	mgmt = (struct ieee80211_mgmt *) buf;
+	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+					   WLAN_FC_STYPE_ACTION);
+	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);
+	mgmt->u.action.category = WLAN_ACTION_WNM;
+	mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
+	mgmt->u.action.u.bss_tm_req.dialog_token = 1;
+	mgmt->u.action.u.bss_tm_req.req_mode =
+		WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
+	mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0);
+	mgmt->u.action.u.bss_tm_req.validity_interval = 0;
+
+	pos = mgmt->u.action.u.bss_tm_req.variable;
+
+	/* Session Information URL */
+	*pos++ = url_len;
+	os_memcpy(pos, url, url_len);
+	pos += url_len;
+
+	if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+		wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
+			   "Management Request frame");
+		return -1;
+	}
+
+	return 0;
+}
+
+
 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
 					 char *buf, size_t buflen)
 {
@@ -879,6 +931,9 @@
 		if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
 			reply_len = -1;
 #endif /* CONFIG_WPS */
+	} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
+		if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
+			reply_len = -1;
 	} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
 		reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
 							  reply_size);
diff --git a/hostapd/defconfig b/hostapd/defconfig
index 26be2a8..bae5ba2 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -208,3 +208,40 @@
 # considered for builds that are known to be used on devices that meet the
 # requirements described above.
 #CONFIG_NO_RANDOM_POOL=y
+
+# Select TLS implementation
+# openssl = OpenSSL (default)
+# gnutls = GnuTLS
+# internal = Internal TLSv1 implementation (experimental)
+# none = Empty template
+#CONFIG_TLS=openssl
+
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
+# can be enabled to get a stronger construction of messages when block ciphers
+# are used.
+#CONFIG_TLSV11=y
+
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
+# can be enabled to enable use of stronger crypto algorithms.
+#CONFIG_TLSV12=y
+
+# If CONFIG_TLS=internal is used, additional library and include paths are
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
+# and drawbacks of this option.
+#CONFIG_INTERNAL_LIBTOMMATH=y
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
+#LTM_PATH=/usr/src/libtommath-0.39
+#CFLAGS += -I$(LTM_PATH)
+#LIBS += -L$(LTM_PATH)
+#LIBS_p += -L$(LTM_PATH)
+#endif
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
+# can be configured to include faster routines for exptmod, sqr, and div to
+# speed up DH and RSA calculation considerably
+#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
+
+# Interworking (IEEE 802.11u)
+# This can be used to enable functionality to improve interworking with
+# external networks.
+#CONFIG_INTERWORKING=y
diff --git a/hostapd/dump_state.c b/hostapd/dump_state.c
index 73aa93d..110cedc 100644
--- a/hostapd/dump_state.c
+++ b/hostapd/dump_state.c
@@ -13,6 +13,7 @@
  */
 
 #include "utils/includes.h"
+#include <time.h>
 
 #include "utils/common.h"
 #include "radius/radius_client.h"
@@ -106,7 +107,8 @@
 		fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
 
 		fprintf(f,
-			"  AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
+			"  AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
+			"\n"
 			"  capability=0x%x listen_interval=%d\n",
 			sta->aid,
 			sta->flags,
@@ -127,6 +129,7 @@
 			(sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
 			(sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
 			(sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
+			(sta->flags & WLAN_STA_WPS2 ? "[WPS2]" : ""),
 			sta->capability,
 			sta->listen_interval);
 
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 3b1548c..4e6202b 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -99,19 +99,18 @@
 
 # Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,
 # Default: IEEE 802.11b
-hw_mode=a
+hw_mode=g
 
 # Channel number (IEEE 802.11)
 # (default: 0, i.e., not set)
-# Please note that some drivers (e.g., madwifi) do not use this value from
-# hostapd and the channel will need to be configuration separately with
-# iwconfig.
-channel=60
+# Please note that some drivers do not use this value from hostapd and the
+# channel will need to be configured separately with iwconfig.
+channel=1
 
 # Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
 beacon_int=100
 
-# DTIM (delivery trafic information message) period (range 1..255):
+# DTIM (delivery traffic information message) period (range 1..255):
 # number of beacons between DTIMs (1 = every beacon includes DTIM element)
 # (default: 2)
 dtim_period=2
@@ -340,6 +339,12 @@
 # the STA with a data frame.
 # default: 300 (i.e., 5 minutes)
 #ap_max_inactivity=300
+#
+# The inactivity polling can be disabled to disconnect stations based on
+# inactivity timeout so that idle stations are more likely to be disconnected
+# even if they are still in range of the AP. This can be done by setting
+# skip_inactivity_poll to 1 (default 0).
+#skip_inactivity_poll=0
 
 # Disassociate stations based on excessive transmission failures or other
 # indications of connection loss. This depends on the driver capabilities and
@@ -511,6 +516,10 @@
 # Fragment size for EAP methods
 #fragment_size=1400
 
+# Finite cyclic group for EAP-pwd. Number maps to group of domain parameters
+# using the IANA repository for IKE (RFC 2409).
+#pwd_group=19
+
 # Configuration data for EAP-SIM database/authentication gateway interface.
 # This is a text string in implementation specific format. The example
 # implementation in eap_sim_db.c uses this as the UNIX domain socket name for
@@ -673,6 +682,7 @@
 # Enable WPA. Setting this variable configures the AP to require WPA (either
 # WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either
 # wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK.
+# Instead of wpa_psk / wpa_passphrase, wpa_psk_radius might suffice.
 # For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys),
 # RADIUS authentication server must be configured, and WPA-EAP must be included
 # in wpa_key_mgmt.
@@ -697,6 +707,15 @@
 # configuration reloads.
 #wpa_psk_file=/etc/hostapd.wpa_psk
 
+# Optionally, WPA passphrase can be received from RADIUS authentication server
+# This requires macaddr_acl to be set to 2 (RADIUS)
+# 0 = disabled (default)
+# 1 = optional; use default passphrase/psk if RADIUS server does not include
+#	Tunnel-Password
+# 2 = required; reject authentication if RADIUS server does not include
+#	Tunnel-Password
+#wpa_psk_radius=0
+
 # Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
 # entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be
 # added to enable SHA256-based stronger algorithms.
@@ -1008,6 +1027,12 @@
 # 12-digit, all-numeric code that identifies the consumer package.
 #upc=123456789012
 
+# WPS RF Bands (a = 5G, b = 2.4G, g = 2.4G, ag = dual band)
+# This value should be set according to RF band(s) supported by the AP if
+# hw_mode is not set. For dual band dual concurrent devices, this needs to be
+# set to ag to allow both RF bands to be advertized.
+#wps_rf_bands=ag
+
 ##### Wi-Fi Direct (P2P) ######################################################
 
 # Enable P2P Device management
@@ -1024,6 +1049,75 @@
 # Prohibit use of TDLS Channel Switching in this BSS
 #tdls_prohibit_chan_switch=1
 
+##### IEEE 802.11v-2011 #######################################################
+
+# Time advertisement
+# 0 = disabled (default)
+# 2 = UTC time at which the TSF timer is 0
+#time_advertisement=2
+
+# Local time zone as specified in 8.3 of IEEE Std 1003.1-2004:
+# stdoffset[dst[offset][,start[/time],end[/time]]]
+#time_zone=EST5
+
+##### IEEE 802.11u-2011 #######################################################
+
+# Enable Interworking service
+#interworking=1
+
+# Access Network Type
+# 0 = Private network
+# 1 = Private network with guest access
+# 2 = Chargeable public network
+# 3 = Free public network
+# 4 = Personal device network
+# 5 = Emergency services only network
+# 14 = Test or experimental
+# 15 = Wildcard
+#access_network_type=0
+
+# Whether the network provides connectivity to the Internet
+# 0 = Unspecified
+# 1 = Network provides connectivity to the Internet
+#internet=1
+
+# Additional Step Required for Access
+# Note: This is only used with open network, i.e., ASRA shall ne set to 0 if
+# RSN is used.
+#asra=0
+
+# Emergency services reachable
+#esr=0
+
+# Unauthenticated emergency service accessible
+#uesa=0
+
+# Venue Info (optional)
+# The available values are defined in IEEE Std 802.11u-2011, 7.3.1.34.
+# Example values (group,type):
+# 0,0 = Unspecified
+# 1,7 = Convention Center
+# 1,13 = Coffee Shop
+# 2,0 = Unspecified Business
+# 7,1  Private Residence
+#venue_group=7
+#venue_type=1
+
+# Homogeneous ESS identifier (optional; dot11HESSID)
+# If set, this shall be identifical to one of the BSSIDs in the homogeneous
+# ESS and this shall be set to the same value across all BSSs in homogeneous
+# ESS.
+#hessid=02:03:04:05:06:07
+
+# Roaming Consortium List
+# Arbitrary number of Roaming Consortium OIs can be configured with each line
+# adding a new OI to the list. The first three entries are available through
+# Beacon and Probe Response frames. Any additional entry will be available only
+# through ANQP queries. Each OI is between 3 and 15 octets and is configured a
+# a hexstring.
+#roaming_consortium=021122
+#roaming_consortium=2233445566
+
 ##### Multiple BSSID support ##################################################
 #
 # Above configuration is using the default interface (wlan#, or multi-SSID VLAN
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index a48d773..527860c 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -16,7 +16,9 @@
 #include <dirent.h>
 
 #include "common/wpa_ctrl.h"
-#include "common.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/edit.h"
 #include "common/version.h"
 
 
@@ -113,6 +115,7 @@
 static const char *pid_file = NULL;
 static const char *action_file = NULL;
 static int ping_interval = 5;
+static int interactive = 0;
 
 
 static void usage(void)
@@ -512,6 +515,26 @@
 #endif /* CONFIG_WPS */
 
 
+static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
+					char *argv[])
+{
+	char buf[300];
+	int res;
+
+	if (argc < 2) {
+		printf("Invalid 'ess_disassoc' command - two arguments (STA "
+		       "addr and URL) are needed\n");
+		return -1;
+	}
+
+	res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s",
+			  argv[0], argv[1]);
+	if (res < 0 || res >= (int) sizeof(buf))
+		return -1;
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
 				      char *argv[])
 {
@@ -588,6 +611,8 @@
 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	hostapd_cli_quit = 1;
+	if (interactive)
+		eloop_terminate();
 	return 0;
 }
 
@@ -723,6 +748,7 @@
 	{ "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
 	{ "wps_config", hostapd_cli_cmd_wps_config },
 #endif /* CONFIG_WPS */
+	{ "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
 	{ "get_config", hostapd_cli_cmd_get_config },
 	{ "help", hostapd_cli_cmd_help },
 	{ "interface", hostapd_cli_cmd_interface },
@@ -801,70 +827,39 @@
 }
 
 
-static void hostapd_cli_interactive(void)
+#define max_args 10
+
+static int tokenize_cmd(char *cmd, char *argv[])
 {
-	const int max_args = 10;
-	char cmd[256], *res, *argv[max_args], *pos;
-	int argc;
+	char *pos;
+	int argc = 0;
 
-	printf("\nInteractive mode\n\n");
-
-	do {
-		hostapd_cli_recv_pending(ctrl_conn, 0, 0);
-		printf("> ");
-		alarm(ping_interval);
-		res = fgets(cmd, sizeof(cmd), stdin);
-		alarm(0);
-		if (res == NULL)
-			break;
-		pos = cmd;
-		while (*pos != '\0') {
-			if (*pos == '\n') {
-				*pos = '\0';
-				break;
-			}
+	pos = cmd;
+	for (;;) {
+		while (*pos == ' ')
 			pos++;
+		if (*pos == '\0')
+			break;
+		argv[argc] = pos;
+		argc++;
+		if (argc == max_args)
+			break;
+		if (*pos == '"') {
+			char *pos2 = os_strrchr(pos, '"');
+			if (pos2)
+				pos = pos2 + 1;
 		}
-		argc = 0;
-		pos = cmd;
-		for (;;) {
-			while (*pos == ' ')
-				pos++;
-			if (*pos == '\0')
-				break;
-			argv[argc] = pos;
-			argc++;
-			if (argc == max_args)
-				break;
-			while (*pos != '\0' && *pos != ' ')
-				pos++;
-			if (*pos == ' ')
-				*pos++ = '\0';
-		}
-		if (argc)
-			wpa_request(ctrl_conn, argc, argv);
-	} while (!hostapd_cli_quit);
+		while (*pos != '\0' && *pos != ' ')
+			pos++;
+		if (*pos == ' ')
+			*pos++ = '\0';
+	}
+
+	return argc;
 }
 
 
-static void hostapd_cli_cleanup(void)
-{
-	hostapd_cli_close_connection();
-	if (pid_file)
-		os_daemonize_terminate(pid_file);
-
-	os_program_deinit();
-}
-
-
-static void hostapd_cli_terminate(int sig)
-{
-	hostapd_cli_cleanup();
-	exit(0);
-}
-
-
-static void hostapd_cli_alarm(int sig)
+static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
 {
 	if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
 		printf("Connection to hostapd lost - trying to reconnect\n");
@@ -884,7 +879,55 @@
 	}
 	if (ctrl_conn)
 		hostapd_cli_recv_pending(ctrl_conn, 1, 0);
-	alarm(ping_interval);
+	eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
+}
+
+
+static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
+{
+	eloop_terminate();
+}
+
+
+static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
+{
+	char *argv[max_args];
+	int argc;
+	argc = tokenize_cmd(cmd, argv);
+	if (argc)
+		wpa_request(ctrl_conn, argc, argv);
+}
+
+
+static void hostapd_cli_edit_eof_cb(void *ctx)
+{
+	eloop_terminate();
+}
+
+
+static void hostapd_cli_interactive(void)
+{
+	printf("\nInteractive mode\n\n");
+
+	eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
+	edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
+		  NULL, NULL, NULL);
+	eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
+
+	eloop_run();
+
+	edit_deinit(NULL, NULL);
+	eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
+}
+
+
+static void hostapd_cli_cleanup(void)
+{
+	hostapd_cli_close_connection();
+	if (pid_file)
+		os_daemonize_terminate(pid_file);
+
+	os_program_deinit();
 }
 
 
@@ -927,7 +970,6 @@
 
 int main(int argc, char *argv[])
 {
-	int interactive;
 	int warning_displayed = 0;
 	int c;
 	int daemonize = 0;
@@ -975,6 +1017,9 @@
 		       hostapd_cli_license);
 	}
 
+	if (eloop_init())
+		return -1;
+
 	for (;;) {
 		if (ctrl_ifname == NULL) {
 			struct dirent *dent;
@@ -1014,10 +1059,6 @@
 		continue;
 	}
 
-	signal(SIGINT, hostapd_cli_terminate);
-	signal(SIGTERM, hostapd_cli_terminate);
-	signal(SIGALRM, hostapd_cli_alarm);
-
 	if (interactive || action_file) {
 		if (wpa_ctrl_attach(ctrl_conn) == 0) {
 			hostapd_cli_attached = 1;
@@ -1039,6 +1080,7 @@
 		wpa_request(ctrl_conn, argc - optind, &argv[optind]);
 
 	os_free(ctrl_ifname);
+	eloop_destroy();
 	hostapd_cli_cleanup();
 	return 0;
 }
diff --git a/hostapd/main.c b/hostapd/main.c
index 01ad826..da8135b 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -37,6 +37,16 @@
 extern int wpa_debug_show_keys;
 extern int wpa_debug_timestamp;
 
+extern struct wpa_driver_ops *wpa_drivers[];
+
+
+struct hapd_global {
+	void **drv_priv;
+	size_t drv_count;
+};
+
+static struct hapd_global global;
+
 
 struct hapd_interfaces {
 	size_t count;
@@ -246,6 +256,24 @@
 		b = NULL;
 
 	os_memset(&params, 0, sizeof(params));
+	for (i = 0; wpa_drivers[i]; i++) {
+		if (wpa_drivers[i] != hapd->driver)
+			continue;
+
+		if (global.drv_priv[i] == NULL &&
+		    wpa_drivers[i]->global_init) {
+			global.drv_priv[i] = wpa_drivers[i]->global_init();
+			if (global.drv_priv[i] == NULL) {
+				wpa_printf(MSG_ERROR, "Failed to initialize "
+					   "driver '%s'",
+					   wpa_drivers[i]->name);
+				return -1;
+			}
+		}
+
+		params.global_priv = global.drv_priv[i];
+		break;
+	}
 	params.bssid = b;
 	params.ifname = hapd->conf->iface;
 	params.ssid = (const u8 *) hapd->conf->ssid.ssid;
@@ -275,8 +303,10 @@
 	}
 
 	if (hapd->driver->get_capa &&
-	    hapd->driver->get_capa(hapd->drv_priv, &capa) == 0)
+	    hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
 		iface->drv_flags = capa.flags;
+		iface->probe_resp_offloads = capa.probe_resp_offloads;
+	}
 
 	return 0;
 }
@@ -372,6 +402,10 @@
 static int hostapd_global_init(struct hapd_interfaces *interfaces,
 			       const char *entropy_file)
 {
+	int i;
+
+	os_memset(&global, 0, sizeof(global));
+
 	hostapd_logger_register_cb(hostapd_logger_cb);
 
 	if (eap_server_register_methods()) {
@@ -396,12 +430,32 @@
 	openlog("hostapd", 0, LOG_DAEMON);
 #endif /* CONFIG_NATIVE_WINDOWS */
 
+	for (i = 0; wpa_drivers[i]; i++)
+		global.drv_count++;
+	if (global.drv_count == 0) {
+		wpa_printf(MSG_ERROR, "No drivers enabled");
+		return -1;
+	}
+	global.drv_priv = os_zalloc(global.drv_count * sizeof(void *));
+	if (global.drv_priv == NULL)
+		return -1;
+
 	return 0;
 }
 
 
 static void hostapd_global_deinit(const char *pid_file)
 {
+	int i;
+
+	for (i = 0; wpa_drivers[i] && global.drv_priv; i++) {
+		if (!global.drv_priv[i])
+			continue;
+		wpa_drivers[i]->global_deinit(global.drv_priv[i]);
+	}
+	os_free(global.drv_priv);
+	global.drv_priv = NULL;
+
 #ifdef EAP_SERVER_TNC
 	tncs_global_deinit();
 #endif /* EAP_SERVER_TNC */