eclair snapshot
diff --git a/Android.mk b/Android.mk
index 844897b..5e8f07f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -33,9 +33,15 @@
 # To ignore possible wrong network configurations
 L_CFLAGS += -DWPA_IGNORE_CONFIG_ERRORS
 
+# To allow non-ASCII characters in SSID
+L_CFLAGS += -DWPA_UNICODE_SSID
+
+# OpenSSL is configured without engines on Android
+L_CFLAGS += -DOPENSSL_NO_ENGINE
+
 INCLUDES = external/openssl/include frameworks/base/cmds/keystore
   
-OBJS = config.c common.c md5.c md4.c rc4.c sha1.c des.c if_index.c
+OBJS = config.c common.c md5.c md4.c rc4.c sha1.c des.c
 OBJS_p = wpa_passphrase.c sha1.c md5.c md4.c common.c des.c
 OBJS_c = wpa_cli.c wpa_ctrl.c
 
@@ -661,7 +667,10 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := wpa_supplicant
 ifdef CONFIG_DRIVER_CUSTOM
-LOCAL_STATIC_LIBRARIES := libCustomWifi libWifiApi
+LOCAL_STATIC_LIBRARIES := libCustomWifi
+endif
+ifneq ($(BOARD_WPA_SUPPLICANT_PRIVATE_LIB),)
+LOCAL_STATIC_LIBRARIES += $(BOARD_WPA_SUPPLICANT_PRIVATE_LIB)
 endif
 LOCAL_SHARED_LIBRARIES := libc libcutils libcrypto libssl
 LOCAL_CFLAGS := $(L_CFLAGS)
diff --git a/common.c b/common.c
index fce9254..c5b6f7d 100644
--- a/common.c
+++ b/common.c
@@ -616,8 +616,11 @@
 	os_memcpy(ssid_txt, ssid, ssid_len);
 	ssid_txt[ssid_len] = '\0';
 	for (pos = ssid_txt; *pos != '\0'; pos++) {
+#ifndef WPA_UNICODE_SSID
+		/* Don't do this, since it prevents us from using APs with non-ASCII SSIDs */
 		if ((u8) *pos < 32 || (u8) *pos >= 127)
 			*pos = '_';
+#endif
 	}
 	return ssid_txt;
 }
diff --git a/config.c b/config.c
index 6ea66de..e5aeac2 100644
--- a/config.c
+++ b/config.c
@@ -205,6 +205,25 @@
 	return wpa_config_write_string((const u8 *) *src, len);
 }
 
+#ifdef WPA_UNICODE_SSID
+static char * wpa_config_write_str_unicode(const struct parse_data *data,
+				   struct wpa_ssid *ssid)
+{
+	size_t len;
+	char **src;
+
+	src = (char **) (((u8 *) ssid) + (long) data->param1);
+	if (*src == NULL)
+		return NULL;
+
+	if (data->param2)
+		len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
+	else
+		len = os_strlen(*src);
+
+	return wpa_config_write_string_ascii((const u8 *) *src, len);
+}
+#endif
 
 static int wpa_config_parse_int(const struct parse_data *data,
 				struct wpa_ssid *ssid,
@@ -1059,6 +1078,16 @@
 #define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
 #define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
 
+#ifdef WPA_UNICODE_SSID
+/* STR_* variants that do not force conversion to ASCII */
+#define _STR_UNICODE(f) #f, wpa_config_parse_str, wpa_config_write_str_unicode, OFFSET(f)
+#define STR_UNICODE(f) _STR_UNICODE(f), NULL, NULL, NULL, 0
+#define _STR_LEN_UNICODE(f) _STR_UNICODE(f), OFFSET(f ## _len)
+#define STR_LEN_UNICODE(f) _STR_LEN_UNICODE(f), NULL, NULL, 0
+#define _STR_RANGE_UNICODE(f, min, max) _STR_LEN_UNICODE(f), (void *) (min), (void *) (max)
+#define STR_RANGE_UNICODE(f, min, max) _STR_RANGE_UNICODE(f, min, max), 0
+#endif
+
 #define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
 	OFFSET(f), (void *) 0
 
@@ -1099,7 +1128,11 @@
  * functions.
  */
 static const struct parse_data ssid_fields[] = {
+#ifdef WPA_UNICODE_SSID
+	{ STR_RANGE_UNICODE(ssid, 0, MAX_SSID_LEN) },
+#else
 	{ STR_RANGE(ssid, 0, MAX_SSID_LEN) },
+#endif
 	{ INT_RANGE(scan_ssid, 0, 1) },
 	{ FUNC(bssid) },
 	{ FUNC_KEY(psk) },
@@ -1163,6 +1196,15 @@
 	{ INT_RANGE(frequency, 0, 10000) }
 };
 
+#ifdef WPA_UNICODE_SSID
+#undef _STR_UNICODE
+#undef STR_UNICODE
+#undef _STR_LEN_UNICODE
+#undef STR_LEN_UNICODE
+#undef _STR_RANGE_UNICODE
+#undef STR_RANGE_UNICODE
+#endif
+
 #undef OFFSET
 #undef _STR
 #undef STR
diff --git a/ctrl_iface.c b/ctrl_iface.c
index c774c86..ef93533 100644
--- a/ctrl_iface.c
+++ b/ctrl_iface.c
@@ -642,6 +642,7 @@
 		ssid = ssid->next;
 	}
 	wpa_s->reassociate = 1;
+	wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
 	wpa_supplicant_req_scan(wpa_s, 0, 0);
 
 	return 0;
@@ -670,7 +671,11 @@
 		 * Try to reassociate since there is no current configuration
 		 * and a new network was made available. */
 		wpa_s->reassociate = 1;
+#ifdef ANDROID
+		wpa_supplicant_req_scan(wpa_s, 2, 0);
+#else
 		wpa_supplicant_req_scan(wpa_s, 0, 0);
+#endif
 	}
 	ssid->disabled = 0;
 
@@ -1249,8 +1254,12 @@
 		wpa_s->disconnected = 1;
 		wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
 	} else if (os_strcmp(buf, "SCAN") == 0) {
-		wpa_s->scan_req = 2;
-		wpa_supplicant_req_scan(wpa_s, 0, 0);
+		if (!wpa_s->scan_ongoing) {
+			wpa_s->scan_req = 2;
+			wpa_supplicant_req_scan(wpa_s, 0, 0);
+		}
+		else
+			wpa_printf(MSG_DEBUG, "Ongoing Scan action...");
 	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_scan_results(
 			wpa_s, reply, reply_size);
diff --git a/driver_wext.c b/driver_wext.c
index a2e4578..c512586 100644
--- a/driver_wext.c
+++ b/driver_wext.c
@@ -21,6 +21,7 @@
 #include "includes.h"
 #include <sys/ioctl.h>
 #include <net/if_arp.h>
+#include <net/if.h>
 
 #include "wireless_copy.h"
 #include "common.h"
@@ -31,6 +32,9 @@
 #include "priv_netlink.h"
 #include "driver_wext.h"
 #include "wpa.h"
+#include "wpa_ctrl.h"
+#include "wpa_supplicant_i.h"
+#include "config_ssid.h"
 
 #ifdef CONFIG_CLIENT_MLME
 #include <netpacket/packet.h>
@@ -401,6 +405,12 @@
 		}
 		wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
 #endif /* CONFIG_PEERKEY */
+#ifdef ANDROID
+	} else if (os_strncmp(custom, "STOP", 4) == 0) {
+		wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED");
+	} else if (os_strncmp(custom, "START", 5) == 0) {
+		wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED");
+#endif /* ANDROID */
 	}
 }
 
@@ -1001,6 +1011,13 @@
 {
 	int flags;
 
+	if (wpa_driver_wext_get_ifflags(drv, &flags) != 0 ||
+	    wpa_driver_wext_set_ifflags(drv, flags | IFF_UP) != 0) {
+		printf("Could not set interface '%s' UP\n", drv->ifname);
+	}
+#ifdef ANDROID
+	os_sleep(0, WPA_DRIVER_WEXT_WAIT_US);
+#endif
 	/*
 	 * Make sure that the driver does not have any obsolete PMKID entries.
 	 */
@@ -1010,11 +1027,6 @@
 		printf("Could not configure driver to use managed mode\n");
 	}
 
-	if (wpa_driver_wext_get_ifflags(drv, &flags) != 0 ||
-	    wpa_driver_wext_set_ifflags(drv, flags | IFF_UP) != 0) {
-		printf("Could not set interface '%s' UP\n", drv->ifname);
-	}
-
 	wpa_driver_wext_get_range(drv);
 
 	drv->ifindex = if_nametoindex(drv->ifname);
@@ -1226,7 +1238,13 @@
 	size_t len, clen, res_buf_len;
 
 	os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
-
+#ifdef ANDROID
+	/* To make sure correctly parse scan results which is impacted by wext
+	 * version, first check range->we_version, if it is default value (0),
+	 * update again here */
+	if (drv->we_version_compiled == 0)
+		wpa_driver_wext_get_range(drv);
+#endif
 	res_buf_len = IW_SCAN_MAX_DATA;
 	for (;;) {
 		res_buf = os_malloc(res_buf_len);
@@ -1912,10 +1930,16 @@
 	struct wpa_driver_wext_data *drv = priv;
 	int ret = 0;
 	int allow_unencrypted_eapol;
-	int value;
+	int value, flags;
 
 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
 
+	if (wpa_driver_wext_get_ifflags(drv, &flags) == 0) {
+		if (!(flags & IFF_UP)) {
+			wpa_driver_wext_set_ifflags(drv, flags | IFF_UP);
+		}
+	}
+
 	/*
 	 * If the driver did not support SIOCSIWAUTH, fallback to
 	 * SIOCSIWENCODE here.
@@ -2473,6 +2497,68 @@
 	return drv->we_version_compiled;
 }
 
+#ifdef ANDROID
+static char *wpa_driver_get_country_code(int channels)
+{
+	char *country = "US"; /* WEXT_NUMBER_SCAN_CHANNELS_FCC */
+
+	if (channels == WEXT_NUMBER_SCAN_CHANNELS_ETSI)
+		country = "EU";
+	else if( channels == WEXT_NUMBER_SCAN_CHANNELS_MKK1)
+		country = "JP";
+	return country;
+}
+
+static int wpa_driver_priv_driver_cmd( void *priv, char *cmd, char *buf, size_t buf_len )
+{
+	struct wpa_driver_wext_data *drv = priv;
+	struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx);
+	struct iwreq iwr;
+	int ret = 0;
+
+	wpa_printf(MSG_DEBUG, "%s %s len = %d", __func__, cmd, buf_len);
+
+	if (os_strcasecmp(cmd, "RSSI-APPROX") == 0) {
+		os_strncpy(cmd, "RSSI", MAX_DRV_CMD_SIZE);
+	}
+	else if( os_strncasecmp(cmd, "SCAN-CHANNELS", 13) == 0 ) {
+		int no_of_chan;
+
+		no_of_chan = atoi(cmd + 13);
+		os_snprintf(cmd, MAX_DRV_CMD_SIZE, "COUNTRY %s",
+			wpa_driver_get_country_code(no_of_chan));
+	}
+	os_memset(&iwr, 0, sizeof(iwr));
+	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+	os_memcpy(buf, cmd, strlen(cmd) + 1);
+	iwr.u.data.pointer = buf;
+	iwr.u.data.length = buf_len;
+
+	if ((ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr)) < 0) {
+		perror("ioctl[SIOCSIWPRIV]");
+	}
+
+	if (ret < 0)
+		wpa_printf(MSG_ERROR, "%s failed", __func__);
+	else {
+		ret = 0;
+		if ((os_strcasecmp(cmd, "RSSI") == 0) ||
+		    (os_strcasecmp(cmd, "LINKSPEED") == 0) ||
+		    (os_strcasecmp(cmd, "MACADDR") == 0)) {
+			ret = strlen(buf);
+		}
+/*		else if (os_strcasecmp(cmd, "START") == 0) {
+			os_sleep(0, WPA_DRIVER_WEXT_WAIT_US);
+			wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED");
+		}
+		else if (os_strcasecmp(cmd, "STOP") == 0) {
+			wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED");
+		}*/
+		wpa_printf(MSG_DEBUG, "%s %s len = %d, %d", __func__, buf, ret, strlen(buf));
+	}
+	return ret;
+}
+#endif
 
 const struct wpa_driver_ops wpa_driver_wext_ops = {
 	.name = "wext",
@@ -2506,4 +2592,7 @@
 	.mlme_add_sta = wpa_driver_wext_mlme_add_sta,
 	.mlme_remove_sta = wpa_driver_wext_mlme_remove_sta,
 #endif /* CONFIG_CLIENT_MLME */
+#ifdef ANDROID
+	.driver_cmd = wpa_driver_priv_driver_cmd,
+#endif
 };
diff --git a/driver_wext.h b/driver_wext.h
index d65a544..4804ae5 100644
--- a/driver_wext.h
+++ b/driver_wext.h
@@ -45,4 +45,13 @@
 int wpa_driver_wext_set_operstate(void *priv, int state);
 int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv);
 
+#ifdef ANDROID
+#define WEXT_NUMBER_SCAN_CHANNELS_FCC	11
+#define WEXT_NUMBER_SCAN_CHANNELS_ETSI	13
+#define WEXT_NUMBER_SCAN_CHANNELS_MKK1	14
+
+#define WPA_DRIVER_WEXT_WAIT_US		400000
+#define MAX_DRV_CMD_SIZE		248
+#endif
+
 #endif /* DRIVER_WEXT_H */
diff --git a/eap_tls_common.c b/eap_tls_common.c
index de17886..d91c6cb 100644
--- a/eap_tls_common.c
+++ b/eap_tls_common.c
@@ -23,152 +23,6 @@
 #include "tls.h"
 #include "config.h"
 
-#ifdef ANDROID
-#include <openssl/pem.h>
-#include <openssl/x509v3.h>
-#include <keystore_get.h>
-
-#define PEM_CERT_KEYWORD "CERTIFICATE"
-#define PEM_PRIVATEKEY_KEYWORD "PRIVATE KEY"
-
-struct temporal_blobs {
-	struct temporal_blobs *next;
-	struct wpa_config_blob *blob;
-};
-
-static struct temporal_blobs *ks_blobs = NULL;
-
-/**
- * The blob data can not be inserted into config->blobs structure, since the 
- * protected cert/key may be rewritten to config file. We have to maintain the
- * keystore-only blobs.
- */
-static int add_temporal_blob(struct wpa_config_blob *blob)
-{
-	struct temporal_blobs *p;
-
-	p = (struct temporal_blobs*) malloc(sizeof(struct temporal_blobs));
-	if (p == NULL) {
-		return -1;
-	}
-	p->next = ks_blobs;
-	p->blob = blob;
-	ks_blobs = p;
-	return 0;
-}
-
-static void free_temporal_blobs()
-{
-	struct temporal_blobs *p = ks_blobs;
-
-	while (p != NULL) {
-		struct temporal_blobs *q = p;
-		p = p->next;
-		if (q->blob) free(q->blob);
-		free(q);
-	}
-	ks_blobs = NULL;
-}
-
-typedef enum {
-	PEM_CERTIFICATE,
-	PEM_PRIVATE_KEY,
-	DER_FORMAT,
-	UNKNOWN_CERT_TYPE
-} CERT_TYPE;
-
-/**
- * Tell the encoding format and type of the certificate/key by examining if
- * there is "CERTIFICATE" or "PRIVATE KEY" in the blob. If not, at least we
- * can test if the first byte is '0'.
- */
-static CERT_TYPE get_blob_type(struct wpa_config_blob *blob)
-{
-	CERT_TYPE type = UNKNOWN_CERT_TYPE;
-	unsigned char p = blob->data[blob->len - 1];
-
-	blob->data[blob->len - 1] = 0;
-	if (strstr(blob->data, PEM_CERT_KEYWORD) != NULL) {
-		type = PEM_CERTIFICATE;
-	} else if (strstr(blob->data, PEM_PRIVATEKEY_KEYWORD) != NULL) {
-		type = PEM_PRIVATE_KEY;
-	} else if (blob->data[0] == '0') {
-		type = DER_FORMAT;
-	}
-	blob->data[blob->len - 1] = p;
-	return type;
-}
-
-/**
- * convert_PEM_to_DER() provides the converion from PEM format to DER one, since
- * original certificate handling does not accept the PEM format for blob data.
- * Therefore, we need to convert the data to DER format if it is PEM-format.
- */
-static void convert_PEM_to_DER(struct wpa_config_blob *blob)
-{
-	X509 *cert = NULL;
-	EVP_PKEY *pkey = NULL;
-	BIO *bp = NULL;
-	unsigned char *buf = NULL;
-	int len = 0;
-	CERT_TYPE type;
-
-	if (blob->len < sizeof(PEM_CERT_KEYWORD)) {
-		return;
-	}
-
-	if (((type = get_blob_type(blob)) != PEM_CERTIFICATE) &&
-		(type != PEM_PRIVATE_KEY)) {
-		return;
-	}
-
-	bp = BIO_new(BIO_s_mem());
-	if (!bp) goto err;
-	if (!BIO_write(bp, blob->data, blob->len)) goto err;
-	if (type == PEM_CERTIFICATE) {
-		if ((cert = PEM_read_bio_X509(bp, NULL, NULL, NULL)) != NULL) {
-			len = i2d_X509(cert, &buf);
-		}
-	} else {
-		if ((pkey = PEM_read_bio_PrivateKey(bp, NULL, NULL, NULL)) != NULL) {
-			len = i2d_PrivateKey(pkey, &buf);
-		}
-	}
-
-err:
-	if (bp) BIO_free(bp);
-	if (cert) X509_free(cert);
-	if (pkey) EVP_PKEY_free(pkey);
-	if (buf) {
-		free(blob->data);
-		blob->data = buf;
-		blob->len = len;
-	}
-}
-
-struct wpa_config_blob *get_blob_from_keystore(const char *name)
-{
-	int len;
-	char *buf = keystore_get((char*)name, &len);
-	struct wpa_config_blob *blob = NULL;
-
-	if (buf) {
-		if ((blob = os_zalloc(sizeof(*blob))) != NULL) {
-			blob->name = os_strdup(name);
-			blob->data = (unsigned char*)buf;
-			blob->len = len;
-		} else {
-			free(buf);
-		}
-	}
-	if (blob) {
-		convert_PEM_to_DER(blob);
-		add_temporal_blob(blob);
-	}
-	return blob;
-}
-#endif
-
 static int eap_tls_check_blob(struct eap_sm *sm, const char **name,
 			      const u8 **data, size_t *data_len)
 {
@@ -178,11 +32,6 @@
 		return 0;
 
 	blob = eap_get_config_blob(sm, *name + 7);
-#ifdef ANDROID
-	if(blob == NULL) {
-		blob = get_blob_from_keystore(*name + 7);
-	}
-#endif
 	if (blob == NULL) {
 		wpa_printf(MSG_ERROR, "%s: Named configuration blob '%s' not "
 			   "found", __func__, *name + 7);
@@ -346,9 +195,6 @@
 	ret = 0;
 
 done:
-#ifdef ANDROID
-	free_temporal_blobs();
-#endif
 	return ret;
 }
 
diff --git a/events.c b/events.c
index 1512097..bb5be64 100644
--- a/events.c
+++ b/events.c
@@ -505,6 +505,7 @@
 	struct wpa_ssid *ssid = NULL;
 	struct wpa_scan_result *results;
 
+	wpa_s->scan_ongoing = 0;
 	if (wpa_supplicant_get_scan_results(wpa_s) < 0) {
 		if (wpa_s->conf->ap_scan == 2)
 			return;
@@ -515,7 +516,7 @@
 	}
 
 	wpa_supplicant_dbus_notify_scan_results(wpa_s);
-    wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS " Ready"); /* Dm: */
+	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS " Ready");
 
 	if (wpa_s->conf->ap_scan == 2 || wpa_s->disconnected)
 		return;
@@ -660,9 +661,9 @@
 		p += len;
 	}
 
-	if (!wpa_found && data->assoc_info.beacon_ies)
+	if (!wpa_found)
 		wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
-	if (!rsn_found && data->assoc_info.beacon_ies)
+	if (!rsn_found)
 		wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
 }
 
diff --git a/if_index.c b/if_index.c
deleted file mode 100644
index 8f87d5f..0000000
--- a/if_index.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/* if_index.c
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-
-#include <linux/if.h>
-#include <linux/sockios.h>
-#include <linux/route.h>
-
-unsigned int if_nametoindex( const char *ifname )
-{
-#ifndef SIOCGIFINDEX
-    return 0;
-#else
-    struct ifreq ifr;
-    int fd = socket(AF_INET, SOCK_DGRAM, 0);    
-
-    if (fd < 0)
-        return 0;
-
-    strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
-    ifr.ifr_ifindex = 0;
-    if (ioctl (fd, SIOCGIFINDEX, &ifr) < 0) {
-        return 0;
-    }
-    return ifr.ifr_ifindex;
-#endif
-}
diff --git a/os_unix.c b/os_unix.c
index 7e3ab4a..edb160a 100644
--- a/os_unix.c
+++ b/os_unix.c
@@ -16,6 +16,12 @@
 
 #include "os.h"
 
+#ifdef ANDROID
+#include <linux/capability.h>
+#include <linux/prctl.h>
+#include <private/android_filesystem_config.h>
+#endif
+
 void os_sleep(os_time_t sec, os_time_t usec)
 {
 	if (sec)
@@ -171,6 +177,28 @@
 
 int os_program_init(void)
 {
+#ifdef ANDROID
+	/* We ignore errors here since errors are normal if we
+	 * are already running as non-root.
+	 */
+	gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
+	setgroups(sizeof(groups)/sizeof(groups[0]), groups);
+
+	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+
+	setgid(AID_WIFI);
+	setuid(AID_WIFI);
+
+	struct __user_cap_header_struct header;
+	struct __user_cap_data_struct cap;
+	header.version = _LINUX_CAPABILITY_VERSION;
+	header.pid = 0;
+	cap.effective = cap.permitted =
+		(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
+	cap.inheritable = 0;
+	capset(&header, &cap);
+#endif
+
 	return 0;
 }
 
diff --git a/tls_openssl.c b/tls_openssl.c
index cb6b974..61fa747 100644
--- a/tls_openssl.c
+++ b/tls_openssl.c
@@ -37,13 +37,29 @@
 #define OPENSSL_d2i_TYPE unsigned char **
 #endif
 
+#ifdef ANDROID
+#include <openssl/pem.h>
+#include "keystore_get.h"
+
+static BIO *BIO_from_keystore(const char *key)
+{
+	BIO *bio = NULL;
+	char value[KEYSTORE_MESSAGE_SIZE];
+	int length = keystore_get(key, value);
+	if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL) {
+		BIO_write(bio, value, length);
+	}
+	return bio;
+}
+#endif
+
 static int tls_openssl_ref_count = 0;
 
 struct tls_connection {
 	SSL *ssl;
 	BIO *ssl_in, *ssl_out;
 #ifndef OPENSSL_NO_ENGINE
-	ENGINE *engine;        /* functional reference to the engine */
+	ENGINE *engine;	/* functional reference to the engine */
 	EVP_PKEY *private_key; /* the private key if using engine */
 #endif /* OPENSSL_NO_ENGINE */
 	char *subject_match, *altsubject_match;
@@ -571,7 +587,7 @@
  * @pre: an array of commands and values that load an engine initialized
  *       in the engine specific function
  * @post: an array of commands and values that initialize an already loaded
- *        engine (or %NULL if not required)
+ *	engine (or %NULL if not required)
  * @id: the engine id of the engine to load (only required if post is not %NULL
  *
  * This function is a generic function that loads any openssl engine.
@@ -1092,7 +1108,6 @@
 }
 #endif /* OPENSSL_NO_STDIO */
 
-
 static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
 				  const char *ca_cert, const u8 *ca_cert_blob,
 				  size_t ca_cert_blob_len, const char *ca_path)
@@ -1143,6 +1158,33 @@
 		return 0;
 	}
 
+#ifdef ANDROID
+	if (ca_cert && strncmp("keystore://", ca_cert, 11) == 0) {
+		BIO *bio = BIO_from_keystore(&ca_cert[11]);
+		STACK_OF(X509_INFO) *stack = NULL;
+		int i;
+		if (bio) {
+			stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
+			BIO_free(bio);
+		}
+		if (!stack) {
+			return -1;
+		}
+		for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
+			X509_INFO *info = sk_X509_INFO_value(stack, i);
+			if (info->x509) {
+				X509_STORE_add_cert(ssl_ctx->cert_store, info->x509);
+			}
+			if (info->crl) {
+				X509_STORE_add_crl(ssl_ctx->cert_store, info->crl);
+			}
+		}
+		sk_X509_INFO_pop_free(stack, X509_INFO_free);
+		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
+		return 0;
+	}
+#endif
+
 #ifdef CONFIG_NATIVE_WINDOWS
 	if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) ==
 	    0) {
@@ -1298,6 +1340,25 @@
 	if (client_cert == NULL)
 		return -1;
 
+#ifdef ANDROID
+	if (strncmp("keystore://", client_cert, 11) == 0) {
+		BIO *bio = BIO_from_keystore(&client_cert[11]);
+		X509 *x509 = NULL;
+		int ret = -1;
+		if (bio) {
+			x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+			BIO_free(bio);
+		}
+		if (x509) {
+			if (SSL_use_certificate(conn->ssl, x509) == 1) {
+				ret = 0;
+			}
+			X509_free(x509);
+		}
+		return ret;
+	}
+#endif
+
 #ifndef OPENSSL_NO_STDIO
 	if (SSL_use_certificate_file(conn->ssl, client_cert,
 				     SSL_FILETYPE_ASN1) == 1) {
@@ -1587,6 +1648,23 @@
 		break;
 	}
 
+#ifdef ANDROID
+	if (!ok && private_key && strncmp("keystore://", private_key, 11) == 0) {
+		BIO *bio = BIO_from_keystore(&private_key[11]);
+		EVP_PKEY *pkey = NULL;
+		if (bio) {
+			pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+			BIO_free(bio);
+		}
+		if (pkey) {
+			if (SSL_use_PrivateKey(conn->ssl, pkey) == 1) {
+				ok = 1;
+			}
+			EVP_PKEY_free(pkey);
+		}
+	}
+#endif
+
 	while (!ok && private_key) {
 #ifndef OPENSSL_NO_STDIO
 		if (SSL_use_PrivateKey_file(conn->ssl, private_key,
diff --git a/wireless_copy.h b/wireless_copy.h
index ac81f69..db1a5f3 100644
--- a/wireless_copy.h
+++ b/wireless_copy.h
@@ -1,17 +1,10 @@
-/* This is based on Linux Wireless Extensions header file from WIRELESS_EXT 18.
- * I have just removed kernel related headers and added some typedefs etc. to
- * make this easier to include into user space programs.
- * Jouni Malinen, 2005-03-12.
- */
-
-
 /*
  * This file define a set of standard wireless extensions
  *
- * Version :	19	18.3.05
+ * Version :	22	16.3.07
  *
  * Authors :	Jean Tourrilhes - HPL - <[email protected]>
- * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
  */
 
 #ifndef _LINUX_WIRELESS_H
@@ -76,27 +69,9 @@
 
 /***************************** INCLUDES *****************************/
 
- /* jkm - replaced linux headers with C library headers, added typedefs */
-#if 0
-/* To minimise problems in user space, I might remove those headers
- * at some point. Jean II */
-#include <linux/types.h>		/* for "caddr_t" et al		*/
+#include <linux/types.h>		/* for __u* and __s* typedefs */
 #include <linux/socket.h>		/* for "struct sockaddr" et al	*/
 #include <linux/if.h>			/* for IFNAMSIZ and co... */
-#else
-#include <sys/types.h>
-#include <net/if.h>
-#if !defined(HAVE_ANDROID_OS)
-typedef __uint32_t __u32;
-typedef __int32_t __s32;
-typedef __uint16_t __u16;
-typedef __int16_t __s16;
-typedef __uint8_t __u8;
-#endif
-#ifndef __user
-#define __user
-#endif /* __user */
-#endif
 
 /***************************** VERSION *****************************/
 /*
@@ -105,7 +80,7 @@
  * (there is some stuff that will be added in the future...)
  * I just plan to increment with each new version.
  */
-#define WIRELESS_EXT	19
+#define WIRELESS_EXT	22
 
 /*
  * Changes :
@@ -229,6 +204,22 @@
  *	- Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
  *	- Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
  *	- Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
+ *
+ * V19 to V20
+ * ----------
+ *	- RtNetlink requests support (SET/GET)
+ *
+ * V20 to V21
+ * ----------
+ *	- Remove (struct net_device *)->get_wireless_stats()
+ *	- Change length in ESSID and NICK to strlen() instead of strlen()+1
+ *	- Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers
+ *	- Power/Retry relative values no longer * 100000
+ *	- Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI
+ *
+ * V21 to V22
+ * ----------
+ *	- Prevent leaking of kernel space in stream on 64 bits.
  */
 
 /**************************** CONSTANTS ****************************/
@@ -342,7 +333,7 @@
  * separate range because of collisions with other tools such as
  * 'mii-tool'.
  * We now have 32 commands, so a bit more space ;-).
- * Also, all 'odd' commands are only usable by root and don't return the
+ * Also, all 'even' commands are only usable by root and don't return the
  * content of ifr/iwr to user (but you are not obliged to use the set/get
  * convention, just use every other two command). More details in iwpriv.c.
  * And I repeat : you are not forced to use them with iwpriv, but you
@@ -356,7 +347,7 @@
 #define SIOCIWLAST	SIOCIWLASTPRIV		/* 0x8BFF */
 #define IW_IOCTL_IDX(cmd)	((cmd) - SIOCIWFIRST)
 
-/* Even : get (world access), odd : set (root access) */
+/* Odd : get (world access), even : set (root access) */
 #define IW_IS_SET(cmd)	(!((cmd) & 0x1))
 #define IW_IS_GET(cmd)	((cmd) & 0x1)
 
@@ -459,6 +450,7 @@
 #define IW_MODE_REPEAT	4	/* Wireless Repeater (forwarder) */
 #define IW_MODE_SECOND	5	/* Secondary master/repeater (backup) */
 #define IW_MODE_MONITOR	6	/* Passive monitor (listen only) */
+#define IW_MODE_MESH	7	/* Mesh (IEEE 802.11s) network */
 
 /* Statistics flags (bitmask in updated) */
 #define IW_QUAL_QUAL_UPDATED	0x01	/* Value was updated since last read */
@@ -469,6 +461,7 @@
 #define IW_QUAL_QUAL_INVALID	0x10	/* Driver doesn't provide value */
 #define IW_QUAL_LEVEL_INVALID	0x20
 #define IW_QUAL_NOISE_INVALID	0x40
+#define IW_QUAL_RCPI		0x80	/* Level + Noise are 802.11k RCPI */
 #define IW_QUAL_ALL_INVALID	0x70
 
 /* Frequency flags */
@@ -521,10 +514,12 @@
 #define IW_RETRY_TYPE		0xF000	/* Type of parameter */
 #define IW_RETRY_LIMIT		0x1000	/* Maximum number of retries*/
 #define IW_RETRY_LIFETIME	0x2000	/* Maximum duration of retries in us */
-#define IW_RETRY_MODIFIER	0x000F	/* Modify a parameter */
+#define IW_RETRY_MODIFIER	0x00FF	/* Modify a parameter */
 #define IW_RETRY_MIN		0x0001	/* Value is a minimum  */
 #define IW_RETRY_MAX		0x0002	/* Value is a maximum */
 #define IW_RETRY_RELATIVE	0x0004	/* Value is not in seconds/ms/us */
+#define IW_RETRY_SHORT		0x0010	/* Value is for short packets  */
+#define IW_RETRY_LONG		0x0020	/* Value is for long packets */
 
 /* Scanning request flags */
 #define IW_SCAN_DEFAULT		0x0000	/* Default scan of the driver */
@@ -540,7 +535,17 @@
 #define IW_SCAN_TYPE_ACTIVE 0
 #define IW_SCAN_TYPE_PASSIVE 1
 /* Maximum size of returned data */
-#define IW_SCAN_MAX_DATA	4096	/* In bytes */
+#define IW_SCAN_MAX_DATA	8192	/* In bytes */
+
+/* Scan capability flags - in (struct iw_range *)->scan_capa */
+#define IW_SCAN_CAPA_NONE		0x00
+#define IW_SCAN_CAPA_ESSID		0x01
+#define IW_SCAN_CAPA_BSSID		0x02
+#define IW_SCAN_CAPA_CHANNEL	0x04
+#define IW_SCAN_CAPA_MODE		0x08
+#define IW_SCAN_CAPA_RATE		0x10
+#define IW_SCAN_CAPA_TYPE		0x20
+#define IW_SCAN_CAPA_TIME		0x40
 
 /* Max number of char in custom event - use multiple of them if needed */
 #define IW_CUSTOM_MAX		256	/* In bytes */
@@ -551,6 +556,8 @@
 /* MLME requests (SIOCSIWMLME / struct iw_mlme) */
 #define IW_MLME_DEAUTH		0
 #define IW_MLME_DISASSOC	1
+#define IW_MLME_AUTH		2
+#define IW_MLME_ASSOC		3
 
 /* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
 #define IW_AUTH_INDEX		0x0FFF
@@ -604,6 +611,7 @@
 #define IW_ENCODE_ALG_WEP	1
 #define IW_ENCODE_ALG_TKIP	2
 #define IW_ENCODE_ALG_CCMP	3
+#define IW_ENCODE_ALG_PMK	4
 /* struct iw_encode_ext ->ext_flags */
 #define IW_ENCODE_EXT_TX_SEQ_VALID	0x00000001
 #define IW_ENCODE_EXT_RX_SEQ_VALID	0x00000002
@@ -623,6 +631,7 @@
 #define IW_ENC_CAPA_WPA2	0x00000002
 #define IW_ENC_CAPA_CIPHER_TKIP	0x00000004
 #define IW_ENC_CAPA_CIPHER_CCMP	0x00000008
+#define IW_ENC_CAPA_4WAY_HANDSHAKE	0x00000010
 
 /* Event capability macros - in (struct iw_range *)->event_capa
  * Because we have more than 32 possible events, we use an array of
@@ -668,6 +677,19 @@
   __u16		flags;		/* Optional params */
 };
 
+#ifdef __KERNEL__
+#ifdef CONFIG_COMPAT
+
+#include <linux/compat.h>
+
+struct compat_iw_point {
+	compat_caddr_t pointer;
+	__u16 length;
+	__u16 flags;
+};
+#endif
+#endif
+
 /*
  *	A frequency
  *	For numbers lower than 10^9, we encode the number in 'm' and
@@ -962,6 +984,9 @@
 	__u16		old_num_channels;
 	__u8		old_num_frequency;
 
+	/* Scan capabilities */
+	__u8		scan_capa; 	/* IW_SCAN_CAPA_* bit field */
+
 	/* Wireless event capability bitmasks */
 	__u32		event_capa[6];
 
@@ -1038,7 +1063,7 @@
 	/* Note : this frequency list doesn't need to fit channel numbers,
 	 * because each entry contain its channel index */
 
-	__u32		enc_capa; /* IW_ENC_CAPA_* bit field */
+	__u32		enc_capa;	/* IW_ENC_CAPA_* bit field */
 };
 
 /*
@@ -1065,7 +1090,7 @@
  */
 struct iw_event
 {
-	__u16		len;			/* Real lenght of this stuff */
+	__u16		len;			/* Real length of this stuff */
 	__u16		cmd;			/* Wireless IOCTL */
 	union iwreq_data	u;		/* IOCTL fixed payload */
 };
@@ -1088,4 +1113,30 @@
 #define IW_EV_POINT_LEN	(IW_EV_LCP_LEN + sizeof(struct iw_point) - \
 			 IW_EV_POINT_OFF)
 
+#ifdef __KERNEL__
+#ifdef CONFIG_COMPAT
+struct __compat_iw_event {
+	__u16		len;			/* Real length of this stuff */
+	__u16		cmd;			/* Wireless IOCTL */
+	compat_caddr_t	pointer;
+};
+#define IW_EV_COMPAT_LCP_LEN offsetof(struct __compat_iw_event, pointer)
+#define IW_EV_COMPAT_POINT_OFF offsetof(struct compat_iw_point, length)
+#define IW_EV_COMPAT_POINT_LEN	\
+	(IW_EV_COMPAT_LCP_LEN + sizeof(struct compat_iw_point) - \
+	 IW_EV_COMPAT_POINT_OFF)
+#endif
+#endif
+
+/* Size of the Event prefix when packed in stream */
+#define IW_EV_LCP_PK_LEN	(4)
+/* Size of the various events when packed in stream */
+#define IW_EV_CHAR_PK_LEN	(IW_EV_LCP_PK_LEN + IFNAMSIZ)
+#define IW_EV_UINT_PK_LEN	(IW_EV_LCP_PK_LEN + sizeof(__u32))
+#define IW_EV_FREQ_PK_LEN	(IW_EV_LCP_PK_LEN + sizeof(struct iw_freq))
+#define IW_EV_PARAM_PK_LEN	(IW_EV_LCP_PK_LEN + sizeof(struct iw_param))
+#define IW_EV_ADDR_PK_LEN	(IW_EV_LCP_PK_LEN + sizeof(struct sockaddr))
+#define IW_EV_QUAL_PK_LEN	(IW_EV_LCP_PK_LEN + sizeof(struct iw_quality))
+#define IW_EV_POINT_PK_LEN	(IW_EV_LCP_LEN + 4)
+
 #endif	/* _LINUX_WIRELESS_H */
diff --git a/wpa_ctrl.c b/wpa_ctrl.c
index 0d5dd28..32866cf 100644
--- a/wpa_ctrl.c
+++ b/wpa_ctrl.c
@@ -153,7 +153,7 @@
  * event of crashes that prevented them from being removed as part
  * of the normal orderly shutdown.
  */
-void wpa_ctrl_cleanup()
+void wpa_ctrl_cleanup(void)
 {
     DIR *dir;
     struct dirent entry;
@@ -292,7 +292,11 @@
 	os_free(cmd_buf);
 
 	for (;;) {
+#ifdef ANDROID
+		tv.tv_sec = 10;
+#else
 		tv.tv_sec = 2;
+#endif
 		tv.tv_usec = 0;
 		FD_ZERO(&rfds);
 		FD_SET(ctrl->s, &rfds);
diff --git a/wpa_ctrl.h b/wpa_ctrl.h
index a81dec9..1171712 100644
--- a/wpa_ctrl.h
+++ b/wpa_ctrl.h
@@ -187,7 +187,7 @@
  * event of crashes that prevented them from being removed as part
  * of the normal orderly shutdown.
  */
-void wpa_ctrl_cleanup();
+void wpa_ctrl_cleanup(void);
 #endif  /* ANDROID */
 
 #ifdef CONFIG_CTRL_IFACE_UDP
diff --git a/wpa_supplicant.c b/wpa_supplicant.c
index 706a010..aabef73 100644
--- a/wpa_supplicant.c
+++ b/wpa_supplicant.c
@@ -492,6 +492,7 @@
  */
 void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
 {
+#ifndef ANDROID
 	/* If there's at least one network that should be specifically scanned
 	 * then don't cancel the scan and reschedule.  Some drivers do
 	 * background scanning which generates frequent scan results, and that
@@ -513,6 +514,7 @@
 			return;
 		}
 	}
+#endif
 
 	wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec",
 		sec, usec);
@@ -954,7 +956,11 @@
 
 	wpa_supplicant_clear_status(wpa_s);
 	wpa_s->reassociate = 1;
+#ifdef ANDROID
+	wpa_supplicant_req_scan(wpa_s, 2, 0);
+#else
 	wpa_supplicant_req_scan(wpa_s, 0, 0);
+#endif
 	wpa_msg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
 	return 0;
 }
@@ -1105,6 +1111,8 @@
 		wpa_printf(MSG_WARNING, "Failed to initiate AP scan.");
 		wpa_supplicant_req_scan(wpa_s, 10, 0);
 	}
+	else
+		wpa_s->scan_ongoing = 1;
 }
 
 
@@ -1385,6 +1393,8 @@
 			wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
 		os_memset(wpa_s->bssid, 0, ETH_ALEN);
 		os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
+		wpa_s->link_speed = bss->maxrate;
+		wpa_s->rssi = bss->level;
 	} else {
 		wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
 			wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
diff --git a/wpa_supplicant_i.h b/wpa_supplicant_i.h
index 775462e..9989fe7 100644
--- a/wpa_supplicant_i.h
+++ b/wpa_supplicant_i.h
@@ -342,6 +342,9 @@
 
 	struct wpa_client_mlme mlme;
 	int use_client_mlme;
+	int scan_ongoing;   /* scan ongoing or not */
+	int link_speed;     /* current link speed */
+	int rssi;           /* current signal level */
 #ifdef ANDROID
 	int scan_interval;  /* time between scans when no APs available */
 #endif