From 2c23b7348ac966c08728d4908cf89d673d91bb76 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Fri, 20 Nov 2009 14:34:44 -0800 Subject: [PATCH] Add ANDROID-related changes Signed-off-by: Dmitry Shmidt --- wpa_supplicant/config.c | 42 +++++++ wpa_supplicant/config_file.c | 11 ++ wpa_supplicant/ctrl_iface.c | 192 ++++++++++++++++++++++++++++-- wpa_supplicant/ctrl_iface_unix.c | 18 +++ wpa_supplicant/events.c | 12 +- wpa_supplicant/scan.c | 6 +- wpa_supplicant/src/common/defs.h | 16 +++ wpa_supplicant/src/common/wireless_copy.h | 2 +- wpa_supplicant/src/common/wpa_ctrl.c | 99 ++++++++++++++- wpa_supplicant/src/common/wpa_ctrl.h | 17 +++ wpa_supplicant/src/crypto/tls_openssl.c | 79 ++++++++++++ wpa_supplicant/src/drivers/driver.h | 12 ++ wpa_supplicant/src/drivers/driver_test.c | 34 +++++- wpa_supplicant/src/drivers/driver_wext.c | 104 +++++++++++++++- wpa_supplicant/src/drivers/driver_wext.h | 9 ++ wpa_supplicant/src/drivers/drivers.c | 6 + wpa_supplicant/src/utils/common.c | 2 + wpa_supplicant/src/utils/os_unix.c | 28 +++++ wpa_supplicant/src/utils/wpa_debug.c | 26 ++++ wpa_supplicant/src/utils/wpa_debug.h | 24 ++++ wpa_supplicant/wpa_cli.c | 172 ++++++++++++++++++++++---- wpa_supplicant/wpa_supplicant.c | 37 +++++- wpa_supplicant/wpa_supplicant.conf | 4 +- wpa_supplicant/wpa_supplicant_i.h | 15 +++ wpa_supplicant/wps_supplicant.c | 4 + 25 files changed, 926 insertions(+), 45 deletions(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 08e107e..89e0fba 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -223,6 +223,26 @@ static char * wpa_config_write_str(const struct parse_data *data, 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 #endif /* NO_CONFIG_WRITE */ @@ -1264,6 +1284,15 @@ static char * wpa_config_write_wep_key3(const struct parse_data *data, OFFSET(f), (void *) 0 #define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \ OFFSET(eap.f), (void *) 0 +#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 #endif /* NO_CONFIG_WRITE */ /* INT: Define an integer variable */ @@ -1308,7 +1337,11 @@ static char * wpa_config_write_wep_key3(const struct parse_data *data, * 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) }, @@ -1379,6 +1412,15 @@ static const struct parse_data ssid_fields[] = { { INT(wpa_ptk_rekey) } }; +#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/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 29e494c..6074c00 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -24,6 +24,8 @@ #include "uuid.h" #include "eap_peer/eap_methods.h" +#include + /** * wpa_config_get_line - Read the next configuration file line @@ -520,13 +522,20 @@ struct wpa_config * wpa_config_read(const char *name) return NULL; } + /* When creating the config file, give group read/write access + * to allow backup and restoring the file. + */ + chmod(name, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); + while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { if (os_strcmp(pos, "network={") == 0) { ssid = wpa_config_read_network(f, &line, id++); if (ssid == NULL) { wpa_printf(MSG_ERROR, "Line %d: failed to " "parse network block.", line); +#ifndef WPA_IGNORE_CONFIG_ERRORS errors++; +#endif continue; } if (head == NULL) { @@ -563,11 +572,13 @@ struct wpa_config * wpa_config_read(const char *name) config->ssid = head; wpa_config_debug_dump_networks(config); +#ifndef WPA_IGNORE_CONFIG_ERRORS if (errors) { wpa_config_free(config); config = NULL; head = NULL; } +#endif return config; } diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 2b737bc..31bb6af 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -20,6 +20,7 @@ #include "config.h" #include "eapol_supp/eapol_supp_sm.h" #include "wpa_supplicant_i.h" +#include "blacklist.h" #include "ctrl_iface.h" #include "l2_packet/l2_packet.h" #include "preauth.h" @@ -422,6 +423,108 @@ static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, return 0; } +#ifdef ANDROID +static int wpa_supplicant_ctrl_iface_blacklist( + struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) +{ + u8 bssid[ETH_ALEN]; + struct wpa_blacklist *e; + char *pos, *end; + int ret; + + /* cmd: "BLACKLIST []" */ + if (*cmd == '\0') { + pos = buf; + end = buf + buflen; + + e = wpa_s->blacklist; + while (e) { + ret = os_snprintf(pos, end-pos, MACSTR"\n", MAC2STR(e->bssid)); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + e = e->next; + } + return pos - buf; + } + + ++cmd; + if (os_strncmp(cmd, "clear", 5) == 0) { + wpa_blacklist_clear(wpa_s); + os_memcpy(buf, "OK\n", 3); + return 3; + } + + wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd); + if (hwaddr_aton(cmd, bssid)) { + wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", cmd); + return -1; + } + + /* + * Add the BSSID twice, so its count will be 2, causing it to be + * skipped when processing scan results. + */ + ret = wpa_blacklist_add(wpa_s, bssid); + if (ret != 0) + return -1; + ret = wpa_blacklist_add(wpa_s, bssid); + if (ret != 0) + return -1; + os_memcpy(buf, "OK\n", 3); + return 3; +} + + +extern int wpa_debug_level; +extern int wpa_debug_timestamp; +static int wpa_supplicant_ctrl_iface_log_level( + struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) +{ + char *pos, *end, *stamp; + int ret; + + if (cmd == NULL) { + return -1; + } + + /* cmd: "LOG_LEVEL []" */ + if (*cmd == '\0') { + pos = buf; + end = buf + buflen; + ret = os_snprintf(pos, end-pos, "Current level: %d\n" + "{0-MSGDUMP, 1-DEBUG, 2-INFO, 3-WARNING, 4-ERROR}\n" + "Timestamp: %d\n", wpa_debug_level, wpa_debug_timestamp); + if (ret < 0 || ret >= end - pos) + ret = 0; + + return ret; + } + + while (*cmd == ' ') { + cmd++; + } + + stamp = os_strchr(cmd, ' '); + if (stamp) { + *stamp++ = '\0'; + while (*stamp == ' ') { + stamp++; + } + } + + if (cmd && os_strlen(cmd)) { + wpa_debug_level = atoi(cmd); + } + + if (stamp && os_strlen(stamp)) { + wpa_debug_timestamp = atoi(stamp); + } + + os_memcpy(buf, "OK\n", 3); + return 3; +} +#endif static int wpa_supplicant_ctrl_iface_list_networks( struct wpa_supplicant *wpa_s, char *buf, size_t buflen) @@ -659,7 +762,7 @@ static int wpa_supplicant_ctrl_iface_scan_result( ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", MAC2STR(res->bssid), res->freq, res->level); if (ret < 0 || ret >= end - pos) - return pos - buf; + return -1; pos += ret; ie = wpa_scan_get_vendor_ie(res, WPA_IE_VENDOR_TYPE); if (ie) @@ -671,26 +774,32 @@ static int wpa_supplicant_ctrl_iface_scan_result( if (!ie && !ie2 && res->caps & IEEE80211_CAP_PRIVACY) { ret = os_snprintf(pos, end - pos, "[WEP]"); if (ret < 0 || ret >= end - pos) - return pos - buf; + return -1; pos += ret; } if (res->caps & IEEE80211_CAP_IBSS) { ret = os_snprintf(pos, end - pos, "[IBSS]"); if (ret < 0 || ret >= end - pos) - return pos - buf; + return -1; + pos += ret; + } + /* Just to make the fields line up nicely when printed */ + if (!ie && !ie2) { + ret = os_snprintf(pos, end - pos, "\t"); + if (ret < 0 || ret >= end - pos) + return -1; pos += ret; } - ie = wpa_scan_get_ie(res, WLAN_EID_SSID); ret = os_snprintf(pos, end - pos, "\t%s", ie ? wpa_ssid_txt(ie + 2, ie[1]) : ""); if (ret < 0 || ret >= end - pos) - return pos - buf; + return -1; pos += ret; ret = os_snprintf(pos, end - pos, "\n"); if (ret < 0 || ret >= end - pos) - return pos - buf; + return -1; pos += ret; return pos - buf; @@ -708,6 +817,8 @@ static int wpa_supplicant_ctrl_iface_scan_results( if (wpa_s->scan_res == NULL && wpa_supplicant_get_scan_results(wpa_s) < 0) return 0; + if (wpa_s->scan_res == NULL) + return 0; pos = buf; end = buf + buflen; @@ -769,6 +880,7 @@ static int wpa_supplicant_ctrl_iface_select_network( 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; @@ -792,7 +904,11 @@ static int wpa_supplicant_ctrl_iface_enable_network( ssid = ssid->next; } if (wpa_s->reassociate) +#ifdef ANDROID + wpa_supplicant_req_scan(wpa_s, 2, 0); +#else wpa_supplicant_req_scan(wpa_s, 0, 0); +#endif return 0; } @@ -811,7 +927,11 @@ static int wpa_supplicant_ctrl_iface_enable_network( * 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; @@ -849,6 +969,14 @@ static int wpa_supplicant_ctrl_iface_disable_network( return -1; } +#ifdef ANDROID + if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not disable WPS network " + "id=%d", id); + return -1; + } +#endif + if (ssid == wpa_s->current_ssid) wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); ssid->disabled = 1; @@ -1473,11 +1601,24 @@ static int wpa_supplicant_ctrl_iface_ap_scan( } +static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, + char *cmd, char *buf, size_t buflen) +{ + int ret; + + ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen); + if( ret == 0 ) { + ret = sprintf(buf, "%s\n", "OK"); + } + return( ret ); +} + + char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, char *buf, size_t *resp_len) { char *reply; - const int reply_size = 2048; + const int reply_size = 4096; int ctrl_rsp = 0; int reply_len; @@ -1486,8 +1627,10 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", (const u8 *) buf, os_strlen(buf)); } else { - wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", + if (os_strcmp(buf, "PING") != 0) { + wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (const u8 *) buf, os_strlen(buf)); + } } reply = os_malloc(reply_size); @@ -1580,6 +1723,23 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "BSSID ", 6) == 0) { if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) reply_len = -1; +#ifdef ANDROID + } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) { + reply_len = wpa_supplicant_ctrl_iface_blacklist( + wpa_s, buf + 9, reply, reply_size); + if (os_strlen(buf) > 10 && reply_len == 0) { + struct wpa_blacklist *bl = wpa_s->blacklist; + if (os_strncmp(buf+10, "clear", 5) == 0 || + (bl != NULL && os_memcmp(bl->bssid, wpa_s->bssid, ETH_ALEN) == 0)) { + wpa_s->disconnected = 0; + wpa_s->reassociate = 1; + wpa_supplicant_req_scan(wpa_s, 0, 0); + } + } + } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { + reply_len = wpa_supplicant_ctrl_iface_log_level( + wpa_s, buf + 9, reply, reply_size); +#endif } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { reply_len = wpa_supplicant_ctrl_iface_list_networks( wpa_s, reply, reply_size); @@ -1588,8 +1748,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, wpa_s->disconnected = 1; wpa_supplicant_disassociate(wpa_s, WLAN_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); @@ -1634,6 +1798,8 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "BSS ", 4) == 0) { reply_len = wpa_supplicant_ctrl_iface_bss( wpa_s, buf + 4, reply, reply_size); + } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { + reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, reply_size); } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; @@ -1828,11 +1994,13 @@ char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, char *buf, size_t *resp_len) { char *reply; - const int reply_size = 2048; + const int reply_size = 4096; int reply_len; - wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface", + if (os_strcmp(buf, "PING") != 0) { + wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface", (const u8 *) buf, os_strlen(buf)); + } reply = os_malloc(reply_size); if (reply == NULL) { diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c index 8c45bd6..c67d010 100644 --- a/wpa_supplicant/ctrl_iface_unix.c +++ b/wpa_supplicant/ctrl_iface_unix.c @@ -17,6 +17,9 @@ #include #include #include +#ifdef ANDROID +#include +#endif #include "common.h" #include "eloop.h" @@ -283,6 +286,13 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) buf = os_strdup(wpa_s->conf->ctrl_interface); if (buf == NULL) goto fail; +#ifdef ANDROID + os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s", + wpa_s->conf->ctrl_interface); + priv->sock = android_get_control_socket(addr.sun_path); + if (priv->sock >= 0) + goto havesock; +#endif if (os_strncmp(buf, "DIR=", 4) == 0) { dir = buf + 4; gid_str = os_strstr(dir, " GROUP="); @@ -397,6 +407,7 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) } os_free(fname); +havesock: eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, wpa_s, priv); wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); @@ -639,6 +650,12 @@ wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) if (global->params.ctrl_interface == NULL) return priv; +#ifdef ANDROID + priv->sock = android_get_control_socket(global->params.ctrl_interface); + if (priv->sock >= 0) + goto havesock; +#endif + wpa_printf(MSG_DEBUG, "Global control interface '%s'", global->params.ctrl_interface); @@ -687,6 +704,7 @@ wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) } } +havesock: eloop_register_read_sock(priv->sock, wpa_supplicant_global_ctrl_iface_receive, global, NULL); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index ab3cc64..e96ca35 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -613,6 +613,7 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s) struct wpa_scan_res *selected = NULL; struct wpa_ssid *ssid = NULL; + wpa_s->scan_ongoing = 0; if (wpa_supplicant_get_scan_results(wpa_s) < 0) { if (wpa_s->conf->ap_scan == 2) return; @@ -687,7 +688,14 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s) rsn_preauth_scan_results(wpa_s->wpa, wpa_s->scan_res); } else { wpa_printf(MSG_DEBUG, "No suitable AP found."); +#ifdef ANDROID + timeout = wpa_s->scan_interval; + if (wpas_wps_searching(wpa_s)) { + timeout = 5; + } +#else timeout = 5; +#endif goto req_scan; } @@ -782,9 +790,9 @@ static void wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, 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); if (wpa_found || rsn_found) wpa_s->ap_ies_from_associnfo = 1; diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 67e2282..e7ca963 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -204,8 +204,10 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) if (ret) { wpa_printf(MSG_WARNING, "Failed to initiate AP scan."); wpa_supplicant_req_scan(wpa_s, 10, 0); - } else + } else { wpa_s->scan_runs++; + wpa_s->scan_ongoing = 1; + } } @@ -220,6 +222,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) */ 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 @@ -241,6 +244,7 @@ void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) return; } } +#endif wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec", sec, usec); diff --git a/wpa_supplicant/src/common/defs.h b/wpa_supplicant/src/common/defs.h index 4930e73..29e30e7 100644 --- a/wpa_supplicant/src/common/defs.h +++ b/wpa_supplicant/src/common/defs.h @@ -186,6 +186,22 @@ typedef enum { * fully configured. */ WPA_COMPLETED + +#ifdef ANDROID + /** + * WPA_IDLE - Eeplicit disconnect was performed + * + * This state is entered when a disconnect command is issued to the + * supplicant. In this case, the supplicant not only disassociates + * from the current network, but it also stops trying to associate + * with any AP until a subsequent reconnect or reassociate command + * is issued. This state was added to distinguish it from the + * WPA_DISCONNECTED state, which is now reserved for disconnects + * that were not explicitly requested by a client. + * This state is reported to clients, but it is not internally stored. + */ + , WPA_IDLE +#endif /* ANDROID */ } wpa_states; #define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0 diff --git a/wpa_supplicant/src/common/wireless_copy.h b/wpa_supplicant/src/common/wireless_copy.h index d7958f9..db1a5f3 100644 --- a/wpa_supplicant/src/common/wireless_copy.h +++ b/wpa_supplicant/src/common/wireless_copy.h @@ -535,7 +535,7 @@ #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 diff --git a/wpa_supplicant/src/common/wpa_ctrl.c b/wpa_supplicant/src/common/wpa_ctrl.c index 2b4e3aa..37c6ad0 100644 --- a/wpa_supplicant/src/common/wpa_ctrl.c +++ b/wpa_supplicant/src/common/wpa_ctrl.c @@ -20,12 +20,24 @@ #include #endif /* CONFIG_CTRL_IFACE_UNIX */ +#ifdef ANDROID +#include +#include +#include +#include +#include "private/android_filesystem_config.h" +#endif + #include "wpa_ctrl.h" #include "common.h" #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) #define CTRL_IFACE_SOCKET +#ifdef ANDROID +static const char *local_socket_dir = "/data/misc/wifi/sockets"; +static const char *local_socket_prefix = "wpa_ctrl_"; +#endif /* ANDROID */ #endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */ @@ -81,7 +93,12 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) counter++; try_again: ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), +#ifdef ANDROID + "%s/%s%d-%d", local_socket_dir, local_socket_prefix, + getpid(), counter); +#else /* ANDROID */ "/tmp/wpa_ctrl_%d-%d", getpid(), counter); +#endif if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) { close(ctrl->s); os_free(ctrl); @@ -105,6 +122,30 @@ try_again: return NULL; } +#ifdef ANDROID + chmod(ctrl->local.sun_path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); + chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI); + /* + * If the ctrl_path isn't an absolute pathname, assume that + * it's the name of a socket in the Android reserved namespace. + * Otherwise, it's a normal UNIX domain socket appearing in the + * filesystem. + */ + if (ctrl_path != NULL && *ctrl_path != '/') { + os_snprintf(ctrl->dest.sun_path, sizeof(ctrl->dest.sun_path), "wpa_%s", + ctrl_path); + if (socket_local_client_connect(ctrl->s, + ctrl->dest.sun_path, + ANDROID_SOCKET_NAMESPACE_RESERVED, + SOCK_DGRAM) < 0) { + close(ctrl->s); + unlink(ctrl->local.sun_path); + os_free(ctrl); + return NULL; + } + return ctrl; + } +#endif ctrl->dest.sun_family = AF_UNIX; res = os_strlcpy(ctrl->dest.sun_path, ctrl_path, sizeof(ctrl->dest.sun_path)); @@ -127,13 +168,61 @@ try_again: void wpa_ctrl_close(struct wpa_ctrl *ctrl) { + if (ctrl == NULL) + return; unlink(ctrl->local.sun_path); - close(ctrl->s); + if (ctrl->s >= 0) + close(ctrl->s); os_free(ctrl); } -#endif /* CONFIG_CTRL_IFACE_UNIX */ +#ifdef ANDROID +/** + * wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that + * may be left over from clients that were previously connected to + * wpa_supplicant. This keeps these files from being orphaned in the + * event of crashes that prevented them from being removed as part + * of the normal orderly shutdown. + */ +void wpa_ctrl_cleanup() +{ + DIR *dir; + struct dirent entry; + struct dirent *result; + size_t dirnamelen; + int prefixlen = strlen(local_socket_prefix); + size_t maxcopy; + char pathname[PATH_MAX]; + char *namep; + + if ((dir = opendir(local_socket_dir)) == NULL) + return; + + dirnamelen = (size_t)snprintf(pathname, sizeof(pathname), "%s/", local_socket_dir); + if (dirnamelen >= sizeof(pathname)) { + closedir(dir); + return; + } + namep = pathname + dirnamelen; + maxcopy = PATH_MAX-dirnamelen; + while (readdir_r(dir, &entry, &result) == 0 && result != NULL) { + if (strncmp(entry.d_name, local_socket_prefix, prefixlen) == 0) { + if (strlcpy(namep, entry.d_name, maxcopy) < maxcopy) { + unlink(pathname); + } + } + } + closedir(dir); +} +#endif /* ANDROID */ +#else /* CONFIG_CTRL_IFACE_UNIX */ +#ifdef ANDROID +void wpa_ctrl_cleanup() +{ +} +#endif /* ANDROID */ +#endif /* CONFIG_CTRL_IFACE_UNIX */ #ifdef CONFIG_CTRL_IFACE_UDP @@ -234,7 +323,11 @@ int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, 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); @@ -447,7 +540,7 @@ int wpa_ctrl_pending(struct wpa_ctrl *ctrl) int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) { - return -1; + return ctrl->pipe; } #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ diff --git a/wpa_supplicant/src/common/wpa_ctrl.h b/wpa_supplicant/src/common/wpa_ctrl.h index 1bfc0d6..c2662b6 100644 --- a/wpa_supplicant/src/common/wpa_ctrl.h +++ b/wpa_supplicant/src/common/wpa_ctrl.h @@ -48,6 +48,12 @@ extern "C" { #define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE " /** New scan results available */ #define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS " +/** wpa_supplicant state change */ +#define WPA_EVENT_STATE_CHANGE "CTRL-EVENT-STATE-CHANGE " +/** AP to STA speed */ +#define WPA_EVENT_LINK_SPEED "CTRL-EVENT-LINK-SPEED " +/** Driver state change */ +#define WPA_EVENT_DRIVER_STATE "CTRL-EVENT-DRIVER-STATE " /** WPS overlap detected in PBC mode */ #define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED " @@ -200,6 +206,17 @@ int wpa_ctrl_pending(struct wpa_ctrl *ctrl); */ int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl); +#ifdef ANDROID +/** + * wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that + * may be left over from clients that were previously connected to + * wpa_supplicant. This keeps these files from being orphaned in the + * event of crashes that prevented them from being removed as part + * of the normal orderly shutdown. + */ +void wpa_ctrl_cleanup(); +#endif /* ANDROID */ + #ifdef CONFIG_CTRL_IFACE_UDP #define WPA_CTRL_IFACE_PORT 9877 #define WPA_GLOBAL_CTRL_IFACE_PORT 9878 diff --git a/wpa_supplicant/src/crypto/tls_openssl.c b/wpa_supplicant/src/crypto/tls_openssl.c index f290a39..8b16eb2 100644 --- a/wpa_supplicant/src/crypto/tls_openssl.c +++ b/wpa_supplicant/src/crypto/tls_openssl.c @@ -47,6 +47,22 @@ #endif #endif +#ifdef ANDROID +#include +#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 { @@ -1180,6 +1196,33 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn, 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) { @@ -1350,6 +1393,25 @@ static int tls_connection_client_cert(struct tls_connection *conn, 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) { @@ -1742,6 +1804,23 @@ static int tls_connection_private_key(void *_ssl_ctx, 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/wpa_supplicant/src/drivers/driver.h b/wpa_supplicant/src/drivers/driver.h index 9bce6c6..506f120 100644 --- a/wpa_supplicant/src/drivers/driver.h +++ b/wpa_supplicant/src/drivers/driver.h @@ -1017,6 +1017,18 @@ struct wpa_driver_ops { * failure */ struct wpa_interface_info * (*get_interfaces)(void *global_priv); + + /** + * driver_cmd - execute driver-specific command + * @priv: private driver interface data from init() + * @cmd: command to execute + * @buf: return buffer + * @buf_len: buffer length + * + * Returns: 0 on success, -1 on failure + * + */ + int (*driver_cmd)(void *priv, char *cmd, char *buf, size_t buf_len); }; /* Function to check whether a driver is for wired connections */ diff --git a/wpa_supplicant/src/drivers/driver_test.c b/wpa_supplicant/src/drivers/driver_test.c index 2a41cf2..c312754 100644 --- a/wpa_supplicant/src/drivers/driver_test.c +++ b/wpa_supplicant/src/drivers/driver_test.c @@ -1172,6 +1172,37 @@ wpa_driver_test_get_interfaces(void *global_priv) } +int wpa_driver_test_driver_cmd( void *priv, char *cmd, char *buf, size_t buf_len ) +{ + struct wpa_driver_test_data *drv = (struct wpa_driver_test_data *)priv; + int ret = -1; + + wpa_printf(MSG_DEBUG, "%s %s", __func__, cmd); + if( os_strncasecmp(cmd, "start", 5) == 0 ) { + wpa_printf(MSG_DEBUG,"Start command"); + ret = 0; + } + else if( os_strncasecmp(cmd, "stop", 4) == 0 ) { + wpa_printf(MSG_DEBUG,"Stop command"); + ret = 0; + } + else if( os_strncasecmp(cmd, "macaddr", 7) == 0 ) { + u8 *macaddr = (u8 *)wpa_driver_test_get_mac_addr(priv); + wpa_printf(MSG_DEBUG,"Macaddr command"); + wpa_printf(MSG_DEBUG, " Macaddr = " MACSTR, MAC2STR(macaddr)); + ret = os_snprintf(buf, buf_len, "Macaddr = " MACSTR "\n", MAC2STR(macaddr)); + } + else if( os_strncasecmp(cmd, "rssi", 4) == 0 ) { + wpa_printf(MSG_DEBUG,"RSSI command"); + ret = os_snprintf(buf, buf_len, MACSTR " Rssi %d\n", MAC2STR(drv->bssid), -10); + } else if (os_strncasecmp(cmd, "linkspeed", 9) == 0) { + wpa_printf(MSG_DEBUG, "LinkSpeed command"); + ret = os_snprintf(buf, buf_len, "LinkSpeed %u\n", 11); + } + return ret; +} + + const struct wpa_driver_ops wpa_driver_test_ops = { "test", "wpa_supplicant test driver", @@ -1226,5 +1257,6 @@ const struct wpa_driver_ops wpa_driver_test_ops = { wpa_driver_test_global_init, wpa_driver_test_global_deinit, wpa_driver_test_init2, - wpa_driver_test_get_interfaces + wpa_driver_test_get_interfaces, + wpa_driver_test_driver_cmd }; diff --git a/wpa_supplicant/src/drivers/driver_wext.c b/wpa_supplicant/src/drivers/driver_wext.c index 8c2daa8..57ed33f 100644 --- a/wpa_supplicant/src/drivers/driver_wext.c +++ b/wpa_supplicant/src/drivers/driver_wext.c @@ -21,6 +21,7 @@ #include "includes.h" #include #include +#include #include "wireless_copy.h" #include "common.h" @@ -30,6 +31,9 @@ #include "driver_wext.h" #include "ieee802_11_defs.h" #include "wpa_common.h" +#include "wpa_ctrl.h" +#include "wpa_supplicant_i.h" +#include "config_ssid.h" static int wpa_driver_wext_flush_pmkid(void *priv); @@ -352,6 +356,12 @@ wpa_driver_wext_event_wireless_custom(void *ctx, char *custom) } 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 */ } } @@ -1073,6 +1083,10 @@ int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len) struct iwreq iwr; int ret = 0, timeout; struct iw_scan_req req; +#ifdef ANDROID + struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx); + int scan_probe_flag = 0; +#endif if (ssid_len > IW_ESSID_MAX_SIZE) { wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)", @@ -1083,7 +1097,14 @@ int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len) os_memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); +#ifdef ANDROID + if (wpa_s->prev_scan_ssid != BROADCAST_SSID_SCAN) { + scan_probe_flag = wpa_s->prev_scan_ssid->scan_ssid; + } + if (scan_probe_flag && (ssid && ssid_len)) { +#else if (ssid && ssid_len) { +#endif os_memset(&req, 0, sizeof(req)); req.essid_len = ssid_len; req.bssid.sa_family = ARPHRD_ETHER; @@ -1467,6 +1488,14 @@ struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv) struct wpa_scan_results *res; struct wext_scan_data data; +#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 = wpa_driver_wext_giwscan(drv, &len); if (res_buf == NULL) return NULL; @@ -2046,10 +2075,16 @@ int wpa_driver_wext_associate(void *priv, 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. @@ -2323,6 +2358,70 @@ int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv) } +#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", .desc = "Linux wireless extensions (generic)", @@ -2346,4 +2445,7 @@ const struct wpa_driver_ops wpa_driver_wext_ops = { .flush_pmkid = wpa_driver_wext_flush_pmkid, .get_capa = wpa_driver_wext_get_capa, .set_operstate = wpa_driver_wext_set_operstate, +#ifdef ANDROID + .driver_cmd = wpa_driver_priv_driver_cmd, +#endif }; diff --git a/wpa_supplicant/src/drivers/driver_wext.h b/wpa_supplicant/src/drivers/driver_wext.h index b89c2cb..d956b3a 100644 --- a/wpa_supplicant/src/drivers/driver_wext.h +++ b/wpa_supplicant/src/drivers/driver_wext.h @@ -79,4 +79,13 @@ int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv, int wpa_driver_wext_cipher2wext(int cipher); int wpa_driver_wext_keymgmt2wext(int keymgmt); +#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/wpa_supplicant/src/drivers/drivers.c b/wpa_supplicant/src/drivers/drivers.c index d278797..29e0cd4 100644 --- a/wpa_supplicant/src/drivers/drivers.c +++ b/wpa_supplicant/src/drivers/drivers.c @@ -74,6 +74,9 @@ extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */ /* driver_roboswitch.c */ extern struct wpa_driver_ops wpa_driver_roboswitch_ops; #endif /* CONFIG_DRIVER_ROBOSWITCH */ +#ifdef CONFIG_DRIVER_CUSTOM +extern struct wpa_driver_ops wpa_driver_custom_ops; +#endif /* CONFIG_DRIVER_CUSTOM */ struct wpa_driver_ops *wpa_supplicant_drivers[] = @@ -135,5 +138,8 @@ struct wpa_driver_ops *wpa_supplicant_drivers[] = #ifdef CONFIG_DRIVER_ROBOSWITCH &wpa_driver_roboswitch_ops, #endif /* CONFIG_DRIVER_ROBOSWITCH */ +#ifdef CONFIG_DRIVER_CUSTOM + &wpa_driver_custom_ops, +#endif /* CONFIG_DRIVER_CUSTOM */ NULL }; diff --git a/wpa_supplicant/src/utils/common.c b/wpa_supplicant/src/utils/common.c index cb373c3..f5319ab 100644 --- a/wpa_supplicant/src/utils/common.c +++ b/wpa_supplicant/src/utils/common.c @@ -320,8 +320,10 @@ const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) os_memcpy(ssid_txt, ssid, ssid_len); ssid_txt[ssid_len] = '\0'; for (pos = ssid_txt; *pos != '\0'; pos++) { +#ifndef WPA_UNICODE_SSID if ((u8) *pos < 32 || (u8) *pos >= 127) *pos = '_'; +#endif } return ssid_txt; } diff --git a/wpa_supplicant/src/utils/os_unix.c b/wpa_supplicant/src/utils/os_unix.c index 060892d..9b6abfa 100644 --- a/wpa_supplicant/src/utils/os_unix.c +++ b/wpa_supplicant/src/utils/os_unix.c @@ -16,6 +16,12 @@ #include "os.h" +#ifdef ANDROID +#include +#include +#include +#endif + void os_sleep(os_time_t sec, os_time_t usec) { if (sec) @@ -210,6 +216,28 @@ char * os_rel2abs_path(const char *rel_path) 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/wpa_supplicant/src/utils/wpa_debug.c b/wpa_supplicant/src/utils/wpa_debug.c index e17cf06..02b7ea0 100644 --- a/wpa_supplicant/src/utils/wpa_debug.c +++ b/wpa_supplicant/src/utils/wpa_debug.c @@ -25,6 +25,31 @@ int wpa_debug_show_keys = 0; int wpa_debug_timestamp = 0; +#ifdef CONFIG_ANDROID_LOG + +#include + +void android_printf(int level, char *format, ...) +{ + if (level >= wpa_debug_level) { + va_list ap; + if (level == MSG_ERROR) { + level = ANDROID_LOG_ERROR; + } else if (level == MSG_WARNING) { + level = ANDROID_LOG_WARN; + } else if (level == MSG_INFO) { + level = ANDROID_LOG_INFO; + } else { + level = ANDROID_LOG_DEBUG; + } + va_start(ap, format); + __android_log_vprint(level, "wpa_supplicant", format, ap); + va_end(ap); + } +} + +#else /* CONFIG_ANDROID_LOG */ + #ifndef CONFIG_NO_STDOUT_DEBUG void wpa_debug_print_timestamp(void) @@ -257,6 +282,7 @@ void wpa_debug_close_file(void) #endif /* CONFIG_NO_STDOUT_DEBUG */ +#endif /* CONFIG_ANDROID_LOG */ #ifndef CONFIG_NO_WPA_MSG static wpa_msg_cb_func wpa_msg_cb = NULL; diff --git a/wpa_supplicant/src/utils/wpa_debug.h b/wpa_supplicant/src/utils/wpa_debug.h index 2d23f06..c8e840f 100644 --- a/wpa_supplicant/src/utils/wpa_debug.h +++ b/wpa_supplicant/src/utils/wpa_debug.h @@ -22,6 +22,29 @@ enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR }; +#ifdef CONFIG_ANDROID_LOG + +#define wpa_debug_print_timestamp() do {} while (0) +#define wpa_hexdump(...) do {} while (0) +#define wpa_hexdump_key(...) do {} while (0) +#define wpa_hexdump_buf(l,t,b) do {} while (0) +#define wpa_hexdump_buf_key(l,t,b) do {} while (0) +#define wpa_hexdump_ascii(...) do {} while (0) +#define wpa_hexdump_ascii_key(...) do {} while (0) +#define wpa_debug_open_file(...) do {} while (0) +#define wpa_debug_close_file() do {} while (0) + +void android_printf(int level, char *format, ...); + +#define wpa_printf(level, ...) \ + do { \ + if ((level) >= MSG_DEBUG) { \ + android_printf((level), __VA_ARGS__); \ + } \ + } while (0) + +#else /* CONFIG_ANDROID_LOG */ + #ifdef CONFIG_NO_STDOUT_DEBUG #define wpa_debug_print_timestamp() do { } while (0) @@ -138,6 +161,7 @@ void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, #endif /* CONFIG_NO_STDOUT_DEBUG */ +#endif /* CONFIG_ANDROID_LOG */ #ifdef CONFIG_NO_WPA_MSG #define wpa_msg(args...) do { } while (0) diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 7de6534..c57d20d 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -24,9 +24,14 @@ #include #endif /* CONFIG_READLINE */ +#define CTRL_INTERFACE_2_SOCKETS + #include "wpa_ctrl.h" #include "common.h" #include "version.h" +#ifdef ANDROID +#include +#endif static const char *wpa_cli_version = @@ -87,11 +92,16 @@ static const char *wpa_cli_full_license = "\n"; static struct wpa_ctrl *ctrl_conn; +static struct wpa_ctrl *monitor_conn; static int wpa_cli_quit = 0; static int wpa_cli_attached = 0; static int wpa_cli_connected = 0; static int wpa_cli_last_id = 0; +#ifdef ANDROID +static const char *ctrl_iface_dir = "/data/misc/wifi/wpa_supplicant"; +#else static const char *ctrl_iface_dir = "/var/run/wpa_supplicant"; +#endif static char *ctrl_ifname = NULL; static const char *pid_file = NULL; static const char *action_file = NULL; @@ -121,9 +131,10 @@ static void usage(void) static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname) { + struct wpa_ctrl *cur_conn; #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE) - ctrl_conn = wpa_ctrl_open(ifname); - return ctrl_conn; + cur_conn = wpa_ctrl_open(ifname); + return cur_conn; #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ char *cfile; int flen, res; @@ -131,6 +142,11 @@ static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname) if (ifname == NULL) return NULL; +#ifdef ANDROID + if (access(ctrl_iface_dir, F_OK) < 0) + cfile = (char *)ifname; + else { +#endif flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2; cfile = os_malloc(flen); if (cfile == NULL) @@ -140,10 +156,21 @@ static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname) os_free(cfile); return NULL; } - - ctrl_conn = wpa_ctrl_open(cfile); +#ifdef ANDROID + } +#endif + + cur_conn = wpa_ctrl_open(cfile); +#ifdef CTRL_INTERFACE_2_SOCKETS + monitor_conn = wpa_ctrl_open(cfile); +#else + monitor_conn = cur_conn; +#endif +#ifdef ANDROID + if (cfile != ifname) +#endif os_free(cfile); - return ctrl_conn; + return cur_conn; #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ } @@ -154,11 +181,14 @@ static void wpa_cli_close_connection(void) return; if (wpa_cli_attached) { - wpa_ctrl_detach(ctrl_conn); + wpa_ctrl_detach(monitor_conn); wpa_cli_attached = 0; } +#ifdef CTRL_INTERFACE_2_SOCKETS + wpa_ctrl_close(monitor_conn); +#endif wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; + ctrl_conn = monitor_conn = NULL; } @@ -170,7 +200,7 @@ static void wpa_cli_msg_cb(char *msg, size_t len) static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print) { - char buf[2048]; + char buf[4096]; size_t len; int ret; @@ -717,6 +747,60 @@ static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[]) } +#ifdef ANDROID +static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256], *pos, *end; + int i, ret; + + end = cmd + sizeof(cmd); + pos = cmd; + ret = os_snprintf(pos, end - pos, "BLACKLIST"); + if (ret < 0 || ret >= end - pos) { + printf("Too long BLACKLIST command.\n"); + return -1; + } + pos += ret; + for (i = 0; i < argc; i++) { + ret = os_snprintf(pos, end - pos, " %s", argv[i]); + if (ret < 0 || ret >= end - pos) { + printf("Too long BLACKLIST command.\n"); + return -1; + } + pos += ret; + } + + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256], *pos, *end; + int i, ret; + + end = cmd + sizeof(cmd); + pos = cmd; + ret = os_snprintf(pos, end - pos, "LOG_LEVEL"); + if (ret < 0 || ret >= end - pos) { + printf("Too long LOG_LEVEL command.\n"); + return -1; + } + pos += ret; + for (i = 0; i < argc; i++) { + ret = os_snprintf(pos, end - pos, " %s", argv[i]); + if (ret < 0 || ret >= end - pos) { + printf("Too long LOG_LEVEL command.\n"); + return -1; + } + pos += ret; + } + + return wpa_ctrl_command(ctrl, cmd); +} +#endif /* ANDROID */ + + static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -990,9 +1074,9 @@ static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[]) os_free(ctrl_ifname); ctrl_ifname = os_strdup(argv[0]); - if (wpa_cli_open_connection(ctrl_ifname)) { + if ((ctrl_conn = wpa_cli_open_connection(ctrl_ifname)) != NULL) { printf("Connected to interface '%s.\n", ctrl_ifname); - if (wpa_ctrl_attach(ctrl_conn) == 0) { + if (wpa_ctrl_attach(monitor_conn) == 0) { wpa_cli_attached = 1; } else { printf("Warning: Failed to attach to " @@ -1078,6 +1162,26 @@ static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc, } +static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[32]; + + if (argc < 1) { + printf("Invalid DRIVER command: needs one argument (cmd)\n"); + return -1; + } + + if (argc > 1) + os_snprintf(cmd, sizeof(cmd), "DRIVER %s %s", argv[0], argv[1]); + else + os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]); + cmd[sizeof(cmd) - 1] = '\0'; + + return wpa_ctrl_command(ctrl, cmd); +} + + enum wpa_cli_cmd_flags { cli_cmd_flag_none = 0x00, cli_cmd_flag_sensitive = 0x01 @@ -1157,7 +1261,18 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { { "bssid", wpa_cli_cmd_bssid, cli_cmd_flag_none, " = set preferred BSSID for an SSID" }, - { "list_networks", wpa_cli_cmd_list_networks, +#ifdef ANDROID + { "blacklist", wpa_cli_cmd_blacklist, + cli_cmd_flag_none, + " = add a BSSID to the blacklist\n" + "blacklist clear = clear the blacklist\n" + "blacklist = display the blacklist" }, + { "log_level", wpa_cli_cmd_log_level, + cli_cmd_flag_none, + " [] = update the log level/timestamp of wpa_supplicant\n" + "log_level = display the current log level and log options" }, +#endif + { "list_networks", wpa_cli_cmd_list_networks, cli_cmd_flag_none, "= list configured networks" }, { "select_network", wpa_cli_cmd_select_network, @@ -1241,6 +1356,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { { "wps_reg", wpa_cli_cmd_wps_reg, cli_cmd_flag_sensitive, " = start WPS Registrar to configure an AP" }, + { "driver", wpa_cli_cmd_driver, + cli_cmd_flag_none, + " = driver private commands" }, { NULL, NULL, cli_cmd_flag_none, NULL } }; @@ -1333,6 +1451,9 @@ static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) printf("Unknown command '%s'\n", argv[0]); ret = 1; } else { + if( os_strncasecmp( "level", argv[0], os_strlen(argv[0]) ) == 0 ) { + ctrl = monitor_conn; + } ret = match->handler(ctrl, argc - 1, &argv[1]); } @@ -1451,7 +1572,7 @@ static void wpa_cli_reconnect(void) ctrl_conn = wpa_cli_open_connection(ctrl_ifname); if (ctrl_conn) { printf("Connection to wpa_supplicant re-established\n"); - if (wpa_ctrl_attach(ctrl_conn) == 0) { + if (wpa_ctrl_attach(monitor_conn) == 0) { wpa_cli_attached = 1; } else { printf("Warning: Failed to attach to " @@ -1465,7 +1586,7 @@ static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read, int action_monitor) { int first = 1; - if (ctrl_conn == NULL) { + if (ctrl == NULL) { wpa_cli_reconnect(); return; } @@ -1563,7 +1684,7 @@ static void wpa_cli_interactive(void) #endif /* CONFIG_READLINE */ do { - wpa_cli_recv_pending(ctrl_conn, 0, 0); + wpa_cli_recv_pending(monitor_conn, 0, 0); #ifndef CONFIG_NATIVE_WINDOWS alarm(ping_interval); #endif /* CONFIG_NATIVE_WINDOWS */ @@ -1587,7 +1708,7 @@ static void wpa_cli_interactive(void) #endif /* CONFIG_NATIVE_WINDOWS */ if (cmd == NULL) break; - wpa_cli_recv_pending(ctrl_conn, 0, 0); + wpa_cli_recv_pending(monitor_conn, 0, 0); pos = cmd; while (*pos != '\0') { if (*pos == '\n') { @@ -1719,10 +1840,10 @@ static void wpa_cli_alarm(int sig) "reconnect\n"); wpa_cli_close_connection(); } - if (!ctrl_conn) + if (!monitor_conn) wpa_cli_reconnect(); - if (ctrl_conn) - wpa_cli_recv_pending(ctrl_conn, 1, 0); + if (monitor_conn) + wpa_cli_recv_pending(monitor_conn, 1, 0); alarm(ping_interval); } #endif /* CONFIG_NATIVE_WINDOWS */ @@ -1735,8 +1856,17 @@ static char * wpa_cli_get_default_ifname(void) #ifdef CONFIG_CTRL_IFACE_UNIX struct dirent *dent; DIR *dir = opendir(ctrl_iface_dir); - if (!dir) + if (!dir) { +#ifdef ANDROID + char ifprop[PROPERTY_VALUE_MAX]; + if (property_get("wifi.interface", ifprop, NULL) != 0) { + ifname = os_strdup(ifprop); + printf("Using interface '%s'\n", ifname); + return ifname; + } +#endif return NULL; + } while ((dent = readdir(dir))) { #ifdef _DIRENT_HAVE_D_TYPE /* @@ -1758,7 +1888,7 @@ static char * wpa_cli_get_default_ifname(void) #endif /* CONFIG_CTRL_IFACE_UNIX */ #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE - char buf[2048], *pos; + char buf[4096], *pos; size_t len; struct wpa_ctrl *ctrl; int ret; @@ -1886,7 +2016,7 @@ int main(int argc, char *argv[]) #endif /* CONFIG_NATIVE_WINDOWS */ if (interactive || action_file) { - if (wpa_ctrl_attach(ctrl_conn) == 0) { + if (wpa_ctrl_attach(monitor_conn) == 0) { wpa_cli_attached = 1; } else { printf("Warning: Failed to attach to " diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index c1f95cb..b92bc9e 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -39,6 +39,9 @@ #include "blacklist.h" #include "wpas_glue.h" #include "wps_supplicant.h" +#ifdef ANDROID +#include +#endif const char *wpa_supplicant_version = "wpa_supplicant v" VERSION_STR "\n" @@ -471,12 +474,26 @@ const char * wpa_supplicant_state_txt(int state) */ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_states state) { +#ifdef ANDROID + int network_id = -1; + if (wpa_s && wpa_s->current_ssid) { + network_id = wpa_s->current_ssid->id; + } + wpa_states reported_state = state; + if (state == WPA_DISCONNECTED && wpa_s->disconnected) { + reported_state = WPA_IDLE; + } +#endif wpa_printf(MSG_DEBUG, "State: %s -> %s", wpa_supplicant_state_txt(wpa_s->wpa_state), wpa_supplicant_state_txt(state)); wpa_supplicant_dbus_notify_state_change(wpa_s, state, wpa_s->wpa_state); +#ifdef ANDROID + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE "id=%d state=%d", + network_id, reported_state); +#endif if (state == WPA_COMPLETED && wpa_s->new_connection) { #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) @@ -581,7 +598,11 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) 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; } @@ -922,6 +943,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, ie ? wpa_ssid_txt(ie + 2, ie[1]) : "", bss->freq); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); + wpa_s->link_speed = wpa_scan_get_max_rate(bss) * 500000; + wpa_s->rssi = bss->level; #ifdef CONFIG_IEEE80211R ie = wpa_scan_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) @@ -1932,7 +1955,17 @@ struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global, os_free(wpa_s); return NULL; } - + +#ifdef ANDROID + char scan_prop[PROPERTY_VALUE_MAX]; + char *endp; + if (property_get("wifi.supplicant_scan_interval", scan_prop, "6") != 0) { + wpa_s->scan_interval = (int)strtol(scan_prop, &endp, 0); + if (endp == scan_prop) { + wpa_s->scan_interval = 6; + } + } +#endif wpa_s->next = global->ifaces; global->ifaces = wpa_s; @@ -2140,6 +2173,8 @@ void wpa_supplicant_deinit(struct wpa_global *global) if (global == NULL) return; + wpa_supplicant_terminate(0, global, NULL); + while (global->ifaces) wpa_supplicant_remove_iface(global, global->ifaces); diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 43e81a1..06f6714 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -21,7 +21,7 @@ # wpa_cli/wpa_gui to be able to store the configuration changes permanently. # Please note that overwriting configuration file will remove the comments from # it. -#update_config=1 +update_config=1 # global configuration (shared by all network blocks) # @@ -72,7 +72,7 @@ # DACL (which will reject all connections). See README-Windows.txt for more # information about SDDL string format. # -ctrl_interface=/var/run/wpa_supplicant +ctrl_interface=wlan0 # IEEE 802.1X/EAPOL version # wpa_supplicant is implemented based on IEEE Std 802.1X-2004 which defines diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 5e4dcc1..30c8b41 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -358,6 +358,13 @@ struct wpa_supplicant { struct wps_context *wps; int wps_success; /* WPS success event received */ int blacklist_cleared; + + 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 }; @@ -760,4 +767,12 @@ static inline int wpa_drv_set_probe_req_ie(struct wpa_supplicant *wpa_s, return -1; } +static inline int wpa_drv_driver_cmd(struct wpa_supplicant *wpa_s, + char *cmd, char *buf, size_t buf_len) +{ + if (wpa_s->driver->driver_cmd) + return wpa_s->driver->driver_cmd(wpa_s->drv_priv, cmd, buf, buf_len); + return -1; +} + #endif /* WPA_SUPPLICANT_I_H */ diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 241526c..86d6663 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -442,6 +442,10 @@ static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx) struct wpa_supplicant *wpa_s = eloop_ctx; wpa_printf(MSG_INFO, WPS_EVENT_TIMEOUT "Requested operation timed " "out"); + if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid) { + wpa_supplicant_deauthenticate(wpa_s, + WLAN_REASON_DEAUTH_LEAVING); + } wpas_clear_wps(wpa_s); } -- 2.11.0